srs /srs 3 12:21:28 1996// /srsinstall/1.8/Tue Aug 13 12:21:29 1996// /srs/bin ================ This is the beta release of SRS5.0 which has been compiled and tested on irix, osf1 and Linux. It could also work on sunos, solaris, irix64 and Ultrix. To install set default into the srs directory and run srsinstall all This will ask you a few questions regarding 'make' and 'cc' and compile most programs - it also changes the 'etc/srs/prep_srs' file to contain the correct root directory, runs the 'srssection' command to create the SRS object base (database definitions etc) After this is done set the SRS environment by source srs/etc/prep_srs The icarus files are in srs/icarus. All databank defining files are in the 'db' subdirectory. Right now there are definitions for swissprot, prosite, enzyme ...you must edit srsdb.i and get the paths right - don't forget to run 'srssection' after that. All databanks are defined by two files (eg, 'prosite.i' and 'prosite.is') After a change in the .i file 'srssection' must be invoked. The .is file is interpreted - so you can just run the program again. To install the SRSWWW set the default into the SRS root directory again and invoke srsinstall www You will be asked for the names of both the doc root and bin root of SRSWWW. You must define aliases for these and restart the httpd. You can access SRSWWW with the URL "http://your-httpd/srs/" The top page of SRSWWW has a link to the documentation which you can install on your site with srsintall doc Thure Etzold, 12.8. 1996 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSFile: /home/etzold/srs/RCS/srsinstall,v $ # $Revision: 1.8 $ # $Date: 1996/08/13 12:21:29 $ # $Author: etzold $ # # installs an srs release # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # print "usage" # if (${#argv} == 0) then usage: cat << END Usage: srsinstall option Options: all does a complete installation make compiles all programs commands replaces the "cc", "make" commands by something else www install SRS WWW server ...on the SRS side doc installs the SRS documentation on the WWW NOTE: Use "srsinstall all" the first time you run srsinstall ----- END exit endif #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # analyse command line and print usage if wrong # if (${argv[1]} == "make") then set option = "make" cd etc goto make else if (${argv[1]} == "libs") then set option = "libs" cd etc goto libs else if (${argv[1]} == "commands") then set option = "commands" cd etc goto commands else if (${argv[1]} == "all") then set option = "all" else if (${argv[1]} == "www") then set option = "www" goto www else if (${argv[1]} == "doc") then set option = "doc" goto doc else echo 'unkown option "'${argv[1]}'"' set error=1 goto usage endif #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # insert the correct root into prep_srs # cat << END You must edit the file "odd/srsdb.sdl" first. Edit the object defining the 'environment' "unix" ("vms" on VMS). Only libraries that you have on your site may appear in the list of 'libenv' definitions. Each library must be associated with a valid directory name. Delete or outcomment 'libenv' definitions for libraries you don't have. END echo -n 'press RETURN to continue: ' set yes = $< if ($yes != "") exit echo ...updating file "prep_srs" set rootdir = `pwd` cd etc sed "s:setenv SRSROOT .*:setenv SRSROOT "$rootdir":" prep_srs >! tmp mv tmp prep_srs chmod +x prep_srs #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # put correct "make" and "cc" commands into srsmake # commands: echo -n 'enter the make command [make]: ' set makeCom = $< if ($makeCom == "") set makeCom = 'make' echo -n 'enter the cc command [cc]: ' set ccCom = $< if ($ccCom == "") set ccCom = 'cc' set os = `uname` if ($os == "SunOS" && `uname -r` =~ [56]*) set os = 'Solaris2' # # Possibility for Correction ???? # echo '...inserting commands "'$makeCom'" and "'$ccCom'" into srsmake for '$os'' sed "/case "$os"/,/breaksw/s@MAKE '[^ '][^ ']*@MAKE '"$makeCom"@" srsmake>! tmp mv tmp srsmake sed "/case "$os"/,/breaksw/s@CCOMP=[^ '][^ ']*@CCOMP="$ccCom"@" srsmake>! tmp mv tmp srsmake chmod +x srsmake if ($option == "commands") exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # now prepare the environment and compile # make: chmod u+x prep_srs source prep_srs srsmake msgdef rehash msgdef # make a dummy srsenv.h file touch $SRSEXE/srsenv.h echo "...making ODD-Compiler" srsmake nodd echo "...compiling Icarus files to object base" srssection echo "...make srsbuild" srsmake srsbuild echo "...make srscheck" srsmake srscheck echo "...make header file 'srsenv.h'" $SRSEXE/srscheck -header echo "...make getz" srsmake getz echo "...make icarus" srsmake icarus cat << END NEXT STEPS TO DO: ----------------- source etc/prep_srs srscheck srsupdate END exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # moves the SRS directory to another location # move: echo 'Sorry, not yet implemented' exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Installs the SRS documentation # doc: echo "...Creating and installing the SRS documentation for the WWW" source etc/prep_srs makedoc exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # installs WWW server # www: source etc/prep_srs echo -n 'enter the doc root of SRSWWW [/srs]: ' set docRoot = $< if ($docRoot == "") set docRoot = '/srs' echo -n 'enter the bin root or SRSWWW [/srsbin]: ' set binRoot = $< if ($binRoot == "") set binRoot = '/srsbin' echo -n 'enter short name for your institution (eg, 'EMBL, Heidelberg'): ' set siteName = "$<" if ("$siteName" == "") set siteName = 'unknown' # do replacement sed "s#docdir set:'[^']*'#docdir set:'"$docRoot"'#" $SRSICA/srswww.i >! tmpsed mv tmpsed $SRSICA/srswww.i sed "s#cgidir set:'[^']*'#cgidir set:'"$binRoot"'#" $SRSICA/srswww.i >! tmpsed mv tmpsed $SRSICA/srswww.i sed "s#siteName set:'[^']*'#siteName set:'""$siteName""'#" $SRSICA/srswww.i >! tmpsed mv tmpsed $SRSICA/srswww.i srscheck -header srsmake wgetz chmod 777 $SRSWWWTMP $SRSEXE/wgetz -top -color yellowWeave -mime none > $SRSWWW/index.html cat << END Now you must edit the file 'srm.conf' of the httpd. Add the two aliases: ------------------------------------------------------- ScriptAlias $binRoot/ $SRSROOT/www/bin/ Alias $docRoot/ $SRSROOT/www/ ------------------------------------------------------- Then restart the server. END exit /srs/doc g 13 11:51:25 1996// /icarus.html/1.2/Wed Jul 24 22:24:33 1996// /install.html/1.1/Fri Jul 19 16:33:02 1996// /internal.html/1.3/Thu Jul 11 14:00:08 1996// /prog.html/1.2/Sun Aug 11 22:52:48 1996// /query.html/1.4/Tue Aug 13 11:51:26 1996// /srsman.html/1.1/Tue Aug 13 11:51:26 1996// /srswww.html/1.2/Tue Aug 13 11:51:27 1996// /tour.html/1.2/Wed Jul 24 22:24:34 1996// /usage.html/1.1/Fri Jul 19 16:33:05 1996// /srs/doc/demo 9:03 1996// /ex001.c/1.1/Wed Jun 26 15:47:49 1996// /ex002.c/1.1/Wed Jun 26 15:47:51 1996// /ex003.c/1.1/Wed Jun 26 15:47:51 1996// /ex004.c/1.1/Wed Jun 26 15:47:52 1996// /ex005.c/1.1/Tue Jul 9 21:36:11 1996// /views.c/1.1/Tue Aug 13 14:05:59 1996// #include #include "srs.h" #include "dict.h" int main () { DICTv dict; struct X{ int a; char b[100]; }x[100], *tmp; Iter i; dict = DictCreate(DictCreateClassPtrKey ((KeyAccessor)KeyItself , 0, FALSE)); x[0].a = 10; x[5].a = 5; x[1].a = 1; x[3].a = 3; DictSet (&dict, &x[0], struct X*) = &x[0]; DictSet (&dict, &x[5], struct X*) = &x[5]; DictSet (&dict, &x[1], struct X*) = &x[1]; DictSet (&dict, &x[3], struct X*) = &x[3]; DictDebug (dict); if ((i = DictWith (dict, &x[3]))) { tmp = DictIn (i, struct X*); printf ("found %d\n", tmp->a); } else printf ("not found\n"); } building an SRS query expression */ #include #include "srs.h" int main () { QASoQUERY *qas; char s[1000]; SrsEnv (); LibOpen (); qas = QasNew (); QasSetLibrary (qas, "swissprot"); QasSetLibrary (qas, "prosite"); QasSetRetrieveStr (qas, "description", "kinase"); QasSetRangeBegin (qas, "seqlength", "400"); QasSetRangeEnd (qas, "seqlength", "500"); QasSetOp (qas, "and"); strcpy (s, QasGetQueryString (qas)); printf ("the query: \"%s\"\n", s); QasInitLink (qas); QasSetQueryToLink (qas, s); QasSetLinkWith (qas, "prosite"); QasSetLinkWith (qas, "pfam"); QasSetLinkType (qas, "notToSet"); printf ("the query linked: \"%s\"\n", QasGetQueryString (qas)); } #include #include "srs.h" int main () { SrsEnv (); LibOpen (); if (Query ("[embl-definition:receptor]", "Q1")) { printf ("Q1 has %d entries\n", SetSize ("Q1")); Query ("[embl-definition:acetylchol*] & Q1", "Q2"); printf ("Q2 has %d entries\n", SetSize ("Q2")); Query ("Q2 > SWISSPROT", "Q3"); printf ("%d SWISSPROT entries are linked to entries in Q2\n", SetSize ("Q3")); Query ("Q2 < SWISSPROT", "Q4"); printf ("%d entries in Q2 are linked to SWISSPROT\n", SetSize ("Q4")); } } #include #include "srs.h" int main () { SETo *set; IDoENTRY id; ENTRYo *entry; int n, entryN; SrsEnv (); LibOpen (); ParDefStr ("fieldList", "ID"); ParDefStr ("fieldList", "Definition"); if (Query ("[swissprot-definition:transferase]", "Q")) { set = SetGet ("Q"); entryN = SetSize ("Q"); for (n=1; n <= entryN; n++) { SetGetID (set, n, &id); entry = EntryOpen (&id); EntryPrintFields (entry); EntryClose (&entry); } } } lds */ #include #include "srs.h" int main () { SLBo *lib; SRSoGROUP *group; SLBoFIELD *field; int c1, c2, c3; SrsEnv (); LibOpen ("srswin"); for (c1=0; (group = LibNextLibGroup (&c1));) { printf ("Group: %s\n", LibGetGroupName (group)); for (c2=0; (lib = LibNextLib (group, &c2));) { printf (" Library: %s\n", LibName (lib)); for (c3=0; (field = LibNextField (lib, &c3));) { printf (" Data-field: %s\n", LibGetFieldName (field)); /* see what can be done with the fields */ if (LibIsField (field, "index")) printf (" ... is indexed\n"); else if (LibIsField (field, "show") || LibIsField (field, "link")) printf (" ... can be displayed only\n"); } } } } #include #include #include "srs.h" int MyPrintMessage (MSGo *msg) { switch (msg->msg_code) { case e__objectunknown: fprintf (stderr, "ERROR: (%s) %s, %s\n", msg->msg_nm, msg->primsg, msg->secmsg); break; default: if (msg->msg_t != MSGxINFO) fprintf (stderr, "ERROR: %s, %s\n", msg->primsg, msg->secmsg); else fprintf (stderr, "INFO: %s\n", msg->secmsg); break; } return 1; } int main () { SrsEnv (); LibOpen ("srswin"); MsgSetFnct (MyPrintMessage); Query ("[swisprot-definition:acetylchol*]", "Q"); Query ("[swissprot-defintion:acetylchol*]", "Q"); Query ("[swissprot-definition:acetylchol*]", "Q"); ParDefStr ("fieldList", "defintion"); } #include #include "srs.h" int main () { VIEWv view; VIEWvLIB vlib; VIEWvFIELD vfield; IDoENTRY id; ENTRYo *entry; SETo *set; int n, entryN; SrsEnv (); LibOpen (); IcaInitSyntax (LibObjByName ("syntax", "icarus")); view = ViewNew (1, "swiss1"); ViewSetFormat (view, "table"); ViewAddRootLib (view, LibObjByName ("library", "swissprot")); ViewAddRootField (view, LibGetFieldType ("swissprot", "description")); ViewAddRootField (view, LibGetFieldType ("swissprot", "seqlength")); vfield = ViewAddRootField (view, LibGetFieldType ("swissprot", "sequence")); ViewSetFieldFormat (vfield, "gcg"); vlib = ViewAddLeafLib (view, LibObjByName ("library", "prosite")); ViewAddField (vlib, LibGetFieldType ("prosite", "description")); ViewAddField (vlib, LibGetFieldType ("prosite", "patterns")); if (Query ("[swissprot-des:kinase]", "Q")) { set = SetGet ("Q"); entryN = SetSize ("Q"); printf ("query has %d entries\n", entryN); for (n=1; n <= entryN; n++) { SetGetID (set, n, &id); entry = EntryOpen (&id); EntryView (entry, view); EntryClose (&entry); } } } SRS functions list

(1)
Installation

(2)
The SRSWWW server

(3)
SRS Query Language

(4)
SRS Programs

(5)
Icarus

(6)
Icarus Functions

(7)
Adding Databanks - a Guided Tour

(8)
Programming with the C Language API

(9)
The C Language API

(10)
The SRS Object Classes

(11)
Internal


* Index *

The Icarus Language

The Icarus Language

The Icarus language was originally designed to parse flat file databanks. The syntax of these databanks can be often described in layers: the syntax of the entry within the databank, the data-fields within the entry and the syntax of the data-field itself. The full layered syntax we call incremental or recursive. A syntax definition alone is not enough. During the parsing process it is necessary to save certain infomation or to modify or reformat the tokens found. An example is the date in textual representation which might look like "12-APR-88" and for the purpose of indexing needs to be reformatted to the number "19880412". This is one of many tasks that are conveniently executed during the parsing process.

The name Icarus stands for Interpreter of Commands And RecUrsive Syntax which means that commands can be attached to syntax descriptions. In fact, the 'command part' became so powerful that Icarus can be seen as a 'normal' interpreted language such as Perl or Tcl with the added capability of syntax specification.

The current Icarus is not yet a general purpose language, mainly since functions can still not be implemented in Icarus and since a few operators like %, ++, -- are still missing. We developed Icarus so that it meets the demands of the SRS system but we will continue with its development.

Getting Started

Use your favorite text editor to write the program "first" with the line

$print:"hello world\n"

then start the Icarus program with the command

% icarus first

On systems that support the #! syntax for specifying the name of an interpreter, you can put a magical line at the front of the file so that the operating system knows what program to interpret your file with, like this:

#!/usr/local/bin/icarus

(put the proper path in place of /usr/local/bin/try if that is not the path on your system to the Icarus interpreter) and then all you have to say is:

% first

Expressions

Any Icarus expression consists of operands and operators. Operators are binary, if they have two operands, such as the * for multiplication, or unary if they act on one operand, such as the ++ for incrementing the value of the operand. An expression with more than one operation is executed by a certain order. The order depends on the precedence of the operators, the order within the expression since they are normally evaluated left to right, and the grouping by parentheses.

Example:

$sum = (1 + 2) * 3

The result from the expression, the number 9, is stored in the variable $sum.

The operands within expressions can be integers, strings, reals, names, variables, results returned from function calls or expressions within parentheses. The following sections will detail the operands of Icarus expressions.

Basic Types

Icarus provides signed integers (32bit integers), real numbers (implemented as the C language double, a 64bit floating point number), a type called production (rule), which will be explained later and strings.

Icarus knows four types of strings:

  • names
  • single quoted strings
  • double quoted string
  • barstrings - strings starting with a bar until the rest of the line

Examples:

$sqstring  = 'Hello World'
$dqstring  = "Hello World"
$name      = Hello
$barstring = |Hello
             |World

A name consists of one or more characters. The first must be an alphabetical letter and the others alphanumerical characters with the addition of the _. Double and single quoted strings must begin and end on the same line and may contain any character with the exception of the character used for quoting. The quoting character must be represented by an escape sequence, eg, \" specifies the double quote. The escape sequence is used also for other 'tricky' characters:

\n
a newline character or line break
\t
a tab character
\a
an alert (beep)
\decimal number
any ASCII character specified by a decimal number. eg, \10 is the same as \n
\\
the \ itself
\any other character
the character itself. This includes, of course, ' and ".

The barstring may consist of more than one line and is identified by a vertical bar | at the beginning of every line which belongs to the string. It is optionl to put white spaces in the front of the vertical bar. Every char after the vertical bar to the end of the line, including the carriage return is part of the string. The carriage return can excluded from the string with an backslash \ at the end of the line.

Lists and associative lists

Icarus has flexible lists where several or all of its elements can be associated with a name. This association of elements with a name is a feature of associative arrays that are also found in other programming. The difference here is that the elements in the list are always ordered and hence can always be also accessed by position. Lists can have elements of mixed types (eg, strings and integers) and they can be nested to any degree. In the Icarus syntax members of a list must appear withing curly braces (eg, {1 2 3}).

Elements can be accessed by position where the first element (list head) has position 1. The number must appear in square brackets after the list variable name. If a name is associated with the element it can be used by adding the name to the list variable name using a . as separator.

Examples:

Initialize or reset a list:

$list = {}

Define a list with 5 elements of type string:

$list = {a e i o u}

Access members in a list by position.:

$a = $list[2]
$print:$a


will give the output

e

Define a nested associative list:

$list2 = {
  a: {aa: 1 bb: 2}
  b: 2
  c: 3
  d: {1 2 3}
}

here "list2" has 4 elements where the first and the last are lists themselves. The following shows four ways of accessing the same element in "list2" in order to assign the value 5.

Access by associated name:

$list2.a.aa = 5

Access by associated name using the name a stored in a variable. Note that $selector must be put in parentheses; otherwise the name aa would refer to an element in $selector:

$selector = "a"
$list2.($selector).aa = 5

Access by list position:

$list2[1][1] = 5

Access by list position where the position numbers are stored in variables

$i = 1
$j = 1
$list2[$i][$j] = 5

Identifiers: Variables and Functions

In Icarus all identifiers are preceded with a $. Identifiers can be both function or variable names.

So the identifier

$a

can refer to the variable 'a' or call the function 'a'. Functions can receive zero or more arguments which are enclosed in square brackets ([ ]) and separated from the function name by a colon (:). All argument values must be preceded by an argument name with the exception of the unnamed argument. There can be only one unnamed argument per function which must be explicitly defined as such (Interface to C). The unnamed argument must be, if it appears, always the first argument in the list. The following calls the function "print" which receives the unnamed argument "hello world" and the argument with the name 'file' and the value of the argument are stored in the variable 'output' ..

$print:["hello world" file:$output]

If the argument list consists only of the unnamed attribute the square brackets can be omitted:

$print:"hello world" 

Substitutions (Interpreted Literals)

String Literals are delimited by either single or double quotes. They work much like shell quotes: double-quoted strings are subject to backslash and variable substitution; single-quoted strings have no variable substitution.

In all quoted strings, the usual (C programming) backslash rules apply for representing invisible characters such as newline, tab, and so on. Double-quoted strings are also subject to variable substitution. Icarus searches your string for identifiers beginning with $.

Example:

The example

$x =  'World\n'
$print:"hello\n$x"

gets the output

hello
World

There is one problem by the substition of a variable. Is the variable followed by an alphanumeric character the name of the variable is not clear. It is necessary to put the variable in parentheses.

Example: In this example the name Muller or Mueller can be printed dependend on the variable $vowel.

$vowel =  'e'
$print:"Mu($vowel)ller \n "

Printing formats, list, variables and interpolation

In principle there are three printing formats which can be used. The first one is a list argument.

Example:

$print:{'You can mix text and variables (' $variable ') in an list argument.'}

The second example has as argument a string including a variable and have to be enclosed by double quotes.

Example:

$print:"You can mix text and variables ($variable) in an list argument."

The third form is a format string. The metacharacter % requires the presence of additional arguments. It is the same format as in the C language.

Example:

$print:{"You can mix text and variables (%s) in an list argument." $variable}

The square brackets in these three examples can be omitted, because the argument list consists only the unnamed attribute.

Object Description

The Icarus language can be used for the definition of data. Data here are regarded as a series of object definitions. An object comprises of attributes such as an integer, a character string, a list of objects or a reference to another object. The object definition requires knowledge of the object type or class which "knows" the type and name of all attributes of the object. This knowledge in turn can be specified in objects as well which are then of the type "class". In Icarus both objects and object classes can be specified using the same syntax which is equivalent to function calls where the class name is the equivalent of the function name.

An attribute assignment is the attribute name and a colon followed by either a single value or a value list enclosed by curly braces ({}). The following example defines an instance of the object class Shopping_list:

Example:

$shopping_list:[budget:20 buy:{bread butter cheese milk} ]

The attribute .budget is assigned the number "20" and the attribute .buy a list of character strings. An object can reference other objects by two ways. One way is the nested object definition. The following example defines instances of the class $item within the definition of $Shopping_list.

Example:

$shopping_list: {
    $item:[name:bread weight:1000]
    $item:[name:butter weight:250]
    $item:[name:cheese weight:200]
    $item:[name:milk weight:1000]
}

The defined instances of $item are only referenced by the object of type $Shopping_list, they are not part of it. The other way, the direct reference, makes use of object-IDs. An object-ID is a name associated to an object definition through assignment to the special attribute id. An object-ID can be used from anywhere within the programs as a pointer to the associated object. It must be preceded by an @ when used as a reference. The example shows the same definition as above using object-IDs.

$shopping_list:[buy:{@ITEM1 @ITEM2 @ITEM3 @ITEM4}]

ITEM1:$item:[name:bread weight:1000]
ITEM2:$item:[name:butter weight:250]
ITEM3:$item:[name:cheese weight:200]
ITEM4:$item:[name:milk weight:1000]

Control statements

Control statements, such as if-then-else, control the flow of a program. In Icarus all control statements have a common syntax which is similar to that of function calls. In general it consists of a name, e.g., for or while, wich can have an argument and must be followed by a body with a a list of statements. The body can consist of a single statement or a list which must be enclosed in curly braces. The init command is described in the chapter "Precompilation and Execution".

Example:

init{$m=5}

The control statements may optionally receive arguments which follows exactly the same rules as for function calls.

Example:

while:$k < 10
  print:|$k

The if, else and elif statement

starts with the if with one argument followed by the body. The if statement can be optionally followed by elif clause and can be finished with an else statement.

Example:

if:$count<$min
  $print:|The value $count is below the range minimum of $min
elif:$count>$max
  $print:|The value $count is above the range maximum of $max
else
  $print:|The value $count is in the range of ($min to $max)

The while statement

begins with the name while which have one argument statement, followed by the body. The body is a list of statements.

Example:

while ($k > 1)
$print: $k

The for and foreach statement

consists of the name for which receives as single argument a list of three statements as in C (the init, condition and update statement).

Example:

for:{$k=1 $k<10 $k++} {
  $print:$k
  $print:
}

The next Example shows an iteration over a (variable) list:

Example:

foreach:[$elem in:$list]
  $print:$elem

Parsing

This section describes the part Icarus was originally designed for - the parsing of files with a given syntax. Two types of syntax or pattern description are available:

  • an extended version of the Backus Naur format for specifying a context free grammar, which naturally describes the hierarchical structure of programming language constructs;
  • regular expressions for specifying lexemes or patterns. The regular expressions are treated as part of the extended Backus Naur format

Productions

Icarus has a special data type, the production, which is delimited by '~' reminiscent of delimiting strings by quotation marks. A production derives or 'produces' all sentences with a certain syntax, eg,

~ '1' '2'? '3' ~

derives the string "123" or "13". If the input string to be parsed is within the set of derived strings it matches with the production. Parsing of all other input strings will generate a parsing error. The ? after the second symbol ('2') indicates the occurence of the 2 to be optional. A syntax or grammar, can be formed by grouping one or more productions into an associative list. The following defines the same syntax as the above but uses for each of the literals '1', '2' and '3' a separate production.

$rules={
  a:     ~ one two? three ~
  one:   ~ '1' ~
  two:   ~ '2' ~
  three: ~ '3' ~
}
$Parse:['123' prod:$rules start:a]

The variable $rules is assigned a list with four productions named "a", "one", "two" and "three". The production named "a" refers to the other productions by using their name. Parsing of "a" begins with the evaluation of "one" which is a nonterminal since forwards evaluation to production "one" which consists of the literal '1', a terminal, since the string "1" can be directly compared with the input. Both terminals and nonterminals are called symbols. The $Parse command receives as arguments the input string to be parsed ('123'), the production list stored in the variable $rules and the name of the production ("a") to start with.

A production can be seen as an expression with operands and operators which are detailed below.

Operands

The operands within productions, also called symbols, will be matched with the input in the same order as they occur in the expression.

Literal:
A string in single quotes, eg, '1' that must directly match the input. The ' character within a literal must be prefixed with a \ as in '\'hello\''.
Regular Expression:
A pattern to be matched with the input. A regular expression must be enclosed in forward slashes, eg, /[123]/ which matches one of '1' or '2' or '3'. Regular expression are explained in detail in a separate section below.
Production Name:
The name forwards parsing to the production with the specified name which must be part of the same production list as the referring production. This can be also recursive as in 'a: ~ '1' a? ~' which describes a string consisting of more than one '1'.
Subexpression:
An expression contained in parentheses.

Operators

Only one binary but several unary operators exist. All unary operators must be applied after a symbol, eg, "'2'?".
Binary | :
Separates alternative operands, or symbols, that can match. The alternatives are evaluated from left to right, eg, "'1' | '2' | '3'" matches either '1', '2', or '3'.
Unary ?:
Makes the occurrence of a symbol optional.
Unary *:
Asks for zero or more instances of a symbol.
Unary +:
Asks for one or more instances of a symbol.

Regular Expressions

Regular expressions are a powerful way to describe patterns. They are quite similar to productions and have very similar operators. They must appear within forward slashes (/). The characters (^$.[]()?+*) have a special meaning. They must be prefixed with a backslash (\) to be matched literally. This includes also the forward slash.

.
matches any character except newline.
[...]
indicates a set of characters to match, e.g. [()] matches an opening or closing parenthesis. Character ranges can be specified by using a hyphen -, e.g. [0-9] matches a digit. A caret ^ in front of the character set (after the opening square bracket) negates the character set, e.g., [^0-9] matches any non digit character.
(...)
Groups a series of pattern elements to a single element.
|
Separates two alternative patterns.
*
The preceding group may be repeated zero or more times.
+
The preceding group may be repeated one or more time.
?
The preceding group may or may not occur.

Example Productions

The easiest way of learning to write production is by looking at examples.

op:  ~ /[0-9]+/ '+' /[0-9]+/ ~

Matches a number with one or more digits followed by a + which is followed by a number again., eg, "7 + 235".

op:  ~ /[0-9]+/ (/(+|-)/ /[0-9]+/)* ~

As above but the + operator followed by the number is optional or can be repeated any number of times, eg, "7" or "7 + 10 - 15".

expr:   ~ term (/(+|-)/ term)* ~
term:   ~ factor (/\\*|\/) factor)*
factor: ~ /(-|+)?[0-9]+/ | '(' expr ')'

The three productions together describe arithmetic expressions with positive or negative integers and the four operators, +, -, * and /. Parentheses can be used for grouping, eg, "(5+10) * -7".

Using Productions

Although the syntax of the productions used in Icarus is simple and programming of productions is straightforward there are some pit falls to be avoided:

Avoid left recursion

As mentioned above productions can be recursive. If the first symbol in the expression is the nonterminal defined by he production itself, it is said to be left recursive. Consider the example

a: ~ a b c ~

During parsing a will be replaced by the expression "a b c". Since the first symbol of the expression is again a, a will be replaced by a ....which will be replaced by a which...will never end!

Only the last alternative in the list may start with a symbol that is optional (postfixed with * or ?).

In a list of alternatives the first (!) symbol must decide whether or not a subexpression is applied. Consider the example

a: ~ x? a | y? b ~

The first symbol x? of the term x? a will always match since it is optional which means that control is never transferred to the following term y? b.

Within a list of alternative subexpressions a first symbol must not be a superset of the first symbol of the subexpression that follows.

A list of alternatives is evaluated from left to right; the next subexpression is only evaluated if the first symbol of the preceding subexpression fails. Using the production

a: ~ /[a-z]/ | 'abc' ~

the subexpression abc will never be found since it is a subset of [a-z]. If the order of the alternatives is reversed first the string abc and then the presence of any other string composed of characters between a and z will be tested.

Actions

The previous section explained how to write productions that can be used for parsing. None of the examples so far does anything, except raise an exception if a syntax error occurs. However, it is possible to 'let' the productions do something by adding actions to the symbols within a production. An action is a list of Icarus statements within curly braces ({}) that must be associated to a single symbol by placing it after the symbol, eg,

num: ~ /[0-9]+/ {$Print:"matched a number\n"} ~  

Normally the list of Icarus statements is executed after the symbol was successfully matched against the input. This means that in the example above "matched a number" will be printed to the screen as soon as the regular expression /[0-9]+/ was successfully evaluated.

If the production starts with an action it is associated with the entire production and executed after its successful evaluation. Thus

num: ~ {$Print:"matched a number\n"} /[0-9]+/ ~  

will appear to do exactly the same as the previous example but the action is executed after the evaluation of the production "num" instead of after the regular expression.

Example:
expr:  ~ {$Print:"expr: |$Ct|\n"} num op {$Print:"op: |$Ct|\n"} 
         num {$Print:"n: |$Ct|\n"} ~
num:   ~ /[0-9]+/~
op:    ~ '+'~

if applied to the input

3 + 7

will give the output

expr: |3 + 7|
op:   |+|
n:    |7|

The command $Ct returns the current token or the part of the input that matched with the symbol associated with the action.

Icarus knows special scalar variables, which are important because a number of operations affect them. That are the variables:

  • $Ct holds the current token
  • $It
  • $1,$2...$9,$0 $1 returns the first submatch of the most recent regular expression matching. The submatch is indicated by parentheses within the regular expression and the opening parenthesis is used for counting. $2, $3 until $9 will return the submatches with the respective number. $0 returns the entire match.

Execution Times

In Icarus are three types of Execution commands. The "init" command is evaluated in the precompilation-state. In the parsing of the execution-state, there are two commands - the "pre" command (before the match) and the "post" command (after the match). The post command is the default.

Examples:

The "expre" production is the start symbol and will print the string before and a carriage return. The "expre" production calls the production "date" in which the variable $year is set to 96, with the "pre" command. During the precompilation-state $m is assigned with the "init" command to the list of the names of the month. Then the submatches of the day (first parentheses) and the year (second parentheses) is assigned to the variables $day and $month. Because there is no year in the input, the $year still have the value 96 from the pre command. The action node (x{}) directly prints the date string.

$productions={
    expre: ~ {pre{$print:"before \n"} $print:"after\n"} date ~
    date:  ~  {pre{$year=96} 
              init{$m={Jan Feb Mar Apr Mai Jun Jul Aug Sep Oct Nov Dec}}}
              /([0-9]+)-([0-9]+)/ {$day=$1 $month=$m[$2]}
              /-([0-9]+)/? {$year=$1}
              x{$print:"$day\. $month\. 19$year\n"} ~
}


if applied to the input

$parse:['1-12' prod:$expre start:expre]


will give the output

before
1. Dec. 1996
after


Action Symbol

Most commands are executed after the parsing process. Commands within the "node action" can access variables that reflect the parsing process. Such a variable is $ct (Current Token) which gives the matching region of the last symbol comparison. x{commands} (see also action node) has a special meaning for command execution. Commands associated with x will be executed every time when the parser process goes through this point. This "dummy" nonterminal allows to make an action between two

Input/Output

The system is now able to parse a string with a defined syntax, but at some stage the found tokens must be handed over to the calling program or some other function that further processes the token (token processor). Usually the parser hands over control to the token processor after each token has been read.

Since the parser described here is mainly used for the extraction of keys from data-fields, it reads until the end of a data-field is reached and returns a table with all tokens found. Commands are neccessary for directing the insertion of tokens into the table and for the assignment of token codes.

$out

Sets the output table for all writing of tokens for the current production and its dependants.

$in

Sets the input token table for parsing

$wrt

This function can be called inside an action attached to the symbol of a production. It writes the match of the current symbol or a specified string into the output table.

$new

The token is added to the table only if it is unique there.

$app

The token is not inserted as separate entry, but appended to the previous token.

Lazy Parsing

The Concept of lazy/forced parsing can be best understood by thinking of a model of producer/consumer relationship. The producer makes a product (output) which the consumer uses (input). Lazy parsing means, that the parsing process is only started when needed. So we get a "food chain" from the start consumer up to the last producer, which produce output for exact that parsing process. By forced parsing the producer initiates the consumer to start the parsing process. This is good for situations in which it is better to have a special output directly.

Example:

Forced Parsing

Forced parsing is ...

Interface to C

Introducing your C functions as Icarus commands

Like other interpreted languages as Perl, Tcl or Python new commands can be defined and linked to C language functions. Creating a new Icarus command needs three steps:

  • Declaration of the new command in Icarus using the commands $Com and $Var.
  • Implementation of the command as a C function.
  • Insertion of that function in the Icarus function list.

The following example shows you through these steps. To declare a new command $toupper, that converts lowercase characters in a string to uppercase, to Icarus

$com:[toupper f:MyToupper
  arg:$var:[s t:string unnamed:y]
  return:$var:[t:string]

This statement can be placed either into your Icarus program where the command $toupper is used. Of course, you must take care that the command is defined before its usage. The safest is to put the declaration into an 'init' clause.

init{ $com:[toupper ...]}
$print:$toupper:"hello world"

To make the command $toupper available to all your scripts put the declaration into the file 'local.i' with all definitions of user defined Icarus commands. The difference is that this file can be compiled to a C language .h file. Once Icarus has been recompiled with the new header file the definition of $toupper is part of the Icarus interpreter.

icarus icacom.is local.i

srsmake icarus

Particularly useful commands can be requested, or recommended, to be put into 'builtin.i' that defines all commands of the Icarus release.

To implement the command $toupper in C edit the file local.c. You will find there at least one example of an implementation. The following function can implement $touppper:

STRv MyToupper (Int4 runTime, STRv s)
{
  if (runTime)
  IcaGetArgs ("s", &s);
  if (runTime)
    IcaReturn (s);
  else
    return (s)
}

At the bottom of local.c you will find the function LocalInitFunctions. In its body insert the statement

IcaSetFunction ("MyUpper", (Func)MyUpper);

The type casting of "MyUpper" casts it to a standard function prototype.

Glossary

attribute

property, data member or method, these two can be interchangeable to some extent: e.g. the sequence length instead of being stored in the object can also be calculated each time it is requested.

class

A class is an abstract data implementation, not the abstract data type itself.

OR ?

A class is a blueprint or prototype that defines the variables and the methods common to all objects of a certain kind.

expression

a meaningful combination of operands and operators

        example: a = b + 1

grammatic rule

see production.

instance

one of possibly many actual objects that exist for a given class

lexeme

A lexeme is a sequence of characters in the source program that is matched by the pattern for a token.

link

A link is an pointer to any structured data.

match

A match is an agreement between a symbol and the input stream.

messages

Software objects interact and communicate with each other via messages.

nonterminal

A nonterminal is a syntax element defined by a production.

object

a physical and logical unit containing attributes (data members) and behaviour (methods) each object of the same class or type has the same set of attributes and behaviour.

OR ?

Objects are software bundles of data and related procedures. Software objects are often used to model real-world objects you find in everyday life.

parsing

Parsing or syntax analysis, as it sometimes known, is a process in which the string of tokens is examined to determine wether the string obeys certain structural conventions explicit in the syntactic definition of the language.

pattern

A pattern is a production describing the set of lexemes that can represent a particular token in source programs.

production

same as (grammatic) rule, production has a name and a list of symbols to be matched against the input stream

recursion

A recursion includes, as one of its steps, the need to invoke itself.

regular expression

Regular expressions are an important notation for specifying patterns. Each pattern matches a set of strings.

rule

same as production. Look there.

symbol

terminal or nonterminal

terminal

A terminal is a lexical element (token) of a syntax.

token

A token has a code and a string; string is the matching input.

token table

A token table has one or more tokens and a name.

value

A value can be an integer, string, ident, list, namestr or reference.

Installation of SRS

The following is for the release SRS4.05 and later. If you have any suggestions or problems with the installation please contact me.
e-mail: etzold@embl-heidelberg.de

Instructions

Before you compile any of the programs edit the file "srs4_0/odd/srsdb.sdl". You must customize the object 'environment' with the name "unix" ("vms" on VMS). Add or modify a 'libenv' definition for each databank that you would like to index with SRS. Remove or outcomment all 'libenv' definitions of databanks you don't have. Each databank must be associated with the name of the directory with the flatfiles.
Example:
   #libenv /lib=@EMBLNEW_DB    /dir="/data/emnew/"

Some sequence databanks have a special format when used under GCG (EMBL, GenBank, SwissProt). For each of these edit the respective files ("embl.sdl", "genbank.sdl", "swissprot.sdl").

  1. You must change the file name(s) defined in 'file' objects; eg, the EMBL file "fun" is usually called "em_fun" under GCG.
  2. In the 'libformat' definition for these databanks change the 'file_type' attribute so that it points to 'GCGREF_FILE' and 'GCGSEQ_FILE'. It is all there - all you have to do is move the begin-of-comment character ('!'). Now 'go' to the root directory of SRS ("srs4_0") and invoke "srsinstall":
    > srsinstall all
    This script asks you for the 'make' and 'cc' commands, compiles all the programs and, using the ODD compiler, creates a new binary file with all data defined by the files in the 'odd' directory.

    To build the indices 'source' the file "etc/prep_srs" and issue the command

    > srscheck
    If it complains then, if a path or file name is at fault, edit the appropriate file in the directory "odd" (eg, "srsdb.sdl") and run "srssection" to recompile the ODD files.

    If anything went well, build the indices with

    > srsbuild
    "srsbuild" invokes the script that was generated by "srscheck". You can create a crontab file with these two commands to keep the indices up to date automatically.

    The only program you can use for searching is the command line interface "getz". You can invoke it in two ways: Either prepare the SRS environment with

    > source srs4_0b/prep_srs
    or copy the file "$SRSEXE/getz" ("SRSEXE" is by running "prep_srs") to a directory that is included in your path (eg, "/usr/bin"). Try the following commands:
    > getz -help 
    prints all command options (the same is true for "srsbuild", "srscheck")
    > getz -libs 
    prints status of all indexed libraries
    > getz -info swissprot 
    prints more information on a single databank
    > getz '[swissprot-def:elastase]' -f 'id def'
    searches all "elastases" in swissprot and prints the "ID" and "Definition" fields of all found entries

    Additional Steps to Install the SRSWWW Server

    • Run the "srsinstall" again with option "www"
      > srsinstall www
    • The executables and the document files are, at least to the knowledge of the server, situated in two different directories 'srs' and 'srsdoc' respectively. Add the script alias 'srs' in the file 'srm.conf':
      ScriptAlias /srs/ /usr/local/srs/www/
      and the alias 'srsdoc' in the same file:
      Alias /srsdoc/ /usr/local/srs/www/
      or add the symbolic link 'srsdoc' into the httpd's document root.

      If for some reason the names 'srs' and 'srsdoc' are not acceptable you can change them (eg, if you want to run two different SRSWWW servers in parallel).
      To change the directory name with the executable, 'srs', replace the string '/srs/' in 'odd/hyperlink.sdl' and if you you don't make your own network images (see below) 'www/srswww.map'. Edit the file 'www/wgetz.script' and change the assignment to 'cgidir'.
      To change the directory name 'srsdoc' edit the files www/wgetz.script' and 'www/wgetz_text.script' and change the assignments to 'docdir'.

    • For the clickable map the location of the program 'imagemap' must be defined in the file 'www/wgetz.script' (assignment to the variable 'imagemap'). This file contains also variables with the path of the file with the icon link to your homepage ('homePageIcon') and your homepage's URL ('homePageURL') that will both be used in the top page of SRSWWW.

    • You can now access the with the URL "http://serverAddress/srs/srsc"

    • Each user of the server will get his own directory in "srs4_0b/www/tmp". The directory and the file "user.par" don't take much space but will have to be deleted occasionally. A "crontab" job can handle that.

    • SRSWWW inserts many hypertext links into the entries before display. These often request SRSWWW to retrieve an entry from a databank installed locally. You must change the configuration of the hypertext links if one or more of the databanks addressed are missing.
      Edit the file "hyperlink.sdl". There you find definitions of 'linkcall' objects. The first link to medline already suggests a the alternative of a link directly to medline. In other cases you may address SRSWWW servers installed on other nodes; eg, replace "/srs/srsc" by "www.embl-heidelberg.de/srs/srsc". After the changes you must run the command "srssection" to recompile the ODD files!

    Optional

    • SRSWWW builds almost every HTML page during run-time. You can, to some extent, change their layout and content.
      Edit the file "srs4_0b/www/wgetz.script". You find here the templates for all pages. The file contains labels that start with "@@" and directives for the insertion of numbers ("%d") and strings ("%s"). You can change anything except the order and content of labels and directives.

    • You can create your own network image! This is a new feature and the following procedure has been tested only at the EMBL:

      • Set the default to the directory 'www' and run the program 'srsnet.tcl'. It is a tcl script that requires 'wish' with a tk version 3.x or 4.0. Use command 'load' to load all databank icons onto the canvas. At the first time the file 'srsnet.dat'with coordinates is missing and all the databanks will be put into a vertical row. Now move all databank icons around until you are satisfied (use left mouse button) and save the databank's coordinates with the 'save' option.

        If some time later you add new databanks they will appear at the left top corner of your network picture - simply drag them to a more appropriate location.

      • Make the program 'srspict' with
        srsmake srspict
        

      • Run the command
        srspict -n
        
        to create the network picture. This will read the coordinates you saved within 'srspict.tcl' and produce a GIF file and the map file for the httpd.

      • Run the command
        srspict -t
        
        to produce both the GIF file with the network as tabular diagram and the map file (This does not require the coordinates).

      • Tell SRSWWW to use your own GIF files by editing the file 'www/wgetz.script'. Just flip around the comment character ('#') so that 'NEWNETWORK' is defined:
        @@# OLDNETWORK = 'NETWORK'
        @@ NEWNETWORK = 'NETWORK'
        

    Identification Convention

    Identification Convention

    1. General

    All identifiers should be in NameName format. If identifier name has more that one tag, every tag (except the first) starts from a capital letter.

    Example: 
    tokenListName
     

    2. Public

    2.1 Function names:

    Function names should start from (short) capitalized module tag followed by a function name in NameName format.

     Example:  
    IcaFunctionCall 
    

    2.2 Variable Names:

    Variable names (external and static) should start from a module tag and a name in NameName format.

    Example: 
    icaGlobalScope
    

    2.3 Names of Macro Functions:

    Macro names should start from the underscore character, a capitalized module tag and a name in NameName format.

    Example: 
    #define _IcaPrintError(x) printf("%d\n", (x))
    

    2.4 Names Macro and Enumeration:

    Macro names should start from all capitalized module tag plus "x" and a name in NameName format.

    Example: 
    #define ICAxMaxNameSize 32
    enum repeat {BNXxOne, BNXxZeroOrMore, BNXxZeroOrOne, BNXxOneOrMore};
    

    2.5 Type Names:

    Type names should start from all capitalized module tag plus "o" and a name in NameName format. For pointer to the structure instead "o" should be "p", for counted pointer it changes to "v".

    Example: 
    typedef struct ICAoProdName { ... }  ICAoProdName,
                                        *ICApProdName,
                                        *ICAvProdName;
    

    3. Exceptions

    3.1 def.h and def.c:

    There are several constants, variables and functions that have common meaning like maximum or minimum macros. All this stuff should be placed in def.h and def.c files. Those file have "personal sections" where every person of SRS team should put his own variables. All variables in those files do not have module tag and start from a capital letter.

    Example: 
    #define True 0
    typedef Int4 int;
    

    4. Function Head Description

    Function head has a format represented bellow:

    /****** RegWildToRegexp *************************************************
    **
    **      converts a string containing wildcards into a regular
    **      expression; the world can contain the wildcards '*' (any number
    **      of chars) and '?' (any single character); the function returns
    **      the position of the first wildcard within the word (first
    **      position is 1!); "." is converted to "\."
    **      expression will begin with '^' and end with '$';
    **
    **      INPUT:   o string containing wildcards [R]
    **               o pointer to output regular expression [R]
    **               o flag if wildcards (see above) are to be recognized as
    **                 such and be replaced within a regular expression [R]
    **
    **      RETURNS:  0 if word contains no wildcards
    **                position of the first wildcard in string (1=string begin)
    */      
    

    The first line has the format "/****** FunctionName ********" than a description of the function. The "INPUT" and "RETURNS" are essential part of the head. If argument description too long to fit in one line all the argument descriptions should have a prefix "o" as in the example above. The last line has a format "*/"


    Documentation Convention

    1. Names

    Icarus Functions, Icarus Variables $name
    SRS classes $name
    attributes of SRS classes .name
    names 'string'
    characters courier
    value "string"
    C Functions name
    C structures name
    C variable names name
    examples courier

    short one in quotes

    t

    Programming in SRS

    Introduction

    It is very easy to write programs that use all of SRS's power to retrieve, link and access entries from all indexed databanks. Just link your program to the SRS library (written in C, documentation will be available). The file "srs4_0b/src/try.c" is an example of such a program:

    #include <stdio.h>
    #include "srs.h"
    
    int main ()
    {
      SrsEnv ();
      LibOpen ();
    
      if (Query ("[swissprot-def:elastase]", "Q1"))
        printf ("query Q1 found %d entries\n", SetSize ("Q1"));
    }
    

    The program must (in that order)

    • include the file "srs.h" (in the directory "$SRSROOT/src");
    • call the function SrsEnv (without arguments) that defines all SRS directory names;
    • call the function LibOpen with the name of the binary file containing all run time data, eg, all information about the indexed libraries.

    The program can be compiled (and run) anywhere:

    > cc -Isrs4_0/src try.c -I$SRSEXE $SRSEXE/libsrs.a -o try
    

    The variable "SRSEXE" is defined by executing the c-shell script "prep_srs" (see above).

    Note that modules without a "main" section must define the macro "DECLARE_ONLY" before including "srs.h".

    Example:
    #define DECLARE_ONLY
    #include "srs.h"
    


    Programming Examples

    All program examples given are complete. Each example can be compiled as shown for the program "try.c" in the introduction.

    Performing queries

    The function Query lets you submit any SRS query language expression. Each query must be associated with a name. If successful, that name lets you access the resulting set or can be used within further query expressions. The following retrieves all "receptor" sequences from EMBL and, using SetSize, prints the size of the resultant set. The next query searches "acetylchol*" and performs an AND operation with "Q1" from the previous query. The last two queries link "Q2" to SwissProt by both link operators.

    INCLUDE EXAMPLE:ex002.c

    Printing Entries

    Three steps are required to access a single entry from a successful query:

    • SetGet uses the query name to retrieve the set object (SETo).
    • SetGetID retrieves the nth ID-object (IDoENTRY) from the set object.
    • EntryOpen uses the ID-object to create an entry object (ENTRYo). Use EntryClose to delete this object after use.

    Once the entry is opened the annotation and, if exists, the sequence can be obtained. Here only the "ID" and the "Definition" data-fields are extracted from the entry and printed by EntryPrintFields. The two fields are selected using the function ParDefStr to successively assign the global parameter "fieldList" the values "Definition" and "ID". This method to define global parameters accessible by all functions in the library is commonly used. "fieldList" can be reset by assigning the value "reset". You will see more examples of that in other programs where even functions are assigned as parameter values.

    INCLUDE EXAMPLE:ex003.c

    Accessing Information About the Databanks

    This program accesses information about the databanks seen from SRS. The run-time-library provides iterators to access library group, library, and respective data-field information ( LibNextLibGroup, LibNextLib, LibNextField). For iterating over all libraries (databanks) one must first iterate over the group and then descend to the libraries. The function LibIsField can be used to obtain more information about the data-field.

    INCLUDE EXAMPLE:ex004.c

    Redefining Message Processing

    SRS prints quite a few error messages, warnings and informational messages to "stderr". The function MsgSetFnct allows you to redefine the function that prints these messages. When called it receives a pointer to the message object MSGo as argument and must always return 1.

    The message object MSGo contains several fields with the message type, the message name, etc. The message name (eg, "e__objectunknown") is defined as macro, so it can be directly used for comparisons (see switch statement below).

    The example performs three queries, where only the last is successful since the first two specify incorrect databank and data-field names. The assignment to the global parameter "libList" is also incorrect since the data-field name is misspelt.

    INCLUDE EXAMPLE:ex005.c

    Constructing an SRS query expression

    If you write a user interface to SRS you might create a form displaying all the searchable indices plus some more search options. The user input would have to be collected and combined to an SRS query string which can be submitted to the function Query. The functions in the "queryassist" module help you to construct that query expression. It is possible to construct a query step by step and at the end ask for the complete expression. The example first constructs a query with a string search and a range search in two databanks. The resulting string is then used to generated a link expression.

    INCLUDE EXAMPLE:ex001.c

    Printing Entries with Views

    This prints a set of SWISS-PROT entries with a view defined in the program.

    INCLUDE EXAMPLE:views.c

    SRS functions list

    The SRS Query Language

    In SRS any retrieval command, logical operations with sets that were obtained by previous queries, links between sets of different databanks, or a combination of all can be expressed by the SRS query language. This chapter describes the language and gives examples of its use.


    General Syntax

    A query is an expression with operands and operators. In this chapter queries are sometimes shown as equations in the form

    queryName = expression

    The query name will be associated with the resultant set of entries. Expressions can specify index searches, logical operations between sets and link operations or a combination of all.

    List of Operators

    |
    Logical OR.
    &
    Logical AND.
    !
    Logical AND NOT, or in colloquial english, BUT NOT.
    >
    Link to the right operand.
    <
    Link to the left operand.

    The link operators have precedence over logical operators.

    List of Operands

    Name of a Databank
    In SRS only one name for each databank is used (eg, "EMBL"). Currently only the link operators accept the databank name as a valid operand.
    Set Name
    Each query must be given a name (eg, "Q1") which can be later used to operate on the set that results from that query.
    Index Search
    A command to search in one or more indices of one or more libraries.
    Expression
    An expression is treated as an operand if it occurs within parentheses (eg, "(Q1&Q2)>EMBL"). Parentheses can be nested to any degree.
    parent
    Special operand that allows the conversion of a set of subentries (eg, sequence features) into a set of entries (sequence entries). This is achieved by linking the set with the subentries to "parent" (eg, "Q1 > parent").

    A query can be minimally a single operand excluding databank names and the "parent" keyword.


    Searching in Indices

    This command specifies a search in a single index or a group of indices of one or more databanks. An index search must specify within square brackets the databank or databank group name, the index or index group name, and a search expression. The two names must be separated by a hyphen ('-') and be separated from the search expression by a ':' (string search) or a '#' (range search). Both the field name (eg, "Definition") and its abbreviation ("DEF") can be used as index name. All strings, including the search words, are treated case insensitive.

    Example:
    [pir-def:elastase]
    searches "elastase" in the DEFinition field of the protein databank PIR.

    As indicated above two different types of searches, the string search and the range search exist. A string search expression starts with a colon (':') after the index name whereas the range search starts with a hash ('#'). Range searches can be performed only in indices of the types "num" and "real"

    Searching Strings

    A search expression is a single search word or several words separated by a logical operator. Parentheses may be used for grouping.

    Examples:
    [embl-key:insulin]
    [medline-aut:needleman,*!wunsch,*]
    [embl-def:(acetylchol*&receptor)!muscarinic]
    

    Wildcards are useful for searching a group of words or whenever it is unclear how a word is spelt in the databank. You can use two different types of wildcards:

    *
    Matches one or more characters of any value;
    ?
    Matches a single character of any value,

    Any number of wildcards can be placed anywhere in the search word. If you place one at the beginning you might have a slightly longer response time since then all words of the index have to be searched. But don't worry too much about that - it is still quite fast!

    Regular Expressions

    Since search words with wildcards are translated into regular expressions, it is of course possible to enter regular expressions directly. They must appear within forward slashes ('/'). Some characters ("^$.[]()?+*") have a special meaning. They must be prefixed with a backslash ('\') if to be matched literally.

    ^
    marks the begin of a string, eg, "/^phos/" will find all words beginning with "phos", eg, "phosphate".
    $
    marks the end of a string, eg, "/ase$" will find all words ending with "ase", eg, "kinase".
    .
    means any character.
    [...]
    indicates a set of characters to match, eg "[()]" matches an opening or closing parenthesis. Character ranges can be specified by using a hyphen ('-'), eg "[0-9]" matches a digit. A caret ('^') in front of the character set (after the opening square bracket) negates the character set, eg, "[^0-9]" matches any nondigit character.
    (...)
    Groups a series of pattern elements to a single element.
    *
    The preceeding group may be repeated zero or more times.
    +
    The preceding group may be repeated one or more time.
    ?
    The preceding group may or may not occur.
    Examples:
    /^5...$/
    finds all 4 digit numbers with a five at the begin;
    /^nif[a-e]$/
    finds the gene names "nifa", "nifb", "nifc", "nifd", "nife";
    /^mue?ller$/
    finds both "muller" and "mueller".

    Note that searches with regular expressions can be slow since all words in the index have to be searched.

    Searching Numeric Ranges

    In a numeric index (integers, reals) it is possible to search numeric ranges. The number index is only applicable where there is a one to one relationship of entry and value (eg, sequence length, creation date, resolution)

    A range can be specified by a single value or two values separated by a colon (':') where the left value must be smaller than the right value. To exclude a boundary value from the range put a '!' in front. A missing number on the left means the minimum, and on the right the maximum value in the index.

    Examples:
    The following are queries in an index of the sequence length.
    400
    selects all sequences with the length of 400
    400:500
    selects all sequences from 400 to 500 residues
    400:
    selects all sequences longer than 400 residues
    :500
    selects all sequences up to 500 residues
    400:!500
    selects all sequences between 400 and 500 residues excluding 500
    :
    is also valid and retrieves ...all sequences

    Note that ranges can be combined by logical operators.

    Example:
    300:!500 | !600:700
    or
    300:700 ! 500:600
    retrieve the same set of sequences, namely all sequences from 300 to 500, excluding 500, plus all sequences from 600 to 700 where the 600 is excluded.

    Using Logical Operators

    The three logical operators OR ('|'), AND ('&') and BUTNOT ('!') can be used to combine search words in an index search, or sets in a query expressions. The figure illustrates the effect of the three operators in an expression of the form "A operator B"

    Within expressions, parentheses with any degree of nesting are allowed.

    Examples:
    [medline-authors:(wu* & rice*) ! (smith* | jones*)]
    (q2 & q2) ! (q3 & q4)
    

    Logical operations can be only performed between two sets of the same type. It is not possible to combine a set of entries and a set of subentries (see below). In those cases an additional link operation must be specified.


    Using Link Operators

    The powerful link operators are unique in the SRS query language. They to some extent resemble the join in relational databank systems. The two link operators '<' and '>' combine two sets from different databanks.

    The figure shows two databanks "A" and "B" where some entries in "A" have cross references to entries in "B" as indicated by red lines. These cross references are processed to build link indices which provide the basis for the link operation.

    A > B
    gives those entries in "B" that are referenced by entries in "A"
    A < B
    gives those entries in "A" that reference entries in "B"

    References are by nature not bidirectional, that is, there is no guarantee that entries in "B" that are referenced by entries in "A" have references back to "A". The link indices in SRS, however, can be always used bidirectionally. The two link expression can now be seen as:

    A > B
    gives those entries in "B" that are linked to entries in "A"
    A < B
    gives those entries in "A" that are linked to entries in "B"

    In this context it is irrelevant which databank contributed the information for building the link index.

    Example:
    [swissprot-def:kinase] > PDB
    The index search retrieves all kinase sequences from the SwissProt protein sequence databank which are then linked to the PDB databank of solved tertiary protein structures. The result is all the PDB entries with atomic coordinates for all kinases for which the tertiary structure has been determined.

    In SRS all the pairwise links are combined to generate a network of databanks. Within this network a link can be performed from any databank to any other. If two databanks are not directly connected by a link then a series of links is performed. The following rules are applied resolve links:

    • The same pairwise link index is used for both directions.
    • SRS tries to find the shortest possible way for linking entries from two libraries. Ideally this is the direct link as, eg, between EMBL and SwissProt; if no direct link is available (eg, EMBL > PDB) then automatically the optimal or cheapest succession of links is performed (eg, EMBL > SwissProt > PDB).
    • If a set contains entries from different databanks (eg, from EMBL and SwissProt) then the subsets of all libraries found in the set are linked independently.
    Examples:
    enzyme < pdb
    The Enzyme databank contains all known reactions catalyzed by enzymes. The number of entries retrieved by the query is the number of different reactions catalyzed by proteins with known structure.
    [swissprot-id: acha_human] > prosite > swissprot
    The index search retrieves the SwissProt entry "ACHA_HUMAN". This entry is then linked to the Prosite entry(s) that documents the protein family where "ACHA_HUMAN" is a member, in this case the family of neuronal acetylcholine receptors. The next link retrieves all SwissProt entries that belong to that family. In Effect, the entry "ACHA_HUMAN" is amplified to all members of the protein family or families it belongs to. the example shows that it is possible to navigate over the databank network with an explicit succession of links that is evaluated from left to right.
    [swissprot-id:tdt_human] > prodom > pdb
    This example shows how the amplification by homologous entries in the same databank can be used to find related information in another databank to which the single entry itself is not linked. The query retrieves a DNA polymerase from Swissprot, expands it by related proteins as documented in Prodom (databank of protein domains, another possibility would be Prosite or HSSP) and links these entries to PDB. The result is the set of PDB tertiary protein structures that are homologous to the SwissProt entry "TDT_HUMAN".
    q = [sequence-def: kinase] q ! (q < swissprot)
    Most protein or DNA databanks overlap to a great extend which creates a lot of redundancy. The annotation of equivalent entries in different databanks can be quite different which ban be very useful for string searching since the probability of finding a certain enzyme name is much greater if you search all sequence databanks. After the search the links come in handy to remove the overlap. The first query in the example searches "kinase" in all sequence databanks (eg, EMBL, PIR, SwissProt, GenBank). The second query removes the overlap. The goal is to have SwissProt entries plus those in other databanks that do not have equivalents in SwissProt. This is achieved by subtracting all entries from "q" that are linked to SwissProt. SwissProt entries in "q" are not linked to SwissProt and won't be removed!. Just change "SwissProt" to "PIR" if you would rather have PIR entries.

    Entries and Subentries

    Sets originating from the same databank may have different set types. Consider the two queries:

    [swissprot-keywords: transmembrane]
    [swissprot-features: transmem]

    The first query retrieves all SwissProt entries that have transmembrane segments, the second finds all transmembrane features contained in SwissProt entries. The second query will retrieve many more entries since most transmembrane proteins have more than one membrane spanning segment. If you requested the sequences for entries in the second set you would get the transmembrane segments and not the parent entry's sequence. The first query returns a set of entries whereas the second returns a set of subentries. The "features" index has a special type: searches in that index will for all sequence databanks result in sets of subentries. Sets of entries and subentries can not be combined with logical operators! Only the link operators may be used between them, ie, it is always possible to link subentries to their respective parent entries.

    Example:
    [swissprot-org:human] > [swissprot-features:transmem]
    returns all transmembrane segments found in human proteins.
    [swissprot-org:human] < [swissprot-features:transmem]
    returns all human proteins that have transmembrane segments.

    Sometimes it is necessary to do an explicit conversion from subentries to entries. This can be done with a link to "parent".

    Example:
    [swissprot-features:transmem] > parent | [swissprot-key:transmembrane]
    returns all entries that have the "transmembrane" keyword or "transmem" sequence features. This may be necessary to ensure all entries with a certain property are retrieved - the annotation is often not complete!
    [swissprot-features:transmem] > parent > pdb
    finds all PDB entries of proteins that have transmembrane segments (even though the known structure may not yet include the transmembrane region).

    Icarus Documentation

    SRSWWW

    Introduction

    SRSWWW is an World Wide Web interface to Sequence Retrieval System (SRS). Compared with other SRS interfaces SRSWWW has more users because of its availability on the web, its easiness and its user friendly interface. It supports HTML3 and lesser versions of html. Since http is stateless an user id is created to keep the state for the whole session.

    On most pages in the srswww are six header buttons which have links to other srswww pages. One header Button is the 'Top Page' which is the start page of the srswww. The other buttons are the 'Query Form' page, the 'Query Manager' page, the 'View Manager' page, the 'Databanks' page and the 'Help' page. The 'Help' page is context sensitive.


    SRSWWW

    The Top Page

    The Top Page is used to select the searching Databanks. Selecting databank(s) can be done by clicking their check boxes. In all cases the Databank names are links to an information page.

    Continue & Reset Button

    The 'reset' button can be used to deselect all selections done so far. Each databank can individually be deselected by clicking again their checkboxes. Clicking the 'continue' button finishes the 'Top page' and brings up the 'query form' page.

    Common Fields selection

    Some fields in the databanks are common (eg., id field). The check box 'Show only fields that selected databanks have in common' is used to list only the common fields in the 'query form' page.

    Grouping the Databanks

    In the Top Page all available databanks are collected in groups defined by SRS (eg. 'sequence related').

    User defined Databases

    There is a possibility to include user defined Databanks. For example with the search engine FASTA or BLAST special databanks can be created. Before such a Databank can be selected it has to be created with a (eg. FASTA or BLAST) search.


    SRSWWW

    The Query Form Page

    With the 'query form' page the databank query is defined. The selected databank(s) is/are listed at the top of the page. Which fields are listed depends on the 'Show only fields that... ' check box from the 'top page' and the searchable fields of the databank(s).

    Do Query & Reset Button

    The 'reset' button can be used to deselect all selections done so far. Each check box can individually be deselected by clicking again. Clicking the 'Do Query' button starts the query and brings up the 'query result' page.

    FieldName, Query, Include in List and Retrieve Subentries Column

    The main query fillout form has four columns. The column 'FieldName' lists all field names which are links to an information page. The 'Query' column is the input field for the query. The 'Include in List' column is a check box for inclusion of the corresponding field in the query result. The 'Subentries' column is a check box for the inclusion of subentries in the query result. The last two check boxes can be done also by the view definition, but here it is just faster and easier.

    Additional Menus

    Some fields can have additional menus with "greater than" and "greater than or equel to" and "less than" and "less than or equal to" symbols (eg. seqLength) for their range selection. (eg., seqLength > 100 && seqLength < 500).

    Combine Searches with

    Once the keyword fields are filled for the search, they can be combined with the boolean operators 'AND', 'OR' and 'NOT', and can be appended by a wildcard to make the query more elaborate.

    Chunk Size and View Selection

    Additional options are 'Entry list in chunks of' to define the number of entries shown per page and a view selection (see Chap 'The View Create/Edit Page' for more detail on view). A View can be defined before doing a query. All the views which are applicable to the selected databanks are listed here and one of them can be selected . The default view is 'No View'.


    SRSWWW

    Browse Index Page

    From the 'query form' page the 'browse index' page is reachable by clicking a field (eg. the 'ID' field).

    List Values Button

    With the 'list values' button the values which are selected by the match option can be listed in page 'Values in the index of the ... field'.In this list values can be select and whith the 'Make Query' button the 'Query Result' page is reached.


    SRSWWW

    The Query Result Page

    The Query result page shows the query strings constructed by the query form input fields, the number of hits found and entry names with check boxes and fields (if selected by the 'query form' page or in the view definition). Entries can be selected by the checkboxes. The 'reset' button can be used to deselect all selections done so far. With the 'link', 'receive' and 'view' submit buttons further manipulations can be done with the result entries.

    Link Button

    With this button the whole/selected result entries can be checked wether they are ilinked to other databanks (see Chapter 'The Link Page' for more detail information).

    Receive Button

    With the 'receive' button the selected entries can be downloaded to the client disk.

    View Button

    With this button the result entries can be viewed with predefined view definitions. The view definitions can be selected out of the view box.

    Chunk Hypertext Links

    The last line are hypertext links for any nth chunk set. These links are only present if the number of entries found is bigger than the number of the defined chunk size. The chunk set numbers starts from 1 to "number of hits" divided by "entry list chunk size" (selected from 'query form' page). Users can skip to any nth chunkset through the hypertext link. The current chunk set is shown within braces. The left anglebrace hyperlink moves to the first chunkset whereas the right angle bracket hyperlink moves to the last chunkset.


    SRSWWW

    Single Entry Page

    Every entry found and listed in the 'Query Result' page is a link to the entry information. Clicking to the entry link, the 'single entry' page comes up and shows the entry form.


    SRSWWW

    The Link Page

    The 'Link' page is used to find the links between the found entries (the set) and the selected Databanks. The user can decide out of three options to display the different entries. The 'link' page lists all the databanks like the top page. The user should select the databanks which are different from the databanks selected for query search and should select one of the three following options. Clicking on the 'continue' submit button shows the 'query result' page. The 'link' can also be done in the 'query manager' page (see Chapter 'Query Manager Page').

    (More about linking can be found in the Chapter srs manual ....)

    Find all entries:

    in the selected DATABANKS which are linked to the current set

    the result are entries out of the selected Databanks, which are linked with the set.

    in the current SET which are linked to all selected databanks

    the result are entries out of the set, which are linked with the selected Databanks.

    in the current set which are not linked to any of the selected databanks

    the result are entries out of the set, which are NOT linked with the selected Databanks.


    SRSWWW

    Query Manager Page

    The function of the 'query manager' is to control the queries done so far. The queries are listed in a table. Every query is listed with a check box, their name in the form 'Qn' (eg.,Q1, Q2,..), a type (eg., 'query' , 'link' etc.,), the total number of entries found, the library name(s), the number of entries for each library, the query expression (srs query syntax) and a comment . The comment can be filled from the user. For html3 (HTML version 3) mode user gets a table of all these information and for lesser version same information is available with different style in different order. The second function of the 'query manager' is to make further queries and links. There are three functions to control the queries and three functions to do further queries and links.

    Control Functions

    Receive With the 'receive' function the selected queries can be exported to the clients disk.

    Delete The 'delete' function deletes selected queries.

    View The 'view' function can be used to inspect a single query again.

    Query/Link Functions

    Link The 'link' function is exactly the same as in the 'query result' page, see detailed information in the Chapter 'The Query Result Page'.

    Combine With this function it is possible to combine one or more queries with the logical Operators AND, OR or NOT.

    Expression With this function the User can directly enter a valid query. The 'expression' function do not need any query selection. Expression is unique in the sense that itallows you to enter more than one boolean operators and link operators at once. In this case the user can enter a complex query like (Q1 & Q2) & !(Q3 | Q4) > PDB etc. In the query form page user is allowed to use only one of the boolean operators at a time.

    Result Display Options

    The 'query manager' has two options to manipulate the 'query result' page.

    Entry list in chunks of ... and using the view The options 'Entry list in chunks of ...' and 'using the view' is allready described in the Chapter 'The Query Form Page'.

    ??? Save in history queries of type ... ???


    SRSWWW

    View Manager Page

    The 'view manager' page can handle views by 'create a new view', 'edit selected view' or 'delete selected view'. It lists all the views defined so far in a table with View Name, Format, Root Libs, Root Fields, Leaf Libs and Leaf Fields. The view concept is independent from the queries but can be attached to the queries. After doing a query on the selected database(s) the user gets a set of entries as a result. View helps to see whether these entries may have links to other databases. View can be configured to see the fields of interest from the set and from the linked database entries.

    independent View Editor

    With the 'independent View Editor' a new netscape window is created. With that 'view editor' it is possible to change the view(s) or create new ones without leaving the 'query manager page' to get a new or different view.


    SRSWWW

    Create A New View Page

    In the 'Create A New View Page' the available Databanks are listed in two coloumns. The databanks in the first column are called root databanks. The databanks in the second column are called leaf databanks. The root databanks refers to the databanks used for a particular query search. The leaf databank refers to the databanks which will be linked by the result set of a query search (from the 'root' databanks). For example the user can define a view with swissprot as root databank and prosite as leaf databank. In the 'View Select' page the fields which have to be displayed from both databanks have to be selected. Choose this as a current view and make a query on swissprot (which is the root databank). The result will be swissprot entries and for entries with a link to prosite the prosite entries.

    Name of new view

    The 'create a new view' page has a 'Name of view' field for the view name. In the absense of the view name specification it creates a view name prefixed by the first root databank name and a viewnumber at the end (eg., Swissprot_view1, Prosite_view5 etc.).

    Display view as table

    With selecting the 'Display view as table' checkbox the result is displayed in a table form instead of a list form.

    Print short field names in header

    With this checkbox it is possible to get the short field names in the header of the table columns.

    Show only fields common to selected root databanks

    This checkbox is selcted by default. So only common fields of the root databanks are listed.

    Continue & Reset Button

    The 'reset' button can be used to deselect all selections done so far. Each field and checkbox can individually be deselected by clicking again. Clicking the 'continue' button finishes the 'Create new view' page and brings up the 'View Field Select' page.


    SRSWWW

    Edit Existing View Page

    With this page a predefind view can be edited. The 'edit existing view' page is a prefilled page with the same options as the 'create a new view' page.


    SRSWWW

    View Field Select Page

    Lists the fields of all selected root- and leaf databanks. Fields can be selected by their checkboxes and are displayed in the query. The display format of the sequence field can be selected by the format menu selection (eg. fasta, pir, embl, gcg etc.). The leaf databank selection have four options:

    Use query instead link

    ???

    Use view to display entries

    ???

    Display only number of linked entries

    Displays only the number of links which exist, not the links itself.

    To submit the view one of the four options ('Top page', 'Query form', 'Query manager' or 'View manager') must be clicked.

    Databanks Page

    The 'Databanks page' lists all available Databanks in a table form. Every databank is listed as a link, the release, the number of entries, the indexing date, the group (eg., HomolSearch, Sequence etc. and a availability flag.

    Help Page

    Most of the information about the databanks and their fields description are available through hypertext links. Help is provided wherever possible in a case sensitive way. In addition to providing information, field hrefs can browse their index by entering a keyword. The result will be shown with checkboxes which can be selected and combined for further search.

    Guided Tour

    Adding Databanks - A Guided Tour

    This chapter is an introduction to SRS seen from the maintenance side and requires knowledge of the basic principles of SRS and, to a lesser degree, the Icarus language. It describes the integration of two 'demo' databanks into SRS. There have to be two databanks in this guided tour in order to demonstrate the specification of links.

    The Databanks

    The first databank which we call Genes is in a 'Genbank like' format. Every entry of this databank consists of an annotation and a DNA sequence part. The annotation has the four data-fields: "LOCUS", "DATE", "DEFINITION", and "CITATION". The "CITATION" field in Genes links the name of an entry from the other example databank - RefList. The RefList databank has an 'EMBL like' format and is a compilation of literature citations which are referenced in Genes. Every entry of RefList has four data-fields: The unique entry name ("ID") and the lines starting with "RT", "RA" and "RL" that describe the title, the author names and bibliographical reference of the literature citation. Samples of the two databanks can be found in the directory "SRSDEMO" in the files "genes.dat" and "reflist.dat".

    Example of a Genes entry:

    LOCUS       HSU07616
    DATE        02-FEB-1995
    DEFINITION  Human amphiphysin mRNA, complete cds.
    CITATION    YAMOR95
    SEQUENCE  
            1 ccaggtgcct actgactcct tcagaaatgt cagttcctgt cccatgccct taatatttcc
           61 cacatgcagg gctctgtgca caatgcgtga caatggcttt tagat
    
    //
    

    Example of a RefList entry:

    ID   YAMOR95
    RA   Yamamoto R., Li X., Winter S., Francke U., Kilimann M.W.;
    RT   Primary structure of human amphiphysin, the dominant autoantigen
    RT   of paraneoplastic Stiff-Man syndrome, and mapping of its gene
    RT   (AMPH) to chromosome 7
    RL   Hum. Mol. Genet. 4:265-268(1995).
    //
    

    The Syntax Description

    To add a new databank to SRS you need to write two files:

    1. a file with the syntax of the entry and the data-fields (file extension ".is")
    2. a file describing the logical structure of the databank - the name and type of the databank and its fields, how to index field contents, links to other databanks etc. (file extension ".i")

    Both files must be written in the Icarus language and should be stored in the directory "SRSDB". The best strategy is to start with the syntax file since, as it will be shown later, it can be tested independently from the SRS system.

    Before starting with the details a few terms need to be introduced (See chapter "The Icarus language" for more information). A production is a syntax rule that during parsing must match with at least a part of the input stream. A token is a part of the input string identified as syntactic element by the parser, eg, the part that matches with a production. During the parsing process tokens can be written to a token table. To allow identification of an individual token it can be assigned a token code, which is normally a name like "id". The token table can also have a name, eg, "fields".

    The following describes incrementally the creation of the syntax file "genes.is" for the databank Genes. Essentially, the file is an Icarus program with only one statement, an assignment of a list of productions to the variable $rules.

    The productions in the list can be grouped into the one with the syntax of an entry in the flat file (production "entry"), and the ones defining the syntax of the data-fields within the entry (production "fields"). The production "entry" starts with a list of Icarus commands within curly braces. The command $Out declares that parsing of "entry" will produce an output token table. By default, the output token table will be called after the production, in this case "entry". The $Wrt command used later deposits parts of the input stream which we call tokens into an output token table. By default the parser skips line feeds, tabs and spaces ("white space") which is convenient when parsing, eg, an author list. However, in this example we need to keep the white space since it is part of the entry. As we will see later it is also of syntactical importance, eg, for parsing "SEQUENCE" data-field which spans the first line starting with "SEQUENCE" and all following lines that start with two blanks. The command "$Skip:0" turns the white space skipping off. By default actions associated to symbols, here the production "entry", are executed AFTER the nodes matched with the input stream. The pre directive ensures that the $Skip command is executed BEFORE the parsing starts.

    $rules={
    
      # the entry
      entry:     ~ {$Out pre{$Skip:0}} 
                    ('LOCUS' {$Wrt} ln {$App}
                    ('LOCUS' {$Not} ln {$App})*)?
                 ~
      ln:        ~ /[^\n]*\n/ ~
    
      # the data-fields
      fields:    ~ {$In:entry $Out} id date def cit seq  ~
      id:        ~ {$wrt:id}   'LOCUS'      ln ~
      date:      ~ {$wrt:date} 'DATE'       ln ~
      def:       ~ {$wrt:def}  'DEFINITION' ln ('  ' ln)* ~
      cit:       ~ {$wrt:cit}  'CITATION'   ln ~
      seq:       ~ {$wrt:seq}  'SEQUENCE'   ln ('  ' ln)* ~
    }
    

    The entry itself starts with the literal 'Locus' which is written into the token table "entry" by $Wrt. Of course this is not enough and we want the entire entry, so we need to continue and add more to the token we just wrote. The function $App appends the current match to the last token written. The production "ln" is a regular expression and matches the rest of the line. We continue adding lines to the one token we have in the output token table if the begin of the line does NOT match 'LOCUS' which is specified with the $Not command attached to the literal 'LOCUS'. The production "entry" gets the input directly from the flat file which means that we need to process the input line by line. This will be easier afterwards when the entire entry resides as a single string in memory.

    The other productions are used to divide the entry into its data-fields. The production "fields", like production "entry", has an $Out directive which means that parsing of "fields" will produce a token table with the name "fields". The input for parsing "fields" is not the flat file but the token in the table "entry" which is described by the command "$In:entry". The relationship of "entry" and "fields" exemplifies a very important concept in Icarus and can be used to build lazy and forced parsers as will be shown later.

    The "fields" production describes the order of all data-fields in the entry which are represented by the productions "id", "def" etc. The production "def" specifies that the first line of the field starts with "DEFINITION" but may be continued by lines beginning with two blanks. Note that all data-field productions start with the command $Wrt followed by the production name itself. If the production starts with a command or action it applies to the entire production and is, as mentioned already, executed after the matching of the production with the input. This means that the entire data-field is written to the token table "fields". The name supplied will be attached to each token so that later all tokens in the table "fields" can be distinguished by their token code.

    The general syntax of Genes is now completed and can be immediately tested. For this we need to append the following lines to "genes.is"

    $fil = $FileOpen:"SRSDEMO:genes.dat"
    $job = $JobNew:[prod:$rules]
    $JobNext:[$job file:$fil]
    while:$JobTokens:[$job name:fields]
      $JobNext:[$job file:$fil]
    

    This opens the flat file and creates a new parsing job with the productions we have defined above ($JobNew). The parser needs to iterate over all entries in "Genes" and parse them one by one. The whole process can be viewed as a series of parsing jobs for each entry. $JobNext resets the tables "entry" and "fields" for the next job. The command $JobTokens introduces the concept of lazy parsing, it asks for all tokens in the table "fields" which by default are printed to your screen together with the token codes. It is important to understand that $JobTokens 'does' all the parsing. This is what happens:

    $JobNext associates the file with the parsing job. When $JobTokens is called the file is still at the begin and nothing really happened. However, asking for the token table "fields" triggers a whole chain of events. The parser cannot return the table "fields" since it does not exist yet; in order to produce it it 'knows' it should use the production "fields" which in turn needs the token table "entry" as input. This token table does not exist either but its producer, the production "entry", can directly read from the file. Once parsing the file with production "entry" is completed the output token table can be handed over to production "fields" which produces the token table "fields" which $JobTokens finally prints it to the screen. We call this process "lazy parsing" since nothing happens unless somebody asks for an output token table. Also the parser is 'smart' enough to do the minimum amount of work required to return the desired table. You could replace the name "fields" by "entry" in the call of $JobTokens. This triggers directly the production "entry". Parsing "fields" is not necessary.

    Having defined "entry" and "fields" we can proceed to add productions that extract words for indexing from individual data-fields.

    # indexing
    word:   ~ /[a-zA-Z0-9_]+/ ~
    i_id:   ~ {$In:[fields c:id]  $out:id}  word word {$Wrt} ~
    i_date: ~ {$In:[fields c:date] $out:date 
               init{$month={JAN:1 FEB:2 MAR:3 APR:4 MAY:5 JUN:6 JUL:7 AUG:8 
                            SEP:9 OCT:10 NOV:11 DEC:12}
                   }
              } word
              /([0-9]+)-([A-Z][A-Z][A-Z])-([0-9]+)/ 
              {$Wrt:[s:$3 + $month.$2 * 10000 + $1 * 1000000]}
            ~ 
    i_def:  ~ {$In:[fields c:def] $out:def} word
              ( '('? /[^)., \n]+/ {$Wrt} /[).,\n]+/? )* ~
    i_cit:  ~ {$In:[fields c:cit] $out:cit} word word {$Wrt} ~
    

    For each of four data-fields a production is specified. On top of the parsing levels "entry" and "fields" we build another level which consumes tokens from "fields" as input. However, for extracting, eg, the entry name we need not to parse all fields, the "LOCUS" line is quite enough! So apart from the table name, the code of the desired token is specified as in "$In:[fields c:id]". Note that supplying more than one argument to an Icarus function, in this case $In, requires them to be enclosed in square brackets. Each production declares its own output token table. In this case we decided not to use the production names that start with "i_" to make them disctinct from the ones parsing the entire fields, but explicitly name them "id", "def", etc. Note that the $Wrt command is used only for the parts of the fields which should be put into the index. After adding the above to "genes.is" we can test each production by replacing the argument "fields" for $JobTokens with "id", "def", etc.

    The first symbol in all four productions is "word" which is used to skip the field name. The most complicated production is "i_date" which converts the date in a string form such as "02-FEB-1995" into the number "19950202". This conversion is necessary for allowing range queries like all entries later than the 1. January, 1995. The production shows that $Wrt can write any string into the token table which then needs to be specified as argument "s" since by default it writes the current match. The three components of the string date are parsed in one regular expression and extracted as submatches afterwards. The variables $1, $2, $3 refer to whatever matches within the respective pair of parentheses in the regular expression. Conversion of the month name to a month number uses an associative list defined in an init clause which executes the list definition only once just after the precompilation phase of the Icarus program (See the Icarus Manual for more information).

    The file "genes.is" is now almost ready but one additional command must be added that SRS needs for the indexing process. The indexer needs to know the location, or file address, of the entry in the flat file. This number can be obtained by the command $Fip (Fip stands for File PoInter). The result must be assigned to the Icarus variable $entryFip which is accessed by the indexer. The change affects only the production "entry" which is shown below again.

      # the entry
      entry:     ~ {$Out pre{$Skip:0}} 
                    ('LOCUS' {$entryFip=$Fip $Wrt} ln {$App}
                    ('LOCUS' {$Not} ln {$App})*)?
                 ~
    

    The assignment "$entryFip=$Fip" is added to the action of the first token of the entry, the name "LOCUS". The complete file "genes.is" is contained in the directory "SRSDEMO".

    The format of RefList is simpler than that of Genes and is defined in an analogue manner. The difficult parts here are the parsing of the single author names and the reference line for indexing. The production "entry" allows the flat file to start with some documentation or status information since the production starts by skipping all lines that do not contain the literal "ID" at the begin of the line.

    $rules={
      entry:     ~ {$Out}
                   ('ID' {$Not} ln)*
                   ('ID   ' {$entryFip=$Fip $Wrt} ln {$App} 
                   ('ID' {$Not} ln {$App})*)?
                 ~
    
      fields:    ~ {$In:entry $Out} f_id f_date (f_ra f_rt f_rl)*
                 ~
      id:        ~ {$Wrt:id}   'ID   ' ln   ~ 
      ra:        ~ {$Wrt:ra}  ('RA   ' ln)* ~
      rt:        ~ {$Wrt:rt}  ('RT   ' ln)* ~
      rl:        ~ {$Wrt:rl}  ('RL   ' ln)* ~
    
      # indexing
      i_id:      ~ {$In:[fields c:id] $Out:id} 
                   'ID' /[A-Z0-9_]+/ {$Wrt} ~
      i_authors: ~ {$In:[fields c:ra] $Out:au} 
                   ('RA' ( author {$Wrt} /[,;]/ )* )* ~
      i_title:   ~ {$In:[fields c:rt] $Out:tl} 
                   ('RT' /[";]/? /[^ .,"\n]+/* {$Wrt} ln )* ~
      i_ref:     ~ {$In:[fields c:rl] $Out:rf} 
                   unpubl | submit address | journal ~
      author:    ~ name /[^,;]+/ ~
      unpubl:    ~ 'RL   Unpublished' ln ~
      submit:    ~ 'RL   Submitted' '(' datenum { $Wrt:[sub s:$date] } ')' ln ~
      address:   ~ ( 'RL' ( /[^ .,\n]+/ {$Wrt:adr} /[.,]+/? )* ln )*
                 ~
      journal:   ~ 'RL' /[^0-9]+/ {$Wrt:jrn}
                   /([0-9]+):([0-9]+)-([0-9]+)\\(([0-9]+)\\)/
                   {$Wrt:[vol s:$1] $Wrt:[pg1 s:$2] $Wrt:[pg2 s:$3] $Wrt:[year s:$4] }
                 ~
      name:      ~ /[a-zA-Z0-9_'-]+/ ~ 
      num:       ~ /[0-9]+/ ~
      ln:        ~ /[^\n]*\n/ ~
    }
    
    $fil =  $fileOpen:"SRSDEMO:genes.dat"
    $job = $jobNew:[prod:$rules skip:" "]
    $jobNext:[$job file:$fil]
    while:$jobTokens:[$job name:fields print:0] {
      $jobNext:[$job file:$fil]
    } 
    

    Additional Tricks for Debugging a Syntax

    Above, a few lines of Icarus were appended to the production list for testing the syntax on the flat file. If the command $JobTokens does not print the desired result we can use a number of tricks to find out what is wrong. The main strategy is to use special Icarus variables to print out information about the parsing process. Theses variables are:

    $Ct
    the match of the current symbol
    $It
    the input stream from the current position onwards

    We can add additional $Print commands to any symbol in the syntax. By default the commands are executed after the symbol matched. The pre directive lets us print before the symbol is parsed. The example shows again the "fields" production from "genes.is" but 'embellished' with $Print statements 'around' production "id"

    fields:    ~ {$In:entry $Out} 
                 id {pre{$Print:"...before: $It\n"} $Print:"...after: $It\n"}
                 def cit ref seq  ~
    

    To compare the the diagnostics with the input from the file itself you could add $Print commands to the production "ln":

    ln:      ~ /[^\n]*\n/ {$Print:"...the line is |$Ct|\n"} ~
    

    Icarus is an interpreted language so debugging with diagnostic messages can be quite rapid since no compilation is required.

    The Structure Description

    Apart from the syntax SRS needs to have more information about the databank: the number and type of its data-fields, which tokens should be put into which type of index and, how to establish links to other databanks. This section describes the creation of the other Icarus file for each Genes and RefList. In contrast to the syntax file, it must be compiled before use and after any modification with the command

    % srssection
    

    We start with "genes.i" which consists entirely of object definitions of various predefined classes such as $library, $libformat, $field, $link. Objects can be associated with a name. In the example below the object created by $library is named "GENES_DB". The name can be used as a reference to the associated object by prefixing it with a @.

    We define first the object of type $library. It is the top level object in the hierarchically organized description of Genes and represents it to SRS. The name "GENES", defined as the unnamed attribute of $library is used by all SRS programs, e.g., in the list of active databanks created by the SRSWWW server.

    GENES_DB:$library:[GENES group:@SEQUENCE_LIBS 
      format:@GENES_FORMAT maxNameLen:10 files:{
        $file:genes
      }
    ]
    

    The three attributes .group, .format and .file reference other objects: .group points to the library group object ($libgroup) "SEQUENCE_LIBS" which is defined in the file "SRSICA:srsgen.i". Every databank must belong to a group - you can let the new databank be a member of an already existing group or of a new group which you define. .file contains a list of $file objects which name all flat files of the databank, in our case there is only the one named "genes". Note that the file name is given without directory name and file extension which will be defined later inside the objects $libloc and $filetype respectively. Attribute .format points to the object "GENES_FORMAT" of type $libformat with the format description which we define next:

    GENES_FORMAT:$libformat:[fileType:@SEQ_FILE syntax:@GENES_SYNTAX
      fields:{
        $field:[@DF_ID code:id index:id indexToken:id]    
        $field:[@DF_Description code:def index:str indexToken:def]
        $field:[@DF_Reference code:ref index:str indexToken:ref]
        $field:[@DF_Citation code:cit index:str indexToken:cit]
      }
    ]
    

    Here, .fileType and .syntax reference objects described later and .fields is a list of $field objects, one for each data-field in Genes. The unnamed attribute for $field is the pointer to the description of an abstract field type ($srsfield). Attribute .code is very special in our guided tour since it links to information in the file "genes.i"; eg, the first $field object which represents the ID or locus line has the .code "id" which means that in order to obtain the ID line from the entry we must ask for the token table "fields" and get the token with code "id". This, of course, requires for every databank that the production with the ouput list "fields" must be defined. If the contents of the data-field should be indexed attribute .index must specify one of the 5 index types "id", "str", "int", "real" and "link". Each databank must have exactly one index of type "id" where a unique name represents each entry. All other indices are optional. Attribute .indexToken is another link to the syntax and specifies the name of the token table which contains the words to be indexed for each data-field. As a reminder the production to extract the index token for the "ID" field from "genes.is" is repeated:

    i_id: ~ {$In:[fields c:id] $Out:id} word word {$Wrt} ~
    

    The production writes into the token table "id" and reads the token with the code "id" from the "fields" table. The name of the syntax file is defined in a separate object of the class $syntax:

    GENES_SYNTAX:$syntax:[file:"SRSDB:genes.is"]
    

    To allow queries and the presentation of query forms a data-field needs to have a name. the class $srsfield allows the definition of short and long names. If two fields from different databanks are very similar, eg, the creation date or the short description, the $srsfield object should be shared by both data-fields. The file "SRSDB:srsgen.i has a list of 'shareable' data-field types - more can be added. Below are the two field type definitions for the data-fields "Date" and "Description" of the databank Genes:

    DF_Date:$srsfield:[Date short:dat]
    DF_Description:$srsfield:[Description short:des]
    

    Later we can use either the long or the short names of the two data-fields to search all kinase genes that were entered into Genes after the 1.January, 1995:

    [genes-description:kinase] & [genes-dat# 1-jan-1995:]
    

    An important part of the databank structure is the description of the flat file where the databank is stored.

    SEQ_FILE:$filetype:[typename:dat maxline:100]
    

    The definition contains the file extension name "dat" which will be added to the name in $file defined above. Attribute .maxline contains the maximum line length of the flat file - be generous, it does not much to storage requirements.

    The last object in "gene.i" defines the link between Genes and Reflist.

    $link:[@GENES_DB to:@?REFLIST_DB fromField:@DF_Citation toField:@DF_ID
      token:cit]
    

    SRS links two databanks usually by comparing the contents of a certain data-field from one data-bank with those from another data-field from the other databank. In this case the name listed in the "Citation" field (.fromField) of Genes must match a name in the "ID" field (.toField) of RefList to link the Genes entry to one from RefList. The attribute .token specifies the name of the token table with the names (see also production 'i_cit' above) to be used for comparison. Note that the reference assigned to .fromField has a ? after the @. This means that the object named "REFLIST_DB" may be absent which will invalidate the link. This feature facilitates exchange of the file "genes.i". If it is used on another site that has the Genes databank but not RefList the $link definition can be left in the file.

    The file "genes.i" is now complete and can be stored in the directory "SRSDB". The file "reflist.i" can be created in an analogue manner. It does not contain a $link definition since that would duplicate the one in "genes.i".

    REFLIST_DB:$library:[REFLIST group:@SEQUENCE_LIBS 
      format:@REFLIST_FORMAT cachesize:512 maxNameLen:10 files:{
        $file:reflist
      }
    ]
    REFLIST_FORMAT:$libformat:[fileType:@SEQ_FILE syntax:@REFLIST_SYNTAX
      fields:{
        $field:[@DF_ID code:id index:id indexToken:id]    
        $field:[@DF_AUTHORS code:refaut index:str indexToken:authors]
        $field:[@DF_Title code:title index:str indexToken:title]
        $field:[@DF_Reference code:ref index:str indexToken:ref]
      }
    ]
    
    DF_Reference:$srsfield:[SeqReference short:rff group:@DF_ALL]
    DF_Citation:$srsfield:[Citation short:cit] group:@DF_ALL]
    REFLIST_SYNTAX:$syntax:[file:"SRSDB:reflist.is" level3:1]
    

    Adding Genes and Reflist to the System

    The next step is to tell SRS that the two new databanks exist and where they physically reside. Within the file "SRSDB:srsdb.i" all databanks are declared and assigned a location and a library ID. At the beginning of the file there is a long list of include statements, eg, file:"SRSDB:swissprot.i" which includes a ".i" for databanks installed. For Genes and RefList you must add

    file:"SRSDB:genes.i"
    file:"SRSDB:reflist.i"
    

    For each databank a library -ID must be defined. The library ID is a number between 1 and 255 and is used to unambigously identify the databank source within an entry-ID which SRS stores as representative of a retrieved entry. We chose the numbers 201 and 202 for Genes and RefList respectively.

    $srsdb:[ 
      libIds:{
        $libid:[201 lib:@?GENES_DB] 
        $libid:[202 lib:@?REFLIST_DB]
      } 
    ]
    

    The two $libid definitions must be inserted in the list .libIds of the $srsdb definition.

    Finally two objects of class $libloc must be inserted in the list .libs of the $site definition.

    $site:[name:unix
      libs:{
        $libloc:[@GENES_DB dir:"SRSDEMO:"]
        $libloc:[@REFLIST_DB dir:"SRSDEMO:"]
      }
    ]
    

    The directory name "SRSDEMO:" refers to the environment variable (UNIX) or logical name (VMS) defined by the command script "SRSETC:prep_srs". Names like that are always separated from the file name with a colon.

    We are now finished with the modifications to the file "srsdb.i" and can save it. To bring the changes into effect, the file "srs.i" which includes among other files "srsdb.i" must be compiled with the command

    srssection
    

    If the compiler reports errors you must correct them and run the command again.

    Testing and Debugging Phase

    Before indexing Genes and RefList we should convince ourselves that the information in the ".i" is correct and that it properly connects to the token tables defined in the ".is" files. The command

    srsbuild -info genes
    

    displays the information SRS has about Genes. After checking their correctness run

    srsbuild -d genes 
    

    This parses the databank for indexing all data-fields but instead of putting the extracted words into the index it prints them onto the screen. It is possible to run the command for individual data-fields.

    srsbuild -d genes -f 'id date'
    

    prints only the contents of the "ID" and the "Date" fields. If you find errors then either the name of the index token specified in "genes.i" or one or more syntax rules in "genes.is" can be incorrect. Again, after corrections in the "genes.i" the command "srssection" must be run whereas after corrections in "genes.is" you can immediately try again.

    Links must be built separately from the indices. The "-l" option directs srsbuild to process link information only. The command

    srsbuild -l -d genes 
    

    should display the references in the "Citation" field of Genes.

    If everything is well build all indices manually with the "-w" option added. This will inform you of any syntax errors found and of any cross-reference that could not effectively used for building a link. The following commands build all indices for both Genes and RefList and then the link between Genes and RefList. The "-c" option directs srsbuild to compress the indexes.

    srsbuild -w genes
    srsbuild -c genes
    srsbuild -w reflist
    srsbuild -c reflist
    srsbuild -w -l genes
    

    One final check you can do is to analyse the contents of individual indices. The command

    getz '[reflist-authors:*]' -lv
    

    searches all values in the "authors" index of RefList that match the wildcard '*' and prints them alphabetically sorted to the screen.

    Databank Maintenance

    Indices must be built separately for each databank which needs to be done whenever a new release of that databank is installed. For instance the EMBL nucleotide sequence library is released about every 3 months. New entries that come in between releases can be accumulated in a separate file which can be updated daily together with the indices. For both tasks which are normally handled by scripts an srsbuild command for the generation of indices could be easily added.

    However, besides the search indices, the link indices must be built as well. These are a bit more complex since they depend on two databanks. Once either partner changes a new link index is required. So when a new release of, e.g., the EMBL nucleotide databank is installed, all the link indices from or to EMBL must be recreated. To do that we need the knowledge about all links and their types.

    The good news is that there is a program that can deal with all these complications and manage the entire task of updating indices: srscheck, once called, examines the status of each installed databank and writes a script with all the commands to build new indices. By default this script is called srsupdate. It is advisable to set up a periodical job that minimally has the following three commands:

    source prep_srs
    srscheck
    srsupdate
    

    Such a job could run every hour or even on a shorter period - of course it should check if the index updating is already under way.

    Controlling Memory Requirements

    During building of a search index the part of the it must be kept in memory. Later the index will be saved into the file with the "inx" extension . If this becomes a too heavy burden to your computer system the indexing process can be configured so that it does not build indices all at once but instead in several iterations over the databank.

    First, you must modify the Icarus programs of the databanks that you cannot build in one round. Edit the attribute .maxindexsizekb of the $library object which sets an estimation size of the largest index file (with the "inx" extension) of the databank. You can obtain it by looking at the files in the SRS index directory - a rough estimate should work! The attribute .relindexsize in the $field object allows to specify relative to the global maximum size of an index. This number ranges from 0 to 1. The default value for this number is 1.

    Having specified those number you can now call srscheck with the option "-s" which specifies the maximum number of kilobytes you want to let the indexing process use for allocating the indices.

    srscheck -s 20000 
    

    srscheck takes this number and then for each databank with a total index size above 20 megabyte issues several srsbuild commands.

    Assigning Release Numbers

    Often biologists need to specify a release number if they publish results that were obtained from analysis involving a particular databank (e.g., homology search). In SRS it is possible to assign a release number, or name, to a set of indices with the command:

    srsbuild -rel "22" genes 
    

    This assigns the current release of Genes the release number "22". Unfortunately this must be done by hand for most if not all databanks since there is no commonly accepted way of specifying the current release number (e.g. in the first line of the flat file or in a special file called "release").

    Extensions for the SRSWWW Server

    If you have an SRSWWW server installed there are a few optional additions for the two databanks Genes and RefList you should consider to do:

    Add a description of a databank to be included into the databank information page.

    Tell the system how to add hypertext links into entries to be displayed.

    Adding Text to the Databank Information Page

    The databank information page in the SRSWWW server lists all indices and links for a given databank. This information is generated automatically; however, the page can also contain handwritten text which may even have hypertext links to, e.g., the site producing that databank.

    Those texts are contained in the ".it" file in $SRSDB directory, For Genes and RefList databaks there are "genes.it" and "reflist.it" files. Every ".it" file has only one Icarus list variable - $main. The $main list has several elements : .description, .more, .citation, .ftpSite, .fields, .signature and .date. The meaning of every element is obvious. The .fields element usualy is a list also and contains information about entry fields. You may take a look at "general.it" file in $SRSDB directory that contains desctiptions of most common fields in SRS.

    Specifying Hypertext Links

    The entries of Genes and RefList are linked by SRS links. For a single Genes entry the related RefList entries can be obtained with a single SRS query. Since the link to RefList is actually shown in the "Citation" field of Genes it can be converted into a hypertext link that on clicking calls the RefList entry identified by the highlighted name. SRS supports the insertion of hypertext links into entries before they are displayed to the user. First, the hypertext link to RefList needs to be declared in the file "srsdb.i" as an object of class $href.

    $href:[reflistR link:"<A HREF=wgetz?[reflist-id:%s]>%s</A>"]
    

    This defines the HTML code with wich a RefList name should be replaced and associates it with the name "reflistR". Within string assigned to .link all places where the actual RefList entry name must be inserted is indicated by a "%s". This link uses the local "wgetz" program to search and display the RefList entry with the specified "ID". It is also possible to use SRSWWW servers installed or to point to completely different systems, eg, Medline or GDB.

    SRS needs to be instructed where and how to insert the hypertext links. This information is added to the syntax in "genes.i" as a separate production

    h_cit: ~ {$In:[fields c:cit t:html]} 
             word word {$Rep:{$ParStr:reflistR $Ct $Ct}} ~ 
    

    This example introduces forced parsing. The command "$In:[field c:cit t:html]" asks for tokens with the code "cit" from the token table"fields". The additional argument "t:html" specifies that the production "h_cit" should be only called if the task "html" is active. This means that after production "fields" has successfully completed it checks if the task "html" is active and then calls the production "h_cit" which is in contrast to lazy parsing where, eg, the consumer "i_cit" activates the producer "fields".

    The $Rep command replaces the current match ("word") with the hypertext link which is specified as a list of the print format define in the $href object above followed by instances of $Ct which are the entry names to be inserted at the positions marked with "%s". $ParStr returns the string value of the global variable "reflistR" which is a way in which the the parts in SRS written in Icarus can communicate the the ones written in C.

    You can check the correctness of hypertext link insertion with the SRSWWW server or with the program getz. The following command extracts the the "Citation" field from a single entry. The second does the same but activates the task "html" with the additional "-html" on the command line

    getz '[genes-id:?] -f cit
    getz '[genes-id:?] -f cit -html 
    
    ype html public "-//IETF//DTD HTML//EN">

    Program Descriptions

    GETZ

    getz is the command line interface to the SRS query system. It offers access to all the functionality that there is in SRS albeit lengthy command lines must be typed.

    The most complicated part of a getz command is the query expression which is explained in the chapter "The SRS Query Language" on page 0. The command line options mostly influence the output you get after a successful query. With GETZ you usually make a query and you get back a set of entries in some form:

    only entry names and entry-IDs;

    the entry annotation;

    the sequence selected data-fields;

    complete features;

    features with their begin and/or end positions redefined.

    It is also possible to obtain a list of all accessible databanks or information about individual databanks.

    Command Line Summary

    getzwas originally written as a workbench for testing new functionality within SRS which means that new options will be added all the time. Some options might have been added since this documentation was written!

    INCLUDE OPTIONS getz

    Examples

    getz -libs
    

    Lists all available databanks.

    getz -info swissprot
    

    Displays information about SwissProt: the data-fields and their index types and the links. Note that for retrieval both the short and the long names can be used.

    getz '[swissprot-id:acha_human]' -t
    

    Retrieves the SwissProt entry "Acha_human" and displays the annotation part.

    getz '[embl-def:insulin&receptor]' -td -sf gcg -fil
    

    Searches all insulin receptor sequences from EMBL as defined by the definition field and displays for each entry both text and sequence part in the GCG sequence format. The entries are written into separate file with the name of the entry and a ".gcg" appended.

    getz '[medline-authors:smith,j.]' -f 'id aut ref'
    

    Searches all articles in Medline where J. Smith is an author and displays for each entry the ID line, the author names and the reference line. The example shows that both short and long data-field names can be used (Use the option "-info" to obtain the list of all data-fields available for searching).

    getz '[embl-key:*glu*]' -rep -pmin 100
    

    Searches all words containing "glu" in the keyword index of the EMBL databank. As a result of the query only the strings that represent at least 100 entries will be listed.

    getz '[prosite-def:protease]' > q.dat
    getz '@q.dat > swissprot'
    

    The first query retrieves all "protease" entries in Prosite and writes the resulting entry list into the file "q.dat". The second query accesses the list stored in "q.dat" and links the set of Prosite entries to SwissProt. Note that any file of entry names can be used as input.

    getz '[embl-org:escherichia]' -link ecdc -f def
    

    Retrieves all EMBL sequences from E.coli and prints for each entry, if available, the corresponding entry from ECDC. Prints for both entries the definition line.

    getz '[sequence-all:homeobox]' -libs 'swissprot pir trembl'
    

    Searches "homeobox" in all text fields of the databanks SwissProt, PIR and TREMBL.

    getz '[embl-features:cds]&[embl-org:yeast]' -f 'id fts' -d
    

    Retrieves all CDS features (coding sequences) from yeast as a list of entries that contain the ID line of the parent entry, the feature description and its sequence.

    getz '[embl-features:cds]&[embl-org:yeast]' -pos
    

    Returns the same set of features as a GCG compatible list of names. The begin and end positions of each CDS feature are given together with the name of the parent entry. "joins" are converted into separate lists of subentries.

    getz '[embl-fts:cds]&[embl-org:yeast]' -d \
         -fbegs 50 -fends 50 -fendsrbeg
    

    Searches all introns from yeast and extracts for each intron found the sequences 50 bp upstream and 50 bp downstream of the intron begin, that is, all exon-intron boundaries.

    WGETZ

    Command Line Summary

    INCLUDE OPTIONS wgetz

    SRSBUILD

    The program srsbuild builds the indices in SRS. It must be called separately for every databank. For building the indices it is not really necessary to invoke srsbuild directly. The program srscheck checks for each databank if indices have to be built and writes a script with the srsbuild commands necessary to get the index system up to date.

    However, there are a few occasions such as testing a newly written ODD file for a new databank or for assigning a release name/number to the set of indices of a databank where srsbuild must be used directly.

    Command Line Summary

    INCLUDE OPTIONS srsbuild

    Examples

    srsbuild swissprot 
    

    Builds all search indices (not the link indices!) for the SwissProt databank.

    srsbuild swissprot -c
    

    Compresses the indices build by above command. Compression means here not just a reduction in space but a reorganization of the index that makes its use more efficient.

    srsbuild swissprot -d -f -w 'aut tit ref'
    

    This command is very useful for testing new databank formats written in ODD. It displays all words to be indexed for the authors, title and reference fields of SwissProt. The "-w" option turns on the printing of syntax errors found by the parser. These errors may reflect errors in the databank as well as errors in the grammar written in EBNF.

    srsbuild swissprot -l -d
    

    Displays cross-references read from the databank without creating the link index.

    srsbuild swissprot -rel "23.1"
    

    Assigns a release number to a set of indices.

    srsbuild swissprot -t
    

    Sets the time stamp within the indices to the current data. This becomes necessary after the databank files have been moved to another location which changes the modification data of these files. SRS will think the indices out of date since the file date is now more recent than the indexing time stamp.

    SRSCHECK

    When maintaining indices for a large number of flat file databanks a huge number of indices has to be created and maintained. Whenever a new release of a databank supercedes an old file the indices for that databank have to be build again. But also all link indices to or from the new databank must be rebuild. This might inolve reading cross-reference information from databanks other than the new one.

    The program srscheck relieves you of having which indices have to be build at a given time. It compares the status of indices and the databank files and writes a command procedure with all srsbuild calls necessary to rebuild the indices that are out of date.

    Using srscheck the maintenance of indices can be completely automized. You can write a script to be executed daily, or even hourly that has to commands:

    srscheck
    srsupdate
    

    The latter command invokes the script produced by srscheck.

    Command Line Summary

    INCLUDE OPTIONS srscheck

    Examples

    srscheck
    srscheck -l 'swissprot embl'
    

    ICARUS

    Command Line Summary

    INCLUDE OPTIONS try

    NODD

    The ODD compiler processes all information stored in the files in the "odd" directory and produces a binary file that is not platform independent at the moment. After every change in one of the files in the "odd" directory the this section file must be produced again.

    It is normally not necessary to know more details about the command line interface since the alias

    srssection
    

    takes care of the recompilation

    Command Line Summary

    INCLUDE OPTIONS nodd

    Examples

    odd -ds srswin
    

    Compiles all files that pertain to the "srswin" collection of ODD files. This command is defined by the alias srssection /srs/etc 2:21:30 1996// /makefile.mms/1.1/Mon May 6 16:24:25 1996// /message.dat/1.8/Sun Aug 11 22:52:15 1996// /prep_srs/1.9/Mon Aug 12 22:54:20 1996// /prep_srs.com/1.1/Mon May 6 16:24:30 1996// /rcsalldiff/1.1/Mon May 6 16:24:31 1996// /readme.txt/1.1/Mon May 6 16:24:32 1996// /srsinstall.com/1.1/Mon May 6 16:24:36 1996// /srsmake/1.4/Wed May 8 00:20:54 1996// /srsmake.com/1.1/Mon May 6 16:24:39 1996// /srsmakefile/1.11/Tue Aug 13 13:52:23 1996// /srsnet.tcl/1.1/Mon May 6 16:24:42 1996// /srssection/1.2/Mon May 6 19:24:43 1996// /srsversion/1.1/Mon May 6 16:24:48 1996// cp $SRSDOC/srsman.html $SRSMAN/srsman.html cp $SRSDOC/contents.html $SRSMAN/contents.html $SRSEXE/icarus -class $SRSICA/srs.ic >! $SRSMAN/class.html $SRSEXE/icarus -ci >! $SRSMAN/icafunc.html $SRSEXE/icarus $SRSMAN/icafunc.html $SRSEXE/icarus $SRSICA/man_capi.i $SRSEXE/icarus $SRSICA/man_usage.i $SRSEXE/icarus $SRSICA/man_chap.i $SRSEXE/icarus $SRSICA/man_inx.i $SRSEXE/icarus $SRSICA/man_toc.i \rm $SRSMAN/mff_* LIB = srsexe:srs.olb CFLAGS = $(XCFLAGS) /define="SRSINCLUDE=""srswin.h""" .c.olb cc $(CFLAGS) $(mms$source) $(libr) $(librflags) $(mms$target) $(mms$target_name).obj delete $(mms$target_name).obj; .c.obj cc $(CFLAGS)/obj=$(mms$target) $(mms$source) LIBSRCS = futil.c message.c sm.c - script.c oddfncts.c oddtools.c parser.c - sdl.c sdlget.c - index.c btree.c ids.c hash.c - idx.c seq.c par.c - seqlib.c library.c entry.c - query.c set.c id.c - link.c stack.c expr.c - lst.c map.c regexp.c - arglist.c tm.c rtl.c EXES = srsexe:srsbuild.exe srsexe:getz.exe srsexe:odd.exe srsexe:srscheck.exe - srsexe:trembl.exe all : $(LIB) $(EXES) continue $(LIB) : $(LIB)($(LIBSRCS)) continue srsexe:srsbuild.exe : srsexe:srsbuild.obj srsexe:srs.lib link /execu=srsexe:srsbuild srsexe:srsbuild,$(LIB)/lib srsexe:srscheck.exe : srsexe:srscheck.obj link /execu=srsexe:srscheck srsexe:srscheck,$(LIB)/lib srsexe:odd.exe : srsexe:bs_odd.obj srsexe:bs_parser.obj - srsexe:bs_sdl.obj srsexe:bs_sdlget.obj link /execute=srsexe:odd srsexe:bs_odd,srsexe:bs_parser,- srsexe:bs_sdl,srsexe:bs_sdlget,$(LIB)/lib srsexe:getz.exe : srsexe:getz.obj srsexe:srs.lib link /execute=srsexe:getz srsexe:getz,$(LIB)/lib srsexe:trembl.exe : srsexe:trembl.obj link /execute=srsexe:trembl srsexe:trembl,$(LIB)/lib srsexe:bs_parser.obj : parser.c $(CC) $(CFLAGS) /object=srsexe:bs_parser /define=BOOTSTRAP parser srsexe:bs_sdl.obj : srssou:sdl.c $(CC) $(CFLAGS) /object=srsexe:bs_sdl /define=BOOTSTRAP sdl srsexe:bs_sdlget.obj : srssou:sdlget.c $(CC) $(CFLAGS) /object=srsexe:bs_sdlget /define=BOOTSTRAP sdlget srsexe:bs_odd.obj : srssou:odd.c $(CC) $(CFLAGS) /object=srsexe:bs_odd /define=BOOTSTRAP odd .c.obj: $(CC) $(CFLAGS) $< #$(SRSSOU)/message.h : $(SRSETC)/message.dat # msgdef # mv -f message.h $(SRSSOU)/message.h #depend $(LIB)(futil.c) : futil.c message.h msg.h futil.h sm.h $(LIB)(message.c) : message.c futil.h sm.h msg.h $(LIB)(sm.c) : sm.c message.h msg.h sm.h $(LIB)(oddfncts.c) : oddfncts.c message.h msg.h sm.h futil.h sdl.h sdl_def.h $(LIB)(oddtools.c) : oddtools.c message.h msg.h oddtools.h srsexe:bs_parser.obj $(LIB)(parser.c) : parser.c futil.h parser.h - message.h msg.h sm.h srsexe:bs_sdl.obj $(LIB)(sdl.c) : sdl.c message.h msg.h futil.h sm.h parser.h - sdlparser.h map.h sdl_def.h sdl.h srsexe:bs_sdlget.obj $(LIB)(sdlget.c) : sdlget.c futil.h message.h - msg.h sdl.h sdl_def.h $(LIB)(index.c) : index.c sm.h message.h msg.h futil.h map.h binpack.h - btree.h id.h ids.h idx.h index.h $(LIB)(btree.c) : btree.c message.h msg.h futil.h tm.h binpack.h - btree.h ids.h $(LIB)(ids.c) : ids.c message.h msg.h binpack.h futil.h tm.h id.h - ids.h set.h idx.h library.h map.h $(LIB)(idx.c) : idx.c sm.h message.h msg.h futil.h binpack.h idx.h $(LIB)(seq.c) : seq.c sm.h message.h msg.h futil.h lst.h seq.h $(LIB)(par.c) : par.c message.h msg.h futil.h lst.h par.h $(LIB)(seqlib.c) : seqlib.c message.h msg.h lst.h futil.h par.h - parser.h id.h library.h entry.h seq.h query.h seqlib.h stack.h expr.h srswin.h $(LIB)(library.c) : library.c message.h msg.h futil.h sm.h tm.h - btree.h ids.h par.h parser.h library.h srswin.h $(LIB)(entry.c) : entry.c message.h msg.h sm.h tm.h futil.h par.h - parser.h id.h library.h entry.h srswin.h $(LIB)(query.c) : query.c message.h msg.h futil.h parser.h par.h - regexp.h ids.h btree.h sm.h tm.h library.h id.h entry.h set.h link.h - query.h srswin.h $(LIB)(set.c) : set.c lst.h sm.h message.h msg.h futil.h parser.h - id.h set.h library.h srswin.h $(LIB)(id.c) : id.c message.h msg.h futil.h binpack.h id.h $(LIB)(link.c) : link.c message.h msg.h futil.h sm.h id.h set.h link.h - map.h btree.h ids.h library.h query.h srswin.h $(LIB)(stack.c) : stack.c stack.h message.h msg.h futil.h parser.h $(LIB)(expr.c) : expr.c message.h msg.h futil.h parser.h stack.h - expr.h srswin.h $(LIB)(hash.c) : hash.c hash.h $(LIB)(lst.c) : lst.c lst.h $(LIB)(map.c) : map.c message.h msg.h futil.h map.h $(LIB)(script.c) : script.c script.h $(LIB)(regexp.c) : regexp.c regexp.h regmagic.h $(LIB)(arglist.c) : arglist.c message.h msg.h futil.h parser.h par.h - srswin.h arglist.h $(LIB)(tm.c) : tm.c message.h msg.h tm.h $(LIB)(rtl.c) : rtl.c rtl.h srsexe:getz.obj : getz.c message.h msg.h futil.h parser.h seq.h par.h - arglist.h id.h set.h entry.h library.h seqlib.h query.h srswin.h - arglist.h entry.h id.h set.h ids.h library.h link.h index.h srswin.h srsexe:trembl.exe : trembl.c srsexe:srsbuild.obj : srsbuild.c message.h msg.h futil.h sm.h - parser.h seq.h par.h btree.h srsexe:srscheck.obj : srscheck.c message.h msg.h futil.h sm.h - seq.h par.h btree.h srsexe:msgdef.obj : msgdef.c msg.h srsexe:bs_odd.obj : futil.h message.h msg.h sm.h parser.h sdl.h sdl_def.h srsexe:bs_sdl.obj : message.h msg.h futil.h sm.h parser.h sdlparser.h - map.h sdl_def.h sdl.h # $RCSfile: message.dat,v $ # $Revision: 1.8 $ # $Date: 1996/08/11 22:52:15 $ # $Author: etzold $ # e__msgfail, invalid message address - rebuild system e__allocfail, insufficient memory - error during malloc "could not allocate \"%s\"\n\n" e__freefail, allocated memory could not be freed "could not free \"%s\"\n\n" e__settoobig, set size would exceed MAXIDS e__readerr, error during fgets or fread e__novalop, OR may not performed with sets of mixed type e__novaltyp, set types may not be mixed in logical expression "types of set A: %d, set B: %d\n" e__nosetfree, all sets occupied e__userabort, name entered is empty e__filnotopen, file is not opened for specified access e__filnotok, file could not be opened "\"%s\"\n\a\n " e__filopenerr, file could not be opened "\"%s\"\n\a\n " e__eof, end of file encountered e__ltoolong, line read is too long for output array e__invnodenum, invalid node number or step specification missing e__missnode, step definition contains no number of target node e__toomansym, symboltable already contains max number of symbols e__eot, end of symbol table is reached, no more symbols can be loaded e__parsefail, syntax error "Line nr. %d in file %s\n%s\n" e__bldparsefail, error during parsing "in %s, entry nr.: %d, name: \"%s\", field: %s \n%s\n\n" e__strprsfail, syntax error "at \"%s\" \n\n" e__lnotsaved, line cannot be restored - was not saved e__novalpnam, parameter name not known "Line nr. %d in file %s\nname: \"%s\"\n\n" e__novalsnam, structure name not known "Line nr. %d in file %s\nname: \"%s\"\n\n" e__invalnum, parameters value does not meet constraints "Line nr. %d in file %s\n%s\n\n" e__procfail, program execution stopped due to reported errors e__symnotuniq, symbol is already defined "symbol: \"%s\" value: %d\n\n" o__parnotok, parameter does not meet constraints "Line nr. %d in file %s\n%s\n\n" o__nossbeg, no begin of sub structure block was found "Line nr. %d in file %s\n\n" o__nossend, end of sub structure block ('}') missing "Line nr. %d in file %s\n\n" o__parismiss, required parameter is missing "before line nr. %d in file %s\nParameter name: \"%s\"\n\n" e__toomanstrct, number of structures is greater than allocated for "structure nr.: %d - memory allocated for %d structures\n\n" e__startismiss, no root node in parsing tree specified e__isnotss, structure cannot be a substructure as declared "Line nr. %d in file %s \nstructure name: %s\n\n" e__novalid, id of structure is not same as local count "Line nr. %d in file %s\nstructure: %s\n\n" e__missingchar, expected character(s) not found "Line nr. %d in file %s %s\n\n" e__unknownnterm, nonterminal symbol is not defined "\"%s\"\n\n" e__charnotknown, character is not valid in this context "Line nr. %d in file %s\ncharacter: %c\n\n" e__symnotknown, symbol is not defined "Line nr. %d in file %s\nsymbol: %s\n\n" e__novalsyminfo, symbol information is not valid "Line nr. %d in file %s \n<%s>\n\n" e__novalarg, invalid argument in command line "Argument nr. %d must be %s\n\n" e__novalcommand, invalid command line "At least %d argument expected\n\n" e__bnfbuildfail, could not process Backus-Naur expressions "before Line nr. %d\n\n" e__wrongpartyp, parameter value has incorrect type "Line nr. %d in file %s\n %s\n\n" e__novalptyp, parameter value is not allowed "Line nr. %d in file %s\nvalue: %d\n\n" e__novalopt, option value unknown "value %d for \"%s\"" e__misscolon, colon is missing "in line: \"%s\"" e__nammismatch, names are not identical "\"%s\" and \"%s\"\n\n" e__namnotuniq, name already exists in database "\"%s\"\n\n" e__novalauthor, invalid author name "in \"%s\", entry nr.: %d, author: \"%s\"\n" i__slbreportbeg, 4 parameters "\n________________________________________________________________________________\n\n" "Statistics of processing library \"%s\"\n\n" " total nr. of entries: %d\n" " nr. of new entries: %d\n" "nr. of updated entries: %d\n\n" "List of processed fields:\n" i__slbreportend, 0 parameters "\n_______________________________________________________________________________\n\n" i__inxreport, "%10s: %6d new keys, %6d key references, index-file size: %d blocks\n" i__processing, 1 parameter "...processing %s" e__eom, attempt to write beyond map section "section name: %s, size of section (bytes): %d\n" i__inxcmprss, 4 parameters "compressed file %s to %d blocks\n\n" e__nofieldend, end-of-field-mark is missing "%s\n" e__wrongfieldcnt, nr. of defined fields does not correspond with actual nr. "actual: %d, defined: %d \n" e__strtoolong, string is too long "string: %s, max. len %d\n" e__linenotexst, line is not pasted "row number: %d\n" e__invalstr, invalid string "length must be between %d and %d " e__invalnumber, invalid number "value must be between %d and %d " e__invalifn, invalid input file name "file \"%s\" could not be opened" e__invalofn, invalid output file name "file \"%s\" could not be opened" e__activesubmenu, can't delete menu with active submenu "menu-ID: %d, submenu-ID: %d; e__allwinused, no free window available e__exceedsize, attempt to write beyond end of block "name of block:%s, size: %d\n" e__eob, end of buffer was reached e__novalfield, inivalid field name "%s\n" e__novalnam, invalid name "\"%s\"\n" e__unexpectnum, number not as expected "%s, expected: %d found: %d\n" e__noinit, item not initialized "%s\n" e__strnotfou, string was not found "string %s in %s\n" e__strnotfound, string was not found "\"%s\"\n" e__novalstr, string is not valid "\"%s\"\n" e__novalfadd, invalid fadd specified "%u, max fadd: %u\n" e__novalnum, number to high or to small, not valid in this context "%d\n" e__libnotinx, library has not index "Library: \"%s\", Index: \"%s\"\n" i__wrotefile, wrote file "\"%s\"\n" i__wrotefiles, ...done "wrote total of %d files\n" e__novalpos, invalid begin/end positions "in \"%s\": %s\n" e__novalseqlen, sequence length does not meet constraints "in \"%s\" - length: %d\n" e__seqfrg, sequence fragmentary "in \"%s\": %s\n" e__seekfail, fseek failure "in file \"%s\"\n" e__crmpscfail, map section too small "requested: %d blocks, got: %d blocks\n" e__maxlinksexceed, exceeded nr. of links per node "max. nr. of links: %d\n" e__unknownnam, name is not known "\"%s\"\n" e__novallink, link cannot be performed "\"%s < %s\"\n" e__toofew, array is too small "actual size:%d, minimum size:%d\n" e__namreserved, name is reserved for internal use "\"%s\"\n" i__sdlreport, 7 parameters "\n________________________________________________________________________________\n\n" " made section files:\n" " \"%s\" with %d blocks \n" " \"%s\" with %d blocks \n\n" " from input: \"%s\"\n\n" " defined %d objects of %d different classes\n" "\n_______________________________________________________________________________\n\n" e__nopath, no linkage found "from \"%s\" to \"%s\"\n" e__ambigouslink, linkage ambiguity "from \"%s\" to \"%s\"\n" o__novalcol, invalid column number "\"%d\"\n" o__novalrow, invalid row number "\"%d\"\n" e__badarglist, wrong number of argument in function call e__namnotdef, name is not defined "%s name: \"%s\"\n" e__invaloutdir, invalid output directory name "\"%s\"\n" i__wroteseq, wrote sequence "\"%s\"\n" i__wroteseqsfile, ...done "wrote %d entries to file \"%s\"\n" e__complement, feature cannot be reverse complemented yet - have patience "\nin \"%s\": %s\n" e__novalreference, link cannot be performed "between libraries %s and %s using reference \"%s\"\n" i__lnkreport, "%10s: references to \"%s\": %d valid, %d invalid\n" e__exceedquota, exceeded quota "%s\n" e__rtlfail, RTL-function failed "function name: \"%s\"\n" e__novalsettyp, no set operation with different set types "\"%s\", \"%s\"\n" e__collidsfail, collected incorrect number of ID's "actual:%d, should be:%d"\n" e__inheritfail, invalid inheritance "\"%s\" cannot inherit \"%s\"\n" e__objnotfound, object is not defined "Line nr. %d in file %s\n Object-ID: %s\n\n" e__objnotnhrt, object is not yet inherited - change order of attributes "Line nr. %d in file %s\n Object: %s\n" e__missdefattr, attribute is missing in object class definition "Line nr. %d in file %s\n, Attribute: %s\n" o__nolibslct, no libraries were selected - use the \"Library\" option! e__symappendfail, cannot append symbol - table is still empty "Symbol: %s" e__exceedarr, too many elements "maximum number: %d\n" e__novalterm, invalid terminal symbol "Line nr. %d in file %s \"%s\"\n\n" i__mappedset, libraries "Mapped to \"%s\" -> %d entries" i__loadlinkset, "...loading link set \"%s\"" e__novalseqform, invalid format "\"%s\", expected \"%s\"" i__wroteseqlen, wrote sequence "\"%s\" with %d characters\n" o__obsoletemsg, value is not defined "Line nr. %d in file %s\nvalue: %s\n\n" e__novalpar, invalid parameter group value "%d, current number of groups: %d\n\n" e__toomanpar, maximum number of parameter groups exceeded "%d, increase mm->maxpar\n\n" i__procsubset, processing subset "first: %d, last: %d, from %d entries\n\n" e__sicinvalgroups, groups add not to total sequence number "should be: %d, group sum: %d\n\n" e__unknowncommand, unknown command "\"%c\"\b\n" i__readingname, ...reading name "nr. %d in list: %s\n" e__interrupt, aborted by Ctrl-C i__wroteset, ...done "%d entries written to set \"%s\"\n" e__sftop, location operator cannot be processed yet! "in \"%s\": %s\n" e__libnotlinked, library has no links "\b\"%s\"" e__filnotfound, file was not found or could not be opened "\"%s\"\n\n" e__filcloseerr, could not close file "\b\"%s\"\n\n " e__filwriteerr, could not write to file "File: \"%s\", Number of bytes attempted to write: %d\n\n" i__noentriesfound, no entries found e__nonounix, internal SRS-unix error "The routine \"%s\" should not be called " i__listtolib, read file of names "%d entries were successfully read from file \"%s\"\n" e__eostack, end of stack f__limitexceeded, limitexceeded "Maximum number of \"%s\" is %d\n" e__nontermexpect, name of nonterminal expected e__novalformat, line has incorrect format "<%s\n>" e__parnottype, parameter has not requested type "parameter \"%s\" is not of type \"%s\"\n" e__foundoneof, one-of operator encountered "in subentry \"%s\"\n" e__unknownoption, option is not known in this context "\"%s\"\n" e__parisdefined, parameter cannot be defined twice "\"%s\"\n" e__parnotdefined, parameter is not defined "\"%s\"\n" e__notwriteopen, file is not open for write access "\"%s\"\n" e__indexisbusy, index is busy or was never completed "\"%s\"\n" e__doesnotexistfunction, function name does not exist "\"%s\"\n" e__overflowstack, stack overflow "current stack size is \"%d\"\n" f__failedtomovelist, FATAL: failed to move list "\"%s\"\n" e__couldnotgetsequence, could not get sequence for accession number "\"%s\"\n" e__nothingtoevaluate, nothing to evaluate e__failureinslbgetx, could not get feature or sequence for entry "\"%s\"\n" e__joinillegalpar, join has illegal parameter "\"%s\"\n" e__entryparsefail, syntax error "in entry \"%s\"\n" e__illegalposition, illegal position (pos<=0) in range "in entry \"%s\"\n" e__illegalvalueonstack, illegal value (float) on stack "illegal value *%8.2f* on stack: position must be INT" e__illegalvaluesonstack, illegal values (float) on stack "illegal values *%8.2f* *%8.2f* on stack: position must be INT" e__illegaldirectioninrange, illegal direction in range "in entry \"%s\"\n" e__operatorbeforenotallowed, operator BEFORE not allowed e__operatorafternotallowed, operator AFTER not allowed e__postoohigh, position too high in range "in entry \"%s\"\n" i__entry, That was "entry \"%s\"\n" e__objectunknown, unknown object "%s \"%s\" does not exist\n" e__noseqinlist, no sequence in range list e__noresult, failed to evaluate result e__illegalrangemod, illegal modification of position prohibited e__illegalmodparam, illegal combination of modification parameters e__illegalqueryparam, illegal combination of query parameters e__noparamlist, parameter list for join missing e__negativelength, negative length of subsequence in SlbEvalSequence e__incorrectlength, incorrect length of subsequence in SlbEvalSequence e__fnctnotdefined, function associated to ODD-object is not defined "you must define %s_M before including ODD generated header file e__btreenotprep, btree is not prepared for building "could not start build phase %d\n" i__writeindex, writing index "...writing index \"%s\" with %d records" e__invalidid, invalid entry ID "record with number %d cannot be accessed\n" e__hasnotfixedrecord, index has not fixed length records "index: \"%s\"\n" e__fieldnotindex, data-field can not be indexed "\"%s\"\n" e__iscompressed, index is already compressed "\"%s\"\n" e__notcompressed, index needs to be compressed before use "\"%s\"\n" i__processingentry, "...no. %d, %s" i__wrotebtree, wrote btree file "\n...wrote index file \"%s\"\n" " size: %d kbytes, bucket size: %d, records: %d" i__wroteidfile, wrote file with id-lists "...wrote IDs file \"%s\"\n" " size: %d kbytes, IDs: %d" e__inxnotcompress, index cannot be compressed "\"%s\"\n" e__listnotfilled, list is not completed "list \"%s\", expected: %d, received: %d\n" e__buffexceeded, buffer size exceeded "buffer \"%s\", size %d\n" i__openedidpatch, opened Id patch file "...opened ID patch file generated for \"%s\"" e__dupllibid, duplicate library ID "ID \"%d\" defined for \"%s\" is already occupied by \"%s\"\n" e__novallibid, invalid library ID ...must range from 1 to 255 "ID \"%d\" defined for \"%s\"\n e__libidexst, library has already an ID "ID \"%d\" for \"%s\" with already defined ID \"%d\"\n" e__libidnotknown, library ID does not exist "no library with ID \"%d\" is defined\n" e__settoosmall, set has not enough space for IDs "attempt to copy %d IDs where only for %d is space\n" i__builtlink, wrote link file "...wrote link from \"%s\" to \"%s\"\n" " valid references: %d, invalid references: %d, \n" " total number of links: %d\n" i__checkinglib, "...checking library \"%s\"\n" e__novalentryidlen, length of ID hexnum string is not correct "length: %d, hexnum ID string: \"%s\"" e__indexnotuptodate, index not up to date "ID-index for entry \"%s\" is from %s, library from %s\n e__indexwrongversion, invalid index "can't open index \"%s\" with version %d ...should be %d" e__regerror, regexp: "%s\n" i__mustbuildinx, "======> must build indices for library \"%s\"\n" i__mustbuildlink, "------> must build link between \"%s\" and \"%s\"\n" i__diffentrynum, "library \"%s\" had previously %d, now %d entries\n" e__labelnotfound, label not found in script file "label: \"%s\" in script file \"%s\"\n" i__givinguplib, "cannot do anything about library \"%s\" now\n e__strnotinset, invalid string value "string \"%s\" is not in value set for parameter \"%s\"\n" e__numnotinset, invalid number value "number \"%d\" is not in value set for parameter \"%s\"\n" e__realnotinset, invalid real value "real \"%f\" is not in value set for parameter \"%s\"\n" e__functionnotinset, invalid function value "function is not in value set for parameter \"%s\"\n" e__charnotallowed, invalid character "character \"%c\" is not allowed within parameter \"%s\"\n" e__realnotinrange, value is not in range "%f is outside the range of %f to %f for parameter \"%s\"\n" e__checkerr, invalid value "for parameter \"%s\"\n" e__setopneedsidtype, at least one of the two sets must have ID-type "set "\%s", set "\%s\"\n" e__nolinklibselected, no library is selected for linking "use option \"%s\" first \n" i__querynegative, no entries found "query: \"%s\"\n" e__novalvar, invalid value of variable "%s is: %d, should be: %s" e__novalvar2, invalid value of variable "%s is: %s, should be: %s" e__novalvar3, invalid value of variable "%s is: %d, should be: %d" e__formatnomatch, string and format do not match, "format \"%s\" does not match string \"%s\"\n" e__relbegandend, invalid shift - cannot be relative to both begin and end "\"%s\"" e__invalidshift, invalid shift "\"%s\": begin: %d, end: %d, both relative to %s" e__shiftseqisfrag, shifted sequence is fragmentary "\"%s\"" e__seqwithneglen, cannot extract subsequence "from \"%s\", beg: %d, end %d" e__badfile, file cannot be accessed "%s\n" i__indexnotexist, "++++++> must build index \"%s\" for %s, does not exist\n" i__indexnotcompleted, "++++++> must rebuild index \"%s\" for %s, was never completed\n" i__indexnotuptodate, "++++++> must rebuild index \"%s\" for %s, is not up to date\n" i__indexnotcompressed, "++++++> must compress index \"%s\" for %s, is not compressed\n" e__rangewithundefval, begin or end position is not defined "in entry \"%s\"\n" e__argwrongnum, wrong number of arguments "label: %s, arguments sent: %d, expected: %d\n" e__argwrongtype, wrong argument type "label: %s, argument no: %d, type sent: %c, expected: %c\n" e__argsendnull, sent NULL pointer "label: %s, argument no: %d\n" e__fatal, fatal error e__unknownarg, unknown argument name "\"%s\" for command \"%s\"\n" e__nocurrentcommand, commands must be defined before their arguments "\"%s\"" e__onlyoneunnamed, only one unnamed argument allowed per command "\"%s\" for command \"%s\"" o__obsoletemess, wrong variable type "variable \"%s\" has type \"%s\", requested \"%s\" requires \"%s\"\n" e__varwrongclass, incompatible classes in assignment "variable \"%s\" has object of class \"%s\", not \"%s\"\n" e__varisreadonly, variable is readonly "variable \"%s\"\n" o__parsererror, parser error "production `%s' :\n%s ...\n%s\n pattern ``%s'' did not fit.\n" e__seqillegallength, sequence cannot be translated "begin position %d, sequence length\n" e__novalchar, invalid character "%s \"%c\" is not valid\n" e__missingarg, missing argument "insufficient number of arguments for %s\n" e__nosetorlib, unknown set or databank "\"%s\"\n" e__functionnotexist, function does not exist "\"%s\"\n" e__emptyquerystring, empty query string e__illegalbaseconv, illegal base conversion "Maximum possible base for conversion is %d, continuing...\n" e__dbnotlegal, databank name not legal in context "databank \"%s\" can not be an operator in logical operation\n" e__noviewselect, no view selected for edit "No view selected for view edit .... \n" e__querynotfound, query does not exist "query with number %d\n" e__dbhasnotfield, non existing field "data bank \"%s\" does not have field \"%s\".\n" e__icastackempty, stack is empty "stack number: %d\n" e__icaunknownattr, unknown attribute "class \"%s\" has no attribute \"%s\"\n" e__icavartype, invalid type "variable: \"%s\", type: %s, %s operation requires %s\n" e__icaenumval, unknown value "\"%s\" for attribute \"%s\"\n" e__icarequiredattr, attribute value is required "attribute \"%s\" of class \"%s\"\n" e__icaattrval, invalid attribute value %s\n" e__templNoCurrTemplate, no current template object selected e__unknownformat, unknown format option "field \"%s\" has no format \"%s\"\n" e__templEndOfHistory, invalid TemplEndWith "no more contexts on the stack\n" i__invalidentry, invalid or empty entry name "entry: \"%s\"\n" e__setnotuniqname, set with this name exists already set "\"%s\"\n" e__icainvalidselect, attempt to access an element of a NON-list variable "\"%s\" cannot be an element of \"$%s\"\n" e__icainvallistassign, attempt to assign a nonzero value to a list variable "only 0 can be assigned to \"$%s\" which deletes the list\n" e__icaopTask, prodName not def for task "prdName: \"%s\" task: \"%s\"\n" e__icaopEdit, Format has wrong numer of arguments "format: \"%s\" args: %d listSize: %d\n" e__icaopAssign, assigment has a wrong type "Variable name: \"%s\" Value name: \"%s\"\n" e__icaopRestrictLen, cursor length restriction has a wrong type "Value name: \"%s\"\n" e__icaopMove, cursor move has a wrong type "Value name: \"%s\"\n" e__icabnfGetProd, production name is not uniq "Name: \"%s\" Syntax: \"%s\"\n" e__icabnfExpression, Too many choice statments "Choice: \"%s\" Syntax: \"%s\"\n" e__icabnfProgram, Wrong syntax "Syntax: \"%s\" Action: \"%s\"\n" e__icabnfLinkBnfNet, production not defined "Production name: \"%s\"\n" e__icabnfParser, wrt expected but found "Current token \"%s\"\n" e__icarusFatal, (NULL) name for IcaGetTokenList call e__toklistFind, Wrong token list name "Name: \"%s\"\n" e__toklistReplace, toklist has ECHO style "Name: \"%s\"\n" e__toklistIsUniq, toklist has FILE style "Name: \"%s\"\n" e__parsererror1, syntax error "\n|%s|\n%s\n -- end of input expected\n" e__parsererror2, syntax error "production `%s' :\n -- no more input\n" e__parsererror3, syntax error "production `%s' :\n|%s|\n%s\n no match with |%s|\n" e__wwwnomatchingview, not all databanks represented by query are defined as root databanks in the view. "View \"%s\" is not suitable for displaying query \"%s\". e__nolibslct, no libraries were selected. e__wwwNoQueryOrEntriesSelected, no query or entries were selected "Try again!" e__wwwNoQuerySpecified, no query was specified "Try again!" e__toktablenotwritable, not possible to write to token table "\"%s\"" i__bldReadLink, processing read link "...reading links to \"%s\"" e__bldNoReadLinks, databank has no active read links "\"%s\"" f__noVarScope, variable scope does not exist "Please contact the program developer." #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSfile: prep_srs,v $ # $Revision: 1.9 $ # $Date: 1996/08/12 22:54:20 $ # $Author: etzold $ # # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # define the SRS root directory setenv SRSROOT /scrap/etzold/srs #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # find out operating system and define a symbolic name setenv OS `uname` if ($OS == "SunOS" && `uname -r` =~ [56]*) setenv OS 'Solaris' switch($OS) case Linux: set OS_SPECIFIC = linux breaksw case AIX: set OS_SPECIFIC = aix breaksw case HP-UX: set OS_SPECIFIC = hpux breaksw case IRIX: set OS_SPECIFIC = irix breaksw case IRIX64: set OS_SPECIFIC = irix64 breaksw case SunOS: set OS_SPECIFIC = sunos breaksw case Solaris: set OS_SPECIFIC = solaris breaksw case OSF1: set OS_SPECIFIC = osf breaksw case ULTRIX: set OS_SPECIFIC = ultrix breaksw default: echo "SRS does not support $OS" exit endsw #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # SRS internal directories setenv SRSDAT ${SRSROOT}/etc setenv SRSDB ${SRSROOT}/icarus/db setenv SRSICA ${SRSROOT}/icarus/util setenv SRSSOU ${SRSROOT}/src setenv SRSETC ${SRSROOT}/etc setenv SRSWWW ${SRSROOT}/www setenv SRSWWWTMP ${SRSROOT}/tmp setenv SRSDOC ${SRSROOT}/doc setenv SRSDEMO ${SRSROOT}/doc/demo setenv SRSMAN ${SRSWWW}/man setenv SRSINX ${SRSROOT}/index setenv SRSSEC ${SRSROOT}/etc/${OS_SPECIFIC} setenv SRSEXE ${SRSROOT}/bin/${OS_SPECIFIC} setenv pd /data/prosite #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # create OS specific directories if (!(-e $SRSSEC)) then echo "directory SRSSEC does not exist ... $SRSSEC is created." mkdir $SRSSEC endif if (!(-e $SRSEXE)) then echo "directory SRSEXE does not exist ...$SRSEXE is created." mkdir $SRSEXE endif if (!(-e $SRSINX)) then echo "directory SRSINX does not exist ...$SRSINX is created." mkdir $SRSINX endif #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # SRS commands # # add to the path the srs/etc and the srs/bin directory ...remove any # other srs..etc or srs..bin directory (from other versions) from the path first # set DIR = ($path) set newpath = () while ($#DIR != 0) if (!($DIR[1] =~ */srs*etc || $DIR[1] =~ */srs*bin*)) then set newpath=($newpath $DIR[1]) endif shift DIR end set path = ($newpath) set path = ($SRSEXE $SRSETC $path) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # type banner and exit echo "---------- Welcome to SRS 5.0b -------------" exit $ SAVE_VERIFY = f$VERIFY("NO") $ say := "write sys$output" $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! $ ! $File: /home/etzold/srs/src/RCS/file.c,v $ $ ! $Revision: 1.1 $ $ ! $Date: 1996/05/06 16:24:30 $ $ ! $Author: srs $ $ ! $ ! DCL script defines environment for either the SRS user or the $ ! SRS administrator (call script with parameter "admin"). $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! define the SRS root directory $ ! $ assign /nolog /tran=CONCEALED $2:[ETZOLD.SRS4_0.] SRSROOT $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! determine the mode: user or srs-administrator $ ! $ if P1 .eqs. "SRSADMIN" $ then $ ADMIN = 1 $ else $ ADMIN = 0 $ endif $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! find out operating system and define a symbolic name $ ! $ if f$getsyi ("HW_MODEL") .gt. 1024 $ then $ OS_SPECIFIC = "ALPHA" $ else $ OS_SPECIFIC = "VAX" $ endif $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! SRS internal directories $ ! $ define /nolog SRSCOM SRSROOT:[ETC] $ define /nolog SRSINX SRSROOT:[INDEX] $ define /nolog SRSSOU SRSROOT:[SRC] $ define /nolog SRSEXE SRSROOT:[BIN.'OS_SPECIFIC'] $ define /nolog SRSDAT SRSROOT:[ETC] $ define /nolog SRSHELP SRSROOT:[ETC] $ define /nolog SRSSDL SRSROOT:[ODD] $ define /nolog SRSSEC SRSROOT:[ETC] $ define /nolog SRSETC SRSROOT:[ETC] $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! create OS specific directories $ ! $ if ADMIN $ then $ if f$search ("SRSROOT:[BIN]''OS_SPECIFIC'.DIR") .eqs. "" $ then $ say "directory SRSEXE does not exist ... will be created just now" $ create /dir SRSEXE $ endif $ endif $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! SRS commands $ ! $ getz :== $SRSEXE:GETZ $ trembl :== $SRSEXE:TREMBL $ ! $ if ADMIN $ then $ odd :== $SRSEXE:odd $ etcdir = f$trnlnm ("SRSROOT") - "]" + "ETC]" $ srscheck :== $SRSEXE:srscheck $ srsu*pdate :== @SRSETC:SRSUPDATE $ srsb*uild :== $SRSEXE:SRSBUILD $ srsm*ake :== @SRSCOM:SRSMAKE $ msgdef :== $SRSEXE:MSGDEF $ srssec*tion :== "''odd' -ds srswin" $ endif $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! type banner and exit $ ! $ say "" $ say " *** Welcome to SRS, version 4.0 ***" $ if ADMIN then - say " Administration environment $ say "" $ ! Restore verification to the status quo ante $ if "''SAVE_VERIFY'" then set verify $ exit foreach i (${argv[1]}) rcsdiff $i >& /dev/null if ($status == 1) then echo $i rcsdiff $i endif end these are the release notes for SRS version 3.1 - there are almost no differences except that it runs now on VMS and OpenVMS, Irix, SunOS, Solaris, Ultrix (Hp-ux, AIX, OSF under way). The unix version has its own screen managament but no on-line help yet. Except for initial differences the installation and usage of SRS on UNIX and VMS are the same (1) compilation and installation of the programs ------------------------------------------------ VMS: $ edit [srs.etc]prep_srs.com -> define the logical SRSROOT $ @[srs.etc]prep_srs srsadmin compile all programs with the command $ srsmake if there is no "mms" installed do instead $ @srsinstall UNIX: % emacs SRSROOT/etc/prep_srs -> define the variable SRSROOT % setenv SRSADMIN % source SRSROOT/etc/prep_srs % srsmake (2) tell SRS which databanks you have and where they are -------------------------------------------------------- edit the file SRSROOT/odd/srsdb.sdl go to all definitions of "libgroup", eg #libgroup /command="SeqRelated..." /search=single /key=R /comment=" search in libraries linked to sequence libraries" /help="srs_me query lib" /libraries=@PROSITE_DB, @PROSITEDOC_DB, @BLOCKS_DB, @EPD_DB, @ECD_DB, !@TFD_DB, !@MIM_DB, @ENZYME_DB, @REBASE_DB!, !@CPGISLE_DB ...like in the example - outcomment (with '!') the libraries you don't have be careful with the ',' - if you have none of the libraries of a "libgroup" outcomment the whole thing edit the prep_srs.com or prep_srs and modify the definitions of logicals or environment variables (another possibility is to edit the srsdb.sdl file and edit the definitions of "library" and define the attribute "dir" to the correct directory name) when you have done that do srssection which you will have to repeat whenever you change something in the ODD files! and of course source prep_srs / @prep_srs (3) index the databases ----------------------- Do srsupdate which will check all your libraries - it informs you if it can't find them! either change the ODD files (srssection again) or the logical directory names ... it the directory is correct then check the file name (eg, "emrod", edit the ODD object "library" in "srsdb.sdl" or in files like "embl.sdl" to change that, ...maintenance manual!) srsupdate checks the dates of all libraries and (if existing) indices - so in order to install a new library or a new release within a working system srsupdate will generate all commands necessary to update the system. After srsupdate completed successfully there should be a file srsupdate (unix) or srsupdate.com (vms) in SRSROOT/etc execute it directly or send it to a batch queue - make sure the command "prep_srs" is defined in the latter case (note that the files srsupdate_unix.cfu srsupdate_vms.cfu serve as templates - you are free to change them if you promise not to fiddle with lines that have `##'s and `%'s. There are two postscript files in SRSROOT/etc with the user manual and the maintenance manual. Please contact me if you have problems or suggestions, Thure Etzold, August 30, 1993 EMBL, Meyerhofstrasse 1, 69012 Heidelberg etzold@embl-heidelberg.de $ say := "write sys$output" $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! $ ! $File: /home/etzold/srs/src/RCS/file.c,v $ $ ! $Revision: 1.1 $ $ ! $Date: 1996/05/06 16:24:36 $ $ ! $Author: srs $ $ ! $ ! DCL script builds the srs system $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! change the file "prep_srs.com" to assign the correct SRSROOT $ ! $ open/read RFILE [.etc]prep_srs.com $ open/write WFILE [.etc]prep_srs.com $ ! $ NEXT_LINE: $ read /end_of_file=FILE_END RFILE LINE $ if f$locate ("CONCEALED", LINE) .lt. f$length (LINE) $ then $ PDIR = f$directory () $ PWD = f$parse (PDIR,,,"DEVICE",) + PDIR $ LINE = "$ assign /nolog /tran=CONCEALED " + PWD - "]" + ".]" + " SRSROOT" $ endif $ write WFILE LINE $ goto NEXT_LINE $ FILE_END: $ close RFILE $ close WFILE $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! build the programs $ ! $ @[.etc]prep_srs srsadmin $ srsmake all $ odd -ds srswin $ exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSfile: srsmake,v $ # $Revision: 1.4 $ # $Date: 1996/05/08 00:20:54 $ # $Author: etzold $ # # Cshell script that calls make on different UNIX operating systems; # SRS-administrator environment must be defined before calling; # # script builds either all sources (call without parameters) or individual # programs (program name as parameter); # are parameters specified for calling this script will be handed over to # make # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # find out current operating system setenv OS `uname` if ($OS == "SunOS" && `uname -r` =~ [56]*) setenv OS 'Solaris' #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # define system dependend make command # ranlib not defined on all systems ...search $path set DIR = ($path) set RANLIB = touch while ($#DIR != 0) if (-x $DIR[1]'/ranlib') then set RANLIB = ranlib endif shift DIR end switch ($OS) case Linux: alias MAKE 'make "SPEZ_FLAGS=" CCOMP=cc RANLIB='$RANLIB breaksw case AIX: alias MAKE 'make "SPEZ_FLAGS= -Daix" CCOMP=cc MALLOC= LIBS=-lPW' breaksw case HP-UX: alias MAKE 'make SPEZ_FLAGS=-Dhpux' breaksw case IRIX: alias MAKE 'make "SPEZ_FLAGS=" CCOMP=cc RANLIB='$RANLIB breaksw case IRIX64: alias MAKE 'make "SPEZ_FLAGS=-Dirix64" CCOMP=cc RANLIB='$RANLIB breaksw case OSF1: alias MAKE 'gmake "SPEZ_FLAGS=-Dosf" CCOMP=cc MALLOC= RM=' #use this with the make from GNU # alias MAKE 'gmake SPEZ_FLAGS=-Dosf CCOMP=cc MALLOC= RM=' breaksw case SunOS: alias MAKE 'gmake "SPEZ_FLAGS= -Dsun" CCOMP=gcc MALLOC=' breaksw case Solaris: alias MAKE '/usr/ccs/bin/make "SPEZ_FLAGS= -Dsun" "LIBS=/usr/ccs/lib/libgen.a" "CCOMP=/opt/SUNWspro/bin/cc " MALLOC= RANLIB='$RANLIB breaksw case ULTRIX: set MFLAGS = '' alias MAKE 'make "SPEZ_FLAGS=-Dultrix" LFLAGS=-g CCOMP=gcc TO=\$%' breaksw default: echo "cannot make SRS on that operating system" endsw #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # now make SRS, if no parameter is specified build all executables. if (${#argv} == 0) then echo "at least one argument required" exit else if (${argv[1]} == 'depend') then echo "producing makefile dependencies for include files" cd ${SRSSOU}; MAKE -f ${SRSETC}/srsmakefile $* else if (${argv[1]} == 'tags') then echo "making new tags file" cd ${SRSSOU}; MAKE -f ${SRSETC}/srsmakefile $* else if (${argv[1]} == 'all') then cd ${SRSSOU}; /bin/rm *.o >& /dev/null cd ${SRSSOU}; MAKE -f ${SRSETC}/Makefile odd cd ${SRSSOU}; MAKE -f ${SRSETC}/Makefile all else echo "make for $OS with parameters: $*" cd ${SRSSOU}; MAKE -f ${SRSETC}/srsmakefile ${SRSEXE}/$* endif echo "the end" $ say := "write sys$output" $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! $ ! $File: /home/etzold/srs/src/RCS/file.c,v $ $ ! $Revision: 1.1 $ $ ! $Date: 1996/05/06 16:24:39 $ $ ! $Author: srs $ $ ! $ ! DCL script calls mms on VMS or OpenVMS; $ ! SRS-administrator environment must be defined before calling; $ ! $ ! script builds either all sources (call with parameter all) or individual $ ! programs (program name as parameter); $ ! all parameters specified for calling this script will be handed over to $ ! make $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! find out whether script is running on an alpha or not $ ! $ if f$getsyi ("ARCH_NAME") .eqs. "Alpha" $ then $ XCFLAGS = """XCFLAGS = /nomember/standard=vaxc""" $ LINK_OPT = """LINK_OPT = /lib""" $ else $ XCFLAGS = """XCFLAGS =""" $ LINK_OPT = """LINK_OPT = /opt""" $ endif $ ! $ ! $ !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ ! set default to both SRSSOU (sources) and SRSEXE (objects and images) using $ ! a logical defined for that purpose $ ! $ ! $ ! create a new library if not already there $ if f$search ("srsexe:srs.olb") .eqs. "" then library /create srsexe:srs.olb $ ! $ ! save current directory $ PDIR = f$directory () $ PWD = f$parse (PDIR,,,"DEVICE",) + PDIR $ ! $ define /nolog MAKELOC SRSSOU,SRSEXE $ set default MAKELOC $ ! $ if P1 .eqs. "ALL" $ then $ mms /descript=SRSETC:makefile /ignore /macro=('XCFLAGS', 'LINK_OPT') - 'P1' 'P2' 'P3' 'P4' 'P5' 'P6' 'P7' 'P8' $ else $ mms /descript=SRSETC:makefile /ignore /macro=('XCFLAGS', 'LINK_OPT') - SRSEXE:'P1'.exe 'P2' 'P3' 'P4' 'P5' 'P6' 'P7' 'P8' $ endif $ ! $ set def 'PWD' $ exit # # $RCSfile: srsmakefile,v $ # $Revision: 1.11 $ # $Date: 1996/08/13 13:52:23 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # .SUFFIXES : .c .o .i .m .h .a #os specific flags (specified in 'srsmake') SPEZ_FLAGS = #for compiling ALL c-files CFLAGS = -g -D__ODD -DSRSINCLUDE=\"srs5.h\" #default compiler SRSH = srs5.h CCOMP = cc CC = $(CCOMP) $(SPEZ_FLAGS) -I$(SRSEXE) MALLOC = -lmalloc BIN = $(SRSEXE)/ LIB = $(BIN)libsrs.a #variable for the target object name TO = $% #add. flags for compiling to normal objects OCFLAGS = -c -o $@ #add. flags for compiling lib members LOCFLAGS = -c -o $(TO) #LIBENTER = /usr/ccs/bin/ar rv $(LIB) $(TO) #command puts object into archive LIBENTER = ar r $(LIB) $(TO) #RANLIB = ls RANLIB = ranlib RM = /bin/rm -f $% ODD_OBJS = $(BIN)bs_odd.o \ $(BIN)oddfncts.o \ $(BIN)bs_parser.o \ $(BIN)bs_sdl.o \ $(BIN)bs_sdlget.o LOCAL_OBJS = $(BIN)local.o LIB_OBJS = $(LIB)($(BIN)arglist.o) \ $(LIB)($(BIN)lst.o) \ $(LIB)($(BIN)oddfnctsnew.o) \ $(LIB)($(BIN)sdlnew.o) \ $(LIB)($(BIN)error.o) \ $(LIB)($(BIN)toklist.o) \ $(LIB)($(BIN)cursor.o) \ $(LIB)($(BIN)icarus.o) \ $(LIB)($(BIN)icabnf.o) \ $(LIB)($(BIN)icaop.o) \ $(LIB)($(BIN)icaarg.o) \ $(LIB)($(BIN)icatask.o) \ $(LIB)($(BIN)icadebug.o) \ $(LIB)($(BIN)ica2c.o) \ $(LIB)($(BIN)bnf2c.o) \ $(LIB)($(BIN)icainit.o) \ $(LIB)($(BIN)dict.o) \ $(LIB)($(BIN)strv.o) \ $(LIB)($(BIN)def.o) \ $(LIB)($(BIN)sm.o) \ $(LIB)($(BIN)message.o) \ $(LIB)($(BIN)futil.o) \ $(LIB)($(BIN)set.o) \ $(LIB)($(BIN)unix_map.o) \ $(LIB)($(BIN)logicals.o) \ $(LIB)($(BIN)sdlget.o) \ $(LIB)($(BIN)btree.o) \ $(LIB)($(BIN)ids.o) \ $(LIB)($(BIN)idx.o)\ $(LIB)($(BIN)index.o) \ $(LIB)($(BIN)library.o) \ $(LIB)($(BIN)query.o) \ $(LIB)($(BIN)queryass.o) \ $(LIB)($(BIN)link.o) \ $(LIB)($(BIN)seq.o) \ $(LIB)($(BIN)par.o) \ $(LIB)($(BIN)variable.o) \ $(LIB)($(BIN)id.o) \ $(LIB)($(BIN)entry.o) \ $(LIB)($(BIN)regexp.o) \ $(LIB)($(BIN)templ.o) \ $(LIB)($(BIN)tm.o) \ $(LIB)($(BIN)view.o) \ $(LIB)($(BIN)hash.o) $(BIN)srs : echo MAKE FOR COMPLETE SRS SYSTEM FINISHED $(LIB) : $(LIB_OBJS) $(RANLIB) $(LIB) $(BIN)odd : $(BIN)bs_odd.o $(LIB) $(ODD_OBJS) $(CC) -o $@ $(ODD_OBJS) $(LIB) $(BIN)srsbuild : $(BIN)srsbuild.o $(LIB) $(LOCAL_OBJS) $(CC) -o $@ $(BIN)srsbuild.o $(LOCAL_OBJS) $(LIB) $(BIN)reflink : $(BIN)reflink.o $(LIB) $(CC) -o $@ $(BIN)reflink.o $(LIB) $(BIN)trembl : $(BIN)trembl.o $(LIB) $(CC) -o $@ $(BIN)trembl.o $(LIB) $(BIN)icarus : $(BIN)icarusi.o $(LIB) $(LOCAL_OBJS) $(CC) -o $@ $(BIN)icarusi.o $(LOCAL_OBJS) $(LIB) $(BIN)x : $(BIN)x.o $(LIB) $(LOCAL_OBJS) $(CC) -o $@ $(BIN)x.o $(LOCAL_OBJS) $(LIB) $(BIN)nodd : $(BIN)nodd.o $(LIB) $(LOCAL_OBJS) $(CC) -o $@ $(BIN)nodd.o $(LOCAL_OBJS) $(LIB) $(BIN)getz : $(BIN)getz.o $(LIB) $(LOCAL_OBJS) $(CC) -o $@ $(BIN)getz.o $(LOCAL_OBJS) $(LIB) $(BIN)srscheck : $(BIN)srscheck.o $(LIB) $(CC) -o $@ $(BIN)srscheck.o $(LOCAL_OBJS) $(LIB) $(BIN)msgdef : $(BIN)msgdef.o $(CC) -o $@ $(BIN)msgdef.o $(BIN)wgetz : $(BIN)wgetz.o $(BIN)srswww.o $(LIB) $(LOCAL_OBJS) $(CC) -o $@ $(BIN)srswww.o $(BIN)wgetz.o $(LOCAL_OBJS) $(LIB) cp $(BIN)wgetz $(SRSWWW)/bin/wgetz $(BIN)srspict : $(BIN)srspict.o $(BIN)gd.o $(LIB) $(CC) -o $@ $(BIN)gd.o $(BIN)srspict.o $(LIB) # some modules of the ODD compiler must be compiled with BOOTSTRAP # $(BIN)bs_parser.o : parser.c futil.h message.h msg.h sm.h $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP parser.c $(BIN)bs_sdl.o : sdl.c message.h msg.h futil.h sm.h map.h odd.h $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP sdl.c $(BIN)bs_sdlget.o : sdlget.c futil.h message.h msg.h odd.h $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP sdlget.c $(BIN)bs_odd.o : odd.c futil.h message.h msg.h sm.h odd.h $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP odd.c $(BIN)oddfncts.o : oddfncts.c message.h msg.h sm.h futil.h odd.h $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP oddfncts.c #$(BIN)oddfnctsnew.o : oddfnctsnew.c message.h msg.h sm.h futil.h odd.h # $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP oddfnctsnew.c $(BIN)oddtools.o : oddtools.c message.h msg.h oddtools.h $(CC) $(CFLAGS) $(OCFLAGS) -DBOOTSTRAP oddtools.c $(BIN)local.o : local.c message.h msg.h sm.h lst.h futil.h $(CC) $(CFLAGS) $(OCFLAGS) local.c #depend $(LIB)($(BIN)bs_sdlnew.o): sdlnew.c message.h msg.h futil.h sm.h map.h odd.h $(CC) $(CFLAGS) $(LOCFLAGS) sdlnew.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)futil.o): futil.c message.h msg.h regexp.h futil.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) futil.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)message.o): message.c msg.h futil.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) message.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)sm.o): sm.c message.h msg.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) sm.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)parser.o): parser.c message.h msg.h futil.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) parser.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)error.o): error.c error.h message.h msg.h futil.h sm.h toklist.h cursor.h ($(CC) $(CFLAGS) $(LOCFLAGS) error.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)toklist.o): toklist.c toklist.h message.h msg.h futil.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) toklist.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)cursor.o): cursor.c cursor.h message.h msg.h futil.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) cursor.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icarus.o): icarus.c icarus.h message.h msg.h regexp.h futil.h par.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) icarus.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icabnf.o): icabnf.c icarus.h icabnf.h message.h msg.h regexp.h futil.h par.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) icabnf.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icastack.o): icastack.c icastack.h message.h msg.h par.h ($(CC) $(CFLAGS) $(LOCFLAGS) icastack.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icatask.o): icatask.c icatask.h icarus.h message.h msg.h par.h ($(CC) $(CFLAGS) $(LOCFLAGS) icatask.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icadebug.o): icadebug.c icadebug.h icarus.h message.h msg.h par.h ($(CC) $(CFLAGS) $(LOCFLAGS) icadebug.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)ica2c.o): ica2c.c ica2c.h message.h msg.h variable.h strv.h ($(CC) $(CFLAGS) $(LOCFLAGS) ica2c.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)bnf2c.o): bnf2c.c message.h msg.h variable.h strv.h ($(CC) $(CFLAGS) $(LOCFLAGS) bnf2c.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icainit.o): icainit.c icarus.h ($(CC) $(CFLAGS) $(LOCFLAGS) icainit.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icaop.o): icaop.c message.h msg.h icarus.h sm.h ($(CC) $(CFLAGS) $(LOCFLAGS) icaop.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)icaarg.o): icaarg.c message.h msg.h icarus.h sm.h builtin.h ($(CC) $(CFLAGS) $(LOCFLAGS) icaarg.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)sdl.o): sdl.c message.h msg.h futil.h sm.h tm.h map.h par.h \ odd.h ($(CC) $(CFLAGS) $(LOCFLAGS) sdl.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)sdlnew.o): sdlnew.c message.h msg.h futil.h sm.h tm.h map.h par.h ($(CC) $(CFLAGS) $(LOCFLAGS) sdlnew.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)sdlget.o): sdlget.c message.h msg.h futil.h odd.h ($(CC) $(CFLAGS) $(LOCFLAGS) sdlget.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)index.o): index.c message.h msg.h sm.h futil.h binpack.h btree.h id.h ids.h hash.h \ index.h ($(CC) $(CFLAGS) $(LOCFLAGS) index.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)btree.o): btree.c message.h msg.h futil.h sm.h tm.h binpack.h btree.h ids.h ($(CC) $(CFLAGS) $(LOCFLAGS) btree.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)ids.o): ids.c message.h msg.h binpack.h futil.h tm.h id.h ids.h set.h library.h map.h ($(CC) $(CFLAGS) $(LOCFLAGS) ids.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)idx.o): idx.c message.h msg.h sm.h tm.h futil.h binpack.h idx.h ($(CC) $(CFLAGS) $(LOCFLAGS) idx.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)seq.o): seq.c message.h msg.h sm.h futil.h lst.h par.h seq.h ($(CC) $(CFLAGS) $(LOCFLAGS) seq.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)par.o): par.c message.h msg.h sm.h futil.h sdlget.h lst.h par.h $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) par.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)variable.o): variable.c message.h msg.h sm.h futil.h lst.h variable.h ($(CC) $(CFLAGS) $(LOCFLAGS) variable.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)seqlib.o): seqlib.c message.h msg.h sm.h lst.h futil.h par.h id.h library.h \ entry.h seq.h query.h seqlib.h $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) seqlib.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)seqdb.o): seqdb.c message.h msg.h sm.h lst.h futil.h icaarg.h \ icarus.h ($(CC) $(CFLAGS) $(LOCFLAGS) seqdb.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)library.o): library.c message.h msg.h futil.h sm.h tm.h btree.h sdlget.h ids.h idx.h \ par.h library.h $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) library.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)entry.o): entry.c message.h msg.h sm.h tm.h futil.h par.h icarus.h id.h set.h \ library.h entry.h $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) entry.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)queryass.o): queryass.c queryass.h message.h msg.h futil.h par.h sm.h library.h ($(CC) $(CFLAGS) $(LOCFLAGS) queryass.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)query.o): query.c message.h msg.h futil.h par.h regexp.h ids.h btree.h \ sm.h tm.h library.h id.h entry.h set.h link.h seqlib.h lst.h query.h \ $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) query.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)set.o): set.c message.h msg.h lst.h sm.h futil.h id.h set.h library.h \ $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) set.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)id.o): id.c message.h msg.h futil.h binpack.h id.h library.h ($(CC) $(CFLAGS) $(LOCFLAGS) id.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)link.o): link.c message.h msg.h futil.h sm.h id.h set.h par.h link.h map.h btree.h \ ids.h library.h binpack.h query.h $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) link.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)stack.o): stack.c message.h msg.h futil.h ($(CC) $(CFLAGS) $(LOCFLAGS) stack.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)expr.o): expr.c message.h msg.h futil.h $(SRSH) ($(CC) $(CFLAGS) $(LOCFLAGS) expr.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)lst.o): lst.c lst.h sdlget.h ($(CC) $(CFLAGS) $(LOCFLAGS) lst.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)unix_map.o): unix_map.c message.h msg.h futil.h map.h ($(CC) $(CFLAGS) $(LOCFLAGS) unix_map.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)regexp.o): regexp.c regexp.h regmagic.h message.h msg.h ($(CC) $(CFLAGS) $(LOCFLAGS) regexp.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)arglist.o): arglist.c message.h msg.h futil.h par.h $(SRSH) arglist.h ($(CC) $(CFLAGS) $(LOCFLAGS) arglist.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)logicals.o): logicals.c ($(CC) $(CFLAGS) $(LOCFLAGS) logicals.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)tm.o): tm.c message.h msg.h tm.h ($(CC) $(CFLAGS) $(LOCFLAGS) tm.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)script.o): script.c message.h msg.h futil.h sm.h lst.h ($(CC) $(CFLAGS) $(LOCFLAGS) script.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)templ.o): templ.c message.h icarus.h msg.h futil.h sm.h lst.h templ.h ($(CC) $(CFLAGS) $(LOCFLAGS) templ.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)view.o): view.c message.h sm.h futil.h library.h set.h par.h view.h ($(CC) $(CFLAGS) $(LOCFLAGS) view.c;$(LIBENTER); $(RM)) $(LIB)($(BIN)hash.o): hash.c message.h msg.h hash.h ($(CC) $(CFLAGS) $(LOCFLAGS) hash.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)oddfnctsnew.o): oddfnctsnew.c message.h msg.h sm.h futil.h odd.h ($(CC) $(CFLAGS) $(LOCFLAGS) -DBOOTSTRAP oddfnctsnew.c; $(LIBENTER); $(RM)) $(BIN)icarusi.o: icarusi.c message.h msg.h futil.h sm.h seq.h par.h arglist.h id.h \ idx.h set.h entry.h library.h seqlib.h query.h $(SRSH) $(SRSEXE)/srsenv.h $(CC) $(CFLAGS) $(OCFLAGS) icarusi.c $(BIN)x.o: x.c $(CC) $(CFLAGS) $(OCFLAGS) x.c $(BIN)nodd.o: nodd.c odd.h message.h msg.h futil.h sm.h seq.h par.h arglist.h id.h \ idx.h set.h entry.h library.h seqlib.h query.h $(SRSH) $(SRSEXE)/srsenv.h $(CC) $(CFLAGS) $(OCFLAGS) nodd.c $(BIN)tryz.o: tryz.c $(CC) $(CFLAGS) $(OCFLAGS) tryz.c $(BIN)ntry.o: ntry.c $(CC) $(CFLAGS) $(OCFLAGS) ntry.c $(BIN)getz.o: getz.c icarus.h message.h msg.h futil.h sm.h seq.h par.h arglist.h id.h \ idx.h set.h entry.h library.h seqlib.h query.h $(SRSH) $(SRSEXE)/srsenv.h $(CC) $(CFLAGS) $(OCFLAGS) getz.c $(BIN)srsbuild.o: srsbuild.c message.h msg.h futil.h sm.h seq.h seqlib.h par.h \ btree.h arglist.h entry.h id.h set.h ids.h idx.h library.h link.h index.h $(SRSH) $(CC) $(CFLAGS) $(OCFLAGS) srsbuild.c $(BIN)msgdef.o: msgdef.c msg.h futil.h $(CC) $(CFLAGS) $(OCFLAGS) msgdef.c $(LIB)($(BIN)dict.o): dict.c dict.h strv.h ($(CC) $(CFLAGS) $(LOCFLAGS) dict.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)print.o): print.c print.h strv.h ($(CC) $(CFLAGS) $(LOCFLAGS) print.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)oldlistbuf.o): oldlistbuf.c oldlistbuf.h strv.h ($(CC) $(CFLAGS) $(LOCFLAGS) oldlistbuf.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)strv.o): strv.c strv.h ($(CC) $(CFLAGS) $(LOCFLAGS) strv.c; $(LIBENTER); $(RM)) $(LIB)($(BIN)def.o): def.c def.h ($(CC) $(CFLAGS) $(LOCFLAGS) def.c; $(LIBENTER); $(RM)) $(BIN)reflink.o: reflink.c message.h msg.h futil.h library.h par.h arglist.h id.h \ set.h entry.h seq.h seqlib.h query.h lst.h $(SRSH) $(SRSEXE)/srsenv.h $(CC) $(CFLAGS) $(OCFLAGS) reflink.c $(BIN)trembl.o: trembl.c message.h msg.h futil.h library.h par.h arglist.h id.h \ set.h entry.h seq.h seqlib.h query.h lst.h $(SRSH) $(SRSEXE)/srsenv.h $(CC) $(CFLAGS) $(OCFLAGS) trembl.c $(BIN)srscheck.o: srscheck.c message.h msg.h futil.h sm.h tm.h arglist.h par.h library.h \ id.h ids.h set.h btree.h link.h $(SRSH) $(CC) $(CFLAGS) $(OCFLAGS) srscheck.c $(BIN)odd.o: odd.c message.h msg.h futil.h sm.h arglist.h par.h odd.h $(CC) $(CFLAGS) $(OCFLAGS) odd.c $(BIN)srswin.o: srswin.c message.h msg.h screen.h smglib.h smg_termio.h futil.h sm.h \ win.h seq.h par.h id.h set.h library.h entry.h query.h seqlib.h srswin2.h $(CC) $(CFLAGS) $(OCFLAGS) srswin.c $(BIN)wgetz.o: wgetz.c icarus.h message.h msg.h arglist.h sm.h tm.h futil.h library.h \ par.h id.h set.h entry.h query.h srswww.h view.h $(SRSH) $(SRSEXE)/srsenv.h $(CC) $(CFLAGS) $(OCFLAGS) wgetz.c $(BIN)srswww.o: srswww.c message.h msg.h sm.h tm.h lst.h futil.h par.h \ id.h set.h library.h btree.h idx.h entry.h link.h seq.h query.h seqlib.h \ srswww.h $(SRSH) $(CC) $(CFLAGS) $(OCFLAGS) srswww.c $(BIN)srspict.o: srspict.c srs.h gd.h $(CC) $(CFLAGS) $(OCFLAGS) srspict.c $(BIN)gd.o: gd.c gd.h $(CC) $(CFLAGS) $(OCFLAGS) gd.c # # $RCSfile: srsnet.tcl,v $ # $Revision: 1.1 $ # $Date: 1996/05/06 16:24:42 $ # $Author: srs $ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # global variable initialisation #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ set gvar(ch) 800 set gvar(cw) 600 set gvar(ZOOM) 100 set gvar(OLDSCALE) 1.0 #unix command for calling getz set getz getz set isQuery 0 #set color(0) chocolate1 #set color(1) turquoise #set color(2) darkgoldenrod1 #set color(3) plum #set color(4) palevioletred #set color(5) grey set color(0) turquoise set color(1) turquoise set color(2) turquoise set color(3) turquoise set color(4) turquoise set color(5) turquoise wm title . "SRS-Network" wm maxsize . 1200 1200 wm minsize . 100 100 wm iconname . "SRS-Network" #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # widgets and layout #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # buttons on right hand side frame .f2 -relief ridge scale .f2.zoom -label "Zoom" -orient horiz -relief raised -length 150 -from 50 -to 250 \ -command "resize .f1.c" .f2.zoom set 100 button .f2.quit -text "QUIT" -relief raised \ -command exit button .f2.savedbs -text "SAVE" -relief raised -command "SaveDBs" button .f2.loaddbs -text "LOAD" -relief raised -command "LoadDBs" pack .f2.zoom -side top -padx 5 -pady 2 -ipady 5 pack .f2.loaddbs -side top -padx 5 -pady 2 -ipady 5 -fill x pack .f2.savedbs -side top -padx 5 -pady 2 -ipady 5 -fill x pack .f2.quit -side top -padx 5 -pady 2 -ipady 5 -fill x # # canvas with scroll bars # frame .f1 -relief ridge scrollbar .f1.scx -width 15 -orient horiz -relief flat \ -command ".f1.c xview" frame .f1.f1 -relief flat frame .f1.f1.spacer -height 15.p -width 15.p scrollbar .f1.f1.scy -width 15 -orient verti -relief flat -command ".f1.c yview" pack .f1.f1.spacer -side bottom -expand n pack .f1.f1.scy -side top -expand yes -fill both pack .f1.f1 -side right -expand n -fill both pack .f1.scx -side bottom -expand n -fill x canvas .f1.c -w 200 -height 200 -bg bisque1 -yscrollc ".f1.f1.scy set" -xscrollc ".f1.scx set" pack .f1.c -side left -fill both -expand yes pack .f1 -side right -fill both -expand yes pack .f2 -side left -fill y #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # list of procedures #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ proc resize { c z } { global gvar isMustScaleCoord set sreg "0 0 [expr $z*$gvar(cw)/100.0] [expr $z*$gvar(ch)/100.0]" $c configure -scrollregion $sreg set sc [expr 1.0*$z/$gvar(ZOOM)] set gvar(ZOOM) $z set gvar(SCALE) [expr $z/100.0] $c scale all 0 0 $sc $sc set isMustScaleCoord 1 } proc SaveDBs {} { global nodeX nodeY DBNodeName allDBs if (![info exists allDBs]) { error "Nothing to save!" return } set stat "[catch {set file [open "srsnet.dat" w]} msg]" if {$stat} { puts "$msg" return } foreach node [.f1.c find withtag node] { puts $file "coord: $DBNodeName($node) $nodeX($node) $nodeY($node)" } close $file } proc ReadDBCoord {} { global nodeX nodeY DBname DBnodeX DBnodeY set stat "[catch {set file [open "srsnet.dat" r]} msg]" if {$stat} { puts "$msg" return } while {[gets $file line] >= 0} { if [regexp {coord: +([^ ]+) +([0-9]+) +([0-9]+)} \ $line match libName x y ] { set DBnodeX($libName) $x set DBnodeY($libName) $y } } close $file } proc LoadDBs {} { global nodeX nodeY edgeFirst edgeSecond isActive DB DBname DBcolor getz \ DBnodeX DBnodeY node curX curY color allDBs fields DBNodeName set yy 10 set xx 40 ReadDBCoord set f1 [open "|$getz -si" r] set groups {} while {[gets $f1 line] >= 0} { if [regexp {lib: ([^ ,]+), .*group: ([^ ,]+)} \ $line match libName group ] { set index [lsearch $groups $group] if {$index == -1} { lappend groups $group } set index [lsearch $groups $group] if {[info exists DBnodeX($libName)]} { set tmpx $DBnodeX($libName) set tmpy $DBnodeY($libName) } else { set tmpx $xx set tmpy $yy } set tmp [string tolower $libName] button .f1.c.$tmp -text "$libName" -relief raised -height 1\ -bg $color($index) \ -highlightcolor white -highlightbackground bisque1 set new [.f1.c create window $tmpx $tmpy -window .f1.c.$tmp \ -tags node ] # # key bindings for each button in the graph ...don't know how to do one # binding for all # bind .f1.c.$tmp { global curX curY set curX %X set curY %Y } bind .f1.c.$tmp { global node moveNode $node(%W) [expr (%X-$curX)] [expr (%Y-$curY)] set curX %X set curY %Y } set node(.f1.c.$tmp) $new set DB($libName) $new set DBcolor(.f1.c.$tmp) $color($index) set isActive($libName) 0 set nodeX($new) $tmpx set nodeY($new) $tmpy set edgeFirst($new) {} set edgeSecond($new) {} set DBname(.f1.c.$tmp) $libName set DBNodeName($new) $libName lappend allDBs $libName if {$tmpy == $yy} { set yy [expr $yy + 20] } } elseif [regexp {field: +([^ ,]+), type: +(index|num|real|id)} \ $line match fieldName ] { lappend fields($libName) $fieldName } elseif [regexp {link: +([^ ]+) +([^ ]+)} $line \ match libName1 libName2] { mkEdge $DB($libName1) $DB($libName2) } } } proc mkNode {x y} { global nodeX nodeY edgeFirst edgeSecond isActive set new [.f1.c create text [expr $x] [expr $y] -text "hallo" \ -fill black -tags node ] set isActive($new) 0 set nodeX($new) $x set nodeY($new) $y set edgeFirst($new) {} set edgeSecond($new) {} } proc mkEdge {first second} { global nodeX nodeY edgeFirst edgeSecond set edge [.f1.c create line $nodeX($first) $nodeY($first) \ $nodeX($second) $nodeY($second) \ -width 1 -fill blue1] .f1.c lower $edge lappend edgeFirst($first) $edge lappend edgeSecond($second) $edge } focus .f1.c proc moveNode {node xDist yDist} { global isMustScaleCoord nodeX nodeY edgeFirst edgeSecond gvar .f1.c move $node $xDist $yDist incr nodeX($node) $xDist incr nodeY($node) $yDist if {$isMustScaleCoord == 1} { set isMustScaleCoord 0 foreach node [.f1.c find withtag node] { set nodeX($node) [expr int ($nodeX($node) * \ $gvar(SCALE) / $gvar(OLDSCALE))] set nodeY($node) [expr int ($nodeY($node) * \ $gvar(SCALE) / $gvar(OLDSCALE))] } set gvar(OLDSCALE) $gvar(SCALE) } foreach edge $edgeFirst($node) { .f1.c coords $edge \ $nodeX($node) $nodeY($node) \ [lindex [.f1.c coords $edge] 2] \ [lindex [.f1.c coords $edge] 3] } foreach edge $edgeSecond($node) { .f1.c coords $edge [lindex [.f1.c coords $edge] 0] \ [lindex [.f1.c coords $edge] 1] \ $nodeX($node) $nodeY($node) } } #defines an 'alias' for the old srssection command nodd -s $SRSICA/srs.ic $SRSICA/srs.i if (${#argv} == 0) then echo "name of program required" exit endif if ($?SRSEXE) then strings $SRSEXE/${argv[1]} | grep '$Id' | sed 's/.*\(\$Id.* \$\)/\1/' else strings `which ${argv[1]}` | grep '$Id' | sed 's/.*\(\$Id.* \$\)/\1/' endif exit r /srs/icarus /srs/icarus/db 5 1996// /blast.is/1.3/Wed Jul 24 22:19:15 1996// /cabi.is/1.1/Tue May 28 08:59:59 1996// /ecdc.is/1.1/Mon May 6 15:31:34 1996// /embl.i/1.2/Fri May 24 14:05:59 1996// /embl.is/1.1/Fri May 24 14:08:52 1996// /embl.it/1.2/Tue Jul 30 10:26:48 1996// /emp.i/1.6/Mon Aug 12 20:20:42 1996// /emp.is/1.6/Fri Jul 26 21:22:18 1996// /enzyme.i/1.5/Mon Aug 12 19:04:40 1996// /enzyme.is/1.4/Wed Jul 24 22:19:17 1996// /enzyme.it/1.2/Tue Jul 30 10:26:48 1996// /epd.i/1.3/Wed Jul 24 22:19:17 1996// /epd.is/1.3/Sun Aug 11 22:51:51 1996// /epd.it/1.1/Tue Jul 30 10:26:50 1996// /fasta.i/1.2/Fri May 24 14:06:00 1996// /fasta.is/1.3/Wed Jul 24 22:19:18 1996// /flygene.is/1.1/Tue May 28 09:00:00 1996// /fssp.is/1.1/Tue May 28 09:00:00 1996// /genbank.i/1.4/Sun Aug 11 22:51:52 1996// /genbank.is/1.4/Sun Aug 11 22:51:52 1996// /genbank.it/1.3/Tue Jul 30 10:26:50 1996// /general.it/1.3/Tue Jul 30 10:26:51 1996// /mpw.i/1.6/Mon Aug 12 19:04:40 1996// /mpw.is/1.5/Wed Jul 24 22:19:20 1996// /pdb.i/1.1/Wed Jul 24 23:01:39 1996// /pdb.is/1.2/Wed Jul 24 22:19:20 1996// /pdb.it/1.2/Tue Jul 30 10:26:52 1996// /pdbfinder.i/1.5/Wed Jul 24 22:19:21 1996// /pdbfinder.is/1.4/Wed Jul 24 22:19:21 1996// /pdbfinder.it/1.3/Tue Jul 30 10:26:53 1996// /pmd.is/1.1/Mon May 6 15:31:45 1996// /primers.i/1.3/Wed Jul 24 22:19:22 1996// /primers.is/1.1/Mon May 6 15:31:47 1996// /prosite.i/1.6/Sun Aug 11 22:51:53 1996// /prosite.is/1.6/Fri Jul 26 21:22:30 1996// /prosite.it/1.2/Tue Jul 30 10:26:54 1996// /prositedoc.i/1.4/Sun Aug 11 22:51:53 1996// /prositedoc.is/1.4/Sun Aug 11 22:51:54 1996// /prositedoc.it/1.2/Tue Jul 30 10:26:55 1996// /reptilia.i/1.4/Sun Aug 11 22:51:54 1996// /reptilia.is/1.2/Wed Jul 24 22:19:24 1996// /srsdb.i/1.14/Sun Aug 11 23:05:38 1996// /swissprot.i/1.6/Sun Aug 11 22:51:55 1996// /swissprot.is/1.6/Sun Aug 11 22:51:56 1996// /swissprot.it/1.2/Tue Jul 30 10:26:56 1996// /taxonomy.i/1.1/Sun Aug 11 23:03:18 1996// /taxonomy.is/1.1/Sun Aug 11 23:03:19 1996// /tfcell.i/1.3/Wed Jul 24 22:19:27 1996// /tfcell.is/1.1/Mon May 6 15:31:53 1996// /tfcell.it/1.2/Tue Jul 30 10:26:56 1996// /tfclass.i/1.3/Wed Jul 24 22:19:27 1996// /tfclass.is/1.1/Mon May 6 15:31:55 1996// /tfclass.it/1.2/Tue Jul 30 10:26:57 1996// /tffactor.i/1.5/Sun Aug 11 22:51:56 1996// /tffactor.is/1.3/Sun Aug 11 22:51:57 1996// /tffactor.it/1.2/Tue Jul 30 10:26:58 1996// /tfmatrix.i/1.4/Sun Aug 11 22:51:57 1996// /tfmatrix.is/1.3/Tue Aug 13 12:21:31 1996// /tfmatrix.it/1.2/Tue Jul 30 10:26:58 1996// /tfsite.i/1.3/Wed Jul 24 22:19:28 1996// /tfsite.is/1.1/Mon May 6 15:31:59 1996// /tfsite.it/1.2/Tue Jul 30 10:26:59 1996// /ypd.i/1.4/Sun Aug 11 22:51:58 1996// /ypd.is/1.3/Wed Jul 24 22:19:29 1996// # $RCSfile: blast.i,v $ # $Revision: 1.3 $ # $Date: 1996/07/24 22:19:15 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BLAST_DB:$library:[BLAST group:@HOMOLSEARCH_LIBS comment:"" format:@BLAST_FORMAT maxNameLen:40 ifiles:{"blast.i" "blast.is"} type:user files:{ $file:tmp } ] BLAST_FORMAT:$libformat:[fileType:@BLAST_FILE syntax:@BLAST_SYNTAX fields:{ $field:[@DF_ID code:title index:id indexToken:id] $field:[@DF_TopMatch code:tmatch tableToken:t_tmatch tableFormat:left] $field:[@DF_TopScore code:tscore1 index:int indexToken:score tableToken:score tableFormat:right] $field:[@DF_PercIdent code:tscore2 index:int indexToken:percIdent tableToken:percIdent tableFormat:right] $field:[@DF_QueryBeg code:tmatch index:int indexToken:queryBeg tableToken:queryBeg tableFormat:right] $field:[@DF_QueryEnd code:tmatch index:int indexToken:queryEnd tableToken:queryEnd tableFormat:right] $field:[@DF_MatchLen code:tmatch index:int indexToken:matchLen tableToken:matchLen tableFormat:right] $field:[@DF_LINK index:link code:link indexToken:link] } ] DF_TopMatch:$srsfield:[TopMatch short:tma] DF_TopScore:$srsfield:[TopScore short:tsc] DF_PercIdent:$srsfield:[PercentIdentity short:pid] DF_QueryBeg:$srsfield:[QueryMatchBeginPos short:qbp] DF_QueryEnd:$srsfield:[QueryMatchEndPos short:qep] DF_MatchLen:$srsfield:[MatchLength short:mtl] BLAST_SYNTAX:$syntax:[file:"SRSDB:blast.is" ignore:" "] BLAST_FILE:$filetype:[typename:blast maxline:100] $link:[@BLAST_DB to:@?SWISSPROT_DB token:'link|swiss' toField:@DF_Accession] # $RCSfile: blast.is,v $ # $Revision: 1.3 $ # $Date: 1996/07/24 22:19:15 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $rules={ entry: ~ {$In:[file:text] init{$count=0} $Out $count+=1} ('>' {$Not} ln)* '>' {pre {$Skip:0 $entryFip=$Fip} $Wrt} appLn ('>' {$Not} appLn)* ~ # data fields fields: ~ {$In:entry $Out $Skip:1} title length tscores1 tscores2 tmatch (scores1 scores2 match)* ~ title: ~ {$Wrt:title} '>' ln (/ *Length/ {$Not} ln)* ~ length: ~ {$Wrt:length} / *Length/ ln ln ~ tscores1: ~ {$Wrt:tscore1} / *Score/ ln ~ tscores2: ~ {$Wrt:tscore2} / *Identities/ ln ln ~ tmatch: ~ {$Wrt:tmatch} ('Query' ln ln ln ln)* ~ scores1: ~ {$Wrt:score1} / *Score / ln ~ scores2: ~ {$Wrt:score2} / *Identities/ ln ln ~ match: ~ {$Wrt:match} ('Query' ln ln ln ln)* ~ # indexing id: ~ {$In:[fields c:title] $Out} />([a-zA-Z]+)\\|([a-zA-Z0-9]+)/ {$Wrt:[s:"$count\_$1\_$2"]} ~ score: ~ {$In:[fields c:tscore1] $Out} /.*Score = ([0-9]+)/{$Wrt:[s:$1]} ~ percIdent:~ {$In:[fields c:tscore2] $Out} /.*Identities[^a-z]*\\(([0-9]+)%/ {$Wrt:[s:$1]} ~ queryBeg: ~ {$In:[fields c:tmatch] $Out} /Query: *([0-9]+)/ {$b=$1 $Wrt:[s:$1]} ~ queryEnd: ~ {$In:[fields c:tmatch] $Out} /.*Query: *[0-9]+[^\n0-9]*([0-9]+)/ {$e=$1 $Wrt:[s:$1]} ~ matchLen: ~ {$Out pre{$Request:queryEnd $Request:queryBeg $Wrt:[s:($e-$b+1)]}} /./ ~ link: ~ {$Out $In:[fields c:title]} '>' ('swiss|' name {$Wrt:swiss})? ~ # table display t_tmatch: ~ {$Out $In:[fields c:tmatch]} /.+/ {$Wrt:[s:""]} ~ # other appLn: ~ /[^\n]*\n/ {$App} ~ ln: ~ /[^\n]*\n/ ~ name: ~ /[a-zA-Z][a-zA-Z0-9]+/~ } init = * <$hb := "* "; $he := " * "; $fe := "
    "; com:s2a f:IcaFunny2Ascii; arg:funny unnamed:y; return:ascii>; entry = '

    ' ln { // ln }; # # the fields # fields = dt cd sn jn aj cp yr vl no pp la it au aa cc ti [ab] ls de pb lp ; dt = '
    ' /(.+)<\/DT>/ ln; cd = '' /(.+)<\/CD>/ ln; sn = '' /(.+)<\/SN>/ ln; jn = '' /(.+)<\/JN>/ ln; aj = '' /(.+)<\/AJ>/ ln; cp = '' /(.+)<\/CP>/ ln; yr = '' /(.+)<\/YR>/ ln; vl = '' /(.+)<\/VL>/ ln; no = '' /(.+)<\/NO>/ ln; pp = '' /(.+)<\/PP>/ ln; la = '' /(.+)<\/LA>/ ln; it = '' /(.+)<\/IT>/ ln; au = '' * auLn '' * ln; aa = '' * auAddr '' * ln; cc = '' /(.+)<\/CC>/ ln; ti = '' * tiLn '' * ln; ab = '' * abLn '' * ln; ls = '' /(.+)<\/LS>/ ln; de = '' /(.+)<\/DE>/ ln; pb = '' /(.+)<\/PB>/ ln; lp = '' /(.+)<\/LP>/ ln; nr = '' /(.+)<\/NR>/ ; # # contents of fields # ln = /[^$]*$?/; auLn = { '' repLn } [/$/] ; auAddr = { '' repLn } [/$/] ; abLn = { '' repLn } [/$/] ; tiLn = { '' repLn } [/$/] ; repLn = ( '' "> | '' "> | '' | '' | '' | '' | /&[a-zA-Z0-9]+;/ | /[^$]/ ). $rules={ entry: ~ {init{$count=0} $out:entry $count=$count+1} ('ID' {$not} ln)* ('ID ' {pre {$entryFip = $fip} $wrt} ln {$app} ('//' {$not} ln {$app})* '//' {$app $fip:on})? ~ # fields fields: ~ {$in:entry $out} f_id f_xx f_acc f_xx f_def f_xx f_key? f_xx f_org f_xx f_rl f_xx f_dr f_xx f_func f_map f_links ~ f_id: ~ {$wrt:id} 'ID ' ln ~ f_xx: ~ ('XX' ln)* ~ f_acc: ~ {$wrt:acc} ('AC ' ln)* ~ f_date: ~ {$wrt:date} ('DT ' ln)* ~ f_def: ~ {$wrt:def} ('DE ' ln)* ~ f_key: ~ {$wrt:key} ('KW ' ln)+ ~ f_org: ~ {$wrt:org} ('OS ' ln)* ~ f_rl: ~ {$wrt:rl} ('RL ' ln)* ~ f_dr: ~ {$wrt:dr} ('DR ' ln)* ~ f_func: ~ {$wrt:func} ('FT FUNCTION' ln)* ~ f_map: ~ {$wrt:map} ('FT MAP' ln)* ~ f_links: ~ {$wrt:link} ('FT ' /(CDS|CONTIG)/ ln)* ~ # indexing id: ~ {$in:[fields c:id] $out:id} 'ID ' (/[A-Za-z0-9_][A-Za-z0-9_() -]+/ {$wrt} | ',' | /[^a-zA-Z0-9_ -]+/ )* ~ acc: ~ {$in:[fields c:acc] $out:acc} 'AC' /[A-Z0-9_]+/? {$wrt} ~ def: ~ {$in:[fields c:def] $out} ( 'DE' ( /[A-Za-z0-9_]+/ {$wrt} | /[^A-Za-z0-9_]+/ )* )* ~ org: ~ {$in:[fields c:org] $out:org} 'OS' /[A-Za-z0-9_ ]+/ {$wrt} ~ key: ~ {$in:[fields c:key] $out:key} ('KW' /[A-Za-z0-9_ -]+/? {$wrt} ln)* ~ date: ~ {$in:[fields c:date] $out} 'DT' datenum {$wrt:[s:$date c:cre]} '(CREATED);' datenum {$wrt:[s:$date c:dupd]} '(DATA UPDATE);' datenum {$wrt:[s:$date c:iupd]} '(INFO UPDATE).' ~ allpos: ~ {$in:[fields c:rule] $out} (/.*POSITIVE=([0-9]+)/ {$wrt:[s:$1]})? ~ datenum: ~ {init {$month={JAN:1 FEB:2 MAR:3 APR:4 MAY:5 JUN:6 JUL:7 AUG:8 SEP:9 OCT:10 NOV:11 DEC:12}}} /([A-Z][A-Z][A-Z])-([0-9]+)/ {$date=$month.$1 * 100 + $2 * 10000} ~ links: ~ {$in:[fields c:link] $out} (/DR/ (name {$wrt:swiss} ',' name ',' /[A-Z?]/ ';')* ln)* (/3D/ (name {$wrt:pdb} (';'|'.'))* ln)* /DO/ name {$wrt:pd} ~ # table display t_date: ~ {$in:[fields c:date] $out} /.* ([A-Z0-9-]+) *CREATED/ {$wrt:[s:$1]} ~ # html display hl_links:~ {$in:[fields c:dr t:hl]} ('DR' 'EMBL;' name {$rep:{$parStr:emblR $ct $ct}} ln)* ~ # other name: ~ /[a-zA-Z0-9_]+/ ~ ln: ~ /[^\n]*\n/ ~ } $fil = $fileOpen:"/data/ecdc/div.dat" $job = $jobNew:[prod:$rules skip:" "] $jobNext:[$job file:$fil] #for:{1 $jobTokens:[$job name:fields code:dr task:hl print:1] 1} { $print:"-------->entry\n" for:{1 $jobTokens:[$job name:fields code:id print:1] 1} { # $jobTokens:[$job name:acc print:1] # $jobTokens:[$job name:def print:1] $jobTokens:[$job name:fields print:1] # $jobTokens:[$job name:key print:1] # $jobTokens:[$job name:org print:1] # $jobTokens:[$job name:fields code:dr task:hl print:1] $jobEnd:$job $jobNext:[$job file:$fil] $print:"-------->entry\n" } # # $RCSfile: embl.i,v $ # $Revision: 1.2 $ # $Date: 1996/05/24 14:05:59 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EMBL_DB:$library:[EMBL group:@SEQUENCE_LIBS comment:" Nucleotide Sequence Database from EBML" format:@EMBL_FORMAT cachesize:2048 maxNameLen:30 files:{ $file:est1 $file:est2 $file:est3 $file:est4 $file:patent $file:fun $file:inv $file:mam $file:org $file:phg $file:pln $file:pri $file:pro $file:rod $file:syn $file:unc $file:vrl $file:vrt $file:sts } ] EMBL_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@EMBL_SYNTAX subentries:@Seqfeature_Subentry fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_ACCNO code:acc index:str indexToken:acc tableToken:acc tableFormat:left] $field:[@DF_DESCRIPTION code:def index:str indexToken:def tableToken:t_def tableFormat:left] $field:[@DF_AUTHORS code:refaut index:str indexToken:authors tableToken:authors tableFormat:left] $field:[@DF_DATE code:date index:int indexToken:date tableToken:date tableFormat:center] $field:[@DF_SEQLENGTH code:seqTitle index:int indexToken:seqlength tableToken:seqlength tableFormat:right] $field:[@DF_FEATURES code:features index:str indexToken:features indexId:@SUBENTRY_ID] $field:[@DF_LINK code:xref] } ] DF_FEATLEN:$srsfield:[featureLength short:ftl] EMBL_SYNTAX:$syntax:[file:"SRSDB:embl.is" level3:1 ignore:" \n\t"] $link:[@EMBL_DB to:@?SWISSPROT_DB toField:@DF_ACCNO] $link:[@EMBL_DB to:@?GENBANK_DB toField:@DF_ACCNO] $link:[@EMBL_DB to:@?PIR_DB toField:@DF_ACCNO] $link:[@EMBL_DB to:@?PDB_DB toField:@DF_ID] $link:[@EMBL_DB to:@?REBASE_DB toField:@DF_ID] $link:[@EMBL_DB to:@?OMIM_DB toField:@DF_ID] $link:[@EMBL_DB to:@?MEDLINE_DB toField:@DF_ID] Seqfeature_Subentry:$subentry:[idType:@SUBENTRY_ID fields:{ $field:@DF_DESCRIPTION $field:@DF_ORGANISM $field:[@DF_FEATURES token:'feature|body'] $field:[@DF_PROTSEQUENCE token:ftSeq] } ] # declaration of functions # functions = * ; # >; # com:seqCompl f:SeqOpCompl; # com:seqAcc f:SeqOpAcc; # com:seqRepl f:SeqOpRepl; # com:seqJoinEdit f:SeqOpJoinEdit; # arg:s1;arg:s2;arg:b1;arg:b2; # com:seqCleanup f:SeqOpCleanup; arg:isErr unnamed:y>; entry = {'ID' ln } 'ID ' ln { '//' ln } '//' ; # # the data-fields # fields = f_id { f_acc | f_ft | f_seq | ln} ; f_id = 'ID ' ln; f_acc = 'AC ' ln {'AC ' ln}; f_ft = 'FT CDS' ln { 'FT ' ln }; f_seq = 'SQ ' ln ln { ln }; ln = /[^$]*$/; # # the feature location # sequence = *<$entryseq=seqNew> { /[a-zA-Z ]+/ ln }; cds = 'FT ' 'CDS' ln { 'FT ' ln }; location = *<$inJoin=0; $inCompl=0> join | order | replace | seq | range ; join = 'join' <$inJoin=1>'(' seq { ',' seq } ')' ; order = 'order' '(' seq { ',' seq } ')'; seq = complement | fragment | join; complement = 'complement' <$inCompl=1> '(' (join | fragment) ')' ; replace = 'replace' '(' * <$noBegin=0;$noEnd=0> begin end ',' /"([A-Z]+)"/ ')'; fragment = range; range = * <$noBegin=0;$noEnd=0> ( /[A-Z][A-Z0-9]+/ ':' | * ) begin ( end | cut); begin = [ '<' <$noBegin=1> ] pos <$begin=$ct>; end = '.' '.' pos <$end=$ct> [ '>' <$noEnd=1> ]; cut = '^' pos; oneofrange = 'one-of' '(' range {',' range } ')'; oneofpos = 'one-of' '(' num {',' num } ')'; pos = oneofpos | num; num = /[0-9]+/. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSfile: embl.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:48 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The European Bioinformatics Institute (EBI) maintains and distributes |the EMBL Nucleotide Sequence database, Europe's primary nucleotide |sequence data resource. The EBI also maintains and distributes the |SWISS-PROT Protein Sequence database, in collaboration with Amos |Bairoch of the University of Geneva. Over fifty additional specialist |molecular biology databases, as well as software and documentation |of interest to molecular biologists are available. The EBI network |services include database searching and sequence similarity searching |facilities. |

    more: |

    |More on Swissprot |

    citation: | Reference: |Patricia Rodriguez-Tom , Peter J. Stoehr , Graham N. Cameron and Tomas P. |Flores, "The European Bioinformatics Institute (EBI) databases", |Nucleic Acids Res. |24:(6-13), 1996 ftpSite:'' date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: emp.i,v $ # $Revision: 1.6 $ # $Date: 1996/08/12 20:20:42 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EMP_DB:$library:[EMP group:@SEQRELATED_LIBS comment:"Metabolic pathways - Selkov." format:@EMP_FORMAT maxNameLen:30 ifiles:{"emp.i emp.is"} files:{ $file:8612 $file:8912 $file:9211 $file:8701 $file:9001 $file:9212 $file:8702 $file:9002 $file:9301 $file:8703 $file:9003 $file:9302 $file:8704 $file:9004 $file:9303 $file:8705 $file:9005 $file:9304 $file:8706 $file:9006 $file:9305 $file:8707 $file:9007 $file:9306 $file:8708 $file:9008 $file:9307 $file:8709 $file:9009 $file:9308 $file:8710 $file:9010 $file:9309 $file:8711 $file:9011 $file:9310 $file:8712 $file:9012 $file:9311 $file:8801 $file:9101 $file:9312 $file:8802 $file:9102 $file:9401 $file:8803 $file:9103 $file:9402 $file:8804 $file:9104 $file:9403 $file:8805 $file:9105 $file:9404 $file:8806 $file:9106 $file:9405 $file:8807 $file:9107 $file:9406 $file:8808 $file:9108 $file:9407 $file:8810 $file:9109 $file:9408 $file:8811 $file:9110 $file:9409 $file:8812 $file:9111 $file:9410 $file:8901 $file:9112 $file:9411 $file:8902 $file:9201 $file:9412 $file:8903 $file:9202 $file:9501 $file:8904 $file:9203 $file:9502 $file:8905 $file:9204 $file:9503 $file:8906 $file:9205 $file:9504 $file:8907 $file:9206 $file:9509 $file:8908 $file:9207 $file:8909 $file:9208 $file:8910 $file:9209 $file:8911 $file:9210 } ] $link:[@EMP_DB to:@?MPW_DB toField:@DF_Name token:'links|mpw'] $link:[@EMP_DB to:@?ENZYME_DB toField:@DF_ID token:'links|enzyme'] EMP_FORMAT:$libformat:[fileType:@EMP_FILE syntax:@EMP_SYNTAX tableFormat:left printFormat:table fields:{ $field:@DF_ALL $field:[@DF_LINK index:link indexToken:links] $field:[@DF_HeaderField name:'Entry Identification'] $field:[@DF_ID code: AN index:id indexToken:id] $field:[@DF_StaffFootnote code: '**'] $field:[@DF_AnnotatorsFootnote code: '***'] $field:[@DF_ReferenceNumber code: RN] $field:[@DF_HeaderField name:'Bibliographic Description'] $field:[@DF_Author code: AU] $field:[@DF_OrganizationalSource code:OS index:str indexToken:'words|OS'] $field:[@DF_Title code: TI index:str indexToken:'words|TI'] $field:[@DF_BibliographicSource code: SO] $field:[@DF_PublicationYear code: YR] $field:[@DF_SourceCode code: SC] $field:[@DF_DocumentType code: DT] $field:[@DF_Language code: LA] $field:[@DF_CategoryCode code: CC] $field:[@DF_IndexTerms code: IT] $field:[@DF_SupplementaryTerms code: ST] $field:[@DF_Abstract code: AB] $field:[@DF_AnnotatorsAbstract code: AAB] $field:[@DF_Reference code: REF] $field:[@DF_HeaderField name:'Biological Source'] $field:[@DF_CellLine code: CLI] $field:[@DF_CellType code: CTY] $field:[@DF_OrganismSystematicName code: OR index:str indexToken:'words|OR'] $field:[@DF_OrganismSubspecies code: SSP] $field:[@DF_OrganismCommonName code: OCN] $field:[@DF_TaxonomicGroup code: TG index:str indexToken:'words|TG'] $field:[@DF_CellSpeciesExtracellFluid code: CS] $field:[@DF_Strain code: STR] $field:[@DF_Genotype code: GET] $field:[@DF_Phenotype code: PHT] $field:[@DF_MetabolicType code: MET] $field:[@DF_Age code: AGE] $field:[@DF_Sex code: SEX] $field:[@DF_OrganismWeight code: WT] $field:[@DF_KeepingConditions code: KCO] $field:[@DF_OrganismTreatment code: OTR] $field:[@DF_PhysiologicalState code: PHS] $field:[@DF_DevelopmentalStage code: DEV] $field:[@DF_Pathology code: PAT] $field:[@DF_LightConditions code: LC] $field:[@DF_LightIntensity code: LI] $field:[@DF_WaveLength code: WL] $field:[@DF_TimeOftheDay code: TOD] $field:[@DF_CellCultureCategory code: CCC] $field:[@DF_HeaderField name:'Organism Phenotype'] # $field:[@DF_OrganismSystematicName code: OR] $field:[@DF_SubspeciesName code: SSP] $field:[@DF_TypeSpecies code: TSP] $field:[@DF_TypeStrainName code: TSN] $field:[@DF_BactClassificationCode code: BC] $field:[@DF_OrganismCommonName code: OCN] # $field:[@DF_TaxonomicGroup code: TG] $field:[@DF_CellCultureCategoryCode code: CCC] $field:[@DF_CellType code: CTY] $field:[@DF_molGCContentInDNA code: GCC] $field:[@DF_GenomeSizeDaltons code: GSZ] $field:[@DF_ColonyMorphology code: CMO] $field:[@DF_CellMorphology code: MOR] $field:[@DF_PeptidoglycanComposition code: PGC] $field:[@DF_MembraneLipidComposition code: LIP] $field:[@DF_CytochromePresent code: CYT] $field:[@DF_MembrIsoprenoidQuinonesPresent code: QUI] $field:[@DF_FlagellarArrangement code: FLA] $field:[@DF_Physiology code: PHY] $field:[@DF_CellOrSporeMotility code: MOT] $field:[@DF_ConcentrationInCultivationMedium code: CON] $field:[@DF_AbsoluteRequirementForGrowth code: AR] $field:[@DF_GrowthInhibitor code: GRI] $field:[@DF_GrowthActivator code: GRA] $field:[@DF_CommonAntigeneName code: CAN] $field:[@DF_MetabolicType code: MET] $field:[@DF_AlternativePathwayNames code: LAP] $field:[@DF_SystematicPathwayNames code: LSP] $field:[@DF_EnzymeProduced code: ENP] $field:[@DF_FermentationProduct code: FPR] $field:[@DF_ProductionOf code: PRD] $field:[@DF_AcidProducedFrom code: ACD] $field:[@DF_GasProducedFrom code: GAS] $field:[@DF_CarbonSourceUsed code: CSO] $field:[@DF_NitrogenSourceUsed code: NSO] $field:[@DF_Test code: TST] $field:[@DF_NaturalHost code: NHO] $field:[@DF_PathogenicityForHost code: PGY] $field:[@DF_HostPathologyDescription code: HPD] $field:[@DF_Habitat code: HAB] $field:[@DF_GeographicalDistribution code: GEO] $field:[@DF_CulturePreservationConditions code: CPC] $field:[@DF_HeaderField name:'Host'] $field:[@DF_LaboratoryHostSystematicName code: HST] $field:[@DF_HostAge code: HAG] $field:[@DF_HostCommonName code: HCN] $field:[@DF_HostTaxonomicGroup code: HTG] $field:[@DF_HostDevelopmentalStage code: HDS] $field:[@DF_HostStrainName code: HSN] $field:[@DF_HostSex code: HSX] $field:[@DF_HostGenotype code: HGT] $field:[@DF_HostPhenotype code: HPT] $field:[@DF_HostSubcellularFraction code: HSF] $field:[@DF_HostCellSpecies code: HCS] $field:[@DF_HostCellularLocation code: HSL] $field:[@DF_HostCellCultureCategory code: HCC] $field:[@DF_HostCellLine code: HCL] $field:[@DF_HostCellType code: HCT] $field:[@DF_HostTreatment code: HTR] $field:[@DF_NaturalHostSystematicName code: NHO] $field:[@DF_ClonedVector code: CLV] $field:[@DF_HeaderField name:'Biochemical Genetics'] $field:[@DF_GeneAcronym code: GN] $field:[@DF_AlternativeGeneAcronym code: AGA] $field:[@DF_GeneMnemonics code: GMN] $field:[@DF_GeneProduct code: GNP] $field:[@DF_GeneticMapPosition code: GMP] $field:[@DF_GeneLocation code: GL] $field:[@DF_CoordinatelyExpressedGenes code: CEG] $field:[@DF_NucleotideSequenceCrossref code: NS] $field:[@DF_TypeofSynthesis code: SYN] $field:[@DF_Inducer code: IND] $field:[@DF_InductionDegree code: IDE] $field:[@DF_Repressor code: REP] $field:[@DF_RepressionDegree code: RDE] $field:[@DF_DegradationActivator code: DAC] $field:[@DF_DegradationInhibitor code: DIN] $field:[@DF_EnzymeHalfLifeTime code: T05] $field:[@DF_HeaderField name:'Cell Cultivation Conditions'] $field:[@DF_CultivationConditions code: CUC] $field:[@DF_CultivationTemperature code: CUT] $field:[@DF_DilutionRate code: DR] $field:[@DF_CultivationMedium code: MED] $field:[@DF_NitrogenSource code: NSO] $field:[@DF_CarbonSource code: CSO] $field:[@DF_LimitingSubstrate code: LS] $field:[@DF_GrowthSubstrate code: GS] $field:[@DF_CultureDensity code: CD] $field:[@DF_CellCyclePhase code: CCP] $field:[@DF_GrowthPhase code: GP] $field:[@DF_GenerationTime code: GT] $field:[@DF_CellCyclePeriod code: CPE] $field:[@DF_GrowthRate code: GRR] $field:[@DF_SpecificGrowthRate code: SGR] $field:[@DF_GrowthMode code: GM] $field:[@DF_GrowthYield code: GY] $field:[@DF_ColonySize code: CSZ] $field:[@DF_HeaderField name:'Metabolism'] $field:[@DF_MetabolicPathwayName code: MPW] $field:[@DF_SystematicPathwayName code: SPN] $field:[@DF_AlternativePathwayName code: APN] $field:[@DF_OverallReaction code: OVR] $field:[@DF_OverallReactionVelocity code: VEL] $field:[@DF_MetabolicState code: MES] $field:[@DF_HeaderField name:'Enzyme and Reaction'] $field:[@DF_SubcellularLocation code: SL] $field:[@DF_SubcellularFraction code: SF] $field:[@DF_ActiveSiteLocation code: ASL] $field:[@DF_MultifunctionalEnzymeName code: MF] $field:[@DF_MultifunctionalEnzymeForm code: MFF] $field:[@DF_AltMultifunctionalEnzymeName code: AMF] $field:[@DF_MultifunctionalEnzymeCode code: MFC] $field:[@DF_RecommendedEnzymeName code: EN] $field:[@DF_SystematicEnzymeName code: SEN] $field:[@DF_OtherEnzymeName code: ON] $field:[@DF_EnzymeCode code: EC index:str indexToken:enzCode] $field:[@DF_EnzymeForm code: EF] $field:[@DF_ProteinName code: PN] $field:[@DF_NonCatalyticFunction code: NCF] $field:[@DF_ProteinForm code: PRF] $field:[@DF_ProteinConcentration code: PCO] $field:[@DF_IsozymeNumber code: IZN] $field:[@DF_ReactionEquation code: RE index:str indexToken:'words|RE'] $field:[@DF_ReactionIdentifier code: RI] $field:[@DF_ReactionType code: RET] $field:[@DF_ElementaryStepEquation code: ESE] $field:[@DF_Substrate code: SU index:str indexToken:'words|SU'] $field:[@DF_SiteofEnzymeAction code: SEA] $field:[@DF_NonSubstrate code: NSU index:str indexToken:'words|NSU'] $field:[@DF_Coenzyme code: CO] $field:[@DF_NonCoenzyme code: NCO] $field:[@DF_Product code: PR] $field:[@DF_NonProduct code: NPR] $field:[@DF_AbsoluteRequirement code: AR] $field:[@DF_ReactionPhase code: RP] $field:[@DF_Reversibility code: REV] $field:[@DF_ReactionDirection code: RD] $field:[@DF_EnzymeApplication code: APP] $field:[@DF_HeaderField name:'Assay and Purification'] $field:[@DF_AssayConditions code: ASS] $field:[@DF_TissueActivity code: TA] $field:[@DF_PreparationSpecificActivity code: PA] $field:[@DF_SpecificActivity code: SA index:str indexToken:'words|SA'] $field:[@DF_PurificationSteps code: PS index:str indexToken:'words|PS'] $field:[@DF_PurifFactorAndPurityDegree code: PF] $field:[@DF_Yield code: YD] $field:[@DF_EnzymeConcentration code: ECO] $field:[@DF_ProteinConcentration code: PCO] $field:[@DF_TotalProteinContent code: TPC] $field:[@DF_PreparationSpecificBinding code: PB] $field:[@DF_SpecificBinding code: SB] $field:[@DF_StorageConditions code: STO] $field:[@DF_Buffer code: BUF] $field:[@DF_pHValue code: PH] $field:[@DF_Temperature code: TEM] $field:[@DF_IonicStrength code: IS] $field:[@DF_OptimalConditions code: OC] $field:[@DF_HeaderField name:'Enzyme Kinetics'] $field:[@DF_TypeofKineticsOrFunctDependence code: KT] $field:[@DF_MaxReactionVelocity code: VM] $field:[@DF_PreparationMaxVelocity code: PVM] $field:[@DF_RelativeMaxVelocity code: RVM] $field:[@DF_RelativeActivity code: RA] $field:[@DF_MolecularActivity code: MA] $field:[@DF_CatalyticConst code: KC] $field:[@DF_MichaelisConst code: KM index:str indexToken:'words|KM'] $field:[@DF_HalfSaturatingSubstrateConc code: S05] $field:[@DF_Conditions code: CND] $field:[@DF_CatalyticEfficiency code: CEF] $field:[@DF_ApparentCatalyticConst code: ACC] $field:[@DF_Ligand code: LIG] $field:[@DF_FixedLigand code: FL] $field:[@DF_VariableLigand code: VL] $field:[@DF_MaxSpecificBinding code: BM] $field:[@DF_HillsNumber code: NH] $field:[@DF_ReactionMechanism code: ME] $field:[@DF_RateLaw code: RL] $field:[@DF_RateConstDesignation code: RCD] $field:[@DF_RateConst code: RC] $field:[@DF_TimeConst code: TC] $field:[@DF_FunctionalDependence code: FUN] $field:[@DF_HeaderField name:'Enzyme Regulation'] $field:[@DF_Activator code: AC] $field:[@DF_ActivationType code: ACT] $field:[@DF_ActivationDegree code: AD] $field:[@DF_MaxActivationDegree code: MAD] $field:[@DF_ActivationConst code: KA] $field:[@DF_HalfActivatingConcentration code: A05] $field:[@DF_Inhibitor code: IN index:str indexToken:'words|IN'] $field:[@DF_InhibitionType code: INT] $field:[@DF_InhibitionDegree code: ID] $field:[@DF_MaxInhibitionDegree code: MID] $field:[@DF_InhibitionConst code: KI] $field:[@DF_HalfInhibitingConc code: I05] $field:[@DF_InterceptInhibitionConst code: KII] $field:[@DF_SlopeInhibitionConst code: KIS] $field:[@DF_NonInfluencingCompound code: NIC] $field:[@DF_HeaderField name:'Enzyme Modification'] $field:[@DF_EnzymeModificationProcess code: MP] $field:[@DF_EnzymeModifier code: MOD] $field:[@DF_EnzymeBindingPartner code: BPA] $field:[@DF_ModifyingEnzymeName code: MEN] $field:[@DF_ModifyingEnzymeCode code: MEC] $field:[@DF_ModifyingEnzymeForm code: MEF] $field:[@DF_ModificationResidual code: MRE] $field:[@DF_ModificationMechanism code: MME] $field:[@DF_ModificationPromotor code: MPR] $field:[@DF_ModificationAntagonist code: MAN] $field:[@DF_ModificationEffect code: MOE] $field:[@DF_EnzymeTreatment code: TR] $field:[@DF_TreatmentEffect code: EFF] $field:[@DF_HeaderField name:'Enzyme Structure'] $field:[@DF_MolecularMass code: MM index:str indexToken:'words|MM'] $field:[@DF_SedimentationConst code: ESC] $field:[@DF_SubunitMass code: SM] $field:[@DF_SubunitSedimentationConst code: SSC] $field:[@DF_SubunitName code: SUN] $field:[@DF_SubunitDesignation code: SUD] $field:[@DF_SubunitFunction code: SUF] $field:[@DF_SubunitNumber code: SN] $field:[@DF_SubunitComposition code: SUC] $field:[@DF_SubunitStructure code: SUS] $field:[@DF_SubunitBindingType code: SBT] $field:[@DF_MolecularSymmetry code: MS] $field:[@DF_PolypeptideChainNumber code: PCN] $field:[@DF_ProstheticGroup code: PRG] $field:[@DF_ProstheticGroupNumber code: PGN] $field:[@DF_BindingType code: BT] $field:[@DF_SHGroupNumber code: SHN] $field:[@DF_DisulfideBondNumber code: SSN] $field:[@DF_BindingSiteName code: SNA] $field:[@DF_BindingSiteNumber code: SNU] $field:[@DF_SiteAminoAcidSequence code: SSQ] $field:[@DF_BindingSiteResidual code: SRE] $field:[@DF_AminoAcids code: AA] $field:[@DF_Content code: CNT] $field:[@DF_AminoAcidSequenceOrCrossref code: AAS] $field:[@DF_EnzymeComposition code: ENC] $field:[@DF_TerminalAminoAcids code: TAA] $field:[@DF_SignalPeptide code: SP] $field:[@DF_SignalPeptideLength code: SPL] $field:[@DF_IntramolecularLocation code: LOC] $field:[@DF_PrimaryStructureHomology code: HOM] $field:[@DF_HeaderField name:'Equilibrium and Thermodynamics'] $field:[@DF_EquilibConst code: KEQ] $field:[@DF_EquilibConstFormula code: KEF] $field:[@DF_DissociationConstDesignation code: KDD] $field:[@DF_DissociationConst code: KD] $field:[@DF_AssociationConstDesignation code: KAD] $field:[@DF_AssociationConst code: KAS] $field:[@DF_EquilibConstDesignation code: KED] $field:[@DF_ElementaryStepEquilibConst code: KEE] $field:[@DF_MassActionRatio code: MAR] $field:[@DF_StandardFreeEnergyChange code: DG0] $field:[@DF_StandardEntropyChange code: DS0] $field:[@DF_StandardEnthalpyChange code: DH0] $field:[@DF_ActivationEnergy code: EA] $field:[@DF_ActivationFreeEnergyChange code: DGA] $field:[@DF_ActivationEnthalpyChange code: DHA] $field:[@DF_ActivationEntropyChange code: DSA] $field:[@DF_StandardRedoxPotential code: E0] $field:[@DF_ElectronTransferNumber code: ETN] $field:[@DF_HeatCapacityChange code: DCP] $field:[@DF_HeaderField name:'Physical Chemistry and Spectral Properties'] $field:[@DF_IsoelectricPoint code: IP] $field:[@DF_OptimalPH code: PHO] $field:[@DF_pHDependentParameter code: PHD] $field:[@DF_pHRange code: PHR] $field:[@DF_pKValues code: PKV] $field:[@DF_InactivationConst code: IC] $field:[@DF_OptimalTemperature code: TO] $field:[@DF_TempDependentParameter code: TD] $field:[@DF_TemperatureRange code: TER] $field:[@DF_TemperatureCoefficient code: Q10] $field:[@DF_NameofParameterorVariable code: PAR] $field:[@DF_ValueofParameterorVariable code: VAL] $field:[@DF_AbsorptionMaxWaveLength code: AM] $field:[@DF_AbsorptionCoefficient code: ABC] $field:[@DF_MolarAbsorptionCoefficient code: MAC] $field:[@DF_AbsorptionShoulder code: ASH] $field:[@DF_FluorescenceMax code: FM] $field:[@DF_CDSpectrumMax code: CMA] $field:[@DF_CDSpectrumMin code: CMI] $field:[@DF_CDSpectrumShoulder code: CSH] $field:[@DF_EPRSignals code: EPR] $field:[@DF_HeaderField name:'Immunochemistry'] $field:[@DF_Antigene code: AGN] $field:[@DF_Antibody code: ABD] $field:[@DF_CrossReactivity code: CRR] $field:[@DF_HeaderField name:'Common fields'] $field:[@DF_Abbreviation code: ABB] $field:[@DF_Addition code: ADD] $field:[@DF_BiologicalFunction code: BFN] $field:[@DF_Comments code: COM] $field:[@DF_Concentration code: CON] $field:[@DF_Designation code: DES] $field:[@DF_Formula code: FOR] $field:[@DF_Method code: MT] $field:[@DF_OscillationPeriod code: OP] $field:[@DF_PhaseDifference code: PDI] $field:[@DF_Process code: PRS] $field:[@DF_Property code: PRY] $field:[@DF_SubstanceComposition code: SCN] $field:[@DF_StandardDeviation code: SD] $field:[@DF_Substance code: SUB] $field:[@DF_Synonyms code: SYM] $field:[@DF_Time code: TIM] $field:[@DF_Type code: TYP] $field:[@DF_Unit code: UN] } ] DF_AccessionNumber: $srsfield:[AccessionNumber short: AN] DF_StaffFootnote: $srsfield:[StaffFootnote short: SF] DF_AnnotatorsFootnote: $srsfield:[AnnotatorsFootnote short: AF] DF_ReferenceNumber: $srsfield:[ReferenceNumber short: RN] DF_Author: $srsfield:[Author short: AU] DF_OrganizationalSource: $srsfield:[OrganizationalSource short: OS] DF_Title: $srsfield:[Title short: TI] DF_BibliographicSource: $srsfield:[BibliographicSource short: SO] DF_PublicationYear: $srsfield:[PublicationYear short: YR] DF_SourceCode: $srsfield:[SourceCode short: SC] DF_DocumentType: $srsfield:[DocumentType short: DT] DF_Language: $srsfield:[Language short: LA] DF_CategoryCode: $srsfield:[CategoryCode short: CC] DF_IndexTerms: $srsfield:[IndexTerms short: IT] DF_SupplementaryTerms: $srsfield:[SupplementaryTerms short: ST] DF_Abstract: $srsfield:[Abstract short: AB] DF_AnnotatorsAbstract: $srsfield:[AnnotatorsAbstract short: AAB] DF_Reference: $srsfield:[Reference short: REF] DF_CellLine: $srsfield:[CellLine short: CLI] DF_CellType: $srsfield:[CellType short: CTY] DF_OrganismSystematicName: $srsfield:[OrganismSystematicName short: OR] DF_OrganismSubspecies: $srsfield:[OrganismSubspecies short: SSP] DF_OrganismCommonName: $srsfield:[OrganismCommonName short: OCN] DF_TaxonomicGroup: $srsfield:[TaxonomicGroup short: TG] DF_CellSpeciesExtracellFluid: $srsfield:[CellSpeciesExtracellFluid short: CS] DF_Strain: $srsfield:[Strain short: STR] DF_Genotype: $srsfield:[Genotype short: GET] DF_Phenotype: $srsfield:[Phenotype short: PHT] DF_MetabolicType: $srsfield:[MetabolicType short: MET] DF_Age: $srsfield:[Age short: AGE] DF_Sex: $srsfield:[Sex short: SEX] DF_OrganismWeight: $srsfield:[OrganismWeight short: WT] DF_KeepingConditions: $srsfield:[KeepingConditions short: KCO] DF_OrganismTreatment: $srsfield:[OrganismTreatment short: OTR] DF_PhysiologicalState: $srsfield:[PhysiologicalState short: PHS] DF_DevelopmentalStage: $srsfield:[DevelopmentalStage short: DEV] DF_Pathology: $srsfield:[Pathology short: PAT] DF_LightConditions: $srsfield:[LightConditions short: LC] DF_LightIntensity: $srsfield:[LightIntensity short: LI] DF_WaveLength: $srsfield:[WaveLength short: WL] DF_TimeOftheDay: $srsfield:[TimeOftheDay short: TOD] DF_CellCultureCategory: $srsfield:[CellCultureCategory short: CCC] DF_OrganismSystematicName: $srsfield:[OrganismSystematicName short: OR] DF_SubspeciesName: $srsfield:[SubspeciesName short: SSP] DF_TypeSpecies: $srsfield:[TypeSpecies short: TSP] DF_TypeStrainName: $srsfield:[TypeStrainName short: TSN] DF_BactClassificationCode: $srsfield:[BactClassificationCode short: BC] DF_OrganismCommonName: $srsfield:[OrganismCommonName short: OCN] DF_TaxonomicGroup: $srsfield:[TaxonomicGroup short: TG] DF_CellCultureCategoryCode: $srsfield:[CellCultureCategoryCode short: CCC] DF_CellType: $srsfield:[CellType short: CTY] DF_molGCContentInDNA: $srsfield:[molGCContentInDNA short: GCC] DF_GenomeSizeDaltons: $srsfield:[GenomeSizeDaltons short: GSZ] DF_ColonyMorphology: $srsfield:[ColonyMorphology short: CMO] DF_CellMorphology: $srsfield:[CellMorphology short: MOR] DF_PeptidoglycanComposition: $srsfield:[PeptidoglycanComposition short: PGC] DF_MembraneLipidComposition: $srsfield:[MembraneLipidComposition short: LIP] DF_CytochromePresent: $srsfield:[CytochromePresent short: CYT] DF_MembrIsoprenoidQuinonesPresent: $srsfield:[MembrIsoprenoidQuinonesPresent short: QUI] DF_FlagellarArrangement: $srsfield:[FlagellarArrangement short: FLA] DF_Physiology: $srsfield:[Physiology short: PHY] DF_CellOrSporeMotility: $srsfield:[CellOrSporeMotility short: MOT] DF_ConcentrationInCultivationMedium: $srsfield:[ConcentrationInCultivationMedium short: CON] DF_AbsoluteRequirementForGrowth: $srsfield:[AbsoluteRequirementForGrowth short: AR] DF_GrowthInhibitor: $srsfield:[GrowthInhibitor short: GRI] DF_GrowthActivator: $srsfield:[GrowthActivator short: GRA] DF_CommonAntigeneName: $srsfield:[CommonAntigeneName short: CAN] DF_MetabolicType: $srsfield:[MetabolicType short: MET] DF_AlternativePathwayNames: $srsfield:[AlternativePathwayNames short: LAP] DF_SystematicPathwayNames: $srsfield:[SystematicPathwayNames short: LSP] DF_EnzymeProduced: $srsfield:[EnzymeProduced short: ENP] DF_FermentationProduct: $srsfield:[FermentationProduct short: FPR] DF_ProductionOf: $srsfield:[ProductionOf short: PRD] DF_AcidProducedFrom: $srsfield:[AcidProducedFrom short: ACD] DF_GasProducedFrom: $srsfield:[GasProducedFrom short: GAS] DF_CarbonSourceUsed: $srsfield:[CarbonSourceUsed short: CSO] DF_NitrogenSourceUsed: $srsfield:[NitrogenSourceUsed short: NSO] DF_Test: $srsfield:[Test short: TST] DF_NaturalHost: $srsfield:[NaturalHost short: NHO] DF_PathogenicityForHost: $srsfield:[PathogenicityForHost short: PGY] DF_HostPathologyDescription: $srsfield:[HostPathologyDescription short: HPD] DF_Habitat: $srsfield:[Habitat short: HAB] DF_GeographicalDistribution: $srsfield:[GeographicalDistribution short: GEO] DF_CulturePreservationConditions: $srsfield:[CulturePreservationConditions short: CPC] DF_LaboratoryHostSystematicName: $srsfield:[LaboratoryHostSystematicName short: HST] DF_HostAge: $srsfield:[HostAge short: HAG] DF_HostCommonName: $srsfield:[HostCommonName short: HCN] DF_HostTaxonomicGroup: $srsfield:[HostTaxonomicGroup short: HTG] DF_HostDevelopmentalStage: $srsfield:[HostDevelopmentalStage short: HDS] DF_HostStrainName: $srsfield:[HostStrainName short: HSN] DF_HostSex: $srsfield:[HostSex short: HSX] DF_HostGenotype: $srsfield:[HostGenotype short: HGT] DF_HostPhenotype: $srsfield:[HostPhenotype short: HPT] DF_HostSubcellularFraction: $srsfield:[HostSubcellularFraction short: HSF] DF_HostCellSpecies: $srsfield:[HostCellSpecies short: HCS] DF_HostCellularLocation: $srsfield:[HostCellularLocation short: HSL] DF_HostCellCultureCategory: $srsfield:[HostCellCultureCategory short: HCC] DF_HostCellLine: $srsfield:[HostCellLine short: HCL] DF_HostCellType: $srsfield:[HostCellType short: HCT] DF_HostTreatment: $srsfield:[HostTreatment short: HTR] DF_NaturalHostSystematicName: $srsfield:[NaturalHostSystematicName short: NHO] DF_ClonedVector: $srsfield:[ClonedVector short: CLV] DF_GeneAcronym: $srsfield:[GeneAcronym short: GN] DF_AlternativeGeneAcronym: $srsfield:[AlternativeGeneAcronym short: AGA] DF_GeneMnemonics: $srsfield:[GeneMnemonics short: GMN] DF_GeneProduct: $srsfield:[GeneProduct short: GNP] DF_GeneticMapPosition: $srsfield:[GeneticMapPosition short: GMP] DF_GeneLocation: $srsfield:[GeneLocation short: GL] DF_CoordinatelyExpressedGenes: $srsfield:[CoordinatelyExpressedGenes short: CEG] DF_NucleotideSequenceCrossref: $srsfield:[NucleotideSequenceCrossref short: NS] DF_TypeofSynthesis: $srsfield:[TypeofSynthesis short: SYN] DF_Inducer: $srsfield:[Inducer short: IND] DF_InductionDegree: $srsfield:[InductionDegree short: IDE] DF_Repressor: $srsfield:[Repressor short: REP] DF_RepressionDegree: $srsfield:[RepressionDegree short: RDE] DF_DegradationActivator: $srsfield:[DegradationActivator short: DAC] DF_DegradationInhibitor: $srsfield:[DegradationInhibitor short: DIN] DF_EnzymeHalfLifeTime: $srsfield:[EnzymeHalfLifeTime short: T05] DF_CultivationConditions: $srsfield:[CultivationConditions short: CUC] DF_CultivationTemperature: $srsfield:[CultivationTemperature short: CUT] DF_DilutionRate: $srsfield:[DilutionRate short: DR] DF_CultivationMedium: $srsfield:[CultivationMedium short: MED] DF_NitrogenSource: $srsfield:[NitrogenSource short: NSO] DF_CarbonSource: $srsfield:[CarbonSource short: CSO] DF_LimitingSubstrate: $srsfield:[LimitingSubstrate short: LS] DF_GrowthSubstrate: $srsfield:[GrowthSubstrate short: GS] DF_CultureDensity: $srsfield:[CultureDensity short: CD] DF_CellCyclePhase: $srsfield:[CellCyclePhase short: CCP] DF_GrowthPhase: $srsfield:[GrowthPhase short: GP] DF_GenerationTime: $srsfield:[GenerationTime short: GT] DF_CellCyclePeriod: $srsfield:[CellCyclePeriod short: CPE] DF_GrowthRate: $srsfield:[GrowthRate short: GRR] DF_SpecificGrowthRate: $srsfield:[SpecificGrowthRate short: SGR] DF_GrowthMode: $srsfield:[GrowthMode short: GM] DF_GrowthYield: $srsfield:[GrowthYield short: GY] DF_ColonySize: $srsfield:[ColonySize short: CSZ] DF_MetabolicPathwayName: $srsfield:[MetabolicPathwayName short: MPW] DF_SystematicPathwayName: $srsfield:[SystematicPathwayName short: SPN] DF_AlternativePathwayName: $srsfield:[AlternativePathwayName short: APN] DF_OverallReaction: $srsfield:[OverallReaction short: OVR] DF_OverallReactionVelocity: $srsfield:[OverallReactionVelocity short: VEL] DF_MetabolicState: $srsfield:[MetabolicState short: MES] DF_SubcellularLocation: $srsfield:[SubcellularLocation short: SL] DF_SubcellularFraction: $srsfield:[SubcellularFraction short: SF] DF_ActiveSiteLocation: $srsfield:[ActiveSiteLocation short: ASL] DF_MultifunctionalEnzymeName: $srsfield:[MultifunctionalEnzymeName short: MF] DF_MultifunctionalEnzymeForm: $srsfield:[MultifunctionalEnzymeForm short: MFF] DF_AltMultifunctionalEnzymeName: $srsfield:[AltMultifunctionalEnzymeName short: AMF] DF_MultifunctionalEnzymeCode: $srsfield:[MultifunctionalEnzymeCode short: MFC] DF_RecommendedEnzymeName: $srsfield:[RecommendedEnzymeName short: EN] DF_SystematicEnzymeName: $srsfield:[SystematicEnzymeName short: SEN] DF_OtherEnzymeName: $srsfield:[OtherEnzymeName short: ON] DF_EnzymeForm: $srsfield:[EnzymeForm short: EF] DF_ProteinName: $srsfield:[ProteinName short: PN] DF_NonCatalyticFunction: $srsfield:[NonCatalyticFunction short: NCF] DF_ProteinForm: $srsfield:[ProteinForm short: PRF] DF_ProteinConcentration: $srsfield:[ProteinConcentration short: PCO] DF_IsozymeNumber: $srsfield:[IsozymeNumber short: IZN] DF_ReactionEquation: $srsfield:[ReactionEquation short: RE] DF_ReactionIdentifier: $srsfield:[ReactionIdentifier short: RI] DF_ReactionType: $srsfield:[ReactionType short: RET] DF_ElementaryStepEquation: $srsfield:[ElementaryStepEquation short: ESE] DF_Substrate: $srsfield:[Substrate short: SU] DF_SiteofEnzymeAction: $srsfield:[SiteofEnzymeAction short: SEA] DF_NonSubstrate: $srsfield:[NonSubstrate short: NSU] DF_Coenzyme: $srsfield:[Coenzyme short: CO] DF_NonCoenzyme: $srsfield:[NonCoenzyme short: NCO] DF_Product: $srsfield:[Product short: PR] DF_NonProduct: $srsfield:[NonProduct short: NPR] DF_AbsoluteRequirement: $srsfield:[AbsoluteRequirement short: AR] DF_ReactionPhase: $srsfield:[ReactionPhase short: RP] DF_Reversibility: $srsfield:[Reversibility short: REV] DF_ReactionDirection: $srsfield:[ReactionDirection short: RD] DF_EnzymeApplication: $srsfield:[EnzymeApplication short: APP] DF_AssayConditions: $srsfield:[AssayConditions short: ASS] DF_TissueActivity: $srsfield:[TissueActivity short: TA] DF_PreparationSpecificActivity: $srsfield:[PreparationSpecificActivity short: PA] DF_SpecificActivity: $srsfield:[SpecificActivity short: SA] DF_PurificationSteps: $srsfield:[PurificationSteps short: PS] DF_PurifFactorAndPurityDegree: $srsfield:[PurifFactorAndPurityDegree short: PF] DF_Yield: $srsfield:[Yield short: YD] DF_EnzymeConcentration: $srsfield:[EnzymeConcentration short: ECO] DF_ProteinConcentration: $srsfield:[ProteinConcentration short: PCO] DF_TotalProteinContent: $srsfield:[TotalProteinContent short: TPC] DF_PreparationSpecificBinding: $srsfield:[PreparationSpecificBinding short: PB] DF_SpecificBinding: $srsfield:[SpecificBinding short: SB] DF_StorageConditions: $srsfield:[StorageConditions short: STO] DF_Buffer: $srsfield:[Buffer short: BUF] DF_pHValue: $srsfield:[pHValue short: PH] DF_Temperature: $srsfield:[Temperature short: TEM] DF_IonicStrength: $srsfield:[IonicStrength short: IS] DF_OptimalConditions: $srsfield:[OptimalConditions short: OC] DF_TypeofKineticsOrFunctDependence: $srsfield:[TypeofKineticsOrFunctDependence short: KT] DF_MaxReactionVelocity: $srsfield:[MaxReactionVelocity short: VM] DF_PreparationMaxVelocity: $srsfield:[PreparationMaxVelocity short: PVM] DF_RelativeMaxVelocity: $srsfield:[RelativeMaxVelocity short: RVM] DF_RelativeActivity: $srsfield:[RelativeActivity short: RA] DF_MolecularActivity: $srsfield:[MolecularActivity short: MA] DF_CatalyticConst: $srsfield:[CatalyticConst short: KC] DF_MichaelisConst: $srsfield:[MichaelisConst short: KM] DF_HalfSaturatingSubstrateConc: $srsfield:[HalfSaturatingSubstrateConc short: S05] DF_Conditions: $srsfield:[Conditions short: CND] DF_CatalyticEfficiency: $srsfield:[CatalyticEfficiency short: CEF] DF_ApparentCatalyticConst: $srsfield:[ApparentCatalyticConst short: ACC] DF_Ligand: $srsfield:[Ligand short: LIG] DF_FixedLigand: $srsfield:[FixedLigand short: FL] DF_VariableLigand: $srsfield:[VariableLigand short: VL] DF_MaxSpecificBinding: $srsfield:[MaxSpecificBinding short: BM] DF_HillsNumber: $srsfield:[HillsNumber short: NH] DF_ReactionMechanism: $srsfield:[ReactionMechanism short: ME] DF_RateLaw: $srsfield:[RateLaw short: RL] DF_RateConstDesignation: $srsfield:[RateConstDesignation short: RCD] DF_RateConst: $srsfield:[RateConst short: RC] DF_TimeConst: $srsfield:[TimeConst short: TC] DF_FunctionalDependence: $srsfield:[FunctionalDependence short: FUN] DF_Activator: $srsfield:[Activator short: AC] DF_ActivationType: $srsfield:[ActivationType short: ACT] DF_ActivationDegree: $srsfield:[ActivationDegree short: AD] DF_MaxActivationDegree: $srsfield:[MaxActivationDegree short: MAD] DF_ActivationConst: $srsfield:[ActivationConst short: KA] DF_HalfActivatingConcentration: $srsfield:[HalfActivatingConcentration short: A05] DF_Inhibitor: $srsfield:[Inhibitor short: IN] DF_InhibitionType: $srsfield:[InhibitionType short: INT] DF_InhibitionDegree: $srsfield:[InhibitionDegree short: IND] DF_MaxInhibitionDegree: $srsfield:[MaxInhibitionDegree short: MID] DF_InhibitionConst: $srsfield:[InhibitionConst short: KI] DF_HalfInhibitingConc: $srsfield:[HalfInhibitingConc short: I05] DF_InterceptInhibitionConst: $srsfield:[InterceptInhibitionConst short: KII] DF_SlopeInhibitionConst: $srsfield:[SlopeInhibitionConst short: KIS] DF_NonInfluencingCompound: $srsfield:[NonInfluencingCompound short: NIC] DF_EnzymeModificationProcess: $srsfield:[EnzymeModificationProcess short: MP] DF_EnzymeModifier: $srsfield:[EnzymeModifier short: MOD] DF_EnzymeBindingPartner: $srsfield:[EnzymeBindingPartner short: BPA] DF_ModifyingEnzymeName: $srsfield:[ModifyingEnzymeName short: MEN] DF_ModifyingEnzymeCode: $srsfield:[ModifyingEnzymeCode short: MEC] DF_ModifyingEnzymeForm: $srsfield:[ModifyingEnzymeForm short: MEF] DF_ModificationResidual: $srsfield:[ModificationResidual short: MRE] DF_ModificationMechanism: $srsfield:[ModificationMechanism short: MME] DF_ModificationPromotor: $srsfield:[ModificationPromotor short: MPR] DF_ModificationAntagonist: $srsfield:[ModificationAntagonist short: MAN] DF_ModificationEffect: $srsfield:[ModificationEffect short: MOE] DF_EnzymeTreatment: $srsfield:[EnzymeTreatment short: TR] DF_TreatmentEffect: $srsfield:[TreatmentEffect short: EFF] DF_MolecularMass: $srsfield:[MolecularMass short: MM] DF_SedimentationConst: $srsfield:[SedimentationConst short: ESC] DF_SubunitMass: $srsfield:[SubunitMass short: SM] DF_SubunitSedimentationConst: $srsfield:[SubunitSedimentationConst short: SSC] DF_SubunitName: $srsfield:[SubunitName short: SUN] DF_SubunitDesignation: $srsfield:[SubunitDesignation short: SUD] DF_SubunitFunction: $srsfield:[SubunitFunction short: SUF] DF_SubunitNumber: $srsfield:[SubunitNumber short: SN] DF_SubunitComposition: $srsfield:[SubunitComposition short: SUC] DF_SubunitStructure: $srsfield:[SubunitStructure short: SUS] DF_SubunitBindingType: $srsfield:[SubunitBindingType short: SBT] DF_MolecularSymmetry: $srsfield:[MolecularSymmetry short: MS] DF_PolypeptideChainNumber: $srsfield:[PolypeptideChainNumber short: PCN] DF_ProstheticGroup: $srsfield:[ProstheticGroup short: PRG] DF_ProstheticGroupNumber: $srsfield:[ProstheticGroupNumber short: PGN] DF_BindingType: $srsfield:[BindingType short: BT] DF_SHGroupNumber: $srsfield:[SHGroupNumber short: SHN] DF_DisulfideBondNumber: $srsfield:[DisulfideBondNumber short: SSN] DF_BindingSiteName: $srsfield:[BindingSiteName short: SNA] DF_BindingSiteNumber: $srsfield:[BindingSiteNumber short: SNU] DF_SiteAminoAcidSequence: $srsfield:[SiteAminoAcidSequence short: SSQ] DF_BindingSiteResidual: $srsfield:[BindingSiteResidual short: SRE] DF_AminoAcids: $srsfield:[AminoAcids short: AA] DF_Content: $srsfield:[Content short: CNT] DF_AminoAcidSequenceOrCrossref: $srsfield:[AminoAcidSequenceOrCrossref short: AAS] DF_EnzymeComposition: $srsfield:[EnzymeComposition short: ENC] DF_TerminalAminoAcids: $srsfield:[TerminalAminoAcids short: TAA] DF_SignalPeptide: $srsfield:[SignalPeptide short: SP] DF_SignalPeptideLength: $srsfield:[SignalPeptideLength short: SPL] DF_IntramolecularLocation: $srsfield:[IntramolecularLocation short: LOC] DF_PrimaryStructureHomology: $srsfield:[PrimaryStructureHomology short: HOM] DF_EquilibConst: $srsfield:[EquilibConst short: KEQ] DF_EquilibConstFormula: $srsfield:[EquilibConstFormula short: KEF] DF_DissociationConstDesignation: $srsfield:[DissociationConstDesignation short: KDD] DF_DissociationConst: $srsfield:[DissociationConst short: KD] DF_AssociationConstDesignation: $srsfield:[AssociationConstDesignation short: KAD] DF_AssociationConst: $srsfield:[AssociationConst short: KAS] DF_EquilibConstDesignation: $srsfield:[EquilibConstDesignation short: KED] DF_ElementaryStepEquilibConst: $srsfield:[ElementaryStepEquilibConst short: KEE] DF_MassActionRatio: $srsfield:[MassActionRatio short: MAR] DF_StandardFreeEnergyChange: $srsfield:[StandardFreeEnergyChange short: DG0] DF_StandardEntropyChange: $srsfield:[StandardEntropyChange short: DS0] DF_StandardEnthalpyChange: $srsfield:[StandardEnthalpyChange short: DH0] DF_ActivationEnergy: $srsfield:[ActivationEnergy short: EA] DF_ActivationFreeEnergyChange: $srsfield:[ActivationFreeEnergyChange short: DGA] DF_ActivationEnthalpyChange: $srsfield:[ActivationEnthalpyChange short: DHA] DF_ActivationEntropyChange: $srsfield:[ActivationEntropyChange short: DSA] DF_StandardRedoxPotential: $srsfield:[StandardRedoxPotential short: E0] DF_ElectronTransferNumber: $srsfield:[ElectronTransferNumber short: ETN] DF_HeatCapacityChange: $srsfield:[HeatCapacityChange short: DCP] DF_IsoelectricPoint: $srsfield:[IsoelectricPoint short: IP] DF_OptimalPH: $srsfield:[OptimalPH short: PHO] DF_pHDependentParameter: $srsfield:[pHDependentParameter short: PHD] DF_pHRange: $srsfield:[pHRange short: PHR] DF_pKValues: $srsfield:[pKValues short: PKV] DF_InactivationConst: $srsfield:[InactivationConst short: IC] DF_OptimalTemperature: $srsfield:[OptimalTemperature short: TO] DF_TempDependentParameter: $srsfield:[TempDependentParameter short: TD] DF_TemperatureRange: $srsfield:[TemperatureRange short: TER] DF_TemperatureCoefficient: $srsfield:[TemperatureCoefficient short: Q10] DF_NameofParameterorVariable: $srsfield:[NameofParameterorVariable short: PAR] DF_ValueofParameterorVariable: $srsfield:[ValueofParameterorVariable short: VAL] DF_AbsorptionMaxWaveLength: $srsfield:[AbsorptionMaxWaveLength short: AM] DF_AbsorptionCoefficient: $srsfield:[AbsorptionCoefficient short: ABC] DF_MolarAbsorptionCoefficient: $srsfield:[MolarAbsorptionCoefficient short: MAC] DF_AbsorptionShoulder: $srsfield:[AbsorptionShoulder short: ASH] DF_FluorescenceMax: $srsfield:[FluorescenceMax short: FM] DF_CDSpectrumMax: $srsfield:[CDSpectrumMax short: CMA] DF_CDSpectrumMin: $srsfield:[CDSpectrumMin short: CMI] DF_CDSpectrumShoulder: $srsfield:[CDSpectrumShoulder short: CSH] DF_EPRSignals: $srsfield:[EPRSignals short: EPR] DF_Antigene: $srsfield:[Antigene short: AGN] DF_Antibody: $srsfield:[Antibody short: ABD] DF_CrossReactivity: $srsfield:[CrossReactivity short: CRR] DF_Abbreviation: $srsfield:[Abbreviation short: ABB] DF_Addition: $srsfield:[Addition short: ADD] DF_BiologicalFunction: $srsfield:[BiologicalFunction short: BFN] DF_Comments: $srsfield:[Comments short: COM] DF_Concentration: $srsfield:[Concentration short: CON] DF_Designation: $srsfield:[Designation short: DES] DF_Formula: $srsfield:[Formula short: FOR] DF_Method: $srsfield:[Method short: MT] DF_OscillationPeriod: $srsfield:[OscillationPeriod short: OP] DF_PhaseDifference: $srsfield:[PhaseDifference short: PDI] DF_Process: $srsfield:[Process short: PRS] DF_Property: $srsfield:[Property short: PRY] DF_SubstanceComposition: $srsfield:[SubstanceComposition short: SCN] DF_StandardDeviation: $srsfield:[StandardDeviation short: SD] DF_Substance: $srsfield:[Substance short: SUB] DF_Time: $srsfield:[Time short: TIM] DF_Type: $srsfield:[Type short: TYP] DF_Unit: $srsfield:[Unit short: UN] EMP_SYNTAX:$syntax:[file:"SRSDB:emp.is" ignore:" "] EMP_FILE:$filetype:[typename:bnk maxline:3000] $tags= { '**': 'Staff Footnote' '***': 'Annotators Footnote' A05: 'Half-Activating Concentration' AAB: 'Annotators Abstract' AA: 'Amino Acids' AAS: 'Amino Acid Sequence or Crossreference' AB: 'Abstract' ABB: 'Abbreviation' ABC: 'Absorption Coefficient' ABD: 'Antibody' AC: 'Activator' ACC: 'Apparent Catalytic Constant' ACT: 'Activation Type' AD: 'Activation Degree' ADD: 'Addition' AGE: 'Age' AGD: 'Alternative Gene Designation' AGE: 'Age' AGN: 'Antigene' ALG: 'Alternative gene name' AM: 'Absorption Maximum Wave Length' AMF: 'Alternative Multifunctional Enzyme Name' AN: 'Accession Number' APN: 'Alternative Pathway Name' APP: 'Enzyme Application' AR: 'Absolute Requirement' ASH: 'Absorption Shoulder' ASL: 'Active Site Location' ASS: 'Assay Conditions' AU: 'Author' BFN: 'Biological Function' BM: 'Maximum Specific Binding' BPA: 'Enzyme Binding Partner' BT: 'Binding Type' BUF: 'Buffer' CC: 'Category Code' CCC: 'Cell Culture Category' CD: 'Culture Density' CEF: 'Catalytic Efficiency' CEG: 'Coordinately Expressed Genes' CLI: 'Cell Line' CLV: 'Cloned Vector' CMA: 'CD Spectrum Maximum' CMI: 'CD Spectrum Minimum' CND: 'Conditions' CNT: 'Content' CO: 'Coenzyme' COL: 'Solution color' COM: 'Comments' CON: 'Concentration' CPE: 'Cell Cycle Period' CCP: 'Cell Cycle Phase' CRR: 'Cross-Reactivity' CS: 'Cell Species or Extracellular Fluid' CSH: 'CD Spectrum Shoulder' CSO: 'Carbon Source' CSZ: 'Colony Size' CTY: 'Cell Type' CUC: 'Cultivation Conditions' CUT: 'Cultivation Temperature' DAC: 'Degradation Activator' DCP: 'Heat Capacity Change' DES: 'Designation' DEV: 'Developmental Stage' DG0: 'Standard Free Energy Change' DGA: 'Activation Free Energy Change' DH0: 'Standard Enthalpy Change' DHA: 'Activation Enthalpy Change' DIN: 'Degradation Inhibitor' DR: 'Dilution Rate' DS0: 'Standard Entropy Change' DSA: 'Activation Entropy Change' DT: 'Document Type' E0: 'Standard Redox Potential' EA: 'Activation Energy' EC: 'Enzyme Code' ECO: 'Enzyme Concentration' EF: 'Enzyme Form' EFF: 'Treatment Effect' EN: 'Recommended Enzyme Name' ENC: 'Enzyme Composition' EPR: 'EPR Signals' ESC: 'Sedimentation Constant' ESE: 'Elementary Step Equation' ESR: 'unknown field-ESR' ETN: 'Electron Transfer Number' FL: 'Fixed Ligand' FM: 'Fluorescence Maximum' FOR: 'Formula' FUN: 'Functional Dependence' GCC: 'unknown field GCC' GEN: 'Gene Name' GET: 'Genotype' GL: 'Gene Location' GM: 'Growth Mode' GMP: 'Genetic Map Position' GN: 'Gene Designation' GNP: 'Gene Product' GP: 'Growth Phase' GRR: 'Growth Rate' GS: 'Growth Substrate' GT: 'Generation Time' GY: 'Growth Yield' HAB: 'unknown field-HAB' HAG: 'Host Age' HCC: 'Host Cell Culture Category' HCL: 'Host Cell Line' HCN: 'Host Common Name' HCS: 'Host Cell Species' HCT: 'Host Cell Type' HDS: 'Host Developmental Stage' HGT: 'Host Genotype' HMT: 'Host metabolic type' HOM: 'Primary Structure Homology' HPT: 'Host Phenotype' HSF: 'Host Subcellular Fraction' HSL: 'Host Cellular Location' HSN: 'Host Strain Name' HST: 'Laboratory Host Systematic Name' HSX: 'Host Sex' HTG: 'Host Taxonomic Group' HTR: 'Host Treatment' I05: 'Half-Inhibiting Concentration' IC: 'Inactivation Constant' ID: 'Inhibition Degree' IDE: 'Induction Degree' IN: 'Inhibitor' IND: 'Inducer' INT: 'Inhibition Type' IP: 'Isoelectric Point (pI)' IS: 'Ionic Strength' IT: 'Index Terms' IZN: 'Isozyme Number' KA: 'Activation Constant' KAD: 'Association Constant Designation' KAS: 'Association Constant' KC: 'Catalytic Constant' KCO: 'Keeping Conditions' KD: 'Dissociation Constant' KDD: 'Dissociation Constant Designation' KED: 'Equilibrium Constant Designation' KEE: 'Elementary Step Equilibrium Constant' KEF: 'Equilibrium Constant Formula' KEQ: 'Equilibrium Constant' KI: 'Inhibition Constant' KII: 'Intercept Inhibition Constant' KIS: 'Slope Inhibition Constant' KM: 'Michaelis Constant' KT: 'Type of Kinetics or Functional Dependence' LA: 'Language' LC: 'Light Conditions' LI: 'Light Intensity' LIG: 'Ligand' LOC: 'Intramolecular Location' LS: 'Limiting Substrate' LSO: 'Light source' MA: 'Molecular Activity' MAC: 'Molar Absorption Coefficient' MAD: 'Maximum Activation Degree' MAN: 'Modification Antagonist' MAR: 'Mass Action Ratio' MCC: 'Membrane carrier code' MCF: 'Membrane carrier form' MCN: 'Membrane carrier name' ME: 'Reaction Mechanism' MEC: 'Modifying Enzyme Code' MED: 'Cultivation Medium' MEF: 'Modifying Enzyme Form' MEN: 'Modifying Enzyme Name' MES: 'Metabolic State' MET: 'Metabolic Type' MF: 'Multifunctional Enzyme Name' MFC: 'Multifunctional Enzyme Code' MFF: 'Multifunctional Enzyme Form' MID: 'Maximum Inhibition Degree' MM: 'Molecular Mass' MME: 'Modification Mechanism' MOD: 'Enzyme Modifier' MOE: 'Modification Effect' MOR: 'unknown field-MOR' MOT: 'unknown field-MOT' MP: 'Enzyme Modification Process' MPR: 'Modification Promotor' MPW: 'Metabolic Pathway Name' MRE: 'Modification Residual' MS: 'Molecular Symmetry' MT: 'Method' NCF: 'Non-Catalytic Function' NCO: 'Non-Coenzyme' NH: 'Hills Number' NHO: 'Natural Host Systematic Name' NIC: 'Non-Influencing Compound' NPR: 'Non-Product' NS: 'Nucleotide Sequence Crossreference' NSO: 'Nitrogen Source' NSU: 'Non-Substrate' OC: 'Optimal Conditions' OCN: 'Organism Common Name' AGD: 'Alternative Gene Designation' ON: 'Other Enzyme Name' OP: 'Oscillation Period' OPN: 'unknown field OPN' OR: 'Organism Systematic Name' OS: 'Organizational Source' OTR: 'Organism Treatment' OVR: 'Overall Reaction' PA: 'Preparation Specific Activity' PAR: 'Name of Parameter or Variable' PAT: 'Pathology' PB: 'Preparation Specific Binding' PCN: 'Polypeptide Chain Number' PCO: 'Protein Concentration' PDI: 'Phase Difference' PF: 'Purification Factor and Purity Degree' PGN: 'Prosthetic Group Number' PH: 'pH Value' PHD: 'pH-Dependent Parameter' PHO: 'Optimal pH' PHR: 'pH Range' PHS: 'Physiological State' PHT: 'Phenotype' PHY: 'unknown Field' PKV: 'pK Values' PLO: 'Ploidy' PN: 'Protein Name' PR: 'Product' PRF: 'Protein Form' PRG: 'Prosthetic Group' PRI: 'Primer/Template' PRS: 'Process' PRY: 'Property' PS: 'Purification Steps' PSL: 'Polypeptide synthesis Location' PVM: 'Preparation Maximum Velocity' Q10: 'Temperature Coefficient' RA: 'Relative Activity' RC: 'Rate Constant' RCD: 'Rate Constant Designation' RD: 'Reaction Direction' RDE: 'Repression Degree' RE: 'Reaction Equation' REF: 'Reference' REP: 'Repressor' RET: 'Reaction_Type' REV: 'Reversibility' RI: 'Reaction Identifier' RL: 'Rate Law' RN: 'Reference Number' RP: 'Reaction Phase' RVM: 'Relative Maximum Velocity' S05: 'Half-Saturating Substrate Concentration' SA: 'Specific Activity' SAA: 'Site amino acid sequence' SB: 'Specific Binding' SBT: 'Subunit Binding Type' SC: 'Source Code' SCN: 'Substance Composition' SD: 'Standard Deviation' SEA: 'Site of Enzyme Action' SEN: 'Systematic Enzyme Name' SEX: 'Sex' SF: 'Subcellular Fraction' SGR: 'Specific Growth Rate' SHN: 'SH-Group Number' SL: 'Subcellular Location' SM: 'Subunit Mass' SN: 'Subunit Number' SNA: 'Binding Site Name' SNU: 'Binding Site Number' SO: 'Bibliographic Source' SP: 'Signal Peptide' SPL: 'Signal Peptide Length' SPN: 'Systematic Pathway Name' SRE: 'Binding Site Residual' SSC: 'Subunit Sedimentation constant' SSN: 'Disulfide Bond Number' SSP: 'Organism Subspecies' SSQ: 'Site Sequence' ST: 'Supplementary Terms' STA: 'Stabilizer' STO: 'Storage Conditions' STR: 'Strain' SU: 'Substrate' SUB: 'Substance' SUC: 'Subunit Composition' SUD: 'Subunit Designation' SUF: 'Subunit Function' SUN: 'Subunit Name' SUS: 'Subunit Structure' SYM: 'Synonyms' SYN: 'Type of Synthesis' T05: 'Half-Life Time' TA: 'Tissue Activity' TAA: 'Terminal Amino Acids' TC: 'Time Constant' TD: 'Temperature-Dependent Parameter' TEM: 'Temperature' TER: 'Temperature Range' TG: 'Taxonomic Group' TI: 'Title' TIM: 'Time' TO: 'Optimal Temperature' TOD: 'Time Of the Day' TPC: 'Total Protein Content' TR: 'Enzyme Treatment' TRT: 'Transition temperature' TYP: 'Type' UN: 'Unit' VAL: 'Value of Parameter or Variable' VEL: 'Overall Reaction Velocity' VL: 'Variable Ligand' VM: 'Maximum Reaction Velocity' WL: 'Wave Length' WT: 'Organism Weight' YD: 'Yield' YR: 'Publication Year' } $rules={ entry: ~ {$In:[file:text] $Out} (/[A-Z][A-Z]/ {$Not} ln)* (tag {pre {$Skip:0 $entryFip = $Fip} $Wrt} appLn ('#'{$not} appLn)* '#' ln? )? ~ # fields fields: ~ {$In:entry $Out $Skip:1} (tag {$c=$Ct $Wrt:$Ct } appLn (/[A-Z]/ {$Not} appLn)* | annot)+ ~ annot: ~ {$Wrt} '**' appLn ~ # indexing i_id: ~ {$Out:id $In:[fields c:AN]} /../ name {$Wrt} ~ i_str: ~ /a-zA-Z_/ ~ i_enzCode:~ {$Out:enzCode $In:[fields c:EC]} /.../ str {$Wrt} ~ i_words: ~ {$In:fields $Out:words pre{$Skip:0}} tag? i_word* ~ i_word: ~ ( /[0-9-]+\\.[0-9-]+\\.[0-9-]+\\.[0-9-]+/ {$Wrt:$Itc} | /[a-zA-Z0-9_-]+/ {$Uniq:$Itc} | /[^a-zA-Z0-9_-]+/ )+ ~ i_links: ~ {$In:fields $Out:links pre{$Skip:1}} /[A-Z]+/ { if:($Ct==MFC || $Ct==EC) {$Prod:ecLink} elif:$Ct==MPW $Prod:mpwLink } ~ ecLink: ~ /[A-Z ]+/ ec {$Wrt:enzyme} (/[:\/ ]+/ ec {$Wrt:enzyme})* ~ ec: ~ /[0-9-]+\\.[0-9-]+\\.[0-9-]+\\.[0-9-]+/ ~ mpwLink: ~ /MPW G +/ /[A-Z0-9]+\\.[A-Z0-9]+/ {$Wrt:mpw} ~ # html display h_field: ~ {$In:[fields t:hl]} tag {$t=$tags.$Ct if:$ParInt:isTable $Rep:"" else $Rep:"
    $t
    " } (h_Ttable | h_Mtable | (h_word '\n')+) ~ h_Mtable: ~ 'M '{$Rep:"
    "} h_tabhdr ('//'{$Rep:"
    "} h_Mtabrow)* x{$Rep:[s:"
    "]}~ h_Mtabrow:~ (/[^!\n]+/ ('!!' {$Rep:""})?)* '\n'{$Rep:"\n"}~ h_Ttabbeg:~ ('T ' | 'R ' | 'E ' | 'G ' | 'F ') ~ h_Ttable: ~ h_Ttabbeg {$Rep:"
    "} h_tabhdr ('//'{$Rep:"
    "} h_Ttabrow)* x{$Rep:[s:"
    "]}~ h_Ttabrow:~ (h_word ('!!' {$Rep:""})?)* '\n'{$Rep:"\n"} ~ h_tabhdr: ~ (h_word ('!!' {$Rep:""})?)* '\n'{$Rep:"\n"} ~ h_word: ~ ( (/(EC_)?[0-9-]+\\.[0-9-]+\\.[0-9-]+\\.[0-9-]+/ {$Rep:{$ParStr:enzymeR $Ct $Ct}} (/([^0-9])([0-9-]+\\.[0-9-]+\\.[0-9-]+\\.[0-9-]+)/ {$Rep:{$ParStr:enzymeR $Ct $Ct}})*) | /(SWISS-PROT)_([A-Z0-9]+)/{$Rep:{"$1\:($ParStr:swissR)" $2 $2}}| /(PIR)_([A-Z0-9]+)/ {$Rep:{"$1\:($ParStr:pirR)" $2 $2}} | /(EMBL)_([A-Z0-9]+)/ {$Rep:{"$1\:($ParStr:emblR)" $2 $2}} | /(GenBank)_([A-Z0-9]+)/ {$Rep:{"$1\:($ParStr:genbankR)" $2 $2}}| /[^[(`' !<>\n_]+/ | /\\[(\\*[^]]*)\\]/ {$Rep:"$1"} | /`([a-zA-Z0-9]+)`/ {$Rep:"$1"} | /'([a-zA-Z0-9]+)'/ {$Rep:"$1"} | /\\(,([^)]+)\\)/ {$Rep:"$1"} | /\\('([^')]+)\\)/ {$Rep:"$1"} | '<' {$Rep:"<"} | '>' {$Rep:">"} | '_' {$Rep:' '} | /[[(`']/ )+ ~ h_head: ~ {$In:[fields c:head t:hl]} /.*/ {$Rep:"
    \n"} ~ h_tail: ~ {$In:[fields c:tail t:hl]} /.*/ {$Rep:"\n
    \n"} ~ h_pathway:~ {$In:[fields c:MPW t:hl]} /.* */ /[0-9A-Z]+\\.[0-9A-Z]+/ {$Rep:{$ParStr:mpwR $Ct $Ct}} ~ # other tag: ~ /[A-Z\*][0-9A-Z\*]+/ ~ appLn: ~ /[^\n]*\n/ {$App} ~ more: ~ (/ [^\n]*\n/)* ~ name: ~ /[A-Z0-9a-z-]+/ ~ str: ~ /[^\t \n]*/ ~ ln: ~ /[^\n]*\n/ ~ } #$fil = $fileOpen:"/opt/srs/data/emp/9311.bnk" #$job = $jobNew:[prod:$rules skip:" "] # #$jobNext:[$job file:$fil] #while:$jobTokens:[$job name:links print:1] { # $jobEnd:$job # $jobNext:[$job file:$fil] # $print:|\n====================\n #} # $RCSfile: enzyme.i,v $ # $Revision: 1.5 $ # $Date: 1996/08/12 19:04:40 $ # # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENZYME_DB:$library:[ENZYME group:@SEQRELATED_LIBS comment:" - A. Bairoch" format:@ENZYME_FORMAT maxNameLen:10 ifiles:{"enzyme.i" "enzyme.is"} files:{ $file:enzyme } ] ENZYME_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@ENZYME_SYNTAX tableFormat:left fields:{ $field:@DF_ALL $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_AltName code:altnam index:str indexToken:i_altnam tableToken:t_altnam] $field:[@DF_Description code:des index:str indexToken:i_des tableToken:t_des] $field:[@DF_CatActivity code:i_catact tableToken:t_catact] $field:[@DF_COMMENT code:cc] $field:[@DF_LINK index:link code:link indexToken:links] } ] ENZYME_SYNTAX:$syntax:[file:"SRSDB:enzyme.is" ignore:" "] DF_CatActivity:$srsfield:[CatalyticActivity short:cat group:@DF_ALL] DF_AltName:$srsfield:[AltName short:alt group:@DF_ALL] #$link:[@ENZYME_DB to:@?SWISSPROT_DB token:'links|swiss' toField:@DF_ACCNO] $link:[@ENZYME_DB to:@?PROSITEDOC_DB token:'links|pr' toField:@DF_ID] # # enzyme databank # # Ramu C # $rules={ entry: ~ {$In:[file:text] $Out} ('ID' {$Not} ln)* ('ID ' {$entryFip=$fip $Wrt} ln {$App} ('ID' {$Not} ln {$App})*)? ~ # fields fields: ~ {$In:entry $Out} f_id des altNam catact f_cf f_cc f_di f_links ~ f_id: ~ {$Wrt:id} 'ID ' ln ~ des: ~ {$Wrt:des} ('DE ' ln)* ~ altNam: ~ {$Wrt:altnam}('AN ' ln)* ~ catact: ~ {$Wrt:catact} ('CA ' ln)* ~ f_cf: ~ {$Wrt:cf} ('CF ' ln)* ~ f_cc: ~ {$Wrt:cc} ('CC ' ln)* ~ f_di: ~ {$Wrt:di} ('DI ' ln)* ~ f_links: ~ {$Wrt:link} (/(DR|PR) / ln)* ~ # indexing id: ~ {$In:[fields c:id] $Out:id} 'ID' /[0-9.]+/ {$Wrt} ~ i_des: ~ {$In:[fields c:des] $Out} ('DE' ( /[A-Za-z0-9_]+/ {$Wrt} | /[^A-Za-z0-9_]+/ )* )* ~ i_altnam: ~ {$In:[fields c:altnam] $Out} ('AN' ( /[A-Za-z0-9_]+/ {$Wrt} | /[^A-Za-z0-9_]+/ )* )* ~ i_catact: ~ {$In:[fields c:catact] $Out} 'CA' /[A-Z0-9_]+/ {$Wrt} ~ cf: ~ {$In:[fields c:cf] $Out:cf} 'CF' /[A-Z0-9_]+/ {$Wrt} ~ cc: ~ {$In:[fields c:cc] $Out:cc} 'CC' /[A-Z0-9_]+/ {$Wrt} ~ di: ~ {$In:[fields c:di] $Out:di} 'DI' /[A-Z0-9_]+/ {$Wrt} ~ links: ~ {$In:[fields c:link] $Out} (/DR/ (name {$Wrt:swiss} ',' name ';')*)* (/PR/ 'PROSITE;' name {$Wrt:pr} ';'?)* ~ # table display t_catact: ~ {$In:[fields c:catact] $Out} /../ ln {$Wrt} (/../ ln {$App})* ~ t_des: ~ {$In:[fields c:des] $Out} /../ ln {$Wrt} (/../ ln {$App})* ~ t_altnam: ~ {$In:[fields c:altnam] $Out} /../ ln {$Wrt} (/../ ln {$App})* ~ # html display hl_links: ~ {$In:[fields c:link t:hl]} ( (/DR/ (name {$Rep:{$ParStr:swissR $Ct $Ct}}',' name ';')* ln) | (/PR/ name ';' name {$Rep:{$ParStr:prositedocR $Ct $Ct}} ln) )* ~ # other name: ~ /[a-zA-Z0-9_]+/ ~ ln: ~ /[^\n]*\n/ ~ } #$fil = $fileOpen:"/data/enzyme/enzyme.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #for:{1 $jobTokens:[$job name:des print:1 ] 1} { # $jobEnd:$job # $jobNext:[$job file:$fil] #} #$jobEnd:$job # # $RCSfile: enzyme.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:48 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The ENZYME data bank contains the following data for each type of |characterized enzyme for which an EC number has been provided: EC number, |Recommended name, |Alternative names, Catalytic activity, Cofactors, Pointers to the SWISS-PROT |entrie(s) |that correspond to the enzyme, Pointers to disease(s) associated with a |deficiency of the enzyme. | |

    more: |

    |More on ENZYME |

    citation: | Reference: |Bairoch A. (1993) The ENZYME data bank. Nucleic Acids Res, Jul |1;21(13):3155-6. ftpSite:'' fields:{ ID: |

    Enzyme ID Field

    |The ID (IDentification) line is always the first line of an entry. The |format of the ID line is: |

    |ID EC NUMBER |

    Description: |

    Enzyme Description Field

    | The DE (DEscription) line(s) contain the NC-IUB recommended name for an | enzyme. The format of the DE line is: |

    | DE DESCRIPTION. |

    | Important note: enzymes are sometimes deleted from the EC list, others | are renumbered; however the NC-IUBMB does not allocate the old numbers | to new enzymes. Obsolete EC numbers are indicated in this data bank by | the following DE line syntaxes. For deleted enzymes: |

    | DE DELETED ENTRY. |

    | and for renumbered enzymes: |

    | DE TRANSFERRED ENTRY: x.x.x.x. |

    | where x.x.x.x is the new, valid, EC number; as shown in the following | example: |

    | DE TRANSFERRED ENTRY: 1.7.99.5. AltName: |

    Enzyme AltName Field

    | The AN (Alternate Name) line(s) are used to indicate the different | name(s), other than the NC-IUBMB recommended name, that are used in the | literature to describe an enzyme. The format of the AN line is: |

    | AN NAME. |

    Reaction: |

    Enzyme Reaction Field

    | The CA (Catalytic Activity) line(s) are used to indicate the reaction(s) | catalyzed by an enzyme. The format of the CA line is: |

    | CA REACTION. |

    | Where the reaction is indicated following the recommendations of the NC- | IUBMB. The majority of the reactions are described using a standard | chemical reaction format: |

    | CA SUBSTRATE_11 + SUBSTRATE_12 [+ SUBSTRATE_1N...] = SUBSTRATE_21 + | CA SUBSTRATE_22 [+ SUBSTRATE_2N]. |

    | As shown in the following examples: |

    | CA L-MALATE + NAD(+) = OXALOACETATE + NADH. |

    | CA 2 ATP + GLUTAMINE + CO(2) + H(2)O = 2 ADP + ORTHOPHOSPHATE + | CA GLUTAMATE + CARBAMOYL PHOSPHATE. |

    | In some cases free text is used to describe a reaction. As shown in the | following examples: |

    | CA DEGRADES STARCH TO CYCLODEXTRINS BY FORMATION OF A 1,4-ALPHA-D- | CA GLUCOSIDIC BOND. |

    | CA CLEAVES LEU-|-LEU BOND IN ANGIOTENSINOGEN TO GENERATE | CA ANGIOTENSIN I. |

    | Notes |

    | - Subscript and superscript are indicated between brackets: for example | NAD+ and NADP+ are indicated as NAD(+) and NADP(+), H2O as H(2)O, CO2 | as CO(2), etc. | - Greek letters are spelled out. |

    Cofactor: |

    Enzyme Cofactor Field

    | The CO (CoFactor) line(s) are used to indicate which cofactor(s) are | required by an enzyme. The format of the CF line is: |

    | CF COFACTOR_1; COFACTOR_2 OR COFACTOR_3[; COFACTOR_N...]. |

    Comments: |

    Enzyme Comments Field

    | The CC lines are free text comments on the entry, and may be used to | convey any useful information. |

    Disease: |

    Enzyme Disease Field

    | The DI (DIsease) line(s) are used to indicate the known disases(s) | associated with a deficiency of the enzyme. Currently this information | is only given for human diseases listed in the MIM book [2]. |

    | [2] McKusick V.A. | Mendelian Inheritance in Man | Catalogs of autosomal dominant, autosomal recessive, and X-linked | phenotypes | Tenth edition | Johns Hopkins University Press, Baltimore, (1991). |

    | The format of the DI line is: |

    | DI DISEASE_NAME; MIM:NUMBER. |

    | Where 'NUMBER' is the MIM catalog number of the disease (or phenotype). |

    Ref: |

    Enzyme Ref Field

    | The DR (Data bank Reference) line(s) are used as pointers to the SWISS- | PROT entries that corresponds to the enzyme being described. The format | of the DR line is: |

    | DR AC_NB, ENTRY_NAME; AC_NB, ENTRY_NAME; AC_NB, ENTRY_NAME; |

    | where: |

    | - 'AC_NB' is the SWISS-PROT primary accession number of the entry to | which reference is being made. | - 'ENTRY_NAME' is the SWISS-PROT entry name. |

    } date: |25 Jul 1996 signature: |Anatoly Ulyanov } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSfile: epd.i,v $ # $Revision: 1.3 $ # $Date: 1996/07/24 22:19:17 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EPD_DB:$library:[EPD group:@SEQRELATED_LIBS comment:"Eukariotic Promoter Database - Philipp Bucher (1996)" format:@EPD_FORMAT cachesize:512 ifiles:{"epd.i" "epd.is"} files:{ $file:epd } ] EPD_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@EPD_SYNTAX fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_LINK code:link index:link indexToken:links] $field:[@DF_Organism code:source index:str indexToken:source tableToken:t_source tableFormat:left] $field:[@DF_Product code:prod index:str indexToken:product tableToken:t_product tableFormat:left] $field:[@DF_Protocol code:prtcl index:str indexToken:protocol tableToken:t_protocol tableFormat:center] $field:[@DF_Express code:exprs index:str indexToken:express tableToken:t_express tableFormat:center] } ] EPD_SYNTAX:$syntax:[file:"SRSDB:epd.is" ignore:" \t"] $link:[@EPD_DB to:@?EMBL_DB toField:@DF_ACCNO] DF_Product: $srsfield:[GeneProduct short:pro group:@DF_ALL] DF_Protocol:$srsfield:[ExpProtocol short:ptc group:@DF_ALL] DF_Express: $srsfield:[ExpresRegul short:ess group:@DF_ALL] specie: { # Code Scientific name (English name) # AAV2: 'Adeno-associated virus 2' Ac: 'Aplysia californica (gastropod mollusk)' AcNPV: 'Autographa californica nuclear polyhedrosis virus' Ad2: 'Human adenovirus type 2' Ad5: 'Human adenovirus type 5' Ad7: 'Human adenovirus type 7' Ad12: 'Human adenovirus type 12' Ag: 'Ateles geoffroyi (spider monkey)' ALV: 'Avian leukemia virus' Am: 'Antirrhinum majus (snapdragon)' 'A-MLV': 'Abelson murine leukemia virus' Apo: 'Antheraea polyphemus (silkmoth)' Ap: 'Anas platyrhynchos (mallard, domestic duck)' As: 'Avena sativa' At: 'Agrobacterium tumefaciens' Ath: 'Arabidopsis thaliana (fam. cruciferae)' Atr: 'Aotus trivirgatus (owl or night monkey)' Ay: 'Antheraea yamamai (Japanese oak silkmoth)' B19: 'Human parvovirus B19' Be: 'Bertholletia excelsa (Brazil nut)' BKV: '(Human) papovavirus BK' BLV: 'Bovine leukemia virus' Bm: 'Bombyx mori (silkmoth)' Bn: 'Brassica napus (rape)' BPV1: 'Bovine papilloma virus type 1' Bt: 'Bos taurus (cattle)' C4BP: 'Complement component C4b-binding protein' CaMV: 'Cauliflower mosaic virus' Cc: 'Cricetus cricetus (Chinese hamster)' Cco: 'Coturnix coturnix (Quail)' Ce: 'Caenorhabditis elegans (nematode)' Cg: 'Canavalia gladiata (Japanese jackbean)' Ch: 'Capra hircus (goat)' Cl: 'Canis lupus (dog)' Cm: 'Cairina moschata (muscovy duck)' Cp: 'Cavia porcellus (guinea pig)' Cpe: 'Cucurbita pepo (zucchini)' Ct: 'Chironomus thummi (midge)' Cte: 'Chironomus tentans (midge)' DAF: 'Decay-accelerating factor' Dc: 'Daucus carota (carrot)' Df: 'Drosophila funebris (fruit fly)' Dh: 'Drosophila hydei (fruit fly)' DHBV: 'Duck hepatitis virus' Dm: 'Drosophila melanogaster (fruit fly)' Dma: 'Drosophila mauritiana (fruit fly)' Dmo: 'Drosophila mojavensis (fruit fly)' Dmu: 'Drosophila mulleri (fruit fly)' Do: 'Drosophila orena (fruit fly)' Dp: 'Drosophila pseudoobscura (fruit fly)' Ds: 'Drosophila simulans (fruit fly)' Dse: 'Drosophila sechellia (fruit fly)' Dv: 'Drosophila virilis (fruit fly)' EBV: '(Human) Epstein-Barr virus' Ec: 'Equus caballus (horse)' 'FBJ-MSV': 'Finkel-Biskis-Jinkins murine osteosarcoma virus' 'FBR-MSV': 'Finkel-Biskis-Reilly murine osteosarcoma virus' 'F-MCF': '(Murine) Friend mink cell focus-inducing virus' Fs: 'Felis silvestris (cat)' 'F-SFFV': '(Murine) Friend spleen focus forming virus' Ft: 'Flaveria trinervia (dicot plant)' 'GA-FeLV': 'Gardner-Arnstein feline leukemia virus' GALV: 'Gibbon ape leukemia virus' Gg: 'Gallus gallus (chicken)' Ggo: 'Gorilla gorilla (gorilla)' Gm: 'Glycine max (soybean)' GSHV: 'Ground squirrel hepatitis virus' 'H-1': '(Murine) H-1 parvovirus' Ha: 'Helianthus annuus (sunflower)' Hb: 'Hevea brasiliensis (para rubber tree)' HBV: 'Human hepatitis B virus' HCMV: 'Human cytomegalovirus' Hg: 'Halichoerus grypus (grey seal)' 'HIV-1': 'Human immunodeficiency virus type 1' 'HIV-2': 'Human immunodeficiency virus type 2' HPV16: 'Human Pappilloma virus 16' HPV18: 'Human Pappilloma virus 18' Hs: 'Homo sapiens (man)' 'HSV-1': 'Human herpes simplex virus type 1' 'HSV-2': 'Human herpes simplex virus type 2' 'HTLV-I': 'Human T-cell leukemia virus type I' 'HTLV-II': 'Human T-cell leukemia virus type II' Hv: 'Hordeum vulgare (barley)' HVS: 'Herpesvirus saimiri' JCV: '(Human) papovavirus JC' Le: 'Lycopersicon esculentum (tomato)' Leu: 'Lepus europeaeus (hare)' Lm: 'Locusta migratoria' Lp: 'Lytechinus pictus (sea urchin)' Lpe: 'Lycopersicon peruvianum (wild tomato)' Lv: 'Lytechinus variegatus (sea urchin)' Ma: 'Mesocricetus aureus (golden hamster)' Mc: 'Macaca cynomolgus (macaque)' MCF: 'Mink cell focus-inducing virus' MCMV: 'Murine cytomegalovirus' MLV: 'Murine leukemia virus' Mm: 'Mus musculus (mouse)' 'M-MLV': 'Moloney murine leukemia virus' 'M-MSV': 'Moloney murine sarcoma virus' MMTV: 'Mouse mammary tumor virus' Ms: 'Medicago sativa (alfalfa)' MSV: 'Maize streak virus' Np: 'Nicotiana plumbaginifolia (leadwort-leaved tobacco)' Ns: 'Nicotiana silvestris (wood tobacco)' Nt: 'Nicotiana tabacum (tobacco)' Nto: 'Nicotiana tomentosiformis' Oa: 'Ovis aries (sheep)' Oc: 'Oryctolagus cuniculus (rabbit)' Os: 'Oryza sativa (rice)' Ph: 'Petunia hybrida (e.g. Petunia strain Mitchell)' Pa: 'Papio anubis (olive baboon)' Pc: 'Petroselinum crispum (parsley)' Pl: 'Paracentrotus lividus (sea urchin)' Pm: 'Psammechinus miliaris (sea urchin)' Polyoma: '(Murine) polyoma virus' Ppy: 'Photinus pyralis' Pp: 'Pongo pygmaeus (orangutan)' Ps: 'Pisum sativum (pea)' Pt: 'Pan troglodytes (chimpanzee)' Pth: 'Pinus thunbergii (Japanese black pine)' Pv: 'Phaseolus vulgaris (french bean, kidney bean)' RAV2: '(Avian) Rous associated virus type 2' Rc: 'Ricinus communis' 'R-MCF': '(Murine) Rauscher mink cell focus-inducing virus' Rn: 'Rattus norvegicus (rat)' RSV: '(Avian) Rous sarcoma virus' Sa: 'Sinapis alba (white mustard)' SA7P: 'Simian adenovirus 7P' Sd: 'Strongylocentrotus drobachiensis (sea urchin)' Se: 'Spalax ehrenbergi (blind mole rat)' Sg: 'Salmo gairdneri (rainbow trout)' 'SIV-III': 'Simian immunodeficiency virus type III' SNV: '(Avian) spleen necrosis virus' So: 'Spinacia oleracea (spinach)' Sp: 'Strongylocentrotus purpureatus (sea urchin)' Spe: 'Sarcophaga peregrina (flesh fly)' Sr: 'Sesbania rostrata' Ss: 'Sus scrofa (pig)' SSV: 'Simian sarcoma virus' St: 'Solanum tuberosum (potato)' Sv: 'Sorghum vulgare (sorghum)' SV40: 'Simian virus 40' Ta: 'Triticum aestivum (wheat)' Visna: 'Visna lentivirus' Xb: 'Xenopus borealis (Kenyan clawed frog)' Xl: 'Xenopus laevis (African clawed frog)' Xt: 'Xenopus tropicalis (western clawed frog)' Zm: 'Zea mays (maize)' } # iGene Product Abbreviations # product: { '1-25OH2D3': '1,25-(OH)_2 vitamin D_3' '20-OHE': '20-Hydroxyecdysone' 4CL: '4-coumarate coenzyme A ligase' a1: 'Gene locus 1 involved in anthocyanin biosynthesis' 'abd-g.': 'Abdominal ganglion' abl: 'Abelson murine leukemia virus oncogene' ACC: '1-aminocyclopropane-1-carboxylic acid' AChR: 'Acetylcholin receptor' ACP: 'b^-ketoacyl-acyl carrier protein of fatty acid synthase' ACTH: 'Adrenocorticotropic hormone' ADA: 'Adenosine deaminase' ADH: 'Alcohol dehydrogenase' 'ADPg-s': 'GT ADPglucose-starch glucosyltransferase' 'adult-HA': 'Adult hermaphrodite' AFW1: 'Adult fast-white (myosin heavy chain) 1' Ag: 'Antigen' '(AGM)': '"from african green monkey"' AGP: 'Acid glycoprotein' AGPP: 'ADP glucose pyrophosphorylase' AIRS: 'Aminoimidazole ribonucleotide synthase' 'ALA-synt.': '5-Aminolevulinate synthase' ALDH_2: 'Aldehyde dehydrogenase 2' AlkExo: 'Alkaline exonuclease' Amy: 'Amylase' antp: '"antennapedia" locus' aP2: 'Adipocyte homologue of myelin P2' 'apolipop.': 'Apolipoprotein' apoVLDLII: 'Very low densitiy apolipoprotein II' APRT: 'Adenine phosphoribosyltransferase' AR: 'Adrenergic receptor' ARF: 'ADP-ribosylation factor' arg: 'Arginine' AS: 'Argininosuccinate synthetase' 'AS-C': '"achaete-scute" complex locus' AspAT: 'Aspartate aminotransferase' 'ass.': 'Associated' AT: 'Antitrypsin' ATIII: 'Antithrombin III' ATCase: 'Aspartate transcarbamylase' ATP: 'Adenosinetriphosphate' awd: '"abnormal wing disk" locus' BB: 'Bowman-Birk (protease inhibitor)' BCKDHA: 'Branched-chain alpha-keto acid dehydrogenase complex' 'Bcl-2': 'B-cell leukemia/lymphoma 2 proto-oncogene' BPTI: 'Bovine pancreatic trypsin inhibitor' BSF: 'B-cell stimulating factor' bsg25D: 'Blastoderm specific locus 25D' 'c-': 'Cellular protooncogene ' c1: 'Regulatory locus of anthocyanin synthesis (maize)' CA: 'Carbonic anhydrase' cab: 'Chlorophyll a/b-binding protein' cAMP: 'Cyclic AMP (Adenosinemonophosphate)' 'card-m': 'Cardiac muscle' 'cc-ind.': 'Cell cycle-independent' CD3: 'T-cell differentiation antigen CD3' CD4: 'T-cell differentiation antigen CD4' CD8: 'T-cell differentiation antigen CD8' CEA: 'Carcinoembryonic antigen' CG: 'Chorionic gonadotropin' CNS: 'Central nervous system' CNTF: 'Ciliary neurotrophic factor' 'car.': 'Cartilage' 'col.': 'Collagen' 'conglyc.': 'Conglycinin' 'cor.': 'Cornea' 'cotyl.': 'Cotyledon' cp: 'Cytoplasm(ic)' CPS: 'Carbamyl-phosphate synthetase' CRF: 'Corticotropin-releasing factor' CRP: 'C-reactive protein' cs: 'Cytosol(ic)' CSF: 'Colony stimulating facter' cyt: 'Cytokinin gene (coding for isopentenyltransferase)' dbp: 'DNA binding protein' DDC: 'DOPA decarboxylase' 'dep.': 'dependent' 'dev.': 'Development(ally)' DHFR: 'Dihydrofolate reductase' 'diff.': 'differentiation, differentiated' 'DL/R': 'Left and right duplicated region' dUTPase: 'Deoxyuridinetriphosphatase' E: '1. Early, 2. Erythroid cell-specific' E8: 'Ethylene inducible gene during fruit ripening 8' EAS: '5-epi-aristolochene synthase (sesquiterpene cyclase)' EBNA: 'Epstein-Barr virus nuclear antigens' 'ecd-ind.': 'Ecdysone-inducible' EDF: 'Eosinophil differentiation factor' EFW1: 'Embryonic fast-white (myosin heavy chain) 1' EGF: 'Epidermal growth factor' EIa: 'Adenovirus early Ia region (transactivating element)' Eip: 'Ecdysone-induced protein' ELH: 'Egg-laying hormone' em: 'Embryo, embryonic' EPSP: '5-Enolpyruvylshikimate-3-phosphate' erbA: '(Avian) erythroblastosis virus oncogene A' erbB: '(Avian) erythroblastosis virus oncogene B' 'E-resp.': 'Estrogen-responsive' ERV3: 'Endogenous retrovirus 3' 'E.Tn': 'Early transposon' 'et-hypocot.': 'Etiolated hypocotyl' ev1: '(Avian) endogenous virus 1' eve: '"even-skipped" locus' 'exch.': 'Exchanger' 'f.': 'Factor' 'fibrob.': 'Fibroblasts' FMRFamide: 'Phe-Met-Arg-Phe-NH(2) neuropeptide' FNR: 'Ferredoxin-(NADP+)-oxidoreductase' fos: 'FBJ (Finkel-Biskis-Jinkins) osteosarcoma virus oncogene' FSH: 'Follicle stimulating hormone' ftz: '"fushi tarazu" locus' 'g.': 'Gene' G0S: 'G0/G1 switch regulatory gene ' G6PD: 'Glucose-6-phosphate dehydrogenase' GA: 'Gibberellic acid' GADPH: 'Glyceraldehyde-3-phosphate dehydrogenase' GARS: 'Glycinamide ribonucleotide synthase' Gart: '"Gart" locus (-> GARS, AIRS, GART)' GART: 'Glycinamide ribonucleotide transformylase' gC: 'Glycoprotein C' 'G-CSF': 'Granulocyte colony stimulating factor' gD: 'Glycoprotein D' GdX: 'X-linked gene downstream of G6PD gene' gE: 'Glycoprotein E' GFAP: 'Glial fibrillary acidic protein' gln: 'Glutamine' 'globul-12s': '12s globulin (oat seed storage protein)' glucc: 'Glucocorticoid' GLUT1: 'Glucose transporter type 1' 'GM-CSF': 'Granulocyte/Macrophage colony stimulating factor' GnRH: 'Gonadotropin-releasing hormone' gp: 'Glycoprotein' GPD: 'Glycerol-3-phosphate dehydrogenase' GRF: 'Growth hormone-releasing factor' GRP: 'Glycine-rich (cell wall) protein' GS17: 'Gastrula-specific transcript 17' GSHPx: 'Gluthathione peroxidase' 'G-spec.': 'Gastrula-specific' GST: 'Gutathione S-transferase' H: '1. Heavy chain, 2. Housekeeping-type promoter' 'Ha-ras': 'Rat-derived Harvey murine sarcoma virus oncogene' hb: '"hunchbank" locus' Hc: 'High-cysteine (chorion protein)' HGT: 'High-(glycine+tyrosine) keratin' 'hist.': 'Histone' 'HMG-': 'High mobility group chromosomal protein' 'HMG-CoA': '3-Hydroxy-3-methylglutaryl coenzyme A' HPRT: 'Hypoxanthine phosphoribosyltransferase' hs: 'Heatshock' hsc: 'Constitutive analogue of heatshock gene/protein' HSF: 'Hepatocyte-stimulating factor' hsp: 'Heatshock protein' HTF: 'Restriction endonuclease HpaII tiny fragments' 'I-FABP': 'Intestinal fatty-acid binding protein' IAA: 'Indolacetic acid' IAP: 'Intracisternal A-particles' ICP: 'Infected cell protein' IE: 'Immediate early (gene, RNA)' IF: 'Intermediate filament' IFI: 'Interferon-induced gene/protein' IFN: 'Interferon' Ig: 'Immunoglobulin' IGF: 'Insulin-like growth factor' IL: 'Interleukin' 'inf.': 'Infected' 'inh.': 'Inhibitor' ISG: 'Interferon-stimulated gene' 'k.': 'Kinase' 'Ki-ras': 'Rat-derived Kirsten murine sarcoma virus oncogene' L: '1. Light chain; 2. Late' larva: 'instar larva' LAT: 'Lycopersicon anther-specific gene ' LCAT: 'Lecithin-cholesterol acyltransferase' LDH: 'Lactate dehydrogenase' 'leghem.': 'Leghemoglobin' LeIF: 'Leukocyte interferon' LH: 'Luteinizing hormone' LHC: 'Light-harvesting complex' LHRH: 'Luteinizing hormone-releasing factor' LMW: 'Low molecular weight' LPH: 'Lipotropic hormone' LPS: 'Lipopolysaccharide' MBP: 'Myelin basic protein' '(MAC)': 'Macaque' MC: 'Methylcholanthrene' MCK: 'Muscle-specific creatine kinase' mGK: 'Submaxillary gland kallikrein' 'MHCI/MHCII': 'Class I/II transplantation antigens of major histocompatibility complex' MIF: 'Macrophage migration inhibitory factor' mit: 'Mitochondrial' 'mononuc-c.': 'Mononuclear cells' MOPC: 'Mineral oil-induced plasmacytoma' mos: 'Moloney murine sarcoma virus oncogene' MP: 'Macrophage' MPC: 'Mouse plasma cell tumor' MRP: 'MIF-related protein (see MIF)' MSF: 'Megakaryocyte stimulating factor' msp: 'Major sperm protein gene' MT: 'Metallothionein' mst: 'Male-specific transcript' MUP: 'Major urinary protein' myb: '(Avian) myeoloblastosis virus oncogene' myc: 'Myelocytomatosis virus 29 oncogene' NCA: 'nonspecific cross-reacting (with -> CEA) antigen' neu: 'Ethyl-nitrosurea-induced rat neuroblastoma oncogene' 'neuropep.': 'Neuropeptide' NGF: 'Nerve growth factor' ninaE: '"neither inactivation nor afterpotential" locus E' NMDH: 'NADP-malate dehydrogenase' nos: 'Nopaline synthetase' NR: 'Nitrate reductase' 'N-ras': 'Neuroblastoma ras-like (-> Ha-ras) oncogene' NS: 'Nervous system' OAT: 'Ornithine aminotransferase' ocs: 'Octopine synthetase' ODC: 'Ornithine decarboxylase' Ori: 'Origin of replication' OTC: 'Ornithine transcarbamylase' 'ovalb.': 'Ovalbumin' 'p.': 'Protein' 'P-450': 'Cytochrome P-450' p53: '53K phosphoprotein' 'panc.': 'pancreas, pancreatic' 'parath.': 'Parathyroid' PB: 'Phenobarbital' PBGD: 'Porphobilinogen deaminase' PCNA: 'Proliferating cell nuclear antigen' PDGF: 'Platelet-derived growth factor' PEPCase: 'Phosphoenolpyruvate carboxylase' PEPCK: 'Phosphoenolpyruvate carboxykinase' PG: 'Prostaglandin' PGK: '3-Phosphoglycerate kinase' PHA: 'Phytohemagglutinin' PK: 'Protein kinase' P_L: 'Late promoter' PLP: 'Proteolipid protein' POL: 'Polymerase' POMC: 'Proopiomelanocortin' pp: 'Phosphoprotein ' PR1a: 'Pathogenesis-related protein 1a' PRBP: 'Plasma retinol-binding protein' PRL: 'Prolactin' 'prog.': 'Progesterone' prolyl: '4-hydr. Prolyl 4-hydroxylase' PrP: 'Prion protein' PSG: 'Pregnancy-specific glycoproteins ' PSBP: 'Prostatic steroid binding protein' PSP: 'Parotid secretory protein' PTH: 'Parathyroid hormone' pTiN: 'Nopaline type tumor inducing plasmid' pTiO: 'Octopine type tumor inducing plasmid' r: '"rudimentary" locus' R: '1. Regulatory subunit, 2. Erythroid cell-specific' RAB: 'Gene responsive to ABA' ras: 'Homologue of -> Ha-ras, Ki-ras, etc.' 'rec.': 'Receptor' 'red.': 'Reductase' 'reg.': 'Regulated' 'rep-dep.': 'Replication-dependent' rig: 'Rat insulinoma gene' RnBP: 'Renin-binding protein' RNR2: 'Ribonucleotide reductase large, small subunit' rp: 'Ribosomal protein' rTn: 'Retrotransposon' RuBPCss: 'Ribulose-1,5-biphosphate carboxylase small subunit' RuBPCA: 'Ribulose-1,5-biphosphate carboxylase/oxygenase activase' 's.': 'Small' 'saliv-g.': 'Salivary gland' SBP: 'Spermine-binding protein' 'sem-v.': 'Seminal vesicle' 'ser.': 'Serum' sgs: 'Salivary gland secretion protein' sis: 'Simian sarcoma virus oncogene' 'sk-m.': 'Skeletal muscle' 'skel-m.': 'Skeletal muscle' 'smooth-m.': 'Smooth muscle' snRNA: 'Small nuclear RNA' snRNA: 'Small nuclear ribonucleoprotein' SOD: 'Superoxide dismutase' som: 'Somatic' 'spat-reg.': 'Spatially regulated' Spec: 'Strongylocentrotus purpureatus ectoderm enriched RNA' sry: '"serendipity" locus' SV40T: 'Tumor antigen of simian virus 40 (SV40)' SVS: 'Seminal vesicle secretory protein' synt: '^Synthase^' T3d: 'T-cell antigen receptor-associated T3-complex delta chain' TAT: 'Tyrosine aminotransferase' TCDD: '2,3,7,8-Tetrachlorodibenzo-p-dioxin' TCGF: 'T-cell growth factor' TCR: 'T-cell receptor' TdT: 'Terminal deoxynucleotidyltransferase' 'test.': 'testis' TF: 'Transcription factor' TGA1a: 'TGACG-specific DNA-binding protein 1a' 'TGF-b': 'Transforming growth factor beta' TH: 'Tyrosin hydroxylase' 'thyr.': 'Thyroxine' 'Thy-1.2': 'Thy-1 (thymocyte) antigen/glycoprotein allotype 2' TIF: 'Trans-inducing factor' TIM: 'Triosephosphate isomerase' 'tis.': 'Tissue' TM: 'Tropomyosin' tmr: '"tumor morphology root" locus' TNF: 'Tumor necrosis factor' TnT: 'Troponin T (tropomyosin-binding subunit)' TO: 'Tryptophan oxygenase' TP1: 'Transition protein 1' TP2: 'Transition protein 2' TPA: '12-O-tetradecaonyl-phorbol-13-acetate' TPI: 'Triosephosphate isomerase' 'tr.': 'Transcript' 'tr-': 'Transcript' TRF: 'T-cell replacing factor' TRH: 'Thyrotropin-releasing hormone' TS: 'Thymidylate sythetase' TSH: 'Thyroid stimulating hormone' 'T/t': 'Large/small T(tumor) antigen' Ubx: '"ultrabithorax" locus' uPA: 'Urine plasminogen activator' 'URO-D': 'Uroporphyrinogen decarboxylase' Vg1: 'Vegetal hemisphere-specific mRNA 1' 'vir-inf.': 'Viral infection' VL30: 'Retrovirus-like 30s RNA' V_NP: '(Immunoglobulin heavy chain) variable region specific for 4-hydroxyl-3-nitrophenacetyl' VP5: 'Virion protein 5 (HSV-1/2: =major capsid protein)' VSP: 'Virion stimulatory protein' vWf: 'von Willebrand factor' Zen: '"zerknuellt" protein' } } $rules={ entry: ~ {$In:[file:text] $Out:entry} ('FP' {$Not} ln)* ('FP ' {pre {$entryFip = $Fip} $Wrt} ln {$App} ('//' {$Not} ln {$App})*)? ~ # fields fields: ~ {$In:entry $Out} f_id f_com? f_doc ~ f_id: ~ {$Wrt:id} 'FP ' ln ~ f_com: ~ {$Wrt:com} 'XX' ln ~ f_doc: ~ {$Wrt:doc} ('DO ' ln)* ~ # sustitude abbreviations ab_spec: ~ {$In:[fields c:id] $Out} 'FP' /[A-Za-z0-9-]+/ {if:[$abbrev.specie.$Ct != ''] $Wrt:[s:$abbrev.specie.$Ct] else $Wrt:[s:$Ct] } ~ ab_prod: ~ {$In:[fields c:id] $Out} 'FP' /[^ ]+/ ( /[^:][^ :]+/ {if:[$abbrev.product.$Ct != ''] $Wrt:[s:$abbrev.product.$Ct] else $Wrt:[s:$Ct] } /'/? )* ~ ab_proto:~ '(' {$exp="related"} | '<' {$exp="low-precision"} | /[0-9]+/ {$exp=$Ct} | '*' {$exp="in_vitro"} | 'o' {$exp="oocyte"} | '#' {$exp="transfected"} | '!' {$exp="transgenic"} ~ # indexing id: ~ {$In:[fields c:id] $Out:id} x:{$Mov:56} ' '? /[A-Z0-9_]+/ {$Wrt} ~ links: ~ {$In:[fields c:id] $Out:link} x:{$Mov:34} /[A-Z0-9_]+/ {$Wrt} ~ source: ~ {$In:ab_spec $Out:source} ( '('? /[^ )(,]+/ {$Wrt} /[)(,]/? )* ~ product: ~ {$In:ab_prod $Out:product} ( '('? /[^ )(,]+/ {$Wrt} /[)(,]/? )* ~ protocol:~ {$In:[fields c:doc] $Out} ( ( 'DO Experimental evidence:' ( ab_proto {$Wrt:[s:$exp]} /[)>,\/]/? )* ) | ln )* ~ express: ~ {$In:[fields c:doc] $Out} ( ( 'DO Expression/Regulation:' ( /[\[(+-]+/? /[A-Za-z0-9_':-]+/ {$Wrt} /[\]);,.+-]+/? )* | ln ) | ln )* ~ doc: ~ {$In:[fields c:doc] $Out} ( 'DO' ( ( 'Experimental evidence:' ( ab_proto {$Wrt:[prot s:$exp]} /[)>,\/]/? )* ln ) | ( 'Expression/Regulation:' ( /[(+-]+/? /[A-Za-z0-9_':-]+/ {$Wrt:regul} /[);,.+-]+/? )* ln ) ) )* ~ sequence:~ {$Inn:[fields c:id] $Out:id} x:{$Mov:34} /[A-Z0-9_]+/ {$accN=$Ct} /[01]/ {$type=$Ct} /[+-]/ {$dir=$st} /[0-9]+/ # {$Wrt:[s:$getSeq:["EMBL" ac:$accN t:$type d:$dir p:{$Ct 100}]]} ~ # table display t_source: ~ {$Out $In:[fields c:id]} 'FP' /[A-Za-z0-9-]+/ {$Wrt} ~ t_product: ~ {$Out $In:[fields c:id]} 'FP' /[^ ]+/ /[^:]+/? {$Wrt} ~ t_protocol: ~ {$Out $In:[fields c:doc]} ( ( 'DO Experimental evidence:' /[^\n]*/ {$Wrt} ) | ln )* ~ t_express: ~ {$Out $In:[fields c:doc]} ( ( 'DO Expression/Regulation:' /[^\n]*/ {$Wrt} ) | ln )* ~ # HTML display hl_links:~ {$In:[fields c:id t:hl]} x:{$Mov:34} /[A-Z0-9_]+/ {$Rep:{$ParStr:epdR $Ct $Ct}} ~ # other ln: ~ /[^\n]*\n/ ~ } #$fil = $fileOpen:"/data/epd/epd.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #$print:"-------->Entry\n" #while:$jobTokens:[$job name:fields print:0] { # $jobTokens:[$job name:id print:1] # $jobTokens:[$job name:link print:1] # $jobEnd:$job # $jobNext:[$job file:$fil] # $print:"----------------------------------------------------------->new entry\n" #} # $jobTokens:[$job name:protocol print:1] # $jobTokens:[$job name:express print:1] # $jobTokens:[$job name:t_protocol print:1] # $jobTokens:[$job name:t_express print:1] # $jobTokens:[$job name:source print:1] # $jobTokens:[$job name:product print:1] # $jobTokens:[$job name:t_source print:1] # $jobTokens:[$job name:t_product print:1] # # # # # # # # # # # # # # # $RCSfile: epd.it,v $ # $Revision: 1.1 $ # $Date: 1996/07/30 10:26:50 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The Eukaryotic Promoter Database EPD was designed and developed at |the WeizmannInstitute of Science in Rehovot (Israel) and is currently |maintained at ISREC inEpalinges s/Lausanne (Switzerland). EPD is a |specialized annotation database ofthe EMBL Data Library. It provides |information about eukaryotic promoters avail-able in the EMBL Data |Library and is intended to assist experimental research-ers, as well as |computer analysts, in the investigation of eukaryotic transcrip-tion |signals. The present version originated from a previous compilation |pub-lished in an article (1) and is organized as a hierarchically |ordered and docu-mented "functional position set" (2) pointing to |transcription initiation sites. All information is directly abstracted |from scientific literature and is thusindependent of the EMBL sequence |entry descriptions. As a consequence, many ofthe initiation sites |referred to in EPD do not appear in corresponding EMBLfeature tables. |

    A co-ordinated updating procedure has been set up by the two |laboratories thatwill ensure future compatibility between the position |references in EPD and thesequence data in the main data library. |Investigators who access EMBL via pub-licly available programs should |be aware of the fact that software producers oc-casionally modify the |sequence data in ways that render position referencesinaccurate. EPD is |generally not compatible with sequence data of anotherrelease because |EMBL sequence entries are not designed as stable data units.

    The |completeness and accuracy of EPD greatly benefits from user-feedback. |Anyreport of mistakes or omissions would be very much appreciated. |Direct communi-cation of newly published transcript mapping or gene |expression data is alsowelcome. Please forward all correspondence |to the address given on top of thisdocument. Use electronic mail if |possible. more: '' citation: '' ftpSite:'' fields:{ ID: |

    The EPD ID Field

    |The entry code is a five-digit number which is the only part of a |promoter entry that is stable from release to release. The first two |digits designate the release of initial appearance. Organism: |

    The EPD Organism Field

    | |Species codes consist of the |initials of genus and species name. Occasionally, three characters |are required to generate unique codes. Standard abbreviations identify |viruses. The full names of the organisms can be used in a query. The |names are given in appendix B.1. Subspecies or strains are specified |in parentheses. |Chromosomal locations (genetic or cytogenetic loci, genomic map |units, etc.) appear in square brackets immediately following species |codes. GeneProduct: |

    The EPD GeneProduct Field

    |Many gene products are listed in appendix B.3. Alternative initiation |sites are identified by right-justified P1,P2.., or E1,E2.., depending |on whether the corresponding 5'exons are 3'co-terminal or not. The |strongest initiation site is marked by trailing + if known. ExpProtocol: |

    The EPD Protocol Field

    |Special characters appended to the number codes designate an |experimental geneexpression system where the RNA for the corresponding |experiments wassynthesized. A query may have next key words: |
      |
    • related |
    • low-precision |
    • in_vitro |
    • oocyte |
    • transfected |
    • transgenic |
    |or the transcript mapping experiments number that define the promoter, |that gives information about expression and regulation. The varies |experimental techniques are identified by number codes: | |
    codesexperiments |
    1direct RNA sequencing |
    2length measurement of an RNA product |
    3length measurement of a nuclease-protected complementary |RNA or DNA fragment by comparison with homologous sequence ladder |
    4same as 3 but with heterologous size markers |
    5RNA sequencing by dideoxy-terminated primer extension |
    6DNA Sequencing of an in vitro generated strong-stop cDNA or |a full-length cDNA clone |
    7length measurement of a primer-extension product by |comparison with homologous sequence ladder |
    8same as 7 but with heterologous size markers |
    9DNA sequencing of a full-length processed pseudogene |
    10length measurement of a reverse direction primer-extension |product (blocked by RNA 5'end) by comparison with homologous sequence |ladder |
    ExpresRegul: |

    The EPD Expression Field

    |The information on expression/regulation may include indication of |developmentalstages, tissues, cell types, cell cycle stages, and |various regulatory features. | |
           |Conventions:
           |
           |-  Semicolon delimits different types of specifications
           |   (e.g. developmental stage and tissue).
           |
           |-  Comma delimits alternative keywords (e.g. liver,  kidney)
           |
           |-  "+" means "induced by" or "strongly expressed in".
           |
           |-  "-" means "repressed by" or "weakly expressed in".
           |
           |-  "~" means "modulated by".
           |
           |-  Cell cycle stages are given in square brackets.
           |
    } date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: fasta.i,v $ # $Revision: 1.2 $ # $Date: 1996/05/24 14:06:00 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FASTA_DB:$library:[FASTA group:@HOMOLSEARCH_LIBS comment:"" format:@FASTA_FORMAT maxNameLen:40 ifiles:{"fasta.i" "fasta.is"} type:user files:{ $file:tmp } ] FASTA_FORMAT:$libformat:[fileType:@FASTA_FILE syntax:@FASTA_SYNTAX fields:{ $field:[@DF_ID code:title index:id indexToken:id] $field:[@DF_Init1 code:scores index:int indexToken:init1] $field:[@DF_Initn code:scores index:int indexToken:initn] $field:[@DF_OptScore code:scores index:int indexToken:percIdent tableToken:opt tableFormat:right] $field:[@DF_Alignment code:align tableToken:t_align tableFormat:left] $field:[@DF_QueryBeg code:align index:int indexToken:queryBeg] $field:[@DF_QueryEnd code:align index:int indexToken:queryEnd] $field:[@DF_MatchLen code:align index:int indexToken:matchLen tableToken:matchLen tableFormat:right] $field:[@DF_LINK code:title index:link indexToken:link] } ] DF_Init1:$srsfield:[Init1 short:in1] DF_Initn:$srsfield:[Initn short:inn ] DF_OptScore:$srsfield:[OptScore short:opt] DF_Alignment:$srsfield:[Alignment short:ali] FASTA_SYNTAX:$syntax:[file:"SRSDB:fasta.is" ignore:" "] FASTA_FILE:$filetype:[typename:fasta maxline:100] # links $link:[@FASTA_DB to:@?SWISSPROT_DB token:'link|swiss' toField:@DF_ID]] $link:[@FASTA_DB to:@?SWISSNEW_DB token:'link|swissnew' toField:@DF_ACCNO] $link:[@FASTA_DB to:@?PIR_DB token:'link|pir'] $link:[@FASTA_DB to:@?TREMBL_DB token:'link|trembl'] $link:[@FASTA_DB to:@?TREMBLNEW_DB token:'link|tremblnew'] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: fasta.is,v $ # $Revision: 1.3 $ # $Date: 1996/07/24 22:19:18 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $rules={ entry: ~ {$In:[file:text] init{$count=0} $Out $count+=1} (/[^ ]+\n/ {$Not} ln)* (/[^ ]+\n/ {pre {$skipChars:"" $entryFip = $Fip} $Wrt} ('SCORES ' {$Not} appLn)* (/[^ ]+\n/ {$Not} appLn)* )? ~ # data fields fields: ~ {$In:entry $Out $Skip:1} title link excerpt scores align ~ title: ~ {$Wrt:title} ln ~ link: ~ {$Wrt:link} ln ~ excerpt: ~ {$Wrt:excerpt} ('SCORES ' {$Not} ln)+ ~ scores: ~ {$Wrt:scores} ln ln ~ align: ~ {$Wrt:align} ln+ ~ # indexing id: ~ {$In:[fields c:link] $Out} /([^:]+):([^\n]+)/ {$Wrt:[s:"$count\_$1\_$2"]} ~ init1: ~ {$In:[fields c:scores] $Out} /.*Init1: *([0-9]+)/{$Wrt:[s:$1]} ~ initn: ~ {$In:[fields c:scores] $Out} /.*Initn: *([0-9]+)/{$Wrt:[s:$1]}~ opt: ~ {$In:[fields c:scores] $Out} /.*Opt: *([0-9]+)/{$Wrt:[s:$1]} ~ percIdent:~ {$In:[fields c:scores] $Out} ln / *([^%]+)/ {$Wrt:[s:$1]} ~ queryBeg: ~ {$In:[fields c:align] $Out} /[ \n]+([0-9]+)/ {$b=$1 $Wrt:[s:$1]} ~ queryEnd: ~ {$In:[fields c:align] $Out} /.* ([0-9]+) *\n *[a-zA-Z0-9]/ {$e=$1 $Wrt:[s:$1]} ~ matchLen: ~ {$Out pre{$Request:queryEnd $Request:queryBeg $Wrt:[s:($e-$b+1)]}} / /~ link: ~ {$Out $In:[fields c:link]} (/sw|swiss|swissprot/ ':' name {$Wrt:swiss})? ~ # table display t_align: ~ {$Out $In:[fields c:align]} /.+/ {$Wrt:[s:""]} ~ # other name: ~ /[a-zA-Z0-9_]+/ ~ appLn: ~ /[^\n]*\n/ {$App} ~ ln: ~ /[^\n]*\n/ ~ } $fil = $fileOpen:"/home/etzold/dnak_ecoli.fasta" $job = $JobNew:[prod:$rules skip:" "] $JobNext:[$job file:$fil] for:{1 $JobTokens:[$job name:id print:1] 1} { $JobTokens:[$job name:init1 print:1] $JobTokens:[$job name:initn print:1] $JobTokens:[$job name:opt print:1] $JobTokens:[$job name:queryBeg print:1] $JobTokens:[$job name:queryEnd print:1] $JobTokens:[$job name:matchLen print:1] $JobTokens:[$job name:link print:1] $JobEnd:$job $JobNext:[$job file:$fil] $print:"----------------------------------------------\n" } entry: ~ {$out} ('*a' {$not} ln)* '*a' {$wrt} ln {$app} ('#' {$not} ln {$app})* ~ fields: ~ {$out $in:entry $init{ $fn={ a: "Gene symbol" b: "Genetic map position" c: "Cytological map position" d: "Function(s) of product" e: "Full name" g: "D. mel. DNA/RNA AC no(s)" h: "D. spp. DNA/RNA AC no(s)" i: "Synonym(s)" j: "Non-Drosophila homologue" k: "Phenotypic information" l: "Length (type\\ends\\total)" m: "D. mel. protein AC no(s)" n: "D. spp. protein AC no(s)" o: "Origin/mutagen" p: "Phenotypic information" q: "Miscellaneous information on genes and alleles" r: "Copy number" s: "Molecular biology data" t: "Target site duplication" u: "Other information" w: "Discoverer(s)" x: "Genes References" y: "Secondary FlyBase id(s)" z: "FlyBase gene id number" A: "Allele" B: "Revised genetic map posn." C: "Associated cytology" D: "Revised cyto. map posn." E: "References" F: "Enzyme name/number(s)" H: "Last update" J: "Prosite protein domains" K: "RNA space/time distrib." N: "Cyto. location of clone" O: "Progenitor allele/chromosome" R: "Misc. allele information" S: "Open reading frame size" T: "cDNA clone length" U: "RNA in situ distribution" V: "Protein distribution" Y: "Transcript size(s)" Z: "Genomic length of clone" } } $prevField="" } ('*' /[a-zA-Z]/ { if:($ct eq $prevField) $wrt:[$ct s:$fn.$ct] else $app:[s:" "] $lastField = $ct} ln {$app})* ~ html-fields:~ {$in:[fields t:html] case:$itc { head: $ins:"\n$entry\n
    \n"
                    tail:    
                      $ins:"
    \n" m: $parse:[$it start:hl rules:{ hl: ~ 'PIR/' name {$rep:{$pirhl $ct $ct} ~ } ] default: $ list header bold dosomething head: wrt nucRef: p:## html-title ('PDB/([^ ]+)' | 'dbEST/([^ ]+)' | 'dbSTS/([^ ]+)' | /[^ ]/ )##; prositeRef: p:## html-title /[^ ]/ ##; protRef: p:## html-title ('SWP/([^ ]+)' | 'PIR/([^ ]+)' ) ##; litRef: > } ~ seqlen: ~ 'SEQLENGTH' num {$len = $ct} ~ nalign: ~ 'NALIGN' num {$nalign = $ct} ~ aliblock: ~ {$out $wrt} ('seqNo' {$not} ln)* 'SeqNo' ln (num ln )* ~ ali: ~ {$in:aliblock pre:{seqN=1}} x:{$move:40 $pos++} (/([A-Z])../) {$seq[$seqN++][$pos] = $1})* ~ # # $RCSfile: genbank.i,v $ # $Revision: 1.4 $ # $Date: 1996/08/11 22:51:52 $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GENBANK_DB:$library:[GENBANK group:@SEQUENCE_LIBS format:@GENBANK_FORMAT cachesize:512 maxNameLen:10 files:{ $file:gbvrt } ] GENBANK_FORMAT:$libformat:[fileType:@SEQ_FILE syntax:@GENBANK_SYNTAX fields:{ $field:[@DF_ALL] $field:[@DF_ID code:id index:id indexToken:ID] $field:[@DF_Division code:str index:str indexToken:Division tableToken:Division tableFormat:left] $field:[@DF_SeqLength code:id index:int indexToken:SeqLength tableToken:SeqLength tableFormat:right] $field:[@DF_Molecule code:id index:str indexToken:Molecule tableToken:Molecule tableFormat:left] $field:[@DF_Date code:id index:int indexToken:Date tableToken:Date tableFormat:left] $field:[@DF_Description index:str code:def indexToken:Definition] $field:[@DF_Accession code:acc index:str indexToken:Accession tableToken:Accession tableFormat:left] $field:[@DF_Nid code:nid index:str indexToken:NID tableToken:NID tableFormat:left] $field:[@DF_Keywords code:kwd index:str indexToken:Keywords] $field:[@DF_Source code:src index:str indexToken:Source] $field:[@DF_Organism code:srcorg index:str indexToken:Organism] $field:[@DF_Authors code:refaut index:str indexToken:Authors] $field:[@DF_Title code:reftit index:str indexToken:Title] $field:[@DF_Citation code:refjnl index:str indexToken:Reference] $field:[@DF_Features code:fts index:str indexToken:Features] } ] DF_Nid:$srsfield:[Nid short:nid] GENBANK_SYNTAX:$syntax:[file:"SRSDB:genbank.is"] REF_FILE:$filetype:[typename:seq maxline:200 fieldTokens:fields fipVar:refFip] SEQ_FILE:$filetype:[typename:seq maxline:200 fieldTokens:seq fipVar:seqFip] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: genbank.is,v $ # $Revision: 1.4 $ # $Date: 1996/08/11 22:51:52 $ # # Author: Antoine Daruvar # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $rules={ # entry and fields entry: ~ {$In:[file:text] pre{$Skip:0} $Out} ('LOCUS' {$Not} eol)* ('LOCUS' {$Wrt $entryFip=$Fip} eol {$App} ('LOCUS' {$Not} eol {$App})+)? ~ fields: ~ {$In:entry $Out} id def acc nid kwd seg? src srcorg ((refttl refaut | refaut) reftit? refjnl refmed? refrem?)+ com? (fttitle fts+)? bct seq ~ # fields id: ~ {$Wrt:id} /LOCUS / eol ~ def: ~ {$Wrt:def} /DEFINITION / eol (/ / eol)* ~ acc: ~ {$Wrt:acc} /ACCESSION / eol ~ nid: ~ {$Wrt:nid} /NID / eol ~ kwd: ~ {$Wrt:kwd} /KEYWORDS / eol (/ / eol)* ~ seg: ~ {$Wrt:seg} /SEGMENT / eol ~ src: ~ {$Wrt:src} /SOURCE / eol (' ' eol)* ~ srcorg: ~ {$Wrt:srcorg} / ORGANISM / eol (/ / eol)* ~ refttl: ~ {$Wrt:reftit} /REFERENCE / eol ~ refaut: ~ {$Wrt:refaut} / AUTHORS / eol (/ / eol)* ~ reftit: ~ {$Wrt:reftit} / TITLE / eol (/ / eol)* ~ refjnl: ~ {$Wrt:refjnl} / JOURNAL / eol (/ / eol)* ~ refmed: ~ {$Wrt:refmed} / MEDLINE / eol ~ refrem: ~ {$Wrt:refrem} / REMARK / eol (/ / eol)* ~ com: ~ {$Wrt:com} /COMMENT / eol (/ / eol)* ~ fttitle: ~ {$Wrt} /FEATURES / eol ~ fts: ~ {$Wrt:fts} / [^ ]/ eol (/ / eol)* ~ bct: ~ {$Wrt:bct} /BASE COUNT / eol ~ seq: ~ {$Wrt:seq} /ORIGIN / eol (/ / eol)* ~ # indexing i_id: ~ {$In:[fields c:id] $Out:ID} /LOCUS */ iword {$Wrt} ~ i_sl: ~ {$In:[fields c:id] $Out:SeqLength} /.+ ([0-9]+) *bp/ {$Wrt:[s:$1]} ~ i_mol: ~ {$In:[fields c:id] $out:Molecule} /.* bp +([a-zA-Z0-9-]+)/ {$Wrt:[s:$1]} ~ i_div: ~ {$In:[fields c:id] $Out:Division} /.+([A-Z][A-Z][A-Z]) +[0-9]+-[A-Z][A-Z][A-Z]-[0-9]+/ {$Wrt:[s:$1]} ~ i_date: ~ {$In:[fields c:id] $Out:Date} gbdatenum {$Wrt:[s:$dateval]} ~ i_def: ~ {$In:[fields c:def] $Out:Definition} ((/DEFINITION */ | / */) ( iword {$Uniq} | noiword)+)* ~ i_ac: ~ {$In:[fields c:acc] $Out:Accession} /ACCESSION */ iword {$Wrt} ~ i_nid: ~ {$In:[fields c:nid] $Out:NID} /NID */ iword {$Wrt} ~ i_kwd: ~ {$In:[fields c:kwd] $Out:Keywords} ((/KEYWORDS */ | / */) ((kwexp {$Wrt})? kwsep)+ eol)+ ~ i_src: ~ {$In:[fields c:src] $Out:Source} ((/SOURCE */ | / */) ( iword {$Wrt} | noiword)+)* ~ i_srcorg: ~ {$In:[fields c:srcorg] $Out:Organism} ((/ ORGANISM */ | / */) ('Mitochondrion' {$Wrt} | kwexp {$Wrt} | kwsep)+ eol)+ ~ i_refaut: ~ {$In:[fields c:refaut] $Out:Authors} ((/ AUTHORS */ | / */) ((/([^,\n]+),([^ ,\n]+)/ {$Wrt:[s:"$1,$2"]}) (/, */ | / and */)?)+ eol)+ ~ i_reftit: ~ {$In:[fields c:reftit] $Out:Title} ((/ TITLE */ | / */) ( iword {$Uniq} | noiword)+)* ~ i_refjml: ~ {$In:[fields c:refjnl] $Out:Reference} ((/ JOURNAL */ | / */) ( iword {$Uniq} | noiword)+)* ~ i_refmed: ~ {$In:[fields c:refmed] $Out:Medline} / MEDLINE */ iword {$Wrt} ~ i_ftsqua: ~ {$In:[fields c:fts] $Out:Features} /[^\/]+/ (/[^\/]*\//) ( (/translation.*/) | (/[^=]*=/)? ( iword {$Uniq} | noiword)+) ~ # HTML display h_ftxref: ~ {$In:[fields c:fts t:html]} (/[^\/]+/ | /\/EC_number="?/ /[0-9.]+/ {$Rep:{$ParStr:enzymeR $Ct $Ct}} | /\/db_xref="/ ('PID:' iword {$Rep:{$ParStr:pidR $Ct $Ct}} | 'SWISS-PROT:' iword {$Rep:{$ParStr:swissR $Ct $Ct}}) | '/')+ ~ h_medline:~ {$In:[fields c:refmed t:html]} tag /[0-9]+/ {$Rep:{$ParStr:medlineR $Ct $Ct}} ~ # utilities # ========= # genbank date gbdatenum: ~ {init {$month={JAN:1 FEB:2 MAR:3 APR:4 MAY:5 JUN:6 JUL:7 AUG:8 SEP:9 OCT:10 NOV:11 DEC:12}}} /.+([0-9]+)-([A-Z][A-Z][A-Z])-([0-9]+)/ {$dateval=$1 + $month.$2 * 100 + $3 * 10000} ~ # ASCII string => any combinaison of one or more letters and number and _ asciiword: ~ /[a-zA-Z0-9_]+/ ~ # not ASCII string => noasciiword: ~ /[^a-zA-Z0-9_]+/ ~ # index string => combinaison of one or more letters and number and _ # with at least one character iword: ~ /[a-zA-Z0-9_]+/ ~ # not index string => not ascci noiword: ~ /[^a-zA-Z0-9_]+/ ~ # key word expression (strings without ; , or \n) kwexp: ~ /[^;.\n]+/ ~ # key word separator (; , followed by any number of spaces) kwsep: ~ /[.;]+ */ ~ # any string any: ~ /[^\n]+/ ~ # end of line eol: ~ /[^\n]*\n/ ~ tag: ~ / *[A-Z]+ */ ~ } #$fil = $fileOpen:"/home/daruvar/icarus/test/gb_sample" #$job = $JobNew:[prod:$rules skip:" "] #$JobNext:[$job file:$fil] #while:$JobTokens:[$job name:fields print:0] { # $print:"\n\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" # $print:"=============== ID ==============================================\n" # $JobTokens:[$job name:ID print:1] # $print:"=============== SeqLength =======================================\n" # $JobTokens:[$job name:SeqLength print:1] # $print:"=============== Division ========================================\n" # $JobTokens:[$job name:Division print:1] # $print:"=============== Date ============================================\n" # $JobTokens:[$job name:Date print:1] # $print:"=============== Definition ======================================\n" # $JobTokens:[$job name:Definition print:1] # $print:"=============== Accession =======================================\n" # $JobTokens:[$job name:Accession print:1] # $print:"=============== NID =============================================\n" # $JobTokens:[$job name:NID print:1] # $print:"=============== Keywords ========================================\n" # $JobTokens:[$job name:Keywords print:1] # $print:"=============== Source ==========================================\n" # $JobTokens:[$job name:Source print:1] # $print:"=============== Organism ========================================\n" # $JobTokens:[$job name:Organism print:1] # $print:"=============== Authors =========================================\n" # $JobTokens:[$job name:Authors print:1] # $print:"=============== Title ===========================================\n" # $JobTokens:[$job name:Title print:1] # $print:"=============== Reference =======================================\n" # $JobTokens:[$job name:Reference print:1] # $print:"=============== Medline =========================================\n" # $JobTokens:[$job name:Medline print:1] # $print:"=============== Features ========================================\n" # $JobTokens :[$job name:Features print:1] # $JobEnd:$job # $JobNext:[$job file:$fil] #} ~~~~~~~~~~~~~~~~~~ # # $RCSfile: genbank.it,v $ # $Revision: 1.3 $ # $Date: 1996/07/30 10:26:50 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |GenBank (1) is the NIH's database of all known nucleotide and protein |sequences including supporting bibliographic and biological |information. Since 1992 it has been based at the National Center for |Biotechnology Information (NCBI), a division of the National Library of |Medicine, located on the NIH campus. NCBI was created by Congress in |1988 and specifically charged with developing automated information |systems to support molecular biology and biotechnology. Its other |mission is to conduct basic research and as part of the NIH Intramural |Program, NCBI scientists pursue research in genome analysis, molecular |structure modeling and prediction, and mathematical methods for |sequence analysis. |

    more: |

    |More on GenBank |

    citation: | Reference: |1. Benson, D., Boguski, M., Lipman, D.J., and Ostell, J. (1994) |Nucleic Acids Research, 22, 3441-3444. |

    |2. Boguski, M.S. (1995) Trends in Biochemical Sciences, 20, 295-296. |

    |3. Boguski, M.S., Tolstoshev, C. M. and Bassett, D. E. (1994) Science, |265, 1993-1994. |

    |4. Boguski, M.S. and Schuler, G.D. (1995) Nature Genetics, 10, 369-371. |

    |5. Levy-Lahad, E., Wasco, W., Poorkaj, P., Romano, D.M., Oshima, J., |Pettingell, W.H., Yu, C.-E., Jondro, P.D., Schmidt, S.D., Wang, K., |Crowley, A.C., Fu, Y.-H., Guenette, S.Y., Galas, D., Nemens, E., |Wijsman, E.M., Bird, T.D., Schellenberg, G.D. and Tanzi, R.E. (1995) |Science, 269, 973-977. |

    |6. Bassett, D.E., Boguski, M.S., Spencer, F., Reeves, R. Goebl, M., and |Hieter, P. (1995) Trends in Genetics, 11, 372-373. |

    |7. Schuler, G.D., Epstein, J.A., Ohkawa, H., and Kans, J.A. Methods in |Enzymology, in press. |

    |8. Altschul, S.F., Boguski, M.S., Gish, W., and Wootton, J.C. (1994) |Nature Genetics, 6, 119-129. |

    |9. Madden, T.L., Tatusov, R.L. and Zhang, J. Methods in Enzymology, in |press. ftpSite:'' fields:{ ID: |

    GenBank Locus Name(ID)

    |The pieces of information contained in the LOCUS (ID) record are always |found in fixed positions. The locus name (or entry name), which is |always ten characters or less, begins in position 13. The locus name |is designed to help group entries with similar sequences: the first |three characters usually designate the organism; the fourth and fifth |characters can be used to show other group designations, such as gene |product; for segmented entries the last character is one of a series |of sequential integers. |

    AccNumber: |

    GenBank Accession Number

    |The ACCESSION number is assigned to a sequence and should remain |linked with it for ever, whereas |entry names may change; also occasionally a few sequences may be merged to a |single sequence |that will then inherit all accession numbers). |

    |Corresponding sequences in EMBL and GenBank should to have the same accession |numbers. In |all current sequence libraries the accession number consists of an |alphabetical character followed |by 5 digits, e.g "X12345". Description: |

    GenBank Definition Field

    |The DEFINITION record gives a brief description of the sequence, |proceeding from general to specific. It starts with the common name of |the source organism, then gives the criteria by which this sequence is |distinguished from the remainder of the source genome, such as the |gene name and what it codes for, or the protein name and mRNA, or some |description of the sequence's function (if the sequence is |non-coding). |

    Keywords: |

    GenBank Keywords

    |Short phrases describing gene products and other |information about an entry. Mandatory keyword in all annotated |entries/one or more records. |

    Organism: |

    GenBank Organism Source

    |Formal scientific name of the organism (first line) |and taxonomic classification levels (second and subsequent lines). |Mandatory subkeyword in all annotated entries/two or more records. |

    |A taxon is either an organism name or the name of the family, group etc.. |Usually latin names are best (e.g. "EUKARYOTA", or "HOMO SAP*") but often |the english common name is also given in this data field. |

    Authors: |

    GenBank Author Names Field

    |Lists the authors of the citation. Mandatory subkeyword/one or more records. |All author names of all libraries are converted to this format: surname |followed by a comma, followed by the initials (no blanks before or after |the "," or between initials!). |If you don't know the initials put a wildcard ("*") after the comma; e.g., |"SCHULZ,*"; if you place it after the surname you might get "SCHULZKI,.." |as well. |

    Title: |

    GenBank Title

    |Full title of citation. Optional subkeyword (present |in all but unpublished citations)/one or more records. |

    Reference: |

    GenBank Literature Reference

    |Four items of the literature reference are indexed: |
      |
    • journal name (e.g., "EMBO JOURNAL"), |
    • volume number (e.g., "22"), |
    • first page (e.g., "1712-"), |
    • and publication year (e.g., "1987"). |
    |

    |Note: The journal names are not yet converted to standard names; e.g., | the journal NAR might be called "Nucl. Acids Res." in one | library and "Nucl. Acids Research" in the other. |

    |Note: When searching first page numbers a dash must be added to the | number (e.g., 122-) which is necessary to make the page number | distinct from both volume number and publication year. |

    Features: |

    GenBank Features

    |Table containing information on portions of the |sequence that code for proteins and RNA molecules and information on |experimentally determined sites of biological significance. Optional |keyword/one or more records. |

    } date: |25 Jul 1996 signature: |Anatoly Ulyanov } # # $RCSfile: general.it,v $ # $Revision: 1.3 $ # $Date: 1996/07/30 10:26:51 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: | General purpose filds more: '' citation: '' ftpSite:'' fields:{ AccNumber: |

    Accession Number

    |The accession number is assigned to a sequence and should remain linked |with it for ever, whereas entry names may change; also occasionally a few |sequences may be merged to a single sequence that will then inherit all |accession numbers). |

    |Corresponding sequences in EMBL and GenBank should to |have the same accession numbers. In all current sequence libraries the |accession number consists of an alphabetical character followed by 5 |digits, e.g "X12345". |

    |Using Wildcards Description: |

    Definition Field

    |This is probably the best data field for searching an entry you don't know |very much about; however, you can't expect to find all entries of a |class, since often different conventions are used for naming enzymes, |organisms, genes, etc.. |

    |In EMBL the Definition field consists of one or more lines each |\ preceded by "DE ". Swissprot follows the same convention. In |PIR The Definition field is always a single line (which may |become very long) which follows the line with the entry name ">P1;...". |

    Organism: |

    Organism Source

    |A taxon is either an organism name or the name of the family, group etc.. |Usually latin names are best (e.g. "EUKARYOTA", or "HOMO SAP*") but often |the english common name is also given in this data field. |

    |Using Wildcards Authors: |

    Author Names Field

    |All author names of all libraries are converted to this format: surname |followed by a comma, followed by the initials (no blanks before or after |the "," or between initials!). |If you don't know the initials put a wildcard ("*") after the comma; e.g., |"SCHULZ,*"; if you place it after the surname you might get "SCHULZKI,.." |as well. |

    |Using Wildcards SeqLength: |

    Sequence Length Field

    |The sequence length is calculated by reading the sequence. Some libraries |(EMBL, SWISSPROT) have the length also in the first entry line so |to display the sequence length in these libraries, select the ID field. |

    |Note that ranges can be combined: "300-!500 | !600-700" or "300-700 ! |500-600" retrieve the |same set of sequences, namely all sequences from 300 to 500, |excluding 500, plus sequences from 600 to |700 where the 600 is excluded. Date: |

    Creation Date

    |All sequence libraries have a field with the entry's creation date. |The index can be |searched by specifying the date in the form of date-month-year: |
      |
    • day is a one or two digit number; |
    • month is the three letter abbreviation of the month |(eg, jan for January); |
    Reference: |

    Literature Reference

    |Four items of the literature reference are indexed: |
      |
    • journal name (e.g., "EMBO JOURNAL"), |
    • volume number (e.g., "22"), |
    • first page (e.g., "1712-"), |
    • and publication year (e.g., "1987"). |
    |

    |Note:The journal names are not yet converted to standard | names; e.g., | the journal NAR might be called "Nucl. Acids Res." in one | library and "Nucl. Acids Research" in the other. |

    |Note:When searching first page numbers a dash must be added to the | number (e.g., 122-) which is necessary to make the page number | distinct from both volume number and publication year. |

    |Using Wildcards Methods: |

    Experimental Method

    |The ExpMethod field can contain one of the following: |
    |
    X |
    X-ray structure |
    NMR |
    NMR structure |
    FIBER |
    Fiber diffraction study |
    MODEL |
    A model without explicit experimental data |
    |The Exp-Method is derived from the EXPDTA field in |the PDB if present, otherwise it is derived from other sources. Resolution: |

    Resolution

    |The Resolution is derived from REMARK 2 in the PDB |file. For NMR structures and models no resolution is given. RFactor: |

    R-Factor

    |The R-Factor for X-ray structures is derived from REMARK |3 and REMARK 4 if possible. For X-ray structures lacking |a valid R-factor in the PDB file, the R-factor field |is based on the original literature. A number of corrections to values |found in the PDB have also been applied. In some cases no |R-factor could be found, or the original literature does contain an |R-factor but the published coordinates are C-alpha only. In those |cases no R-Factor field is present. Also no R-factor is given |for NMR structures, because the calculation methods are too diverse. NoHSSPAlign: |

    HSSP-N-Align

    |The HSSP-N-Align field gives the number of aligned sequences in |the HSSP database, if a HSSP file for the structure |exists (Normally: if the structure is a protein structure). TotFractHelix: |

    TotFractHelix

    |Gives the fraction of the assigned |secondary structure that is helical: it is the total of the |Helix fields for all chains divided by the total of all |Sec-Struc fields. This field is only present if there is a |secondary structure. TotFractBeta: |

    TotFractBeta

    |Gives the fraction of the assigned |secondary structure that is Beta: it is the total of the Beta |fields for all chains divided by the total of all Sec-Struc |fields. This field is only present if there is a secondary structure. TotNResProt: |

    TotNResProt

    |Gives the total number of amino acid residues |in the structure, if any. Non-standard amino-acids are included. TotWaterMols: |

    TotWaterMols

    |Gives the total number of water molecules in |the structure, if any. NoHetGroups: |

    HET-Groups

    |The HET-Groups field gives the number of HET cards |in the PDB file, if any. The following items are repeated for |every HET-group, and are all derived from the PDB HET cards. } date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: mpw.i,v $ # $Revision: 1.6 $ # $Date: 1996/08/12 19:04:40 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MPW_DB:$library:[MPW group:@SEQRELATED_LIBS comment:"Metabolic pathways - Selkov." format:@MPW_FORMAT maxNameLen:30 ifiles:{"prosite.i" "prosite.is"} files:{ $file:pathway_graphics # $file:aac # $file:aro # $file:car # $file:coe # $file:enz # $file:hal # $file:hyd # $file:lip # $file:mtr # $file:nit # $file:nuc # $file:oxy # $file:pho # $file:pro # $file:pur # $file:pyr # $file:sig # $file:sul } ] MPW_FORMAT:$libformat:[fileType:@MPW_FILE syntax:@MPW_SYNTAX tableFormat:left printFormat:topicList fields:{ $field:[@DF_ID index:id indexToken:id] $field:[@DF_Name code:MPW index:str indexToken:name] $field:[@DF_CellCultureCategoryCode code:CCC indexToken:'words|CCC'] $field:[@DF_AlternativePathwayNames code:APN index:str indexToken:'words|APN'] $field:[@DF_SystematicPathwayNames code:SPN index:str indexToken:'words|SPN'] # $field:[@DF_SystematicPathwayNames code:SPW index:str # indexToken:'words|SPW'] $field:[@DF_MetabolicPathwayName code:MPW index:str indexToken:'name'] $field:[@DF_TaxonomicGroup code:TG index:str indexToken:'words|TG'] $field:[@DF_Strain code:STR index:str indexToken:'words|STR'] $field:[@DF_OverallReaction code:OVR index:str indexToken:'words|OVR'] $field:[@DF_Diagram code:diag index:str indexToken:'words|diag'] $field:[@DF_EnzymeCode code:diag index:str indexToken:enzyme tableToken:enzyme tableFormat:left] } ] DF_Diagram:$srsfield:[Diagram short:dia] MPW_SYNTAX:$syntax:[file:"SRSDB:mpw.is" ignore:" "] MPW_FILE:$filetype:[typename:txt maxline:1000] $link:[@MPW_DB to:@?ENZYME_DB fromField:@DF_EnzymeCode toField:@DF_ID] UDP: 'UDP-Unknown data-field' COM: 'COM-Unknown data-field' OVR: 'Overall Reaction' CCC: 'Cell Culture Category' STR: 'Strain' APN: 'Alternative Pathway Name' SPN: 'Systematic Pathway Name' SPW: 'Systematic Pathway Name' MPW: 'Metabolic Pathway Name' TG: 'Taxonomic Group' } $rules={ entry: ~ {$In:[file:text] $Out init{$count=0} $count+=1 pre{$Skip:0}} ( /[A-Z][A-Z]/ {$Not} ln)* (tag {$entryFip=$Fip $Wrt} appLn (/\12| *#/ {$Not} appLn)* )? ~ # fields fields: ~ {$In:entry $Out $Skip:1} (org)* (date)? (str)? (ccc)? (apn)* (mpw)? (spw | spn | ovr)* (id)? diag ~ org: ~ {$Wrt:$code} (/(TG|OR|MET|CS)/ {$code=$Ct} ln more)+ ~ date: ~ {$Wrt:date} '***' ln ~ str: ~ {$Wrt:STR} 'STR' ln more ~ ccc: ~ {$Wrt:CCC} 'CCC' ln more ~ apn: ~ {$Wrt:APN} 'APN' ln more ~ mpw: ~ {$Wrt:MPW} 'MPW' ln more ~ spw: ~ {$Wrt:SPW} 'SPW' ln more ~ spn: ~ {$Wrt:SPN} 'SPN' ln more ~ ovr: ~ {$Wrt:OVR} 'OVR' ln more ~ id: ~ {$Wrt:name} 'MPW G' ln ~ diag: ~ {$Wrt:diag} (ln)* ~ # indexing i_id: ~ {$In:[file:text] $Out:id} x{$Wrt:[s:$count]}~ i_name: ~ {$Out:name $In:[fields c:name]} /MPW G */ /[0-9A-Z.]+/ {$Wrt} ~ i_enzyme:~ {$Out:enzyme $In:[fields c:diag]} (/[0-9-]+\\.[0-9]+\\.[0-9]+\\.[0-9]+/{$Wrt} | /[^0-9.]+/ | /./)* ~ i_words: ~ {$In:fields $Out:words pre{$Skip:0}} tag? i_word* ~ i_word: ~ ( /[0-9-]+\\.[0-9-]+\\.[0-9-]+\\.[0-9-]+/ {$Wrt:$Itc $InWord=0} | /(--|__)/ {$inWord=0} | '_' {$App:[s:' ']} | /'([a-zA-Z0-9]+)'/ {if:$inWord $App:[s:$1] else {$Wrt:[$Itc s:$1] $inWord=1}}| /`([a-zA-Z0-9]+)`/ {if:$inWord $App:[s:$1] else {$Wrt:[$Itc s:$1] $inWord=1}}| /\\([,']([0-9+-]+)\\)/ {$App:[s:$1]} | /[a-zA-Z0-9.-]+/ {if:$inWord $App else {$Wrt:$Itc $inWord=1}} | /./ {$inWord=0} )+ ~ # html display h_field: ~ {$In:[fields t:hl]} tag {$t=$tags.$Ct if:$parInt:isTable $Rep:"" else $Rep:"
    $t
    " } /[ \n]*G +([A-Z0-9.]+) +!!/? {$Rep:"$1
    "} (/[ \n|]+/ | h_word)* | x:{$Prod:h_diag} ~ h_diag: ~ {pre{$Skip:0} $Skip:1} ln x:{$Rep:"

    "} 
                 (/[ \n|]+/ | h_word 
                 {if:$n $Rep:
              "($HtmlSpace:[($n/2) l:3 s:2])$Ct($HtmlSpace:[($n-$n/2) l:3 s:2])"})+
                 x:{$Rep:"
    "} ~ h_word: ~ {pre{$n=0}} ( /[0-9-]+\\.[0-9-]+\\.[0-9-]+\\.[0-9-]+/ {$Rep:{$ParStr:enzymeR $Ct $Ct}} | '_' {$Rep:' '} | /[^(`' \n]/ | /`([a-zA-Z0-9]+)`/ {$Rep:"$1" $n=$n+6} | /'([a-zA-Z0-9]+)'/ {$Rep:"$1" $n=$n+6} | /\\(,([^)]+)\\)/ {$Rep:"$1" $n=$n+9+$Strlen:$1} | /\\('([^')]+)\\)/ {$Rep:"$1" $n=$n+9+$Strlen:$1} | /[(`']/ )+ ~ # other appLn: ~ /[^\n]*\n/ {$App} ~ more: ~ (/ [^\n]*\n/)* ~ ln: ~ /[^\n]*\n/ ~ tag: ~ /[A-Z][A-Z][A-Z]?/ ~ } #$fil = $fileOpen:"/data/mpw/aac.asc" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #while:$jobTokens:[$job name:fields print:1] { # $jobTokens:[$job name:words print:1] # $jobEnd:$job # $jobNext:[$job file:$fil] #} # $RCSfile: pdb.i,v $ # $Revision: 1.1 $ # $Date: 1996/07/24 23:01:39 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PDB_DB:$library:[PDB group:@PROTSTRUCT_LIBS format:@PDB_FORMAT maxNameLen:30 ifiles:{"pdb.i" "pdb.is"} ] PDB_FORMAT:$libformat:[fileType:@PDB_FILE syntax:@PDB_SYNTAX fields:{ $field:[@DF_HeaderField name:'Title Section'] $field:[@DF_ID code:hea index:id indexToken:id] $field:[@DF_Date code:hea index:int indexToken:creDate] $field:[@DF_Compound code:com index:str indexToken:com tableToken:'t_fields|com'] $field:[@DF_Source code:com index:str indexToken:src] $field:[@DF_EntryAuthors code:entryAut index:str indexToken:entryAut] $field:[@DF_HeaderField name:'Primary Structure Section'] $field:[@DF_HeaderField name:'Annotation Section'] $field:[@DF_HeaderField name:'Crystallographic Section'] $field:[@DF_CRYST1 code:CRYST1 tableToken:'t_fields|CRYST1'] $field:[@DF_ORIGXn code:ORIGX tableToken:'t_fields|ORIGX'] $field:[@DF_SCALEn code:SCALE tableToken:'t_fields|SCALE'] $field:[@DF_MTRIXn code:MTRIX tableToken:'t_fields|MTRIX'] $field:[@DF_TVECT code:TVECT tableToken:'t_fields|TVECT'] $field:[@DF_MODEL code:MODEL tableToken:'t_fields|MODEL'] $field:[@DF_HeaderField name:'Coordinate Section'] $field:[@DF_ATOM token:'fields2|ATOM' tableToken:'t_fields2|ATOM'] $field:[@DF_SIGATM token:'fields2|SIGATM' tableToken:'t_fields2|SIGATM'] $field:[@DF_ANISOU token:'fields2|ANISOU' tableToken:'t_fields2|ANISOU'] $field:[@DF_SIGUJ token:'fields2|SIGUJ' tableToken:'t_fields2|SIGUJ'] $field:[@DF_TER token:'fields2|TER' tableToken:'t_fields2|TER'] $field:[@DF_HETATM token:'fields2|HETATM' tableToken:'t_fields2|HETATM'] $field:[@DF_ENDMDL token:'fields2|ENDMDL' tableToken:'t_fields2|ENDMDL'] } ] DF_EntryAuthors:$srsfield:[EntryAuthors short:eat] DF_CRYST1:$srsfield:[CRYST1 short:cr1] DF_ORIGXn:$srsfield:[ORIGXn short:ori] DF_SCALEn:$srsfield:[SCALEn short:sca] DF_MTRIXn:$srsfield:[MTRIXn short:mtr] DF_TVECT:$srsfield:[TVECT short:tve] DF_MODEL:$srsfield:[MODEL short:mod] DF_ATOM:$srsfield:[ATOM short:atm] DF_SIGATM:$srsfield:[SIGATM short:sig] DF_ANISOU:$srsfield:[ANISOU short:ani] DF_SIGUJ:$srsfield:[SIGUJ short:sgu] DF_TER:$srsfield:[TER short:ter] DF_HETATM:$srsfield:[HETATM short:htm] DF_ENDMDL:$srsfield:[ENDMDL short:end] PDB_SYNTAX:$syntax:[file:"SRSDB:pdb.is" ignore:" "] PDB_FILE:$FileType:[typename:'brk' singleEntry:y maxline:100] # the entry text: ~ {$In:[file:text] $Out init{$Skip:0}} 'HEADER ' {pre {$entryFip=$Fip} $Wrt} appLn ('ATOM ' {$Not} appLn)* ~ data: ~ {$Request:text $In:[file:text] } ln {$wrt} appLn+ ~ # fields from text fields: ~ {$In:text $Out} f_header f_title? f_compnd? f_source? f_keywrd? f_expdta? f_author? f_revDate? f_sprsde? (f_jhead|f_jrefn|f_jauthor|f_jtitle|f_jref|f_jrefn)+ f_remark2? f_remark3? f_remarks? f_primstr1* f_primstr2* f_annotSec* f_crystSec* ~ f_header: ~ {$Wrt:hea} 'HEADER' ln ~ f_title: ~ {$Wrt:titl} ('TITLE' ln)+ ~ f_compnd: ~ {$Wrt:com} ('COMPND' ln)+ ~ f_source: ~ {$Wrt:src} ('SOURCE' ln)+ ~ f_keywrd: ~ {$Wrt:key} ('KEY' ln)+ ~ f_expdta: ~ {$Wrt:exp} ('EXPDTA' ln)+ ~ f_author: ~ {$Wrt:entryAut} ('AUTHOR' ln)+ ~ f_revDate: ~ {$Wrt:revDate} ('REVDAT' ln)+ ~ f_sprsde: ~ {$Wrt:spr} ('SPRSDE' ln)+ ~ f_jhead: ~ {$Wrt:jhead} /(REMARK 1 REFERENCE|REMARK 1 )/ ln ~ f_jauthor: ~ {$Wrt:aut} (/(JRNL AUTH|REMARK 1 AUTH)/ ln)+ ~ f_jtitle: ~ {$Wrt:tit} (/(JRNL TITL|REMARK 1 TITL)/ ln)+ ~ f_jref: ~ {$Wrt:ref} (/(JRNL REF |REMARK 1 REF )/ ln)+ ~ f_jrefn: ~ {$Wrt:refn} (/(JRNL REFN |REMARK 1 REFN )/ ln)+ ~ f_remark2: ~ {$Wrt:rem2} ('REMARK 2' ln)+ ~ f_remark3: ~ {$Wrt:rem3} ('REMARK 3' ln)+ ~ f_remarks: ~ {$Wrt:rems} ('REMARK' ln)+ ~ f_primstr1:~ {$Wrt:$c} (/MODRES|DBREF|SEQADV|SEQRES|FTNOTE/{$c=$Ct} ln) ~ f_primstr2:~ {$Wrt:$c} (/HET|HETNAM|HETSYN|HETSIT|FORMUL|HELIX|SHEET|TURN/ {$c=$Ct} ln) ~ f_annotSec:~ {$Wrt:$c} (/SSBOND|SITE/ {$c=$Ct} ln) ~ f_crystSec:~ {$Wrt:$c} (/CRYST1|ORIGX|SCALE|MTRIX|TVECT|MODEL/ {$c=$Ct} ln) ~ # fields from data fields2: ~ {$In:data $Out} f_coord+ f_rest+ ~ f_coord: ~ {$Wrt:$c} (/ATOM|SIGATM|ANISOU|SIGUIJ|TER|HETATM|ENDMDL/ {$c=$Ct} ln) ~ f_rest: ~ {$Wrt:$c} (/CONECT|MASTER|END/ {$c=$Ct} ln)+ ~ #indexing productions id: ~ {$In:[fields c:hea] $Out $Mov:62} /[A-Z0-9]+/ {$Wrt} ~ creDate: ~ {$In:[fields c:hea] $Out $Mov:50} datenum {$Wrt:[s:$date]} ~ com: ~ {$In:[fields c:com] $Out} (x{$Mov:10} words {$Len:60} ln)+ ~ src: ~ {$In:[fields c:src] $Out} (x{$Mov:10} words {$Len:60} ln)+ ~ entryAut: ~ {$In:[fields c:entryAut] $Out} (x{$Mov:10} authors {$Len:60} ln)+ ~ aut: ~ {$In:[fields c:aut] $Out} (x{$Mov:18} authors {$Len:52} ln)+ ~ tit: ~ {$In:[fields c:tit] $Out} (x{$Mov:18} words {$Len:52} ln)+ ~ ref: ~ {$In:[fields c:ref] $Out} (x{$Mov:18} words {$Len:52} ln)+ ~ authors: ~ author (',' author?)* ~ author: ~ / *([^ ,]*\\.)([^ ,]*)/ {$Uniq:[s:"$2,$1"]} ~ words: ~ (/[A-Z0-9]+/ {$Uniq} | /[^A-Z0-9]+/)+ ~ datenum: ~ {init {$month={JAN:1 FEB:2 MAR:3 APR:4 MAY:5 JUN:6 JUL:7 AUG:8 SEP:9 OCT:10 NOV:11 DEC:12}}} / *([0-9]+)-([A-Z][A-Z][A-Z])-([0-9]+)/ {$date=$1 + $month.$2 * 100 + $3 * 10000 + 19000000} ~ # table display t_fields: ~ {$In:fields $Out} (x{$Mov:9 $Getc:62 $Wrt:$Itc} ln)+ ~ # html display h_com: ~ {$In:[t_fields c:com t:hl]} (/(E\\.C\\.|EC: *)([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)/ {$Rep:{"$1($ParStr:enzymeR)" $2 $2}} | /./)+ ~ # other productions word: ~ /[^ ]+/ ~ ln: ~ /[^\n]*\n/ ~ appLn: ~ /[^\n]*\n/ {$App} ~ } #$ff = $fileOpen:"/data/pdb/1tnp.brk" #$job = $jobNew:[prod:$rules skip:" \t\n"] #$jobNext:[$job file:$ff] ##$jobTokens:[$job name:id print:1] ##$jobTokens:[$job name:credate print:1] ##$jobTokens:[$job name:compound print:1] #$jobTokens:[$job name:id print:1] #$jobTokens:[$job name:t_fields print:1] ##$jobTokens:[$job name:entryAut print:1] #$print:"...........\n" ##$jobTokens:[$job name:aut print:1] ##$jobTokens:[$job name:date1 print:1] ##$jobTokens:[$job name:date1 print:1] #$jobEnd:$job #$jobNext:[$job file:$ff] # # $RCSfile: pdb.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:52 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The Protein Data Bank (PDB) is an archive of experimentally determined |three-dimensional structures of biological macromolecules, serving a |global community of researchers, educators, and students. The archives |contain atomic coordinates, bibliographic citations, primary and |secondary structure information, as well as crystallographic structure |factors and NMR experimental data. The PDB Newsletter and CD ROM are |published quarterly.

    The PDB is supported by a combination of |Federal Government Agency funds and user fees. Support is provided |by the U.S. National Science Foundation, the U.S. Public Health |Service, National Institutes of Health, National Center for Research |Resources, National Institutes of General Medical Sciences, National |Library of Medicine, and the U.S. Department of Energy under contract |DE-AC02-76CH00016 and user fees. |

    more: |

    |More on PDB |

    citation: | Reference: |PDB |Quarterly Newsletter ftpSite:'' date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: pdbfinder.i,v $ # $Revision: 1.5 $ # $Date: 1996/07/24 22:19:21 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PDBFINDER_DB:$library:[PDBFINDER group:@PROTSTRUCT_LIBS comment:"Directory for the Brookhaven Protein Data Bank" format:@PDBFINDER_FORMAT ifiles:{'pdbfinder.i' 'pdbfinder.is'} files:{ $file:pdbfinder } ] PDBFINDER_FORMAT:$libformat:[fileType:@PDBFINDER_FILE syntax:@PDBFINDER_SYNTAX subentries:@CHAIN_SUBENTRY fields:{ $field:[@DF_ALL] $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_Header code:header index:str indexToken:header tableToken:t_header tableFormat:left] $field:[@DF_Compound code:compound index:str indexToken:compound tableToken:t_compound tableFormat:left] $field:[@DF_EnzymeCode code:enzyme index:str indexToken:enzyme tableToken:enzyme tableFormat:left] $field:[@DF_Source code:source index:str indexToken:source tableToken:t_source tableFormat:left] $field:[@DF_Authors code:author index:str indexToken:author tableToken:author tableFormat:left] $field:[@DF_Date code:date index:int indexToken:date tableToken:t_date tableFormat:center] $field:[@DF_Resolution code:resolution index:real indexToken:resolution tableToken:resolution tableFormat:right] $field:[@DF_R_FACTOR code:rFactor index:real indexToken:rFactor tableToken:rFactor tableFormat:right] $field:[@DF_N_HSSP_ALIGN code:hsspNAlign index:int indexToken:hsspNAlign tableToken:hsspNAlign tableFormat:right] $field:[@DF_N_HET_GROUPS code:nHetGroups index:int indexToken:nHetGroups tableToken:nHetGroups tableFormat:right] $field:[@DF_EXP_METHOD code:expMethod index:str indexToken:expMethod tableToken:expMethod tableFormat:center] $field:[@DF_tFracHelix code:tFracHelix index:int indexToken:tFracHelix tableToken:tFracHelix tableFormat:right] $field:[@DF_T_NRES_PROT code:tNresProt index:int indexToken:tNresProt tableToken:tNresProt tableFormat:right] $field:[@DF_TWaterMols code:tWaterMols index:int indexToken:tWaterMols tableToken:tWaterMols tableFormat:right] # chain subentry $field:[@DF_ChainName code:chain index:str indexToken:chain indexId:@SUBENTRY_ID tableToken:chain tableFormat:center] $field:[@DF_N_NUCLACIDS code:nuc index:int indexToken:nuc indexId:@SUBENTRY_ID tableToken:nuc tableFormat:right] $field:[@DF_N_AMINOACIDS code:aa index:int indexToken:aa indexId:@SUBENTRY_ID tableToken:aa tableFormat:right] $field:[@DF_SecStruc code:secStruc] $field:[@DF_Helix code:helix index:int indexToken:helix tableToken:helix tableFormat:right] $field:[@DF_II3 code:ii3] $field:[@DF_II5 code:ii5] $field:[@DF_Beta code:beta] $field:[@DF_BBridge code:bBridge] $field:[@DF_ParaHb code:paraHn] $field:[@DF_AntiHb code:antiHB] $field:[@DF_MissBB code:missBB] $field:[@DF_MissSC code:missSC] $field:[@DF_Break code:break] $field:[@DF_Substrate code:substrate] $field:[@DF_WaterMols code:waterMols index:int indexToken:waterMols indexId:@SUBENTRY_ID tableToken:waterMols tableFormat:right] $field:[@DF_Sequence code:sequence tableToken:t_sequence tableFormat:left] } ] CHAIN_SUBENTRY:$subentry:[idType:@SUBENTRY_ID first:@DF_ChainName fields:{ $field:@DF_ChainName $field:@DF_N_NUCLACIDS $field:@DF_N_AMINOACIDS $field:@DF_SecStruc $field:@DF_Helix $field:@DF_II3 $field:@DF_II5 $field:@DF_Beta $field:@DF_BBridge $field:@DF_ParaHb $field:@DF_MissBB $field:@DF_WaterMols $field:@DF_Sequence } ] DF_Compound:$srsfield:[Compound short:com] DF_Header:$srsfield:[Header short:hdr] DF_Source:$srsfield:[Source short:src] DF_EXP_METHOD:$srsfield:[ExpMethod short:exp group:@DF_ALL] DF_N_HET_GROUPS:$srsfield:[NoHetGroups short:het group:@DF_ALL] DF_N_HSSP_ALIGN:$srsfield:[NoHSSPAlign short:nha] DF_tFracHelix:$srsfield:[TotFractHelix short:tfh group:@DF_ALL] DF_T_FRAC_BETA:$srsfield:[TotFractBeta short:tfb group:@DF_ALL] DF_T_NRES_PROT:$srsfield:[TotNResProt short:tnp group:@DF_ALL] DF_TWaterMols:$srsfield:[TotWaterMols short:twm group:@DF_ALL] DF_Resolution:$srsfield:[Resolution short:res group:@DF_ALL] DF_R_FACTOR:$srsfield:[RFactor short:rfa group:@DF_ALL] DF_ChainName:$srsfield:[ChainName short:chn group:@DF_ALL] DF_N_NUCLACIDS:$srsfield:[NucleicAcids short:nuc] DF_N_AMINOACIDS:$srsfield:[AminoAcids short:aa] DF_Substrate:$srsfield:[Substrate short:sub] DF_WaterMols:$srsfield:[WaterMols short:wat] DF_SecStruc:$srsfield:[SecStruc short:ss] DF_Helix:$srsfield:[Helix short:hel] DF_II3:$srsfield:[II3 short:ii3] DF_II5:$srsfield:[II5 short:ii5] DF_Beta:$srsfield:[Beta short:bet] DF_BBridge:$srsfield:[BetaBridge short:bbr] DF_ParaHb:$srsfield:[ParaHb short:phb] DF_AntiHb:$srsfield:[AntiHb short:ahb] DF_MissBB:$srsfield:[MissBB short:mbb] DF_MissSC:$srsfield:[MissSC short:msc] DF_Break:$srsfield:[Break short:bre] DF_WaterMols:$srsfield:[NWaterMols short:nwm] PDBFINDER_SYNTAX:$syntax:[file:"SRSDB:pdbfinder.is" ignore:" \t"] PDBFINDER_FILE:$filetype:[typename:dat maxline:5000] # $RCSfile: pdbfinder.is,v $ # $Revision: 1.4 $ # $Date: 1996/07/24 22:19:21 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $rules={ entry: ~ {$In:[file:text] $Out} ('ID' {$Not} ln)* 'ID :' {pre {$Skip:0 $entryFip = $Fip} $Wrt $chainN=0} appLn ('//' {$Noskip $Not} appLn {$Noskip})* '//' {$App} ~ # data fields fields: ~ {$In:entry $Out $Skip:1} / *ID *:/ {$Wrt:id} appLn / *Header *:/ {$Wrt:header} appLn / *Date *:/ {$Wrt:date} appLn (/ *Compound *:/ {$Wrt:compound} appLn)* (/ *Enzyme-Code *:/ {$Wrt:enzyme} appLn)? (/ *Source *:/ {$Wrt:source} appLn)* (/ *Author *:/ {$Wrt:author} appLn)* (/ *Exp-Method *:/ {$Wrt:expMethod} appLn | / *Resolution *:/ {$Wrt:resolution} appLn | / *R-Factor *:/ {$Wrt:rFactor} appLn | / *Free-R *:/ appLn | / *Ref-Prog *:/ {$Wrt:refProg} appLn | / *N-Models *:/ {$Wrt:nModels} appLn | / *HSSP-N-Align *:/ {$Wrt:hsspNAlign} appLn )* (/ *T-Frac-Helix *:/ {$Wrt:tFracHelix} appLn)? (/ *T-Frac-Beta *:/ {$Wrt:tFracBeta} appLn)? (/ *T-Nres-Prot *:/ {$Wrt:tNresProt} appLn)? (/ *T-non-Std *:/ appLn)? (/ *T-Nres-Nucl *:/ appLn)? (/ *T-Water-Mols *:/ {$Wrt:tWaterMols} appLn)? (/ *HET-Groups *:/ {$Wrt:nHetGroups} appLn (/ *Het-Id *:/ {$Wrt:hetId} appLn / *Natom *:/ {$Wrt:hetNAtom} appLn / *Name *:/ {$Wrt:hetName} appLn )* )? (/ *Chain *:/ {$Wrt:chain} appLn (/ *Sec-Struc *:/ {$Wrt:secStruc} appLn)? (/ *Helix *:/ {$Wrt:helix} appLn)? (/ *i,i\\+3 *:/ {$Wrt:ii3} appLn)? (/ *i,i\\+5 *:/ {$Wrt:ii5} appLn)? (/ *Beta *:/ {$Wrt:beta} appLn)? (/ *B-Bridge *:/ {$Wrt:bBridge} appLn)? (/ *E-Beta *:/ {$Wrt:missSC} appLn)? (/ *Para-Hb *:/ {$Wrt:paraHb} appLn)? (/ *Anti-Hb *:/ {$Wrt:antiHb} appLn)? (/ *Amino-Acids *:/ {$Wrt:aa} appLn)? (/ *non-Std *:/ {$Wrt:missSC} appLn)? (/ *Miss-BB *:/ {$Wrt:missBB} appLn)? (/ *Miss-SC *:/ {$Wrt:missSC} appLn)? (/ *only-Ca *:/ {$Wrt:missSC} appLn)? (/ *CYSS *:/ {$Wrt:missSC} appLn)? (/ *Break *:/ {$Wrt:break} appLn)? (/ *Nucl-Acids *:/ {$Wrt:nuc} appLn)? (/ *Substrate *:/ {$Wrt:substrate} appLn)? (/ *Water-Mols *:/ {$Wrt:waterMols} appLn)? (/ *Sequence *:/ {$Wrt:sequence} appLn)? )* ~ # index information id: ~ {$Out $In:[fields c:id]} tag /..../ {$Wrt} ~ header: ~ {$Out $In:[fields c:header]} tag (word {$Wrt} | sep)* ~ compound: ~ {$Out $In:[fields c:compound]} tag (word {$Wrt} | sep)* ~ enzyme: ~ {$Out $In:[fields c:enzyme]} tag /[0-9.-]+/ {$Wrt} ~ source: ~ {$Out $In:[fields c:source]} tag (word {$Wrt} | sep)* ~ author: ~ {$Out $In:[fields c:author]} tag /([A-Za-z.-]+\\.)([a-zA-Z ]+)/ {$Wrt:[s:"$2,$1"]} ~ date: ~ {$Out $In:[fields c:date]} tag /([0-9]+)-([0-9]+)-([0-9]+)/ {$Wrt:[s:"$1$2$3"]} ~ resolution: ~ {$Out $In:[fields c:resolution]} tag real {$Wrt} ~ rFactor: ~ {$Out $In:[fields c:rFactor]} tag real {$Wrt} ~ tFracHelix: ~ {$Out $In:[fields c:tFracHelix]} tag real {$Wrt} ~ nHetGroups: ~ {$Out $In:[fields c:nHetGroups]} tag int {$Wrt} ~ expMethod: ~ {$Out $In:[fields c:expMethod]} tag word {$Wrt} ~ hsspNAlign: ~ {$Out $In:[fields c:hsspNAlign]} tag int {$Wrt} ~ tNresProt: ~ {$Out $In:[fields c:tNresProt]} tag int {$Wrt} ~ tWaterMols: ~ {$Out $In:[fields c:tWaterMols]} tag int {$Wrt} ~ # chain: ~ {$Out $In:[fields c:chain count:chain var:$chN]} tag str {$Wrt:[n:$chN]} ~ nuc: ~ {$Out $In:[fields c:nuc count:chain var:$chN]} tag int {$Wrt:[n:$chN]} ~ aa: ~ {$Out $In:[fields c:aa count:chain var:$chN]} tag int {$Wrt:[n:$chN]} ~ helix: ~ {$Out $In:[fields c:sequence]} ln {$Wrt:[s:'77777']} ~ waterMols: ~ {$Out $In:[fields c:waterMols count:chain var:$chN]} tag int {$Wrt:[n:$chN]} ~ # table display t_source: ~ {$Out $In:[fields c:source]} wrtField ~ t_compound: ~ {$Out $In:[fields c:compound]} wrtField ~ t_header: ~ {$Out $In:[fields c:header]} wrtField ~ t_date: ~ {$Out $In:[fields c:date]} wrtField ~ t_sequence: ~ {$Out $In:[fields c:sequence]} tag ln {$Wrt:[s: | | | | ]} ~ # t_sequence: ~ {$Out $In:[fields c:sequence]} tag # ln {$Wrt:[s:""]} ~ # HTML display th_enzyme: ~ {$In:[enzyme t:hl]} /.*/ {$Rep:{$parStr:enzymeR $Ct $Ct}} ~ # other wrtField: ~ tag ln {$Wrt} ~ appLn: ~ /[^\n]*\n/ {$App} ~ ln: ~ /[^\n]*\n/ ~ tag: ~ /[^:]+:/ ~ int: ~ /[0-9]+/ ~ real: ~ /[0-9.]+/ ~ str: ~ /[0-9a-zA-Z_]+/ ~ word: ~ /[0-9a-zA-Z_]+/ ~ sep: ~ /[^0-9a-zA-Z_]+/ ~ } # # $RCSfile: pdbfinder.it,v $ # $Revision: 1.3 $ # $Date: 1996/07/30 10:26:53 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The PDBFINDER database is constructed using a PERL |script from the PDB, DSSP and HSSP databases. Many of the fields |contained in the PDBFINDER database are difficult to access from the |original databases. Some Information is retrieved from the original |literature. more: |

    | |More on PDBFINDER |

    citation:'' ftpSite:'' fields:{ ID: |

    The PDBFinder ID Field

    |The ID field contains the 4-letter PDB code of the |entry. It is always present. Header: |

    The PDBFinder Header Field

    |The Header field contains the information from the |HEADER records in the PDB file. It is always |present. Date: |

    The PDBFinder Date Field

    |from the HEADER records in the PDB file. |It contains the |date in the form "YYYY-MM-DD". It is always present. Compound: |

    The PDBFinder Compound Field

    |The Compound field contains the information from the |COMPND records in the PDB file. EnzymeCode: |

    The PDBFinder EnzymeCode Field

    |The Enzyme-Code fields contain E.C. numbers |extracted from the COMPND records in the PDB |file. Wildcards for the last numbers may be present as "-" characters. Source: |

    The PDBFinder Source Field

    |The Source field contains the information from the |SOURCE records in the PDB file. ExprSys: |

    The PDBFinder ExprSys Field

    |The Expr-Sys field contains the expression system |extracted from the SOURCE records in the PDB |file. Author: |

    The PDBFinder Author Field

    |Each of the Author fields contains an author name from the |PDB record AUTHOR. ExpMethod: |

    The PDBFinder ExpMethod Field

    |The Exp-Method field can contain one of the following: |
    |
    X |
    X-ray structure |
    NMR |
    NMR structure |
    FIBER |
    Fiber diffraction study |
    MODEL |
    A model without explicit experimental data |
    NEUTRON |
    Neutron diffraction study |
    OTHER |
    Currently Fluorescence Transfer and Electron Diffraction are | uncategorized. |
    | |The Exp-Method is derived from the EXPDTA field in |the PDB if present, otherwise it is derived from other sources. | Resolution: |

    The PDBFinder Resolution Field

    |The Resolution is derived from REMARK 2 in the |PDB file. For NMR structures and models no resolution is given. | RFactor: |

    The PDBFinder RFactor Field

    |The R-Factor for X-ray structures is derived from REMARK |3 and REMARK 4 if possible. For X-ray structures lacking |a valid R-factor in the PDB file, the R-factor field |is based on the original literature. A number of corrections to values |found in the PDB have also been applied. In some cases no |R-factor could be found, or the original literature does contain an |R-factor but the published coordinates are C-alpha only. In those |cases no R-Factor field is present. Also no R-factor is given |for NMR structures, because the calculation methods are too diverse. | FreeR: |

    The PDBFinder FreeR Field

    |The Free-R for X-ray structures is derived from REMARK |3. It is only given for some modern PDB files. NModels: |

    The PDBFinder NModels Field

    |The N-Models field gives the number of models preceded by |MODEL cards in the PDB file, if any. RefProg: |

    The PDBFinder RefProg Field

    |The Ref-Prog field contains any recognized names of |refinement programs, separated by slashes. Currently the following |program names are recognized: | |'AMBER', |'AMORE', |'ARP', |'ATOM', |'CALIBA', |'CEDAR', |'CHARMM', |'CORELS', |'CORMA', |'CRLS', |'CRYLSQ', |'DERIV', |'DGII', |'DIAMOND', |'DIANA', |'DINOSAUR', |'DISCOVER', |'DISGEO', |'DISMAN', |'DSPACE', |'ECEPP', |'EMBOSS', |'EREF', |'FANTOM', |'FREF', |'FRODO', |'GENERATE', |'GPRLSA', |'GRINCH', |'GROMOS', |'GROMOS-MDX', |'HABAS', |'HAFFIX', |'HKSCAT', |'INSIGHTII', |'IRMA', |'JACK-LEVITT', |'LOOP', |'MANOSK', |'MARDIGRAS', |'MIDGE', |'MM', |'MODELFIT', |'MUMOD', |'NCS', |'NOEMOL', |'NUCLIN', |'NUCLSQ', |'OMIT', |'OPAL', |'PIKSOL', |'PRESTO', |'PROFFT', |'PROLSQ', |'PROTEIN', |'PROTIN', |'PSFRODO', |'QUANTA', |'RESLSQ', |'RESTRAIN', |'ROTLSQ', |'RSREF', |'SCATT', |'SFALL', |'SFRK', |'SHELX', |'SHELXL', |'STEREOSEARCH', |'TNT', |'TOM', |'ULTIMA', |'VEMBED', |'X-PLOR', |'XEASY', |'YASAP'. | NoHSSPAlign: |

    The PDBFinder NoHSSPAlign Field

    |The HSSP-N-Align field gives the number of |different aligned sequences in the HSSP |database, if a HSSP file for the structure exists (Normally: |if the structure is a protein structure). TotFracHelix: |

    The PDBFinder TotFracHelix Field

    |The T-Frac-Helix field gives the fraction of the assigned |secondary structure that is helical: it is the total of the |Helix fields for all chains divided by the total of all |Sec-Struc fields. This field is only present if there is a |secondary structure. TotFracBeta: |

    The PDBFinder TotFracBeta Field

    |The T-Frac-Beta field gives the fraction of the assigned |secondary structure that is Beta: it is the total of the Beta |fields for all chains divided by the total of all Sec-Struc |fields. This field is only present if there is a secondary structure. TotNresProt: |

    The PDBFinder TotNresProt Field

    |The T-Nres-Prot field gives the total number of amino acid |residues in the structure, if any. Non-standard amino-acids are |included. TotNonStd: |

    The PDBFinder TotNonStd Field

    |The T-non-Std field gives the total number of non-standard |amino acid residues in the structure, if any. TotNresNucl: |

    The PDBFinder TotNresNucl Field

    |The T-Nres-Nucl field gives the total number of nucleic acid |residues in the structure, if any. TotWaterMols: |

    The PDBFinder TotWaterMols Field

    |The T-Water-Mols field gives the total number of water |molecules in the structure, if any. NoHetGroups: |

    The PDBFinder NoHetGroups Field

    |The HET-Groups field gives the number of HET cards |in the PDB file, if any. The following items are repeated for |every HET-group, and are all derived from the PDB HET cards. HetId: |

    The PDBFinder HetId Field

    |Het-Id gives the residue ID for each HET group. NAtom: |

    The PDBFinder NAtom Field

    |Natom gives the number of atoms in each HET group. Name: |

    The PDBFinder Name Field

    |Name gives the full name for each HET group. ChainName: |

    The PDBFinder ChainName Field

    |The Chain field and the subfields below are repeated once for |each polymer chain (DNA, RNA, Protein) in the structure. |The Chain |field contains the chain-identifier for the chain, if any. If there is |no chain identifier, the Chain field contains "_". SecStruc: |

    The PDBFinder SecStruc Field

    |The Sec-Struc field contains the number of residues in the |chain of which a secondary structure could be derived by the |DSSP program. Helix: |

    The PDBFinder Helix Field

    |The Helix field contains the number of residues in the chain |for which the secondary structure is helical (either alpha helical, |pi-helical or 3/10 helical). 'i,i+3': |The i,i+3 field contains the number of residues in the chain |for which the assigned secondary structure is "3/10 helix". | |

    Chain, Sec-Struc, Helix, i,i+5

    | |The i,i+5 field contains the number of residues in the chain |for which the assigned secondary structure is "pi helix". | |

    Chain, Sec-Struc, Beta

    | |The Beta field contains the number of residues in the chain |for which the secondary structure is "beta". | |

    Chain, Sec-Struc, Beta, B-Bridge

    | |The B-Bridge field contains the number of residues in the chain |for which the assigned secondary structure is "beta bridge" | |

    Chain, Sec-Struc, Beta, E-Beta

    | |The E-Beta field contains the number of residues in the chain |for which the assigned secondary structure is "extended beta" | ParaHb: |

    The PDBFinder ParaHb Field

    |The Para-Hb field contains the number of "parallel strand" |hydrogen bonds found in the chain. AntiHb: |

    The PDBFinder AntiHb Field

    |The Anti-Hb field contains the number of "antiparallel |strand" hydrogen bonds found in the chain. AminoAcids: |

    The PDBFinder AminoAcids Field

    |The Amino-Acids field contains the number of amino-acid |residues in the chain, including non-standard amino acids. Only |present if non-zero. NonStd: |

    The PDBFinder NonStd Field

    |The non-Std field contains the number of non-standard amino |acids in the chain, if any. | MissBB: |

    The PDBFinder MissBB Field

    |The Miss-BB field contains the number of amino acids in the |chain for which part of the backbone coordinates are missing from the |PDB file. MissSC: |

    The PDBFinder MissSC Field

    |The Miss-SC field contains the number of amino acids in the |chain for which at least part of the side-chain coordinates are |missing from the PDB file. OnlyCa: |

    The PDBFinder OnlyCa Field

    |The only-Ca field contains the number of amino acids in the |chain |for which only the alpha-carbon coordinates are given. Unk: |

    The PDBFinder Unk Field

    |The UNK field contains the number of amino acids in the chain |for which the amino acid type is unknown. Cyss: |

    The PDBFinder Cyss Field

    |The CYSS field contains the number of Cysteine |residues in the chain that are involved in Cysteine bridges. Break: |

    The PDBFinder Break Field

    |The Break field contains the number of chain |breaks in the chain. A chain break is counted whenever two |successive C-alpha atoms have a distance larger than 4.5 Angstrom. NuclAcids: |

    The PDBFinder NuclAcids Field

    |The Nucl-Acids field contains the number of nucleic acid |residues in the chain. Substrate: |

    The PDBFinder Substrate Field

    |The Substrate field contains the number of substrate atoms in |the chain. NwaterMols: |

    The PDBFinder NwaterMols Field

    |The Water-Mols field contains the number of water molecules in |the chain. Sequence: |

    The PDBFinder Sequence Field

    |The Sequence field contains the nucleic acid or protein |sequence derived from the PDB file. | | } } # # pmd.is # # Ramu C # $rules={ entry: ~ {init{$count=0} $out:entry $count=$count+1} ('ENTRY' {$not} ln)* ('ENTRY ' {pre {$entryFip = $fip} $wrt} ln {$app} ('///' {$not} ln {$app})* '///' {$app $fip:on})* ~ # fields fields: ~ {$in:entry $out} f_entry f_authors f_journal f_title f_crosref f_protein f_source f_nterm f_expsys(f_change | f_function | f_structure | f_stability | f_expr | f_trans | f_mut | f_var | f_cmnt) ~ f_ac: ~ {$wrt:ac} 'AC ' ln ~ f_dt: ~ {$wrt:dt} ('DT ' ln)* ~ f_so: ~ {$wrt:so} ('SO ' ln)* ~ f_os: ~ {$wrt:os} ('OS ' ln)* ~ f_cd: ~ {$wrt:cd} ('CD ' ln)* ~ f_xx: ~ ('XX' ln)? ~ # indexing ac: ~ {$in:[fields c:ac] $out:ac} 'AC' /[0-9A-Za-z]+/ {$wrt} ~ dt: ~ {$in:[fields c:dt] $out:dt} 'DT' /([0-9]+).([0-9]+).([0-9]+)/ {$wrt:[s:($1+$2*100+"19$3"*10000)]} ~ so: ~ {$in:[fields c:so] $out:so} 'SO' (sep | word {$wrt})* ~ os: ~ {$in:[fields c:os] $out:os} 'OS' (sep | word {$wrt})* ~ oc: ~ {$in:[fields c:cd] $out:cd} 'CD' (sep | word {$wrt})* ~ # extra ... ln: ~ /[^\n]*\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ } #$fil = $fileOpen:"/data/pmd/pmd.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #for:{1 $jobTokens:[$job name:dt print:1 ] 1} { # $jobEnd:$job # $jobNext:[$job file:$fil] #} #$jobEnd:$job ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# # The PCR Primers Database - 19 Jan 1996. # # Last modified - 14 Feb 1996. # # Author: Benny Shomer (bshomer@ebi.ac.uk) # # # # Many thanks to Jack Leunissen from CAOS/CAMM Center in the # # Netherlands for introducing independently a first working version # # and for introducing many important corrections into this file. # # # # Conversion to Icarus language by Thure Etzold # # # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# PRIMERS_DB:$library:[PRIMERS group:@MISC_LIBS format:@PRIMERS_FORMAT ifiles:{"primers.i" "primers.is"} files:{ $file:primers } ] PRIMERS_FORMAT:$libformat:[syntax:@PRIMERS_SYNTAX fileType:@PRIMERS_FILE fields:{ $field:[@DF_ID code:id indexToken:id index:str] $field:[@DF_Date code:date indexToken:date index:int] $field:[@DF_TARGET code:target index:str indexToken:target] $field:[@DF_NUMREF code:numref index:str indexToken:numref] $field:[@DF_Organism code:ospecs index:str indexToken:ospecs] $field:[@DF_SPAPLL code:spapll index:str indexToken:spapll] $field:[@DF_PNAME code:pname index:str indexToken:pname] $field:[@DF_PSEQN code:pseqn index:str indexToken:pseqn] $field:[@DF_RESTR code:restr index:str indexToken:restr] $field:[@DF_MUTAT code:mutat index:str indexToken:mutat] $field:[@DF_POLYMR code:polymr index:str indexToken:polymr] $field:[@DF_ADITIV code:aditiv index:str indexToken:aditiv] $field:[@DF_SOURCE code:source index:str indexToken:source] $field:[@DF_LINK code:{dbxref refxrf}] $field:[@DF_CONTRIBUTOR code:contrib index:str indexToken:contrib] $field:[@DF_Authors code:refaut index:str indexToken:refaut] $field:[@DF_REFTTL code:refttl index:str indexToken:refttl] $field:[@DF_REF code:refsrc index:str indexToken:refsrc] $field:[@DF_COMMENT code:comment index:str indexToken:comment] $field:[@DF_LINK code:link index:str indexToken:links] } ] #data field types DF_ATARGET:$srsfield:[Target short:TRG group:@DF_ALL] DF_NUMREF:$srsfield:[Number_ref short:NRF group:@DF_ALL] DF_SPAPLL:$srsfield:[Application short:APP group:@DF_ALL] DF_PNAME:$srsfield:[Primer_Name short:PNM group:@DF_ALL] DF_PSEQN:$srsfield:[Primer_Sequence short:PSQ group:@DF_ALL] DF_RESTR:$srsfield:[Restrict_Site short:RST group:@DF_ALL] DF_MUTAT:$srsfield:[Mutation short:MUT group:@DF_ALL] DF_POLYMR:$srsfield:[Polymerase short:POL group:@DF_ALL] DF_ADITIV:$srsfield:[Additive short:ADD group:@DF_ALL] DF_PSOURCE:$srsfield:[DNA_Source short:SRC group:@DF_ALL] DF_CONTRIBUTOR:$srsfield:[Contributor short:CNT group:@DF_ALL] DF_TARGET:$srsfield:[TargetSequence short:tsq group:@DF_ALL] DF_REFTTL:$srsfield:[ReferenceTitle short:rtl group:@DF_ALL] DF_SOURCE:$srsfield:[Source short:src group:@DF_ALL] #links to other databanks $link:[@PRIMERS_DB to:@?EMBL_DB token:'link:embl' toField:@DF_ID] $link:[@PRIMERS_DB to:@?EMNEW_DB token:'link:emnew' toField:@DF_ID] $link:[@PRIMERS_DB to:@?SWISSPROT_DB token:'link:swissprot' toField:@DF_ID] $link:[@PRIMERS_DB to:@?SWISSNEW_DB token:'link:swissnew' toField:@DF_ID] $link:[@PRIMERS_DB to:@?MEDLINE_DB token:'link:medline' toField:@DF_ID] $link:[@PRIMERS_DB to:@?IMGT_DB token:'link:imgt' toField:@DF_ACCNO] $link:[@PRIMERS_DB to:@?TFSITE_DB token:'link:tfsite' toField:@DF_ID] $link:[@PRIMERS_DB to:@?PIR_DB token:'link:pir' toField:@DF_ID] PRIMERS_SYNTAX:$syntax:[file:"SRSDB:primers.is" ignore:" "] PRIMERS_FILE:$filetype:[typeName:dat maxline:200] # the entry # the data fields fields: ~ id s date s target s (numref)? ospecs s spapll lncdna s lngnda (pname s pseqn s (restr s)? (mutat s)? flank s restr)* tcycle s probin s hotstr s idenat s denatr s anneal s tchdwn extend s prgrss s finext s cycles s rxnvol s polymr s buffer dntpcn s primcn s mgconc s aditiv s source s dbxref s cntnam contrib s refaut s refttl refxrf s remark ~ id: ~ {$wrt:id} 'ACCESS' ln ~ s: ~ {$wrt:s} ('XXXXXX' ln)* ~ # line spacer date: ~ {$wrt:} 'DATEIN' ln ~ target: ~ {$wrt:target} 'TARGET' ln ~ numref: ~ {$wrt:numref} 'NUMREF' ln ~ ospecs: ~ {$wrt:ospecs} 'OSPECS' ln ~ spapll: ~ {$wrt:spapll} 'SPAPPL' ln ~ lncdna: ~ {$wrt:lncdna} 'LNCDNA' ln ~ lngdna: ~ {$wrt:lngdna} 'LNGNDA' ln ~ pname: ~ {$wrt:pname} /FPNAME|RPNAME/ ln ~ pseqn: ~ {$wrt:pseqn} /FPSEQN|RPSEQN/ ln ~ flank: ~ {$wrt:flank} /FFLANK|RFLANK/ ln ~ restr: ~ {$wrt:restr} /FRESTR|RRESTR/ ln ~ mutat: ~ {$wrt:mutat} /FMUTAT|RMUTAT/ ln ~ tcycle: ~ {$wrt:tcycle} 'TCYCLE' ln ~ probin: ~ {$wrt:probin} 'PROBIN' ln ~ hotstr: ~ {$wrt:hotstr} 'HOTSTR' ln ~ idenat: ~ {$wrt:idenat} 'IDENAT' ln ~ denatr: ~ {$wrt:denatr} 'DENATR' ln ~ anneal: ~ {$wrt:anneal} 'ANNEAL' ln ~ tchdwn: ~ {$wrt:tchdwn} 'TCHDWN' ln ~ extend: ~ {$wrt:extend} 'EXTEND' ln ~ prgrss: ~ {$wrt:prgrss} 'PRGRSS' ln ~ finext: ~ {$wrt:finext} 'FINEXT' ln ~ cycles: ~ {$wrt:cycles} 'CYCLES' ln ~ rxnvol: ~ {$wrt:rxnvol} 'RXNVOL' ln ~ polymr: ~ {$wrt:polymr} 'POLYMR' ln ~ aditiv: ~ {$wrt:aditiv} 'ADITIV' ln ~ source: ~ {$wrt:source} 'SOURCE' ln ~ contrib: ~ {$wrt:contrib}/CNTNAM|CNTINS|CNTADR|CNTEML|CNTTEL|CNTFAX/ ln ~ refaut: ~ {$wrt:refaut} ('REFAUT' ln)+ ~ refttl: ~ {$wrt:refttl} 'REFTTL' ln ~ refsrc: ~ {$wrt:refsrc} 'REFSRC' ln ~ remark: ~ {$wrt:remark} ('REMARK' ln)+ ~ # indexing i_id: ~ {$in:[fields c:id] $out:id} tag name {$wrt} ~ i_target: ~ {$in:[fields c:target] $out:id} (tag (word {$wrt} sep)* ln)* ~ i_remark: ~ {$in:[fields c:remark] $out:id} (tag (word {$wrt} sep)* ln)* ~ i_link: ~ (tag refdb ':' (name {$wrt:$c} ';')* ln)* ~ # display HTML h_link: ~ {$in:[fields c:dbxref] $out:link} (tag refdb ':' (name {$rep:$parStr:{"$db_hl" $ct $ct}} ';')* ln)* ~ # other stuff refdb: ~ 'EMBL/GENBANK/DDBJ' {$db=embl $c=$embl} | 'MEDLINE' {$db=medline $c=$medline} | 'IMGT/LIGM' {$db=imgt $c=$imgt} | 'SWISS-PROT' {$db=swissprot $c=$swissprot} | 'TRANSFAC' {$db=transfac $c=$transfac} | 'PIR' {$db=pir $c=pir} ~ ln: ~ /[^\n]\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ name: ~ /[a-zA-Z][a-zA-Z0-9_]*/ ~ tag: ~ /....../ ~ } # $RCSfile: prosite.i,v $ # $Revision: 1.6 $ # $Date: 1996/08/11 22:51:53 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROSITE_DB:$library:[PROSITE group:@SEQRELATED_LIBS comment:"A Dictionary of Protein Sites and Patterns - A. Bairoch" format:@PROSITE_FORMAT maxNameLen:30 ifiles:{"prosite.i" "prosite.is"} files:{ $file:prosite } ] PROSITE_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@PROSITE_SYNTAX fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_PATTERN code:patt tableToken:t_patt tableFormat:left] $field:[@DF_Accession code:acc index:str indexToken:acc tableToken:acc tableFormat:left] $field:[@DF_Description code:def index:str indexToken:def tableToken:t_descr tableFormat:left] $field:[@DF_LINK code:link] $field:[@DF_Date code:date index:int indexToken:date tableToken:t_date tableFormat:center] $field:[@DF_ALLPOS code:rule index:int indexToken:allpos tableToken:allpos tableFormat:right] } ] PROSITE_SYNTAX:$syntax:[file:"SRSDB:prosite.is" ignore:" "] DF_PATTERN:$srsfield:[Patterns short:pat] DF_ALLPOS:$srsfield:[AllPositive short:alp] $link:[@PROSITE_DB to:@?SWISSPROT_DB token:'link|swiss' toField:@DF_Accession] $link:[@PROSITE_DB to:@?PDB_DB token:'link|pdb' toField:@DF_ID] $link:[@PROSITE_DB to:@?PROSITEDOC_DB token:'link|pd' toField:@DF_ID] entry: ~ { $In:[file:text] $Out:entry} ('ID' {$Not} ln)* ('ID ' {$entryFip=$Fip $Wrt} ln {$App} ('ID' {$Not} ln {$App})*)? ~ # fields fields: ~ {$In:entry $Out} f_id f_acc f_date f_def (f_mat)? f_patt f_rule f_cc f_links ~ f_id: ~ {$Wrt:id} 'ID ' ln ~ f_acc: ~ {$Wrt:acc} ('AC ' ln)* ~ f_date: ~ {$Wrt:date} ('DT ' ln)* ~ f_def: ~ {$Wrt:def} ('DE ' ln)* ~ f_mat: ~ {$Wrt:mat} ('MA ' ln)* ~ f_patt: ~ {$Wrt:patt} ('PA ' ln)* ~ f_rule: ~ {$Wrt:rule} (/(NR|RU) / ln)* ~ f_cc: ~ {$Wrt:cc} ('CC ' ln)* ~ f_links: ~ {$Wrt:link} (/(DR|3D|DO) / ln)* ~ # indexing id: ~ {$In:[fields c:id] $Out:id} 'ID' /[A-Z0-9_]+/ {$Wrt} ~ acc: ~ {$In:[fields c:acc] $Out:acc} 'AC' /[A-Z0-9_]+/ {$Wrt} ~ def: ~ {$In:[fields c:def] $Out} ( 'DE' ( /[A-Za-z0-9_]+/ {$Wrt} | /[^A-Za-z0-9_]+/ )* )* ~ date: ~ {$In:[fields c:date] $Out} 'DT' datenum {$Wrt:[s:$date c:cre]} '(CREATED);' datenum {$Wrt:[s:$date c:dupd]} '(DATA UPDATE);' datenum {$Wrt:[s:$date c:iupd]} '(INFO UPDATE).' ~ allpos: ~ {$In:[fields c:rule] $Out} (/.*POSITIVE=([0-9]+)/ {$Wrt:[s:$1]})? ~ datenum: ~ {init {$month={JAN:1 FEB:2 MAR:3 APR:4 MAY:5 JUN:6 JUL:7 AUG:8 SEP:9 OCT:10 NOV:11 DEC:12}}} /([A-Z][A-Z][A-Z])-([0-9]+)/ {$date=$month.$1 * 100 + $2 * 10000} ~ link: ~ {$In:[fields c:link] $Out} (/DR/ (name {$Wrt:swiss} ',' name ',' /[A-Z?]/ ';')* ln)* (/3D/ (name {$Wrt:pdb} (';'|'.'))* ln)* /DO/ name {$Wrt:pd} ~ # table display t_date: ~ {$In:[fields c:date] $Out} /.* ([A-Z0-9-]+) *\\(CREATED/ {$Wrt:[s:$1]} ~ t_patt: ~ {$In:[fields c:patt] $Out} /../ ln {$Wrt} (/../ ln {$App})* ~ t_descr: ~ {$In:[fields c:def] $Out} /../ ln {$Wrt} ~ # html display hl_links:~ {$In:[fields c:link t:hl]} (/DR/(name {$Rep:{$ParStr:swissR $Ct $Ct}} ','name',' /[A-Z?]/ ';')* ln)* (/3D/ (name {$Rep:{$ParStr:pdbR $Ct $Ct}} (';'|'.') )* ln)* /DO/ name {$Rep:{$ParStr:prositedocR $Ct $Ct}} ~ # other name: ~ /[a-zA-Z0-9_]+/ ~ ln: ~ /[^\n]*\n/ ~ } #$fil = $fileOpen:"/data/prosite/prosite.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] ##for:{1 $jobTokens:[$job name:fields code:dr task:hl print:1] 1} { #$print:"-------->entry\n" #for:{1 $jobTokens:[$job name:fields print:1 task:hl] 1} { # $jobEnd:$job # $jobNext:[$job file:$fil] # $print:"-------->entry\n" #} # # $RCSfile: prosite.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:54 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The PROSITE data bank is composed of two ASCII (text) files. The first |file (PROSITE.DAT) is a computer readable file that contains all the |information necessary to programs that will scan sequence(s) with patterns |and/or matrices. The second file (PROSITE.DOC) contains textual |information that fully documents each pattern and profile. We must point |out that we strongly urge software developers to build software tools that |make use of both files. A list of patterns or profiles present in a |sequence is not very useful to biologists without the relevant |documentation. |

    more: |

    |More on PROSITE |

    citation: | Reference: |Bairoch A., Bucher P., PROSITE: recent developments. |Nucleic Acids Res. 22:3583-3589(1994). ftpSite:'' fields:{ ID: |

    Prosite ID Field

    |The ID (IDentification) line is always the first line of an |entry. The general form of the ID line is: |

    |ID ENTRY_NAME; ENTRY_TYPE. |

    |The first item on the ID line is the entry name. This name is a useful |means of identifying an entry. The entry name consists of from 2 to 21 |uppercase alphanumeric characters. The characters that are allowed in an |entry name are: A-Z, 0-9, and the underscore character "_". |

    AccNumber: |

    Prosite Accession Number

    |The AC (ACcession number) line lists the accession number |associated with an entry. It is always the second line of an entry. |Accession numbers provide a stable way of identifying entries |from release to release. It is sometimes necessary for reasons of |consistency to change the names of the entries between releases.

    |An accession number, however, never change. Accession numbers allow |unambiguous citation of database entries. Researchers who wish to cite |a PROSITE entry in their publications should always cite the accession |number of that entry in order to ensure that readers can find the |relevant data in a subsequent release.

    The format of the AC line |is:

    AC PSnnnnn;

    Where `PS' stands for PROSITE and `nnnnn' is a |five digit number.

    Patterns: |

    Prosite Pattern Field

    |The PA (PAttern) lines contains the definition of a PROSITE |pattern. The patterns are described using the following conventions: |
      |
    • The standard IUPAC one-letter codes for the amino acids are used. |
    • The symbol `x' is used for a position where any amino acid is |accepted. |
    • Ambiguities are indicated by listing the acceptable amino acids for |a given position, between square parentheses `[ ]'. For example: [ALT] |stands for Ala or Leu or Thr. |
    Matrix: |

    Prosite Matrix Field

    |The MA (MAtrix) lines contain the definition of a PROSITE |profile (or matrix) entry. The exact format content of this line is |fully described in a specific document (PROFILE.TXT) which is part of |the PROSITE distribution files.

    Rule: |

    Prosite Rule Field

    |The RU (RUle) lines contain the definition of a PROSITE rule |entry. The format of the RU line is:

    |

    |DE Rule_Description. |

    |The rule is described in ordinary English and is free-format. |

    Result: |

    Prosite Result Field

    |The NR (Numerical Results) lines contain information relevant |to the results of the scan with a pattern on the complete SWISS-PROT |data bank. Comment: |

    Prosite Comment Field

    |The CC (Comments) lines contains various types of comments. The |format of the CC line is: |

    |CC /QUALIFIER=data; /QUALIFIER=data; ....... |

    |The qualifiers that are currently defined are: |

    |/TAXO-RANGE Taxonomic range. |/MAX-REPEAT Maximum known number of repetitions of the pattern in a | single protein. |/SITE Indication of an `interesting' site in the pattern. |/SKIP-FLAG Indication of an entry that can be, in some cases, ignored | by a program (because it is too unspecific). |

    Ref: |

    Prosite Ref Field

    | The DR (Data bank Reference) line(s) are used as pointers to | the SWISS- PROT entries that corresponds to the enzyme being described. | The format | of the DR line is: |

    | DR AC_NB, ENTRY_NAME; AC_NB, ENTRY_NAME; AC_NB, ENTRY_NAME; |

    | where: |

    | - 'AC_NB' is the SWISS-PROT primary accession number of the entry to | which reference is being made. | - 'ENTRY_NAME' is the SWISS-PROT entry name. |

    3D: |

    Prosite 3D Field

    |

    |The 3D (3D-structure) line is used to list the code(s) of X-ray |crystallography Protein Data Bank (PDB) entries that contain structural |data corresponding the sequence region described in a PROSITE entry. The |format of the 3D line is: |

    |3D name; [name2;...] |

    Doc: |

    Prosite Doc Field

    |The DO (DOcumentation) line contains a pointer to the entry in |the PROSITE documentation file that describes the entry. The format of |the DO line is:

    DO PDOCnnnnn;

    Where `PDOC' stands for PROSITE |DOCumentation and `nnnnn' is a five digit number.

    } date: |25 Jul 1996 signature: |Anatoly Ulyanov } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: prositedoc.i,v $ # $Revision: 1.4 $ # $Date: 1996/08/11 22:51:53 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROSITEDOC_DB:$library:[PROSITEDOC group:@SEQRELATED_LIBS comment:"A Dictionary of Protein Sites and Patterns - A. Bairoch" format:@PROSITEDOC_FORMAT maxNameLen:10 ifiles:{"prositedoc.i" "prositedoc.is"} files:{ $file:prosite } ] PROSITEDOC_FORMAT:$libformat:[fileType:@PDOC_FILE syntax:@PROSITEDOC_SYNTAX fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_Description code:des] $field:[@DF_Authors index:str code:litref indexToken:authors] $field:[@DF_LINK index:link code:proslink indexToken:links] } ] PROSITEDOC_SYNTAX:$syntax:[file:"SRSDB:prositedoc.is" ignore:" "] PDOC_FILE:$filetype:[typename:doc maxline:200] #$link:[@PROSITEDOC_DB to:@?PROSITE_DB token:'link' toField:@DF_Accession] /srs5/bin/osf/try $rules={ entry: ~ {$In:[file:text] $Out pre{$Skip:0}} ('{PDOC' {$Not} ln)* ('{PDOC' {$entryFip=$Fip $Wrt} appLn ('{END' {$Not} appLn)* appLn)? ~ # fields fields: ~ {$In:entry $Out $Skip:1} f_id f_proslink f_title f_des (f_litref)* ~ f_id: ~ {$Wrt:id} '{PDOC' ln ~ f_proslink: ~ {$Wrt:proslink} ('{PS' ln)* ~ f_title: ~ {$Wrt:title} '{BEGIN}' ln ln ln ln ~ f_des: ~ {$Wrt:des} ('[' {$Not} ln)* ~ f_litref: ~ {$Wrt:litref} /\\[[0-9 ][0-9 ]\\] / ln (/(\\[|{END})/ {$Not} ln)* ~ # indexing id: ~ {$In:[fields c:id] $Out:id} '{' /[^}]+/ {$Wrt} ~ authors: ~ {$In:[fields c:litref] $Out} /[^a-zA-Z]+/ author (',' author)* ~ link: ~ {$In:[fields c:proslink] $Out} '{' name {$Wrt} ~ # html display hl_links: ~ {$In:[fields c:proslink t:hl]} ('{' /[^;]+/ {$Rep:{$parStr:prositeR $ct $ct}} ln)+ ~ h_des: ~ {$In:[fields c:des t:hl]} (/PDOC[0-9]+/ {$Rep:{$parStr:prositedocR $ct $ct}} | /(EC +)([0-9]\\.[0-9.]+)/{$Rep:{"$1($parStr:enzymeR)" $2 $2}} | /[a-zA-Z0-9]+/ | /[^a-zA-Z0-9]+/ )* ~ # other name: ~ /[a-zA-Z0-9_]+/ ~ ln: ~ /[^\n]*\n/ ~ appLn: ~ /[^\n]*\n/ {$App} ~ author: ~ /([^.,\n]+) +([^,;\n]+)/ {$Wrt:[s:"$1,$2"]} ~ } # # $RCSfile: prositedoc.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:55 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The PROSITE data bank is composed of two ASCII (text) files. The first |file (PROSITE.DAT) is a computer readable file that contains all the |information necessary to programs that will scan sequence(s) with patterns |and/or matrices. The second file (PROSITE.DOC) contains textual |information that fully documents each pattern and profile. We must point |out that we strongly urge software developers to build software tools that |make use of both files. A list of patterns or profiles present in a |sequence is not very useful to biologists without the relevant |documentation. |

    more: |

    |More on PROSITE |

    citation: | Reference: |Bairoch A., Bucher P., PROSITE: recent developments. |Nucleic Acids Res. 22:3583-3589(1994). ftpSite:'' date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: reptilia.i,v $ # $Revision: 1.4 $ # $Date: 1996/08/11 22:51:54 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ REPTILIA_DB:$library:[REPTILIA group:@MISC_LIBS format:@REPTILIA_FORMAT maxNameLen:50 ifiles:{"reptilia.i" "reptilia.is"} files:{ $file:reptilia } ] REPTILIA_FORMAT:$libformat:[fileType:@REPTILIA_FILE syntax:@REPTILIA_SYNTAX printFormat:topicList fields:{ $field:[@DF_ID code:spec index:id indexToken:id] $field:[@DF_Synonyms code:syn index:str indexToken:syn tableFormat:left] $field:[@DF_Distribution code:distrib index:str indexToken:distrib tableFormat:left] } ] REPTILIA_SYNTAX:$syntax:[file:"SRSDB:reptilia.is"] DF_Distribution:$srsfield:[Distribution short:dis] DF_Synonyms:$srsfield:[Synonyms short:syn] REPTILIA_FILE:$filetype:[typename:dat maxline:5000] $link:[@REPTILIA_DB to:@GENBANK_DB fromField:@DF_ID toField:@DF_Organism] entry: ~ { $In:[file:text] $Out pre{$skip:0}} ('Species:'{$Not} ln)* (ln {pre{$entryFip=$Fip} $Wrt} ('//'{$Not} ln {$App})+)? ~ fields: ~ {$In:entry $Out} spec syn distrib comment reference~ spec: ~ {$Wrt:spec} 'Species:\n' data ~ syn: ~ {$Wrt:syn} 'Synonyms:\n' data* ~ distrib: ~ {$Wrt:distrib} 'Distribution:\n' data* ~ comment: ~ {$Wrt:comment} 'Comment:\n' data* ~ reference: ~ {$Wrt:reference} 'References:\n' data* ~ # indexing i_species: ~ {$In:[fields c:spec] $Out:id} tag specName {$Wrt:[s:$name]} ~ i_syn: ~ {$In:[fields c:syn] $Out:syn} tag (specName {$Uniq:[s:$name]} (/[ \t\n],[ \t\n]/ specName {$Uniq:[s:$name]})*)? ~ i_distrib: ~ {$In:[fields c:distrib] $Out:distrib} tag (word {$Uniq} | sep) * ~ # html h_field: ~ {$In:[fields t:hl]} tag {if:$ParInt:isTable $Rep:"" else $Rep:"
    $Ct
    " } ~ # others word: ~ /[a-zA-Z0-9]+/ ~ sep: ~ /[^a-zA-Z0-9]+/ ~ specName: ~ / *([^ ]+ +[^ \n\t]+)/ {$name=$1} ~ data: ~ ' ' ln ~ ln: ~ /[^\n]*\n/ ~ tag: ~ /[^:]+:\n/ ~ } #$fil = $fileOpen:"/opt/srs/data/reptilia/reptilia.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #while:$jobTokens:[$job name:syn print:1] { # $jobEnd:$job # $jobNext:[$job file:$fil] #} #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSfile: srsdb.i,v $ # $Revision: 1.14 $ # $Date: 1996/08/11 23:05:38 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file:"SRSDB:swissprot.i" file:"SRSDB:prosite.i" file:"SRSDB:prositedoc.i" file:"SRSDB:enzyme.i" file:"SRSDB:pdbfinder.i" file:"SRSDB:mpw.i" file:"SRSDB:emp.i" file:"SRSDB:blast.i" file:"SRSDB:fasta.i" file:"SRSDB:primers.i" file:"SRSDB:tfcell.i" file:"SRSDB:tffactor.i" file:"SRSDB:tfsite.i" file:"SRSDB:tfclass.i" file:"SRSDB:tfmatrix.i" file:"SRSDB:genbank.i" file:"SRSDB:epd.i" file:"SRSDB:ypd.i" file:"SRSDB:pdb.i" file:"SRSDB:reptilia.i" file:"SRSDB:taxonomy.i" $site:[name:unix libs:{ $libloc:[@SWISSPROT_DB dir:"/data/swissprot/"] $libloc:[@GENBANK_DB dir:"/data/genbank/"] $libloc:[@PROSITE_DB dir:"/data/prosite/"] $libloc:[@PROSITEDOC_DB dir:"/data/prosite/"] $libloc:[@ENZYME_DB dir:"/data/enzyme/"] $libloc:[@PDBFINDER_DB dir:"/data/pdbfinder/"] $libloc:[@MPW_DB dir:"/data/mpw/"] $libloc:[@BLAST_DB dir:"" indexDir:""] $libloc:[@FASTA_DB dir:"" indexDir:""] $libloc:[@PRIMERS_DB dir:"/data/primers/"] $libloc:[@YPD_DB dir:"/data/ypd/"] $libloc:[@TFCELL_DB dir:"/data/transfac/"] $libloc:[@TFFACTOR_DB dir:"/data/transfac/"] $libloc:[@TFSITE_DB dir:"/data/transfac/"] $libloc:[@TFCLASS_DB dir:"/data/transfac/"] $libloc:[@TFMATRIX_DB dir:"/data/transfac/"] $libloc:[@EMP_DB dir:"/opt/srs/data/emp/"] $libloc:[@EPD_DB dir:"/data/epd/"] $libloc:[@PDB_DB dir:"/data/pdb/"] $libloc:[@REPTILIA_DB dir:"/opt/srs/data/reptilia/"] $libloc:[@TAXONOMY_DB dir:"/opt/srs/data/taxonomy/"] } ] # hypertext links to be inserted into entries before display $href:[medlineR link:"%s"] $href:[mpwR link:"%s"] $href:[swissR link:"%s"] $href:[pidR link:"%s"] $href:[pdbR link:"%s"] $href:[prositedocR link:"%s"] $href:[prositeR link:"%s"] $href:[enzymeR link:"%s"] $href:[pirR link:"%s"] $href:[emblR link:"%s"] $href:[genbankR link:"%s"] $href:[hsspR link:"%s"] $href:[ecogeneR link:"%s"] $href:[mimR link:"%s"] $href:[pdbR link:"%s"] $href:[epdR link:"%s"] $href:[transfacR link:"%s"] $href:[listaR link:"%s"] $href:[yepdR link:"%s"] $href:[sgdR link:"%s"] $href:[stygeneR link:"%s"] $href:[hivR link:"%s"] $href:[eco2dbaseR link:"%s"] $href:[subtilistR link:"%s"] $href:[flybaseR link:"%s"] $href:[aarhusR link:"%s"] $href:[gcrdbR link:"%s"] $href:[wormpepR link:"%s"] $href:[swiss2dpageR link:"%s"] $href:[swissFeatR link:"%s"] # added ramu, useful for any database which has accno $href:[dbaseR link:"%s"] $href:[dbase_idR link:"%s"] $srsdb:[ libIds:{ $libid:[1 lib:@?SWISSPROT_DB] $libid:[8 lib:@?SWISSNEW_DB] $libid:[2 lib:@?PIR_DB] $libid:[3 lib:@?EMBL_DB] $libid:[4 lib:@?EMBLNEW_DB] $libid:[5 lib:@?GENBANK_DB] $libid:[6 lib:@?NRL3D_DB] $libid:[7 lib:@?TREMBL_DB] $libid:[9 lib:@?TREMBLNEW_DB] $libid:[21 lib:@?PDB_DB] $libid:[22 lib:@?PDBNEW_DB] $libid:[23 lib:@?HSSP_DB] $libid:[24 lib:@?DSSP_DB] $libid:[25 lib:@?ALI_DB] $libid:[26 lib:@?FSSP_DB] $libid:[27 lib:@?PDBFINDER_DB] $libid:[41 lib:@?PROSITE_DB] $libid:[42 lib:@?PROSITEDOC_DB] $libid:[43 lib:@?BLOCKS_DB] $libid:[44 lib:@?EPD_DB] $libid:[46 lib:@?ECDC_DB] $libid:[47 lib:@?MIM_DB] $libid:[48 lib:@?MIMMAP_DB] $libid:[49 lib:@?ENZYME_DB] $libid:[50 lib:@?REBASE_DB] $libid:[51 lib:@?CPGISLE_DB] $libid:[52 lib:@?MOLPROBE_DB] $libid:[53 lib:@?PRODOM_DB] $libid:[54 lib:@?PMD_DB] $libid:[55 lib:@?FLYGENE_DB] $libid:[56 lib:@?SWISSDOM_DB] $libid:[65 lib:@?PIRALN_DB] $libid:[66 lib:@?YPD_DB] $libid:[67 lib:@?MPW_DB] $libid:[68 lib:@?PRIMERS_DB] $libid:[69 lib:@?EMP_DB] $libid:[70 lib:@?TAXONOMY_DB] $libid:[81 lib:@?SEQANALREF_DB] $libid:[82 lib:@?SEQANALRABS_DB] $libid:[83 lib:@?PROTSTRUCTLIT_DB] $libid:[90 lib:@?MEDLINE_DB] $libid:[91 lib:@?YPDREF_DB] $libid:[101 lib:@?NAKAI_DB] $libid:[102 lib:@?LIMB_DB] $libid:[110 lib:@?TFSITE_DB] $libid:[111 lib:@?TFFACTOR_DB] $libid:[112 lib:@?TFCELL_DB] $libid:[113 lib:@?TFCLASS_DB] $libid:[114 lib:@?TFMATRIX_DB] $libid:[201 lib:@?FASTA_DB] $libid:[202 lib:@?BLAST_DB] $libid:[203 lib:@?PROFILE_DB] $libid:[204 lib:@?BLITZ_DB] $libid:[230 lib:@?REPTILIA_DB] $libid:[231 lib:@?MEDIA_DB] } ] # # $RCSfile: swissprot.i,v $ # $Revision: 1.6 $ # $Date: 1996/08/11 22:51:55 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SWISSPROT_DB:$library:[SWISSPROT group:@SEQUENCE_LIBS comment:" A Dictionary of Protein Sites and Patterns - A. Bairoch" format:@SWISSPROT_FORMAT cachesize:512 maxNameLen:30 files:{ $file:seq } ] # #SWISSPROT_DB:$library:[SWISSPROT group:@SEQUENCE_LIBS # comment:" A Dictionary of Protein Sites and Patterns - A. Bairoch" # forward:{@SWISSREL_DB @SWISSNEW_DB} redundant:n #] # #SWISSPROT_DB:$library:[SWISSREL group:@SEQUENCE_LIBS # format:@SWISSPROT_FORMAT cachesize:512 maxNameLen:30 files:{ # $file:seq # } #] # #SWISSPROT_DB:$library:[SWISSNEW group:@SEQUENCE_LIBS # format:@SWISSPROT_FORMAT cachesize:512 maxNameLen:30 files:{ # $file:seq # } #] SWISSPROT_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@SWISSPROT_SYNTAX subentries:@Seqfeature_Subentry fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:@DF_ALL $field:[@DF_Accession code:acc index:str indexToken:acc tableToken:acc tableFormat:left] $field:[@DF_Description code:def index:str indexToken:def tableToken:t_def tableFormat:left] $field:[@DF_Authors code:refaut index:str indexToken:authors tableToken:authors tableFormat:left] $field:[@DF_LINK index:link code:link indexToken:link] $field:[@DF_Date code:date index:int indexToken:date tableToken:date tableFormat:center] $field:[@DF_SeqLength index:int indexToken:seqlength code:seqTitle tableToken:seqlength tableFormat:right] $field:[@DF_MOLWEIGHT index:int indexToken:molweight code:seqTitle tableToken:molweight tableFormat:right] $field:[@DF_Features index:str indexToken:features code:features indexId:@SUBENTRY_ID] $field:[@DF_FEATLEN index:int indexToken:featlen code:features indexId:@SUBENTRY_ID tableToken:featlen tableFormat:right] $field:[@DF_PROTSEQUENCE code:seq] } ] DF_FEATLEN:$srsfield:[featureLength short:ftl] SWISSPROT_SYNTAX:$syntax:[file:"SRSDB:swissprot.is" ignore:" \t"] $link:[@SWISSPROT_DB to:@?EMBL_DB toField:@DF_Accession] #$link:[@SWISSPROT_DB to:@?EMBL_DB toField:@DF_PID # toName:EMBLFeature] $link:[@SWISSPROT_DB to:@?GENBANK_DB toField:@DF_Accession] $link:[@SWISSPROT_DB to:@?PIR_DB token:'link|PIR' toField:@DF_Accession] $link:[@SWISSPROT_DB to:@?PDB_DB token:'link|PDB'toField:@DF_ID] $link:[@SWISSPROT_DB to:@?REBASE_DB toField:@DF_ID] $link:[@SWISSPROT_DB to:@?OMIM_DB toField:@DF_ID] $link:[@SWISSPROT_DB to:@?MEDLINE_DB toField:@DF_ID] $link:[@SWISSPROT_DB to:@?ENZYME_DB fromField:@DF_Description toField:@DF_ID] Seqfeature_Subentry:$subentry:[idType:@SUBENTRY_ID first:@DF_Features fields:{ $field:[@DF_ID token:'feature|id'] $field:@DF_Description $field:@DF_Organism $field:[@DF_Features token:'feature|body'] $field:[@DF_FEATLEN] $field:[@DF_PROTSEQUENCE token:ftSeq] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: swissprot.is,v $ # $Revision: 1.6 $ # $Date: 1996/08/11 22:51:56 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $rules={ entry: ~ {$In:[file:text] $Out} ('ID ' {$not} ln)* ('ID '{$entryFip=$fip $Wrt} ln {$App} ('//' {$Not} ln {$App})* '//' {$App})? ~ # extracting data fields fields: ~ {$In:entry $Out} id acc date def gene org organel tax reference comment link key (feature)* seqTitle sequence ~ id: ~ {$Wrt:id} 'ID ' /[A-Z0-9_]+/{$entryName=$Ct} ln ~ acc: ~ {$Wrt:acc} ('AC ' ln)* ~ date: ~ {$Wrt:date} ('DT ' ln)* ~ def: ~ {$Wrt:def} ('DE ' ln)* ~ gene: ~ {$Wrt:gene} ('GN ' ln)* ~ org: ~ {$Wrt:org} ('OS ' ln)* ~ organel: ~ {$Wrt:organ} ('OG ' ln)* ~ tax: ~ {$Wrt:tax} ('OC ' ln)* ~ reference: ~ (refn | refp | refcc | refmed | refaut | refln | refxref)* ~ comment: ~ {$Wrt:tax} ('CC ' ln)* ~ link: ~ {$Wrt:link} ('DR ' ln)* ~ key: ~ {$Wrt:key} ('KW ' ln)* ~ feature: ~ {$Wrt:features} 'FT ' ln ('FT ' ln)* ~ seqTitle: ~ {$Wrt:seqTitle} 'SQ ' ln ~ sequence: ~ {pre{$seq=$seqNew:$entryName $Wrt:[seq s:$entryName]} $seqMake:$seq} (ln {$seqApp:[$seq s:$Ct]})* ~ refn: ~ {$Wrt:refn} 'RN ' ln ~ refp: ~ {$Wrt:refp} 'RP ' ln ~ refcc: ~ {$Wrt:refc} 'RC ' ln ~ refmed: ~ {$Wrt:refm} 'RM ' ln ~ refaut: ~ {$Wrt:refaut} 'RA ' ln ('RA ' ln)* ~ refln: ~ {$Wrt:refl} 'RL ' ln ~ refxref: ~ {$Wrt:refxref} 'RX ' ln ~ # the fields for the 'features' subentry feature: ~ {$In:[fields c:features count:features var:$ftN] $Out} /.*/ {if:$ftN==2 $print:"+++ $Ct +++"} ~ # for indexing i_dates: ~ {$In:[fields c:date] $Out:date init {$month={JAN:1 FEB:2 MAR:3 APR:4 MAY:5 JUN:6 JUL:7 AUG:8 SEP:9 OCT:10 NOV:11 DEC:12}}} /.* ([0-9]+)-([A-Z]+)-([0-9]+).+CRE/ {$Wrt:[credate s:($1 + $month.$2*100 + $3*10000)]} ~ i_id: ~ {$In:[fields c:id] $Out:id} 'ID' /[a-zA-Z0-9_]+/ {$Wrt} ~ i_acc: ~ {$In:[fields c:acc] $Out:acc} /../ /[a-zA-Z0-9_]+/ {$Wrt} ~ i_def: ~ {$In:[fields c:def] $Out:def} (/../ (/[a-zA-Z0-9_]+/ {$Wrt} | /\\(EC *([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)/ {$Wrt:[s:$1]} | /[^a-aA-Z0-9(_\n]+/ | /[^\n]/ )* ln)* ~ i_authors: ~ {$In:[fields c:refaut] $Out:authors} (/RA/ (/([^.,\n]+) +([^,;\n]+)/ {$Wrt:[s:"$1,$2"]} /[,;]/)* ln)* ~ i_feature: ~ {$In:[fields c:features count:features var:$ftN] $Out:features} 'FT ' /[A-Z0-9_]+/ {$Wrt:[n:$ftN]} num num (/[A-Za-z0-9_]+/ {$Wrt:[n:$ftN]} | /[^A-Za-z0-9_]+/)* ~ featlen: ~ {$In:[fields c:features count:features var:$ftN] $Out} 'FT ' htmlTag?/[A-Z0-9_]+/ ''? (/([0-9]+) +([0-9]+)/ {$Wrt:[n:$ftN s:($2-$1+1)]})? ~ i_seqlen: ~ {$In:[fields c:seqTitle] $Out:seqlength} /.* ([0-9]+) *AA/ {$Wrt:[s:$1]} ~ i_molwght: ~ {$In:[fields c:seqTitle] $Out:molweight} /.* ([0-9]+) *MW/ {$Wrt:[s:$1]} ~ i_sequence:~ {$In:[fields c:sequence] $Out:id} x:{$Wrt:[s:$seqfip]} ~ i_keylist: ~ {$In:[fields c:key] $Out:kwlist} ('KW ' ln {$Wrt})* ~ i_keyword: ~ {$In:[kwlist] $Out:kwords} (/[^;.]/ {$Wrt} /[.;]/)* ~ keylist: ~ {$In:[fields c:key] $Out:kwlist} ('KW ' ln {$Wrt})* ~ crossref: ~ {$In:[fields c:link] $Out:link} (('DR' dbName {$db=$Ct} ';' accno {$Wrt:$db}) ln )* ~ # printing tables t_authors: ~ {$In:[fields c:refaut] $Out} 'RA' ln {$Wrt} ('RA' ln {$App})* ~ t_def: ~ {$In:[fields c:def] $Out} 'DE' ln {$Wrt} ('DE' ln {$App})* ~ # printing in HTML format h_id: ~ {$In:[fields c:id t:hl]} /../ name {$entryName=$Ct} ~ h_refxref: ~ {$In:[fields c:refxref t:hl]} /../ 'MEDLINE;' /[0-9]+/ {$Rep:{$ParStr:medlineR $Ct $Ct}} ~ h_def: ~ {$In:[fields c:def t:hl]} (/(\\(EC )([0-9.-]+)/ {$Rep:{$ParStr:enzymeR $2 $2}} | /[^ ]+/ )* ~ h_features:~ {$In:[fields c:features t:hl]} ('FT ' /[A-Z0-9_]+/ {$Rep:{"%s" $entryName 1 $Ct}} )?~ htmlTag: ~ /<[^<>]*>/ ~ h_links: ~ {$In:[fields c:link t:hl] init{$hl={ 'AARHUS/GHENT-2DPAGE': aarhusR 'SWISS-2DPAGE': swiss2dpageR DICTYDB: dictydbR GCRDB: gcrdbR MAIZEDB: maizedbR WORMPEP: ormpepR ENZYME: enzymeR LISTA: listaR PIR: pirR YEPD: yepdR EMBL: emblR SGD: sgdR HSSP: hsspR STYGENE: stygeneR PROSITE: prositeR HIV: hivR ECOGENE: ecogeneR ECO2DBASE: eco2dbaseR MIM: mimR SUBTILIST: subtilistR PDB: pdbR FLYBASE: flybaseR TRANSFAC: transfacR REBASE: rebaseR } } } (/DR/ dbName {$db=$Ct} ';' accno {$Rep:{$ParStr:$hl.$db $Ct $Ct}} ln)* ~ # other stuff ln: ~ /[^\n]*\n/ ~ accno: ~ /[A-Z0-9]+/ ~ num: ~ /(<|>)?[0-9?]+/ ~ name: ~ /[a-zA-Z0-9_-]+/ ~ dbName: ~ /[^;]+/ ~ } #$fil = $FileOpen:"/data/swissprot/seq.dat" #$job = $JobNew:[prod:$rules skip:" "] #$print:"-------->entry\n" #while:$jobTokens:[$job name:fields code:id print:1] { # $jobTokens:[$job name:feature print:1] # $JobNext:[$job file:$fil] # $print:"-------->entry\n" #} # # $RCSfile: swissprot.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:56 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The SWISS-PROT Protein Sequence Database is a database of protein |sequences produced collaboratively by Amos Bairoch (University of |Geneva) and the EMBL Data Library. The data in Swiss-Prot are derived |from translations of DNA sequences from the EMBL Nucleotide Sequence |Database, adapted from the Protein Identification Resource (PIR) |collection, extracted from the literature and directly submitted by |researchers. It contains high-quality annotation,is non-redundant, |and cross-referenced to several other databases, notably the EMBL |nucleotide sequence database, PROSITE pattern database and PDB. |SWISS-PROT is a curated protein sequence database which strives to |provide a high level of annotation (such as the description of the |function of a protein, its domain structure, post-translational |modifications, variants, etc), a minimal level of redundancy and a |high level of integration with other databases. Recent developments |of the database include: an increase in the number and scope of model |organisms; cross-references to seven additional databases; a variety |of new documentation files; the creation of TREMBL, an unannotated |supplement to SWISS-PROT. This supplement consists of entries in |SWISS-PROT-like format derived from the translation of all coding |sequences (CDS) in the EMBL nucleotide sequence database, except CDS |already included in SWISS-PROT. |

    more: |

    |More on Swissprot |

    citation: | Reference: |Amos Bairoch and Rolf Apweiler "The SWISS-PROT protein sequence |data bank and its new supplement TREMBL", Nucleic Acids Res. |24:(21-25), 1996 ftpSite:'' fields: { Features: |

    SWISSPROT Feature Table

    |The FT (Feature Table) lines provide a precise but simple means for |the annotation of the sequence data. The table describes regions |or sites of interest in the sequence. In general the feature table |lists post- translational modifications, binding sites, enzyme active |sites, local secondary structure or other characteristics reported in |the cited references. Sequence conflicts between references are also |included in the feature table. The feature table is updated when more |becomes known about a given sequence. featureLength: |

    SWISSPROT Feature Length Field

    |Length of an amino acid sequence corresponed to some feature. The |length are defined by `FROM' and `TO' endpoint specifications. in |the Feature Table. entry.

    Note: Ranges can be combined: |"300-!500 | !600-700" or "300-700 ! 500-600" retrieve the same set |of entries, namely all entries with feature lengths from 300 to 500, |excluding 500, plus lengths from 600 to 700 where the 600 is excluded. MolWeight: |

    SWISSPROT Molecular Weight Field

    |Molecular Weight (MW) is rounded to the nearest gram. } date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: taxonomy.i,v $ # $Revision: 1.1 $ # $Date: 1996/08/11 23:03:18 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TAXONOMY_DB:$library:[TAXONOMY group:@SEQRELATED_LIBS format:@TAXONOMY_FORMAT maxNameLen:10 files:{ $file:tax } ] TAXONOMY_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@TAXONOMY_SYNTAX fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_ParentId code:parentId index:link indexToken:'parentId|ga'] $field:[@DF_Name code:name index:str indexToken:name] } ] TAXONOMY_SYNTAX:$syntax:[file:"SRSDB:taxonomy.is"] DF_ParentId:$srsfield:[ParentId short:pid] DF_Name:$srsfield:[Name short:nam] TAX_LINK:$link:[@TAXONOMY_DB to:@TAXONOMY_DB token:'parentId|ga' toField:@DF_ID fromField:@DF_ParentId fromName:TAX_DOWN toName:TAX_UP] $link:[@TAXONOMY_DB to:@TAXONOMY_DB toName:TAX_UP use:@TAX_LINK] $link:[@TAXONOMY_DB to:@TAXONOMY_DB fromName:TAX_DOWN use:@TAX_LINK] $rules={ entry: ~ {$In:[file:text] $Out} ('ID' {$Not} ln)* ('ID ' {$entryFip=$Fip $Wrt} ln {$App} ('ID' {$Not} ln {$App})*)? ~ fields: ~ {$In:entry $Out} f_id f_parentId f_taxLevel f_tlInd f_name ~ f_id: ~ {$Wrt:id} /ID.[^:]+:/ ln ~ f_parentId: ~ {$Wrt:parentId} /Parent ID[^:]+:/ ln ~ f_taxLevel: ~ {$Wrt:taxLevel} /Taxonom.[^:]+:/ ln ~ f_tlInd: ~ {$Wrt:tlInd} /TlInd[^:]+:/ ln ~ f_name: ~ {$Wrt:name} /Name[^:]+:/ ln ~ # indexing id: ~ {$In:[fields c:id] $Out} tag num {$Wrt} ~ parentId: ~ {$In:[fields c:parentId] $Out} tag num {$Wrt:ga} ~ name: ~ {$In:[fields c:name] $Out} tag str {$Wrt} ~ tag: ~ /[^:]+: */ ~ ln: ~ /[^\n]*\n/ ~ num: ~ /[-0-9]*/ ~ str: ~ /[^\n]+/ ~ } #$fil = $FileOpen:"/opt/srs/data/taxonomy/tax.dat" #$job = $JobNew:[prod:$rules file:$fil] #while:$JobTokens:[$job name:name print:1 task:html] # $JobNext:[$job] # $RCSfile: tfcell.i,v $ # $Revision: 1.3 $ # $Date 1996/02/28 # # Author: Chenna Ramu # TFCELL_DB:$library:[TFCELL group:@TRANSFAC_LIBS comment:"The TRANSFAC Database by Edgar Wingender and Rainer Knueppel" format:@TFCELL_FORMAT maxNameLen:10 ifiles:{"tfcell.i" "tfcell.is"} files:{ $file:cell } ] TFCELL_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@TFCELL_SYNTAX fields:{ $field:[@DF_ID code:ac index:id indexToken:ac] $field:[@DF_Date code:dt index:int indexToken:dt] $field:[@DF_Source code:so index:str indexToken:so] $field:[@DF_Organism code:os index:str indexToken:os] $field:[@DF_Description code:cd index:str indexToken:cd] } ] TFCELL_SYNTAX:$syntax:[file:"SRSDB:tfcell.is" ignore:" "] # # cell.is # # Ramu C # $rules={ entry: ~ {init{$count=0} $out:entry $count=$count+1} ('AC' {$not} ln)* ('AC ' {pre {$entryFip = $fip} $wrt} ln {$app} ('//' {$not} ln {$app})* '//' {$app $fip:on})* ~ # fields fields: ~ {$in:entry $out} f_ac f_xx f_dt f_xx f_so f_xx f_os f_xx f_cd f_xx ~ f_ac: ~ {$wrt:ac} 'AC ' ln ~ f_dt: ~ {$wrt:dt} ('DT ' ln)* ~ f_so: ~ {$wrt:so} ('SO ' ln)* ~ f_os: ~ {$wrt:os} ('OS ' ln)* ~ f_cd: ~ {$wrt:cd} ('CD ' ln)* ~ f_xx: ~ ('XX' ln)? ~ # indexing ac: ~ {$in:[fields c:ac] $out:ac} 'AC' /[0-9A-Za-z]+/ {$wrt} ~ dt: ~ {$in:[fields c:dt] $out:dt} 'DT' /([0-9]+).([0-9]+).([0-9]+)/ {$wrt:[s:($1+$2*100+"19$3"*10000)]} ~ so: ~ {$in:[fields c:so] $out:so} 'SO' (sep | word {$wrt})* ~ os: ~ {$in:[fields c:os] $out:os} 'OS' (sep | word {$wrt})* ~ oc: ~ {$in:[fields c:cd] $out:cd} 'CD' (sep | word {$wrt})* ~ # extra ... ln: ~ /[^\n]*\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ } $fil = $fileOpen:"/data/transfac/cell.dat" $job = $jobNew:[prod:$rules skip:" "] $jobNext:[$job file:$fil] for:{1 $jobTokens:[$job name:ac print:1 ] 1} { $jobEnd:$job $jobNext:[$job file:$fil] } $jobEnd:$job # # $RCSfile: tfcell.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:56 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |This table gives short explanations of the cellular sources of proteins |that interact with the sites listed in the SITES table. Among them |may be defined cell lines, tissues / organs, even whole organisms, or |recombinant expression systems. |

    more: |

    | |More on The TRANSFAC database |

    citation: | Reference: |E. Wingender , P. Dietze , H. Karas and R. Knppel, |"TRANSFAC: a database on transcription factors and their DNA binding sites" |Nucleic Acids Res. |24:(21-25), 1996 ftpSite:'' fields:{ Source: |

    TFCELL Source Field

    |The terminology of the factor sources (SO) corresponds to that used |in the SITES table (See TFSITE Source Field). Cell lines are given |with their most common name (e. g. , HeLa, 3T3), the most frequently |used tissues may be abbreviated (e.g., rl for rat liver), others are |explicitly mentioned. Organism: |

    TFCELL Organism Field

    |Recombinant materials are explained by the denotation rec([source |organism] - [expressing cell]). Occasionally, a viral expression system |is also indicated: rec(chick-baculovirus-Sf9). Description: |

    TFCELL Description Field

    |The field contains line cell description. Sometimes some characteristics |of cell matirial are inclided. } date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: tfclass.i,v $ # $Revision: 1.3 $ # $Date 1996/02/28 # # Author: Chenna Ramu # TFCLASS_DB:$library:[TFCLASS group:@TRANSFAC_LIBS comment:"The TRANSFAC Database by Edgar Wingender and Rainer Knueppel" format:@TFCLASS_FORMAT maxNameLen:10 ifiles:{"tfclass.i" "tfclass.is"} files:{ $file:class } ] TFCLASS_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@TFCLASS_SYNTAX fields:{ $field:[@DF_Accession code:ac index:id indexToken:ac] $field:[@DF_Date code:date index:int indexToken:date] $field:[@DF_CLASS code:class index:str indexToken:class] $field:[@DF_STRDES code:strDes index:str indexToken:strDes] $field:[@DF_COMM code:comm index:str indexToken:comm] } ] DF_CLASS:$srsfield:[Class short:cl] DF_STRDES:$srsfield:[StrDescrip short:sd] DF_COMM:$srsfield:[Comment short:cc] TFCLASS_SYNTAX:$syntax:[file:"SRSDB:tfclass.is" ignore:" "] $link:[@TFCLASS_DB to:@?PROSITEDOC_DB token:'links|pr' toField:@DF_ID] # # class.is # # Ramu C # $rules={ entry: ~ {init{$count=0} $out:entry $count=$count+1} ('AC' {$not} ln)* ('AC ' {pre {$entryFip = $fip} $wrt} ln {$app} ('//' {$not} ln {$app})* '//' {$app $fip:on})* ~ # fields fields: ~ {$in:entry $out} f_ac xx f_dt xx f_cl xx f_sd xx f_cc xx f_dr xx f_bf xx (f_rn f_ra f_rt f_rl)* xx ~ f_ac: ~ {$wrt:ac} 'AC ' ln ~ f_dt: ~ {$wrt:date} ('DT ' ln)* ~ f_cl: ~ {$wrt:class} ('CL ' ln)* ~ f_sd: ~ {$wrt:strDes} ('SD ' ln)* ~ f_cc: ~ {$wrt:comm} ('CC ' ln)* ~ f_bf: ~ {$wrt:bindFac} ('BF ' ln)* ~ f_dr: ~ {$wrt:dr} ('DR ' ln)* ~ f_rn: ~ {$wrt:refNum} 'RN ' ln ~ f_ra: ~ {$wrt:refAut} ('RA ' ln)* ~ f_rt: ~ {$wrt:refTit} ('RT ' ln)* ~ f_rl: ~ {$wrt:refData} ('RL ' ln)* ~ xx: ~ ('XX' ln)? ~ # indexing ac: ~ {$in:[fields c:ac] $out:ac} 'AC' /[0-9A-Za-z]+/ {$wrt} ~ dt: ~ {$in:[fields c:date] $out:date} 'DT' /([0-9]+).([0-9]+).([0-9]+)/ {$wrt:[s:($1+$2*100+"19$3"*10000)]} ~ class: ~ {$in:[fields c:class] $out:class} 'CL' (sep | word {$wrt})* ~ strDes: ~ {$in:[fields c:strDes] $out:strDes} 'SD' (sep | word {$wrt})* ~ comm: ~ {$in:[fields c:comm] $out:comm} 'CC' (sep | word {$wrt})* ~ links: ~ {$in:[fields c:dr] $out} (/DR/ (word {$wrt:pr} ',' word ',' /[A-Z?]/ ';')* ln)* ~ # html display hl_links:~ {$in:[fields c:dr t:hl]} ((/DR/ word ':' word {$rep:{$parStr:prositeR $ct $ct}} ln)*) ~ # dr: ~ {$in:[fields c:dr] $out:dr} 'DR' (sep | word {$wrt})* ~ # refNum: ~ {$in:[fields c:refNum] $out:refNum} 'RN' (sep | word {$wrt})* ~ # refAut: ~ {$in:[fields c:refAut] $out:refAut} 'RA' (sep | word {$wrt})* ~ # refTit: ~ {$in:[fields c:refTit] $out:refTit} 'RT' (sep | word {$wrt})* ~ #refData: ~ {$in:[fields c:refData] $out:reData} 'RL' (sep | word {$wrt})* ~ # extra ... ln: ~ /[^\n]*\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ } #$fil = $fileOpen:"/data/transfac/class.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #for:{1 $jobTokens:[$job name:fields print:1 ] 1} { # $jobEnd:$job # $jobNext:[$job file:$fil] #} #$jobEnd:$job # # $RCSfile: tfclass.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:57 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |This record briefly explains some of the main features of the |DNA- binding domains of 26 transcription factor classes. In those |cases where an amino acid consensus motif has been identified, the |corresponding accession number of the PROCLASS database (A. Bairoch) is |included. |

    more: |

    | |More on The TRANSFAC database |

    citation: | Reference: |E. Wingender , P. Dietze , H. Karas and R. Knppel, |"TRANSFAC: a database on transcription factors and their DNA binding sites" |Nucleic Acids Res. |24:(21-25), 1996 ftpSite:'' fields:{ Class: |

    TFCLASS Class Field

    |List of avaliable classes: |
      |
    • Factor family with homology to the ets-protooncogenes |
    • LIM domain |
    • MCM1-agamous-deficiens-SRF |
    • POU domain |
    • Rel-related factor |
    • TEA domain |
    • basic region + helix-loop-helix motif |
    • basic region + helix-loop-helix motif + leucine zipper |
    • basic region + leucine zipper |
    • fork head domain |
    • helix-loop-helix motif |
    • helix-loop-helix motif + leucine zipper |
    • helix-turn-helix |
    • high-mobility group protein-like factors |
    • homeodomain plus leucine zipper |
    • homeodomain; homeobox protein |
    • leucine zipper |
    • myb-like DNA-binding domains |
    • paired domain, paired box |
    • paired domain, paired box + homeo domain |
    • protamine-like domain |
    • zinc cluster; zinc-cysteine cluster; C6 zinc finger |
    • zinc finger |
    • zinc finger + homeo domain |
    • zinc finger; zinc twist |
    Comment: |

    TFCLASS Comment Field

    |This field contains description of the class entry. It is a plain text |describing main characterisitics of DNA-binding protein class. StrDescrip: |

    TFCLASS Structure Description Field

    |List of avaliable structure descriptors: |
      |
    • C6 |
    • CC |
    • CC (g) |
    • CC (rec) |
    • CH |
    • CH+homeo |
    • ETS |
    • HLH |
    • HLH-ZIP |
    • HMG |
    • HTH |
    • LIM-homeo |
    • MADS |
    • POU |
    • Rel |
    • TEA |
    • ZIP |
    • bHLH |
    • bHLH-ZIP |
    • bZIP |
    • fork head |
    • homeo |
    • homeo-Zip |
    • myb |
    • paired |
    • paired-homeo |
    • protamine-like |
    } date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: tffactor.i,v $ # $Revision: 1.5 $ # $Date 1996/02/28 # # Author: Chenna Ramu # TFFACTOR_DB:$library:[TFFACTOR group:@TRANSFAC_LIBS comment:"The TRANSFAC Database by Edgar Wingender and Rainer Knueppel" format:@TFFACTOR_FORMAT maxNameLen:10 ifiles:{"tffactor.i" "tffactor.is"} files:{ $file:factor } ] TFFACTOR_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@TFFACTOR_SYNTAX fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_Date code:dt index:int indexToken:dt] $field:[@DF_Organism code:os index:str indexToken:os] $field:[@DF_FF code:ff index:str indexToken:ff] $field:[@DF_Authors code:author index:str indexToken:author] $field:[@DF_Title code:title index:str indexToken:title] $field:[@DF_REF code:reference index:str indexToken:reference] $field:[@DF_Interaction code:interact index:link indexToken:interact] } ] DF_FF:$srsfield:[FuncFeature short:ff] DF_Interaction:$srsfield:[Interaction short:ia] TFFACTOR_SYNTAX:$syntax:[file:"SRSDB:tffactor.is" ignore:" "] $link:[@TFFACTOR_DB to:@TFFACTOR_DB token:'interact' toName:TFFACTOR_IN fromField:@DF_Interaction toField:@DF_ID] $link:[@TFFACTOR_DB to:@SWISSPROT_DB token:'links|swiss' toField:@DF_Accession] # # tffactor.is # # # $rules={ entry: ~ {$In:[file:text] $Out pre{$Skip:0} $Skip:1} ('ID' {$Not} ln)* ('ID ' {$entryFip=$Fip $Wrt} ln {$App} ('ID' {$Not} ln {$App})+)? ~ # fields fields: ~ {$In:entry $Out} f_id sp f_ac sp f_dt sp f_fa sp f_sy sp f_ho sp f_os sp f_oc sp f_cs sp f_sz sp f_cl sp f_sf sp f_in sp f_ff sp f_bs sp f_ms sp (f_rn f_ra f_rt f_rl)* sp f_dr sp ~ f_id: ~ {$Wrt:id} 'ID ' ln ~ f_ac: ~ {$Wrt:ac} ('AC ' ln)* ~ f_dt: ~ {$Wrt:dt} ('DT ' ln)* ~ f_fa: ~ {$Wrt:fa} ('FA ' ln)* ~ f_sy: ~ {$Wrt:sy} ('SY ' ln)* ~ f_ho: ~ {$Wrt:ho} ('HO ' ln)* ~ f_os: ~ {$Wrt:os} ('OS ' ln)* ~ f_oc: ~ {$Wrt:oc} ('OC ' ln)* ~ f_cs: ~ {$Wrt:cs} ('CS ' ln)* ~ f_sz: ~ {$Wrt:sz} ('SZ ' ln)* ~ f_cl: ~ {$Wrt:cl} ('CL ' ln)* ~ f_sf: ~ {$Wrt:sf} ('SF ' ln)* ~ f_in: ~ {$Wrt:interact} ('IN ' ln)* ~ f_ff: ~ {$Wrt:ff} ('FF ' ln)* ~ f_bs: ~ {$Wrt:bs} ('BS ' ln)* ~ f_ms: ~ {$Wrt:ms} ('MS ' ln)* ~ f_rn: ~ {$Wrt:rn} 'RN ' ln ~ f_ra: ~ {$Wrt:author} ('RA ' ln)* ~ f_rt: ~ {$Wrt:title} ('RT ' ln)* ~ f_rl: ~ {$Wrt:reference} ('RL ' ln)* ~ f_dr: ~ {$Wrt:xref} ('DR ' ln)* ~ sp: ~ {$Wrt:sp} ('XX' ln)? ~ # indexing id: ~ {$In:[fields c:id] $Out} 'ID' /[0-9A-Za-z]+/ {$Wrt} ~ dt: ~ {$In:[fields c:dt] $Out:dt} 'DT' /([0-9]+).([0-9]+).([0-9]+)/ {$Wrt:[s:($1+$2*100+"19$3"*10000)]} ~ os: ~ {$In:[fields c:os] $Out:os} 'OS' (sep | word {$Wrt})* ~ ff: ~ {$In:[fields c:ff] $Out:ff} 'FF' (sep | word {$Wrt})* ~ author: ~ {$In:[fields c:author] $Out:author} 'RA' (sep | word {$Wrt})* ~ title: ~ {$In:[fields c:title] $Out:title} 'RT' (sep | word {$Wrt})* ~ reference: ~ {$In:[fields c:reference] $Out:reference} 'RL' (sep | word {$Wrt})* ~ interact: ~ {$In:[fields c:interact] $Out} (/../ word {$Wrt} ln)* ~ links: ~ {$In:[fields c:xref] $Out} ('DR' (('EMBL:' word {$Wrt:embl} ln) | ('SwissProt:' word {$Wrt:swiss} ln) | ('Flybase:' word {$Wrt:flybase} ln) | ('PIR:' word {$Wrt:pir} ln)) )* ~ # html href links hl_links:~ {$In:[fields c:xref t:hl]} (/DR/ word {$db=$Ct} ':' word {$Rep:{$parStr:dbaseR $db $Ct $Ct}} ln)* ~ # extra ... ln: ~ /[^\n]*\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ } #$fil = $fileOpen:"/data/transfac/factor.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #for:{1 $jobTokens:[$job name:fields print:1 ] 1} { # $jobEnd:$job # $jobNext:[$job file:$fil] #} #$jobEnd:$job # # $RCSfile: tffactor.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:58 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The FACTORS table contains 1236 entries, but this figure doesn't |reflect the number of independent transcription factors. First of all, |homologous factors from different species such as human and mouse SRF |are given in different entries since they may differ in some molecular |aspects. Moreover, factors which have originally been described by |different research groups to bind to different genes may turn out to |be identical as soon as they have been cloned. On the other hand, |more and more factors are recognized to be representatives of whole |transcription factor families comprising products of distinct but very |similar genes or alternative splice products. In many cases, a more |general term originally defining just a specific DNA-binding activity |such as AP-1 appears as one entry. In most cases, this activity has not |been analyzed for its subunit composition by members of the Jun and |Fos families. Nevertheless, all known fos- and jun-related proteins |are included as separate entries.

    All factors that are mentioned |in the SITES table appear in the FACTORS table as well. However, it |includes also polypeptides which do not bind to DNA by themselves. One |well-known example is c-Fos which is forced to contact DNA not until |being complexed with, e. g., c-Jun. Information about non-DNA binding |subunits of transcription factor complexes such as the TAFs is given by |FACTORS as well. There are also proteins that act as inhibitors for a |particular DNA-binding activity and which are of regulatory importance. |Therefore, proteins such as Id, IkappaB or hsp90 have been included in |TRANSFAC FACTORS.

    On the other hand, we have in general not yet |entered proteins just because of the presence of a putative DNA-binding |motif. Thus, there are much more zinc finger or homeo domain proteins |known than are included in FACTORS, but for many of them, no data about |DNA- binding specificity or about other gene important regulatory |features are available. |

    more: |

    | |More on The TRANSFAC database |

    fields:{ Synonyms: |

    TFFACTOR Synonyms Field

    |
    The field Synonyms covers different spelling (AP-1/AP1) |as well as real alternative names (HNF-1: HNF-1alpha, APF, LF-B1). In |contrast, the field Suggested Homologs indicates the names of other |proteins, frequently from evolutionarily more distant species, which |may be functionally and/or structurally related to the factor under |consideration.

    CellSpecif: |

    TFFACTOR CellSpecif Field

    |
    Cell Specificity gives predominant occurrence of a factor |in certain cell types or tissues. Gradual differences between groups of |cells/tissues are indicated by a semicolon. Occasionally, cells from |which the factor has been isolated are indicated in brackets; this |information does not necessarily point to a true cell specificity. |


    The Size field shows the number of amino acid residues of a |polypeptide and its molecular weight. The method by which this figure |has been obtained is indicated in brackets; (cDNA) or (gene) means that |it has been calculated after cloning, (SDS) or (sedim.) hints on the |corresponding experimental approaches.

    Features: |

    TFFACTOR Features Field

    |The field Structural Features may contain information on: |
  3. regions that are enriched in some amino acid residues and |may therefore represent trans-activating domains; S/T stands for |serine/threonine-rich, ac for acidic, Pro for proline-rich, Q for |glutamine-rich, A for alanine-rich regions, W for peculiar tryptophan |patterns.
  4. the nature of a leucine zipper: L4 means that it |consists of four leucine residues spaced by 6-AA-intervals, L2EL2 |indicates a motif such as L-X6-L-X6-E-X6-L-X6-L. |
  5. posttranslational modifications: P or Ph indicates a site of |phosphorylation, glyc of glycosylation.
  6. Interaction: |

    TFFACTOR Interaction Field

    |The field Interactions:
  7. Since most transcription |factors bind to DNA as dimers, the dimerization partners are |indicated in this field. Repeating the factors name in this |field means that it forms homodimers. Also given are inhibitory |protein-protein-interactions such as NF-kappaB - IkappaB.
  8. |
  9. Matrix: |

    TFFACTOR Matrix Field

    |The field Matrix indicates a crossreference if there exists a |nucleotide distribution matrix for this factor in the MATRIX table.

    } citation: | Reference: |E. Wingender , P. Dietze , H. Karas and R. Knppel, |"TRANSFAC: a database on transcription factors and their DNA binding sites" |Nucleic Acids Res. |24:(21-25), 1996 ftpSite:'' date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: tfmatrix.i,v $ # $Revision: 1.4 $ # $Date 1996/02/28 # # Author: Chenna Ramu # TFMATRIX_DB:$library:[TFMATRIX group:@TRANSFAC_LIBS comment:"The TRANSFAC Database by Edgar Wingender and Rainer Knueppel" format:@TFMATRIX_FORMAT maxNameLen:10 ifiles:{"tfmatrix.i" "tfmatrix.is"} files:{ $file:matrix } ] TFMATRIX_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@TFMATRIX_SYNTAX fields:{ $field:[@DF_Accession code:ac index:id indexToken:acc] $field:[@DF_Date code:date index:int indexToken:date] $field:[@DF_BINDFAC code:bindFac index:str indexToken:bindFac] $field:[@DF_STATBAS code:statBas index:str indexToken:statBas] $field:[@DF_COMMENT code:comm index:str indexToken:comm] $field:[@DF_Authors code:refAut index:str indexToken:refAut] $field:[@DF_REFTITLE code:refTit index:str indexToken:refTit] $field:[@DF_REF code:refData index:str indexToken:refData] } ] DF_BINDFAC:$srsfield:[BindingFactor short:cl] DF_STATBAS:$srsfield:[StatisticBasis short:cl] DF_REFTITLE:$srsfield:[Title short:rt] TFMATRIX_SYNTAX:$syntax:[file:"SRSDB:tfmatrix.is" ignore:" "] # # matrix.is # # Ramu C # $rules={ entry: ~ { $Out:entry pre{$Skip:0} $skip:1} ('AC' {$not} ln)* ('AC ' {$entryFip = $Fip $Wrt} ln {$App} ('AC' {$not} ln {$App})+)? ~ # fields fields: ~ {$In:entry $Out} f_ac sep f_id sep f_na sep f_dt sep sep f_po sep f_bf sep f_ba sep f_cc? sep (f_rn f_ra f_rt f_rl)* sep ~ f_ac: ~ {$Wrt:acc} 'AC ' ln ~ f_id: ~ {$Wrt:id} 'ID ' ln ~ f_dt: ~ {$Wrt:date} ('DT ' ln)* ~ f_na: ~ {$Wrt:na} ('NA ' ln)* ~ f_po: ~ {$Wrt:po} 'PO' ln (/[0-9][0-9]/ ln)* ~ f_bf: ~ {$Wrt:bindFac} ('BF ' ln)* ~ f_ba: ~ {$Wrt:statBas} ('BA ' ln)* ~ f_cc: ~ {$Wrt:comm} ('CC ' ln)+ ~ f_rn: ~ {$Wrt:refNum} 'RN ' ln ~ f_ra: ~ {$Wrt:refAut} ('RA ' ln)+ ~ f_rt: ~ {$Wrt:refTit} ('RT ' ln)+ ~ f_rl: ~ {$Wrt:refData} ('RL ' ln)+ ~ sep: ~ ('XX' ln)* ~ # indexing ac: ~ {$In:[fields c:acc] $Out:acc} 'AC' /[0-9A-Za-z]+/ {$Wrt} ~ dt: ~ {$In:[fields c:date] $Out:date} 'DT' skipChar /([0-9]+).([0-9]+).([0-9]+)/ {$Wrt:[s:($1+$2*100+"19$3"*10000)]} ~ bindFac: ~ {$In:[fields c:bindFac] $Out:bindFac} 'BF' (sep | word {$Wrt})* ~ statBas: ~ {$In:[fields c:statBas] $Out:statBas} 'BA' (sep | word {$Wrt})* ~ comm: ~ {$In:[fields c:comm] $Out:comm} 'CC' (sep | word {$Wrt})* ~ refAut: ~ {$In:[fields c:refAut] $Out:refAut} 'RA' (sep | word {$Wrt})* ~ refTit: ~ {$In:[fields c:refTit] $Out:refTit} 'RA' (sep | word {$Wrt})* ~ refData: ~ {$In:[fields c:refData] $Out:refData} 'RA' (sep | word {$Wrt})* ~ # common things ln: ~ /[^\n]*\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ skipChar: ~ /[^0-9.]+/ ~ } $fil = $FileOpen:"/data/transfac/matrix.dat" $job = $JobNew:[prod:$rules skip:" " file:$fil] while:$JobTokens:[$job name:acc print:1] $JobNext:$job # # $RCSfile: tfmatrix.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:58 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |The MATRIX table contains 26 nucleotide distribution matrices of |aligned binding sequences. These sequences may have been obtained by in |vitro selection studies or may be compiled sites of genes. The source |is appropriately indicated. |

    more: |

    | |More on The TRANSFAC database |

    citation: | Reference: |E. Wingender , P. Dietze , H. Karas and R. Knppel, |"TRANSFAC: a database on transcription factors and their DNA binding sites" |Nucleic Acids Res. |24:(21-25), 1996 ftpSite:'' date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: tfsite.i,v $ # $Revision: 1.3 $ # $Date 1996/02/28 # # Author: Chenna Ramu # TFSITE_DB:$library:[TFSITE group:@TRANSFAC_LIBS comment:"The TRANSFAC Database by Edgar Wingender and Rainer Knueppel" format:@TFSITE_FORMAT maxNameLen:10 ifiles:{"tfsite.i" "tfsite.is"} files:{ $file:site } ] TFSITE_FORMAT:$libformat:[fileType:@DAT_FILE syntax:@TFSITE_SYNTAX fields:{ $field:[@DF_ID code:id index:id indexToken:id] $field:[@DF_Date code:dt index:int indexToken:dt] $field:[@DF_Organism code:os index:str indexToken:os] $field:[@DF_Description code:de index:str indexToken:de] } ] TFSITE_SYNTAX:$syntax:[file:"SRSDB:tfsite.is" ignore:" "] # # tfsite.is # # Ramu C # $rules={ entry: ~ {init{$count=0} $out:entry $count=$count+1} ('ID' {$not} ln)* ('ID ' {pre {$entryFip = $fip} $wrt} ln {$app} ('//' {$not} ln {$app})* '//' {$app $fip:on})* ~ # fields fields: ~ {$in:entry $out} f_id xx f_ac xx f_dt xx f_ty xx f_de xx f_se xx f_el xx f_sf f_st f_s1 xx f_bf xx f_os xx f_oc xx f_so xx f_me xx (f_rn f_ra f_rt f_rl)* xx f_cc f_dr xx ~ f_id: ~ {$wrt:id} 'ID ' ln ~ f_ac: ~ {$wrt:ac} ('AC ' ln)* ~ f_dt: ~ {$wrt:dt} ('DT ' ln)* ~ f_ty: ~ {$wrt:ty} ('TY ' ln)* ~ f_de: ~ {$wrt:de} ('DE ' ln)* ~ f_se: ~ {$wrt:se} ('SE ' ln)* ~ f_el: ~ {$wrt:el} ('EL ' ln)* ~ f_sf: ~ {$wrt:sf} ('SF ' ln)* ~ f_st: ~ {$wrt:st} ('ST ' ln)* ~ f_s1: ~ {$wrt:s1} ('S1 ' ln)* ~ f_bf: ~ {$wrt:bf} ('BF ' ln)* ~ f_os: ~ {$wrt:os} ('OS ' ln)* ~ f_oc: ~ {$wrt:oc} ('OC ' ln)* ~ f_so: ~ {$wrt:so} ('SO ' ln)* ~ f_me: ~ {$wrt:me} ('ME ' ln)* ~ f_rn: ~ {$wrt:rn} 'RN ' ln ~ f_ra: ~ {$wrt:ra} ('RA ' ln)* ~ f_rt: ~ {$wrt:rt} ('RT ' ln)* ~ f_rl: ~ {$wrt:rl} ('RL ' ln)* ~ f_cc: ~ {$wrt:cc} ('CC ' ln)* ~ f_dr: ~ {$wrt:dr} ('DR ' ln)* ~ xx: ~ ('XX' ln)? ~ # indexing id: ~ {$in:[fields c:id] $out} 'ID' /[0-9A-Za-z]+/ {$wrt} ~ dt: ~ {$in:[fields c:dt] $out:dt} 'DT' /([0-9]+).([0-9]+).([0-9]+)/ {$wrt:[s:($1+$2*100+"19$3"*10000)]} ~ os: ~ {$in:[fields c:os] $out:os} 'OS' (sep | word {$wrt})* ~ de: ~ {$in:[fields c:de] $out:de} 'DE' (sep | word {$wrt})* ~ # extra ... ln: ~ /[^\n]*\n/ ~ word: ~ /[a-zA-Z0-9_]+/ ~ sep: ~ /[^a-zA-Z0-9_]+/ ~ } #$fil = $fileOpen:"/data/transfac/tfsite.dat" #$job = $jobNew:[prod:$rules skip:" "] #$jobNext:[$job file:$fil] #for:{1 $jobTokens:[$job name:fields print:1 ] 1} { # $jobEnd:$job # $jobNext:[$job file:$fil] #} #$jobEnd:$job ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $RCSfile: tfsite.it,v $ # $Revision: 1.2 $ # $Date: 1996/07/30 10:26:59 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $main = { description: |As outlined above, SITES gives information on individual (putatively) |regulatory protein binding sites. It contains 4303 entries, 4038 |of them referring to sites within more than 841 eukaryotic genes, |the species of which ranging from yeast to human. Additionally, |this table comprises 315 artificial sequences which resulted from |mutagenesis studies, in vitro selection procedures starting from random |oligonucleotide mixtures or from specific theoretical considerations. |And finally, there are 224 consensus binding sequences given in the |IUPAC code, many of them being taken from the compilation of Faisst and |Meyer (Nucleic Acids Res. 20:3-26, 1992). The symbols used |in addition to A, C, G, or T for these consensi are:

    |
        |W: A or T                           S: C or G
        |R: A or G                           Y: C or T
        |K: G or T                           M: A or C
        |B: C, G, or T                       D: A, G, or T
        |H: A, C, or T                       V: A, C, or G
        |N: A, C, G, or T
        |
    |

    more: |

    | |More on The TRANSFAC database |

    citation: | Reference: |E. Wingender , P. Dietze , H. Karas and R. Knppel, |"TRANSFAC: a database on transcription factors and their DNA binding sites" |Nucleic Acids Res. |24:(21-25), 1996 ftpSite:'' date: |25 Jul 1996 signature: |Anatoly Ulyanov } # $RCSfile: ypd.i,v $ # $Revision: 1.4 $ # $Date: 1996/08/11 22:51:58 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ YPD_DB:$library:[YPD group:@SEQRELATED_LIBS comment:"Yeast Protein Databank" format:@YPD_FORMAT maxNameLen:12 ifiles:{"ypd.i" "ypd.is"} files:{ $file:YPD_ASCII } ] YPD_FORMAT:$libformat:[fileType:@YPD_FILE syntax:@YPD_SYNTAX tableFormat:left printFormat:table fields:{ $field:@DF_ALL $field:[@DF_ID code:ygn index:id indexToken:id tableToken:'id'] $field:[@DF_SwissProtName code:sgn index:link indexToken:'words|sgn' tableToken:'words|sgn'] $field:[@DF_SaccGenomeDbName code:sgdn index:link indextoken:'words|sgdn' tableToken:'words|sgdn'] $field:[@DF_Synonyms code:syn index:str indextoken:'words|syn' tableToken:'words|syn'] $field:[@DF_HeaderField name:'Technical Flags'] $field:[@DF_IdentSeqFlag code:idf index:int indextoken:'number|idf' tableToken:'words|idf'] $field:[@DF_RelatedSeqFlag code:csf index:int indextoken:'number|csf' tableToken:'words|csf'] $field:[@DF_DatabaseSource code:dbs index:int indextoken:'number|dbs' tableToken:'words|dbs'] $field:[@DF_SystSeqFlag code:ssf index:int indextoken:'number|ssf' tableToken:'words|ssf'] $field:[@DF_HeaderField name:'Calculated Data'] $field:[@DF_IsoelectricPoint code:isop index:real indextoken:'number|isop' tableToken:'number|isop' tableFormat:right] $field:[@DF_IsoelectricPointPlusPos code:isopp index:real indextoken:'number|isopp' tableToken:'number|isopp' tableFormat:right] $field:[@DF_IsoelectricPointPlusNeg code:isopn index:real indextoken:'number|isopn' tableToken:'number|isopn' tableFormat:right] $field:[@DF_MolWeight code:molw index:int indextoken:'number|molw' tableToken:'number|molw' tableFormat:right] $field:[@DF_CodonBias code:codb index:real indextoken:'number|codb' tableToken:'number|codb' tableFormat:right] $field:[@DF_CodonAdaptIndex code:coda index:real indextoken:'number|coda' tableToken:'number|coda' tableFormat:right] $field:[@DF_HeaderField name:'Genetic data'] $field:[@DF_ChromosomeNumber code:chrn index:str indextoken:'words|chrn' tableToken:'words|chrn'] $field:[@DF_IsIntronInGene code:intg index:str indextoken:'words|intg' tableToken:'words|intg'] $field:[@DF_KnockoutMut code:knm index:str indextoken:'words|knm' tableToken:'words|knm'] $field:[@DF_HeaderField name:'Accession numbers'] $field:[@DF_GenbankLink code:gb index:link indextoken:'words|gb' tableToken:'words|gb'] $field:[@DF_PIRLink code:pir index:link indextoken:'words|pir' tableToken:'words|pir'] $field:[@DF_SwissProtLink code:sw index:link indextoken:'words|sw' tableToken:'words|sw'] $field:[@DF_YEPDLink code:yepd index:link indextoken:'words|yepd' tableToken:'words|yepd'] $field:[@DF_HeaderField name:'Subcellular localization and functional classification'] $field:[@DF_MajorLocCategory code:malc index:str indextoken:'words|malc' tableToken:'words|malc'] $field:[@DF_MinorLocCategory code:milc index:str indextoken:'words|milc' tableToken:'words|milc'] $field:[@DF_MolecEnv code:mole index:str indextoken:'words|mole' tableToken:'words|mole'] $field:[@DF_FunctClassific code:func index:str indextoken:'words|func' tableToken:'words|func'] $field:[@DF_HeaderField name:'Post-translational modifications and length'] $field:[@DF_NTermModif code:ntm index:str indextoken:'words|ntm' tableToken:'words|ntm'] $field:[@DF_CTermModif code:ctm index:str indextoken:'words|ctm' tableToken:'words|ctm'] $field:[@DF_Phosphorylation code:phos index:str indextoken:'words|phos' tableToken:'words|phos'] $field:[@DF_Glycosylation code:glyc index:str indextoken:'words|glyc' tableToken:'words|glyc'] $field:[@DF_NTermPrecursorLen code:ntpl index:int indextoken:'number|ntpl' tableToken:'number|ntpl' tableFormat:right] $field:[@DF_MatureProteinLen code:mpl index:int indextoken:'number|mpl' tableToken:'number|mpl' tableFormat:right] $field:[@DF_MetAdjustField code:maf indextoken:'words|maf'] $field:[@DF_HeaderField name:'Motifs'] $field:[@DF_PotPhosphorylCdc28 code:pcdc index:int indextoken:'number|pcdc' tableToken:'number|pcdc' tableFormat:right] $field:[@DF_PotPhosphorylCKII code:pckii index:int indextoken:'number|pckii' tableToken:'number|pckii' tableFormat:right] $field:[@DF_PotPhosphorylPKA code:ppka index:int indextoken:'number|ppka' tableToken:'number|ppka' tableFormat:right] $field:[@DF_PotNLinkedGlycosyl code:nglyc index:int indextoken:'number|nglyc' tableToken:'number|nglyc' tableFormat:right] $field:[@DF_PotTransmem code:ptm index:int indextoken:'number|ptm' tableToken:'number|ptm' tableFormat:right] $field:[@DF_HeaderField name:'N- and C-terminal sequence fragments'] $field:[@DF_NtermPrecursorProt code:nspp] $field:[@DF_NtermMatureProt code:nsmp] $field:[@DF_CtermMatureProt code:csmp] $field:[@DF_HeaderField name:'Protein name/description and references'] $field:[@DF_Description code:pn index:str indextoken:'words|pn' tableToken:'words|pn'] $field:[@DF_RefList code:refs] } ] YPD_SYNTAX:$syntax:[file:"SRSDB:ypd.is" ignore:" \t\n"] YPD_FILE:$filetype:[typename:'' maxline:10000] DF_Compound:$srsfield:[Compound short:com] DF_SwissProtName:$srsfield:[SwissProtName short:swn] DF_SaccGenomeDbName:$srsfield:[SaccGenomeDbName short:sgn] DF_Synonyms:$srsfield:[Synonyms short:syn group:@DF_ALL] DF_IdentSeqFlag:$srsfield:[IdentSeqFlag short:isf] DF_RelatedSeqFlag:$srsfield:[RelatedSeqFlag short:rsf] DF_DatabaseSource:$srsfield:[DatabaseSource short:dbs] DF_SystSeqFlag:$srsfield:[SystSeqFlag short:ssf] DF_IsoelectricPoint:$srsfield:[IsoelectricPoint short:iep] DF_IsoelectricPointPlusPos:$srsfield:[IsoelectricPointPlusPos short:ipp] DF_IsoelectricPointPlusNeg:$srsfield:[IsoelectricPointPlusNeg short:ipn] DF_MolWeight:$srsfield:[MolWeight short:mow] DF_CodonBias:$srsfield:[CodonBias short:cob] DF_CodonAdaptIndex:$srsfield:[CodonAdaptIndex short:cai] DF_ChromosomeNumber:$srsfield:[ChromosomeNumber short:chn] DF_IsIntronInGene:$srsfield:[IsIntronInGene short:iig group:@DF_ALL] DF_KnockoutMut:$srsfield:[KnockoutMut short:knm group:@DF_ALL] DF_GenbankLink:$srsfield:[GenbankLink short:gbl] DF_PIRLink:$srsfield:[PIRLink short:pil] DF_SwissProtLink:$srsfield:[SwissProtLink short:swl] DF_YEPDLink:$srsfield:[YEPDLink short:yel] DF_MajorLocCategory:$srsfield:[MajorLocCategory short:mal group:@DF_ALL] DF_MinorLocCategory:$srsfield:[MinorLocCategory short:mil group:@DF_ALL] DF_MolecEnv:$srsfield:[MolecEnv short:moe group:@DF_ALL] DF_FunctClassific:$srsfield:[FunctClassific short:fcl group:@DF_ALL] DF_NTermModif:$srsfield:[NTermModif short:ntm] DF_CTermModif:$srsfield:[CTermModif short:ctm] DF_Phosphorylation:$srsfield:[Phosphorylation short:pho] DF_Glycosylation:$srsfield:[Glycosylation short:glc] DF_NTermPrecursorLen:$srsfield:[NTermPrecursorLen short:npl] DF_MatureProteinLen:$srsfield:[MatureProteinLen short:mpl] DF_MetAdjustField:$srsfield:[MetAdjustField short:maf] DF_PotPhosphorylCdc28:$srsfield:[PotPhosphorylCdc28 short:ppc] DF_PotPhosphorylCKII:$srsfield:[PotPhosphorylCKII short:ppk] DF_PotPhosphorylPKA:$srsfield:[PotPhosphorylPKA short:ppp] DF_PotNLinkedGlycosyl:$srsfield:[PotNLinkedGlycosyl short:png] DF_PotTransmem:$srsfield:[PotTransmem short:ptm] DF_NtermPrecursorProt:$srsfield:[NtermPrecursorProt short:ntp] DF_NtermMatureProt:$srsfield:[NtermMatureProt short:ntm] DF_CtermMatureProt:$srsfield:[CtermMatureProt short:ctm] DF_Description:$srsfield:[Description short:des] DF_RefList:$srsfield:[RefList short:rel] $abbrev={ malc: { csk: "cytoskeletal" cyt: "cytoplasmic" nuc: "nuclear" mit: "mitochondrial" ves: "vesicles of secretory system" end: "endoplasmic reticulum" gol: "Golgi" vac: "vacuolar" lip: "lipid particles" pla: "plasma membrane" pox: "peroxisomal" exc: "extracellular, including cell wall" mem: "unspecified membrane" } milc: { mim: "mitochondrial inner membrane" mom: "mitochondrial outer membrane" spb: "spindle pole body" ncl: "nucleolus" num: "nuclear matrix" nup: "nuclear pore" wal: "cell wall" } mole: { sol: "soluble" int: "integral membrane" per: "peripheral membrane" act: "actin cytoskeleton-associated" tub: "tubulin cytoskeleton-associated" dna: "dna-associated (direct or indirect)" psf: "protein synthesis factor" rna: "rna-associated" rib: "ribosome-associated" } func: { aaa: "conserved ATPase domain (CDC48/PAS1/SEC18 family)" aam: "amino acid metabolism" abc: "ATP-binding cassette" cyc: "cyclin" gap: "GTPase activating protein" glm: "glucose metabolism (glycolysis)" gtp: "GTP-binding protein" gef: "guanine nucleotide exchange factor" hsp: "Heat shock protein" pep: "protease (other than proteasomal)" pki: "protein kinase" ppa: "protein phosphatase" pre: "proteasomal protein" srp: "serine-rich protein (Tip1p/Tir1p) family" trf: "transcription factor" trs: "tRNA synthetase" ubc: "ubiquitin-conjugating enzyme" } ntm: { A: acetylation M: myristoylation 0: none } ctm: { F: farnesylation G: geranylgeranylation I: "gpi anchor" } phos: { P: phosphorylation } glyc: { N: "N-linked glycosylation" O: "O-linked glycosylation" } } $names={ ygn: {norm str "YPD gene name"} sgn: {norm str "SWISS-PROT/LISTA gene name"} sgdn: {norm str "Saccharomyces Genome Database name"} syn: {norm str "Synonym list"} {titl nil "Technical flags"} idf: {norm num "Identical sequence flags"} csf: {norm num "Closely-related sequence flags"} dbs: {norm num "Database source"} ssf: {norm num "Systematic sequence flag"} {titl nil "Calculated data"} isop: {norm num "Isoelectric point"} isopp: {norm num "Isoelectric point after adding 1 positive charge"} isopn: {norm num "Isoelectric point after adding 1 negative charge"} molw: {norm num "Molecular weight"} codb: {norm num "Codon bias"} coda: {norm num "Codon adaptation index"} {titl nil "Genetic data"} chrn: {norm str "Chromosome number"} intg: {norm str "Presence or absence of intron in gene"} knm: {norm str "Knockout mutation"} {titl nil "Accession numbers"} gb: {norm str "GenBank"} pir: {norm str "PIR-International"} sw: {norm str "SWISS-PROT"} yepd: {norm str "YEPD"} {titl nil "Subcellular localization and functional classification"} malc: {abbr str "Major localization category"} milc: {abbr str "Minor localization category"} mole: {abbr str "Molecular environment"} func: {abbr str "Functional classification"} {titl nil "Post-translational modifications and length"} ntm: {abbr str "N-terminal modification"} ctm: {abbr str "C-terminal modification"} phos: {abbr str "Phosphorylation"} glyc: {abbr str "N- or O-linked glycosylation"} ntpl: {norm num "N-terminal precursor length"} mpl: {norm num "Mature protein length"} {aa nil "Amino acid composition"} maf: {norm str "Met-adjust field"} {titl nil "Motifs"} pcdc: {norm num "Potential sites for phosphorylation by Cdc28 protein kinase"} pckii: {norm num "Potential sites for phosphorylation by CKII protein kinase"} ppka: {norm num "Potential sites for phosphorylation by PKA protein kinase"} nglyc: {norm num "Potential sites for N-linked glycosylation"} ptm: {norm num "Potential transmembrane domains"} {titl nil "N- and C-terminal sequence fragments"} nspp: {norm str "N-terminal sequence of precursor protein"} nsmp: {norm str "N-terminal sequence of mature protein"} csmp: {norm str "C-terminal sequence of mature protein"} {titl nil "Protein name/description and references"} pn: {norm str "Protein name and descriptive phrases"} refs: {norm str "List of references"} } $rules={ tablehdr: ~ {$Out $exit} (/[^\t\n]+/ {$print:"$Ct\n"} '\t'*)+ ~ entry: ~ {$In:[file:text] $Out} (('YPD name' ln)? ln {$entryFip=$Fip $Wrt} ln?)? ~ # parsing fields fields: ~ {$In:entry $Out pre{$n=1 $Skip:0} $Skip:1} (/[^\t\n]*/ {$tag=$names[$n][3] $code=$Key:$names[$n] $Prod:$names[$n][1] $n=$n+1} /\t|\n/)+ ~ titl: ~ x:{$Wrt:[$code s:"\n** $tag **\n\n"]} ~ norm: ~ x:{if:$Ct!="" $Wrt:[$code s:{"%s\n %s\n" $tag $Ct}]} ~ abbr: ~ x:{if:$Ct!="" $Wrt:[$code s:{"$tag\n %s\n" $abbrev."$code".$Ct}]} ~ aa: ~ {init{$res={' A' C D E F G H I K L M N P Q R S T V W Y}}} /\t|\n/ /[^\t\n]*/ { $Wrt:[$code s:"$tag\n"] foreach:[$aa in:$res] {$Prod:residue $App:[s:"$aa:$num "]} $App:[s:"\n"] } ~ residue: ~ /[^\t\n]*/ {$num=$Ct} /\t|\n/ ~ # indexing id: ~ {$In:[fields c:ygn] $Out:id $Wrt:[s:$1]} ln / *"?([,a-zA-Z0-9_-]+)"?/ ~ number: ~ {$In:[fields] $Out pre{$Skip:1}} x:{if:$Itc == "" || $names.($Itc)[2]!=num $Fail} tag num ~ words: ~ {$In:[fields] $Out pre{$Skip:1}} x:{if:$Itc == "" || $names.($Itc)[2]!=str $Fail} tag word+ ~ # html display h_fields: ~ {$In:[fields t:hl] $Out} ( /.*\\*\\*([^\\*]+)\\*\\*/ {$Rep:"

    $1

    "} | /[^ ][^\n]+/ {$Rep:""} /.+/ {$Rep:""} )? ~ # other ln: ~ /[^\n]*\n/ ~ num: ~ /<[^>]+>/* /-?[0-9.]+/ {$Wrt:$Itc}~ word: ~ /[a-z0-9A-Z_-]+/ {$Uniq:$Itc} | /<[^>]+>/ | /[^a-z0-9A-Z_-]/ ~ tag: ~ /[^\n]*/ ~ } #$fil = $fileOpen:"/data/ypd/YPD_ASCII" #$job = $jobNew:[prod:$rules skip:" \n\t"] # #$jobNext:[$job file:$fil] #while:$jobTokens:[$job name:words print:1 withCode:1] { ## $jobTokens:[$job name:molw print:1] ## $jobTokens:[$job name:fields withCode:0 print:1] # $jobEnd:$job # $jobNext:[$job file:$fil] # $print:"//\n" #} /srs/icarus/util 7 1996// /arglist.ic/1.2/Wed Jul 24 22:07:11 1996// /ascii.it/1.2/Sun Aug 11 22:51:20 1996// /builtin.i/1.14/Sun Aug 11 22:51:21 1996// /builtin.ic/1.2/Fri May 24 14:11:50 1996// /classes.i/1.3/Tue Jul 30 10:49:02 1996// /command.i/1.1/Mon May 6 16:13:59 1996// /ica2c.it/1.6/Mon Aug 12 23:00:35 1996// /icacom.ic/1.3/Wed Jul 24 22:07:13 1996// /icarus.i/1.1/Mon May 6 16:14:00 1996// /icarus.is/1.1/Mon May 6 16:14:01 1996// /makewild.i/1.2/Sun Jul 14 16:21:51 1996// /man_capi.i/1.6/Mon Aug 12 11:21:43 1996// /man_chap.i/1.4/Tue Aug 13 12:21:32 1996// /man_inx.i/1.3/Tue Aug 13 12:21:33 1996// /man_toc.i/1.5/Tue Aug 13 12:21:33 1996// /man_usage.i/1.1/Wed Jul 24 22:07:15 1996// /odd.i/1.2/Fri May 24 14:11:51 1996// /odd.ic/1.2/Fri May 24 14:11:52 1996// /oddfncts.i/1.1/Mon May 6 16:14:03 1996// /oddgen.i/1.1/Mon May 6 16:14:03 1996// /parameter.i/1.9/Sun Aug 11 22:51:23 1996// /parameter.ic/1.1/Mon May 6 16:14:05 1996// /script.i/1.1/Mon May 6 16:14:06 1996// /script.is/1.8/Mon Aug 12 11:21:44 1996// /srs.i/1.2/Mon May 6 19:22:06 1996// /srs.ic/1.2/Mon May 6 19:22:07 1996// /srscheck.i/1.2/Sun Aug 11 22:51:24 1996// /srsenv.i/1.1/Mon May 6 19:22:10 1996// /srsgen.i/1.9/Wed Jul 24 22:07:17 1996// /srsgen.ic/1.11/Sun Aug 11 22:51:25 1996// /srsquery.i/1.4/Tue Jul 9 20:39:41 1996// /srswww.i/1.19/Mon Aug 12 16:18:39 1996// /syntax.ic/1.2/Wed Jul 24 22:07:19 1996// /translation.i/1.1/Mon May 6 16:14:11 1996// /translation.ic/1.2/Fri May 24 14:11:55 1996// # # $RCSfile: arglist.i,v $ # $Revision: 1.9 $ # $Date: 1996/08/12 23:14:47 $ # $Author: etzold $ # # # definition of command line options for SRS programs # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $command:[name:srsbuild usage:"libName [libName]" vars:{ $arg:[name:"-help" type:help comment:"this message"] $arg:[name:"-w" parameter:showWarnings] $arg:[name:"-c" parameter:compress] $arg:[name:"-t" parameter:touchIndex] $arg:[name:"-f" parameter:fieldList] $arg:[name:"-b" parameter:buildIndex] $arg:[name:"-d" parameter:parseTest] $arg:[name:"-l" parameter:readLink] $arg:[name:"-r" parameter:relocateLib] $arg:[name:"-i" parameter:indexLink] $arg:[name:"-xdir" parameter:indexDirName] $arg:[name:"-odir" parameter:outDirName] $arg:[name:"-info" parameter:printLibInfo] $arg:[name:"-libs" parameter:printLibs] $arg:[name:"-rel" parameter:releaseName] $arg:[name:"-env" parameter:environment] } ] $command:[name:wgetz usage:"'queryExpression'" vars:{ $arg:[name:"-help" comment:"this message" type:help] $arg:[name:"-e" parameter:printEntireEntry] $arg:[name:"-fun" parameter:wwwFunctionName] $arg:[name:"-id" parameter:"userId"] $arg:[name:"-l" parameter:"libList"] $arg:[name:"-h3" parameter:"isHtml3"] $arg:[name:"-style" parameter:"style"] $arg:[name:"-dbg" parameter:"isDebug"] $arg:[name:"-lo" parameter:"linkToLibs"] $arg:[name:"-qm" parameter:"wwwFunctionName" defaultstr:"PageQueryManager"] $arg:[name:"-qf" parameter:"wwwFunctionName" defaultstr:"PageQueryForm"] $arg:[name:"-top" parameter:"wwwFunctionName" defaultstr:PageStart] $arg:[name:"-start" parameter:"wwwFunctionName" defaultstr:"PageSelectLibrary"] $arg:[name:"-libs" parameter:"wwwFunctionName" defaultstr:"WwwPrintLibList"] $arg:[name:"-rep" parameter:"doRepeat"] $arg:[name:"-info" parameter:"libInfo"] $arg:[name:"-linfo" parameter:"wwwFunctionName" defaultstr:"PageLinkInfo"] $arg:[name:"-from" parameter:fromLibName] $arg:[name:"-to" parameter:toLibName] $arg:[name:"-blast" parameter:"prepBlastSearch"] $arg:[name:"-ht" parameter:"printHelpTopic"] $arg:[name:"-viv" parameter:"visitIndexValue"] $arg:[name:"-f" parameter:fieldList] $arg:[name:"-bl" parameter:listEntriesStartN] $arg:[name:"-ll" parameter:listEntriesChunkSize] $arg:[name:"-bv" parameter:viewEntriesStartN] $arg:[name:"-lv" parameter:viewEntriesChunkSize] $arg:[name:"-lset" parameter:listSetNumber] $arg:[name:"-vset" parameter:viewSetNumber] $arg:[name:"-lquery" parameter:listQuery] $arg:[name:"-msg" parameter:getMessage] $arg:[name:"-sf" parameter:"seqFormat"] $arg:[name:"-subn" parameter:subEntryN] $arg:[name:"-tr" parameter:translateSequence] $arg:[name:"-network" parameter:printNetwork] $arg:[name:"-ls" parameter:linkLibSelect] $arg:[name:"-link" parameter:printLinkTable] $arg:[name:"-odd" parameter:getOddFile] $arg:[name:"-env" parameter:environment] $arg:[name:"-q" parameter:queryString] $arg:[name:"-use" parameter:"readUserFile"] $arg:[name:"-w" parameter:"makeWild"] $arg:[name:"-mime" parameter:"mimeType"] $arg:[name:"-qnum" parameter:"queryNumber"] $arg:[name:"-dp" parameter:"deleteParam"] $arg:[name:"-bm" parameter:"mimeEntriesStartN"] $arg:[name:"-lm" parameter:"mimeEntriesChunkSize"] $arg:[name:"-m" parameter:"method"] $arg:[name:"-vroot" parameter:viewLibListRoot] $arg:[name:"-vleaf" parameter:viewLibListLeaf] $arg:[name:"-vl" parameter:viewName] $arg:[name:"-cv" parameter:currentView] $arg:[name:"-vt" parameter:isTable] $arg:[name:"-vn" parameter:"viewNumber"] $arg:[name:"-fbegs" parameter:shiftbeginpos] $arg:[name:"-fends" parameter:shiftendpos] $arg:[name:"-fbegsrend" parameter:isshiftbeginrelend] $arg:[name:"-fendsrbeg" parameter:isshiftendrelbegin] $arg:[name:"-takeuncf" parameter:takeuncompletefeature] $arg:[name:"-takeuncsf" parameter:takeuncompleteshiftfeature] $arg:[name:"-bf" parameter:browseIndex] $arg:[name:"-blib" parameter:browseLibs] $arg:[name:"-color" parameter:wwwColorScheme] $arg:[name:"-sl" parameter:wwwSessionEntryList] } ] $command:[name:getz usage:"'queryExpression'" vars:{ $arg:[name:"-help" comment:"this message" type:help] $arg:[name:"-e" parameter:printEntireEntry] $arg:[name:"-f" parameter:fieldList] $arg:[name:"-vf" parameter:viewFieldList] $arg:[name:"-l" parameter:libList] $arg:[name:"-w" parameter:makeWild] $arg:[name:"-r" parameter:doQueryReport] $arg:[name:"-lv" parameter:queryListValues] $arg:[name:"-lmin" parameter:minIndexValN] $arg:[name:"-qf" parameter:queryFileName] $arg:[name:"-xdir" parameter:indexDirName] $arg:[name:"-info" parameter:printLibInfo] $arg:[name:"-libs" parameter:printLibs] $arg:[name:"-fosn" parameter:listFOSN] $arg:[name:"-fil" parameter:printToFile] $arg:[name:"-sf" parameter:seqFormat] $arg:[name:"-pos" parameter:fosnWithPos] $arg:[name:"-link" parameter:linkTable] $arg:[name:"-si" parameter:getStartupInfo] $arg:[name:"-html" parameter:isHTMLFormat] $arg:[name:"options for retrieval of sequence features" type:title] $arg:[name:"-fbegs" parameter:shiftbeginpos] $arg:[name:"-fends" parameter:shiftendpos] $arg:[name:"-fbegsrend" parameter:isshiftbeginrelend] $arg:[name:"-fendsrbeg" parameter:isshiftendrelbegin] $arg:[name:"-takeuncf" parameter:takeuncompletefeature] $arg:[name:"-takeuncsf" parameter:takeuncompleteshiftfeature] $arg:[name:"-env" parameter:environment] } ] $command:[name:try usage:"'dataFile'" vars:{ $arg:["-help" comment:"this message" type:help] $arg:["-t" parameter:printTrace] $arg:["-dbg" parameter:icaIsDebug] $arg:["-tt" parameter:printSyntaxTree] $arg:["-task" parameter:productionName] $arg:["-synx" parameter:syntaxName] $arg:["-pall" parameter:printAllTokLists] $arg:["-des" parameter:icaDbgExecStack defaultnum:2] $arg:["-dbs" parameter:icaDbgBuildStack defaultnum:4] $arg:["-2c" parameter:ica2cName] $arg:["-use" parameter:useIni] $arg:["-rb" parameter:readBuiltin] $arg:["-class" parameter:doClassInfo] $arg:["-ci" parameter:doCommandInfo] } ] $command:[name:trembl usage:"" vars:{ $arg:[name:"-help" comment:"this message" type:help] $arg:[name:"-l" parameter:libName] $arg:[name:"-f" parameter:tremblInFile] $arg:[name:"-c" parameter:findAccNoCommand] $arg:[name:"-sf" parameter:inputSeqFile] $arg:[name:"-s" parameter:printSeparateFiles] $arg:[name:"-o" parameter:outputFileName] } ] $command:[name:srscheck usage:"" vars:{ $arg:[name:"-help" type:help comment:"this message"] $arg:[name:"-xdir" parameter:indexDirName] $arg:[name:"-odir" parameter:outDirName] $arg:[name:"-info" parameter:printLibInfo] $arg:[name:"-e" parameter:etcDir] $arg:[name:"-s" parameter:procIndexSize] $arg:[name:"-l" parameter:checkLibList] $arg:[name:"-L" parameter:notCheckLibList] $arg:[name:"-header" parameter:srsEnvHeader] $arg:[name:"-o" parameter:updateScriptName] $arg:[name:"-env" parameter:environment] } ] $command:[name:reflink usage:libName vars:{ $arg:[name:"-help" type:help comment:"this message"] $arg:[name:"-r" parameter:readLib] $arg:[name:"-s" parameter:searchLib] $arg:[name:"-jf" parameter:journalListFile] $arg:[name:"-j" parameter:doJournalList] $arg:[name:"-m" parameter:doMergeJournalLists] $arg:[name:"-l" parameter:doRefLink] $arg:[name:"-p" parameter:doRefLinkFile] } ] $command:[name:srspict usage:"" vars:{ $arg:[name:"-help" type:help comment:"this message"] $arg:[name:"-n" parameter:doNetworkPict] $arg:[name:"-t" parameter:doGraphTablePict] } ] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: arglist.ic,v $ # $Revision: 1.2 $ # $Date: 1996/07/24 22:07:11 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ O_GETARG:$object:[name:arg typname:"arg_t" declname:args status:system attrs:{ $attribute:[name:name type:string declname:name valtype:{name text} required:y unnamed:y] $attribute:[name:type declname:type type:int valtype:name defaultval:0 enum:{ $value:[name:bool val:2] $value:[name:string val:6] $value:[name:number val:3] $value:[name:real val:4] $value:[name:parameter val:0] $value:[name:help val:1] $value:[name:title val:2] } ] $attribute:[name:parameter declname:parameter type:string valtype:{name text} ] $attribute:[name:comment declname:comment type:string valtype:{name text}] $attribute:[name:check type:function declname:check defaultstr:"(void *)" valtype:constant] $attribute:[name:defaultnum type:int valtype:num declname:defaultNum] $attribute:[name:defaultstr type:string valtype:{name text} declname:defaultStr] $attribute:[name:defaultreal type:float valtype:num declname:defaultReal] } ] O_COMMAND:$object:[name:command typname:"ARGoLIST" declname:"argList" nchilds:1 child:@O_GETARG status:system attrs:{ $attribute:[name:name declname:name type:string valtype:name unnamed:y] $attribute:[name:usage declname:usage type:string valtype:{name text}] $attribute:[name:vars declname:"arg" type:child defaultval:@O_GETARG] $attribute:[declname:"argN" type:nr_of_childs defaultval:@O_GETARG] } ] # $RCSfile: ascii.it,v $ # $Revision: 1.2 $ # $Date: 1996/08/11 22:51:20 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $queryReport={ head: | |//////////////////////////////////////////////////////////////////////////// library: | |Values in "%s" value: | %-65s %d tail: | |//////////////////////////////////////////////////////////////////////////// | |report of query "%s" | } $libInfo={ head: |Databank: "%s" from group "%s", Release: %s | |Data Fields (B=busy, C=compressed): | |Name Short Type Inx Ids No No Creation B C | Name (kb) (kb) Words IDs Date |------------------------------------------------------------------------------- field:{ head: |%-20s %-5s %-5s index: |%6d %7d %8d %9s %d %d tail: |%s } links:{ head: | |Links: | link: |%s "%s" to "%s" } Source:{ dir:{ head: |Directory: name: | "%s" tail: | } files:{ head: |Filename(s): } } } $linkInfo={ } $classInfo={ } $entry={ inList:{ envelope:{ head: { preformatted: '' topicList: '' table: '' } tail: { preformatted: '' topicList: '' table: '' } } entry:{ name:'' #? inListNoId: |%s rootName: |%s leafName: |%s head:'' tail:'' } } inTable:{ # before first entry in a set head: '' # table header title:{ library: '' field: '' tail: '' } entry:{ head: '' tail: '\n' rootName: '%s||' leafName: '%s||' value:{ leftAlign: '' rightAlign: '' center: '' listing: '' value: '%s' empty: ' ' next: ',' tail: '||' } emptyValue: ' ||' onlyEntryN: '%d ||' } tail: '' } } # # commands for processing icarus 4 with icarus 4 # $com:[_prog f:IopProg_] $com:[_opnd f:IopOpnd_ return:var args:{ $var:[opnd t:strv unnamed:y] $var:[t t:strv] } ] $com:[_list f:IopList_ return:var] $com:[_assoc f:IopAssoc_ return:var args:{ $var:[val t:var unnamed:y] $var:[key t:var] } ] $com:[_binop f:IopBinop_ return:var args:{ $var:[op t:strv unnamed:y] $var:[a t:var] $var:[b t:var] } ] $com:[_strmake f:IopStrMake_ return:var] $com:[_makearg f:IopMakeArg_ return:var args:{ $var:[val t:var unnamed:y] $var:[name t:var] } ] $com:[_select f:IopSelect_ return:var args:{ $var:[key t:var] $var:[index t:var] $var:[var t:var] } ] $com:[_func f:IopFunc_ return:var] $com:[_body f:IopBody_ return:var] $com:[_ref f:IopRef_ return:var args:{ $var:[name t:var unnamed:y] $var:[opt t:int] } ] #flow control $com:[_file f:IopFile_ return:var args:{$var:[file t:var unnamed:y]}] $com:[_pre f:IopPre_ return:var args:{$var:[body unnamed:y t:var]}] $com:[_init f:IopInit_ return:var args:{$var:[body unnamed:y t:var]}] $com:[_for f:IopFor_ return:var args:{ $var:[i t:var] $var:[c t:var] $var:[u t:var] $var:[b t:var] } ] $com:[_foreach f:IopForeach_ return:var args:{ $var:[body t:var] $var:[list t:var] $var:[var t:var] } ] $com:[_while f:IopWhile_ return:var args:{ $var:[c t:var] $var:[b t:var] } ] $com:[_if f:IopIf_ return:var] #parsinge BNF rules $com:[_prod f:IopProd_ return:object returnClass:node] $com:[_endProd f:IopEndProd_ return:var args:{ $var:[node t:object class:node] $var:[prod t:object class:node] } ] $com:[_expr f:IopExpr_ return:object returnClass:node] $com:[_term f:IopTerm_ return:object returnClass:node] $com:[_regexp f:IopRegexp_ return:object returnClass:node args:{$var:[reStr t:strv unnamed:y]} ] $com:[_literal f:IopLiteral_ return:object returnClass:node args:{$var:[name t:strv unnamed:y]} ] $com:[_makeOpt f:IopMakeOpt_ return:object returnClass:node args:{ $var:[node t:object unnamed:y] $var:[t t:strv] } ] $com:[_nodeProg f:IopNodeProg_ return:object returnClass:node args:{ $var:[node t:object unnamed:y] $var:[prog t:var unnamed:y ] } ] $com:[_prodName f:IopProdName_ return:object returnClass:node args:{ $var:[name t:strv unnamed:y] $var:[lookahead t:int] } ] $com:[_doCom f:IopCommand_ return:object returnClass:node] $com:[_doInputEnd f:IopInputEnd_ return:object returnClass:node] $com:[_nullNode f:IopNullNode_ return:object returnClass:node] ###### $com:[_push f:IopPush_ args:{$var:[value t:var unnamed:y] $var:[stack t:int defInt:0]}] $com:[_push1 f:IopPush_ args:{$var:[value t:var unnamed:y] $var:[stack t:int defInt:1]}] $com:[_push2 f:IopPush_ args:{$var:[value t:var unnamed:y] $var:[stack t:int defInt:2]}] $com:[_push3 f:IopPush_ args:{$var:[value t:var unnamed:y] $var:[stack t:int defInt:3]}] $com:[_push4 f:IopPush_ args:{$var:[value t:var unnamed:y] $var:[stack t:int defInt:4]}] $com:[_push5 f:IopPush_ args:{$var:[value t:var unnamed:y] $var:[stack t:int defInt:5]}] $com:[_pop f:IopPop_ return:var args:{$var:[stack t:int defInt:0]}] $com:[_pop1 f:IopPop_ return:var args:{$var:[stack t:int defInt:1]}] $com:[_pop2 f:IopPop_ return:var args:{$var:[stack t:int defInt:2]}] $com:[_pop3 f:IopPop_ return:var args:{$var:[stack t:int defInt:3]}] $com:[_pop4 f:IopPop_ return:var args:{$var:[stack t:int defInt:4]}] $com:[_pop5 f:IopPop_ return:var args:{$var:[stack t:int defInt:5]}] # # end of icarus 4 build commands ############################################################################## # # commands for debugging icarus productions # $com:[break f:IopBreak time:init args:{ $var:[prod unnamed:y t:strv] $var:[time t:int enum:{ $val:[pre n:1] $val:[post n:2] } ] } ] $com:[next f:IopNext] $com:[continue f:IopContinue] ###### end debugging ############################### $com:[prod f:IopProd args:{ $var:[name unnamed:y] } ] $com:[Prod f:IopProd show:y args:{ $var:[name unnamed:y] } ] $com:[CDefine f:IopCDefine args:{ $var:[n t:int unnamed:y] $var:[name] } ] # 'normal' icarus commands (level 3) $com:[test f:IopTest rem:"Test command." return:int args:{ $var:[x t:int] $var:[y t:int] $var:[color] } ] $com:[printProd f:IopPrintProduction rem:"Prints a production." return:int args:{ $var:[prod t:object class:production unnamed:y] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # commands for parsing # $com:[Parse show:y f:IopParse rem:"Parses a string." args:{ $var:[prod t:list] $var:[string t:strv unnamed:y] $var:[start t:strv rem:"The name of the start symbol (production)."] $var:[file t:object class:file rem:"Selects opened file to be read for input."] $var:[fileName t:strv rem:"Selects opened file to be read for input."] $var:[show t:int rem:"Sets display of the syntax before parsing."] $var:[skip t:strv rem:"The set of characters to be skipped as white space"] $var:[comment t:strv rem:"Regular expression for skipping comments"] $var:[tree t:int rem:"Flag if set requests printing the syntax tree."] } ] $com:[JobNew show:y f:IopJobNew rem:"" return:object returnClass:job rem: |Creates a new parsing job and associates it with a syntax and |the input. Use \$JobTokens to start the parsing (lazy parsing) and |\$JobNext to move to the next job in the input stream. args:{ $var:[prod t:list unnamed:y] $var:[skip t:strv rem:"The set of characters to be skipped as white space"] $var:[comment t:strv rem:"Regular expression for skipping comments"] $var:[file t:object class:file rem:"Sets opened file as input."] $var:[str t:strv rem:"Sets string as input."] $var:[show t:int rem:"Sets display of the syntax before parsing."] $var:[tree t:int rem:"Flag if set requests printing the syntax tree."] } ] $com:[Fail show:y f:IopFail rem: |Can be used only in an action node. If called the action node reports |a parsing error which is treated in the same way as a 'normal' parsing |error from, eg, a literal. ] $com:[JobNext show:y f:IopJobNext rem:"" args:{ $var:[job t:object class:job unnamed:y] $var:[string t:string] $var:[start rem:"The name of the start symbol (production)."] $var:[file t:object class:file rem:"Selects opened file to be read for input."] $var:[fileName rem:"Selects opened file to be read for input."] } ] $com:[JobEnd show:y f:IopJobEnd rem:"" args: { $var:[job t:object class:job unnamed:y] } ] $com:[JobTokens show:y f:IopJobTokens return: int args:{ $var:[job t:object class:job unnamed:y] $var:[name rem:"Name of the token list."] $var:[code] $var:[n t:int] $var:[print t:int] $var:[task] $var:[withCode t:int defInt:1] $var:[outFile t:object class:file rem:"Output file object."] } ] $com:[In f:IopIn show:y time:initpre return:int rem:"Sets the input token table for parsing." args:{ $var:[in unnamed:y required:y t:strv rem:"Name of the input token table."] $var:[c t:strv rem:"Token code."] $var:[n t:int defInt:-1 rem:"Numerical token code."] $var:[p t:strv rem:"Name of production to be linked."] $var:[t t:strv rem:"Name of task that if results in forced parsing."] $var:[count t:strv rem:""] $var:[var t:var rem:""] $var:[file t:strv rem:"Symbolic name of the input file."] } ] $com:[in f:IopIn time:initpre return:int rem:"Sets the input token table for parsing." args:{ $var:[in unnamed:y required:y t:strv rem:"Name of the input token table."] $var:[c t:strv rem:"Token code."] $var:[n t:int rem:"Numerical token code."] $var:[p t:strv rem:"Name of production to be linked."] $var:[t t:strv rem:"Name of task that if results in forced parsing."] $var:[count t:strv rem:""] $var:[var t:var rem:""] $var:[file t:strv rem:"Symbolic name of the input file."] } ] $com:[Out f:IopOut show:y time:initpre rem: |Sets the output table for all writing of tokens for the |current production and its dependants. args:{ $var:[name unnamed:y t:strv rem:"Name of ouput token table."] } ] $com:[out f:IopOut time:initpre rem: |Sets the output table for all writing of tokens for the |current production and its dependants. args:{ $var:[name unnamed:y t:strv rem:"Name of ouput token table."] } ] $com:[Getc f:IopGetc call:direct args:{$var:[len]}] $com:[Len f:IopRestrictLength time:prepost call:direct args:{$var:[len]}] $com:[Mov f:IopMove show:y call:direct time:pre args:{$var:[len]}] $com:[Wrt f:IopWrt show:y call:direct rem: |This function can be called inside an action attached to the symbol of |a production. It writes the match of the current symbol or a specified |string into the output table specified by the most recent call of \$out. args:{ $var:[c unnamed:y rem:"token code as a name"] $var:[n t:int rem:"token code as a number"] $var:[s rem: |string to be written to the token table. |If left unspecified the current match, or current token (\$Ct) |is written. ] } ] $com:[wrt f:IopWrt call:direct rem: |This function can be called inside an action attached to the symbol of |a production. It writes the match of the current symbol or a specified |string into the output table specified by the most recent call of \$out. args:{ $var:[c unnamed:y rem:"token code as a name"] $var:[n t:int rem:"token code as a number"] $var:[s rem: |string to be written to the token table. |If left unspecified the current match, or current token (\$Ct) |is written. ] } ] $com:[Uniq f:IopUniq show:y call:direct rem: |Exactly as \$wrt but writes the token only into the table if it does |not already exist. Unique here means that both the token string as the |token code are used for comparison. args:{ $var:[c unnamed:y rem:"token code as a name"] $var:[n t:int rem:"token code as a number"] $var:[s rem: |string to be written to the token table. |If left unspecified the current match, or current token (\$Ct) |is written. ] } ] $com:[App show:y f:IopApp call:direct args:{ $var:[s unnamed:y rem:"String to be written to the token table."] } ] $com:[app f:IopApp call:direct args:{ $var:[s unnamed:y rem:"String to be written to the token table."] } ] $com:[Rep show:y f:IopRep rem: |Replaces the current token (\$Ct) in case of a symbol match. The |input cursor is moved after the replaced string. args:{ $var:[s t:var unnamed:y rem:"String with which current match is to be replaced"] } ] $com:[rep f:IopRep rem: |Replaces the current token (\$Ct) when args:{ $var:[s t:var unnamed:y rem:"String with which current match is to be replaced"] } ] $com:[Not show:y f:IopNot time:init] $com:[not f:IopNot time:init] $com:[noskip f:IopNoskip time:init] $com:[Noskip show:y f:IopNoskip time:init] $com:[Request show:y f:IopRequest args:{ $var:[name unnamed:y rem:"Name of requested token table."] } ] $com:[nocase show:y f:IcaOpSetFlag args:{$var:[flag defStr:nocase]} ] $com:[push show:y f:IopPush args:{ $var:[value t:var unnamed:y] $var:[stack t:int defInt:0] } ] $com:[push1 f:IopPush args:{ $var:[value t:var unnamed:y] $var:[stack t:int defInt:1] } ] $com:[push2 f:IopPush args:{ $var:[value t:var unnamed:y] $var:[stack t:int defInt:2] } ] $com:[push3 f:IopPush args:{ $var:[value t:var unnamed:y] $var:[stack t:int defInt:3] } ] $com:[push4 f:IopPush args:{ $var:[value t:var unnamed:y] $var:[stack t:int defInt:4] } ] $com:[push5 f:IopPush args:{ $var:[value t:var unnamed:y] $var:[stack t:int defInt:5] } ] $com:[pop show:y f:IopPop return:var args:{$var:[stack t:int defInt:0]}] $com:[pop1 f:IopPop return:var args:{$var:[stack t:int defInt:1]}] $com:[pop2 f:IopPop return:var args:{$var:[stack t:int defInt:2]}] $com:[pop3 f:IopPop return:var args:{$var:[stack t:int defInt:3]}] $com:[pop4 f:IopPop return:var args:{$var:[stack t:int defInt:4]}] $com:[pop5 f:IopPop return:var args:{$var:[stack t:int defInt:5]}] $com:[exit show:y f:IopExit args:{$var:[val unnamed:y defInt:0]}] # global parameter list $com:[parStr f:IopParStr return:strv rem: |Returns the value of a 'string' parameter or sets its value if ".set" is |defined. args:{ $var:[name t:strv unnamed:y rem:"Parameter name."] $var:[set t:strv] } ] $com:[parInt f:IopParInt return:int rem: |Returns the value of an 'int' parameter or sets its value if ".set" is |defined. args:{ $var:[name t:strv unnamed:y rem:"Parameter name."] $var:[set t:int defInt:2] } ] $com:[ParStr show:y f:IopParStr return:strv rem: |Returns the value of a 'string' parameter or sets its value if ".set" is |defined. args:{ $var:[name t:strv unnamed:y rem:"Parameter name."] $var:[set t:strv] } ] $com:[ParInt show:y f:IopParInt return:int rem: |Returns the value of an 'int' parameter or sets its value if ".set" is |defined. args:{ $var:[name t:strv unnamed:y rem:"Parameter name."] $var:[set t:int defInt:2] } ] $com:[ParDel show:y f:IopParDel rem: |Deletes the parameter with specified name. args:{ $var:[name t:strv unnamed:y rem:"Parameter name."] } ] $com:[subStr f:IcaOpSubStr return:strv args:{ $var:[str t:strv unnamed:y rem:"Classical substr function"] $var:[s t:int required:y rem:"Start posilion inside of string"] $var:[l t:int required:n defInt:0 rem:"subStr length if ommited - suffix"] } ] $com:[System f:IopSystem return:strv args:{ $var:[com required:y t:string unnamed:y rem:"Unix command"] $Var:[off required:n t:int rem:"output suppresor flag" enum:{ $val:[out n:1] $val:[err n:2] $val:[all n:3] } ] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Function to work with images (GIF) # $com:[ImNew f:IgdImageCreate return:object returnClass:image rem:"Creates a new image optionally from a gif file." args:{ $var:[x t:int rem:"Width of image in pixels"] $var:[y t:int rem:"Height of image in pixels"] $var:[file t:string rem:"Input gif file."] } ] $com:[ImRect f:IgdRectangle return:object returnClass:image rem:"Creates a rectangle that can be optionally filed or tiled." args:{ $var:[im t:object class:image rem:"Input image." required:y unnamed:y] $var:[x1 t:int rem:"X-coordinate of lower right corner." required:y] $var:[y1 t:int rem:"Y-coordinate of lower right corner." required:y] $var:[x2 t:int rem:"X-coordinate of upper left corner." required:y] $var:[x3 t:int rem:"Y-coordinate of upper left corner." required:y] $var:[tile t:object class:image rem:"Image used for tiling."] $var:[rgb t:list rem:"Color specified as list of three RGB values"] $var:[filled rem:"Flag if rectangle should be filled or not"] } ] $com:[string f:IgdString methodOf:image args:{ $var:[s unnamed:y rem:""] $var:[orient enum:{$val:[horiz n:0] $val:[vert n:1]} rem:"Orientation of string." ] $var:[font rem:""] $var:[x rem:""] $var:[y rem:""] $var:[color rem:""] } ] $com:[ImString f:IgdString args:{ $var:[s unnamed:y rem:""] $var:[orient enum:{$val:[horiz n:0] $val:[vert n:1]} rem:"Orientation of string." ] $var:[font rem:""] $var:[x rem:""] $var:[y rem:""] $var:[color rem:""] } ] $com:[ImLine f:IgdLine args:{ $var:[style t:list rem:"Define line style by defining a pattern of arbitrary length where each pixel is represented by a color." ] } ] $com:[ImCopy f:IgdImageCopy ] $com:[ImPoly f:IgdPoly ] $com:[ImArg f:IgdArc ] $com:[ImWrite f:IgdImageWrite ] $com:[fileOpen f:IopFileOpen return:object returnClass:file args:{ $var:[name t:strv unnamed:y] $var:[mode t:strv] } ] $com:[fileClose f:IopFileClose args:{ $var:[file t:object class:file unnamed:y] } ] $com:[FileOpen show:y f:IopFileOpen return:object returnClass:file args:{ $var:[name t:strv unnamed:y] $var:[mode t:strv] } ] $com:[FileClose show:y f:IopFileClose args:{ $var:[file t:object class:file unnamed:y] } ] $com:[_close methodOf:file] $com:[_next methodOf:file] $com:[_lineN methodOf:file] $com:[_name methodOf:file args:{ $var:[t unnamed:y enum:{ $val:[path n:1 rem:"The complete path."] $val:[dir n:2 rem:"The directory name"] $val:[ext n:3 rem:"The file extension name (after the '.')."] $val:[name n:4 rem:"The name without directory and extension names."] $val:[file n:4 rem:"The name without the directory name"] } ] } ] $com:[print show:y f:IopPrint rem:"Prints a string." args:{ $var:[s t:var unnamed:y] $var:[f t:object class:file] $var:[mode t:int enum:{ $val:[normal n:0] $val:[raw n:1] } ] } ] $com:[nprint f:IopNPrint rem:"Prints a string." args:{ $var:[s t:strv unnamed:y] } ] $com:[po f:IopPrintOpen rem:"" args:{ $var:[width t:int] $var:[min t:int] $var:[ident t:int] } ] $com:[pc f:IopPrintClose rem:""] $com:[ps f:IopPrintString rem:"Prints a string to output stream." args:{ $var:[s t:var unnamed:y] } ] $com:[pf f:IopPrintFormat rem:"Prints a string to output stream." args:{ $var:[f unnamed:y] } ] $com:[It show:y f:IopInToken return:strv args:{ $var:[n t:int unnamed:y] } ] $com:[itc f:IopInTokenCode return:strv] $com:[Itc show:y f:IopInTokenCode return:strv] $com:[ct f:IopCurrToken return:strv] $com:[Ct show:y f:IopCurrToken return:strv] $com:[Key show:y f:IopKey return:strv args:{ $var:[val t:var unnamed:y] } ] $com:[fip f:IopFip return:int args:{ $var:[switch t:int unnamed:y] } ] $com:[Fip show:y f:IopFip return:int args:{ $var:[switch t:int unnamed:y] } ] $com:[skip f:IopSetSkip rem: |Controls skipping of white space during parsing which is |active by default. args:{ $var:[state t:int unnamed:y rem: |0: turns skipping white space off
    |1: turns it on again ] $var:[s t:strv] } ] $com:[Skip show:y f:IopSetSkip rem: |Controls skipping of white space during parsing which is |active by default. args:{ $var:[state t:int unnamed:y rem: |0: turns skipping white space off
    |1: turns it on again ] $var:[s t:strv] } ] $com:[Trim show:y f:IopStrTrim return:strv rem:"Cuts leading or trailing white space from the string." args:{ $var:[s t:strv unnamed:y] $var:[skip t:strv rem:|String containing characters to be removed from ends. ] } ] $com:[1 show:y f:IopSubMatch return:strv args:{$var:[n defInt:1 t:int]} rem: |Returns the first submatch of the most recent regular expression |matching. The submatch is indicated by parentheses within the |regular expression and the opening parenthesis is used for counting. |\$2, \$3 until \$9 will return the submatches with the respective |number. \$0 returns the entire match. ] $com:[2 f:IopSubMatch return:strv args:{$var:[n defInt:2 t:int]}] $com:[3 f:IopSubMatch return:strv args:{$var:[n defInt:3 t:int]}] $com:[4 f:IopSubMatch return:strv args:{$var:[n defInt:4 t:int]}] $com:[5 f:IopSubMatch return:strv args:{$var:[n defInt:5 t:int]}] $com:[6 f:IopSubMatch return:strv args:{$var:[n defInt:6 t:int]}] $com:[7 f:IopSubMatch return:strv args:{$var:[n defInt:7 t:int]}] $com:[8 f:IopSubMatch return:strv args:{$var:[n defInt:8 t:int]}] $com:[9 f:IopSubMatch return:strv args:{$var:[n defInt:9 t:int]}] $com:[SetFunctions f:IopSetFunctions args:{ $var:[name unnamed:y] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # implementation of the srs query language # $com:[SetResult f:QuerySaveResult args:{ $var:[set t:object class:set unnamed:y] $var:[q t:strv] } ] $com:[DbGroup f:QueryDBGroup return:object returnClass:dbGroup args:{ $var:[init] $var:[db t:string] $var:[group t:object class:dbGroup unnamed:y] } ] $com:[SetRetrRange f:QueryRangeSearch return:object returnClass:set args:{ $var:[index required:y] $var:[group t:object class:dbGroup unnamed:y] $var:[l t:string] $var:[h t:string] $var:[le t:int] $var:[re t:int] } ] $com:[SetRetrStr f:QueryStrSearch return:object returnClass:set args:{ $var:[s] $var:[index required:y] $var:[group t:object class:dbGroup unnamed:y] } ] $com:[SetLogOp f:QueryLogOp return:object returnClass:set args:{ $var:[op unnamed:y] $var:[s1 t:object class:set] $var:[s2 t:object class:set] } ] $com:[SetLinkOp f:QueryLinkOp return:object returnClass:set args:{ $var:[op unnamed:y] $var:[s1 t:object class:set] $var:[s2 t:object class:set] } ] $com:[SetAssign f:QuerySetAssign return:object returnClass:set args:{ $var:[name unnamed:y t:strv] $var:[s t:object class:set] } ] $com:[SetGet f:QuerySetGet return:object returnClass:set args:{ $var:[name unnamed:y] $var:[fileName] } ] $com:[MakeWild f:QueryOpMakeWild return:strv args:{ $var:[s t:strv unnamed:y] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $com:[GCGwordsearch f:GCGWordsearch args:{ $var:[infile1 rem:"Name of input file with the search probe."] $var:[infile2 rem:"Name of input file with the data bank."] } ] $com:[setFormat f:EntryIopSetFieldFormat args:{ $var:[field t:strv unnamed:y ] $var:[set t:strv] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # sequence manipulation # $com:[seqNew f:SeqIopNew return:object returnClass:sequence args:{ $var:[name t:strv unnamed:y ] $var:[list t:object class:sequence] } ] $com:[seqApp f:SeqIopApp return:object returnClass:sequence args:{ $var:[seq unnamed:y t:object class:sequence] $var:[s t:strv] } ] $com:[seqMake f:SeqIopMake return:object returnClass:sequence args:{ $var:[seq unnamed:y t:object class:sequence] } ] $com:[seqPrint f:SeqIopPrint args:{ $var:[seq unnamed:y t:object class:sequence] $var:[name] $var:[format t:int enum:{ $val:[gcg n:1] $val:[msf n:2] $val:[pir n:3] $val:[plain n:4] $val:[fasta n:5] $val:[embl n:6] $val:[swiss n:7] $val:[clustal n:8] } ] $var:[width t:int defInt:60] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $com:[calc f:IopCalc return:int args:{ $var:[op unnamed:y] $var:[l t:int] $var:[r t:int] } ] $com:[strlen f:IopStrlen return:int args:{ $var:[s unnamed:y] } ] $com:[Strlen show:y f:IopStrlen return:int args:{ $var:[s unnamed:y] } ] $com:[HtmlSpace f:IopHtmlSpace return:string args:{ $var:[thirds t:int unnamed:y] $var:[s t:int] $var:[l t:int] } ] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # binary operators # #$com:['+' f:IopAdd return:int args:{$var:[t:int] $var:[t:int]}] #$com:['+' f:IopPlusReal return:real args:{$var:[t:real] $var:[t:real]}] #$com:['+' f:IopPlusStr return:string args:{$var:l $var:r}] #$com:['+' f:IopPlusVar return:string args:{$var:l $var:r}] $com:['=' f:IopAss return:var args:{$var:[l t:var] $var:[r t:var]}] $com:['+' f:IopAdd return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['<' f:IopLT return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['>' f:IopGT return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['==' f:IopEq return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['*' f:IopMul return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['/' f:IopDivide return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['!=' f:IopNEq return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['-' f:IopSubt return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['+=' f:IopAddAss return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['&&' f:IopLogAnd return:int args:{$var:[l t:var] $var:[r t:var]}] $com:['||' f:IopLogOr return:int args:{$var:[l t:var] $var:[r t:var]}] #$convert:[int to:string cost:] #$convert:[int to:strv cost:] #$convert:[int to:strv] $com:[debug show:y f:IopSetDebug args:{ $var:[state t:int unnamed:y defInt:0] } ] # for the 'templ' module $com:[labelAdd f:TemplIcaAddLabel args:{ $var:[name t:strv unnamed:y] $var:[fip t:int] } ] $com:["" ] $object:[function declname:"X" status:system attrs:{ $attribute:[name type:protofunction declname:"fnctnam" max:30 valtype:text] $attribute:[args type:string declname:"args" max:132 valtype:text required:y] $attribute:[module type:string declname:"module" max:30] } ] file:"SRSICA:icacom.ic" $def:[infile:"SRSICA:srswin.sdl" outfile:"SRSSOU:builtin.h" section_name:"builtin" section_size:2000 ] # # $RCSfile: classes.i,v $ # $Revision: 1.3 $ # $Date: 1996/07/30 10:49:02 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # O_VALUE:$object:[name:value typname:ODDoVAL ppname:SDL declname:defval attrs:{ $attribute:[name:name declname:nam type:string valtype:name unnamed:y] $attribute:[name:val declname:val type:uint valtype:{num constant}] } ] O_ATTRTYPE:$object:[name:attrtype typname:ODDoATYP ppname:SDL declname:defatyp attrs:{ $attribute:[name:make type:function declname:make valtype:constant defaultstr:"(struct SDLoOBJ *, struct SDLoATTR *, unsigned int *)"] $attribute:[name:insert type:function declname:insert defaultstr:"(void *, void *, void *, void ***, char *, unsigned int,int)" valtype:constant] $attribute:[name:calcsize type:function declname:size valtype:constant defaultstr:"(struct SDLoOBJ *, struct SDLoATTR *)"] $attribute:[name:write type:function declname:write defaultstr:"(void)" valtype:constant] $attribute:[name:declare type:function declname:declare defaultstr:"(FILE *, struct SDLoATTR *, char *, char *)" valtype:constant] $attribute:[name:check type:function declname:check defaultstr:"(struct SDLoATTR *, int, char *)" valtype:constant] $attribute:[name:gentype type:function declname:gentype defaultstr:"(struct SDLoOBJ *, struct SDLoATTR *)" valtype:constant] $attribute:[name:save_address type:uchar declname:save_f defaultval:0 enum:{ $value:[name:yes val:1] $Value:[name:no val:0] } ] $attribute:[name:typname type:string declname:tnam max:20] } ] O_ATTR:$object:[name:attribute typname:SDLoATTR ppname:SDL declname:defpar CHILD:{@O_VALUE @O_ATTR} NCHILDS:2 attrs:{ $attribute:[name:rem declname:rem type:string valtype:{name text} min:0 max:512] $attribute:[declname:class type:object defaultval:@O_OBJECT] # pointer to list of possible values $attribute:[name:enum declname:val type:child defaultval:@O_VALUE] # number of values in list $attribute:[declname:val_n type:nr_of_childs defaultval:@O_VALUE] $attribute:[name:name declname:nam type:string min:0 max:$SDLxXNAM valtype:{name text} unnamed:y] $attribute:[name:typname declname:tnam type:string min:0 max:$SDLxXNAM valtype:{name text}] # switch used for alternative SDLxUSER type name $attribute:[name:switchname declname:sw_nm type:string valtype:{name text} min:0 max:$SDLxXNAM] # alternative SDLxUSER type name $attribute:[name:alttypname declname:alt_nm type:string valtype:{name text} min:0 max:$SDLxXNAM] # declaration name in C interface $attribute:[name:declname declname:dnam type:string min:0 max:$SDLxXNAM valtype:{name text}] $attribute:[name:unnamed declname:unnamed type:int min:0 defaultval:0 enum:{ $value:[name:y val:1] $value:[name:n val:0] } ] $attribute:[name:type declname:typ type:uchar required:y valtype:name enum:{ $value:[name:int val:@AT_INT] $value:[name:uint val:@AT_UINT] $value:[name:uchar val:@AT_UCHAR] $value:[name:string val:@AT_STRING] $value:[name:protofunction val:@AT_PROTOFNCT] $value:[name:function val:@AT_FNCT] $value:[name:child val:@AT_CHILD] $value:[name:nr_of_childs val:@AT_CHILD_N] $value:[name:object val:@AT_OBJECT] $value:[name:clone val:@AT_CLONE] $value:[name:defer val:@AT_DEFER] $value:[name:inherit val:@AT_INHERIT] $value:[name:user val:@AT_USER] $value:[name:float val:@AT_FLOAT] $value:[name:allobjects val:@AT_ALLOBJ] $value:[name:nr_of_objects val:@AT_ALLOBJ_N] $value:[name:generic val:@AT_GENERIC] $value:[name:generic_typ val:@AT_GENERIC_TYP] $value:[name:generic_obj val:@AT_GENERIC_OBJ] $value:[name:overload val:@AT_OVERLOAD] $value:[name:store val:@AT_STORE] $value:[name:bnf val:@AT_EBNF] } ] # type of value attribute may receive $attribute:[name:valtype declname:ptyp type:uchar defaultval:0 repeat:4 valtype:name enum:{ $value:[name:num val:$SDLxPNUM] $value:[name:name val:$SDLxPNAM] $value:[name:text val:$SDLxPTXT] $value:[name:constant val:$SDLxPCNST] } ] # array size if multivalued attribute $attribute:[name:repeat declname:arrsz type:int min:1 max:10000 defaultval:1 valtype:{num constant}] $attribute:[name:min declname:min type:int min:-1000000000 max:1000000000 defaultval:-1000000000 valtype:{num constant}] $attribute:[name:max declname:max type:int min:0 max:1000000000 valtype:{num constant} defaultval:1000000000] $attribute:[declname:off type:int] $attribute:[name:required declname:req type:uchar valtype:name defaultval:0 enum:{ $value:[name:y val:$TRUE] $value:[name:n val:$FALSE] } ] $attribute:[name:status declname:status type:uchar valtype:name defaultval:0 repeat:2 enum:{ $value:[name:obsolete val:1] $value:[name:system val:2] $value:[name:api val:3] } ] $attribute:[declname:isrd type:uchar min:0 max:0 required:n] $attribute:[name:defaultval declname:dfltv type:int valtype:{num constant} min:-1000000000 max:1000000000 defaultval:0] $attribute:[name:defaultstr declname:dflts type:string valtype:{name constant text} min:0 max:$SDLxXLN defaultstr:""] $attribute:[name:defaultvalf declname:dfltvf type:float valtype:num min:-1000000000 max:1000000000 defaultvalf:0] $attribute:[declname:scnt type:int] # some attribute types need object-class ID's $attribute:[name:objectclass declname:obj type:object defaultval:@O_OBJECT valtype:constant] $attribute:[declname:hasObjsN type:int] } ] O_OBJECT:$object:[name:object typname:SDLoOBJ ppname:SDL declname:defstrct child:@O_ATTR nchilds:1 attrs:{ #used in SDL $attribute:[name:name declname:nam type:string valtype:{name text} min:0 max:$SDLxXNAM unnamed:y] $attribute:[name:rem declname:rem type:string valtype:{name text} min:0 max:512] # `typedef' name to get access through C interface $attribute:[name:typname declname:tnam type:string valtype:{name text} min:0 max:$SDLxXNAM] #used for #define's - preprocessor name $attribute:[name:ppname declname:pp_nm type:string valtype:{name text} min:0 max:$SDLxXNAM] $attribute:[name:declname declname:dnam type:string min:0 max:$SDLxXNAM valtype:{name text}] $attribute:[name:type declname:typ type:uchar valtype:{num constant} min:0 max:12 defaultval:0] $attribute:[name:status declname:status type:uchar valtype:name defaultval:0 repeat:2 enum:{ $value:[name:obsolete val:1] $value:[name:system val:2] $value:[name:api val:3] } ] $attribute:[declname:siz type:int] $attribute:[declname:s type:string] $attribute:[declname:ns type:int min:0 max:10000] $attribute:[declname:uobj_coff type:string] $attribute:[declname:gbl_n type:int] $attribute:[declname:loc_n type:int] $attribute:[name:nchilds declname:nss type:uchar valtype:num max:$SDLxXSS] $attribute:[name:child declname:ss type:uchar repeat:$SDLxXSS valtype:constant min:0 max:255 defaultval:0] $attribute:[declname:np type:nr_of_childs min:1 max:256 defaultval:@O_ATTR] $attribute:[name:attrs declname:p typname:SDLoATTR type:child defaultval:@O_ATTR] #Inheritance #Pointer(s) to object class descriptor(s) $attribute:[declname:gtyp_n type:int defaultval:0] #generic typedef name that object typedef using generic type receives $attribute:[declname:gtypdef_nm type:string repeat:$SDLxXSS repeat:$SDLxXSS] #generic type $attribute:[declname:gtyp_nm type:string repeat:$SDLxXSS repeat:$SDLxXSS] #typdef name for the object with functions and data-header $attribute:[name:orgtypname declname:orgtyp_nm type:string valtype:{text name} max:40] } ] O_SDL:$object:[name:def typname:SDLo declname:def ppname:SDL child:@O_OBJECT nchilds:1 attrs:{ $attribute:[name:infile declname:ifnam type:string min:1 max:$FILxXNAM required:y valtype:{constant text}] $attribute:[name:outfile declname:ofnam type:string min:1 max:$FILxXNAM valtype:{constant text}] #name of map-section $attribute:[name:section_name declname:sec_nm type:string min:0 max:50 valtype:{name text}] #section size in blocks $attribute:[name:section_size declname:sec_z type:int min:1 max:100000 valtype:num defaultval:1000] # objects $attribute:[declname:oc_n type:nr_of_objects defaultval:@O_OBJECT] $attribute:[declname:oc type:allobjects defaultval:@O_OBJECT] # attribute types $attribute:[declname:at_n type:nr_of_objects defaultval:@O_ATTRTYPE] $attribute:[declname:at type:allobjects defaultval:@O_ATTRTYPE] $attribute:[declname:error type:uchar defaultval:0] $attribute:[declname:action type:uchar defaultval:0] $attribute:[declname:pass_n type:uchar defaultval:0] $attribute:[declname:keepst_f type:uchar defaultval:0] $attribute:[declname:section_f type:uchar defaultval:0] } ] programm = [ '$' ] command { ';' [ '$' ] [command] } ; command = ica_instruct | user_instruct | check | equation | usercom ; ica_instruct = 'rd' ':' ( name | variable ) [ 'c' ':' value ] [ 't' ':' name [ 'l' ':' name ] ] | 'ct' [':' ( name |variable )] | 'et' [':' ( name |variable )] | 'wrt' { argument } | 'app' { argument } | 'rep' { argument } | 'len' ':' integer | 'mov' ':' integer | 'not' | 'noskip' | 'nocase' | 'uniq' ; argument = 'c' ':' value | 's' ':' ( format | string | value ) ; check = 'if' '(' variable '==' (integer | variable | name) ')' ; equation = variable ('=' | ':=' ) expression ; expression = operand { op operand } ; operand = variable | float | integer | l_bracket expression r_bracket | command | string ; op = '+' | '-' | '*' | '/' ; identifier = float | integer | variable | name ; value = integer | variable | name ; format = l_brace (string|variable) { variable } r_brace ; arglist = name { ',' identifier } ; string = '"' /[^"]*/ '"' ; integer = /[0-9]+/ ; float = /[0-9]+\.[0-9]/ ; name = /[A-Za-z][0-9A-Za-z_-]*/ ; oneword = /[^ \t]+/ ; variable = '$$' /[0-9A-Za-z]*/ ; l_bracket = '(' ; r_bracket = ')' ; l_brace = '{' ; r_brace = '}' ; user_instruct= 'push1' ':' userval | 'push2' ':' userval | 'push3' ':' userval | 'push4' ':' userval | 'push5' ':' userval | 'push' ':' userval | 'pop1' | 'pop2' | 'pop3' | 'pop4' | 'pop5' | 'pop' | 'test' | 'com' ':' value 'f' ':' value | 'arg' ':' name { /(t|unnamed|required)/ ':' name } | 'return' ':' name { /(t|unnamed|required)/ ':' name } {/(a|b|c|d)/ ':' /[0-9]+/ } | 'p' ':' ( string | oneword ) | 'trigger' ':' name | 'setTask' ':' name ; userval = l_bracket command r_bracket | /[0-9a-zA-Z-_]+/ | variable | string; usercom = /[a-zA-Z]+[a-zA-Z0-9_-]+/ [ ':' userval] { /[a-zA-Z0-9_-]+/ ':' userval} .. # 0: separator (';') # 1-59: operators, first digit: 1: build time, 2:preparse, 4:postparse # second is priority # 100-109,112,113 operands # 110: argName # 111: end of the argument list # 114: end of user argument list # # $RCSfile: ica2c.it,v $ # $Revision: 1.6 $ # $Date: 1996/08/12 23:00:35 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ############################################################################### # # for conversion of the icarus commands to C functions # $prog={ head: |#include |#include "srs.h" | |#include "odd.h" |#define _INITOBJS |#define _CONSTANTS |#define _SDL |#define _FUNCTION |#include "oddclass.h" | |static VARoSCOPE *scope = NULL; | |main () |{ | SrsEnv (); | LibOpen ("srs5"); | | IcarusFunc1 (); |} | |INT4 %s () |{ func:{ end: |} } body:{ head: | |INT4 %s () |{ tail: |} } stmnt:{ head: | \ tail: |; } binop:{ '=': | = \ } call:{ name: |%s (0\ argint: |%d\ argstr: |"%s"\ argstrv:|StrCpyS ("%s")\ argval: |%s\ argvar: |%s\ # argvar: |VarGet (&scope, "%s")\ argsep: |, \ tail: |)\ } var: |%s # |VarGet (&scope, "%s")\ convert:{ int:{ # var: |VarSetInt (VarTemp (), \ string: |VarSetInt (VarTemp (), \ } string:{ var: |VarSetStr (VarTemp (), \ strv: |StrCpyS (\ } strv:{ string: |_Str (\" var: |VarSetStrV (VarTemp (), \ } object:{ var: |VarSetObject (NULL, VarTemp (), (void*)\ } var:{ object: |VarGetObject (NULL, (void*)\ strv: |VarGetStrV (\ } alias:{ object: |VarGetObject (NULL, (void*)\ # int: |VarGetInt (\ } tail: |)\ } staticStrv: |static struct { int u; int l; int d; char arr[8]} str1={1,7,8,"\$ct := "}; } ############################################################################### # # for conversion of the syntax tree to C structures # $bnf2c = { str: "%s" prologue: |#include |#include |#include |#include |#include |#include | |#define DECLARE_ONLY |#define DEFIGNORE " \\n\\t" |#define DEFCOMMENT "^#[^\\n]*\\n" | |#include "srs.h" |#include "regexp.h" | |static VARoSCOPE *scope = NULL; | |extern ICAoJOB *Job; |extern ICAoSYNTAX *Syntax; | |INT4 BnfParseProduction(BNFoPRODUCTION *); |INT4 BnfParseProdLoop(BNFoPRODUCTION *); |INT4 BnfParseRegExp(BNFoREGEXP *); |INT4 BnfParseLiteral(BNFoLITERAL *); |INT4 BnfParseCommand(BNFoNODE *); |INT4 BnfParseLineStart(BNFoNODE *); |INT4 BnfParseInputEnd(BNFoNODE *); |INT4 BnfParseTerm(BNFoTERM *); |INT4 BnfParseChoice(BNFoCHOICE *); |INT4 BnfParseProdName(BNFoPRODNAME *); |void BnfPruneTree(BNFoNODE *); | |VARo *IopPop_(INT4, INT4); |VARo *IopBody_ (Int4 runTime); | |STRv IopInterpStr_(VARo *var, STRv str, ...); |STRv IopInterpStr2(VARo *var, STRv str, ...); |STRv IopSubMatch(INT4, INT4); |STRv IopCurrToken(); | |/* Declaration of C variables used by some translated functions */ |VARo *a, *b, *c, *d, *e, *u, *i; |Int4 opt; | epilogue: |ICAoSYNTAX *IcaInitSyntax(ICAoSYNTAX *syntax) |{ | static ICAoSYNTAX syntaxStatic; | static ICAoJOB job; | VARo *prodList; | INT4 i, | j; | | if (!syntax) | syntax = &syntaxStatic; | | | Job = &job; | Job->isBuildTime = 1; | | j = 0; | for(i=0; icurrNode = (BNFoNODE *) &_prod[i]; | _BnfExecInit (&_prod[i]); | } | | for(i=0; icurrNode = (BNFoNODE *) &_prodN[i]; | _BnfExecInit (&_prodN[i]); | } | |#ifdef LITLNUM | | for(i=0; icurrNode = (BNFoNODE *) &_lit[i]; | _BnfExecInit (&_lit[i]); | } | |#endif |#ifdef REGNUM | | for(i=0; icurrNode = (BNFoNODE *) &_reg[i]; | _BnfExecInit (&_reg[i]); | } | |#endif |#ifdef COMMNUM | | for(i=0; icurrNode = (BNFoNODE *) &_comm[i]; | _BnfExecInit (&_comm[i]); | } | |#endif |#ifdef STRTNUM | | for(i=0; icurrNode = (BNFoNODE *) &_strt[i]; | _BnfExecInit (&_strt[i]); | } | |#endif |#ifdef EOINNUM | | for(i=0; icurrNode = (BNFoNODE *) &_eoin[i]; | _BnfExecInit (&_eoin[i]); | } | |#endif | | VarGet (&job.scope, ""); | | syntax->prod = prodList; | syntax->ign = DEFIGNORE; | if (syntax == &syntaxStatic) { | syntax->cmnt = DEFCOMMENT; | syntax->ignAlt = ""; | } | if ((syntax->cmntRe = RegComp (syntax->cmnt)) == NULL) | _ErrExit2 (e__regerror, syntax->cmntRe); | | Syntax = syntax; | for(i=0; i = ln { ln } ; ln = /[^$]+/ ; prog = * stmnt { stmnt } * ; body = * ('{' { stmnt } '}' | stmnt ) * ; stmnt = (if | for | while | init | pre | file | stassoc | expr); stassoc = key ident ; # # expression # expr = term1 {logop term1 makeop}; term1 = term2 {(compop|assop) term2 }; term2 = term3 {op1 term3 }; term3 = term4 {op2 term4 makeop}; term4 = '(' expr ')' | [unopleft] value [unopright]; makeop = * ; nullopnd = * ; # # operators # logop = '&&' | '||' ; assop = '=+' | '=' | '-=' | '*=' | '/=' ; compop = '<=' | '=<' | '>=' | '=>' | '<' | '>' | '==' | '!=' ; op1 = '+' | '-' | '%' ; op2 = '*' | '/' ; unopleft = '++' | '--' | '-' | '+' ; unopright = '++' | '--' ; # # variables values and lists # list = '{' {assoc|value} '}' ; assoc = key (value |'~' production '~') * ; key = /([a-zA-Z0-9_]+):/; value = int | string | ident | list | namestr | reference; # # flow control # file = 'file' ':' string * ; pre = 'pre' body ; init = 'init' body ; for = 'for'':''{' (expr|nullopnd) (expr|nullopnd) (expr|nullopnd) '}' body ; while = 'while'':' cond body ; if = 'if'':' cond body {'elif'':' cond body} ['else' body] *; cond = '(' expr ')' | '{' expr '}' | '[' expr ']' | expr; case = 'case'ident '{' { '?' value ':' body } '}' ; #/(else|for|while|if|case|\?)[^a-zA-Z0-9]/ ic = 'installClasses'; print = 'print' args * ; # # variable name or function call # ident = '$$' path; path = name { '.'(name | '(' ident ')' | string | ident )| /\\[([0-9]+)\\]/ | '[' expr ']' } [ args ]; args = ':' ('[' [named | unnamed] {named} ']' | unnamed ); unnamed = argvalue | ':::::' ; named = /([a-zA-Z_0-9]+) *:/ argvalue ; argvalue = int | ident | string | strname | list | '(' expr ')' | reference; reference = '@' ('?'<$opt=1> | *<$opt=0>) name ; name = /[a-zA-Z0-9_]+/; real = /[0-9]*\\.[0-9]*/; int = /-?[0-9]+/; namestr = /[a-zA-Z0-9_]+/ ; string = '"' mystring '"' | /'/ /[^']*/ /'/; mystring = * {/((\\\\.)+|[^"\\$$]+)/ | '$$$$' | strident }; strident = '$$(' path | '$$' path; strname = /[a-zA-Z_][a-zA-Z0-9_]*/ ; #" # # commands for creating the syntax tree # # # the 'Backus-Naur format' derived syntax description' # production = * [nodeProg] bnfExpr ; bnfExpr = * term { '|' term } * ; term = * factor { factor } * ; factor = (regexp | literal | command | prodName | laProdName) [occur] [nodeProg] | '(' bnfExpr ')' [occur]; regexp = '/' sqString '/'; sqString = {/((\\\\.)+|[^\/\\]+)/}; literal = /'/ /[^']*/ /'/ ; command = 'x:' ; occur = '?' | '*' | '+' ; nodeProg = '{' * stmnt{stmnt} * '}' ; prodName = /[0-9a-zA-Z_]+/ ; laProdName = '_' /[a-zA-Z_]+/ ; end = 'end'. prog: ~ {$out pre{$push:$opnd:[ga t:mark]} $prog} stmnt (stmnt)* ~ stmnt: ~ {$out} for | init | pre | doFile | assoc | expr ~ body: ~ {pre{$push:$opnd:[t:mark]} $push:$body:"IopBody"} ('{' (stmnt)* '}' | stmnt) ~ # expression expr: ~ term1 (logop term1 makeop)* ~ term1: ~ term2 ((compop | assop) term2 makeop)* ~ term2: ~ term3 (op1 term3 makeop)* ~ term3: ~ term4 (op2 term4 makeop)* ~ term4: ~ '(' expr ')' | (unopleft)? value (unopright)? ~ makeop: ~ x:{$push:$op2:[$pop1 b:$pop a:$pop]} ~ nullopnd: ~ x:{$push:$opnd:[t:null]} ~ # operators logop: ~ '&&' {$push1:IcaOpAnd} | '||' {$push1:IcaOpOr} ~ assop: ~ '=+' {$push1:IopAddAss} | '=' {$push1:IopAss} | '-=' {$push1:IcaOpAssSub} | '*=' {$push1:IcaOpAssMul} | '/=' {$push1:IcaOpAssDiv} ~ compop: ~ '<=' {$push1:IcaOpLE} | '=<' {$push1:IcaOpLE} | '>=' {$push1:IcaOpGE} | '=>' {$push1:IcaOpGE} | '<' {$push1:IopLT} | '>' {$push1:IcaOpGT} | '==' {$push1:IcaOpGE} ~ op1: ~ '+' {$push1:IopAdd} | '-' {$push1:IopSubt} | '%' {$push1:IcaOpMod} ~ op2: ~ '*' {$push1:IopMul} | '/' {$push1:IcaOpDev} ~ unopleft: ~ '++' {$push1:IcaOpIncr} | '--' {$push1:IcaOpDecr} | '-' {$push1:IcaOpNeg} | '+' {$push1:IcaOpPos} ~ unopright: ~ '++' {$push1:IcaOpIncr} | '--' {$push1:IcaOpDecr} ~ # variables values and lists list: ~ '{' {$push:$opnd:[t:mark]} (assoc | value) '}' {$push:$list} ~ assoc: ~ {$push:$assoc:[val:$pop key:$pop5]} key {$push5:$opnd:["$1" t:string]} (value|'~' production '~') ~ key: ~ /([a-zA-Z0-9_]+):/ ~ value: ~ int {$push:$opnd:["$ct" t:int]} | string | ident | list | namestr | reference ~ # flow control doFile: ~ {$push:$file:$pop} 'file' ':' string ~ pre: ~ {$push:$Pre:$pop} 'pre' body ~ init: ~ {$push:$init:$pop} 'init' body ~ for: ~ 'for'':''{' (expr | nullopnd) (expr | nullopnd) (expr|nullopnd) '}' body {$push:$for:[IopFor b:$pop u:$pop c:$pop i:$pop]} ~ # variable name or function call objId: ~ /_[a-zA-Z0-9_]+/ {$newId:"$ct"} ~ ident: ~ '$' path ~ #' path: ~ name {$push:$opnd:["$ct" t:ident]} ('.'(name {$push:$select:[$pop key:"$ct"]} | '(' ident ')' {$push:$select:[keyvar:$pop var:$pop]} | string {$push:$select:[keyvar:$pop var:$pop]} | ident {$push:$select:[keyvar:$pop var:$pop]}) | /\\[([0-9]+)\\]/ {$push:$select:[$pop n:"$1"]})* (args {$push:$func})? ~ args: ~ ':' {$push:$opnd:[t:mark]} ('[' ((named | unnamed) (named)*)* ']' | unnamed) ~ unnamed: ~ argvalue {$push:$Makearg:[$pop name:$opnd:[":::::" t:str]]} ~ named: ~ /([a-zA-Z_0-9]+) *:/ {$push:$opnd:["$1" t:str]} argvalue {$push:$Makearg:[$pop name:$pop]} ~ argvalue: ~ int {$push:$opnd:["$ct" t:int]} | ident | string | strname | list | '(' expr ')' | reference ~ reference: ~ '@' ('?'{$opt=1} | x:{$opt=0}) name {$push:$oddRef:["$ct"]} ~ name: ~ /[a-zA-Z0-9_]+/ ~ real: ~ /[0-9]*\\.[0-9]*/ ~ int: ~ /-?[0-9]+/ ~ namestr: ~ /[a-zA-Z0-9_]+/ {$push:$opnd:["$ct" t:str]} ~ string: ~ '"' mystring {$noskip $push:$opnd:["$ct" t:istr]} '"' | /'/ /[^']*/ {$noskip $push:$opnd:["$ct" t:str]} /'/ ~ #' mystring: ~ {$noskip pre{$push:$opnd:[t:mark]}} (/((\\\\.)+|[^"\\$$]+)/ {$noskip} | '$$' | strident)* ~ #" strident: ~ '$(' path | '$' path ~ #' strname: ~ /[a-zA-Z_][a-zA-Z0-9_]*/ {$push:$opnd:["$ct" t:str]} ~ # the 'Backus-Naur format' derived syntax description production: ~ {pre{$push3:$prod}} (nodeProg)? bnfExpr {$push:$endProd:[node:$pop3 prod:$pop3]} ~ bnfExpr: ~ {pre{$push3:$nullNode} $push3:$expr} term ('|' term)* ~ term: ~ {pre{$push3:$nullNode} $push3:$term} factor (factor)* ~ factor: ~ (regexp | literal | command | prodName | laProdName) (nodeProg)? | '(' bnfExpr ')' (optional | repeat)? ~ regexp: ~ '/' /[^\|]*/ {$noskip $push3:$regexp:"$ct"} '/' ~ literal: ~ /'/ /[^']*/ {$noskip $push3:$literal:"$ct"} /'/ ~ #' command: ~ 'x:' {$push3:$doCom} ~ optional: ~ '?' {$push3:$makeOpt:[$pop3 t:once]} ~ repeat: ~ x:{$push3:$makeOpt:[$pop3 t:multi]} ~ nodeProg: ~ {$push3:$nodeProg:[$pop3 prog:$pop]} '{' {$push:$opnd:[t:mark]} stmnt (stmnt)* x:{$push:$body:IopBody} '}' ~ prodName: ~ /[a-zA-Z_]+/ {$push3:$ProdName:"$ct"} ~ laProdName: ~ '_' /[a-zA-Z_]+/ {$push3:$ProdName:["$ct" lookahead:1]} ~ } # $RCSfile: makewild.i,v $ # $Revision: 1.2 $ # $Date: 1996/07/14 16:21:51 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $rules={ query: ~ {init{$SetFunctions:QuerySetFunctions}} factor (op factor)* ~ op: ~ /[|&<>!=]/ ~ factor: ~ set | retrieve | '(' query ')' ~ set: ~ /[a-zA-Z0-9_]+/ ~ retrieve: ~ '[' libs '-' name (':' wordExpr | /#[^]]+/) ']' ~ wordExpr: ~ wordTerm (logop wordTerm)* ~ wordTerm: ~ '(' wordExpr ')' | word ~ logop: ~ /[!|&]/ ~ name: ~ /[a-zA-Z0-9_]+/ ~ word: ~ '"' /([^"]+|\\\\.)*/ {if:$parInt:makeWild $rep:$MakeWild:$ct} '"' | #" '\'' /([^']+|\\\\.)*/ {if:$parInt:makeWild $rep:$MakeWild:$ct} '\'' | /[^]|&!)]*[^]|&!) ]/ {if:$parInt:makeWild $rep:$MakeWild:$ct} ~ libs: ~ /([a-zA-Z0-9_]+) *=/? ('{' (name)* '}' | name) ~ } #$parInt:[makeWild set:1] #$parse:['(a&[a={pir embl}-def:1&"arg"])' prod:$rules start:expr skip:" "] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: man_capi.i,v $ # $Revision: 1.6 $ # $Date: 1996/08/12 11:21:43 $ # $Author: etzold $ # # Generates the HTML with the documentation of the functions in C language # modules # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $entry = { name:"" api:0 comment:"" input:{ {rem:""}{rem:""}{rem:""}{rem:""}{rem:""}{rem:""}{rem:""} {rem:""}{rem:""}{rem:""}{rem:""}{rem:""}{rem:""}{rem:""} } retCom:{"" "" "" "" "" "" "" "" "" ""} } $Xfiles={ templ } $files={ arglist bnf2c btree cursor dict entry futil hash ica2c icaarg icabnf icaop icaprog icarus icatask id ids idx index library link logicals lst message oldlistbuf par print query queryass regexp sdlget seq seqlib set sm srswww strv templ tm toklist unix_map variable view wgetz } $testfiles={ variable } $rules={ # the entire function header header: ~ { $Out pre{ $Skip:0 $inputN=1 $argN=1 $returnN=1 $implicitN=1 $entry.name='' $entry.fname='' $entry.api=0 } } (/.\\*\\*+(API|api).+[a-zA-Z0-9]+ +\\*+/ {$Not} ln)* (/[*\/]+(API|api)/ {$Wrt} ln {$App}(/[*\/]+/ appLn)* x:{$App:[s:'@@\n']} (/.*{ *\n/ {$Not} appLn)+ /[^{]*/ {$App} )? ~ # fields inside the function header fields: ~ {$Out $In:header} title comment input? implicit? return? proto ~ title: ~ /\/\\*\\*/ ('api' {$entry.api=1} | 'API' {$entry.api=2})? /\\** */ name {$entry.fname=$Ct} ln ~ comment: ~ {$entry.comment=$Ct} (/([ \t]+[A-Z]+ *:|@@)/{$Not} ln)+ ~ input: ~ /[ \t]+INPUT *:/ ln {$Wrt:input} (/([ \t]+[A-Z]+ *:|@@)/{$Not} appLn)* ~ implicit: ~ /[ \t]+IMPLICIT:/ ln {$Wrt:implicit} (/([ \t]+[A-Z]+ *:|@@)/{$Not} appLn)* ~ return: ~ /[ \t]+RETURNS? *:/ ln {$Wrt:return} ('@@'{$Not} appLn)* ~ proto: ~ ln /.*/ {$Wrt:proto} ~ # break lists l_input: ~ {$In:[fields c:input] $Out:input} l_item* ~ l_implicit:~ {$In:[fields c:implicit t:dod] $Out:implicit} l_item* ~ l_return: ~ { $In:[fields c:return] $Out:return} l_item* {$entry.retCom[$returnN] = $Ct $returnN=$returnN+1} ~ l_item: ~ /[ \t]+o[ \t]/ ln {$Wrt $s=$Ct} (/[ \t]+o[ \t]/ {$Not} appLn)* | /[ \t\n]+([^\n \t][^\n]+)\n/ {$Wrt:[s:$1] $s=$1} ~ i_inputRW: ~ { $In:[input] $Out:gaga pre{$arg=$entry.input[$inputN] $arg.write='read'} $arg.rem=$Ct $inputN=$inputN+1 } (/[^[]*/ ('[W]'{$arg.write='write' $Rep:''}| '[R]'{$arg.write='read' $Rep:''} | '[')? )+ ~ # break prototype into single arguments l_proto: ~ { $In:[fields c:proto] $Out:proto pre{$Skip:1} $Skip:0 } typeName {$entry.return = $Ct} name {$entry.name=$Ct} '(' (l_arg (',' l_arg)*)? ')' ~ l_arg: ~ { pre{$arg=$entry.input[$argN]} $argN=$argN+1 } typeName {$arg.type=$Ct} argName {$arg.name=$Ct} | '...' {$arg.type=$Ct $arg.name=' '} ~ # for replacing function names by hypertext links function: ~ {$Out pre{$Skip:1}} ('

    ' {$Not} ln {$print:[$Ct f:$outf]})* ('

    ' {$Wrt} appLn ('

    ' {$Not} appLn)*)? ~ h_function:~ {$In:function $Out} /[^\n]+A>([a-zA-Z0-9]+)[^\n]+\n/ { $print:[$Ct f:$outf] if:$example.($1).isOk { # $print:"... linking function $1 to examples\n" $print:['Used in:' f:$outf] foreach:[$ex in:$example.($1).link] $print:[$ex f:$outf] $print:['
    ' f:$outf] } } h_line+ {$print:[$Ct f:$outf]} ~ h_line: ~ ( /[A-Za-z0-9_]+/ { if:$funct.$Ct !="" $Rep: |$Ct\ } | /[^A-Za-z0-9_\n]+/ )* '\n'? ~ # others typeName: ~ /(static|struct|enum|unsigned|long)/? /[a-zA-Z0-9_]+/ /[ *]*/{$Noskip} ~ argName: ~ (/[][a-zA-Z0-9_*]+/ /[ *]*/{$Noskip} | '(*' /[^)]+\\)/ /\\([^)]*\\)/) ~ name: ~ /[a-zA-Z0-9_*]+/ ~ ln: ~ /[^\n]*\n/ ~ appLn: ~ /[^\n]*\n/ {$App} ~ } # # build the functions index and the function documentation page # $outf = $fileOpen:["SRSMAN:mtoc2_func.html" mode:w] $outt = $fileOpen:["SRSMAN:mtoc_func.html" mode:w] $print:[f:$outf s: | | |Module $SRS functions list | | | ] $print:[f:$outt s: | | |Module $SRS module list | | | |

    Modules in SRS

    |
      ] $print:|...parsing C files foreach:[$module in:$files] { $fil = $FileOpen:"SRSSOU:$module.c" $outm = $FileOpen:["SRSMAN:mff_$module.html" mode:w] $print:[f:$outt s: |
    • $module ] $print:[f:$outf s: |

      Module "$module"

      |
        ] $print:[f:$outm s: | | |Descriptions of module "$module" functions | | ] $job = $JobNew:[prod:$rules skip:" \n\t" file:$fil] while:$JobTokens:[$job name:fields] { $JobTokens:[$job name:gaga] $JobTokens:[$job name:return] $JobTokens:[$job name:proto] if:($entry.name!='' && $entry.api) { $nam = $entry.name $funct.$nam = $module # save for inserting hypertext links $print:[f:$outf s: |
      • ($entry.name) ] # print the function information $print:[f:$outm s: |

        $nam

        |($entry.comment)

        ] # print the function arguments $print:[f:$outm s: |

        |
    $Ct$Ct
    | | | | ] for:{$l=1 $l<$inputN $l=$l+1} { $print:[f:$outm s: | | | | | ] } if:$l==1 $print:[f:$outm s: | | ] # type of return value if:$entry.return=="void " $rem="
    nothing
    " else $rem=$entry.retCom[1] $print:[f:$outm s: | | | | | | |
    TypeNameR/WComment
    |Arguments
    ($entry.input[$l].type)($entry.input[$l].name)($entry.input[$l].write)($entry.input[$l].rem)
       none
    |Returns
    ($entry.return)  ($rem)
    |
] } $JobNext:$job } $FileClose:$fil $FileClose:$outm $print:[''f:$outf] } $FileClose:$outt # # read the programming manual insert hypertext links and examples # $progRules={ file: ~ {pre{$Skip:0}} (title {$print:[$Ct f:$mprog]} | include | line { $print:[$Ct f:$mprog]})+ ~ title: ~ /.*(name|NAME)="([a-zA-Z0-9_-]+)".*\n/ {$chapter=$2} ~ line: ~ ( /[^\na-zA-Z0-9_]+/ | /[a-zA-Z0-9_]+/ {if:$funct.$Ct !="" $Rep:|$Ct\ } )* '\n' ~ include: ~ /.*INCLUDE EXAMPLE:/ /[a-zA-Z0-9.]+/ { $print:[| |
\
                 f:$mprog] 
               $exName = $Ct
               $Parse:[prod:$exRules start:file 
                 fileName:"SRSDEMO:$Ct"]
               $print:['
' f:$mprog] } ~ } $exRules={ file: ~ {pre{$Skip:0}} line+ {$print:[$Ct f:$mprog]} ~ line: ~ ( /[^\na-zA-Z0-9_]+/ | /[a-zA-Z0-9_]+/ { $name = $Ct if:$funct.$Ct !="" { $Rep:|$Ct\ # $print:|found $name <-> $exName $example.($name).isOk = 1 $example.($name).link.$exName = | $exName\ } } )* '\n' ~ } $mprog = $fileOpen:["SRSMAN:m_prog.html" mode:w] $print:|...parsing the C API manual $Parse:[prod:$progRules start:file fileName:"SRSDOC:prog.html"] # # go over the function documentation page again and search for # known function names that will be promoted to hypertext links # $print:|...parsing the module descriptions in HTML foreach:[$module in:$files] { $inf = $FileOpen:["SRSMAN:mff_$module.html"] $outf = $FileOpen:["SRSMAN:mf_$module.html" mode:w] $job = $JobNew:[prod:$rules skip:" \n\t" file:$inf] while:$JobTokens:[$job name:h_function print:0] $JobNext:$job $FileClose:$inf $FileClose:$outf } $chapter={ {path:"SRSDOC:srswww.html" part:srswww} {path:"SRSDOC:tour.html" part:tour} {path:"SRSDOC:icarus.html" part:icarus} {path:"SRSDOC:install.html" part:install} {path:"SRSDOC:query.html" part:query} {path:"SRSMAN:class.html" part:class} {path:"SRSMAN:icafunc.html" part:icafunc} {path:"SRSMAN:usage.html" part:usage} } # get the list of all documented icarus functions $icaFunRules={ title: ~ (/.*<[Hh][1-4]>/ /<(A NAME|a name)="?([^>"]+)"?>/ {$name=$2} #" /.*(\\$[a-zA-Z0-9_]+)<\/[hH]/? {$fun.($1).flag=1 $fun.($1).file=$fileName $fun.($1).name=$name} | ln )+ ~ ln: ~ /[^\n]*\n/ ~ } $rules={ # extract titles and bodies field: ~ {$Out pre{$skip:0}} x:{$Wrt:dummy} ( (/[ \t\n]*<[Hh][1-6]>/ {$Not} ln {$App})+ (/[ \t\n]*<[Hh][1-6]>/ {$Wrt:title} (/.*<\/[Hh][1-6]>/ {$Not} ln {$App})* /.*<\/[Hh][1-6]>/ {$App} ln {$Wrt:text})? )+ ~ # inserting of links to index words text: ~ {$In:[field t:rep] $Out} word* ~ word: ~ // {$Rep:| } | /<[hH][1-4]>.*<\/[hH][1-4]>/ | /<(PRE|pre)>/ {$Rep:"

"}|
            /<\/(PRE|pre)>/{$Rep: "

"} | /\\$[a-zA-Z0-9_]+/ {if:$fun.($Ct).flag==1 $Rep: |$Ct\ } | /[^$<]+/ | /./ ~ # other stuff ln: ~ /[^\n]*\n?/~ } # make a list of all icarus functions and classes foreach:[$fileName in:{'icafunc' 'class'}] { $Parse:[fileName:"SRSMAN:$fileName.html" prod:$icaFunRules start:title ] } # process the chapters $job = $JobNew:[prod:$rules skip:" "] foreach:[$chap in:$chapter] { $ifil = $FileOpen:"($chap.path)" $ofil = $FileOpen:["SRSMAN:m_($chap.part).html" mode:w] $print:|...processing ($chap.path) $JobNext:[$job file:$ifil] while:$JobTokens:[$job name:field task:rep print:1 withCode:0 outFile:$ofil] $JobNext:$job $FileClose:$ofil $FileClose:$ifil } $chapter={ {path:"SRSMAN:m_srswww.html" part:srswww n:1} {path:"SRSMAN:m_install.html" part:install n:1} {path:"SRSMAN:m_query.html" part:query n:3} {path:"SRSMAN:m_usage.html" part:usage n:4} {path:"SRSMAN:m_icarus.html" part:icarus n:5} {path:"SRSMAN:m_icafunc.html" part:icafunc n:6} {path:"SRSMAN:m_tour.html" part:tour n:7} {path:"SRSMAN:m_prog.html" part:prog n:8} {path:"SRSMAN:m_class.html" part:class n:10} } $indexWords={ 'action' 'argument' 'associative list' 'class' 'data-field' 'element' 'expression' 'for statement' 'forced parsing' 'foreach statement' 'grammar' 'icarus' 'if statement' 'input' 'instance' 'interpretation' 'interpreter' 'language' 'lazy parsing' 'nonterminal' 'object class' 'output' 'perl' 'position' 'production' 'recursive' 'regular expression' 'scanner' 'strings' 'substitution' 'symbol' 'syntax' 'task' 'tcl' 'terminal' 'token table' 'token code' 'variable' 'while statement' } $rules={ # extract sections section: ~ {$Out pre{$Skip:0}} x:{$Wrt} (/[ \t\n]*<[Hh][1-2]>/ {$Not} ln {$App})* (/[ \t\n]*<[Hh][1-2]>/ {$Wrt} (/[ \t\n]*<[Hh][1-2]>/ {$Not} ln {$App})*)+ ~ # inserting of links to index words inxSect: ~ {$In:[section t:inx] pre{foreach:[$i in:$inx] $i.n=0}} index ~ index: ~ (/[a-zA-Z_][a-zA-Z0-9_-]+/ { if:$inx.($Ct).ok { $key=$inx.($Ct) if:$key.n < 1 { $key.n += 1 $locN += 1 $key.list += |$chapN\ $Rep:"$Ct" } } if:$concat && $inx."$prev $Ct".ok { $key=$inx."$prev $Ct" if:$key.n < 1 { $key.n += 1 $locN += 1 $key.list += |$chapN\ $Rep:"$Ct" } } $concat=0 $prev=$Ct } | /[ \n\t]+/ {$concat=1} | /[^a-zA-Z]+/ | /./)* ~ # other stuff ln: ~ /[^\n]*\n/ ~ } # initialize index word list foreach:[$iw in:$indexWords] { $inx.($iw).name = $iw $inx.($iw).ok = 1 $inx.($iw).list = {} } $job = $JobNew:[prod:$rules] foreach:[$chap in:$chapter] { $print:|...processing "($chap.path)" $fil = $FileOpen:"($chap.path)" $ofil = $FileOpen:["SRSMAN:mi_($chap.part).html" mode:w] $fileName="($chap.part).html" $chapN = $chap.n $locN = 0 $JobNext:[$job file:$fil] while:$JobTokens:[$job name:section withCode:0 print:1 outFile:$ofil task:inx] { $JobNext:$job } $FileClose:$ofil } # print the index file $inxFile=$FileOpen:["SRSMAN:m_inx.html" mode:w] $print:[ | | |SRS Manual - Index | | | |

Index

f:$inxFile] foreach:[$i in:$inx] if:$i.ok { $print:["($i.name) " f:$inxFile] foreach:[$p in:$i.list] $print:[" $p" f:$inxFile] $print:["
\n" f:$inxFile] } $print:[ | | f:$inxFile] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # $RCSfile: man_toc.i,v $ # $Revision: 1.5 $ # $Date: 1996/08/13 12:21:33 $ # $Author: etzold $ # # Generates a table of contents for a list of HTML files # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # $chapter={ {path:"SRSMAN:m_srswww.html" part:srswww} {path:"SRSMAN:m_query.html" part:query} {path:"SRSMAN:m_icarus.html" part:icarus} {path:"SRSMAN:m_prog.html" part:prog} {path:"SRSMAN:m_class.html" part:class} {path:"SRSMAN:m_icafunc.html" part:icafunc} {path:"SRSMAN:m_tour.html" part:tour} {path:"SRSMAN:m_install.html" part:install} {path:"SRSMAN:m_usage.html" part:usage} } $rules={ # extract titles and bodies field: ~ {$Out pre{$Skip:0}} x:{$Wrt:dummy} ( (/[ \t\n]*<[Hh][1-6]>/ {$Not} ln {$App})+ (/[ \t\n]*<[Hh][1-6]>/ {$Wrt:title} (/.*<\/[Hh][1-6]>/ {$Not} ln {$App})* /.*<\/[Hh][1-6]>/ {$App} ln {$Wrt:text})? )+ ~ # table of contents index: ~ {init{$prev=0} $In:[field c:title] $Out} /<.1>/ label+ /(.*)<\/.1>/ {$print:["$1\n" f:$toc] $prev=0} | /<.([2-4])>/ {$n=$1-1} label+ /(.*)<\/.[2-4]>/ { if:$prev==0 { $prev=$n-1 } if:$n>$prev for:{$k=$n-$prev $k $k=$k-1} $print:[ "
    " f:$toc] elif:$prev>$n for:{$k=$prev-$n $k $k=$k-1} $print:["
" f:$toc] $print:["
  • \n" f:$toc] if:$n==1 $print:["$1\n" f:$toc] elif:$n==2 $print:["$1\n" f:$toc] else $print:["$1\n" f:$toc] $prev = $n } ~ # other stuff ln: ~ /[^\n]*\n?/ ~ label: ~ /<(A NAME|a name)="?([^">]+)"?>(<\/[Aa]>)?/ {$label="$2"}~ #" } foreach:[$chap in:$chapter] { $fil = $FileOpen:"($chap.path)" $toc = $FileOpen:["SRSMAN:mtoc_($chap.part).html" mode:w] $fileName="mi_($chap.part).html" $print:[f:$toc s: | | |Table of Contents for Chapter "$part" | | | ] $job = $JobNew:[prod:$rules skip:" " file:$fil] while:$JobTokens:[$job name:index withCode:0] $JobNext:$job $print:['' f:$toc] $FileClose:$toc } $optRules={ arg: ~ {pre{$skip:0}} (/ +-/ {$not} ln)+ (name type value? text? | ln)+ ~ name: ~ / +-([a-zA-Z0-9]+)/ {$n=$1 $arg.($n).name=$1} ~ text: ~ {$arg.($n).text=$ct} ln (/ [^\n]+\n/)* ~ type: ~ / */ {$arg.($n).type=int} | / */ {$arg.($n).type=string} | x{$arg.($n).type=bool} ~ value: ~ / *\\[([^]]+)\\]/ {$arg.($n).value=$1} ~ ln: ~ /[^\n]*\n/ ~ } $rules={ file: ~ (/INCLUDE OPTIONS ([a-zA-Z0-9]+)/ { $arg=0 $Parse:[$System:"$1 -help" prod:$optRules start:arg] $print:[f:$oFile s: | | | | | | ] foreach:[$a in:$arg] if:$a.name!="" && $Trim:[$a.text skip:" \n"] != "" $print:[f:$oFile s: | | | | | | ] $print:['
    NameTypeDefaultComment
    ($a.name)($a.type)($a.value)($a.text)
    \n' f:$oFile] } | ln {$print:[f:$oFile s:$ct]})+ ~ ln: ~ /[^\n]*\n/ ~ } $arg={} $oFile = $fileOpen:["SRSMAN:usage.html" mode:w] $Parse:[fileName:"SRSDOC:usage.html" prod:$rules start:file] $fileClose:$oFile # # $RCSfile: odd.i,v $ # $Revision: 1.2 $ # $Date: 1996/05/24 14:11:51 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file:"SRSICA:oddgen.i" file:"SRSICA:oddfncts.i" file:"SRSICA:icacom.ic" file:"SRSICA:classes.i" $partable:[ vars:{ $parameter:[name:"doInitHeader" type:bool num:0 comment:"h-file with struct declaration and initialization"] $parameter:[name:"doHeader" type:bool num:0 comment:"h-file with struct declaration"] $parameter:[name:"doSection" type:bool num:0 comment:"binary section file (can be combined with '-h')"] $parameter:[name:"doMetaData" type:bool num:0 comment:"h-file with meta data initialization"] $parameter:[name:"doClassInfo" type:bool num:0 comment:"file with class information"] $parameter:[name:"printProgress" type:bool num:0 comment:"print a line for each ODD-file read"] $parameter:[name:"printProgress" type:bool num:0 comment:"print a line for each ODD-file read"] $parameter:[name:"printDots" type:bool num:0 comment:"print a dot for each ODD-file read"] PART_BOOLEAN:$partype:[name:"boolean" max:3 min:0 charset:"yYnN01oOfFjJ"] } ] $command:[name:odd usage:"sectionName" vars:{ $arg:[name:"-help" type:help comment:"this message"] $arg:[name:"-i" parameter:doInitHeader] $arg:[name:"-h" parameter:doHeader] $arg:[name:"-s" parameter:doSection] $arg:[name:"-m" parameter:doMetaData] $arg:[name:"-c" parameter:doClassInfo] $arg:[name:"-r" parameter:printProgress] $arg:[name:"-d" parameter:printDots] } ] $def:[infile:"SRSICA:sdl.sdl" outfile:"SRSSOU:odd5.h" section_name:"sdl" section_size:50] # # $RCSfile: odd.ic,v $ # $Revision: 1.2 $ # $Date: 1996/05/24 14:11:52 $ # $Author: ulyanov $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ file:"SRSICA:oddgen.i" file:"SRSICA:oddfncts.i" file:"SRSICA:classes.i" file:"SRSICA:parameter.ic" file:"SRSICA:arglist.ic" $def:[infile:"SRSICA:odd.i" outfile:"SRSSOU:oddclass.h" section_name:"sdl" section_size:500] # # $RCSfile: oddfncts.i,v $ # $Revision: 1.1 $ # $Date: 1996/05/06 16:14:03 $ # $Author: srs $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # functions return attribute size F_SIZINHERIT:$function:[name:OFInheritSize args:"(SDLoOBJ *, SDLoATTR *)"] F_SIZ4BARR:$function:[name:OF4BArrSize args:"(SDLoOBJ *, SDLoATTR *)"] F_SIZ4B:$function:[name:OF4BSize args:"(SDLoOBJ *, SDLoATTR *)"] F_SIZPTRARR:$function:[name:OFPtrArrSize args:"(SDLoOBJ *, SDLoATTR *)"] F_SIZPTR:$function:[name:OFPtrSize args:"(SDLoOBJ *, SDLoATTR *)"] F_SIZBNF:$function:[name:OFBNFSize args:"(SDLoOBJ *, SDLoATTR *)"] F_SIZBARR:$function:[name:OFBArrSize args:"(SDLoOBJ *, SDLoATTR *)"] # function to postprocess attributes F_MAKEDFLT:$function:[name:OFMakeDefault args:"(SDLoOBJ *, SDLoATTR *, unsigned int *)"] F_MAKENODFLT:$function:[name:OFMakeNoDefault args:"(SDLoOBJ *, SDLoATTR *, unsigned int *)"] F_MAKECHILD:$function:[name:OFMakeChild args:"(SDLoOBJ *, SDLoATTR *, unsigned int *)"] F_MAKECHILDN:$function:[name:OFMakeChildN args:"(SDLoOBJ *, SDLoATTR *, unsigned int *)"] F_MAKEALLOBJ:$function:[name:OFMakeAllObj args:"(SDLoOBJ *, SDLoATTR *, unsigned int *)"] F_MAKEALLOBJN:$function:[name:OFMakeAllObjN args:"(SDLoOBJ *, SDLoATTR *, unsigned int *)"] # functions to write member declarations F_DEFSIMPLE:$function:[name:OFDefSimple args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFSTR:$function:[name:OFDefStr args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFFNCT:$function:[name:OFDefFnct args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFHEADER:$function:[name:OFDefHeader args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFSTRUCTPTR:$function:[name:OFDefStructPtr args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFGENERICTYP:$function:[name:OFDefGenericTyp args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFUSER:$function:[name:OFDefUser args:"(FILE *, SDLoATTR *, char *, char *)"] F_DEFEBNF:$function:[name:OFDefEbnf args:"(FILE *, SDLoATTR *, char *, char *)"] # functions for inserting attributes in target structures F_INSERTFLOAT:$function:[name:OFInsertFloat args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTINT:$function:[name:OFInsertInt args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTUINT:$function:[name:OFInsertUInt args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTUCHAR:$function:[name:OFInsertUChar args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTUSER:$function:[name:OFInsertUser args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTSTR:$function:[name:OFInsertStr args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTFUNCTION:$function:[name:OFInsertFunction args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTOBJECT:$function:[name:OFInsertObject args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INSERTHEADER:$function:[name:OFInsertHeader args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_INHERIT:$function:[name:OFInherit args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] F_GENERIC:$function:[name:OFGeneric args:"(void *, void *, void *, void ***, char *, unsigned int, int)"] # functions for writing attribute values to the header file F_WRTINT:$function:[name:OFWrtInt args:"(SDLoATTR *, char *, void **)"] F_WRTUCHAR:$function:[name:OFWrtUChar args:"(SDLoATTR *, char *, void **)"] F_WRTUINT:$function:[name:OFWrtUInt args:"(SDLoATTR *, char *, void **)"] F_WRTFLOAT:$function:[name:OFWrtFloat args:"(SDLoATTR *, char *, void **)"] F_WRTSTR:$function:[name:OFWrtStr args:"(SDLoATTR *, char *, void **)"] F_WRTNAME:$function:[name:OFWrtName args:"(SDLoATTR *, char *, void **)"] F_WRTNULL:$function:[name:OFWrtNULL args:"(SDLoATTR *, char *, void **)"] F_WRTADDR:$function:[name:OFWrtAddr args:"(SDLoATTR *, char *, void **)"] F_WRTEBNF:$function:[name:OFWrtEBNF args:"(SDLoATTR *, char *, void **)"] # functions for checking attribute values F_CHECKNUM:$function:[name:OFCheckNum args:"(SDLoATTR *, int, char *)"] F_CHECKSTR:$function:[name:OFCheckStr args:"(SDLoATTR *, int, char *)"] # functions for generic attribute types F_GENSIMPLE:$function:[name:OFGenSimple args:"(SDLoOBJ *, SDLoATTR *)"] F_GENOBJECT:$function:[name:OFGenObject args:"(SDLoOBJ *, SDLoATTR *)"] # attribute type definitions AT_FLOAT:$attrtype:[calcsize:@F_SIZ4BARR make:@F_MAKEDFLT declare:@F_DEFSIMPLE insert:@F_INSERTFLOAT write:@F_WRTFLOAT check:@F_CHECKNUM typname:float gentype:@F_GENSIMPLE] AT_UCHAR:$attrtype:[calcsize:@F_SIZBARR make:@F_MAKEDFLT declare:@F_DEFSIMPLE insert:@F_INSERTUCHAR write:@F_WRTUCHAR check:@F_CHECKNUM typname:"unsigned char"] AT_INT:$attrtype:[calcsize:@F_SIZ4BARR make:@F_MAKEDFLT declare:@F_DEFSIMPLE insert:@F_INSERTINT write:@F_WRTINT check:@F_CHECKNUM typname:INT4 gentype:@F_GENSIMPLE] AT_UINT:$attrtype:[calcsize:@F_SIZ4BARR make:@F_MAKEDFLT declare:@F_DEFSIMPLE insert:@F_INSERTUINT write:@F_WRTUINT check:@F_CHECKNUM typname:UINT4] AT_STRING:$attrtype:[calcsize:@F_SIZPTRARR make:@F_MAKEDFLT declare:@F_DEFSTR insert:@F_INSERTSTR write:@F_WRTSTR save_address:yes check:@F_CHECKSTR gentype:@F_GENSIMPLE typname:char] AT_ALLOBJ:$attrtype:[calcsize:@F_SIZPTR make:@F_MAKEALLOBJ declare:@F_DEFSTRUCTPTR write:@F_WRTADDR save_address:yes] AT_CHILD:$attrtype:[calcsize:@F_SIZPTR make:@F_MAKECHILD declare:@F_DEFSTRUCTPTR write:@F_WRTADDR save_address:yes] AT_CHILD_N:$attrtype:[calcsize:@F_SIZ4B make:@F_MAKECHILDN declare:@F_DEFSIMPLE write:@F_WRTINT typname:INT4] AT_ALLOBJ_N:$attrtype:[calcsize:@F_SIZ4B make:@F_MAKEALLOBJN declare:@F_DEFSIMPLE write:@F_WRTINT typname:INT4] AT_OBJECT:$attrtype:[calcsize:@F_SIZPTRARR make:@F_MAKEDFLT declare:@F_DEFSTRUCTPTR insert:@F_INSERTOBJECT write:@F_WRTADDR save_address:yes gentype:@F_GENOBJECT] AT_PROTOFNCT:$attrtype:[calcsize:@F_SIZPTR make:@F_MAKENODFLT insert:@F_INSERTSTR write:@F_WRTNAME check:@F_CHECKSTR] AT_FNCT:$attrtype:[calcsize:@F_SIZPTR make:@F_MAKEDFLT declare:@F_DEFFNCT insert:@F_INSERTFUNCTION write:@F_WRTNAME save_address:yes] AT_USER:$attrtype:[calcsize:@F_SIZPTRARR make:@F_MAKEDFLT declare:@F_DEFUSER insert:@F_INSERTUSER write:@F_WRTNULL save_address:yes] AT_GENERIC_TYP:$attrtype:[insert:@F_GENERIC] AT_GENERIC_OBJ:$attrtype:[insert:@F_GENERIC] AT_GENERIC:$attrtype:[calcsize:@F_SIZPTRARR declare:@F_DEFGENERICTYP save_address:yes] AT_DEFER:$attrtype:[] AT_INHERIT:$attrtype:[calcsize:@F_SIZINHERIT make:@F_MAKENODFLT insert:@F_INHERIT] AT_OVERLOAD:$attrtype:[] AT_STORE:$attrtype:[calcsize:@F_SIZPTRARR make:@F_MAKEDFLT declare:@F_DEFHEADER insert:@F_INSERTHEADER write:@F_WRTNULL save_address:yes] AT_CLONE:$attrtype:[calcsize:@F_SIZPTRARR make:@F_MAKEDFLT declare:@F_DEFSTRUCTPTR insert:@F_INSERTOBJECT save_address:yes] AT_EBNF:$attrtype:[calcsize:@F_SIZBNF declare:@F_DEFEBNF write:@F_WRTEBNF] $CDefine:[@AT_CHILD name:AT_CHILD] $CDefine:[@AT_PROTOFNCT name:AT_PROTOFNCT] $CDefine:[@AT_FNCT name:AT_FNCT] $CDefine:[@AT_CLONE name:AT_CLONE] # # $RCSfile: oddgen.i,v $ # $Revision: 1.1 $ # $Date: 1996/05/06 16:14:03 $ # $Author: srs $ # # Some general definitions needed for the ODD compiler # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $FALSE=0 $TRUE=1 $SDLxXOBJCLASS=255 $SDLxFLOAT=0 $SDLxUCH=1 $SDLxINT=2 $SDLxUINT=3 $SDLxSTR=4 $SDLxGBLSS=5 $SDLxOWN=6 $SDLxOWN_N=7 $SDLxGBLNSS=8 $SDLxCHILD=9 $SDLxPFNCT=10 $SDLxFNCT=11 $SDLxUSER=12 $SDLxGTYP=13 $SDLxGTYPDEF=14 $SDLxGTYP_P=15 $SDLxDEFER=16 $SDLxINHERIT=17 $SDLxOVERLAY=18 $SDLxORG=19 $SDLxCLONE=20 $SDLxBNF=21 # $SDLxVIRTUAL=1 # $SDLxPNUM=9 $SDLxPNAM=10 $SDLxPTXT=11 $SDLxPCNST=12 # $SDLxREQ=1 $SDLxNOREQ=0 $SDLxXSS=7 $SDLxXNAM=25 $SDLxXLN=132 $FILxXNAM=132 $SDLxHDR=1 $SDLxHDR2=2 $SDLxNOHDR=0 O_FUNCTION:$object:[function type:$SDLxFNCT declname:"X" status:system attrs:{ $attribute:[name type:protofunction declname:"fnctnam" max:30 valtype:text] $attribute:[args type:string declname:"args" max:132 valtype:text required:y] $attribute:[module type:string declname:"module" max:30 valtype:{text name}] } ] # # $RCSfile: parameter.i,v $ # $Revision: 1.9 $ # $Date: 1996/08/11 22:51:23 $ # $Author: etzold $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # functions for checking #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ F_CHECKFIELDLIST:$function:[name:LibParSetFields args:"(char *)"] F_CHECKLIBLIST:$function:[name:LibParSetLibs args:"(char *)"] F_CHECKLINKLIBLIST:$function:[name:LibParSetLinkLibs args:"(char *)"] F_SETENVIRONMENT:$function:[name:LibSetEnvironment args:"(char *)"] F_CHECKLIBLISTVIEWR:$function:[name:"LibParSetLibsViewRoot" args:"(char *)"] F_CHECKLIBLISTVIEWL:$function:[name:"LibParSetLibsViewLeaf" args:"(char *)"] $partable:[ vars:{ $parameter:[seqFormat type:string set:'$setFormat:[Sequence set:"%s"]' get:'$setFormat:Sequence' comment:"format of sequence output file"] $parameter:[printText type:bool num:0 isVolatile:1 comment:"copy complete text (annotation) part of entry"] $parameter:[printData type:bool num:0 isVolatile:1 comment:"copy data (eg, sequence) part of entry"] $parameter:[printEntireEntry type:bool num:0 isVolatile:1 comment:"Print entire entry."] $parameter:[viewFieldList type:string comment:"List of fields that will be placed into a table view."] $parameter:[fieldList type:string parType:@PART_FIELDLIST comment:"include fields in entry list "] $parameter:[doQueryReport type:bool num:0 comment:"write a report about the query"] $parameter:[queryListValues type:bool num:0 isVolatile:1 comment:"List all values that match the query."] $parameter:[minIndexValN type:number num:0 comment: |List only values that occur at least specified number of times. \ |Use together with "lv". ] $parameter:[listFOSN type:bool num:0 comment:"produces a FOSN (File Of Sequence Names)"] $parameter:[printToFile type:bool num:0 comment:"print resultant entries to file(s)"] $parameter:[fosnWithPos type:bool num:0 comment:"output FOSN includes sequence feature locations"] $parameter:[isHTMLFormat type:bool num:0 isVolatile:1 comment:"Select HTML format for output."] # #file and directory names # $parameter:[indexDirName type:string str:"SRSINX:" comment:"directory with the indices"] $parameter:[outDirName type:string str:"SRSINX:" comment:"name of output directory"] $parameter:[etcDir type:string str:"SRSETC:" comment:"path of script that prepares SRS environment"] $parameter:[updateScriptName type:string str:"" comment:"File name of output script file."] $parameter:[environment type:string partype:@PART_ENVIRONMENT comment:"Name of the library environment" str:unix] # #query options # $parameter:[setName type:string partype:@PART_SETNAME] $parameter:[makeWild type:bool partype:@PART_BOOLEAN num:0 comment:"appends a wildcard to each search word"] $parameter:[linkToLibs type:bool partype:@PART_BOOLEAN num:0 comment:"links a single entry to selected libraries"] $parameter:[linkToSet type:bool partype:@PART_BOOLEAN num:0 comment:"links result of query to selected libraries"] $parameter:[libList type:string parType:@PART_LIBLIST comment:"select libraries of group"] $parameter:[linkLibList type:string parType:@PART_LINKLIBLIST comment:"list of libraries to be linked to"] $parameter:[queryFileName type:string comment:"name of file containing a list of queries"] # #others # $parameter:[printLibInfo type:bool num:0 comment:"prints info about specified library"] $parameter:[printLibs type:bool num:0 comment:"prints a list of all active libraries"] $parameter:[linkTable type:string comment:"print link table of entries found by query to selected libs"] $parameter:[getStartupInfo type:bool partype:@PART_BOOLEAN comment:"Startup info for client programs."] # #options for retrieval of sequence features # $parameter:[shiftbeginpos type:number comment:"shift feature begin position"] $parameter:[shiftendpos type:number comment:"shift feature end position"] $parameter:[isshiftbeginrelend type:bool num:0 comment:"shift of feature begin is relative to end pos"] $parameter:[isshiftendrelbegin type:bool comment:"shift of feature end is relative to begin pos"] $parameter:[takeuncompletefeature type:bool comment:"accecpt incomplete features" num:1] $parameter:[takeuncompleteshiftfeature type:bool comment:"accecpt incomplete shifted features"] # #building indices # $parameter:[showWarnings num:0 type:bool comment:"display warnings caused by errors in the databank"] $parameter:[compress type:bool comment:"compresses indices built previously"] $parameter:[touchIndex type:bool comment:"touch index"] $parameter:[relocateLib type:bool comment:"relocate library, ie, build a new IDX file"] $parameter:[buildIndex num:1 type:bool comment:"build all or selected search indices for library"] $parameter:[parseTest type:bool comment:"display only extracted values"] $parameter:[readLink type:bool comment:"read library and process link information"] $parameter:[indexLink type:bool comment:"build a link using two indices"] $parameter:[releaseName type:string comment:"assign a release name to a set of indices"] # #checking and maintaining indices # $parameter:[procIndexSize type:number num:15000 comment:"total index size (kb) to be processed in one go"] $parameter:[checkLibList type:string comment:"list of libraries to be checked - else all libraries"] $parameter:[notCheckLibList type:string comment:"list of libraries to be exclued from checking"] $parameter:[srsEnvHeader type:bool comment:"produces 'srsenv.h' defining all SRS env variables"] # #options for WWW programs # $parameter:[getOddFile type:string comment:"The name of the file with the databank description."] $parameter:[dontShowOrig type:bool comment:"don't list the query..only links to it"] $parameter:[userId type:string comment:"user ID, or file, name associated with a WWW session"] $parameter:[visitIndexValue type:string comment:"visit the set of entries belonging to an index value"] $parameter:[queryManager type:bool comment:"activates query manager"] $parameter:[setListPar type:bool comment:"allows to set parameters for viewing a set"] $parameter:[printHelpTopic type:string comment:"prints specified help topic"] $parameter:[queryCombine type:bool comment:"executes query that was specified in the query manager"] $parameter:[topPage type:bool comment:"revisists top page"] $parameter:[doRepeat type:bool comment:"revisits query form with same input as before"] $parameter:[doHyperTextLinks type:bool comment:"revisits query form with same input as before"] $parameter:[doQueryForm type:bool comment:"present the query form"] $parameter:[doQuery type:bool comment:"do the query"] $parameter:[libInfo type:string comment:"print some info about library"] $parameter:[linkInfo type:bool comment:"print some info about link between 2 libraries"] $parameter:[listSetNumber type:number isVolatile:1 comment:"number (in history) of set to be listed"] $parameter:[viewSetNumber type:number comment:"number (in history) of set to be viewed"] $parameter:[listQuery type:string comment:"query of set to be listed"] $parameter:[doBlastSearch type:bool comment:"perform a search with Blast and index results"] $parameter:[prepBlastSearch type:bool comment:"collect user input for a search with Blast"] $parameter:[listEntriesChunkSize type:number num:50 comment:"number of entries to be listed in one go"] $parameter:[listEntriesStartN type:number isVolatile:1 comment:"number of first entry in set to be listed"] $parameter:[viewEntriesChunkSize type:number num:30 comment:"number of entries to be viewed in one go"] $parameter:[viewEntriesStartN type:number isVolatile:1 comment:"number of first entry in set to be viewed"] $parameter:[maxValN type:number num:0 comment:"print only words that occur number of times"] $parameter:[getMessage type:bool comment:"get a message from user"] $parameter:[sendMessage type:bool comment:"send a user message to the messages file"] $parameter:[subEntryN type:number comment:"number of subentry to be accessed"] $parameter:[translateSequence type:bool comment:"print the translation product instead of DNA sequence"] $parameter:[linkLibSelect type:bool comment:"display a table with all possible links"] $parameter:[linkToLibs type:bool comment:"link set/entry to other libraries"] $parameter:[printLinkTable type:bool comment:"print a link table"] $parameter:[printNetwork type:bool comment:"print a network in tabular form."] $parameter:[linksPicture type:bool comment:"Print page with picture describing network in tabular form."] $parameter:[networkPicture type:bool comment:"Print page with network picture."] # # new wgetz # $parameter:[fromLibName type:string] $parameter:[toLibName type:string] $parameter:[useMime type:bool comment:"mime type for saving the results on clients disk"] $parameter:[mimeType type:string comment:"MIME type to printed on top of the output page."] $parameter:[readUserFile type:bool comment:"readUserFile switch associated with a WWW session"] $parameter:["wwwFunctionName" type:string comment:"Name of function to be called in wgetz."] $parameter:["isHtml3" type:bool num:1 comment:"Client supports new HTML3 standard"] $parameter:["style" type:string comment:"Mode can be 'fancy' or nothing."] $parameter:["isDebug" type:bool comment:"Determines whether or not to print debug information."] $parameter:["queryString" type:string comment:"A string with an SRS query language expression."] $parameter:["delete" type:string set:'$ParDel:"%s"' isVolatile:1 comment: |A command to delete all the parameters matching the regular |expression assigned to it. ] $parameter:["nextFunction" type:string comment:"A Function to be called by WWW Link Page."] $parameter:["viewNumber" type:number comment:"For internal use of wgetz."] $parameter:[queryNumber type:number comment:"refer query by number"] $parameter:[deleteParam type:string comment:"delete parameters in history from command line"] $parameter:[mimeEntriesChunkSize type:number num:100 comment:"number of entries exported to client at a time"] $parameter:[mimeEntriesStartN type:number comment:"nth Entry to start with for mime export "] $parameter:[viewName type:string comment:"view Name to edit that view"] $parameter:[currentView type:number comment:"to print fields set for this view number"] $parameter:[isTable type:bool comment:"prints view result in table format"] $parameter:[method type:string comment:"method function to apply on a querystring"] $parameter:["viewLibListRoot" type:string isVolatile:1 parType:@PART_LIBLISTVIEWROOT comment:"select libraries of group as root for view"] $parameter:["viewLibListLeaf" type:string isVolatile:1 parType:@PART_LIBLISTVIEWLEAF comment:"select libraries of group as leaf for view"] $parameter:[wwwColorScheme type:string str:plain] $parameter:[wwwSessionEntryList type:bool] $parameter:["viewNumber" type:number isVolatile:1] $parameter:["browseIndex" type:string isVolatile:1 comment: |Selects a data-field or index to be displayed for browsing on |the next page. ] $parameter:["browseLibs" type:string isVolatile:1] # #trembl options # $parameter:[tremblInFile type:string comment: |Optional input file name. The file extension and format must be |the same as of the specified library. ] $parameter:[findAccNoCommand type:string comment: |The command with which to obtain a sequence file from an accession |number. Put a '%%s' where the accession number should be placed |within the command (eg, 'findacc %%s'). ] $parameter:[inputSeqFile type:string comment: |Name of the file obtained by the above command; again a '%%s' |must be placed in lieu of the accession number (eg, '%%s.seq'). ] $parameter:[libName type:string comment: |Name of the input library. If you specify a file name then this |specifies the format of the file. ] # #reflink # $parameter:[readLib type:string comment:"name of library to be read for references"] $parameter:[searchLib type:string str:medline comment:"name of library to be searched for references"] $parameter:[journalListFile type:string comment:"name of journal list to be read/written"] $parameter:[doJournalList type:bool comment:"make a new journal list"] $parameter:[doMergeJournalLists type:bool comment:"merge two journal lists to one"] $parameter:[doRefLink type:bool comment:"link the two libraries using their references"] $parameter:[doRefLinkFile type:bool comment:"write a text file with all links found"] $parameter:[printSeparateFiles type:bool comment:"If set then each entry will be written into a separate file."] $parameter:[outputFileName type:string comment: |Name of the output file name. Prints to terminal if no name |is specified. ] # #srspict # $parameter:[doNetworkPict type:bool comment:"Create a file with the network picture."] $parameter:[doGraphTablePict type:bool comment:"Create a file with the graph table picture."] # #try # $parameter:[icaIsDebug type:bool comment:"Puts the Icarus interpreter into debugging mode."] $parameter:[doClassInfo type:bool comment: |Prints information about all object classes that were defined in |the Icarus file. ] $parameter:[doCommandInfo type:bool comment: |Prints information about the builtin functions of Icarus. ] $parameter:[printTrace type:bool comment:"Prints the trace information."] $parameter:[printSyntaxTree type:bool comment:"Prints the syntax tree."] $parameter:[syntaxName type:string comment:"Name of the file with test syntax."] $parameter:[productionName type:string comment:"Name of the target production name."] $parameter:[printAllTokLists type:bool comment:"Prints the contents of all token lists."] $parameter:[icaDbgExecStack type:number comment:"Prints all program stack before execution."] $parameter:[icaDbgBuildStack type:number comment:"Prints Icarus commands and the generated program stacks."] $parameter:[ica2cName type:string comment: |Program is not executed but written to a C language file with the |specified file name. ] $parameter:[useIni type:bool comment:"Use interpreter written to a C language file."] $parameter:[readBuiltin type:bool comment:"Read the file 'builtin.i' before starting."] #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # parameter type objects #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PART_SETNAME:$partype:[name:setName max:20 min:0 charset:"a-zA-Z0-9_"] PART_BOOLEAN:$partype:[name:boolean max:3 min:0 charset:"yYnN01oOfFjJ"] $partype:[name:fieldQuery max:200 min:0 charset:"a-zA-Z0-9\-_\$[]().;*?&|!'"] $partype:[name:inFileName max:200 min:0 charset:"a-zA-Z0-9\-_\$[]().;*?&|!'"] $partype:[name:outFileName max:200 min:0 charset:"a-zA-Z0-9\-_\$[]().;*?&|!'"] $partype:[name:query max:200 min:0 charset:"a-zA-Z0-9\-_\$[]().;*?&|!'"] PART_FIELDLIST:$partype:[name:fieldList check:@F_CHECKFIELDLIST charset:"a-zA-Z0-9 "] PART_LIBLIST:$partype:[name:libList check:@F_CHECKLIBLIST charset:"a-zA-Z0-9_\- "] PART_LINKLIBLIST:$partype:[name:libList check:@F_CHECKLINKLIBLIST charset:"a-zA-Z0-9_\- "] PART_ENVIRONMENT:$partype:[name:env check:@F_SETENVIRONMENT charset:"a-zA-Z0-9_\- "] # -- # added by ramu # -- PART_LIBLISTVIEWROOT:$partype:[name:viewLibListRoot check:@F_CHECKLIBLISTVIEWR charset:"a-zA-Z0-9_\-~ "] PART_LIBLISTVIEWLEAF:$partype:[name:"viewLibLisLeaf" check:@F_CHECKLIBLISTVIEWL charset:"a-zA-Z0-9_\-~ "] PART_ENVIRONMENT:$partype:[name:"env" check:@F_SETENVIRONMENT charset:"a-zA-Z0-9_\- "] } ] # $RCSfile: parameter.ic,v $ # $Revision: 1.1 $ # $Date: 1996/05/06 16:14:05 $ # $Author: srs $ # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ O_PAR:$object:[name:parameter typname:PARo declname:ODD_par attrs:{ $attribute:[declname:"*intern" type:user typname:"char" rem:"for internal use for the list manager"] $attribute:[declname:classId type:int defaultval:0 rem:"for internal use for the list manager"] $attribute:[name:name declname:"name" type:string valtype:{text name} unnamed:y rem:"name of associated global parameter"] $attribute:[name:str declname:str type:string valtype:{text name} rem:"Value of 'string' parameter."] $attribute:[name:num declname:num type:int valtype:num rem:"Value of 'number' parameter."] $attribute:[name:real declname:real type:float rem:"Value of 'real' parameter."] $attribute:[name:function declname:function type:function valtype:constant rem:"Value of 'function' parameter."] $attribute:[name:object typname:"void" declname:"*object" type:user rem:"Value of 'object' parameter."] $attribute:[name:isVolatile type:uchar declname:isVolatile] $attribute:[name:type type:uchar declname:type valtype:name rem:"Parameter type." enum:{ $value:[name:string val:1] $value:[name:number val:2] $value:[name:real val:4] $value:[name:function val:8] $value:[name:bool val:16] $value:[name:object val:32] } ] $attribute:[name:comment declname:comment type:string valtype:text rem:"Short description of parameter."] $attribute:[name:helpTopic declname:helpTopic type:string valtype:{name text} status:obsolete rem:"help topic associated to parameter"] $attribute:[name:key type:string declname:key max:1 valtype:{text name} rem:"keystroke associated to parameter or value" status:obsolete] $attribute:[name:partype declname:parType type:object defaultval:@O_PARTYPE valtype:constant rem:"Object 'partype' for validating the parameter value."] $attribute:[name:check declname:check type:object defaultval:@O_PARTYPE valtype:constant status:obsolete rem:"Object 'partype' for validating the parameter value."] $attribute:[declname:isLocked type:int defaultval:0 rem:"internal use..."] $attribute:[set declname:set type:string rem:"Icarus command to set the current value."] $attribute:[get declname:get type:string rem:"Icarus command to get the current value."] } ] O_PARTYPE:$object:[name:partype typname:PARoTYPE declname:Odd_parType rem:"Describes further a parameter type by specifying constraints or a function for checking the parameter value." attrs:{ $attribute:[declname:"*intern" type:user typname:"char" rem:"for internal use for the list manager"] $attribute:[declname:classId type:int defaultval:0 rem:"for internal use for the list manager"] $attribute:[name:name declname:"name" type:string valtype:{text name} rem:"Name of associated global parameter."] $attribute:[name:check declname:check type:function valtype:constant defaultstr:"(void *)" rem:"Function that checks parameter value."] $attribute:[name:max declname:max type:int defaultval:0 valtype:num rem:"Max value, or max length."] $attribute:[name:min declname:min type:int defaultval:0 valtype:num rem:"Mmin value, or min length."] $attribute:[name:maxReal declname:maxReal type:float defaultval:0 valtype:num rem:"Max real value."] $attribute:[name:minReal declname:minReal type:float defaultval:0 valtype:num rem:"Min real value."] $attribute:[name:charSet declname:"charSet" type:string valtype:{text name} rem:"Permissible set of chars for parameter value string."] }] O_PARTABLE:$object:[name:partable typname:PARoLIST status:system nchilds:2 child:{@O_PAR @O_PARTYPE} declname:ODD_parTable attrs:{ $attribute:[name:vars declname:"par" type:child defaultval:@O_PAR rem:"List of all predefined parameters."] $attribute:[declname:"parN" type:nr_of_childs defaultval:@O_PAR rem:"Number of predefined parameters."] $attribute:[declname:"parType" type:child defaultval:@O_PARTYPE rem:"List of all predefined parameter types."] $attribute:[declname:"parTypeN" type:nr_of_childs defaultval:@O_PARTYPE rem:"Number of predefined parameter types."] }] $parStr:[agazik set:'asfd \n\n\n\n\nsafdkljalksdfjlkasjf'] $viewManager={ head: "this ($parStr:outDirName) is \n $$%d %s |%10d| \the\" heaT\n" aa: |aarararar | end gu:{ ra: | holo | holo \ | hala \ ru: | .. ..... ruhhhhh($parStr:outDirName)HHHHHHHHH holo | ru holo \ | ru hala } bb: 'bbrararar\n' cc: 'ccrararar' dd: 'ddrararar' ee: 'eerararar' ff: "ffra(\$arrr.asfd) rarar" } $viewManagerl={ head: | |:SRS: NEWSRS VIEW Manager Page |
    |($buttons:viewManager) |
    | | | | | | | | | | | | | | |
    | | | | |a new view
    | | |selected view
    selected view
    |

    | | | | | | | | | | | root: |%s
    leaf: |%s
    field:{ head: | root: |%s
    leaf: |%s
    } listing: | | tail: |
    View Listing
    View Name Root Libs Root Fields Leaf Libs Leaf Fields
    tail: |
    | %s | footer: |

    } $viewtable={ header: |%(mimehtml) | | | View Print Fields: | |
    | | | | | title: { libname: | field: | trail: | } rowbeg: | rowend: | entry: { name: | field: { empty: | listing: | } } } $queryform={ header: |@@ |%(mimehtml) | | ($gaga) | |SRS:Query Form Page | | | | | | | |@@print2 %(FANCY)HEADER-BUTTONS srsbar_qf2.gif fafa |

    |Search lib: |%s title: |

    | | | | |


    |Compose query and select fields to be included in entry list. | Not all fields may be searchable or to be displayed table:{ header: |

    |

    View: %s

    %s%s
    | %s | left: | right: | center: |@@ value: |%s
    end: |
    | | | | | field: | | | | | | rangefield: | | | | | | | | | | | | subentry: | noquery: | | | | | | rowend: | trailer: |
    |Field NameQueryInclude in ListRetrieve
    Subentries
    |%s |%s | | |
    |
    |%s |%s | | | | | | | | | | | | |Subentry only |
    |%s | %s | | |
    |
    } getbool: |
    |Combine searches with | | Append wildcard '*' to search words |?!

    chunkset: |Entry list in chunks of | view:{ header: |Select a view | } trailer: |

    | | } $result={ header: |@@ |%(mimehtml) | | QueryResult | |
    | | | | | | Query "%s" found %d entries | | |
    | | | | | | | | | | | | | with chunk size | | | | | | Query "%s" found %d entries | | |
    | | | | | | | | | | | | | with chunk size | | | | | | |Start a new SRS session | | | | | |The SRS Manual | | |The SRS Manual | | | |Status of all databanks served by all SRSWWW sites | |Status of all databanks served by all SRSWWW sites | | | |The SRS Newsgroup |The SRS newsgroup | # the link to the home page | |\ |Home Page | |Back to the EMBL home page | | | | | | | 

    This is the SRSWWW server at ($parStr:siteName), |version ($parStr:srsVersion) | | | } ############################################################################### # # displays help for one or all Icarus command # $icarusCommand={ title: | | |Descriptions of built in Icarus functions | | |

    The Icarus Commands

    |The names are still not alphabetically ordered. head: |

    $%s

    |%s |

    |

    | | | | | | noArgs: | arglist:{ name: | type:{ int: | string: | object: | real: | alias: | var: | d1: | d2: | strv: | d3: | d4: | d5: | d6: | d7: | d8: | list: | enum:{ head: | } } unnamed: | named: | required: | optional: | comment: | defaultNum: | defaultStr: | empty: | tail: | } return:{ head: | preType: | postType: | nothing: | } tail: |
    Name TypeUnn ReqDefault Comment
    |Arguments
    none
    %sintstring%s objectrealaliasvarunknownunknownstrvunknownunknownunknownunknownunknownunknownlistenum:
    value: |%s tail: |
    + +-%s%d%s 
    |Returns
            
    Nothing
    |
    | } ############################################################################### # # displays help for one or all SRS object classes. # # $classInfo={ head: | | |

    List of SRS Object Classes

    |
    |
    Date: %s
    |
    |The following lists among others the object classes that are used to |describe the integrated databanks. dir:{ head: |

    List Object Classes in SRS

    |
    Date: %s
    |
      class: |
    • \$%s tail: |

    } class:{ head: |

    \$%s

    remark: |%s

    |

    | | | | | | | | | attrib:{ head: | empty: | remark: | unnamed: | named: | typeHead: | type: |%s listType: |list of $%s ptrType: |%s $%s arrSize: |
    list size: %d | default:{ option: | num: | real: | } minmaxNum: |
    min: %d
    max: %d minmaxStr: |
    min length: %d
    max length: %d required: | optionList:{ head: |\ option: |
  • %s tail: |\ } infoEnd: |
  • tail:'' } tail: |
    Arguments
    NameCommentUnnReqTypeDefault
    %s %s+  typeTail: |%s string: |"%s"%d%f+

    } } ############################################################################### # # Very importantly, sets a few color schemas # # $colorScheme={ plain:{ page: '' cell: |BGCOLOR="#d3b5b5"\ } white:{ page: |text="#000000" bgcolor="#FFFFF0" link="#0000FF" \ | vlink="#FF0000" alink="#FF0000"\ cell: |BGCOLOR="#d3b5b5"\ } yellow:{ page: |text="#400040" bgcolor="#FFFF80" link="#0000FF" |vlink="#008000" alink="#FF0080" cell: |BGCOLOR="#"\ } blue:{ page: |text="#FFFFFF" bgcolor="#000080" link="#FFFF00" |vlink="#8080FF" alink="#FF00FF" cell: |BGCOLOR="#0000A0"\ } darkGreen:{ page: |BGCOLOR="#344B8C" TEXT="#FFBE00" LINK="#FF7F00" VLINK="#DB9370" cell: |\ } black:{ page: |text="#FFFFFF" bgcolor="#000000" link="#FFFF00" |vlink="#C0C0C0" alink="#COFFCO" cell: |BGCOLOR="#0000A0"\ } grayRock:{ page: |background=($parStr:imgdir)/gray_rock.gif cell: |BGCOLOR="#C0C0C0"\ } yellowWeave:{ page: |background=($parStr:imgdir)/yellow_weave.gif cell: |BGCOLOR="#d3b5b5"\ } greenPaper:{ page: |background=($parStr:imgdir)/greenwhite_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } bluePaper:{ page: |background=($parStr:imgdir)/blue_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } grayAluminium:{ page: |background=($parStr:imgdir)/gray_aluminum.gif cell: |BGCOLOR=\"#edeafb\"\ } tanPaper:{ page: |background=($parStr:imgdir)/tan_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } yellowStucco:{ page: |background=($parStr:imgdir)/yellow_stucco.gif cell: |BGCOLOR="#d3b5b5"\ } purpleWeave:{ page: |background=($parStr:imgdir)/lipurple_weave.gif cell: |BGCOLOR=\"#edeafb\"\ } orangePaper:{ page: |background=($parStr:imgdir)/orange_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } tealPaper:{ page: |background=($parStr:imgdir)/teal_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } summerPaper:{ page: |background=($parStr:imgdir)/summer_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } peachPaper:{ page: |background=($parStr:imgdir)/peach_paper.gif cell: |BGCOLOR=\"#edeafb\"\ } greenMarble:{ page: |background=($parStr:imgdir)/greenred_marble.gif cell: |BGCOLOR="#d3b5b5"\ } blueMarble:{ page: |background=($parStr:imgdir)/tanblue_marble.gif cell: |BGCOLOR="#d3b5b5"\ } } ############################################################################### # # the list of libraries # # $libList={ head: | |SRSWWW at ($parStr:siteName): list of available data banks | | |

    | title: |

    Data Banks Available at ($parStr:siteName)

    |%s

    |

    | | | |
    |
    |

    | | | | | | | | | libraryGood: | | | | | | | | libraryBad: | | | | | | | | tail: |
    Data BankReleaseNo EntriesIndexing DateGroupAvailability
    |%s%s%d%s%sok
    |%s   %s 
    | } ############################################################################### # # the "Select databanks" or "top" page # # $selectLibrary={ head: | |NEW SRS:Select Libraries Page | | |

    | | submit: | \ |Show only fields that selected databanks have in common |

    | | | | libs:{ html3:{ libGroupName: |


    | %s
    | | newRow: | | library: | | tools:{ fasta: | blast: | } tail: | |
    |%s%s | | | | | |
    } html2:{ libGroupsName: |
            |
    %s

    newRow: '\n' library: | \ |%s\ |%-($parStr:l)s\ tools:{ blast: |\ |Do BLAST Search } tail: |

    } } tail: |
    | |... tired of looking at all those data? Change their color! | \ | colorScheme:{ head: | | | | } } ############################################################################### # # the Page with the library network # # $libNetwork={ head: | | |SRSWWW at ($parStr:siteName): Library Network Distance Table | | | |
    | title: |

    The Library Network shown as a Distance Table

    |
    | | | |
    |

    | fromLib: | | link:{ direct: | indirect: | none: | } rowEnd: | toLibs: | toLib:{ head: | } tail: | |
    %s1%d 
    letter: |%c
    last: |%c\ tail: |
    |

    | | } ############################################################################### # # the information about a pairwise link # $linkInfo={ head: | | |SRSWWW at ($parStr:siteName): Link Information | | | |
    | title: |
    |

    Link Information

    noLink: |A link from %s to %s does not exist. direct: |The link from %s to %s is direct. |

    indirect:{ head: |%d entries in %s are linked to %d entries in %s.
    |The link is indirect and has been resolved to the path "%s>\ pathLib: |%s>\ lastLib: |%s". |

    } table:{ head: | | | | | | | | | names: | | | | | total: | read: | index: | creTime: | notCreated: | rowEnd: | } tail: |
    FromLinked
    Entries
    ToLinked
    Entries
    Total No
    of Links
    Information UsedCreation
    Time
    %s%d%s%d%dCross-references in %s referring to contents of the |%s field in %sMatching strings in the %s field of %s and the %s field in %s.%snot available
    | | } ############################################################################### # # the Query form page # # $queryForm={ head: | | |SRS:Query Form Page | | |

    | | | |

    searchInfo: |Search listLibs: |%s submit: |

    | | chunkSize:{ head: | } selectView:{ head: | } searchOptions: | | |
    |\ | | | |Entry List in chunks of\ | | |Use | |
    | | |Combine searches with \ | | | | | Append wildcard '*' to words. |
    queryInput: { html3: { head: |

    | | | | | fieldHeader: | | fieldNum: | | | | | | | fieldText: | | | | | subEntry: | rowEnd: | tail: |
    |Field NameQueryInclude in List |Retrieve
    Subentries

    |%s
    |%s%s |\ | | | | | | |\ |\ |
    |%s%s | | |\ |\ | # |Subentry only |
    } html2:{ head: |

              |Field Name                                  \
              |Query            \
              |Include in List
            fieldNoQuery:
              |\
              |%s%-%(l)s\
              |inc\
            fieldNum:
      	  |
      	  |\
              |%s%-%(l)s\
      	  |  \
      	  | \
      	  | \
      	  | \
      	  |inc
            fieldText:
              |
              |%s\
              |%-%(l)s\
              | \
              | \
              |\
              |inc\
            subEntry:
              | \
              |sub\
            rowEnd:
              |
            combineWith:
              |
    |
    |Combine searches with \ | | Append wildcard '*' to search words \ |?!

    } } tail: |

    | | } ############################################################################### # # the "Library Information" page # $libInfo={ head: | | | View Select Page | |
    | title: |
    |

    Information about %s

    noRelease: |The current release has %d entries and was indexed %s. release: |The current release %s has %d entries and was indexed %s. notIndexed: |The databank is currently not available. fields:{ head: |

    List of Data-fields

    | | | | | | | | | names: | | | type: | numbers: | | | status: | | notIndexed: | | | | | showField: | | | | | tail: |
    NameShort
    Name
    TypeNo of
    Keys
    No of Entry
    References
    Indexing DateStatus
    %s%s%s%d%d%s%s
       not available
       not indexed
    } links:{ to: |

    Links to Other Databanks

      toLib: |
    • to |%s from: |
    |

    Links from Other Databanks

    |
      fromLib: |
    • from |%s none: |none tail: |
    } tail: | | } ############################################################################### # # the "View Create" page - part I of creating views # $viewCreate={ head: | | | View Select Page | |
    | | | | |
    |
    edit:{ head: |
    | | | |

    |Edit an existing view

    |
    | | | | |or use the | | | |
    |
    } create:{ logo: |

    Create new view

    head: |
    | | | | | } rootHeader: | #view name | | | | | | leafHeader: | | |
    | | | #display as table | | | # print short or long field names in header | | | # common fields only | | | |
    |Name of view (optional)
    | |
    | | |Display view as table |
    | | |Print short field names in header |
    | |Show only fields common
    to selected root databanks |

    |

    | | | |

    | |

    |Select databanks for whose
    entries you want to define
    the view |
    |Select databanks to be linked
    to displayed entries (optional)
    |
    | | | |
    |
    | | } ############################################################################### # # the "select fields" page - part II of creating views # $viewSelectFields={ head: | | NEWSRS View Field Select Page | |

    |

    | | | | | | | | |
    | |

    Select Fields for View "%s"

    |Select fields to be appended to entries displayed and continue with |one of the options below |

    | | | | | | | | | | | | |


    |

    |
    | root:{ lib: | |
    | |%s |
    rowBeg: | rowEnd: | newRow: | fieldHeader: | field: | tail: |

    %s
     \ |\ |%s\ format:{ head: |\ } fieldTail:|
    |

    } leaf:{ head: | | | | | | | | |
    |%30.*s | |%s |
    | | newRow: | fieldHeader: | field: | extraOptions: | |

    %s
    \ | |%s%s format:{ head: | } fieldTail:|
    | | | | | | | # | # | # | # | | | | | | |
    | |Use query |instead link | |
    | selectView:{ head: |use view to display entries | } tail: |
    # |  # | # |Input form for # | # |
    | |Display only number of linked entries |
    |
    | |

    } tail: |

    | | | | | } ############################################################################### # # the queryResult page # $queryResult={ head: | QueryResult | |

    | title: | Query "%s" found %d entries | options: |

    Selected entries: | | | | | | | | | | | | | | | chunkSize:{ head: |Entry list in chunks of \ | } selectView:{ head: | with | } entriesStart: |
    | |
    tail: |

    | | } # to be placed at the bottom of the query result page $chunkSet={ head: |

    | go to entries in chunk | \ |[ .. current: | |(%d).. other: | |%d .. tail: | ] } # |

    ############################################################################### # # # the querymanager page # # # $queryManager={ head: | | NEWSRS Query Manager Page | |
    | | queryOptions:{ html3:{ head: |

    |
    | | | | | | | | | | | | | | | | |
    |Use one of the six options
    on one or more selected queries. |
    | |
    | \ | | | | \ | | | | \ | | |
    | \ | | | | \ | | | | \ | | | |select queries with | |
    |

    queryInfo:{ head: |

    |

    | | | | | | | | | | | | title: | | | numAlign: | | | | | } } html2:{ head: | | | |      |selected queries with |      | |
    | | | |      |selected queries |
    | | | |      |selected query |
    | | | |      | |
    queryInfo: { head: |

    Successful Queries

    |
    |
    title: |
    | |%s |(%s) |:= " %s " |Total %d entries found numAlign: | libAlign: | queryStr: | entryN: |
    %6d entries from %s subEntry: |
    | set of \ |Sequence Features } } } chunkSize:{ head: |Entry list in chunks of \ | } selectView:{ head: |using the view \ | # | } tail: |
    Successful Queries
    NameTypeN
    total |
    |From Library | |N | |Query Expression | |Comment |
    | \ |%s | |%s | |%d | libAlign: | queryStr: | |\ | library: |%s
    \ entryN: |%d
    \ subEntry: | set of \ |Sequence Features rowEnd: |
    |

    |Save in history queries of type |query |expression |link |selection |

    |

    | | } ############################################################################### # # the data-field browse and help page # $dataField={ head: | | |SRSWWW at ($parStr:siteName): Data-field information | | | |
    | title: |

    Browse the Index "%s" of "%s"

    inEntry: |See the %s-field within the example entry description: | browse: |
    | | | | | that |match | |and occur in at least |entries |
    |
    tail: | } ############################################################################### # # the index Value list page # $browseList={ head: | | |
    title: |

    Values in the index of the %s field

    | | | | | | | | | | | | | | |
    |

    values:{ head: | | library: | value: | | | tail: |
    ValueNo. Entries
    Values in %s
    | |%s%d
    |

    |
    | | } } ############################################################################### # # an entry with various formats - to be included into other pages # $entry={ inList:{ envelope:{ head: { preformatted: |
    \
            topicList:    |
    table: | } tail: { preformatted: | topicList: |\ table: |
    } } entry:{ name: |
    | | |%s:%s inListNoId: |
    | |%s:%s rootName: |
    |\ |%s leafName: |
    | | \ |%s head:'' tail:'' } } inTable:{ head: | | title:{ library: | field: | tail: | } entry:{ head: '' tail: '' rootName: | leafName: | value:{ leftAlign: | } emptyValue: | onlyEntryN: | } tail: |
    %s | |%s
    | \ |%s\ | |%s\ | rightAlign: | center: | listing: | value: |%s\ empty: |  next: |
    \ tail: |
    |%d
    } } ############################################################################### # # # the view manager page # # $viewManager={ head: | |:SRS: NEWSRS VIEW Manager Page | |
    | | actions: | |
    |
    | |Click here with middle mouse button |to get an independent View Manager |

    | | | | | | | | | | | | | |
    | | | | |a new view
    | | |selected view
    selected view
    |

    | | | | | | | | | | | | | | | | | | viewList:{ head: | | | | | | format: |(%s) leaf:{ lib: | view: | onlyEntryN: | noComment: | } emptyCell: | separator: |
    rowEnd: | tail: | | } tail: |
    List of Views
    View NameFormatRootLeaves
    LibrariesFieldsLibrariesFieldsQueryViewComment
    | %s | |%s shortNames: |
    (short field names) |
    longNames: | root: |%s
    rootField: |%s
    \ tableData: |
    tableDataEnd: |%s field: |%s
    format: |(%s) query: |
    %s%sdisplay No of linked entries  
    |

    | | } ############################################################################### # # the link page # $linkPage={ head: | | |LINK Page | | |
    | | | | linkType: | | | | | | | | | | | |
    | Find
    all
    entries
    |
    | | |in the selected databanks which are linked to the current set |
    | | |in the current set which are linked to all |selected databanks |
    | | |in the current set which are not linked to any of |the selected |databanks |
    # | # |Display a table with linking statistics
    |

    | | | |

    | html3:{ dbGroup: |


    |%s | | newRow: | | library: | | tail: | |
    %s |%s
    } html2:{ dbGroup: |
          |%s
        newRow:
          |
    library: | \ |%s%-%(l)s \ tail: '' } tail: | | | } ############################################################################### # # the Blast Page to launch a homology search with blast # $blastPage={ head: | | SRS: Blast Search | |
    | | | |

    |BLAST  Search

    |Default values will be used when input fields are unchanged. |
    |Search in | |with Matrix | |

    |Enter Query Sequence |
    | |

    | | | |

    | | # Cutoffs and thresholds | | | | | | | | | | | | | | # things to include | | | | | | | | | | | | | # filtering | | | | # sorting of hits | | | | # use | | | | | | | | | | | |
    Thresholds |Exp Threshold (E) | | |Exp Number of HSPs (E2) | |
    |Cutoff Value (S) | | |Exp Score for MSP (S2) | |
    | | |Limit number of HSPs | reported | |Word length | |
    |Adjust query sequence coordinate numbers by |qoffset | |
    Include |Histogram | |General Information | high-scoring alignments |
    | |Include one line description for | entries | | |filtered query sequence |
    | |HSPs |not statistically significant |
    Filter | | | | | |
    Short Repeat |Low Complexity Sequences Both None
    Sort By | | | | | |
    PValue Count High Score | Total Score |
    Use | |Use sum statistics | | |Use Poisson statistics |
    | |Consistency | | |Span2 | | |Span1 | | |Span |
    |

    | | } ############################################################################### # # the script to run the blast query # $blastScript={ body: |#!/bin/csh -f |# |# |# blast command file |# |# |source /data/bin/prepare_proteins.csh;\ |cd \$SRSWWWTMP/($parStr:userId);%s |# |# |sed -n '/^>/q;p' tmp.blast |# Create SRS indices for blast |# |# |setenv SRSADMN 1 |(source \$SRSETC/prep_srs;\ |cd \$SRSWWWTMP/($parStr:userId);\ |\$SRSEXE/srsbuild blast;\ |\$SRSEXE/srsbuild -c blast;\ |\$SRSEXE/srsbuild -l blast ) >& /dev/null |exit | } ############################################################################### # # the Blast result page # $blastResult={ head: |Blast Output |
    | | | | | | | |
    |
    }
    
    
    ###############################################################################
    #
    # the "buttons" part that most pages have at the top
    #
    $buttons={
      head:
        |
      help: {
        head:
          |
      }
      databank:
        |
      selectDatabanks:
        |
      queryForm:
        |
      queryManager:
        |
      oops:
        |
      views:
        |
    |Help
    | | | | | | | | | | | | | | | | | tail: |
    |
    } ############################################################################### # # messages printed during execution # $messages={ head: | | parseError: | | | | |
    |
    %s
    %s
    error: | | | | |
    |
    %s
    %s
    info: |

    Information:

    |%s, %s

    } ################################################################# # # arglist # $argListOption={ header: |

    option: |
    %s |
    %s |

    } ############################################################################### # # link set result # $linkSet={ head: | | SRS link result page | |

    | tableHead: | | | | | | | | libName: | libEntriesH: | libEntries: | endRow: | newRow: | tail: |
    Link result for the set %s
    Selected Databanks Entries in set
    Linked with Databanks
    Databank entries
    Linked with set
    Entries in set
    NOT |
    linked with Databank
    |   | %s %d %d
    |

    |

    | | } ############################################################################### # # # the refine output page # # $downloadSet={ head: | | | SRS:Download query | | |
    | | inputInfo:{ html3:{ shift: |

    |Additional options for saving sequence features: |

    | | |
    | | | | | | | | |
    shift begin | |shift end | |
    | | | |
    } html2:{ shift: |
    |
               |shift begin \
               | \
               |		       shift end \
               |
               | \
               |
               |
    |

    | } } unComplete: | \ |reject incomplete features |
    |\ |reject incomplete shifted features |

    |
    seqFormat: |
    |List sequences with | |format. |
    mime:{ head: |
    |Download chunk with entries | } useMime: |
    | Use MIME type |(for downloading the result to your local directory!) |
    |Local Directory Name
    tail: |If you do not have client support srsmime, fetch a copy of |\ |srsmime.c |
    | |
    | | | |
    | | } #################################################################################### # # # the list refined page # $listRefined={ head: |Content-type: application/srsresult | | | start: |>>>>>>>%s;%s;%s;%s;%s<<<<<<< } ################################################################################### # # # the fasta input form page # # $prepFasta={ head: | | | SRS: FASTA Search |
    | tail: |

    |FASTA  Search

    |

    | | | | | | | | | | | | | | | | | | | |
    Select Options
    Select Databank Word size
    (k-tuple)
    Number of Sequences
    to be listed
    Number of Best Scores
    to be listed
    | | | | | | | |
      
    Enter query sequence
    |
    | |
    |
    |Note: | Default values will be used when input fields are unchanged. |
    |

    | | | | |

    | | } $fastaResult={ head: |

    |

    ... in preparation ...

    } ############################################################################### # # # # $fastaScript={ body: |#!/bin/csh -f |# |# |# fasta command file |# |# |source /opt/gcg/gcgstartup; |source /opt/gcg/genetics; |cd \$SRSWWWTMP/($parStr:userId);%s |# |# print some info |# |sed -n '/SCORES/q;p' tmp.fasta |# |# Create SRS indices for fasta |# |# |(source \$SRSETC/prep_srs;\ |cd \$SRSWWWTMP/($parStr:userId);\ |\$SRSEXE/srsbuild fasta;\ |\$SRSEXE/srsbuild -c fasta;\ |\$SRSEXE/srsbuild -l fasta ) >& /dev/null |exit | } $fastaResult={ head: |FASTA Output |
    | | | | | | |
    |
    }
    
    
    #    $RCSfile: syntax.ic,v $
    #    $Revision: 1.2 $
    #    $Date: 1996/07/24 22:07:19 $
    #    $Author: etzold $
    #
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    $SMxMIXCASE=0
    $SMxLOWCASE=4
    $SMxUPCASE=2
    
    O_SYNTAX:$object:[name:Syntax typname:ICAoSYNTAX declname:syntax
      ppname:SRS attrs:{
        $attribute:[name:name declname:name type:string valtype:{name text}
          required:n rem:"Name of the syntax."]
        $attribute:[name:file declname:fileName type:string 
          rem:"Name of the Icarus file with the production list."]
        $attribute:[name:rules declname:rules type:string 
          rem:"Pointer to the production list."]
        $attribute:[typname:"struct SMoBUFF_" declname:"*buff" type:user 
          rem:"Name of the file with ICA rules"]
        $attribute:[name:commandSyntax declname:commandSyntax type:object 
          defaultval:@O_SYNTAX required:n valtype:constant status:obsolete
          rem:"The syntax of for the commands"]
        $attribute:[typname:"struct ICAoNAMELIST" declname:"*prodList" type:user
          rem:"List of productions"]
        $attribute:[typname:"struct ICAoCOMMAND" declname:"*userCommand" type:user]
        $attribute:[typname:"struct taskList" type:user declname:"*taskList"]
        $attribute:[name:ignore declname:ign type:string defaultstr:" " max:20
          valtype:text
          rem:|
            |String containing characters to be ignored or skipped during 
            |parsing (white space).
        ]
        $attribute:[name:comment declname:lf type:string defaultstr:"" max:50 
          valtype:text 
          rem:"A regular expression to skip comments."]
        $attribute:[name:level3 declname:linkFlag type:uchar 
          status:obsolete defaultval:1]
        $attribute:[declname:"*prod" typname:"struct VARo" type:user]
        $attribute:[declname:"*scope" typname:"struct VARoSCOPE" type:user]
        $attribute:[declname:"*cmntRe" typname:"struct regexp" type:user]
        $attribute:[declname:"ignAlt" type:string]
      }
    ]
    
    $geneticCode:["Standard" code:SGC0 id:1 
      ncbieaa: "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------" 
    ]
    $geneticCode:["Vertebrate Mitochondrial" code:SGC1 id: 2
      ncbieaa: "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSS**VVVVAAAADDEEGGGG" 
      sncbieaa:"--------------------------------MMMM---------------M------------" 
    ]
    $geneticCode:["Yeast Mitochondrial" code:SGC2 id:3
      ncbieaa: "FFLLSSSSYY**CCWWTTTTPPPPHHQQRRRRIIMMTTTTNNKKSSRRVVVVAAAADDEEGGGG" 
      sncbieaa:"-----------------------------------M----------------------------" 
    ]
    $geneticCode:["Mold Mitochondrial; Protozoan Mitochondrial; Coelenterate Mitochondrial; Mycoplasma; Spiroplasma"
      code:SGC3 id: 4
      ncbieaa: "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG" 
      sncbieaa:"--MM---------------M------------MMMM---------------M------------" 
    ]
    $geneticCode:["Invertebrate Mitochondrial"  code:SGC4 id:5
      ncbieaa: "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSSSSVVVVAAAADDEEGGGG"
      sncbieaa:"---M----------------------------M-MM---------------M------------"
    ]
    $geneticCode:["Ciliate Macronuclear; Dasycladacean Nuclear" code:SGC5 id:6
      ncbieaa: "FFLLSSSSYYQQCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------"
    ]
    $GeneticCode:["Echinoderm Mitochondrial" code:SGC8 id:9
      ncbieaa: "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNNKSSSSVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------"
    ]
    $geneticCode:["Euplotid Macronuclear" code:SGC9 id: 10
      ncbieaa: "FFLLSSSSYY**CCCWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------"
    ]
    $geneticCode:["Bacterial" id:11 
      ncbieaa: "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
      sncbieaa:"---M---------------M------------M--M---------------M------------"
    ]
    $geneticCode:["Alternative Yeast Nuclear" id:12
      ncbieaa: "FFLLSSSSYY**CC*WLLLSPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
      sncbieaa:"-------------------M---------------M----------------------------"
    ]
    $geneticCode:["Ascidian Mitochondrial" id:13
      ncbieaa: "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSSGGVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------"
    ]
    $geneticCode:["Flatworm Mitochondrial" id:14
      ncbieaa: "FFLLSSSSYYY*CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNNKSSSSVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------"
    ]
    $geneticCode:["Blepharisma Macronuclear" id:15
      ncbieaa: "FFLLSSSSYY*QCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG"
      sncbieaa:"-----------------------------------M----------------------------"
    ]
    
    
    $object:[name:function declname:"X" 
      status:system 
      attrs:{ 
        $attribute:[name:name type:protofunction declname:"fnctnam" 
          max:30 valtype:text] 
        $attribute:[name:args type:string declname:"args" 
          max:132 valtype:text required:y] 
        $attribute:[name:module type:string declname:"module" max:30] 
      }
    ] 
    
    $object:[name:geneticCode  typname:"SEQoTranslTable" declname:translTable 
      attrs:{ 
        $attribute:[name:name type:string declname:name unnamed:y 
          rem:"Name of translation table." required:y] 
        $attribute:[name:code type:string declname:code unnamed:y 
          rem:"Short name of translation table."] 
        $attribute:[name:id type:int declname:id 
          rem:"Numeric id."] 
        $attribute:[name:ncbieaa type:string declname:"aa" required:y 
          rem:"Amino acid encoded by triplett."] 
        $attribute:[type:string declname:"aaAlt" 
          rem:"Alternative (edited) Amino acid encoded by triplett."] 
        $attribute:[name:sncbieaa type:string declname:"saa" required:y 
          rem:"Amino acid encoded by triplett at translation start."] 
      }
    ] 
    
    
    
    $def:[infile:"SRSICA:srswin.sdl" outfile:"SRSSOU:transl.h" 
      section_name:"builtin" section_size:2000 
    ]
    
    
    
    
    /srs/index
    
    
    
    
    /srs/src
    
     22:48:07 1996//
    /arglist.h/1.1/Mon May  6 15:16:17 1996//
    /auxinfo.c/1.1/Mon May  6 15:16:18 1996//
    /binpack.h/1.1/Mon May  6 15:16:18 1996//
    /blub.c/1.4/Wed Jul  3 16:45:33 1996//
    /blub.h/1.3/Wed Jul  3 16:45:34 1996//
    /bnf2c.c/1.5/Thu Jul 18 09:10:20 1996//
    /btree.c/1.4/Mon Aug 12 19:03:44 1996//
    /btree.h/1.2/Wed May  8 00:19:34 1996//
    /builtin.h/1.13/Mon Aug 12 11:21:58 1996//
    /cursor.c/1.7/Fri Jul 26 21:15:24 1996//
    /cursor.h/1.3/Fri Jul 26 21:15:35 1996//
    /def.c/1.1/Mon May  6 15:16:23 1996//
    /def.h/1.1/Mon May  6 15:16:24 1996//
    /dict.c/1.6/Sun Aug 11 22:47:02 1996//
    /dict.h/1.2/Sun Aug 11 22:47:02 1996//
    /entry.c/1.13/Wed Aug 14 16:19:26 1996//
    /entry.h/1.4/Sun Aug 11 22:47:03 1996//
    /error.c/1.2/Mon May  6 19:20:32 1996//
    /error.h/1.2/Mon May  6 19:20:33 1996//
    /futil.c/1.15/Mon Aug 12 20:24:26 1996//
    /futil.h/1.6/Mon Aug 12 20:24:27 1996//
    /gd.c/1.1/Mon May  6 15:16:31 1996//
    /gd.h/1.1/Mon May  6 15:16:32 1996//
    /getz.c/1.5/Sun Aug 11 22:47:04 1996//
    /hash.c/1.1/Mon May  6 15:16:33 1996//
    /hash.h/1.1/Mon May  6 15:16:34 1996//
    /ica.c/1.2/Thu Jul 18 09:10:23 1996//
    /ica2c.c/1.6/Sun Jul 14 16:21:14 1996//
    /ica2c.h/1.1/Mon May  6 15:16:35 1996//
    /icaarg.c/1.4/Sun Jul  7 10:59:24 1996//
    /icaarg.h/1.2/Tue Jul  9 20:38:13 1996//
    /icabnf.c/1.13/Mon Aug 12 11:21:59 1996//
    /icabnf.h/1.4/Sun Aug 11 22:47:05 1996//
    /icadebug.c/1.1/Sun Aug 11 22:58:33 1996//
    /icadebug.h/1.1/Sun Aug 11 22:58:35 1996//
    /icainit.c/1.12/Tue Aug 13 13:42:46 1996//
    /icaop.c/1.19/Tue Aug 13 13:42:48 1996//
    /icaprog.c/1.3/Sun Aug 11 22:47:08 1996//
    /icaprog.h/1.1/Mon May  6 15:16:41 1996//
    /icarus.c/1.13/Sun Aug 11 23:24:13 1996//
    /icarus.h/1.8/Sun Aug 11 22:47:09 1996//
    /icarusi.c/1.1/Sun Aug 11 23:24:14 1996//
    /icatask.c/1.1/Mon May  6 15:16:43 1996//
    /icatask.h/1.1/Mon May  6 15:16:44 1996//
    /id.c/1.2/Sun Aug 11 22:47:10 1996//
    /id.h/1.2/Sun Aug 11 22:47:11 1996//
    /ids.c/1.3/Sun Aug 11 22:47:12 1996//
    /ids.h/1.2/Sun Aug 11 22:47:12 1996//
    /idx.c/1.1/Mon May  6 15:16:47 1996//
    /idx.h/1.1/Mon May  6 15:16:48 1996//
    /index.c/1.5/Mon Aug 12 19:03:45 1996//
    /index.h/1.1/Mon May  6 15:16:49 1996//
    /library.c/1.12/Sun Aug 11 22:47:14 1996//
    /library.h/1.8/Sun Aug 11 22:47:15 1996//
    /link.c/1.11/Wed Aug 14 16:19:28 1996//
    /link.h/1.3/Sun Aug 11 22:47:16 1996//
    /listv.c/1.1/Thu Jun 20 15:03:50 1996//
    /listv.h/1.1/Thu Jun 20 15:03:51 1996//
    /local.c/1.1/Mon May  6 15:16:52 1996//
    /logicals.c/1.1/Mon May  6 15:16:53 1996//
    /logicals.h/1.1/Mon May  6 15:16:54 1996//
    /lst.c/1.2/Tue Jul  9 20:38:20 1996//
    /lst.h/1.1/Mon May  6 15:16:55 1996//
    /map.c/1.1/Mon May  6 15:16:56 1996//
    /map.h/1.1/Mon May  6 15:16:57 1996//
    /message.c/1.2/Wed May  8 00:19:38 1996//
    /message.h/1.11/Sun Aug 11 22:47:17 1996//
    /mi.c/1.1/Tue Jun 25 15:11:22 1996//
    /mi.h/1.1/Tue Jun 25 15:11:23 1996//
    /msg.h/1.2/Wed May  8 00:19:39 1996//
    /msgdef.c/1.2/Tue Jul  9 23:38:09 1996//
    /nodd.c/1.7/Tue Jul 30 10:48:29 1996//
    /ntry.c/1.1/Mon May  6 15:17:00 1996//
    /odd.c/1.1/Mon May  6 15:17:00 1996//
    /odd.h/1.3/Tue Jul 30 10:48:29 1996//
    /oddclass.h/1.2/Tue Jul 30 10:48:30 1996//
    /oddfncts.c/1.2/Sun Jun 16 17:59:40 1996//
    /oddfnctsnew.c/1.3/Tue Jul 30 10:48:30 1996//
    /oddtools.c/1.1/Mon May  6 15:17:04 1996//
    /oddtools.h/1.1/Mon May  6 15:17:05 1996//
    /oldlistbuf.c/1.1/Mon May  6 15:17:06 1996//
    /oldlistbuf.h/1.1/Mon May  6 15:17:07 1996//
    /par.c/1.3/Sun Jul 14 16:21:23 1996//
    /par.h/1.2/Sun Jul 14 16:21:24 1996//
    /print.c/1.3/Mon Jun 24 16:32:59 1996//
    /print.h/1.4/Mon Jun 24 16:26:15 1996//
    /query.c/1.8/Mon Aug 12 19:03:46 1996//
    /query.h/1.1/Mon May  6 15:17:10 1996//
    /queryass.c/1.5/Sun Jul 14 16:21:25 1996//
    /queryass.h/1.2/Mon Jun 24 13:46:51 1996//
    /regexp.c/1.1/Mon May  6 15:17:12 1996//
    /regexp.h/1.1/Mon May  6 15:17:13 1996//
    /regmagic.h/1.1/Mon May  6 15:17:14 1996//
    /regsub.c/1.1/Mon May  6 15:17:14 1996//
    /sdlget.c/1.1/Mon May  6 15:17:15 1996//
    /sdlget.h/1.1/Mon May  6 15:17:15 1996//
    /sdlnew.c/1.8/Sun Aug 11 22:47:18 1996//
    /seq.c/1.6/Tue Jul 30 10:48:32 1996//
    /seq.h/1.1/Mon May  6 15:17:17 1996//
    /seqlib.c/1.2/Mon May  6 19:20:52 1996//
    /seqlib.h/1.1/Mon May  6 15:17:19 1996//
    /set.c/1.5/Sun Aug 11 22:47:19 1996//
    /set.h/1.4/Sun Aug 11 22:47:20 1996//
    /sm.c/1.4/Mon Aug 12 19:03:47 1996//
    /sm.h/1.1/Mon May  6 15:17:22 1996//
    /srs.h/1.4/Sun Aug 11 22:47:21 1996//
    /srs5.h/1.10/Sun Aug 11 22:47:22 1996//
    /srsbuild.c/1.9/Mon Aug 12 19:03:47 1996//
    /srscheck.c/1.6/Mon Aug 12 20:24:29 1996//
    /srspict.c/1.1/Mon May  6 15:17:26 1996//
    /srswww.c/1.15/Sun Aug 11 22:47:25 1996//
    /srswww.h/1.8/Sun Aug 11 22:47:25 1996//
    /strv.c/1.19/Tue Aug 13 13:42:49 1996//
    /strv.h/1.8/Tue Jul 16 17:05:15 1996//
    /templ.c/1.17/Mon Aug 12 20:24:29 1996//
    /templ.h/1.8/Mon Aug 12 20:24:30 1996//
    /tm.c/1.1/Mon May  6 15:17:31 1996//
    /tm.h/1.1/Mon May  6 15:17:31 1996//
    /toklist.c/1.12/Wed Aug 14 16:19:29 1996//
    /toklist.h/1.6/Fri Jul 26 21:15:42 1996//
    /transl.h/1.1/Mon May  6 15:17:33 1996//
    /trembl.c/1.1/Mon May  6 15:17:34 1996//
    /try.c/1.5/Wed Jul 24 22:48:22 1996//
    /tryblub.c/1.1/Wed Jul  3 16:48:10 1996//
    /unix_map.c/1.2/Mon Jun 24 13:47:02 1996//
    /variable.c/1.10/Sun Aug 11 23:24:14 1996//
    /variable.h/1.4/Sun Aug 11 22:47:27 1996//
    /view.c/1.9/Sun Aug 11 22:47:28 1996//
    /view.h/1.8/Sun Aug 11 22:47:29 1996//
    /wgetz.c/1.22/Sun Aug 11 22:47:30 1996//
    
    
    
    /srs/src/omtest
    
    01:58 1996//
    /tryblub.c/1.1.1.1/Fri Jul  5 15:01:58 1996//
    
    	gcc -g -w -o try blub.c tryblub.c strv.c parse.c mi.c dict.c def.c
    
    trygen: blub.c trygen.c mystr.c parse.c mi.c dict.c /home/srs/srs5/src/def.c
    	gcc -g -w -o trygen -I/home/srs/srs5/src blub.c trygen.c mystr.c parse.c mi.c dict.c /home/srs/srs5/src/def.c
    
    tryget: blub.c tryget.c mystr.c parse.c mi.c dict.c /home/srs/srs5/src/def.c
    	gcc -O3 -w -o tryget -I/home/srs/srs5/src blub.c tryget.c mystr.c parse.c mi.c dict.c /home/srs/srs5/src/def.c
    
    slist: slist.c tryslist.c
    	cc -g -o try -I/home/srs/srs5/src slist.c tryslist.c mycomdef.c
    
    #include "strv.h"
    #include "blub.h"
    
    typedef struct TRYOBJ {
      OBJo head;
      int a;
      STRv b;
      struct TRYOBJ* part;
    } TRYOBJ;
    
    typedef struct TRYMORE {
      TRYOBJ head;
      STRv more;
      ListAttr list;
      int arr[10];
    } TRYMORE;
    
    
    int main() {
        TRYOBJ* o=ObjCpy(Object);
        TRYOBJ* o1,*oc;
        TRYMORE* o2;
        void *r1, *r2, *r3,*a1; 
        AttrIter ai; Iter i;
        int* list;
        OBJpStream s;
        ObjInit();
        ObjAttrNew(&o, StrTemp("a"), int)=3;
        ObjAttrNew(&o, StrTemp("b"), STRv)=StrCpyS("ciao");
        ObjAttrNewRef(&o, StrTemp("part"),TRYOBJ*)=NULL;
        ObjPrint(o); printf("\n");
        ObjMakeClass(o,StrTemp("TRYOBJ"));
        o1=ObjCpy(o);
        ObjChange(&o1,TRYOBJ*);
        o1->part=ObjCpy(o);
        ObjChange(&ObjChange(&o1, TRYOBJ*)->part, TRYOBJ*)->a=10;
        o1->a=5;
        StrSetS(&o1->b,"containing");
        o2=ObjCpy(o1);
        ObjAttrNew(&o2,StrTemp("more"),STRv)=StrCpyS("someMore");
        list=&ObjListNew(&o2,4,int);
        *list++=1;
        *list++=2;
        *list++=3;
        *list++=4;
        ObjDebug(o);
        ObjDebug(o1); 
        ObjDebug(o2);
        ObjMakeClass(o2,StrTemp("TRYMORE"));
        ObjListApp(&o2,int)=6;
        ObjListApp(&o2,int)=7;
        ObjDebug(o2);
        ObjListCut((void**)&o2,ObjListWith(o2,1),3);
        ObjDebug(o2);
        /* try access by name */
        printf("%d %s\n", ObjAttr(o,StrTemp("a"),int),
    	Str(ObjAttr(o,StrTemp("b"),STRv)));
        printf("%d %s\n", ObjAttr(o1,StrTemp("a"),int),
    	Str(ObjAttr(o1,StrTemp("b"),STRv)));
        printf("%d %s\n", ObjAttr(o2,StrTemp("2"),int),
    	Str(ObjAttr(o2,StrTemp("more"),STRv)));
        /* attribute iteration */
        printf("iterating:\n");
        for (ai=ObjAttrFirst(o2); ai; ObjAttrNext(o2,&ai)) {
            STRv name=ObjAttrName(o2,ai);
            printf("%s\n",Str(name));
    	StrDel(name);
        }    
        /* testing list iteration */
        printf("list:\n");
        for (i=ObjListFirst(o2);i;ObjListNext(o2,&i)) {
            printf("%i:%i\n",ObjListPos(o2,i),ObjListIn(i,int));
        }
        printf("%d",ObjListCard(o2));
        
        PathInit();
        oc=ObjCpy(o1);
        r1=PathStaticImpl(theRoot,StrTemp("o"),&o,OBJvClass,NULL);
        r2=PathStaticImpl(theRoot,StrTemp("o1"),&o1,OBJvClass,NULL);
        r3=PathStaticImpl(theRoot,StrTemp("o2"),&o2,OBJvClass,NULL);
        a1=Path("o1.part.a"); PathCompileImpl(a1);
        PathChange(a1, int)=6;
        ObjDebug(o1); ObjDebug(oc);
        
        /* try stream output */
        printf("\n-----------------saving\n");
        ObjDebug(o); ObjDebug(o1); ObjDebug(o2); ObjDebug(oc);
        PathPrint(a1);
        s=ObjStreamOpen("blabla","wb",TRUE);
        ObjStore(o, s); 
        ObjStore(o1, s);
        ObjStore(o2, s);
        ObjStore(oc, s);
        RefStore(a1,s);
        ObjStreamClose(s);
        
        /* try stream input */
        s=ObjStreamOpen("blabla","rb",TRUE);
        ObjSet(&o, ObjLoad(s));
        ObjSet(&o1, ObjLoad(s));
        ObjSet(&o2, ObjLoad(s));
        ObjSet(&oc,ObjLoad(s));
        ObjSet(&a1,RefLoad(s));
        ObjStreamClose(s);
        ObjDebug(o); ObjDebug(o1); ObjDebug(o2); ObjDebug(oc);
        PathPrint(a1);
    
        /* release everything */
        ObjDel(o); ObjDel(o1); ObjDel(o2); 
        ObjDel(oc);
        ObjDel(a1); ObjDel(r1);
    }
    
    
    char arglist_ID[] = "$Id: arglist.c,v 1.3 1996/07/24 22:48:07 etzold Exp $";
    /*
    **
    **    $RCSfile: arglist.c,v $
    **    $Revision: 1.3 $
    **    $Date: 1996/07/24 22:48:07 $
    **    $Author: etzold $
    **
    **    $Locker:  $
    **    $State: Exp $
    **
    */
    /*      arglist - command line argument processor for C programs
     * 
     * See getargs.doc and header file for full explanation
     * (C)  Copyright 1985, Allen I. Holub.  All rights reserved.
     * This program may be copied for personal, non-profit use only
     * 
     * history...
     * 
     * May 1985     published in Dr. Dobb's Journal #103.
     * 19 May 85    Transcribed by James R. Van Zandt
     * Oct 1993     Extended/modified by Philip lijnzaad@embl-heidelberg.de
     *
     * ------------------------------------------------------------------ *
     *								      *
     * Permission to copy all or part of this work is granted, provided   *
     *  that this NO WARRANTY and this copyright notice are retained      *
     *  verbatim and are displayed conspicuously.  If anyone needs other  *
     *  permissions that aren't covered by the above, please contact the  *
     *  author.							      *
     *								      *
     * NO WARRANTY: THIS WORK IS PROVIDED ON AN "AS IS" BASIS.  THE       *
     *  AUTHOR PROVIDES NO WARRANTY WHATSOEVER, EITHER EXPRESS OR         *
     *  IMPLIED, REGARDING THE WORK, INCLUDING WARRANTIES WITH THE WORK,  *
     *  INCLUDING WARRANTIES WITH RESPECT TO ITS MERCHANTABILITY OR       *
     *  FITNESS FOR ANY PARTICULAR PURPOSE.				      *
     *								      *
     *								      *
     * ------------------------------------------------------------------ */
    
    #include 
    #include  
    #include 
    #include 
    
    
    #include "message.h"
    #include "futil.h"
    #include "par.h"
    #include "sm.h"
    
    #define _SRS
    #define _SLB
    #include SRSINCLUDE
    #include "arglist.h"
    
    typedef void (*PFV)(void);
    typedef void (*PFS)(char*);
    
    #define USAGE_MESSAGE "Usage:"
    
    #define OPT_FIRSTCHAR "-+"		/* first chars that imply an option */
    
    #define ERR_EXIT_STATUS 1		/* exit status upon user error */
    #define INT_ERR_EXIT_STATUS 2		/* exit status upon internal error */
    
    
    enum arg_type {ARGxPARAMETER, ARGxHELP, ARGxTITLE};
    
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  external, global and module wide variables
    */
    
    static INT4 (*print)(char *,...)=NULL; /* function for printing errors */
    static INT4 boolval;			/* used in setarg */
    static INT4 help=0;
    char * usage_message;			/* printed by ArgUsage; user-setable */
    
    /* BCB */
    /* static INT4 (*myexit)(INT4); */      /* function for handling errors */
    /*
    #define exit myexit
    */
    /* end BCB */
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  prototypes of static functions
    */
    
    static INT4 ArgSet (arg_t *argp, char **argv);
    static arg_t *ArgFind (char * name, ARGoLIST *arglist);
    
    
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  default function for printing lines
    */
    
    static INT4 ArgPrintMessage (char *formatStr, ...)
    {
        va_list ap;
    
        va_start (ap, formatStr);
        vfprintf (stdout, formatStr, ap);
        va_end (ap);
        return 1;
    }
    
    
    /****** ArgSet ****************************************************************
    **
    **      set an argument.  argp points at the argument table entry corresponding
    **      to argv[0]. Returns number of items that now can be taken out of
    **      argument list, ie. 1 for BOOLEAN and PROC, 2 for rest, and 0 for
    **      error 
    ** 
    ** 	INPUT:	    name [R]
    ** 		    arglist object [R]
    ** 	        IMPLICIT:
    **                  help (int) [W]
    **                  boolval (int) [R]
    ** 
    ** 	RETURNS:    returns pointer to argument object
    */ 
    
    static INT4 ArgSet (arg_t *arg, char **argv) 
    {
      PARo  *par;
      INT4  parType, rv;
      char *cp;
    
      if (arg->type == ARGxHELP) {
        help=1;
        return (0);
      }
    
      if (!(par = ParGetWrite (arg->parameter, NULL)))
        _ErrExit2 (e__parnotdefined, arg->parameter);
      
      if ((parType = ParOGetType (par)) & PARxBOOL) {
        ParODefNum (par, boolval);  
        return 1;
      }
    
      /* was added for the new SRSWWW ...transmitting function names */
    
      if ((parType = ParOGetType (par)) == PARxSTR && *arg->defaultStr) { 
        ParODefStr (par, arg->defaultStr);  
        return 1;
      }
      /* was added for the new SRSWWW ...transmitting function names */
    
      else if (parType == PARxNUM && arg->defaultNum) { 
        ParODefNum (par, arg->defaultNum);  
        return 1;
      }
    
    
      /* following functions all need a value, so see if it's there: */
    
      if ( (! argv[1]) || (!argv[1][0] ) ) {
        print ("option %s needs additional argument", argv[0]);
        return(0);
      }
    
      switch (parType) {
    
      case PARxNUM:
        rv = ParODefNum (par, strtol (argv[1], &cp, 0));
        if (_ErrIs (rv))
          exit (INT_ERR_EXIT_STATUS);
        if (*cp) {
          print ("malformed integer: %s\n", argv[1]); 
          return 0; 
        }
        return 2;
    
      case PARxSTR:
        rv = ParODefStr (par, argv[1]);
        if (_ErrIs (rv))
          exit (INT_ERR_EXIT_STATUS);
        return 2;
    
      case PARxREAL:
        rv = ParODefReal (par, strtod (argv[1], &cp));
        if (_ErrIs (rv))
          exit (INT_ERR_EXIT_STATUS);
        if (*cp) {
          print ("malformed double: %s\n", argv[1]); 
          return 0; 
        }
        return 2;
    
      default:
        break;
      }
    
      print ("getargs internal error: bad argument type %d for %s in %s %s\n", 
    	 parType, par->name, argv[0], argv[1]);
      exit (INT_ERR_EXIT_STATUS);
      return 1; /* compilers ..please shut up!*/
    } 
    
    
    
    /****** ArgFind ***************************************************************
    **
    ** 	searches an argument in the table by name
    ** 
    ** 	INPUT:	    name [R]
    ** 		    arglist object [R]
    ** 	        IMPLICIT:
    ** 
    ** 	RETURNS:    returns pointer to argument object
    */ 
    
    static arg_t *ArgFind (char * name, ARGoLIST *arglist) 
    {
      arg_t *arg;
      INT4   k;
    
      for (k=0 ; k < arglist->argN; k++) {
        arg = &arglist->arg[k];
        if (arg->type != ARGxTITLE && ! strcmp (arg->name, name) )
          return (arg);
      } 
      return (NULL);
    } 
    
    
    /**api* ArgUsageBuild *********************************************************
    **
    ** 	prints a list with all commmand line options
    ** 
    ** 	INPUT:	    address of symboltable [R]
    ** 		    address of file descr. [W]
    ** 	        IMPLICIT:
    **                  help (int) [R]
    ** 
    ** 	RETURNS:    1
    */ 
    
    char *ArgUsageBuild (ARGoLIST *arglist) 
    {
      static char usageStr[512];
      PARo  *par;
      arg_t *arg;
      char  tmp[80], *tmpPtr;
      INT4  k, isBoolOpts=0;
      
      sprintf (usageStr, "Usage: %s", arglist->name);
      strcpy (tmp, "[-");
    
      /*
      ** collect all boolean options ...should be all optional and one letter names
      */
    
      for (k=0; k < arglist->argN; k++) {
        arg = &arglist->arg[k];
        if (arg->type == ARGxPARAMETER) {
          par = ParGetRead (arg->parameter, NULL);
          if (ParOGetType (par) & PARxBOOL && strlen (arg->name) == 2) {  
    	isBoolOpts = 1;
    	sprintf (tmp, "%s%s", tmp, &arg->name[1]);
          }
        }
      }
      if (isBoolOpts)
        sprintf (usageStr, "%s %s]", usageStr, tmp);
    
      /*
      ** now the others
      */
    
      for (k=0, tmpPtr=usageStr; k < arglist->argN; k++) {
        arg = &arglist->arg[k];
        if (arg->type == ARGxPARAMETER) {
          par = ParGetRead (arg->parameter, NULL);
          if (ParOGetType (par) & PARxBOOL || strlen (arg->name) > 2) {
    	if (ParOGetType (par) == PARxBOOL)
    	  sprintf (tmp, "[%s]", arg->name);
    	else
    	  sprintf (tmp, "[%s %s]", arg->name, par->name);
    
    
    	if (strlen (tmp) + strlen (tmpPtr) > 79) {
    	  tmpPtr = &tmpPtr[ strlen (tmpPtr) ];  /* begin of next line */
    	  sprintf (usageStr, "%s\n          %s", usageStr, tmp);
    	}
    	else 
    	  sprintf (usageStr, "%s %s", usageStr, tmp);
          }
        }
      }
    
      /*
      ** and the rest of the command line specified in the ODD file
      */
    
      if (strlen (arglist->usage) + strlen (tmpPtr) > 79) 
        sprintf (usageStr, "%s\n          %s", usageStr, arglist->usage);
      else 
        sprintf (usageStr, "%s %s", usageStr, arglist->usage);
    
      
      return usageStr;
    }
    
    /**api* ArgUsage **************************************************************
    **
    ** 	prints a list with all commmand line options
    ** 
    ** 	INPUT:	    address of symboltable [R]
    ** 		    address of file descr. [W]
    ** 	        IMPLICIT:
    **                  help (int) [R]
    ** 
    ** 	RETURNS:    1
    */ 
    
    void ArgUsage (ARGoLIST *arglist) 
    {
      PARo    *par;
      arg_t   *arg;
      SMoBUFF *buff;
      char    assign[40], tmp[132], *str;
      INT4    k;
    
      print ("%s\n\n", ArgUsageBuild (arglist));
    
      /* this is an error, not a HELP type */
    
      if (!help) { 
        print ("Info: %s -help\n", arglist->name);
        return;
      }
    
      buff = BuffNew (80);
    
      for (k=0; k < arglist->argN; k++) {
        arg = &arglist->arg[k];
        if (arg->type == ARGxPARAMETER) {
          par = ParGetRead (arg->parameter, NULL);
          BuffReset (buff);
          switch (ParOGetType (par))  {
          case PARxBOOL:
    	BuffPrintF (buff, "  %-20s[%s] %s\n", arg->name, 
    		 ParOGetNum (par) ? "TRUE" : "FALSE", par->comment);
    	break;
          case PARxNUM:
    	sprintf (assign, "%s ", arg->name);
    	BuffPrintF (buff, "  %-20s[%d] %s\n", assign, ParOGetNum (par),
    		    par->comment);
    	break;
          case PARxSTR:		
    	sprintf (assign, "%s ", arg->name);
    	if ((str = ParOGetStr (par)))
    	  sprintf (tmp, "[\"%s\"]" , str);
    	BuffPrintF (buff, "  %-20s%s %s\n", assign, str ? tmp : "",
    		    par->comment);
    	break;
          case PARxREAL:		
    	sprintf (assign, "%s ", arg->name);
    	BuffPrintF (buff, "  %-20s[%f] %s\n", assign, 
    		    ParOGetReal (par), par->comment);
    	break;
          }
          print (BuffFormat (buff, 80, 0, 22, NULL));
        }
    
        else if (arg->type == ARGxTITLE)
          print ("\n%s\n\n", arg->name);
        else if (arg->type == ARGxHELP)
          print ("  %-20s%s\n", arg->name, arg->comment);
      }
    } 
    
    
    /**api* ArgGet ***************************************************************
    **
    **       Process command line arguments, stripping all command line switches 
    **       out of argv.  Return a new argc. If an error is found, 
    **       exit(ERR_EXIT_STATUS) is called (getargs won't return) and a usage 
    **       message is printed, showing all arguments in the table 
    ** 	 module must be initialized before first query is done
    ** 
    ** 	INPUT:	 o  name of command, for which command line is to be 
    **                  processed [R]
    **               o  number of args on command line [R]
    **               o  pointer to address of argument array [W]
    **
    ** 	        IMPLICIT:
    **                  print (INT4 (*print)(char *,...)) [W]
    ** 
    ** 	RETURNS:    new value for "argc" 
    */ 
    
    INT4 ArgGet (ARGoLIST *arglist, INT4 argc, char **argv) 
    {
      INT4     nargc, i;
      char    **nargv, *cp, oneletter[3], *savarg;
      arg_t   *argp;
      
      if (!print)
        print = ArgPrintMessage;
    
    /*
    ** BCB /MS : major !
    */
    
    
      if (ParGetFunction ("ArgPrintf") != NULL) 
        print = (INT4 (*)(char *, ...)) ParGetFunction ("ArgPrintf");
    
    #define USAGE_EXIT ArgUsage (arglist),exit(ERR_EXIT_STATUS)
    
    /* would be nice to have _this_ in a further release */ 
    /*
      if ( ParGetFunction ("UserExit") != NULL ) {
        myexit = (INT4 (*)(INT4)) ParGetFunction ("UserExit");
      }
      else {
        myexit = exit;
      }
    #define USAGE_EXIT ArgUsage (arglist),myexit(ERR_EXIT_STATUS)
    */
    
      nargc = 1;			        /* argv[0] is program name  */
      memset (oneletter, 0, sizeof (oneletter)); /* make zero */
      
      for (nargv = ++argv; --argc > 0; argv++) { /* walk all arguments */
        /* for now no provision for '\-'; do it with '--' */
        if ( strchr( OPT_FIRSTCHAR, (INT4)*argv[0]) ) { /* an option (or more) */
          if (! strcmp("--", *argv)) {	/* signals end of options */
    	argv++;				/* skip this one */
    	nargc += (argc-1);		/* all the rest but '--' */
    	for ( ; --argc > 0 ; argv++)	/* shift the rest */
    	  *nargv++ = *argv;
    	return (nargc); 
          }
          if (! argv[0][1] ) {		/* "-" or "+": never an option, */
    	*nargv++ = *argv;		/* always an argument: shift it  */
    	nargc++;
    	continue;
          }
          boolval = (*argv[0] == '-');	/* 1 if -option, 0 if +option */
          if ((argp = ArgFind (*argv, arglist))) { /* first try to find this arg 
    						  as a complete word in the 
    						  table */ 
    	if ((i=ArgSet (argp, argv))) {
    	  i--;
    	  argv += i;
    	  argc -= i;
    	  continue;
    	} else
    	  USAGE_EXIT;			/* wrong or no argument */
          } else {				/* try finding it as a letter arg */
    	oneletter[0]= argv[0][0];	/* any of OPT_FIRSTCHAR (typically -)*/
    	for ( cp = &argv[0][1]; *cp; cp++ ) {
    	  oneletter[1] = *cp;
    	  if ((argp = ArgFind (oneletter, arglist))){ /* find  arg in table */
    
    	    /*
    	    ** we seem to have found a matching one-letter option. 
    	    ** Temporarily change this *argv, so as not to confuse 
    	    ** the error messages: 
    	    */
    
    	    savarg = *argv;		/* save current arg */
    	    *argv = &oneletter[0];	/* argv[1] still 'normal' */
    	    if ((i = ArgSet (argp, argv))) { /* not-nil: succes !  */
    	      *argv = savarg;		/* restore original */
    	      if (i==2) {		/* option that takes a value: */
    		argv++;			/* must have been eaten */
    		argc--;
    		break;			/* continues at upper for-loop */
    	      }	/* else: continues at cp++ */
    	    } else			/* 0: failure */
    	      USAGE_EXIT;		/* wrong or no argument */
    	  } else {
    	    print ("Unrecognized option \'%s\'\n", *argv);
    	    USAGE_EXIT;			/* option not found */
    	  }
    	}
          }
        } else {				/* not an option: shift arguments */
          *nargv++ = *argv;
          nargc++;
        }
      } 
      return(nargc);
    } /* getargs */
    
    
    
    /**api* ArgSetPrint ************************************************************
    ** 
    **	allows other modules to set their own function for outputting
    **	messages;
    **
    **	INPUT:	    address of function [R]
    **	        IMPLICIT:
    **		    print (int (*)) [W]
    **
    */ 
       
    void ArgSetPrint (INT4 (*fnct)(char *,...))
    {
      if (fnct)
        print = fnct;
    }
    
    
     * 
     * See arglist.doc and header file for full explanation
     * (C)  Copyright 1985, Allen I. Holub.  All rights reserved.
     * This program may be copied for personal, non-profit use only
     * 
     * history...
     * 
     * May 1985     published in Dr. Dobb's Journal #103.
     * 19 May 85    Transcribed by James R. Van Zandt
     * Oct 1993     Extended/modified by Philip lijnzaad@embl-heidelberg.de
     *
     * ------------------------------------------------------------------ *
     *								      *
     * Permission to copy all or part of this work is granted, provided   *
     *  that this NO WARRANTY and this copyright notice are retained      *
     *  verbatim and are displayed conspicuously.  If anyone needs other  *
     *  permissions that aren't covered by the above, please contact the  *
     *  author.							      *
     *								      *
     * NO WARRANTY: THIS WORK IS PROVIDED ON AN "AS IS" BASIS.  THE       *
     *  AUTHOR PROVIDES NO WARRANTY WHATSOEVER, EITHER EXPRESS OR         *
     *  IMPLIED, REGARDING THE WORK, INCLUDING WARRANTIES WITH THE WORK,  *
     *  INCLUDING WARRANTIES WITH RESPECT TO ITS MERCHANTABILITY OR       *
     *  FITNESS FOR ANY PARTICULAR PURPOSE.				      *
     *								      *
     *								      *
     * ------------------------------------------------------------------ */
    
    /*	arglist.h - typedefs and defines needed for getargs	*/
    
    
    #include  			/* for prototypes */
    #include   
    #include 
    
    #ifndef _ARGoLIST
    #define _ARGoLIST
    typedef struct ARGoLIST {
      char                    *name;
      char                    *usage;
      struct arg_t            *arg;
      INT4                    argN;
    } ARGoLIST;
    #endif
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  prototypes of exported functions
    */
    
    INT4 ArgGet (ARGoLIST *arglist, INT4 argc, char **argv);
    void ArgUsage (ARGoLIST *arglist);
    void ArgSetPrint (INT4 (*fnct)(char *,...));
    
    
    #include 
    #include "srs.h"
    
    INT4 PrintMessage (MSGo *msg) 
    { 
      if (msg->msg_code == i__readingname)
        putc ('.', stderr); 
    
      switch (msg->msg_code) {
      case i__wroteset:
        return 0;
        
      default:
        if (msg->msg_t != MSGxINFO) 
          fprintf (stderr, "ERROR: %s, %s\n", msg->primsg, msg->secmsg);
        else
          fprintf (stderr, "%s\n", msg->secmsg);
        return 1;
      }
    }
    
    #ifdef BUILD
    int main (int argc, char **argv)
    {
      SMoBUFF      *buff=NULL, *auxBuff=NULL;
      struct IDXo *idx;
      SLBoFIELD    *field;
      SLBo         *lib;
      ENTRYo       *entry;
      char         *name, *ln, indexName[133], *format;
      int          errCode, n=0, len;
    
      SrsEnv ();
      LibOpen ("srswin");
      MsgSetFnct (PrintMessage);
      argc = ArgGet ((ARGoLIST *) LibObjByName ("arglist", "srsbuild"), 
    		 argc, argv);
    
      if (!(lib = (SLBo *) LibObjByName ("library", argv[1])))
        _ErrExit3 (e__objectunknown, "library", argv[1]);
    
      if (SmEqs(LibGetName (lib, "full"), "swissprot"))
        format =  "ID %*s %*[^;]; %*[^;]; %d";
      else if (SmEqs(LibGetName (lib, "full"), "embl"))
        format =  "ID %*s %*[^;]; %*[^;]; %*[^;]; %d";
      
      entry = EntryOpenStream (lib);
      LibGetIndexName (lib, NULL, indexName, "write");
      idx = IdxOpen (indexName, "write", 0, &errCode);
      _ErrExit2 (errCode, indexName);
      
      while (EntryNext (entry)) {
        while (field = EntryToNextField (entry)) {
          name = LibGetFieldName (field);
          if (SmEqs (name, "ID")) {
    	while (ln = EntryFieldNextLine (entry)) {
    	  sscanf (ln, format, &len);
    	}
          }
          else if (SmEqs (name, "Definition")) {
    	buff = BuffInit (buff, 100);
    	auxBuff = BuffInit (auxBuff, 100);
    	while (ln = EntryFieldNextLine (entry))
    	  BuffCopyString (buff, ln);
    	;
    	while (BuffMatch (buff, "((DE   )|(GN   ))"))
    	  BuffSubstMatch (buff, 1, "");
    	while (BuffMatch (buff, "(\n)"))
    	  BuffSubstMatch (buff, 1, " ");
    	
    	BuffPack (auxBuff, "ia60", len, BuffGetPtr (buff));
    	IdxPutBuff (idx, auxBuff);
          } 
          else	
    	EntrySkipField (entry);
        }
        if (!(++n % 300))
          _ErrMsg3 (i__processingentry, n, entry->full_nm);
      }
      IdxClose (idx);
    }
    
    
    
    #else
    int main ()
    {
      SMoBUFF  *buff;
      SETo     *set;
      IDoENTRY id;
      ENTRYo   *entry;
      int      n, entryN, len;
      char     ln[100];
      
      SrsEnv ();
      LibOpen ("srswin");
      
      if (QryDo ("[swissprot-definition:protein]", "Q")) {
        set = SetGet ("Q"); 
        entryN = SetSize ("Q");
        
        for (n=1;  n <= entryN; n++) {
          SetGetID (set, n, &id); 
          entry = EntryOpen (&id);
          buff = EntryGetAuxInfo (entry);
          BuffUnpack (buff, "ia60", &len, ln);
          printf ("entry: %s, len: %d | %s\n",
    	      EntryGetFullName (entry), len, ln);
          EntryClose (&entry);
        }
      }
    }
    #endif
    
    **
    **    $RCSfile: binpack.h,v $
    **    $Revision: 1.1 $
    **    $Date: 1996/05/06 15:16:18 $
    **    $Author: srs $
    **
    **    $Locker:  $
    **    $State: Exp $
    **
    **    Macros for packing and unpacking data into/from platform independent
    **    binary format.
    **
    */
    
    #define BYTE1   0xFFUL
    #define BYTE2   0xFF00UL
    #define BYTE3   0xFF0000UL
    #define BYTE4   0xFF000000UL
    
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  macros for packing and unpacking filepointers and numbers
    */
    
    #define _BinUnpackFip(buff, fip) \
         do { \
         fip = ((UINT4) ((unsigned char) buff[0])) + \
               ((UINT4) ((unsigned char) buff[1]) << 8) + \
    	   ((UINT4) ((unsigned char) buff[2]) << 16) + \
               ((UINT4) ((unsigned char) buff[3]) << 24); \
         buff += 4; \
         } while (0)
    
    #define _BinUnpackNum(buff, num) \
         do { \
         (num) = ((UINT4) ((unsigned char) buff[0])) + \
                 ((UINT4) ((unsigned char) buff[1]) << 8) + \
    	     ((UINT4) ((unsigned char) buff[2]) << 16) + \
                 ((UINT4) ((unsigned char) buff[3]) << 24); \
         buff += 4; \
         } while (0)
    
    #define _BinUnpack3Byte(buff, num) \
         do { \
         (num) = ((UINT4) ((unsigned char) buff[0])) + \
                 ((UINT4) ((unsigned char) buff[1]) << 8) + \
    	     ((UINT4) ((unsigned char) buff[2]) << 16); \
         buff += 3; \
         } while (0)
    
    #define _BinUnpack2Byte(buff, num) \
         do { \
         (num) = ((UINT4) ((unsigned char) buff[0])) + \
                 ((UINT4) ((unsigned char) buff[1]) << 8); \
         buff += 2; \
         } while (0)
    
    #define _BinUnpackByte(buff, byte) \
         byte = buff[0]; \
         buff += 1
    
    #define _BinUnpackStr(buff, s) \
         s = buff; \
         buff += strlen (buff) + 1
    
    #define _BinUnpackFixStr(buff, s, len) \
         strcpy (s, buff); \
         buff += len + 1
    
    #define _BinFileUnpackNum(file, num) \
         do { char buff[4]; \
         fread (buff, 4, 1, file); \
         num = ((UINT4) ((unsigned char) buff[0])) + \
               ((UINT4) ((unsigned char) buff[1]) << 8) + \
    	   ((UINT4) ((unsigned char) buff[2]) << 16) + \
               ((UINT4) ((unsigned char) buff[3]) << 24); \
         } while (0)
    
    #define _BinPackFip(buff, fip) \
      do { \
      buff[0] = fip & BYTE1; \
      buff[1] = (fip & BYTE2) >> 8; \
      buff[2] = (fip & BYTE3) >> 16; \
      buff[3] = (fip & BYTE4) >> 24; \
      buff += 4; \
      } while (0)
      
    #define _BinPackNum(buff, num) \
      do { \
      buff[0] = num & BYTE1; \
      buff[1] = (num & BYTE2) >> 8; \
      buff[2] = (num & BYTE3) >> 16; \
      buff[3] = (num & BYTE4) >> 24; \
      buff += 4; \
      } while (0)
    
    #define _BinPack3Byte(buff, num) \
      do { \
      buff[0] = num & BYTE1; \
      buff[1] = (num & BYTE2) >> 8; \
      buff[2] = (num & BYTE3) >> 16; \
      buff += 3; \
      } while (0)
    
    #define _BinPack2Byte(buff, num) \
      do { \
      buff[0] = num & BYTE1; \
      buff[1] = (num & BYTE2) >> 8; \
      buff += 2; \
      } while (0)
    
    #define _BinPackByte(buff, byte) \
      buff[0] = byte; \
      buff += 1
    
    #define _BinPackFixStr(buff, s, len) \
         strcpy(buff, s); \
         buff += len + 1
    
    #define _BinPackStr(buff, s) \
         strcpy(buff, s); \
         buff += strlen (s) + 1;
    
    #define _BinFilePackNum(file, num) \
         do { char buff[4]; \
         buff[0] = num & BYTE1; \
         buff[1] = (num & BYTE2) >> 8; \
         buff[2] = (num & BYTE3) >> 16; \
         buff[3] = (num & BYTE4) >> 24; \
         fwrite (buff, 4, 1, file); \
         } while (0)
    
    
    
    
    
    
    
    
    #include 
    #include "def.h"
    #include "strv.h"
    #include "dict.h"
    #include "blub.h"
    #include "parse.h"
    
    CLASSoDICT byNameProp = {
        PolyStrEqual, 
        PolyStrHash, 
        (KeyAccessor)KeyOffset, 
        0, /* to be initialized */
        FALSE
    };    
    
    /****************************************************
    ** BASIC TYPE DEFINITIONS
    ****************************************************/
    
    
    typedef struct PATHo {
        OBJo   head;
        /* tree mng. */
        DICTv  depend;
        PATHv  from;
        /* access */
        PathActor get;
        void*     val;
        ATTRv     descr;
    } PATHo;
     
    typedef struct OBJoStream* OBJpStream;
     
    /* value operations */
    typedef void (*ValCopier)  (void* dest,void* src, void* more);
    typedef void (*ValMover)   (void* dest,void* src, void* more);
    typedef void (*ValDeleter) (void* val, void* more);
    typedef void (*ValPrinter) (void* val, void* more);
    typedef void (*ValStorePreparer) (void* val, void* more, OBJpStream file);
    typedef void (*ValStorer)  (void* val, void* more, OBJpStream file);
    typedef void (*ValLoader)  (void* val, void* more, OBJpStream file);
    
    typedef struct VALCLASSo {
        OBJo	head;
        STRv        name;
        int		size;
        ValCopier		copy;
        ValMover		move;
        ValDeleter		del;
        ValPrinter		print;
        ValStorePreparer	storePrep;
        ValStorer		store;
        ValLoader		load;
        ValHasher		hash;
        ValComparer	equal;
    } VALCLASSo;
    
    typedef struct CLASSo {
        OBJo	head;
        CLASSv 	inherits;
        ATTRv*	fixed;
        DICTv	byName;
        /* ATTRv list, open */
        ListAttr	list;
        ATTRv	attrs[10];
    } CLASSo;
    
    /***************************************************************
    ** POLYMORPHIC ATTRIBUTE OPERATIONS 
    ****************************************************************/
    
    void PolyNotImpl() { THROW("NotImplemented"); }
    void PolyNothing() {}
    
    void PolyIntCpy(int* dest,  int* src, void* nothing) { *dest=*src; }
    void PolyPtrCpy(void** dest, void** src, void* nothing) { *dest=*src; } 
    
    void PolyStrCpy(STRv* dest, STRv* src, void* nothing) {
        *dest=StrCpy(*src);
    } 
    
    void PolyStrDel(STRv* v, void* nothing) {
        StrDel(*v);
    }
    
    void PolyObjCpy(void** dest, void** src, void* nothing) {
        *dest=ObjCpy(*src);
    }
    
    void PolyObjDel(void** v, void* nothing) {
        ObjDel(*v);
    }
    
    
    void PolyVirtualCpy(void** dest, void** src, void* nothing) {
        *dest=offset(dest, displ(*src, src), void*);
    }
    
    void PolyStrPrint(STRv* v, void* nothing) {
        if (*v) printf("%s", Str(*v));
        else printf("NULL");
    }
    
    void PolyIntPrint(int* v, void* nothing) {
        printf("%d", *v);
    }
    
    void PolyObjPrint(void** obj, void* nothing) {
        ObjPrint(*obj);
    }
    
    void PolyVirtualPrint(void** attr, void* nothing) {
        /* should print the attr name of the virtual */
        printf("virtual");
    }
    
    int PolyObjHash(void** obj,int max) {
        return ObjHash(*obj,max);
    }
    
    BOOL PolyObjEqual(void** obj1,void** obj2) {
        return ObjEqual(*obj1,*obj2);
    }
    
    /**************************************************************
    ** ATTRIBUTE STORING/LOADING
    */
    
    void PolyIntStore(int* v, void* more, OBJpStream stream) {
        IntStore(*v, stream);
    }
    
    void PolyIntLoad(int* v, void* more, OBJpStream stream) {
        *v=IntLoad(stream);
    }
    
    void PolyStrStore(STRv* v, void* more, OBJpStream stream) {
        StrStore(*v, stream);
    }
    
    void PolyStrLoad(STRv* v, void* more, OBJpStream stream) {
        *v=StrLoad(stream);
    }
    
    void PolyObjStore(void** obj, void* more, OBJpStream stream) {
        ObjStore(*obj, stream);
    }
        
    void PolyObjLoad(void** o, void* more, OBJpStream stream) {
        *o=ObjLoad(stream);
    }
    
    
    /*******************************************************
    ** References
    *******************************************************/
    
    int PolyRefHash(REF* r, int max) {
        return 0;
    }
    
    BOOL PolyRefEqual(REF* r1,REF* r2) {
        return *r1==*r2;
    }
    
    void PolyRefStore(REF* r, void* more, OBJpStream stream) {
        RefStore(*r,stream);
    }
        
    void PolyRefLoad(REF* r, void* more, OBJpStream stream) {
        *r=RefLoad(stream);
    }
    
    
    /***************************************
    ** BOOTSTRAP TEMPORARY, until I grow the metadata system to
    ** "inline" types
    */
    
    /* ATTRv ************************************/
    
    void ATTRvCpy(ATTRv* d, ATTRv* s, void* nothing) {
        if (s->name) d->name=StrCpy(s->name);
        else d->name=NULL;
        d->offs=s->offs;
        d->type=s->type;
        d->more=s->more; /*...???? how do I copy this? */    
    }
    
    void ATTRvMove(ATTRv* d, ATTRv* s, void* nothing) {
        d->name=s->name;
        d->offs=s->offs;
        d->type=s->type;
        d->more=s->more;
    }
      
    void ATTRvDel(ATTRv* a, void* nothing) {
        if (a->name) StrDel(a->name);
    }
    
    void ATTRvPrint(ATTRv* a, void* nothing) {
        if (a->type) {
    	if (a->name) printf("%s:", Str(a->name));
    	printf("%s", Str(a->type->name));
    	printf("[o:%d]",a->offs);
        }
    }
    
    int PolyAttrHash(ATTRv* a, int max) {
        return (StrHash(a->name,max)+StrHash(a->type->name,max))%max;
    }
    
    BOOL PolyAttrEqual(ATTRv* a1,ATTRv* a2) {
        return 
    	StrEqual(a1->name,a2->name) &&
    	a1->type==a2->type &&
    	ObjEqual(a1->more,a2->more);
    }
    
    
    /* CLASS head ********************************************/
    /* temporarily the entire class value a single attribute */
    
    typedef struct CLASSBODYv {
        CLASSv	inherits;
        ATTRv*	fixed;
        DICTv	byName;
    } CLASSBODYv;
    
    void CLASSBODYvCpy(CLASSBODYv* d, CLASSBODYv* s, void* nothing) {
        d->inherits=ObjCpy(s->inherits);
        d->fixed=offset(d, displ(s->fixed, s), ATTRv*);
        d->byName=s->byName; 
    }
    
    void CLASSBODYvMove(CLASSBODYv* d, CLASSBODYv* s, void* nothing) {
        DICTv byName=s->byName;
        if (byName && (s->inherits && byName!=s->inherits->byName)) {
    	/* had a local dictionary, offset attributes */
            ListAttr* slist=cast(s+1,ListAttr*);
    	ListAttr* dlist=cast(d+1,ListAttr*);
    	DictOffsetWithin(byName, slist, displ(slist->tail,slist), dlist);
        }
        d->inherits=s->inherits;
        d->fixed=offset(d, displ(s->fixed, s), ATTRv*);
        d->byName=s->byName; 
    }
    
    void CLASSBODYvDel(CLASSBODYv* c, void* nothing) {
        DICTv* byName=&c->byName;
        if (*byName && (c->inherits && *byName!=c->inherits->byName)) {
    	/* had a local dictionary, delete */
    	DictDestroy(*byName);
        }
        ObjDel(c->inherits);    
    }
    
    void CLASSBODYvPrint(CLASSBODYv* c,  void* nothing) {
      /*if (c->name) printf(" name:%s", Str(c->name));*/
    }
    
    int PolyClassHash(CLASSBODYv* c,int max) {
        return ObjHash(c->inherits,max);
    }
    
    BOOL PolyClassEqual(CLASSBODYv* c1, CLASSBODYv* c2) {
        return c1->inherits==c2->inherits;
    }
    
    /* ListAttr **********************************************************/
    
    void ListAttrCpy(ListAttr* d, ListAttr* s, void* nothing) {
        d->tail=offset(d,displ(s->tail, s),BYTE*);
        d->end=d->tail; /* ??? what if grow is reserved? */
    }
    
    void ListAttrPrint(ListAttr* l,void* nothing) {
        printf("[n:%d", displ(l->tail,l+1));
        if (l->end!=l->tail) printf(" g:%d", displ(l->end,l->tail));
        printf("]");
    }
    
    int ListAttrHash(ListAttr* l, int max) {
        /* hashes the number of elements in a list */
        return displ(l->tail,l)%max;
    }
    
    BOOL ListAttrEqual(ListAttr* l1, ListAttr* l2) {
        return displ(l1->tail,l1)==displ(l2->tail,l2);
    }
    
    /* PATHBODY **********************************************************/
        
    typedef struct PATHBODYv {
        /* tree mng. */
        DICTv  depend;
        PATHv  from;
        /* access */
        PathActor get;
        void*     val;
        ATTRv     descr;
    } PATHBODYv;
    
    void PathBodyDel(PATHBODYv* p, void* nothing) {
        if (p->from) ObjDel(p->from);
        if (p->depend) DictDestroy(p->depend);
        if (p->descr.type) ObjDel(p->descr.type);
        if (p->descr.more) ObjDel(p->descr.more);
        StrDel(p->descr.name);
    }
    
    void PathBodyPrint(PATHBODYv* p, void* nothing) {
        if (p->from) {
            PathBodyPrint(offset(p->from,sizeof(OBJo),PATHBODYv*),NULL);
    	printf(".");
        }
        printf(Str(p->descr.name));
    }
    
    void PathBodyStore(PATHBODYv* path, void* more, OBJpStream stream) {
        StrStore(path->descr.name, stream);
        if (!ObjStreamMappedPtr(path->from, 0, stream)) 
            PathBodyStore(offset(path->from,sizeof(OBJo),PATHBODYv*),NULL, stream);
    }
    
    void PathBodyLoad(PATHBODYv* path, void* more, OBJpStream stream) {
        PATHv from; unsigned long none;
        path->descr.name=StrLoad(stream);
        if (!ObjStreamMappedPos((void**)&from, &none, stream)) {
        	PathBodyLoad(offset(from,sizeof(OBJo),PATHBODYv*),NULL,stream);
        }
        else from=ObjCpy(from);
        path->from=(PATHv)from;
    }
    
    /**********************************************************************
    ** PREDEFINED ATTRIBUTE TYPES
    **********************************************************************/
    
    STRoSTATIC_20 attrTypeNames[]= { 
        {{1},"int"}, 
        {{1},"STRv"}, 
        {{1},"OBJv"},
        {{1},"REF"},  
        {{1},"ListAttr"},  
        {{1},"virtual"}, 
        {{1},"ATTRv"}, 
        {{1},"CLASSBODYv"},
        {{1},"PATHBODYv"},    
        {0}
    };
    
    extern PATHo BootPaths[]; 
    
    #define VALCLASS_NUM 8
    
    VALCLASSo valClasses[]= {
        {	/* int */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[0],
    	sizeof(int), 
    	(ValCopier)PolyIntCpy, 
    	(ValMover)PolyIntCpy, 
    	(ValDeleter)PolyNothing, 
    	(ValPrinter)PolyIntPrint,
    	(ValStorer)PolyIntStore, 
    	(ValLoader)PolyIntLoad, 
    	(ValHasher)PolyIntHash, 
    	(ValComparer) PolyIntEqual
        }, 
        {	/* STRv */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[1],
    	sizeof(STRv), 
    	(ValCopier)PolyStrCpy,
    	(ValMover)PolyPtrCpy,  
    	(ValDeleter)PolyStrDel, 
    	(ValPrinter)PolyStrPrint,
    	(ValStorer)PolyStrStore, 
    	(ValLoader)PolyStrLoad, 
    	(ValHasher)PolyStrHash, 
    	(ValComparer) PolyStrEqual
        }, 
        {	/* OBJv */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[2],
    	sizeof(OBJv), 
    	(ValCopier)PolyObjCpy,
    	(ValMover)PolyPtrCpy,  
    	(ValDeleter)PolyObjDel, 
    	(ValPrinter)PolyObjPrint,
    	(ValStorer)PolyObjStore, 
    	(ValLoader)PolyObjLoad, 
    	(ValHasher)PolyObjHash, 
    	(ValComparer) PolyObjEqual
        }, 
        {	/* REF */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[3], 
    	sizeof(REF), 
    	(ValCopier)PolyObjCpy, 
    	(ValMover)PolyPtrCpy, 
    	(ValDeleter)PolyObjDel, 
    	(ValPrinter)PolyObjPrint, 
    	(ValStorer)PolyRefStore, 
    	(ValLoader)PolyRefLoad, 
    	(ValHasher)PolyRefHash, 
    	(ValComparer) PolyRefEqual
        }, 
        {	/* ListAttr */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[4], 
    	sizeof(ListAttr), 
    	(ValCopier)ListAttrCpy, 
    	(ValMover)ListAttrCpy, 
    	(ValDeleter)PolyNothing, 
    	(ValPrinter)ListAttrPrint, 
    	(ValStorer)PolyNothing, 
    	(ValLoader)PolyNothing, 
    	(ValHasher)ListAttrHash, 
    	(ValComparer)ListAttrEqual
        }, 
        {	/* virtual */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[5],
    	sizeof(void*), 
    	(ValCopier)PolyVirtualCpy,
    	(ValMover)PolyVirtualCpy,  
    	(ValDeleter)PolyNothing, 
    	(ValPrinter)PolyVirtualPrint,             
    	(ValStorer)PolyNothing, 
    	(ValLoader)PolyNothing, 
    	(ValHasher)PolyNothing, 
    	(ValComparer) PolyNothing
        }, 
        {
    	/* ATTRv */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[6],
    	sizeof(ATTRv), 
    	(ValCopier)ATTRvCpy, 
    	(ValMover)ATTRvMove, 
    	(ValDeleter)ATTRvDel, 
    	(ValPrinter)ATTRvPrint, 
    	(ValStorer)PolyNothing, 
    	(ValLoader)PolyNothing, 
    	(ValHasher)PolyAttrHash, 
    	(ValComparer) PolyAttrEqual
        }, 
        {	/* CLASSBODYv */
    	{1, NULL}, 
    	(STRv)&attrTypeNames[7],
    	sizeof(CLASSBODYv),
    	(ValCopier)CLASSBODYvCpy, 
    	(ValMover)CLASSBODYvMove, 
    	(ValDeleter)CLASSBODYvDel, 
    	(ValPrinter)CLASSBODYvPrint, 
    	(ValStorer)PolyNothing, 
    	(ValLoader)PolyNothing, 
    	(ValHasher)PolyClassHash, 
    	(ValComparer) PolyClassEqual
        }, 
        {	/* PATHBODYv */
    	{ 1, NULL },
    	(STRv)&attrTypeNames[8],
    	sizeof(PATHBODYv),
    	(ValCopier)PolyNotImpl,
    	(ValMover)PolyNotImpl,
    	(ValDeleter)PathBodyDel,
    	(ValPrinter)PathBodyPrint, 
    	(ValStorer)PathBodyStore, 
    	(ValLoader)PathBodyLoad, 
    	(ValHasher)PolyNothing, 
    	(ValComparer) PolyNothing
        }
    };
    
    
    
    /*************************************************
    ** PREDEFINED CLASSES
    *************************************************/
    
    STRoSTATIC_20 classNames[]= {
        {{1},"List"}, 
        {{1},"CLASSo"}, 
        {{1},"OBJo"},
        {0}    
    }; 
    
    /* the descriptor for all list attribute headers */ 
    
    ATTRv AttrListAttr = {
        (STRv)&classNames[0], 
        &valClasses[4], 
        0, 
        NULL
    };
    
    #define SIZE_HEAD sizeof(OBJo)
    #define SIZE_CLASSHEAD (sizeof(CLASSo)-sizeof(ListAttr)-sizeof(ATTRv)*10)
    #define SIZE_ATTR sizeof(ATTRv)
    
    CLASSo bootClassClass= {
        { 2, &bootClassClass }, 
        NULL, /* should inherit BootObjClass */
        &bootClassClass.attrs[1], 
        NULL,  
        {(BYTE*)&bootClassClass.attrs[2], (BYTE*)&bootClassClass.attrs[2]}, {
    	/* CLASSBODYv */    { NULL, &valClasses[7], SIZE_HEAD, NULL }, 
    	/* list of ATTRv */ { NULL, &valClasses[6], SIZE_CLASSHEAD, NULL } 
        }
    };
    
    CLASSo bootPathClass= {
        { 2, &bootClassClass }, 
        NULL, /* should inherit BootObjClass */
        &bootPathClass.attrs[1], 
        NULL,  
        {(BYTE*)&bootPathClass.attrs[2], (BYTE*)&bootPathClass.attrs[2]}, {
    	/* PATHBODYv */	{ NULL, &valClasses[8], SIZE_HEAD, NULL }, 
    	/* nothing */	{ NULL, NULL, sizeof(PATHBODYv), NULL } 
        }
    };
    
    CLASSo bootObjClass = {
        { 2, &bootClassClass},
        NULL,  
        &bootObjClass.attrs[0], 
        NULL, 
        { (BYTE*)&bootObjClass.attrs[1], (BYTE*)&bootObjClass.attrs[1] }, {
    	{ NULL, NULL, SIZE_HEAD, NULL }
        }
    };
    
    OBJo objBuf = {
        1, &bootObjClass
    };
    
    void* Object=&objBuf;
    
    /**************************************************************/
    
    void* Class=&bootObjClass;
    VALCLASSv intClass=&valClasses[0];
    VALCLASSv STRvClass=&valClasses[1];
    VALCLASSv OBJvClass=&valClasses[2];
    ATTRv* lastAttr=NULL;
    DICTv  baseTypes=NULL;
    
    /*************************************************************
    ** PATH static initialization
    *************************************************************/
    void* PathGetError(PATHv p, void* from);
    void* PathGetVal(PATHv p, void* from);
    void* PathGetOffs(PATHv p, void* obj);
    void* PathGetName(PATHv p, void* obj);
    
    PATHo bootPaths[]= {
        /* root */   {{5,&bootPathClass}, NULL,NULL,PathGetError,NULL,{NULL,NULL,0,NULL} }
        /* int 	{{2,&bootPathClass}, NULL,&BootPaths[0],PathGetVal,&valClasses[0],{&attrTypeNames[0],valClasses+0,0,NULL}}, 
         STRv 	{{2,&bootPathClass}, NULL,&bootPaths[0],PathGetVal,&valClasses[1],{&attrTypeNames[1],valClasses+1,0,NULL}}, 
         OBJv 	{{2,&bootPathClass}, NULL,&bootPaths[0],PathGetVal,&valClasses[2],{&attrTypeNames[2],valClasses+2,0,NULL}},
         CLASSo {{2,&bootPathClass}, NULL,&bootPaths[0],PathGetVal,&bootClassClass,{&classNames[0],&bootObjClass,0,NULL}},
         OBJo 	{{2,&bootPathClass}, NULL,&bootPaths[0],PathGetVal,&bootObjClass,  {&classNames[1],&objBuf,0,NULL}}*/
    };
    
    /*************************************************************************
    ** NAMED VALUES MNGM.
    *************************************************************************/
    
    /* a val can have several names associated with it, but the first one counts */
    
    typedef struct VALoName {
        STRv name;
        void* val;
    } VALoName;
    
    typedef struct VALoSpace {
        DICTv valKnown;
        DICTv nameKnown;
        struct VALoSpace* included;
    } VALoSpace;
    
    void ValName(VALoSpace* s, void* val, STRv name);
    
    VALoSpace* ValSpaceNew(VALoName* init) {
        static CLASSoDICT* valKnownIndexClass=NULL;
        static CLASSoDICT* nameKnownIndexClass=NULL;
        VALoSpace* s=typeAlloc(VALoSpace);
        if (!valKnownIndexClass) {
    	valKnownIndexClass=DictCreateClassPtrKey(NULL, mPtr(VALoName, val), TRUE);
    	nameKnownIndexClass=DictCreateClassStrKey(NULL, mPtr(VALoName, name), FALSE);
        }
        s->valKnown=DictCreate(valKnownIndexClass);
        s->nameKnown=DictCreate(nameKnownIndexClass);
        if (init) {
    	while (init->name) { 
    	    ValName(s, init->val, init->name);
    	    init++; 
    	}
        }
        return s;
    }
    
    VALoSpace* ValSpaceInclude(VALoSpace* src) {
        VALoSpace* s=ValSpaceNew(NULL);
        DICTv v=src->valKnown;
        Iter i;
        for (i=DictFirst(v); i; DictNext(v, &i)) {
    	VALoName* n=DictIn(i, VALoName*);
    	ValName(s, n->val, n->name);
        }
        return s; 
    }
    
    void ValSpaceDel(VALoSpace* s) {
        Iter i; DICTv v=s->valKnown;
        for (i=DictFirst(v); i; DictNext(v, &i)) {
    	VALoName* n=DictIn(i, VALoName*);
    	ObjDel(n->val);
    	StrDel(n->name);
    	free(n);
        }
        DictDestroy(s->valKnown);
        DictDestroy(s->nameKnown);
    }
    
    void ValName(VALoSpace* s, void* val, STRv name) {
        VALoName* v = typeAlloc(VALoName);
        v->name=StrCpy(name);
        v->val=ObjCpy(val);
        DictAddPtr(&s->valKnown, v);
        DictAddPtr(&s->nameKnown, v);
    }
    
    void* ValFromName(VALoSpace* s, STRv name) {
        Iter n=DictWith(s->nameKnown,&name);
        if (n) return DictIn(n,VALoName*)->val;
        else return NULL;
    }
    
    STRv ValToName(VALoSpace* s, void* val) {
        Iter n=DictWith(s->valKnown,&val);
        if (n) return DictIn(n,VALoName*)->name;
        else return NULL;
    }
    
    /***************************************************************
    ** the system value namespace
    ***************************************************************/
    
    VALoName knownValues[]= {
        {(STRv)&classNames[0], &bootClassClass}, 
        {(STRv)&classNames[1], &bootPathClass}, 
        {(STRv)&classNames[2], &bootObjClass}, 
        {(STRv)&attrTypeNames[0], &valClasses[0]}, 
        {(STRv)&attrTypeNames[1], &valClasses[1]}, 
        {(STRv)&attrTypeNames[2], &valClasses[2]}, 
        {(STRv)&attrTypeNames[3], &valClasses[3]}, 
        {(STRv)&attrTypeNames[4], &valClasses[4]}, 
        {(STRv)&attrTypeNames[5], &valClasses[5]}, 
        {(STRv)&attrTypeNames[6], &valClasses[6]}, 
        {(STRv)&attrTypeNames[7], &valClasses[7]}, 
        {(STRv)&attrTypeNames[8], &valClasses[8]}, 
        {NULL, NULL}
    };
    
    VALoSpace* systemKnown=NULL;
    
    void ObjInit() {
        StrInitStatic(classNames);
        StrInitStatic(attrTypeNames);
        systemKnown=ValSpaceNew(knownValues);
        byNameProp.toKeyInfo=mPtr(ATTRv,name);
    
        /* create dictionary of base type
        bt=typeAlloc(CLASSoDICT);
        bt->equal=PolyStrEqual;
        bt->hash=PolyStrHash;
        bt->toKey=(KeyAccessor)KeyOffset;
        bt->toKeyInfo=mPtr(VALCLASSo, name);
        bt->repetitions=FALSE;
        baseTypes=DictCreate(bt);
        for (v=valClassBuf; vfixed;
        int size=fixed->offs;
        if (fixed->type) {
    	/* it's a list */
    	ListAttr* list=offset(obj, size, ListAttr*);
    	size+=displ(list->tail, list);
        }
        return size;
    }
    
    
    OBJv ObjRealloc(OBJv obj, int grow) {
        OBJv o=(OBJv)malloc(ObjSize(obj)+grow);
        o->usage=1;
        o->descr=ObjCpy(obj->descr);
        return o;
    }
    
    void ObjFree(OBJv obj) {
        ObjDel(obj->descr);
        free(obj);
    }
    
    CLASSv ObjClass(void* obj) {
        return _getObj(obj)->descr;
    }
    
    /************************************************
    ** general functions to do thinks on object attributes 
    */
    
    void ObjDoAttrRecursive(void* obj, CLASSv descr, AttrAction act, void* info) {
        CLASSv inherits=descr->inherits;
        ATTRv* attr;
        ATTRv* list=descr->attrs;
        if (inherits) ObjDoAttrRecursive(obj, inherits, act, info);
        for (attr=list; attrfixed; attr++) {
    	call(act)(offset(obj, attr->offs, void*), attr, info);
        }
    }
    
    void ObjDoAttr(void* obj, AttrAction act, void* info) {
        CLASSv descr=ObjClass(obj);
        ObjDoAttrRecursive(obj, descr, act, info);
    }
    
    void ObjDoInList(void* obj, AttrAction act, ATTRv* elem, void* info, void* from, void* to) {
        int elemSize=elem->type->size;
        while (fromtype->size;
        to=cast(to,BYTE*)-elemSize;
        while (to>=from) {
    	call (act)(to, elem, info);
    	to=cast(to,BYTE*)-elemSize;
        }
    }
    
    void ObjDoList(void* obj, AttrAction act, void* info) {
        ListAttr* list; ATTRv* elem;
        ASSERT (ObjListInfo(obj, &elem, &list),NotAList); 
        ObjDoInList(obj, act, elem, info, list+1, list->tail); 
    }
    
    void ObjDoAll(void* obj, AttrAction act, void* info) {
        ListAttr* list; ATTRv* elem;
        ObjDoAttr(obj, act, info);
        if (ObjListInfo(obj, &elem, &list)) {
    	call (act)(list, &AttrListAttr, info);
    	ObjDoInList(obj, act, elem, info, list+1, list->tail); 
        }
    }
    
    BOOL ObjDoCondRecursive(void* obj, CLASSv descr, AttrCondition act, void* info) {
        CLASSv inherits=descr->inherits;
        ATTRv* attr;
        ATTRv* list=descr->attrs;
        if (inherits) 
    	if (ObjDoCondRecursive(obj, inherits, act, info)) return TRUE;
        for (attr=list; attrfixed; attr++) {
    	if (call(act)(offset(obj, attr->offs, void*), attr, info)) return TRUE;
        }
        return FALSE;
    }
    
    BOOL ObjDoCond(void* obj, AttrCondition act, void* info) {
        ListAttr* list; ATTRv* elem;
        if (ObjDoCondRecursive(obj, _getObj(obj)->descr, act, info)) return TRUE;
        if (ObjListInfo(obj, &elem, &list)) {
    	int elemSize; void *from,*to;
    	if (call (act)(list, &AttrListAttr, info)) return TRUE;
    	elemSize=elem->type->size;
    	from=list+1;
    	to=list->tail;
    	while (fromtype->copy)(offset(attr, (int)copyOffs, void*), attr, a->more);
    }
    
    /* general move */
    
    void AttrMoveAction(void* attr, ATTRv* a, void* moveOffs) {
        call (a->type->move)(offset(attr,(int)moveOffs,void*), attr, a->more);
    }
    
    /* general deletion */
    
    void AttrDelAction(void* attr, ATTRv* a, void* nothing) {
        call (a->type->del)(attr, a->more);
    }
    
    /* general print */
    
    void AttrPrintAction(void* attr, ATTRv* a, void* nothing) {
        printf(" ");
        if (a->type) {
          if (a->name) printf("%s:", Str(a->name));
          call (a->type->print)(attr, a->more);
        }
    }
    
    void AttrStoreAction(void* attr, ATTRv* a, void* stream) {
        call (a->type->store)(attr, a->more, (OBJpStream)stream);
    }
    
    void AttrLoadAction(void* attr, ATTRv* a, void* stream) {
        call (a->type->load)(attr, a->more, (OBJpStream)stream);
    }
    
    void AttrHashAction(void* attr, ATTRv* a, void* hashVal) {
        (*(int*)hashVal) += call (a->type->hash)(attr, 0xFFFFFFFFL);
    }
    
    BOOL AttrDifferentCond(void* attr, ATTRv* a, void* compOffs) {
        return !call(a->type->equal)(attr, offset(attr,(int)compOffs, void*));
    }
    
    
    /*****************************************************************
    ** Object buffer operations 
    */
    
    void* ObjChangeImpl(void** obj) {
        OBJv o=_getObj(*obj);
        if (o->usage>1) {
    	OBJv old=o;
    	*obj=o=ObjRealloc(old, 0);
    	ObjDoAll(old, AttrCopyAction, (void*)displ(o, old));
    	old->usage--;
        }
        return _getVal(o);
    }
    
    void ObjDel(void* obj) {
        if (obj) {
          OBJv o=_getObj(obj);
          if (!--o->usage) {
    	ObjDoAll(obj, AttrDelAction, NULL);
    	ObjFree(o);
          }
        }
    }
    
    /*****************************************************************
    ** REFERENCE COUNTING operations 
    */
    
    void* ObjCpy(void* obj) { 
        if (obj) _getObj(obj)->usage++; 
        return obj; 
    }
    
    void ObjSet(void** dest, void* src) { 
        ObjDel(*dest); *dest=ObjCpy(src); 
    }
    
    int ObjShared(void* obj) { 
        return _getObj(obj)->usage-1; 
    }
    
    int ObjHash(void* obj, int max) {
        int hash=0;
        ObjDoAll(obj,AttrHashAction, &hash);
        hash&=0xFFFFFFFF;
        return hash%max;
    }
    
    BOOL ObjEqual(void* obj1, void* obj2) {
        if (obj1==obj2) return TRUE;
        /* if value managed, I can only check the pointers here */
        if (_getObj(obj1)->descr!=_getObj(obj2)->descr) return FALSE;
        if (ObjSize(obj1)!=ObjSize(obj2)) return FALSE;
        return !ObjDoCond(obj1, AttrDifferentCond, displ(obj2, obj1));
    }
    
    /**************************************************************
    ** ATTRIBUTE OPERATIONS
    ***************************************************************/
    
    void* ObjAttrNewImpl(void** obj, STRv name, VALCLASSv type, void* more) {
        OBJv old=_getObj(*obj);
        OBJv   o; int offs;
        o=ObjRealloc(old, type->size); 
        ObjDoAttr(old, AttrCopyAction, (void*)displ(o,old));
        ObjDel(old);
        offs=ClassAttrNew(&o->descr, name, type, more);
        *obj=o; return offset(o, offs, void*);
    }
    
    /* attribute access */
    void* ObjAttrInImpl(void* obj, AttrIter i) {
        return offset(obj, i, void*);
    }
    
    void* ObjAttrImpl(void* obj, STRv name, VALCLASSv type) {
        AttrIter offs=ObjAttrWith(obj,name);
        ASSERT(!type || lastAttr->type==type,TypeMismatch);
        return offset(obj, offs, void*);
    }
    
    
    
    /* attribute iteration */
    
    AttrIter  ObjAttrWith(void* obj, STRv name) {
        CLASSv descr=_getObj(obj)->descr;
        AttrIter i;
        if (isalpha(Str(name)[0])) {
            /* a normal attribute name */
            lastAttr=DictAt(descr->byName, &name, ATTRv*);
    	i=lastAttr->offs;
        }
        else {
            /* a list element */
            int pos=atoi(Str(name));
    	void* a=ObjListWith(obj,pos);
    	ASSERT(a,NoSuchElem);
    	i=displ(a,obj);
        }
        return i;
    }
    
    AttrIter  ObjAttrFirst(void* obj) {
        return sizeof(OBJo);
    }
    
    void ObjAttrNext(void* obj, AttrIter* i) {
        AttrIter p=*i;
        ATTRv* attr=ObjAttrInfo(obj, p); 
        p=p+attr->type->size;
        if (p>=ObjSize(obj)) p=NULL;
        *i=p;
    }
    
    /* attribute information */
    
    ATTRv* ObjAttrInfoFixed(CLASSv descr, int offs) {
        ATTRv* minAttr=&descr->attrs[0];
        if (offsoffs) {
    	CLASSv inherits=descr->inherits;
    	ASSERT(inherits, InvalidAttribute); 
    	return ObjAttrInfoFixed(inherits,offs);
    	
        }
        else {
    	/* perform a binary search on offsets, 
    	   they are sorted */
    	ATTRv* maxAttr=descr->fixed;
    	int diff=maxAttr-minAttr;
    	while (diff>1) {
    	    ATTRv* attr=minAttr+(diff>>1);
    	    if (offsoffs) maxAttr=attr;
    	    else minAttr=attr;
    	    diff=maxAttr-minAttr;
    	}
    	return minAttr;
        }
    }
    
    ATTRv* ObjAttrInfo(void* obj, AttrIter offs) {
        void* a=offset(obj, offs, void*);
        ATTRv* elem; ListAttr* l;
        if (ObjListInfo(obj, &elem, &l) && a>=(void*)l && a<(void*)l->tail) {
    	/* it's a list element */
            if (a==l) return &AttrListAttr;
    	return elem;
        }
        else {
    	CLASSv descr=_getObj(obj)->descr;
    	ASSERT(offsfixed->offs, InvalidAttribute);
    	return ObjAttrInfoFixed(descr, offs);
        }
    }
    
    STRv ObjAttrName(void* obj, AttrIter offs) {
        void* a=offset(obj, offs, void*);
        ATTRv* elem; ListAttr* l;
        if (ObjListInfo(obj, &elem, &l) && a>=(void*)l && a<(void*)l->tail) {
    	/* it's a list element */
            if (a==l) return StrCpy(AttrListAttr.name);
    	else {
    	    int pos=ObjListPos(obj,a);
    	    return StrFromInt(pos);
    	}
        }
        else {
    	CLASSv descr=_getObj(obj)->descr;
    	ASSERT(offsfixed->offs, InvalidAttribute);
    	return StrCpy(ObjAttrInfoFixed(descr, offs)->name);
        }
    }
    
    /****************************************************************************
    ** CLASS MANAGEMENT
    ****************************************************************************/
    
    
    void ObjMakeClass(void* obj, STRv name) {
        PATHv p; CLASSv descr=_getObj(obj)->descr;
        ValName(systemKnown, descr, name);
        /* p=PathDef(theRoot,name); */
        /* associate the path with the object value */
    }
    
    
    AttrIter ClassAttrNew(CLASSv* cl, STRv name, VALCLASSv type, void* more) {
        CLASSv descr=*cl;
        ATTRv* attr;
        int offs;
        offs=descr->fixed->offs;
        offs+=align(offs,type->size);
        ASSERT(!descr->fixed->type, CannotInheritFromList);
        if (ObjShared(descr)) {
    	CLASSv old=descr;
            descr=ObjCpy(Class);
    	attr=&ObjListApp(&descr, ATTRv);
    	descr->inherits=old;
        }
        else {
            attr=&ObjListApp(&descr, ATTRv);
        }
        /* last ATTRv is fake, only for size: set it */
        descr->fixed=attr;
        attr->offs=offs+type->size;
        attr->type=NULL;
    
        /* now set attribute descriptor */
        attr--;
        attr->type=ObjCpy(type);
        attr->more=more;
        attr->offs=offs;
    
        /* manage now name */
        if (name) {
    	DICTv* byName=&descr->byName;
    	if (!*byName) *byName=DictCreate(&byNameProp);
    	else if (descr->inherits && *byName==((CLASSv)_get(descr->inherits,OBJv))->byName) {
    	    /* copy old dictionary if it was shared */
    	    *byName=DictCopy(((CLASSv)_get(descr->inherits,OBJv))->byName);
    	}
    	DictAdd(byName, &name, ATTRv*)=attr;
    	attr->name=StrCpy(name); 
        }
        else attr->name=NULL;
        *cl=descr; return offs;
    }
    
    AttrIter ClassListNew(CLASSv* cl, VALCLASSv type, void* more) {
        CLASSv descr=*cl;
        ATTRv* attr;int offs;
        ASSERT(!descr->fixed->type, CannotInheritFromList);
        offs=descr->fixed->offs;
        offs+=align(offs,type->size);
        if (ObjShared(descr)) {
    	CLASSv old=descr;
            descr=ObjCpy(Class);
    	attr=ObjChange(&descr, CLASSv)->fixed;
    	descr->inherits=old;
        }
        else {
            attr=ObjChange(&descr, CLASSv)->fixed;
        }
        attr->type=ObjCpy(type);
        attr->more=more;
        attr->name=NULL;
        attr->offs=offs;
        *cl=descr; return offs;
    }
    
    AttrIter ClassAttrWith(CLASSv descr, STRv name, ATTRv** attr) {
        AttrIter i;
        ATTRv* ia=NULL;
        if (isalpha(Str(name)[0])) {
            /* a normal attribute name */
            Iter a=DictWith(descr->byName, &name);
    	if (a) {
    	    ia=DictIn(a, ATTRv*);
    	    i=ia->offs;
    	}
    	else i=NULL;
        }
        else {
            /* a list element */
            int pos=atoi(Str(name));
    	ia=descr->fixed;
    	ASSERT(ia->type,NotAList);
    	i=ia->offs+sizeof(ListAttr)+ia->type->size*pos;
        }
        *attr=ia;
        return i;
    }
    
    AttrIter ClassAttrFirst(CLASSv descr) {
        if (descr->inherits && descr!=Class) return ClassAttrFirst(descr->inherits);
        else {
    	ATTRv* first=&descr->attrs[0];
    	if (first->type) return first->offs;
    	else return NULL;
        }
    }
    
    void ClassAttrNext(CLASSv descr, AttrIter* i) {
        
    }
    
    void* ClassAlloc(CLASSv cl, int nElem) {
        ATTRv* fixed=cl->fixed;
        int size=fixed->offs; int lSize;
        OBJv o; BOOL isList=fixed->type!=NULL;
        if (isList) {
    	lSize=nElem*fixed->type->size;
    	size+=sizeof(ListAttr)+lSize;
        }
        o=(OBJv)malloc(size);
        o->descr=ObjCpy(cl);
        o->usage=1;
        if (isList) {
    	/* init list attribute, empty list of given size */
    	ListAttr* l=offset(o, fixed->offs, ListAttr*);
    	l->tail=(BYTE*)(l+1);
    	l->end=l->tail+lSize;
    	l->tail=l->end;
        }
        return o;
    }
    
    /**************************************************************************
    ** LIST OPERATIONS 
    **************************************************************************/
    
    
    void* ObjListNewImpl(void** obj, int dim, VALCLASSv type, void* more) {
        OBJv old=_getObj(*obj);
        OBJv   o; int offs; ListAttr* list;
        int dimSize=type->size*dim;
        o=ObjRealloc(old, sizeof(ListAttr)+dimSize); 
        ObjDoAttr(old, AttrCopyAction, (void*)displ(o,old));
        ObjDel(old); 
        offs=ClassListNew(&o->descr, type, more);
        /* initialize the ListAttr */
        list = offset(o,offs,ListAttr*);
        list->tail=offset(list+1,dimSize,BYTE*);
        list->end=list->tail;
        *obj=o;
        return offset(o, offs+sizeof(ListAttr), void*);
    }
    
    void* ObjListAddImpl(void** obj, Iter pos, int numAdd) {
        OBJv o=_getObj(*obj);
        ListAttr* list; ATTRv* elem; 
        int addSize; BYTE* head; BYTE* tail;
        ASSERT(ObjListInfo(o, &elem, &list),NotAList);
        head=(BYTE*)(list+1); tail=list->tail;
        addSize=numAdd*elem->type->size;
        if (!pos) pos=tail; /* append */
        if (o->usage>1) {
    	/* make a real copy with space for new elements */
    	OBJv old=o; int offs;
    	o=ObjRealloc(old, addSize);
    	offs=displ(o, old);
    	ObjDoAttr(old, AttrCopyAction, (void*)offs);
    	ObjDoInList(old, AttrCopyAction, elem, (void*)offs, head, pos);
    	ObjDoInList(old, AttrCopyAction, elem, cast(offs+addSize,void*), pos, tail);
    	list=offset(list, offs, ListAttr*);
    	list->tail=tail+offs+addSize;
    	list->end=list->tail; 
    	old->usage--; pos=cast(pos,BYTE*)+offs;
        }
        else {
    	if (tail+addSize<=list->end) {
    	    /* can grow, only move tail */
    	    ObjDoInListReverse(obj, AttrMoveAction, elem, (void*)addSize, pos, tail);
    	    list->tail+=addSize;
    	}
    	else {
    	    /* allocate a buffer, move old obj in new */
    	    OBJv old=o; int offs;
    	    o=ObjRealloc(old, addSize);
    	    offs=displ(o, old);
    	    ObjDoAttr(old, AttrMoveAction, (void*)offs);
    	    ObjDoInList(old, AttrMoveAction, elem, (void*)offs, head, pos);
    	    ObjDoInList(old, AttrMoveAction, elem, cast(offs+addSize,void*), pos, list->tail);
    	    list=offset(list, offs, ListAttr*);
    	    list->tail=tail+offs+addSize;
    	    list->end=list->tail; 
    	    ObjFree(old); pos=cast(pos,BYTE*)+offs;
    	}
        }
        *obj=_getVal(o);
        return pos;
    }
    
    void* ObjListAppImpl(void** obj, int num) {
        return ObjListAddImpl(obj, NULL, num);
    }
    
    void* ObjListInsImpl(void** obj, int num) {
        return ObjListAddImpl(obj, ObjListFirst(*obj), num);
    }
    
    void ObjListCut(void** obj, Iter pos, int numRem) {
        OBJv o=_getObj(*obj);
        ListAttr* list; ATTRv* elem; 
        int remSize; BYTE* head; BYTE* tail; void* cutPos;
        ASSERT(ObjListInfo(o, &elem, &list),NotAList);
        head=(BYTE*)(list+1); tail=list->tail;
        remSize=elem->type->size*numRem;
        if (!pos) pos=offset(tail, -remSize, Iter); /* remove at the end */
        cutPos=offset(pos, remSize, void*);
        if (o->usage>1) {
    	/* make a real copy skipping the removed elements */
    	OBJv old=o; int offs;
    	o=ObjRealloc(old, -remSize);
    	offs=displ(o, old);
    	ObjDoAttr(old, AttrCopyAction, (void*)offs);	     
    	ObjDoInList(old, AttrCopyAction, elem, (void*)offs, head, pos);
    	ObjDoInList(old, AttrCopyAction, elem, cast(offs-remSize,void*), cutPos, tail);
    	list=offset(list, offs, ListAttr*);
    	list->tail=tail+offs-remSize;
    	list->end=list->tail; 	
    	old->usage--;
        }
        else {
    	/* only move tail,leave space for grow */
            ObjDoInList(o, AttrDelAction, elem, NULL, pos, cutPos);
    	ObjDoInList(o, AttrMoveAction, elem, (void*)(-remSize), cutPos, tail);
    	list->tail-=remSize;
        }
        *obj=_getVal(o);
    }
    
    void ObjListGrow(void** obj, int num) {
        OBJv o=_getObj(*obj);
        ListAttr* list; ATTRv* elem; 
        int size; BYTE* head; BYTE* tail; void* cutPos;
        ASSERT(ObjListInfo(o, &elem, &list),NotAList);
        head=(BYTE*)(list+1); tail=list->tail;
        size=elem->type->size*num;
        if (o->usage>1 || offset(tail, size, BYTE*)>list->end) {
    	/* copy the list into a new buffer, making space for n elements */
    	OBJv old=o; int offs;
    	o=ObjRealloc(old, size-displ(tail, head));
    	offs=displ(o, old);
    	ObjDoAll(old, AttrCopyAction, (void*)offs);	     
    	list=offset(list, offs, ListAttr*);
    	list->end=offset(list->tail, size, BYTE*); 	
    	ObjDel(old);
        }
        *obj=o;
    }
    
    /* list access */
    
    void* ObjListInImpl(Iter i) {
        ASSERT(i, NoSuchElem);
        return i;
    }
    
    /* list iteration */
    
    Iter ObjListFirst(void* obj) {
        Iter i;
        ATTRv* elem; ListAttr* list;
        ASSERT(ObjListInfo(obj, &elem, &list), NotAList);
        i=list+1;
        if (i>=(void*)list->tail) i=NULL;
        return i;
    }
    
    void ObjListNext(void* obj, Iter* i) {
        Iter p=*i;
        ATTRv* elem; ListAttr* list;
        ASSERT(ObjListInfo(obj, &elem, &list), NotAList);
        p=offset(p, elem->type->size, Iter);
        if (p>=(void*)list->tail) p=NULL;
        *i=p;
    }
    
    Iter ObjListLast(void* obj) {
        Iter i;
        ATTRv* elem; ListAttr* list;
        ASSERT(ObjListInfo(obj, &elem, &list), NotAList);
        i=offset(list->tail, -elem->type->size, Iter);
        if (itype->size, Iter);
        if (ptype->size,Iter);
        if (i>=(void*)list->tail) i=NULL;
        return i;
    }
    
    /* conversions */
    
    int ObjListPos(void* obj, Iter i) {
        ATTRv* elem; ListAttr* list;
        ASSERT(ObjListInfo(obj, &elem, &list), NotAList);
        ASSERT(i,NoSuchElem);
        return displ(i, list+1)/elem->type->size;
    }    
    
    /* information */
    
    int ObjListCard(void* obj) {
        ATTRv* elem; ListAttr* list;
        if (ObjListInfo(obj, &elem, &list))
    	return displ(list->tail, list+1)/elem->type->size;    
        else return 0;
    }
    
    BOOL ObjListInfo(void* obj, ATTRv** elem, ListAttr** list) {
        ATTRv* fixed=ObjClass(obj)->fixed;
        if (!fixed->type) return FALSE;
        *list=offset(obj, fixed->offs, ListAttr*);
        lastAttr=*elem=fixed;
        return TRUE;
    }
    
    
    /* services */
    
    void ObjPrintDescr(CLASSv descr) {
        STRv name=ValToName(systemKnown,descr);
        if (name) {
          printf("%s",_Str(name));
        } 
        else {
            ObjPrintDescr(descr->inherits);
    	printf(" with:{");
    	ObjDoList(descr, AttrPrintAction, NULL);
    	printf("}");
        }
    }
        
    void ObjPrint(void* obj) {
        if (obj) {
          ObjPrintDescr(_getObj(obj)->descr);
          printf("[");
          ObjDoAll(obj, AttrPrintAction, NULL);
          printf("]");
        }
        else printf("NULL");
    }
    
    void ObjDebug(void* obj) {
        printf("%p: ", obj);
        if (obj) {
          OBJv o=_getObj(obj);
          ObjPrint(obj);
          printf(" ");
          /*ObjPrint(o->descr);*/
        }
        printf("\n");
    }
    
    typedef struct IntList {
        int num;
        int size;
        int arr[1];
    } IntList;
    
    typedef struct STRvList {
        int num;
        int size;
        STRv arr[1];
    } STRvList;
    
    typedef struct OBJvList {
        int   num;
        void* end;
        OBJv  arr[1];
    } OBJvList;
    
    
    
    /*******************************************************************
    ** PATH management
    *******************************************************************/
    
    BOOL IsKindOf(CLASSv c, CLASSv type) {return TRUE; }
    
    Prop PathProp=NULL;
    
    /* path allocation/creation */
    
    #define MAX_PATH 1024
    PATHo paths[MAX_PATH];
    PATHv theRoot=&bootPaths[0];
    PATHv freePath=&paths[4];
    
    PATHv PathAlloc() {
        PATHv p;
        /* p=freePath;
        freePath=p->from;*/
        p=typeAlloc(PATHo);
        return p;
    }
    
    void PathFree(PATHv path) {
        /*path->from=freePath;
        freePath=path;*/
        free(path);
    }
    
    /***********************************************************
    ** PATH MANAGEMENT
    ***********************************************************/
    
    void* PathGetError(PATHv p, void* from) { 
        THROW(NoVal);
    }
    
    void* PathGetVal(PATHv p, void* from) { 
        return offset(p->val, p->descr.offs,void*);
    }
    
    void* PathGetOffs(PATHv p, void* obj) {
        if (!obj) return NULL;  
        return ObjAttrInImpl(obj, p->descr.offs); 
    }
    
    void* PathGetName(PATHv p, void* obj) {
        if (!obj) return NULL;
        PathCompileImpl(p);
        return ObjAttrImpl(obj, p->descr.name, NULL); 
    }
    
    void PathInit() {
        PATHv curr;
        /* init path allocation  
        for (curr=paths; currfrom=curr+1;
        curr->from=NULL; freePath=paths; */
        /* init PathProp */
        PathProp=typeAlloc(CLASSoDICT);
        PathProp->equal=(ValComparer)PolyStrEqual;
        PathProp->hash=(ValHasher)PolyStrHash;
        PathProp->toKey=(KeyAccessor)KeyOffset;
        PathProp->toKeyInfo=mPtr(PATHo, descr.name);
        PathProp->repetitions=FALSE;
    }
    
    /* path creation */
    
    PATHv PathNew(PATHv from, STRv name) {
        PATHv p=PathAlloc();
        p->head.usage=1;
        p->head.descr=ObjCpy(theRoot->head.descr);
        p->from=ObjCpy(from); 
        p->depend=NULL;
        p->get=PathGetName;
        p->descr.name=StrCpy(name);
        p->descr.offs=0;
        p->descr.type=NULL;
        p->descr.more=NULL;
        p->val=NULL;
        DictAddPtr(&from->depend, p);
        return p;
    }
    
    PATHv PathDef(PATHv from, STRv name) {
        PATHv n, *p;
        if (!from->depend) from->depend=DictCreate(PathProp);
        p=&DictSet(&from->depend, &name, PATHv); n=*p;
        if (!n) { n=*p=PathNew(from, name); } 
        return n;
    }
    
    PATHv Path(char* path) {
        PATHv curr=theRoot;
        char* id;
        ParseStart(path); id=ParseId();
        while (id) {
    	curr=PathDef(curr, StrCpyS(id));
    	if (ParseSep()!='.') break;
    	id=ParseId();
        }
        ParseStop();
        return curr;
    }
    
    /* path access definition */
    
    PATHv PathStaticImpl(PATHv root, STRv name, void* val, VALCLASSv type, void* more) {
        PATHv path=PathDef(root, name);
        path->get=PathGetVal;
        path->val=val;
        path->descr.offs=0;
        path->descr.type=ObjCpy(type);
        if (more) path->descr.more=ObjCpy(more);
        else path->descr.more=NULL;
        return path;
    }
    
    void PathCompileImpl(PATHv path) {
        void* obj;
        PATHv from=path->from; ATTRv* myDescr=&path->descr;
        if (path->get==PathGetName) {
    	ATTRv* descr; void* val;
            /* not compiled yet */ 
    	ASSERT(from, NoStartingPoint);
    	PathCompileImpl(from);
    	descr=&from->descr;
    	if (descr->type) {
    	    /* I know what it is, then it must have attributes */
    	    ASSERT(descr->type==OBJvClass, NoAttributes);
    	    /* if there is type info, use it */
    	    if (descr->more) {
    		/* select attribute from class */
    		myDescr->offs=ClassAttrWith(descr->more, path->descr.name, &descr);
    		if (myDescr->offs) {
    		    /* if the attribute was found, copy 
    		    descriptor data into the path: COMPILE */
    		    myDescr->type=ObjCpy(descr->type);
    		    if (descr->more) myDescr->more=ObjCpy(descr->more);
    		    else myDescr->more=NULL;
    		    path->get=PathGetOffs;
    		}
    		else {
    		    /* if did'nt find attribute in the class,
    		    leave the path not compiled */
    		}
    	    }
    	    else {
    		/* if there was no type info in the object attribute,
    		leave the path not compiled */
    	    }
    	}
    	else {
    	    /* if the containing attribute is not known, 
    	    leave the path not compiled */
    	}
    	
        }
        else if (path->get==PathGetOffs) {
    	/* attribute: already compiled */
    	ASSERT(myDescr->type, UnknownVal);
        }
        else if (path->get==PathGetVal) {
    	/* root: already compiled */
    	ASSERT(myDescr->type, UnknownVal);
        }
    }
    
    void PathStable(PATHv path) {
        ObjCpy(path); /* locks the path */
    }
    
    /* path access/modification */
    
    void* PathGetImpl (PATHv path, VALCLASSv expected) {
        void* val;
        ASSERT(path, NoPath);
        /* try to get it directly */
        val=call(path->get)(path, NULL);
        if (!val) {
    	/* if not, go up, get the root and do it */ 
    	ASSERT(path->from, PathWithoutRoot);
    	val=call(path->get)(path, PathGetImpl(path->from,OBJvClass));
        }
        ASSERT(val, InvalidPath);
        ASSERT(path->descr.type==expected, TypeMismatch);
        return val;
    }
    
    void* PathChangeImpl(PATHv path) {
        /* go up until I find a val reference, then change objects
         * down to my path
         */
        void* val=call(path->get)(path, NULL);
        if (!val) {
    	void** from;
    	ASSERT(path->from, PathWithoutRoot);
    	from=PathChangeImpl(path->from);
    	/* but is from really a pointer to the obj value? */
    	ObjChangeImpl(from);
    	val=path->get(path, *from);	
        }
        ASSERT(val, InvalidPath);
        return val;
    }
    
    /*void PathDel (PATHv path) {
        if (!--path->usage) {
    	 hmmm... path allocated variables? 
    	PATHv from=path->from;
    	if (path->stable) return;
    	if (DictCard(from->depend)>1) {
    	    DictRemovePtr(&from->depend, path);
    	}
    	else {
    	    DictDestroy(from->depend);
    	    from->depend=NULL;
    	}
    	PathDel(from);
    	StrDel(path->name);
    	free(path);
        }
    }
    
    */
    
    /* path as handle */
    
    BOOL PathIs(PATHv path, CLASSv type) {
    }
    void PathPrint (PATHv path) {
        if (path) {
          if (path->from!=theRoot) {PathPrint(path->from); printf("."); }
          if (path->descr.name) printf(Str(path->descr.name));
        }
        else printf("NULL");
    }
    
    void* RefGetImpl (REF ref, VALCLASSv expected) {
        if (_getObj(ref)->descr==&bootPathClass) 
    	return PathGetImpl((PATHv)ref, expected);
        else return ref;
    }
    
    BOOL RefIsPath(REF ref) {
        return _getObj(ref)->descr==&bootPathClass;
    }
    
    void RefPrint(REF ref) {
        if (ref && RefIsPath(ref)) PathPrint((PATHv)ref);
        else ObjPrint(ref);
    }
    
    void RefDebug(REF ref) {
        printf("%p:", ref);
        if (ref && ((OBJv)ref)->usage>1) printf("u:%d",((OBJv)ref)->usage);
        RefPrint(ref);
        printf("\n");
    }
    
    
    
    
    
    #define _OBJ_H
    
    /* pre-defined types */
    
    typedef struct VALCLASSo*  VALCLASSv;
    typedef struct CLASSo*     CLASSv;
    typedef struct OBJo*	   OBJv;
    typedef int		   AttrIter;
    typedef struct PATHo*	   PATHv;
    typedef void*		   REF;
    
    
    typedef struct OBJo {
        int	       usage;
        CLASSv     descr;
    } OBJo;
    
    /* the attribute descriptor */
    
    typedef struct ATTRv {
        STRv	name;
        VALCLASSv	type;
        int		offs;
        void*	more;
    } ATTRv;
    
    typedef void (*AttrAction) (void* attr, ATTRv* a, void* more);
    typedef BOOL (*AttrCondition) (void* attr, ATTRv* a, void* more);
    
    /* the list header */
    
    typedef struct ListAttr {
        BYTE* tail;
        BYTE* end;
    } ListAttr;
    
    /* pre-defined objects */
    extern void* Object;
    extern void* Class;
    extern VALCLASSv intClass;
    extern VALCLASSv STRvClass;
    extern VALCLASSv OBJvClass;
    
    void ObjInit();
    
    /* object operations */
    void*	ObjCpy(void* obj);
    void	ObjDel(void* obj);
    void	ObjSet(void** dest, void* src);
    void*	ObjChangeImpl(void** obj);
    #define ObjChange(valPtr,type) ((type)ObjChangeImpl((void**)valPtr))
    void    ObjMakeClass(void* obj, STRv name);
    int	ObjHash(void* obj, int max);
    BOOL	ObjEqual(void* obj1, void* obj2);
    
    /* object information */
    int	ObjShared(void* obj);
    int	ObjSize(OBJv obj);
    
    /* attribute operations */
    void*	ObjAttrNewImpl  (void** obj, STRv name, VALCLASSv type, void* more);
    #define ObjAttrNew(valPtr,name,type) (*(type*)ObjAttrNewImpl((void**)valPtr,name,type##Class,NULL))
    #define ObjAttrNewRef(valPtr,name,refType) (*(refType*)ObjAttrNewImpl((void**)valPtr,name,OBJvClass,NULL))
    ATTRv*	ObjAttrInfo(void* obj, AttrIter i);
    
    /* attribute access */
    void*	ObjAttrInImpl(void* obj, AttrIter i);
    void*	ObjAttrImpl(void* obj, STRv name, VALCLASSv type);
    #define ObjAttrIn(obj, iter, type) (*(type*)ObjAttrInImpl(obj, iter))
    #define ObjAttr(obj, name, type) (*(type*)ObjAttrImpl(obj, name, type##Class))
    
    /* attribute iteration */
    AttrIter  ObjAttrWith(void* obj, STRv name);
    AttrIter  ObjAttrFirst(void* obj);
    void	  ObjAttrNext(void* obj, AttrIter* i);
    STRv	  ObjAttrName(void* obj, AttrIter offs);
    
    /* member pointer support */
    CLASSv    ObjClass(void* obj);
    AttrIter  ClassAttrWith(CLASSv descr, STRv name, ATTRv** attr);
    AttrIter  ClassAttrFirst(CLASSv descr);
    void	  ClassAttrNext(CLASSv descr, AttrIter* i);
    
    /* list operations */
    void*	ObjListNewImpl(void** obj, int dim, VALCLASSv type, void* more);
    void*   ObjListAddImpl(void** obj, Iter pos, int numAdd);
    void*   ObjListAppImpl(void** obj, int num);
    void*   ObjListInsImpl(void** obj, int num);
    void    ObjListCut    (void** obj, Iter pos, int numRem);
    void	ObjListGrow   (void** obj, int num);
    
    #define ObjListNew(valPtr,dim,type) (*(type*)ObjListNewImpl((void**)valPtr,dim,type##Class,NULL))
    #define ObjListApp(valPtr,type) (*(type*)ObjListAppImpl((void**)valPtr,1))
    #define ObjListIns(valPtr,type) (*(type*)ObjListInsImpl((void**)valPtr,1))
    #define ObjListAdd(valPtr,pos,type) (*(type*)ObjListAddImpl((void**)valPtr,pos,1))
    #define ObjListAppMany(valPtr,num, type) (*(type*)ObjListAppImpl((void**)valPtr,num))
    #define ObjListInsMany(valPtr,num, type) (*(type*)ObjListInsImpl((void**)valPtr,num))
    #define ObjListAddMany(valPtr,pos, num, type) (*(type*)ObjListAddImpl((void**)valPtr,pos,num))
    
    /* list access */
    void*	 ObjListInImpl(Iter i);
    #define  ObjListAt(obj, pos, type) ObjListIn(ObjListWith(obj, pos), type)
    #define  ObjListIn(iter, type) (*(type*)ObjListInImpl(iter))
    
    /* list iteration */
    Iter	 ObjListFirst(void* obj);
    void	 ObjListNext(void* obj, Iter* i);
    Iter	 ObjListLast(void* obj);
    void	 ObjListPrev(void* obj, Iter* i);
    
    /* id conversions */
    Iter	 ObjListWith(void* obj, int pos);
    int	 ObjListPos(void* obj, Iter pos);
    AttrIter ObjListAttr(void* obj, Iter pos);
    Iter     ObjListWithAttr(void* obj, AttrIter a);
    
    /* information */
    int	ObjListCard(void* obj);
    BOOL	ObjListInfo(void* obj, ATTRv** elem, ListAttr** list);
    
    /* services */
    void	ObjPrint(void* obj);
    void	ObjScan(void* obj);
    BOOL	ObjEqual(void* obj1, void* obj2);
    int	ObjHash(void* obj, int max);
    void    ObjDebug(void* obj);
    
    /* action dispatchers */
    void	ObjDoAttr(void* obj, AttrAction act, void* info);
    void	ObjDoInList(void* obj, AttrAction act, ATTRv* elem, 
    	    void* info, void* from, void* to);
    void	ObjDoInListReverse(void* obj, AttrAction act, ATTRv* elem, 
    	    void* info, void* from, void* to);
    void	ObjDoList(void* obj, AttrAction act, void* info);
    void	ObjDoAll(void* obj, AttrAction act, void* info);
    
    /* predefined actions */
    void	AttrCopyAction(void* attr, ATTRv* a, void* copyOffs);
    void	AttrMoveAction(void* attr, ATTRv* a, void* moveOffs);
    void	AttrDelAction(void* attr, ATTRv* a, void* nothing);
    void	AttrPrintAction(void* attr, ATTRv* a, void* nothing);
    void    AttrStoreAction(void* attr, ATTRv* a, void* stream);
    void    AttrLoadAction(void* attr, ATTRv* a, void* stream);
    
    /* paths */
    
    extern PATHv theRoot;
    
    typedef void* (*PathActor)(PATHv self, ...);
    
    void PathInit();
    PATHv PathDef (PATHv root, STRv name);
    PATHv Path(char* path);
    void* PathGetImpl (PATHv path, VALCLASSv type);
    void  PathDel (PATHv path);
    void  PathPrint (PATHv path);
    
    REF  Ref(char* path);
    REF  RefCpy(REF r);
    REF  RefSet(REF* r, REF r1);
    void RefDel(REF r);
    void* RefGetImpl (REF r, VALCLASSv type);
    BOOL RefIsPath(REF r);
    
    /*PATHv PathRef(REF ref);
    void* PtrRef(REF ref);*/
    
    #define _get(ref,  type) ((type)RefGetImpl(ref, type##Class))
    PATHv PathStaticImpl(PATHv root, STRv name, void* val, VALCLASSv type, void* more);
    void  PathCompileImpl(PATHv path);
    void  PathSetStable(PATHv path);
    void* PathChangeImpl(PATHv path);
    
    #define PathChange(path, type) (*(type*)PathChangeImpl(path))
    
    #endif
    
    **
    **    $RCSfile: bnf2c.c,v $
    **    $Revision: 1.5 $
    **    $Date: 1996/07/18 09:10:20 $
    **    $Author: ulyanov $
    **
    **    $Locker:  $
    **    $State: Exp $
    **
    **
    */
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include "message.h"
    #include "regexp.h"
    #include "futil.h"
    #include "templ.h"
    #include "sm.h"
    #include "lst.h"
    #include "par.h"
    #include "strv.h"
    #include "dict.h"
    #include "variable.h"
    #include "toklist.h"
    #include "cursor.h"
    #include "icaprog.h"
    #include "icatask.h"
    #include "icarus.h"
    #include "icaarg.h"
    #include "icabnf.h"                                           
    
    #define i2cNodeClassNum 9
    
    #define _PrintClose(x) {	   \
      char *p;			   \
      p = strrchr(BuffGetPtr(x), ','); \
      if(p) {			   \
        *p = ' ';			   \
        p = BuffGetPtr(x);		   \
        BuffPrintF(x, "};\n\n");	   \
        TemplPrint("str", p);	   \
      }				   \
    } (void *)NULL
    
    typedef struct I2CoNode {
      void	*ptr;
      INT4	 index;
      INT4	 exeIndex[3];
    } I2CoNode, *I2CpNode;
    
    CLASSoDICT nodeDictClass = {
      PolyPtrEqual,
      PolyPtrHash,
      (KeyAccessor)KeyOffset,
      NULL,
      FALSE
    };
    
    static char     s1[999];
    static char     s2[999];
    static char     s3[999];
    static DICTv    i2cNodeDict;
    static I2CpNode i2cNode;
    static INT4     i2cNodeCount[i2cNodeClassNum];
    static SMpBUFF  i2cNodeBuff[i2cNodeClassNum],
    		i2cVarBuff,
    		i2cScopeNameBuff,
    		i2cTermReportBuff,
    		i2cChoiceSetBuff;
    
    extern ICAoJOB *Job;
    
    
    /****** I2cPrintVar *****************************************************
    **
    */
    
    static INT4 I2cPrintVar(VARo *var)
    {
      static INT4 i2cVarCount=-1;
      
      if(var) {
        BuffPrintF(i2cVarBuff, TemplSPrint(s3, TemplN(12, "format")), I2cBody(var));
        return(++i2cVarCount);
      }
      else
       return(-1);
    }
    
    /****** I2cRegisterNode *****************************************************
    **
    */
    
    static void I2cRegisterNode(BNFoNODE *bnfNode, INT4 level)
    {
      I2CpNode *p;
    
      INT4 i;
    
    /*   printf("Name:%s, level=%d\n", bnfNode->name, level); */
      p=&DictSet(&i2cNodeDict, &bnfNode, I2CpNode);
      if(!*p) {
        if(bnfNode->name) {
          SmSwapS(bnfNode->name, "\\", "\\\\");/* do this first!*/
          SmSwapS(bnfNode->name, "\"", "\\\"");
          SmSwapS(bnfNode->name, "\n", "\\n");
          SmSwapS(bnfNode->name, "\t", "\\t");
        }
        i2cNode = typeAlloc(I2CoNode);
        i2cNode->ptr  = (void *)bnfNode;
        i2cNode->index  = i2cNodeCount[bnfNode->type]++;
        if(bnfNode->type != Term && bnfNode->type != Choice)
          for(i=0; i<3; i++)
            i2cNode->exeIndex[i] = I2cPrintVar(bnfNode->exec[i]);
        *p=i2cNode;
      }
      return;
    }
    
    /****** I2cPrintVarPtr *****************************************************
    **
    */
    
    static char *I2cPrintVarPtr(INT4 *counter)
    {
      static char buff[999];
      static char ref[999];
      INT4 i;
      
      buff[0]='\0';
      
      for(i=0; i<3; i++) {
        if(*counter == -1)
          strcat(buff, ", 0");
        else {
          sprintf(ref, ", &%s[%d]",
            TemplSPrint(s3, TemplN(12, "arrName")), *counter);
          strcat(buff, ref);
        }
        counter++;
      }
      return(buff);
    }
    
    /****** I2cPrintNode *****************************************************
    **
    */
    
    static void I2cPrintNode(BNFoPRODUCTION *node, INT4 level)
    {
      I2CoNode *dependNode;
    
      INT4 i;
    
      i = node->type;
      i2cNode = DictAt(i2cNodeDict, &node, I2CpNode);
    
      switch (i) {
      case Production:
        dependNode = DictAt(i2cNodeDict, &(node->node), I2CpNode);
        BuffPrintF(i2cNodeBuff[i], TemplSPrint(s1, TemplN(i+1, "format")),
          node->name, I2cPrintVarPtr(i2cNode->exeIndex),
                   TemplSPrint(s2, TemplN(node->node->type+1, "arrName")),
    	       dependNode->index); 
        break;
      case ProdName:
        dependNode=DictAt(i2cNodeDict,&((BNFoPRODNAME *)node)->production,I2CpNode);
        BuffPrintF(i2cNodeBuff[i], TemplSPrint(s1, TemplN(i+1, "format")),
                   node->name, I2cPrintVarPtr(i2cNode->exeIndex),
                   TemplSPrint(s2, TemplN(Production+1, "arrName")),
    	       dependNode->index); 
        break;
      case Literal:
        BuffPrintF(i2cNodeBuff[i], TemplSPrint(s1, TemplN(i+1, "format")),
                   node->name, I2cPrintVarPtr(i2cNode->exeIndex));
        break;
      case Regexp:
        BuffPrintF(i2cNodeBuff[i], TemplSPrint(s1, TemplN(i+1, "format")),
                   node->name, I2cPrintVarPtr(i2cNode->exeIndex));
        break;
      case Command:
      case LineStart:
        BuffPrintF(i2cNodeBuff[i], TemplSPrint(s1, TemplN(i+1, "format")),
                   I2cPrintVarPtr(i2cNode->exeIndex));
        break;
      case Choice:
      case Term:
        BuffPrintF(i2cNodeBuff[i], TemplSPrint(s1, TemplN(i+1, "format")));
        break;
      default:
        break;
      }
    }
    
    /****** I2cPrintTermReport *************************************************
    **
    */
    
    static void I2cPrintTermReport(BNFoNODE *node, INT4 level)
    {
      BNFoREPORT *report;
      BNFoNODE   *nextNode;
    
      switch (node->type) {
      case Term:
        report = ((BNFoTERM *)node)->factorList;                                
        while( report->node ) {                            
          nextNode = report->node;
          i2cNode = DictAt(i2cNodeDict, &nextNode, I2CpNode);
          BuffPrintF(i2cTermReportBuff, TemplSPrint(s1, TemplN(10, "format")),
            report->counter, TemplSPrint(s2, TemplN(nextNode->type+1, "arrName")),
            i2cNode->index);  
          report++;
        }
        BuffPrintF(i2cTermReportBuff, TemplSPrint(s1, TemplN(10, "arrName")));
        break;
      default:
        break;
      }
    }
    
    /****** I2cPrintChoiceSet *************************************************
    **
    */
    
    static void I2cPrintChoiceSet(BNFoNODE *node, INT4 level)
    {
      BNFoNODE    **termList;
      BNFoNODE     *nextNode;
    
      switch (node->type) {
      case Choice:
        termList = ((BNFoCHOICE *)node)->termList;
        while( *termList ) {                            
          nextNode = *termList;
          i2cNode = DictAt(i2cNodeDict, &nextNode, I2CpNode);
          BuffPrintF(i2cChoiceSetBuff, TemplSPrint(s1, TemplN(11, "format")),
                     TemplSPrint(s2, TemplN(nextNode->type+1, "arrName")),
    		 i2cNode->index);  
          termList++;
        }
        BuffPrintF(i2cChoiceSetBuff, TemplSPrint(s1, TemplN(11, "arrName")));
        break;
      default:
        break;
      }
    }
    
    /*api** I2cBnfGenerator *************************************************
    **
    **   Take the BNF production list and generate initialization arrays and
    **   C code to reproduce this list in the computer memory
    **
    **      INPUT:      address of production list object [R]
    ** 
    **      RETURNS:
    */
    
    void I2cBnfGenerator(VARo *prodList)
    {
    
      VARo  *var;
      TEMPLv template;
    
      INT4 i;
    
      nodeDictClass.toKeyInfo = mPtr(I2CoNode, ptr);
      i2cNodeDict = DictCreate(&nodeDictClass);
    
      template=TemplOpen("SRSICA:ica2c.it", ParGetStr("ica2cName"));
      I2cSetTemplate(template);
      TemplWith(template, "$bnf2c");
      TemplPrint("prologue");
      TemplWith(template, "node");
      for(i=0; iscope->varN; i++) {
        BuffPrintF(i2cScopeNameBuff, TemplSPrint(s1, TemplN(13, "format")),
                   VarGetName(&Job->scope->var[i]));
      }
    
      for(i=0; iscope->varN);
      TemplEndWith();
      TemplPrint("str", "\n");
      
      
      _PrintClose(i2cScopeNameBuff);
      _PrintClose(i2cVarBuff);
      for(i=2; i
    #include 
    #include 
    #include 
    
    
    #include "message.h"
    #include "futil.h"
    #include "sm.h"
    #include "tm.h"
    #include "binpack.h"
    #include "btree.h"
    #include "ids.h"
    
    #ifdef __ALPHA
    # define MBCW  , "mbc=16"
    # define MBCR  , "mbf=10" , "mbc=16" 
    #else
    # ifdef VAX
    #  define MBCW  , "mbc=16"
    #  define MBCR  , "mbf=10" , "mbc=16"  
    # else
    #  define MBCW
    #  define MBCR
    # endif
    #endif
    
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  for encapsulating bucket types as 'objects'
    */
    
    #ifdef xxx
    RecordHasher
    
        switch (indexCurr->valueType) { 
            case BTRxSTR: 
            case BTRxIDENTRY: 
                p = ((HASHSTROBJ*) obj)->value;
                len = strlen(p);
                break; 
            case BTRxNUM: 
                p = (char*) &((HASHNUMOBJ*) obj)->value;
                len = sizeof(((HASHNUMOBJ*) obj)->value);
                break; 
            case BTRxREAL: 
                p = (char*) &((HASHREALOBJ*) obj)->value;
                len = sizeof(((HASHREALOBJ*) obj)->value);
                break; 
        }
    
        for (i=0; i> 24)) ^ g;
        }
    
        return (INT4) h % table->max_hash_elem;
    
    
    RecordPacker
    
        case BTRxIDENTRY:
          _BinPackFip (bucketBuff, record->r.id.textFip);
          _BinPackFip (bucketBuff, record->r.id.dataFip);
          _BinPackByte (bucketBuff, record->r.id.fileX);
          break;
        case BTRxVALUE:
          _BinPackFip (bucketBuff, record->r.value.firstIdFip);
          _BinPackFip (bucketBuff, record->r.value.lastIdFip);
          _BinPackNum (bucketBuff, record->r.value.idN);
         break;
        case BTRxPOINTER:
          _BinPackFip (bucketBuff, record->r.pointer.downFip);
          _BinPackNum (bucketBuff, record->r.pointer.downSize);
          break;
    
    RecordCopier
    
      switch (record->type) {
      case BTRxIDENTRY:
        recordSize = 9;
        break;
      case BTRxVALUE:
        recordSize = 12;
        break;
      case BTRxPOINTER:
        recordSize = 8;
        break;
      }
    
    RecordUnpacker
    
        case BTRxIDENTRY:
          _BinUnpackFip (bucketBuff, record->r.id.textFip);
          _BinUnpackFip (bucketBuff, record->r.id.dataFip);
          _BinUnpackByte (bucketBuff, record->r.id.fileX);
          break;
        case BTRxVALUE:
          _BinUnpackFip (bucketBuff, record->r.value.firstIdFip);
          _BinUnpackFip (bucketBuff, record->r.value.lastIdFip);
          _BinUnpackNum (bucketBuff, record->r.value.idN);
          break;
        case BTRxPOINTER:
          _BinUnpackFip (bucketBuff, record->r.pointer.downFip);
          _BinUnpackNum (bucketBuff, record->r.pointer.downSize);
          break;
    
    ValComparer
        switch (indexCurr->valueType) { 
            case BTRxSTR: 
            case BTRxIDENTRY: 
                return  strcmp( ((HASHSTROBJ*)obj1)->value,
                                ((HASHSTROBJ*)obj2)->value );
            case BTRxNUM: 
                return  ((HASHNUMOBJ*)obj1)->value - ((HASHNUMOBJ*)obj2)->value;
            case BTRxREAL: 
                if ( ((HASHREALOBJ*)obj1)->value < ((HASHREALOBJ*)obj2)->value )
                    return -1;
                if ( ((HASHREALOBJ*)obj1)->value > ((HASHREALOBJ*)obj2)->value )
                    return 1;
                return 0;
        }
    
    
    #endif
    
      
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  some contants
    */
    
    #define BTRxMAXLEVEL 2
    #define BTRxPTRRECADDSIZ 8
    #define BTRxBUCKETADDSIZ 16
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  prototypes of static functions
    */
    
    static void BtrWriteInfo (BTRo *btree);
    static INT4 BtrReadInfo (BTRo *btree);
    static void BtrFlush (BTRo *btree);
    static FIP BtrWrite (BTRo *btree, char *buff, INT4 size, INT4 levelN);
    static BTRoBUCKET *BtrBucketGet (BTRo *btree, enum BtrStep option);
    static BTRoBUCKET *BtrReadBucket (BTRo *btree, FIP bucketFip, INT4 bucketSize);
    static FIP BtrGetRecordNumber (BTRo *btree, BTRoBUCKET *bucket, 
    			       INT4 bucketRecX);
    static INT4 BtrFixedBucketSize (BTRo *btree, FIP fip);
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    **  external or module wide variables
    */
    
    static BTRo *btreeCurr;
    
    
    /**api* BtrOpen *************************************************************
    ** 
    **      Opens a B-tree for various access types. To close it again use
    **      BtrClose.
    **
    ** 	INPUT:	 o  address of file name [R]
    **               o  string specifying access type: 
    **                  "read", "update", "write" [R]
    **               o  address of error code [W] or NULL if not wanted
    ** returned values can be
    ** e__filopenerr
    ** e__indexbusy
    ** e__iscompressed ** ** IMPLICIT: ** ** RETURNS: new btree object ** NULL if there is a problem */ BTRo *BtrOpen (char *indexName, char *option, INT4 *errCode) { BTRo *btree; INT4 rv; *errCode = 0; if ((btree = (BTRo *) calloc (1, sizeof (BTRo))) == NULL) _ErrExit2 (e__allocfail, "btree-object"); btree->file = FileNew (indexName); FileSetName (btree->file, "ext", "inx"); FileSetUnixIo (btree->file); switch (tolower (option[0])) { /* ** open for read access - make sure the index is completed; */ case 'r': if (!FileOpen (btree->file)) { _ErrSet (errCode, e__filopenerr); break; } rv = BtrReadInfo (btree); _ErrIf (rv) break; if (btree->isBusy) { _ErrSet (errCode, e__indexisbusy); break; } btree->isFixedRecordSiz = btree->fixedRecordSiz ? 1 : 0; btree->firstBucketFip = btree->levelFip[2]; btree->lastBucketFip = btree->fileSize - btree->lastBucketSize; btree->bucketCurr = NULL; return btree; /* ** open for compress access - make sure the index is completed; */ case 'u': if (!FileOpen (FileSetUpdate (btree->file))) { _ErrSet (errCode, e__filopenerr); break; } if (_ErrIs (BtrReadInfo (btree))) return NULL; if (btree->isBusy) { _ErrSet (errCode, e__indexisbusy); return NULL; } if (btree->isCompressed) { _ErrExit2 (e__iscompressed, FileGetName (btree->file, "path")); } btree->isFixedRecordSiz = btree->fixedRecordSiz ? 1 : 0; btree->firstBucketFip = btree->levelFip[2]; btree->lastBucketFip = btree->fileSize - btree->lastBucketSize; btree->bucketCurr = NULL; btree->isBusy = 1; btree->levelWriteFip[2] = btree->firstBucketFip; BtrWriteInfo (btree); return btree; /* ** open for write access */ case 'w': if (!FileOpen (FileSetWrite (btree->file))) { _ErrSet (errCode, e__filopenerr); break; } btree->bucketRecordN = 0; btree->isWriteOpen = 1; btree->isBusy = 1; return btree; default: _ErrExit2 (e__unknownoption, option); } return btree; } /**api* BtrClose ************************************************************* ** ** Closes a btree which was opened by BtrOpen. ** ** INPUT: address of B-tree object [R] ** */ void BtrClose (BTRo *btree) { if (btree->isBusy) { if (btree->isWriteOpen) { BtrFlush (btree); btree->fileSize = btree->levelWriteFip[2]; _ErrMsg5 (i__wrotebtree, FileGetName (btree->file, "path"), ((btree->fileSize + 999) / 1000), btree->bucketRecordN, btree->recordN); } btree->isBusy = 0; btree->timeCreated = TimeGet (); BtrWriteInfo (btree); } FileDelete (btree->file); free (btree); } /****** BtrBucketNew ********************************************************** ** ** creates a new bucket; ** ** INPUT: address of Btree object [R] ** level number [R] ** ** IMPLICIT: ** ** RETURNS: ** address of new bucket */ static BTRoBUCKET *BtrBucketNew (BTRo *btree, INT4 levelN) { BTRoBUCKET *bucket; INT4 size; if ((bucket = (BTRoBUCKET *) malloc (sizeof (BTRoBUCKET))) == NULL) _ErrExit2 (e__allocfail, "bucket"); if ((bucket->record = (BTRoREC *) malloc (btree->bucketRecordN * sizeof (BTRoREC))) == NULL) _ErrExit2 (e__allocfail, "bucket buffer"); size = btree->bucketRecordN * BTRxTMPRECORDSIZ; if ((bucket->bucketBuff = (char *) malloc (size)) == NULL) _ErrExit2 (e__allocfail, "bucket buffer"); bucket->recordN = 0; bucket->up = 0; bucket->writePtr = 0; if (levelN == 2) { bucket->type = btree->leafType; bucket->fixedRecordSize = btree->fixedRecordSiz; } else { bucket->type = BTRxPOINTER; bucket->fixedRecordSize = 0; } return bucket; } /****** BtrBucketKill *********************************************************** ** deletes a bucket ** ** INPUT: address of Btree object [R] ** type of record to be put into bucket [R] ** ** IMPLICIT: ** ** RETURNS: ** address of new bucket */ static void BtrBucketKill (BTRoBUCKET *bucket) { if (bucket) { if (bucket->record) free (bucket->record); if (bucket->bucketBuff) free (bucket->bucketBuff); free (bucket); } } /**api* BtrSetType ************************************************************ ** ** sets the type of a Btree; ** ** INPUT: o address of btree object [R] ** o string specifying btree type: ** "ID", "str", "num", "real" [R] ** IMPLICIT: ** ** RETURNS: */ void BtrSetType (BTRo *btree, char *option) { if (btree->type) _ErrExit2 (e__parisdefined, "B-tree type"); switch (tolower (option[0])) { case 'i': btree->type = BTRxIDENTRY; btree->leafType = BTRxID; btree->isFixedRecordSiz = 1; btree->recordSiz = 9; break; case 's': btree->type = BTRxSTR; btree->leafType = BTRxVALUE; btree->recordSiz = 12; break; case 'n': btree->type = BTRxNUM; btree->leafType = BTRxVALUE; btree->recordSiz = 12; break; case 'r': btree->type = BTRxREAL; btree->leafType = BTRxVALUE; btree->recordSiz = 12; break; default: _ErrExit2 (e__unknownoption, option); } } /****** BtrWrite ************************************************************** ** ** writes a buffer to a file and returns its file offset; ** ** INPUT: o address of Btree object [R] ** o buffer [R] or NULL ** o size of bucket buffer [R] ** o level number (0,1,2 and -1 for info block) [R] ** IMPLICIT: ** ** RETURNS: file pointer to data written out */ static FIP BtrWrite (BTRo *btree, char *buff, INT4 size, INT4 levelN) { #define BTRxTMPBUFSIZ 20000 char tmp[BTRxTMPBUFSIZ]; long writeFip; INT4 sizeWritten; /* ** go to appropriate file offset */ if (levelN == -1) FileSeek (btree->file, 0); else { FileSeek (btree->file, btree->levelWriteFip[levelN]); } /* ** if buffer address is NULL write junk of specified size to file */ if (!buff) { for (sizeWritten=0; sizeWritten + BTRxTMPBUFSIZ <= size; sizeWritten += BTRxTMPBUFSIZ) FileWrite (btree->file, tmp, BTRxTMPBUFSIZ); FileWrite (btree->file, tmp, size - sizeWritten); } else FileWrite (btree->file, buff, size); /* ** and go back to previous location - assumed to be the end of file */ if (levelN < BTRxMAXLEVEL) FileSeekEnd (btree->file, 0); if (levelN == -1) return 0; else { writeFip = btree->levelWriteFip[levelN]; btree->levelWriteFip[levelN] += size; return writeFip; } } /****** BtrCopyRecord ********************************************************* ** ** copies a record into the appropriate position in the bucket ** ** INPUT: address of bucket object [W] ** address of record [R] ** IMPLICIT: ** btreeCurr (BTRo *) [R] ** ** RETURNS: ** the number of new record within bucket */ static INT4 BtrCopyRecord (BTRoBUCKET *bucket, BTRoREC *record) { BTRoREC *outrecord; INT4 recordSize; switch (record->type) { case BTRxIDENTRY: recordSize = 9; break; case BTRxVALUE: recordSize = 12; break; case BTRxPOINTER: recordSize = 8; break; } if (!bucket->writePtr) { bucket->writePtr = bucket->bucketBuff + (bucket->fixedRecordSize ? 0 : BTRxBUCKETADDSIZ); } bucket->writePtr += recordSize; outrecord = &bucket->record[bucket->recordN++]; memcpy (outrecord, record, sizeof (BTRoREC)); outrecord->str = bucket->writePtr; strcpy (outrecord->str, record->str); bucket->writePtr += bucket->fixedRecordSize ? btreeCurr->maxStrSiz : strlen (record->str) + 1; return bucket->recordN; } /****** BtrWriteInfo ********************************************************** ** ** writes an info block to the beginning of the file; ** ** INPUT: address of B-tree object [R] ** IMPLICIT: ** ** RETURNS: */ static void BtrWriteInfo (BTRo *btree) { char *buff = btree->infoBuff; char *buffSave = buff; INT4 buffSize; _BinPackNum (buff, BTRxINFOSIZE); _BinPackNum (buff, BTRxCURRENT_VERSION); /* version number */ _BinPackFip (buff, btree->writeFip); _BinPackFip (buff, btree->levelFip[0]); _BinPackFip (buff, btree->levelFip[1]); _BinPackFip (buff, btree->levelFip[2]); _BinPackFip (buff, btree->rootSize); _BinPackFip (buff, btree->firstBucketSize); _BinPackFip (buff, btree->lastBucketSize); _BinPackNum (buff, btree->leafType); _BinPackNum (buff, btree->type); _BinPackNum (buff, btree->bucketRecordN); _BinPackNum (buff, btree->recordN); _BinPackNum (buff, btree->fileSize); _BinPackNum (buff, btree->fixedRecordSiz); _BinPackNum (buff, btree->maxStrSiz); _BinPackNum (buff, btree->timeCreated); _BinPackByte (buff, btree->isCompressed); _BinPackByte (buff, btree->isBusy); _BinPackNum (buff, 0); /* dummies for later use */ _BinPackNum (buff, 0); _BinPackNum (buff, 0); _BinPackNum (buff, 0); _BinPackNum (buff, 0); FileSeek (btree->file, 0); buffSize = buff - buffSave; /* ** info block is written twice to the file ...once just after opening ** the index for writing (busy flag set to 1) and again just befor the ** index is closed; */ if (!btree->writeFip) BtrWrite (btree, buffSave, buffSize, -1); else FileWrite (btree->file, buffSave, buffSize); } /****** BtrReadInfo *********************************************************** ** ** Reads and unpacks info block of btree; ** ** INPUT: address of B-tree object [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** e__indexwrongversion + */ static INT4 BtrReadInfo (BTRo *btree) { char *buff = btree->infoBuff; INT4 tmp; FileSeek (btree->file, 0); FileRead (btree->file, buff, BTRxINFOSIZE); _BinUnpackNum (buff, btree->infoSize); _BinUnpackNum (buff, btree->versionN); if (btree->versionN != BTRxCURRENT_VERSION) _ErrRet4 (e__indexwrongversion, FileGetName (btree->file, "path"), btree->versionN, BTRxCURRENT_VERSION); _BinUnpackFip (buff, btree->writeFip); _BinUnpackFip (buff, btree->levelFip[0]); _BinUnpackFip (buff, btree->levelFip[1]); _BinUnpackFip (buff, btree->levelFip[2]); _BinUnpackFip (buff, btree->rootSize); _BinUnpackFip (buff, btree->firstBucketSize); _BinUnpackFip (buff, btree->lastBucketSize); _BinUnpackNum (buff, tmp); btree->leafType = (enum recType) tmp; _BinUnpackNum (buff, tmp); btree->type = (enum btrType) tmp; _BinUnpackNum (buff, btree->bucketRecordN); _BinUnpackNum (buff, btree->recordN); _BinUnpackNum (buff, btree->fileSize); _BinUnpackNum (buff, btree->fixedRecordSiz); _BinUnpackNum (buff, btree->maxStrSiz); _BinUnpackNum (buff, btree->timeCreated); _BinUnpackByte (buff, btree->isCompressed); _BinUnpackByte (buff, btree->isBusy); btree->rootFip = btree->levelFip[0]; return 1; } /****** BtrBucketPack *********************************************************** ** ** packs a bucket into platform independent format; ** ** INPUT: btree object [R] ** address of bucket object [R] ** IMPLICIT: ** ** RETURNS: ** size of bucket in bytes */ static INT4 BtrBucketPack (BTRo *btree, BTRoBUCKET *bucket) { BTRoREC *record; char *bucketBuff = bucket->bucketBuff; char *bucketBuffSave = bucketBuff; INT4 k; if (!bucket->fixedRecordSize) { _BinPackNum (bucketBuff, bucket->bucketSize); _BinPackNum (bucketBuff, bucket->prevBucketSize); _BinPackNum (bucketBuff, bucket->type); _BinPackNum (bucketBuff, bucket->recordN); } for (k=0; k < bucket->recordN; k++) { record = &bucket->record[k]; switch (bucket->type) { case BTRxIDENTRY: _BinPackFip (bucketBuff, record->r.id.textFip); _BinPackFip (bucketBuff, record->r.id.dataFip); _BinPackByte (bucketBuff, record->r.id.fileX); break; case BTRxVALUE: _BinPackFip (bucketBuff, record->r.value.firstIdFip); _BinPackFip (bucketBuff, record->r.value.lastIdFip); _BinPackNum (bucketBuff, record->r.value.idN); break; case BTRxPOINTER: _BinPackFip (bucketBuff, record->r.pointer.downFip); _BinPackNum (bucketBuff, record->r.pointer.downSize); break; } bucketBuff += bucket->fixedRecordSize ? btree->maxStrSiz : strlen (bucketBuff) + 1; } bucket->bucketSize = bucketBuff - bucketBuffSave; if (!bucket->fixedRecordSize) _BinPackNum (bucketBuffSave, bucket->bucketSize); /* to page begin */ return bucket->bucketSize; } /****** BtrBucketUnpack ********************************************************* ** ** unpacks a bucket from platform independent format; if readSize ** is by 4 bytes greater the actual bucket size then it reads the ** first four bytes of the next bucket with its size; ** ** INPUT: btree object [R] ** address of bucket object [R] ** IMPLICIT: ** ** RETURNS: ** size of bucket in bytes */ static void BtrBucketUnpack (BTRo *btree, BTRoBUCKET *bucket, INT4 readSize) { BTRoREC *record; char *bucketBuff = bucket->bucketBuff; INT4 k, tmp; if (!bucket->fixedRecordSize) { _BinUnpackNum (bucketBuff, bucket->bucketSize); _BinUnpackNum (bucketBuff, bucket->prevBucketSize); _BinUnpackNum (bucketBuff, tmp); bucket->type = (enum recType) tmp; _BinUnpackNum (bucketBuff, bucket->recordN); } else { bucket->type = btree->leafType; bucket->bucketSize = BtrFixedBucketSize (btree, bucket->fip); bucket->recordN = bucket->bucketSize / bucket->fixedRecordSize; bucket->prevBucketSize = btree->firstBucketFip == bucket->fip ? 0 : BtrFixedBucketSize (btree, btree->firstBucketFip); } for (k=0; k < bucket->recordN; k++) { record = &bucket->record[k]; switch (bucket->type) { case BTRxIDENTRY: _BinUnpackFip (bucketBuff, record->r.id.textFip); _BinUnpackFip (bucketBuff, record->r.id.dataFip); _BinUnpackByte (bucketBuff, record->r.id.fileX); break; case BTRxVALUE: _BinUnpackFip (bucketBuff, record->r.value.firstIdFip); _BinUnpackFip (bucketBuff, record->r.value.lastIdFip); _BinUnpackNum (bucketBuff, record->r.value.idN); break; case BTRxPOINTER: _BinUnpackFip (bucketBuff, record->r.pointer.downFip); _BinUnpackNum (bucketBuff, record->r.pointer.downSize); break; } record->str = bucketBuff; bucketBuff += bucket->fixedRecordSize ? btree->maxStrSiz : strlen (bucketBuff) + 1; } if (bucket->fip == btree->lastBucketFip) bucket->nextBucketSize = 0; else if (bucket->fixedRecordSize) bucket->nextBucketSize = BtrFixedBucketSize (btree, bucket->fip + bucket->bucketSize); else _BinUnpackNum (bucketBuff, bucket->nextBucketSize); } /****** BtrBucketInsertRecord *************************************************** ** ** inserts a record into bucket - recursive! ** ** INPUT: address of btree object [R] ** pointer to address of bucket object [W] ** address of record to be inserted [R] ** IMPLICIT: ** ** RETURNS: */ static void BtrBucketInsertRecord (BTRo *btree, BTRoBUCKET **bucketPtr, BTRoREC *record, INT4 levelN) { BTRoBUCKET *newbucket, *bucket = *bucketPtr; BTRoREC ptrrec; char stringBuff[133]; if (levelN < 0) return; /* ** if bucket == NULL it is assumed that the bucket is the new root bucket ** the first bucket of each ** level becomes the root ..since the tree grows from leafs to root ...the ** first bucket of the highest level will finally be the root */ if (!bucket) { bucket = BtrBucketNew (btree, levelN); btree->root = bucket; *bucketPtr = bucket; } /* ** if the bucket is full now, it can be written out ** ....a pointer to the bucket must be created and inserted in the upper ** level (recursive procedure) ** ... then a new empty bucket must be created */ if (BtrCopyRecord (bucket, record) == btree->bucketRecordN) { ptrrec.type = BTRxPOINTER; bucket->bucketSize = ptrrec.r.pointer.downSize = BtrBucketPack (btree, bucket); if (levelN == 2) { /* record bucket size of first and last */ if (bucket == btree->root) /* first in level 2 */ btree->firstBucketSize = bucket->bucketSize; else btree->lastBucketSize = bucket->bucketSize; } ptrrec.r.pointer.downFip = BtrWrite (btree,bucket->bucketBuff, bucket->bucketSize, levelN); ptrrec.str = stringBuff; strcpy (ptrrec.str, record->str); newbucket = BtrBucketNew (btree, levelN); newbucket->prevBucketSize = bucket->bucketSize; newbucket->up = bucket->up; newbucket->type = record->type; BtrBucketKill (bucket); /* old bucket can now be deleted */ BtrBucketInsertRecord (btree, &newbucket->up, &ptrrec, levelN-1); *bucketPtr = newbucket; } } /****** BtrFlush ************************************************************** ** ** writes all buckets that exist in memory to file proceeds from leaves to ** root; ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: */ static void BtrFlush (BTRo *btree) { BTRoBUCKET *bucket, *nextbucket; BTRoREC ptrrec, *record; char stringBuff[133]; INT4 level; if (!(bucket = btree->bucket)) return; for (level=2; level >= 0; level--) { /* ** if bucket contains any records then the last record must be inserted ** one level above as a pointer to the bucket; */ if (bucket->recordN) { ptrrec.type = BTRxPOINTER; bucket->bucketSize = ptrrec.r.pointer.downSize = BtrBucketPack (btree, bucket); if (level == 2) btree->lastBucketSize = bucket->bucketSize; ptrrec.r.pointer.downFip = BtrWrite (btree, bucket->bucketBuff, bucket->bucketSize, level); record = &bucket->record[bucket->recordN-1]; /** last record in bucket*/ ptrrec.str = stringBuff; strcpy (ptrrec.str, record->str); if (bucket == btree->root) /** no more buckets */ break; BtrBucketInsertRecord (btree, &bucket->up, &ptrrec, level-1); } nextbucket = bucket->up; BtrBucketKill (bucket); bucket = nextbucket; } btree->rootSize = btree->root->bucketSize; if (bucket == btree->root) BtrBucketKill (bucket); } /****** BtrReadBucket ********************************************************* ** ** reads a bucket from Btree; ** ** INPUT: address of Btree object [W] ** file pointer to bucket [R] ** size of bucket in bytes [R] ** IMPLICIT: ** ** RETURNS: */ static BTRoBUCKET *BtrReadBucket (BTRo *btree, FIP bucketFip, INT4 bucketSize) { BTRoBUCKET *bucket; INT4 size; /* ** get a bucket object */ bucket = BtrBucketNew (btree, bucketFip >= btree->firstBucketFip ? 2 : 0); bucket->fip = bucketFip; /* ** read from file and unpack bucket */ FileSeek (btree->file, bucketFip); /* ** try to read the bucket + the first 4 bytes of the next bucket that ** specifies its size ...this can be used for traversing a level */ size = bucketSize + (btree->isFixedRecordSiz ? 0 : 4); FileRead (btree->file, bucket->bucketBuff, size); BtrBucketUnpack (btree, bucket, size); return bucket; } /**api* BtrSearch ************************************************************* ** ** searches a value in btree; string comparison is case insensitive ** ** INPUT: btree object [R] ** string value [R] ** address of record ID [W] or NULL ** comparison length [R] or 0 ** ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ BTRoREC *BtrSearch (BTRo *btree, char *str, FIP *recNPtr, INT4 cmpLen) { BTRoBUCKET *bucket=btree->bucketCurr; BTRoREC *recordCurr; FIP bucketFip = btree->rootFip; INT4 bucketSize = btree->rootSize, k, l; double cmp; double searchval = 0; if (recNPtr) *recNPtr = 0; /*PURIFY*/ if (bucket) { BtrBucketKill (bucket); btree->bucketCurr = NULL; } if (btree->type == BTRxNUM) searchval = atoi(str); if (btree->type == BTRxREAL) searchval = atof(str); for (k=0; k < 3; k++) { bucket = BtrReadBucket (btree, bucketFip, bucketSize); for (l=0; l < bucket->recordN; l++) { recordCurr = &bucket->record[l]; /* ** goto lower level bucket if current record's value is equal or lesser */ switch (btree->type) { case BTRxNUM: cmp = searchval - atoi(recordCurr->str); break; case BTRxREAL: cmp = searchval - atof(recordCurr->str); break; default: cmp = (cmpLen) ? SmStrCmpLen (str, recordCurr->str, cmpLen) : SmStrCmp (str, recordCurr->str); } if (cmp <= 0) { if (bucket->type != BTRxPOINTER) { /* ** if found then save the record number and the context ** and return ...don't delete the bucket */ if (bucket->type == BTRxID && recNPtr) *recNPtr = BtrGetRecordNumber (btree, bucket, l); btree->bucketCurr = bucket; bucket->recordXCurr = l; recordCurr->type = btree->leafType; return (cmp == 0) ? recordCurr : NULL; } else { bucketFip = recordCurr->r.pointer.downFip; bucketSize = recordCurr->r.pointer.downSize; break; } } } BtrBucketKill (bucket); btree->bucketCurr = NULL; if (cmp > 0) { /* value is even greater than last string ...no hope! */ return NULL; } } return recordCurr; } /**api* BtrIsSearchGreaterMaxVal ********************************************** ** ** Returns 1 if value from previous search exceeded the max value in ** index; ** ** INPUT: o btree object [R] ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ INT4 BtrIsSearchGreaterMaxVal (BTRo *btree) { return btree->bucketCurr ? 0 : 1; } /**api* BtrIsSearchLessMinVal *********************************************** ** ** Returns 1 if value from previous search is below the min value in ** index; Use only after unsuccessful search. ** ** INPUT: o btree object [R] ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ INT4 BtrIsSearchLessMinVal (BTRo *btree) { return (btree->bucketCurr->fip == btree->firstBucketFip) && (btree->bucketCurr->recordXCurr == 0) ? 1 : 0; } /**api* BtrSearchId *********************************************************** ** ** searches a string value in btree; ** ** INPUT: o btree object [R] ** o string value [R] ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ BTRoID *BtrSearchId (BTRo *btree, char *str, FIP *fip) { BTRoREC *record; if (!(record = BtrSearch (btree, str, fip, 0))) return NULL; return &(record->r.id); } /**api* BtrSearchStr ********************************************************** ** ** searches a string value in btree; ** ** INPUT: o btree object [R] ** o string value [R] ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ BTRoVALUE *BtrSearchStr (BTRo *btree, char *str) { BTRoREC *record; if (!(record = BtrSearch (btree, str, NULL, 0))) return NULL; return &(record->r.value); } /**api* BtrSearchNum ********************************************************** ** ** searches a num (integer) value in btree; ** ** INPUT: o btree object [R] ** o num value [R] ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ BTRoVALUE *BtrSearchNum (BTRo *btree, INT4 num) { BTRoREC *record; char str[20]; sprintf(str, "%d", num); if (!(record = BtrSearch (btree, str, NULL, 0))) return NULL; return &(record->r.value); } /**api* BtrSearchReal ******************************************************* ** ** searches a real (double) value in btree; ** ** INPUT: o btree object [R] ** o real value [R] ** IMPLICIT: ** ** RETURNS: pointer to found record or NULL */ BTRoVALUE *BtrSearchReal (BTRo *btree, double real) { BTRoREC *record; char str[20]; sprintf(str, "%18.6f", real); if (!(record = BtrSearch (btree, str, NULL, 0))) return NULL; return &(record->r.value); } /****** BtrGetRecordNumber **************************************************** ** ** searches a string value in btree; ** ** INPUT: btree object [R] ** bucket object [R] ** index of record in bucket [R] ** IMPLICIT: ** ** RETURNS: number of record within the whole btree */ static FIP BtrGetRecordNumber (BTRo *btree, BTRoBUCKET *bucket, INT4 bucketRecX) { return (bucket->fip + (bucketRecX+1) * btree->fixedRecordSiz - btree->firstBucketFip) / btree->fixedRecordSiz; } /**api* BtrBuildStartPhase1 *************************************************** ** ** Initializes building phase 1.
    ** ** INPUT: address of Btree object [W] ** number of records to be inserted [R] ** IMPLICIT: ** ** RETURNS: */ void BtrBuildStartPhase1 (BTRo *btree, INT4 recordN) { INT4 k, bucketRecordN; if (!btree->isWriteOpen) _ErrExit2 (e__notwriteopen, FileGetName (btree->file, "path")); if (!btree->type) _ErrExit2 (e__parnotdefined, "B-tree type"); /* ** calculate the bucket size ... the btree must have three ** levels so the calculation is: bucketsize^3 > no of values */ if (recordN == 1) bucketRecordN = 1; /* k*k*k >= recordN should also work now ...*/ else for (k=0; k < 1000; k += k<10 ? 1 : 10) if (k*k*k > recordN) { bucketRecordN = k; break; } btree->bucketRecordN = bucketRecordN; btree->buildPhase = 1; btree->isBuildPhaseInit = 0; btreeCurr = btree; } /**api* BtrBuildStartPhase2 ********************************************** ** ** initializes building phase 2; ** ** INPUT: address of Btree object [W] ** IMPLICIT: ** ** RETURNS: */ void BtrBuildStartPhase2 () { if (btreeCurr->buildPhase != 1) _ErrExit2 (e__btreenotprep, 2); btreeCurr->buildPhase = 2; btreeCurr->isBuildPhaseInit = 0; } /**api* BtrInsertValue *************************************************** ** ** ** INPUT: address of Btree object [W] ** file pointer to bucket [R] ** size of bucket in bytes [R] ** IMPLICIT: ** btreeCurr [W] ** ** RETURNS: */ void BtrInsertRecord (BTRoREC *record) { static INT4 bucketRecordN, levelFip[3], recordCnt[3], strSiz; switch (btreeCurr->buildPhase) { /* ** phase I calculates the size of all records of all three levels */ case 1: if (!btreeCurr->isBuildPhaseInit) { /* init counters at begin */ btreeCurr->isBuildPhaseInit = 1; bucketRecordN = btreeCurr->bucketRecordN; levelFip[0] = levelFip[1] = levelFip[2] = 0; recordCnt[0] = recordCnt[1] = recordCnt[2] = 0; btreeCurr->maxStrSiz = 0; } /* ** add record string length and level specific record size to overall ** level size ....if record is last in bucket then do the same in uppper ** level */ strSiz = strlen (record->str) + 1; if (strSiz > btreeCurr->maxStrSiz) btreeCurr->maxStrSiz = strSiz; recordCnt[2]++; /* level 2 */ if (!(recordCnt[2] % bucketRecordN)) { recordCnt[1]++; /* level 1 */ levelFip[2] += strSiz + BTRxPTRRECADDSIZ; if (!(recordCnt[1] % bucketRecordN)) { recordCnt[0]++; /* level 0 - root bucket */ levelFip[1] += strSiz + BTRxPTRRECADDSIZ; } } break; case 2: if (!btreeCurr->isBuildPhaseInit) { btreeCurr->isBuildPhaseInit = 1; if (btreeCurr->isFixedRecordSiz) btreeCurr->fixedRecordSiz = btreeCurr->recordSiz + btreeCurr->maxStrSiz; else btreeCurr->fixedRecordSiz = 0; /* ** if the last record counted in phase one is not at the end(level II) ** of bucket then it must be entered in levels I and 0 */ btreeCurr->recordN = recordCnt[2]; { int isAddedToLevel2 = 0; if (recordCnt[2] % bucketRecordN) { recordCnt[1]++; levelFip[2] += strSiz + BTRxPTRRECADDSIZ; isAddedToLevel2 = 1; } if (recordCnt[1] % bucketRecordN || isAddedToLevel2) { recordCnt[0]++; levelFip[1] += strSiz + BTRxPTRRECADDSIZ; } } /* ** now, to get the sizes of the levels right the size of the ** extra information per bucket must be added */ levelFip[1] += BTRxBUCKETADDSIZ; /* only 1 bucket in level 0 */ levelFip[2] += ((recordCnt[1] + bucketRecordN-1) / bucketRecordN) * BTRxBUCKETADDSIZ; /* ** finally we can give for each level the offset within the output ** file (..offset for level 0 is directly after the btree-info-block) */ levelFip[0] = BTRxINFOSIZE; btreeCurr->levelFip[0] = btreeCurr->levelWriteFip[0] = levelFip[0]; btreeCurr->levelFip[1] = btreeCurr->levelWriteFip[1] = levelFip[0] + levelFip[1]; btreeCurr->levelFip[2] = btreeCurr->levelWriteFip[2] = levelFip[0] + levelFip[1] + levelFip[2]; /* ** reserve some space for all internal nodes in levels 0 and 1 ** this is done by writing some junk to the file */ BtrWrite (btreeCurr, NULL, btreeCurr->levelFip[2], -1); BtrWriteInfo (btreeCurr); btreeCurr->bucket = NULL; } BtrBucketInsertRecord (btreeCurr, &btreeCurr->bucket, record, 2); break; default: _ErrExit2 (e__btreenotprep, 1); } } /**api* BtrCompress *********************************************************** ** ** compress an btree, that is it's associated ID-list file; ** ** INPUT: address of Btree object [W] ** IMPLICIT: ** ** RETURNS: */ void BtrCompress (char *fileName) { IDSoFILE *idsFile; BTRoBUCKET *bucket; BTRo *btree; BTRoREC *record; INT4 opt, idN, errCode, k=0; btree = BtrOpen (fileName, "update", &errCode); _ErrExit2 (errCode, FileGetName (btree->file, "path")); if (!(idsFile = IdsOpen (fileName, "compress", 512, NULL, &errCode))) _ErrExit2 (errCode, fileName); if (btree->recordN) { btree->levelWriteFip[2] = btree->firstBucketFip; for (opt=BTRxFIRST; (record = BtrRecordGet (btree, opt)); opt=BTRxNEXT) { k++; idN = IdsCompress (idsFile, &record->r.value.firstIdFip); record->r.value.lastIdFip = record->r.value.firstIdFip; if (idN != record->r.value.idN) printf ("old: %d, new: %d\n", record->r.value.idN, idN); bucket = btree->bucketCurr; if (bucket->recordXCurr == bucket->recordN - 1) { BtrBucketPack (btree, bucket); BtrWrite (btree, bucket->bucketBuff, bucket->bucketSize, 2); } } } IdsClose (idsFile); btree->isCompressed = 1; BtrClose (btree); } /**api* BtrTouch ************************************************************** ** ** sets the internal index time to current time; ** ** INPUT: address of Btree object [W] ** IMPLICIT: ** ** RETURNS: */ void BtrTouch (char *fileName) { BTRo *btree; INT4 errCode; btree = BtrOpen (fileName, "update", &errCode); _ErrExit2 (errCode, FileGetName (btree->file, "path")); btree->timeCreated = TimeGet (); BtrClose (btree); } /****** BtrFixedBucketSize **************************************************** ** ** calculates the size of a bucket in a btree with fixed record size ** ** INPUT: address of Btree object [W] ** file address of bucket ** IMPLICIT: ** ** RETURNS: bucket size in Bytes */ static INT4 BtrFixedBucketSize (BTRo *btree, FIP fip) { INT4 size; if (!(fip == btree->lastBucketFip)) return (btree->fixedRecordSiz * btree->bucketRecordN); size = ((size = btree->recordN % btree->bucketRecordN) ? size : btree->bucketRecordN) * btree->fixedRecordSiz; return size; } /**api* BtrRecordById ********************************************************* ** ** gets record with specified number; recordId ranges from 0 to ** total no of records - 1; ** ** INPUT: address of Btree object [W] ** IMPLICIT: ** ** RETURNS: pointer to record ** NULL if not found */ BTRoREC *BtrRecordById (BTRo *btree, FIP recordId) { BTRoBUCKET *bucket=btree->bucketCurr; FIP fip; INT4 recordX, bucketSize=btree->fixedRecordSiz * btree->bucketRecordN; recordId--; /* convert number into index */ fip = recordId * btree->fixedRecordSiz; fip = btree->firstBucketFip + (fip / bucketSize) * bucketSize; if (!bucket || bucket->fip != fip) { /* get new bucket */ bucket = BtrReadBucket (btree, fip, BtrFixedBucketSize (btree, fip)); BtrBucketKill (btree->bucketCurr); btree->bucketCurr = bucket; } recordX = recordId % btree->bucketRecordN; btree->bucketCurr->recordXCurr = recordX; return &btree->bucketCurr->record[recordX]; } /**api* BtrRecordGet ********************************************************** ** ** gets record by specified option; ** ** INPUT: address of Btree object [W] ** location: BTRxFIRST, BTRxLAST, BTRxPREV, BTRxCURR, ** BTRxNEXT [R] ** IMPLICIT: ** ** RETURNS: pointer to record ** NULL if no more records */ BTRoREC *BtrRecordGet (BTRo *btree, enum BtrStep option) { BTRoBUCKET *bucket=btree->bucketCurr; BTRoREC *record; INT4 recordX; if (!btree->recordN) return NULL; switch (option) { case BTRxFIRST: bucket = BtrBucketGet (btree, BTRxFIRST); recordX = 0; break; case BTRxLAST: bucket = BtrBucketGet (btree, BTRxLAST); recordX = bucket->recordN - 1; break; case BTRxPREV: if (bucket->recordXCurr == 0) { if (!(bucket = BtrBucketGet (btree, BTRxPREV))) return NULL; recordX = bucket->recordN - 1; } else recordX = bucket->recordXCurr - 1; break; case BTRxCURR: if (!bucket) return NULL; recordX = bucket->recordXCurr; break; case BTRxNEXT: if (bucket->recordXCurr == bucket->recordN-1) { if (!(bucket = BtrBucketGet (btree, BTRxNEXT))) return NULL; recordX = 0; } else recordX = bucket->recordXCurr + 1; break; default: return NULL; } record = &bucket->record[recordX]; bucket->recordXCurr = recordX; record->type = btree->leafType; return record; } /****** BtrBucketGet ********************************************************** ** ** gets specified bucket ** ** INPUT: address of Btree object [W] ** location: BTRxFIRST, BTRxLAST, BTRxPREV, BTRxNEXT [R] ** IMPLICIT: ** ** RETURNS: pointer to bucket ** NULL if no more buckets */ static BTRoBUCKET *BtrBucketGet (BTRo *btree, enum BtrStep option) { BTRoBUCKET *bucket, *bucketCurr=btree->bucketCurr; switch (option) { case BTRxFIRST: bucket = BtrReadBucket (btree, btree->firstBucketFip, btree->firstBucketSize); break; case BTRxLAST: bucket = BtrReadBucket (btree, btree->lastBucketFip, btree->lastBucketSize); break; case BTRxPREV: if (bucketCurr && bucketCurr->fip == btree->firstBucketFip) return NULL; /* end of file */ bucket = BtrReadBucket (btree, bucketCurr->fip - bucketCurr->prevBucketSize, bucketCurr->prevBucketSize); break; case BTRxNEXT: if (bucketCurr && (bucketCurr->fip >= btree->lastBucketFip || btree->bucketRecordN == btree->recordN)) /*btree has only one bucket */ return NULL; /* end of file */ bucket = BtrReadBucket (btree, bucketCurr->fip + bucketCurr->bucketSize, bucketCurr->nextBucketSize); break; default: return NULL; } if (bucket) { BtrBucketKill (btree->bucketCurr); btree->bucketCurr = bucket; } return bucket; } /**api* BtrGetFileSize ******************************************************** ** ** gets file size in bytes; ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: file size in bytes */ INT4 BtrGetFileSize (BTRo *btree) { return btree->fileSize; } /**api* BtrGetRecordN ********************************************************* ** ** gets number of records in btree; ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: number of records */ INT4 BtrGetRecordN (BTRo *btree) { return btree->recordN; } /**api* BtrGetTimeCreated ***************************************************** ** ** gets creation time ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: number of records */ UINT4 BtrGetTimeCreated (BTRo *btree) { return btree->timeCreated; } /**api* BtrIsBusy ************************************************************* ** ** returns TRUE if the btree is still busy ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: 1 or 0; */ INT4 BtrIsBusy (BTRo *btree) { return btree->isBusy; } ** ** $RCSfile: btree.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/05/08 00:19:34 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS Copyright by Thure Etzold ** */ #define BTRxCURRENT_VERSION 1000000 #define BTRxTMPRECORDSIZ 132 #define BTRxINFOSIZE 96 enum btrType {BTRxIDENTRY=1, BTRxSTR, BTRxNUM, BTRxREAL}; enum recType {BTRxID=1, BTRxVALUE, BTRxPOINTER}; enum BtrStep {BTRxFIRST=1, BTRxLAST, BTRxCURR, BTRxNEXT, BTRxPREV}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** record of various types to be inserted into a bucket of a btree */ typedef struct BTRoPOINTER { FIP downFip; /* fip of lower level bucket */ INT4 downSize; /* size of lower level bucket */ } BTRoPOINTER; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** record of various types to be inserted into a bucket of a btree */ typedef struct BTRoVALUE { INT4 idN; /* number of IDs associated to value */ FIP firstIdFip; /* file address of first ID */ FIP lastIdFip; /* file address of last ID */ } BTRoVALUE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** record of various types to be inserted into a bucket of a btree */ typedef struct BTRoID { FIP textFip; /* file address of text part of entry */ FIP dataFip; /* file address of data part of entry */ char fileX; /* file index to point to source file in array of flatfiles */ } BTRoID; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** record of various types to be inserted into a bucket of a btree */ typedef struct BTRoREC { union { BTRoPOINTER pointer; BTRoID id; BTRoVALUE value; } r; char *str; /* string value */ enum recType type; } BTRoREC; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** bucket object; */ typedef struct BTRoBUCKET { char *bucketBuff; /* pointer to the buffer containing the packed bucket */ FIP fip; /* buckets address in the file */ enum recType type; char *writePtr; BTRoREC *record; /* array of records */ INT4 recordN; /* number of records in bucket */ struct BTRoBUCKET *up; /* address to upper level bucket */ INT4 bucketSize; /* size of bucket in bytes */ INT4 fixedRecordSize; INT4 nextBucketSize; /* size of bucket in bytes */ INT4 prevBucketSize; /* size of bucket in bytes */ INT4 recordXCurr; /* index of current record - for iteration */ } BTRoBUCKET; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** top level object describing a Btree */ typedef struct BTRo { struct FILEo* file; /* file handle to INX file */ BTRoBUCKET* root; /* pointer to root bucket */ struct BTRoBUCKET* bucketCurr; FIP rootFip; /* file pointer to root node */ INT4 rootSize; /* size of root node */ char infoBuff[BTRxINFOSIZE]; /* buffer for info block */ char infoSize; FIP writeFip; /* write file pointer */ FIP levelWriteFip[3]; /* write file pointer */ FIP levelFip[3]; /* write file pointer */ INT4 buildPhase; INT4 isBuildPhaseInit; INT4 isWriteOpen; /* file open for write access */ INT4 isBusy; INT4 isCompressed; INT4 isFixedRecordSiz; INT4 maxStrSiz; INT4 recordSiz; /* size of record without string */ INT4 fixedRecordSiz; enum btrType type; /* type of Btree */ enum recType leafType; /* type of records in leaf */ INT4 bucketRecordN; INT4 fileSize; INT4 recordN; INT4 firstBucketSize; INT4 lastBucketSize; FIP firstBucketFip; FIP lastBucketFip; UINT4 timeCreated; INT4 versionN; BTRoBUCKET* bucket; /* pointer to leaf bucket currently written */ } BTRo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ BTRo *BtrOpen (char *file_nm, char *opt, INT4 *errCode); void BtrClose (BTRo *btree); void BtrCompress (char *fileName); void BtrTouch (char *fileName); /* manipulating or writing to Btree */ void BtrSetBucketSize (BTRo *btree, INT4 size); void BtrSetType (BTRo *btree, char *option); void BtrBuildStartPhase1 (BTRo *btree, INT4 recordN); void BtrBuildStartPhase2 (); void BtrInsertRecord (BTRoREC *record); /* reading from Btree */ BTRoREC *BtrSearch (BTRo *btree, char *str, FIP *fip, INT4 compLen); BTRoVALUE *BtrSearchStr (BTRo *btree, char *value); BTRoVALUE *BtrSearchNum (BTRo *btree, INT4 num); BTRoVALUE *BtrSearchReal (BTRo *btree, double real); BTRoID *BtrSearchId (BTRo *btree, char *str, FIP *idFip); INT4 BtrIsSearchGreaterMaxVal (BTRo *btree); INT4 BtrIsSearchLessMinVal (BTRo *btree); BTRoREC *BtrRecordGet (BTRo *btree, enum BtrStep option); BTRoREC *BtrRecordById (BTRo *btree, FIP recordId); /* info about btree */ INT4 BtrGetFileSize (BTRo *btree); INT4 BtrGetRecordN (BTRo *btree); INT4 BtrIsBusy (BTRo *btree); UINT4 BtrGetTimeCreated (BTRo *btree); ** ** $RCSfile: builtin.h,v $ ** $Revision: 1.13 $ ** $Date: 1996/08/12 11:21:58 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** from ODD file: "srsica:srswin.sdl" ** date of ODD compilation: 12-AUG-1996 12:41 ** */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Value in an enumeration */ #ifndef _ODDoVALUE #define _ODDoVALUE typedef struct ODDoVALUE { char *name; /* Name of value. */ INT4 n; /* Number value. */ char *rem; /* Comment field. */ } ODDoVALUE; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Argument of Icarus command. */ #ifndef _IARGoVALUE #define _IARGoVALUE typedef struct IARGoVALUE { char *name; /* Name of the argument in an Icarus program. */ char *rem; /* Comment field. */ unsigned char isUnnamed; /* Defines if parameter may be unnamed. */ unsigned char isRequired; /* Defines if parameter is required. */ unsigned char type; /* Type of the argument */ char *className; INT4 defInt; /* Default value of type 'int' arguments. */ char *defaultStr; /* Default value of type 'string' arguments. */ struct ODDoVALUE *vals; INT4 valsN; unsigned char isSet; struct VARo *val; } IARGoVALUE; #endif #ifndef _IARGoCOM #define _IARGoCOM typedef struct IARGoCOM { char *name; /* Name of command in Icarus programs. */ char *functionName; /* C function that implements the command. */ INT4 isShow; /* Determines whether the command should appear in the Icarus functions reference list. */ char *rem; /* Comment field. */ unsigned char returnType; /* Type of value to be returned (if any). */ INT4 time; /* Execution time of command. */ char *returnClass; unsigned char isDirectCall; /* Call function directly or via C-interface. */ char *methodOf; /* normal function. */ struct IARGoVALUE *args; INT4 argsN; INT4 (*function)(); /* Function to be executed for command. */ INT4 orderN; /* Number of arguments ordered from C function (via 'IargGetArgs'). */ INT4 orderAllocN; /* Number of orders currently allocated. */ struct IARGoVALUE **order; /* Array with a list of argument orders. */ } IARGoCOM; #endif #ifdef _INITOBJS ODDoVALUE ODDValue[] = { {"pre", 1, ""}, {"post", 2, ""}, {"out", 1, ""}, {"err", 2, ""}, {"all", 3, ""}, {"horiz", 0, ""}, {"vert", 1, ""}, {"horiz", 0, ""}, {"vert", 1, ""}, {"path", 1, "The complete path."}, {"dir", 2, "The directory name"}, {"ext", 3, "The file extension name (after the '.')."}, {"name", 4, "The name without directory and extension names."}, {"file", 4, "The name without the directory name"}, {"normal", 0, ""}, {"raw", 1, ""}, {"gcg", 1, ""}, {"msf", 2, ""}, {"pir", 3, ""}, {"plain", 4, ""}, {"fasta", 5, ""}, {"embl", 6, ""}, {"swiss", 7, ""}, {"clustal", 8, ""} }; IARGoVALUE IARGVALUE[] = { {"opnd", "", 1, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"t", "", 0, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"val", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"key", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"op", "", 1, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"a", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"b", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"val", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"name", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"key", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"index", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"var", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"name", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"opt", "", 0, 0, 1, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"file", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"body", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"body", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"i", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"c", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"u", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"b", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"body", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"list", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"var", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"c", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"b", "", 0, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"node", "", 0, 0, 3, "node", 0, "", &ODDValue[0], 0, 0, NULL}, {"prod", "", 0, 0, 3, "node", 0, "", &ODDValue[0], 0, 0, NULL}, {"reStr", "", 1, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"node", "", 1, 0, 3, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"t", "", 0, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"node", "", 1, 0, 3, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"prog", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"lookahead", "", 0, 0, 1, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 1, "", &ODDValue[0], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 2, "", &ODDValue[0], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 3, "", &ODDValue[0], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 4, "", &ODDValue[0], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 5, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 1, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 2, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 3, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 4, "", &ODDValue[0], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 5, "", &ODDValue[0], 0, 0, NULL}, {"prod", "", 1, 0, 9, "", 0, "", &ODDValue[0], 0, 0, NULL}, {"time", "", 0, 0, 1, "", 0, "", &ODDValue[0], 2, 0, NULL}, {"name", "", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "", 1, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"x", "", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"y", "", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"color", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"prod", "", 1, 0, 3, "production", 0, "", &ODDValue[2], 0, 0, NULL}, {"prod", "", 0, 0, 16, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"string", "", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"start", "The name of the start symbol (production).", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"file", "Selects opened file to be read for input.", 0, 0, 3, "file", 0, "", &ODDValue[2], 0, 0, NULL}, {"fileName", "Selects opened file to be read for input.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"show", "Sets display of the syntax before parsing.", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"skip", "The set of characters to be skipped as white space", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"comment", "Regular expression for skipping comments", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"tree", "Flag if set requests printing the syntax tree.", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"prod", "", 1, 0, 16, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"skip", "The set of characters to be skipped as white space", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"comment", "Regular expression for skipping comments", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"file", "Sets opened file as input.", 0, 0, 3, "file", 0, "", &ODDValue[2], 0, 0, NULL}, {"str", "Sets string as input.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"show", "Sets display of the syntax before parsing.", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"tree", "Flag if set requests printing the syntax tree.", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"job", "", 1, 0, 3, "job", 0, "", &ODDValue[2], 0, 0, NULL}, {"string", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"start", "The name of the start symbol (production).", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"file", "Selects opened file to be read for input.", 0, 0, 3, "file", 0, "", &ODDValue[2], 0, 0, NULL}, {"fileName", "Selects opened file to be read for input.", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"job", "", 1, 0, 3, "job", 0, "", &ODDValue[2], 0, 0, NULL}, {"job", "", 1, 0, 3, "job", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Name of the token list.", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"code", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"print", "", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"task", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"withCode", "", 0, 0, 1, "", 1, "", &ODDValue[2], 0, 0, NULL}, {"outFile", "Output file object.", 0, 0, 3, "file", 0, "", &ODDValue[2], 0, 0, NULL}, {"in", "Name of the input token table.", 1, 1, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"c", "Token code.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "Numerical token code.", 0, 0, 1, "", -1, "", &ODDValue[2], 0, 0, NULL}, {"p", "Name of production to be linked.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"t", "Name of task that if results in forced parsing.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"count", "", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"var", "", 0, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"file", "Symbolic name of the input file.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"in", "Name of the input token table.", 1, 1, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"c", "Token code.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "Numerical token code.", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"p", "Name of production to be linked.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"t", "Name of task that if results in forced parsing.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"count", "", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"var", "", 0, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"file", "Symbolic name of the input file.", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Name of ouput token table.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Name of ouput token table.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"len", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"len", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"len", "", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"c", "token code as a name", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "token code as a number", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "string to be written to the token table.\nIf left unspecified the current match, or current token ($Ct)\nis written.\n", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"c", "token code as a name", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "token code as a number", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "string to be written to the token table.\nIf left unspecified the current match, or current token ($Ct)\nis written.\n", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"c", "token code as a name", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"n", "token code as a number", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "string to be written to the token table.\nIf left unspecified the current match, or current token ($Ct)\nis written.\n", 0, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "String to be written to the token table.", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "String to be written to the token table.", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "String with which current match is to be replaced", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "String with which current match is to be replaced", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Name of requested token table.", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"flag", "", 0, 0, 2, "", 0, "nocase", &ODDValue[2], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 1, "", &ODDValue[2], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 2, "", &ODDValue[2], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 3, "", &ODDValue[2], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 4, "", &ODDValue[2], 0, 0, NULL}, {"value", "", 1, 0, 6, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 5, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 1, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 2, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 3, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 4, "", &ODDValue[2], 0, 0, NULL}, {"stack", "", 0, 0, 1, "", 5, "", &ODDValue[2], 0, 0, NULL}, {"val", "", 1, 0, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Parameter name.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"set", "", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Parameter name.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"set", "", 0, 0, 1, "", 2, "", &ODDValue[2], 0, 0, NULL}, {"name", "Parameter name.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"set", "", 0, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"name", "Parameter name.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"set", "", 0, 0, 1, "", 2, "", &ODDValue[2], 0, 0, NULL}, {"name", "Parameter name.", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"str", "Classical substr function", 1, 0, 9, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"s", "Start posilion inside of string", 0, 1, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"l", "subStr length if ommited - suffix", 0, 0, 1, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"com", "Unix command", 1, 1, 2, "", 0, "", &ODDValue[2], 0, 0, NULL}, {"off", "output suppresor flag", 0, 0, 1, "", 0, "", &ODDValue[2], 3, 0, NULL}, {"x", "Width of image in pixels", 0, 0, 1, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"y", "Height of image in pixels", 0, 0, 1, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"file", "Input gif file.", 0, 0, 2, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"im", "Input image.", 1, 1, 3, "image", 0, "", &ODDValue[5], 0, 0, NULL}, {"x1", "X-coordinate of lower right corner.", 0, 1, 1, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"y1", "Y-coordinate of lower right corner.", 0, 1, 1, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"x2", "X-coordinate of upper left corner.", 0, 1, 1, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"x3", "Y-coordinate of upper left corner.", 0, 1, 1, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"tile", "Image used for tiling.", 0, 0, 3, "image", 0, "", &ODDValue[5], 0, 0, NULL}, {"rgb", "Color specified as list of three RGB values", 0, 0, 16, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"filled", "Flag if rectangle should be filled or not", 0, 0, 2, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"s", "", 1, 0, 2, "", 0, "", &ODDValue[5], 0, 0, NULL}, {"orient", "Orientation of string.", 0, 0, 2, "", 0, "", &ODDValue[5], 2, 0, NULL}, {"font", "", 0, 0, 2, "", 0, "", &ODDValue[7], 0, 0, NULL}, {"x", "", 0, 0, 2, "", 0, "", &ODDValue[7], 0, 0, NULL}, {"y", "", 0, 0, 2, "", 0, "", &ODDValue[7], 0, 0, NULL}, {"color", "", 0, 0, 2, "", 0, "", &ODDValue[7], 0, 0, NULL}, {"s", "", 1, 0, 2, "", 0, "", &ODDValue[7], 0, 0, NULL}, {"orient", "Orientation of string.", 0, 0, 2, "", 0, "", &ODDValue[7], 2, 0, NULL}, {"font", "", 0, 0, 2, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"x", "", 0, 0, 2, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"y", "", 0, 0, 2, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"color", "", 0, 0, 2, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"style", " each pixel is represented by a color.", 0, 0, 16, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"mode", "", 0, 0, 9, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"file", "", 1, 0, 3, "file", 0, "", &ODDValue[9], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"mode", "", 0, 0, 9, "", 0, "", &ODDValue[9], 0, 0, NULL}, {"file", "", 1, 0, 3, "file", 0, "", &ODDValue[9], 0, 0, NULL}, {"t", "", 1, 0, 2, "", 0, "", &ODDValue[9], 5, 0, NULL}, {"s", "", 1, 0, 6, "", 0, "", &ODDValue[14], 0, 0, NULL}, {"f", "", 0, 0, 3, "file", 0, "", &ODDValue[14], 0, 0, NULL}, {"mode", "", 0, 0, 1, "", 0, "", &ODDValue[14], 2, 0, NULL}, {"s", "", 1, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"width", "", 0, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"min", "", 0, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"ident", "", 0, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 1, 0, 6, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"f", "", 1, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 1, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"val", "", 1, 0, 6, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"switch", "", 1, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"switch", "", 1, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"state", "0: turns skipping white space off
    \n1: turns it on again\n", 1, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 0, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"state", "0: turns skipping white space off
    \n1: turns it on again\n", 1, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 0, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 1, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"skip", "String containing characters to be removed from ends.\n", 0, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 1, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 2, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 3, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 4, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 5, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 6, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 7, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 8, "", &ODDValue[16], 0, 0, NULL}, {"n", "", 0, 0, 1, "", 9, "", &ODDValue[16], 0, 0, NULL}, {"name", "", 1, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"set", "", 1, 0, 3, "set", 0, "", &ODDValue[16], 0, 0, NULL}, {"q", "", 0, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"init", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"db", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"group", "", 1, 0, 3, "dbGroup", 0, "", &ODDValue[16], 0, 0, NULL}, {"index", "", 0, 1, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"group", "", 1, 0, 3, "dbGroup", 0, "", &ODDValue[16], 0, 0, NULL}, {"l", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"h", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"le", "", 0, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"re", "", 0, 0, 1, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"index", "", 0, 1, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"group", "", 1, 0, 3, "dbGroup", 0, "", &ODDValue[16], 0, 0, NULL}, {"op", "", 1, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s1", "", 0, 0, 3, "set", 0, "", &ODDValue[16], 0, 0, NULL}, {"s2", "", 0, 0, 3, "set", 0, "", &ODDValue[16], 0, 0, NULL}, {"op", "", 1, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s1", "", 0, 0, 3, "set", 0, "", &ODDValue[16], 0, 0, NULL}, {"s2", "", 0, 0, 3, "set", 0, "", &ODDValue[16], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 0, 0, 3, "set", 0, "", &ODDValue[16], 0, 0, NULL}, {"name", "", 1, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"fileName", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 1, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"infile1", "Name of input file with the search probe.", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"infile2", "Name of input file with the data bank.", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"field", "", 1, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"set", "", 0, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"list", "", 0, 0, 3, "sequence", 0, "", &ODDValue[16], 0, 0, NULL}, {"seq", "", 1, 0, 3, "sequence", 0, "", &ODDValue[16], 0, 0, NULL}, {"s", "", 0, 0, 9, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"seq", "", 1, 0, 3, "sequence", 0, "", &ODDValue[16], 0, 0, NULL}, {"seq", "", 1, 0, 3, "sequence", 0, "", &ODDValue[16], 0, 0, NULL}, {"name", "", 0, 0, 2, "", 0, "", &ODDValue[16], 0, 0, NULL}, {"format", "", 0, 0, 1, "", 0, "", &ODDValue[16], 8, 0, NULL}, {"width", "", 0, 0, 1, "", 60, "", &ODDValue[24], 0, 0, NULL}, {"op", "", 1, 0, 2, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"s", "", 1, 0, 2, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"s", "", 1, 0, 2, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"thirds", "", 1, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"s", "", 0, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"l", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"r", "", 0, 0, 6, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"state", "", 1, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"name", "", 1, 0, 9, "", 0, "", &ODDValue[24], 0, 0, NULL}, {"fip", "", 0, 0, 1, "", 0, "", &ODDValue[24], 0, 0, NULL} }; IARGoCOM IARGCOM[] = { {"_prog", "IopProg_", 0, "", 2, 8, "", 0, "", &IARGVALUE[0], 0, NULL, 0, 0, NULL}, {"_opnd", "IopOpnd_", 0, "", 6, 8, "", 0, "", &IARGVALUE[0], 2, NULL, 0, 0, NULL}, {"_list", "IopList_", 0, "", 6, 8, "", 0, "", &IARGVALUE[2], 0, NULL, 0, 0, NULL}, {"_assoc", "IopAssoc_", 0, "", 6, 8, "", 0, "", &IARGVALUE[2], 2, NULL, 0, 0, NULL}, {"_binop", "IopBinop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[4], 3, NULL, 0, 0, NULL}, {"_strmake", "IopStrMake_", 0, "", 6, 8, "", 0, "", &IARGVALUE[7], 0, NULL, 0, 0, NULL}, {"_makearg", "IopMakeArg_", 0, "", 6, 8, "", 0, "", &IARGVALUE[7], 2, NULL, 0, 0, NULL}, {"_select", "IopSelect_", 0, "", 6, 8, "", 0, "", &IARGVALUE[9], 3, NULL, 0, 0, NULL}, {"_func", "IopFunc_", 0, "", 6, 8, "", 0, "", &IARGVALUE[12], 0, NULL, 0, 0, NULL}, {"_body", "IopBody_", 0, "", 6, 8, "", 0, "", &IARGVALUE[12], 0, NULL, 0, 0, NULL}, {"_ref", "IopRef_", 0, "", 6, 8, "", 0, "", &IARGVALUE[12], 2, NULL, 0, 0, NULL}, {"_file", "IopFile_", 0, "", 6, 8, "", 0, "", &IARGVALUE[14], 1, NULL, 0, 0, NULL}, {"_pre", "IopPre_", 0, "", 6, 8, "", 0, "", &IARGVALUE[15], 1, NULL, 0, 0, NULL}, {"_init", "IopInit_", 0, "", 6, 8, "", 0, "", &IARGVALUE[16], 1, NULL, 0, 0, NULL}, {"_for", "IopFor_", 0, "", 6, 8, "", 0, "", &IARGVALUE[17], 4, NULL, 0, 0, NULL}, {"_foreach", "IopForeach_", 0, "", 6, 8, "", 0, "", &IARGVALUE[21], 3, NULL, 0, 0, NULL}, {"_while", "IopWhile_", 0, "", 6, 8, "", 0, "", &IARGVALUE[24], 2, NULL, 0, 0, NULL}, {"_if", "IopIf_", 0, "", 6, 8, "", 0, "", &IARGVALUE[26], 0, NULL, 0, 0, NULL}, {"_prod", "IopProd_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[26], 0, NULL, 0, 0, NULL}, {"_endProd", "IopEndProd_", 0, "", 6, 8, "", 0, "", &IARGVALUE[26], 2, NULL, 0, 0, NULL}, {"_expr", "IopExpr_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[28], 0, NULL, 0, 0, NULL}, {"_term", "IopTerm_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[28], 0, NULL, 0, 0, NULL}, {"_regexp", "IopRegexp_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[28], 1, NULL, 0, 0, NULL}, {"_literal", "IopLiteral_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[29], 1, NULL, 0, 0, NULL}, {"_makeOpt", "IopMakeOpt_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[30], 2, NULL, 0, 0, NULL}, {"_nodeProg", "IopNodeProg_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[32], 2, NULL, 0, 0, NULL}, {"_prodName", "IopProdName_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[34], 2, NULL, 0, 0, NULL}, {"_doCom", "IopCommand_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[36], 0, NULL, 0, 0, NULL}, {"_doInputEnd", "IopInputEnd_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[36], 0, NULL, 0, 0, NULL}, {"_nullNode", "IopNullNode_", 0, "", 3, 8, "node", 0, "", &IARGVALUE[36], 0, NULL, 0, 0, NULL}, {"_push", "IopPush_", 0, "", 2, 8, "", 0, "", &IARGVALUE[36], 2, NULL, 0, 0, NULL}, {"_push1", "IopPush_", 0, "", 2, 8, "", 0, "", &IARGVALUE[38], 2, NULL, 0, 0, NULL}, {"_push2", "IopPush_", 0, "", 2, 8, "", 0, "", &IARGVALUE[40], 2, NULL, 0, 0, NULL}, {"_push3", "IopPush_", 0, "", 2, 8, "", 0, "", &IARGVALUE[42], 2, NULL, 0, 0, NULL}, {"_push4", "IopPush_", 0, "", 2, 8, "", 0, "", &IARGVALUE[44], 2, NULL, 0, 0, NULL}, {"_push5", "IopPush_", 0, "", 2, 8, "", 0, "", &IARGVALUE[46], 2, NULL, 0, 0, NULL}, {"_pop", "IopPop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[48], 1, NULL, 0, 0, NULL}, {"_pop1", "IopPop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[49], 1, NULL, 0, 0, NULL}, {"_pop2", "IopPop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[50], 1, NULL, 0, 0, NULL}, {"_pop3", "IopPop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[51], 1, NULL, 0, 0, NULL}, {"_pop4", "IopPop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[52], 1, NULL, 0, 0, NULL}, {"_pop5", "IopPop_", 0, "", 6, 8, "", 0, "", &IARGVALUE[53], 1, NULL, 0, 0, NULL}, {"break", "IopBreak", 0, "", 2, 2, "", 0, "", &IARGVALUE[54], 2, NULL, 0, 0, NULL}, {"next", "IopNext", 0, "", 2, 8, "", 0, "", &IARGVALUE[56], 0, NULL, 0, 0, NULL}, {"continue", "IopContinue", 0, "", 2, 8, "", 0, "", &IARGVALUE[56], 0, NULL, 0, 0, NULL}, {"prod", "IopProd", 0, "", 2, 8, "", 0, "", &IARGVALUE[56], 1, NULL, 0, 0, NULL}, {"Prod", "IopProd", 1, "", 2, 8, "", 0, "", &IARGVALUE[57], 1, NULL, 0, 0, NULL}, {"CDefine", "IopCDefine", 0, "", 2, 8, "", 0, "", &IARGVALUE[58], 2, NULL, 0, 0, NULL}, {"test", "IopTest", 0, "Test command.", 1, 8, "", 0, "", &IARGVALUE[60], 3, NULL, 0, 0, NULL}, {"printProd", "IopPrintProduction", 0, "Prints a production.", 1, 8, "", 0, "", &IARGVALUE[63], 1, NULL, 0, 0, NULL}, {"Parse", "IopParse", 1, "Parses a string.", 2, 8, "", 0, "", &IARGVALUE[64], 9, NULL, 0, 0, NULL}, {"JobNew", "IopJobNew", 1, "Creates a new parsing job and associates it with a syntax and\nthe input. Use $JobTokens to start the parsing (lazy parsing) and\n$JobNext to move to the next job in the input stream.\n", 3, 8, "job", 0, "", &IARGVALUE[73], 7, NULL, 0, 0, NULL}, {"Fail", "IopFail", 1, "Can be used only in an action node. If called the action node reports\na parsing error which is treated in the same way as a 'normal' parsing\nerror from, eg, a literal. \n", 2, 8, "", 0, "", &IARGVALUE[80], 0, NULL, 0, 0, NULL}, {"JobNext", "IopJobNext", 1, "", 2, 8, "", 0, "", &IARGVALUE[80], 5, NULL, 0, 0, NULL}, {"JobEnd", "IopJobEnd", 1, "", 2, 8, "", 0, "", &IARGVALUE[85], 1, NULL, 0, 0, NULL}, {"JobTokens", "IopJobTokens", 1, "", 1, 8, "", 0, "", &IARGVALUE[86], 8, NULL, 0, 0, NULL}, {"In", "IopIn", 1, "Sets the input token table for parsing.", 1, 6, "", 0, "", &IARGVALUE[94], 8, NULL, 0, 0, NULL}, {"in", "IopIn", 0, "Sets the input token table for parsing.", 1, 6, "", 0, "", &IARGVALUE[102], 8, NULL, 0, 0, NULL}, {"Out", "IopOut", 1, "Sets the output table for all writing of tokens for the \ncurrent production and its dependants.\n", 2, 6, "", 0, "", &IARGVALUE[110], 1, NULL, 0, 0, NULL}, {"out", "IopOut", 0, "Sets the output table for all writing of tokens for the \ncurrent production and its dependants.\n", 2, 6, "", 0, "", &IARGVALUE[111], 1, NULL, 0, 0, NULL}, {"Getc", "IopGetc", 0, "", 2, 8, "", 1, "", &IARGVALUE[112], 1, NULL, 0, 0, NULL}, {"Len", "IopRestrictLength", 0, "", 2, 12, "", 1, "", &IARGVALUE[113], 1, NULL, 0, 0, NULL}, {"Mov", "IopMove", 1, "", 2, 4, "", 1, "", &IARGVALUE[114], 1, NULL, 0, 0, NULL}, {"Wrt", "IopWrt", 1, "This function can be called inside an action attached to the symbol of\na production. It writes the match of the current symbol or a specified\nstring into the output table specified by the most recent call of $out.\n", 2, 8, "", 1, "", &IARGVALUE[115], 3, NULL, 0, 0, NULL}, {"wrt", "IopWrt", 0, "This function can be called inside an action attached to the symbol of\na production. It writes the match of the current symbol or a specified\nstring into the output table specified by the most recent call of $out.\n", 2, 8, "", 1, "", &IARGVALUE[118], 3, NULL, 0, 0, NULL}, {"Uniq", "IopUniq", 1, "Exactly as $wrt but writes the token only into the table if it does\nnot already exist. Unique here means that both the token string as the\ntoken code are used for comparison.\n", 2, 8, "", 1, "", &IARGVALUE[121], 3, NULL, 0, 0, NULL}, {"App", "IopApp", 1, "", 2, 8, "", 1, "", &IARGVALUE[124], 1, NULL, 0, 0, NULL}, {"app", "IopApp", 0, "", 2, 8, "", 1, "", &IARGVALUE[125], 1, NULL, 0, 0, NULL}, {"Rep", "IopRep", 1, "Replaces the current token ($Ct) in case of a symbol match. The\ninput cursor is moved after the replaced string. \n", 2, 8, "", 0, "", &IARGVALUE[126], 1, NULL, 0, 0, NULL}, {"rep", "IopRep", 0, "Replaces the current token ($Ct) when \n", 2, 8, "", 0, "", &IARGVALUE[127], 1, NULL, 0, 0, NULL}, {"Not", "IopNot", 1, "", 2, 2, "", 0, "", &IARGVALUE[128], 0, NULL, 0, 0, NULL}, {"not", "IopNot", 0, "", 2, 2, "", 0, "", &IARGVALUE[128], 0, NULL, 0, 0, NULL}, {"noskip", "IopNoskip", 0, "", 2, 2, "", 0, "", &IARGVALUE[128], 0, NULL, 0, 0, NULL}, {"Noskip", "IopNoskip", 1, "", 2, 2, "", 0, "", &IARGVALUE[128], 0, NULL, 0, 0, NULL}, {"Request", "IopRequest", 1, "", 2, 8, "", 0, "", &IARGVALUE[128], 1, NULL, 0, 0, NULL}, {"nocase", "IcaOpSetFlag", 1, "", 2, 8, "", 0, "", &IARGVALUE[129], 1, NULL, 0, 0, NULL}, {"push", "IopPush", 1, "", 2, 8, "", 0, "", &IARGVALUE[130], 2, NULL, 0, 0, NULL}, {"push1", "IopPush", 0, "", 2, 8, "", 0, "", &IARGVALUE[132], 2, NULL, 0, 0, NULL}, {"push2", "IopPush", 0, "", 2, 8, "", 0, "", &IARGVALUE[134], 2, NULL, 0, 0, NULL}, {"push3", "IopPush", 0, "", 2, 8, "", 0, "", &IARGVALUE[136], 2, NULL, 0, 0, NULL}, {"push4", "IopPush", 0, "", 2, 8, "", 0, "", &IARGVALUE[138], 2, NULL, 0, 0, NULL}, {"push5", "IopPush", 0, "", 2, 8, "", 0, "", &IARGVALUE[140], 2, NULL, 0, 0, NULL}, {"pop", "IopPop", 1, "", 6, 8, "", 0, "", &IARGVALUE[142], 1, NULL, 0, 0, NULL}, {"pop1", "IopPop", 0, "", 6, 8, "", 0, "", &IARGVALUE[143], 1, NULL, 0, 0, NULL}, {"pop2", "IopPop", 0, "", 6, 8, "", 0, "", &IARGVALUE[144], 1, NULL, 0, 0, NULL}, {"pop3", "IopPop", 0, "", 6, 8, "", 0, "", &IARGVALUE[145], 1, NULL, 0, 0, NULL}, {"pop4", "IopPop", 0, "", 6, 8, "", 0, "", &IARGVALUE[146], 1, NULL, 0, 0, NULL}, {"pop5", "IopPop", 0, "", 6, 8, "", 0, "", &IARGVALUE[147], 1, NULL, 0, 0, NULL}, {"exit", "IopExit", 1, "", 2, 8, "", 0, "", &IARGVALUE[148], 1, NULL, 0, 0, NULL}, {"parStr", "IopParStr", 0, "Returns the value of a 'string' parameter or sets its value if \".set\" is \ndefined.\n", 9, 8, "", 0, "", &IARGVALUE[149], 2, NULL, 0, 0, NULL}, {"parInt", "IopParInt", 0, "Returns the value of an 'int' parameter or sets its value if \".set\" is \ndefined.\n", 1, 8, "", 0, "", &IARGVALUE[151], 2, NULL, 0, 0, NULL}, {"ParStr", "IopParStr", 1, "Returns the value of a 'string' parameter or sets its value if \".set\" is \ndefined.\n", 9, 8, "", 0, "", &IARGVALUE[153], 2, NULL, 0, 0, NULL}, {"ParInt", "IopParInt", 1, "Returns the value of an 'int' parameter or sets its value if \".set\" is \ndefined.\n", 1, 8, "", 0, "", &IARGVALUE[155], 2, NULL, 0, 0, NULL}, {"ParDel", "IopParDel", 1, "Deletes the parameter with specified name.\n", 2, 8, "", 0, "", &IARGVALUE[157], 1, NULL, 0, 0, NULL}, {"subStr", "IcaOpSubStr", 0, "", 9, 8, "", 0, "", &IARGVALUE[158], 3, NULL, 0, 0, NULL}, {"System", "IopSystem", 0, "", 9, 8, "", 0, "", &IARGVALUE[161], 2, NULL, 0, 0, NULL}, {"ImNew", "IgdImageCreate", 0, "Creates a new image optionally from a gif file.", 3, 8, "image", 0, "", &IARGVALUE[163], 3, NULL, 0, 0, NULL}, {"ImRect", "IgdRectangle", 0, "Creates a rectangle that can be optionally filed or tiled.", 3, 8, "image", 0, "", &IARGVALUE[166], 8, NULL, 0, 0, NULL}, {"string", "IgdString", 0, "", 2, 8, "", 0, "image", &IARGVALUE[174], 6, NULL, 0, 0, NULL}, {"ImString", "IgdString", 0, "", 2, 8, "", 0, "", &IARGVALUE[180], 6, NULL, 0, 0, NULL}, {"ImLine", "IgdLine", 0, "", 2, 8, "", 0, "", &IARGVALUE[186], 1, NULL, 0, 0, NULL}, {"ImCopy", "IgdImageCopy", 0, "", 2, 8, "", 0, "", &IARGVALUE[187], 0, NULL, 0, 0, NULL}, {"ImPoly", "IgdPoly", 0, "", 2, 8, "", 0, "", &IARGVALUE[187], 0, NULL, 0, 0, NULL}, {"ImArg", "IgdArc", 0, "", 2, 8, "", 0, "", &IARGVALUE[187], 0, NULL, 0, 0, NULL}, {"ImWrite", "IgdImageWrite", 0, "", 2, 8, "", 0, "", &IARGVALUE[187], 0, NULL, 0, 0, NULL}, {"fileOpen", "IopFileOpen", 0, "", 3, 8, "file", 0, "", &IARGVALUE[187], 2, NULL, 0, 0, NULL}, {"fileClose", "IopFileClose", 0, "", 2, 8, "", 0, "", &IARGVALUE[189], 1, NULL, 0, 0, NULL}, {"FileOpen", "IopFileOpen", 1, "", 3, 8, "file", 0, "", &IARGVALUE[190], 2, NULL, 0, 0, NULL}, {"FileClose", "IopFileClose", 1, "", 2, 8, "", 0, "", &IARGVALUE[192], 1, NULL, 0, 0, NULL}, {"_close", "", 0, "", 2, 8, "", 0, "file", &IARGVALUE[193], 0, NULL, 0, 0, NULL}, {"_next", "", 0, "", 2, 8, "", 0, "file", &IARGVALUE[193], 0, NULL, 0, 0, NULL}, {"_lineN", "", 0, "", 2, 8, "", 0, "file", &IARGVALUE[193], 0, NULL, 0, 0, NULL}, {"_name", "", 0, "", 2, 8, "", 0, "file", &IARGVALUE[193], 1, NULL, 0, 0, NULL}, {"print", "IopPrint", 1, "Prints a string.", 2, 8, "", 0, "", &IARGVALUE[194], 3, NULL, 0, 0, NULL}, {"nprint", "IopNPrint", 0, "Prints a string.", 2, 8, "", 0, "", &IARGVALUE[197], 1, NULL, 0, 0, NULL}, {"po", "IopPrintOpen", 0, "", 2, 8, "", 0, "", &IARGVALUE[198], 3, NULL, 0, 0, NULL}, {"pc", "IopPrintClose", 0, "", 2, 8, "", 0, "", &IARGVALUE[201], 0, NULL, 0, 0, NULL}, {"ps", "IopPrintString", 0, "Prints a string to output stream.", 2, 8, "", 0, "", &IARGVALUE[201], 1, NULL, 0, 0, NULL}, {"pf", "IopPrintFormat", 0, "Prints a string to output stream.", 2, 8, "", 0, "", &IARGVALUE[202], 1, NULL, 0, 0, NULL}, {"It", "IopInToken", 1, "", 9, 8, "", 0, "", &IARGVALUE[203], 1, NULL, 0, 0, NULL}, {"itc", "IopInTokenCode", 0, "", 9, 8, "", 0, "", &IARGVALUE[204], 0, NULL, 0, 0, NULL}, {"Itc", "IopInTokenCode", 1, "", 9, 8, "", 0, "", &IARGVALUE[204], 0, NULL, 0, 0, NULL}, {"ct", "IopCurrToken", 0, "", 9, 8, "", 0, "", &IARGVALUE[204], 0, NULL, 0, 0, NULL}, {"Ct", "IopCurrToken", 1, "", 9, 8, "", 0, "", &IARGVALUE[204], 0, NULL, 0, 0, NULL}, {"Key", "IopKey", 1, "", 9, 8, "", 0, "", &IARGVALUE[204], 1, NULL, 0, 0, NULL}, {"fip", "IopFip", 0, "", 1, 8, "", 0, "", &IARGVALUE[205], 1, NULL, 0, 0, NULL}, {"Fip", "IopFip", 1, "", 1, 8, "", 0, "", &IARGVALUE[206], 1, NULL, 0, 0, NULL}, {"skip", "IopSetSkip", 0, "Controls skipping of white space during parsing which is\nactive by default.\n", 2, 8, "", 0, "", &IARGVALUE[207], 2, NULL, 0, 0, NULL}, {"Skip", "IopSetSkip", 1, "Controls skipping of white space during parsing which is\nactive by default.\n", 2, 8, "", 0, "", &IARGVALUE[209], 2, NULL, 0, 0, NULL}, {"Trim", "IopStrTrim", 1, "Cuts leading or trailing white space from the string.", 9, 8, "", 0, "", &IARGVALUE[211], 2, NULL, 0, 0, NULL}, {"1", "IopSubMatch", 1, "Returns the first submatch of the most recent regular expression\nmatching. The submatch is indicated by parentheses within the\nregular expression and the opening parenthesis is used for counting.\n$2, $3 until $9 will return the submatches with the respective\nnumber. $0 returns the entire match.\n", 9, 8, "", 0, "", &IARGVALUE[213], 1, NULL, 0, 0, NULL}, {"2", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[214], 1, NULL, 0, 0, NULL}, {"3", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[215], 1, NULL, 0, 0, NULL}, {"4", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[216], 1, NULL, 0, 0, NULL}, {"5", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[217], 1, NULL, 0, 0, NULL}, {"6", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[218], 1, NULL, 0, 0, NULL}, {"7", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[219], 1, NULL, 0, 0, NULL}, {"8", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[220], 1, NULL, 0, 0, NULL}, {"9", "IopSubMatch", 0, "", 9, 8, "", 0, "", &IARGVALUE[221], 1, NULL, 0, 0, NULL}, {"SetFunctions", "IopSetFunctions", 0, "", 2, 8, "", 0, "", &IARGVALUE[222], 1, NULL, 0, 0, NULL}, {"SetResult", "QuerySaveResult", 0, "", 2, 8, "", 0, "", &IARGVALUE[223], 2, NULL, 0, 0, NULL}, {"DbGroup", "QueryDBGroup", 0, "", 3, 8, "dbGroup", 0, "", &IARGVALUE[225], 3, NULL, 0, 0, NULL}, {"SetRetrRange", "QueryRangeSearch", 0, "", 3, 8, "set", 0, "", &IARGVALUE[228], 6, NULL, 0, 0, NULL}, {"SetRetrStr", "QueryStrSearch", 0, "", 3, 8, "set", 0, "", &IARGVALUE[234], 3, NULL, 0, 0, NULL}, {"SetLogOp", "QueryLogOp", 0, "", 3, 8, "set", 0, "", &IARGVALUE[237], 3, NULL, 0, 0, NULL}, {"SetLinkOp", "QueryLinkOp", 0, "", 3, 8, "set", 0, "", &IARGVALUE[240], 3, NULL, 0, 0, NULL}, {"SetAssign", "QuerySetAssign", 0, "", 3, 8, "set", 0, "", &IARGVALUE[243], 2, NULL, 0, 0, NULL}, {"SetGet", "QuerySetGet", 0, "", 3, 8, "set", 0, "", &IARGVALUE[245], 2, NULL, 0, 0, NULL}, {"MakeWild", "QueryOpMakeWild", 0, "", 9, 8, "", 0, "", &IARGVALUE[247], 1, NULL, 0, 0, NULL}, {"GCGwordsearch", "GCGWordsearch", 0, "", 2, 8, "", 0, "", &IARGVALUE[248], 2, NULL, 0, 0, NULL}, {"setFormat", "EntryIopSetFieldFormat", 0, "", 2, 8, "", 0, "", &IARGVALUE[250], 2, NULL, 0, 0, NULL}, {"seqNew", "SeqIopNew", 0, "", 3, 8, "sequence", 0, "", &IARGVALUE[252], 2, NULL, 0, 0, NULL}, {"seqApp", "SeqIopApp", 0, "", 3, 8, "sequence", 0, "", &IARGVALUE[254], 2, NULL, 0, 0, NULL}, {"seqMake", "SeqIopMake", 0, "", 3, 8, "sequence", 0, "", &IARGVALUE[256], 1, NULL, 0, 0, NULL}, {"seqPrint", "SeqIopPrint", 0, "", 2, 8, "", 0, "", &IARGVALUE[257], 4, NULL, 0, 0, NULL}, {"calc", "IopCalc", 0, "", 1, 8, "", 0, "", &IARGVALUE[261], 3, NULL, 0, 0, NULL}, {"strlen", "IopStrlen", 0, "", 1, 8, "", 0, "", &IARGVALUE[264], 1, NULL, 0, 0, NULL}, {"Strlen", "IopStrlen", 1, "", 1, 8, "", 0, "", &IARGVALUE[265], 1, NULL, 0, 0, NULL}, {"HtmlSpace", "IopHtmlSpace", 0, "", 2, 8, "", 0, "", &IARGVALUE[266], 3, NULL, 0, 0, NULL}, {"=", "IopAss", 0, "", 6, 8, "", 0, "", &IARGVALUE[269], 2, NULL, 0, 0, NULL}, {"+", "IopAdd", 0, "", 1, 8, "", 0, "", &IARGVALUE[271], 2, NULL, 0, 0, NULL}, {"<", "IopLT", 0, "", 1, 8, "", 0, "", &IARGVALUE[273], 2, NULL, 0, 0, NULL}, {">", "IopGT", 0, "", 1, 8, "", 0, "", &IARGVALUE[275], 2, NULL, 0, 0, NULL}, {"==", "IopEq", 0, "", 1, 8, "", 0, "", &IARGVALUE[277], 2, NULL, 0, 0, NULL}, {"*", "IopMul", 0, "", 1, 8, "", 0, "", &IARGVALUE[279], 2, NULL, 0, 0, NULL}, {"/", "IopDivide", 0, "", 1, 8, "", 0, "", &IARGVALUE[281], 2, NULL, 0, 0, NULL}, {"!=", "IopNEq", 0, "", 1, 8, "", 0, "", &IARGVALUE[283], 2, NULL, 0, 0, NULL}, {"-", "IopSubt", 0, "", 1, 8, "", 0, "", &IARGVALUE[285], 2, NULL, 0, 0, NULL}, {"+=", "IopAddAss", 0, "", 1, 8, "", 0, "", &IARGVALUE[287], 2, NULL, 0, 0, NULL}, {"&&", "IopLogAnd", 0, "", 1, 8, "", 0, "", &IARGVALUE[289], 2, NULL, 0, 0, NULL}, {"||", "IopLogOr", 0, "", 1, 8, "", 0, "", &IARGVALUE[291], 2, NULL, 0, 0, NULL}, {"debug", "IopSetDebug", 1, "", 2, 8, "", 0, "", &IARGVALUE[293], 1, NULL, 0, 0, NULL}, {"labelAdd", "TemplIcaAddLabel", 0, "", 2, 8, "", 0, "", &IARGVALUE[294], 2, NULL, 0, 0, NULL}, {"", "", 0, "", 2, 8, "", 0, "", &IARGVALUE[296], 0, NULL, 0, 0, NULL} }; #endif ********/ char cursor_ID[] = "$Id: cursor.c,v 1.7 1996/07/26 21:15:24 etzold Exp $"; /* ** ** $RCSfile: cursor.c,v $ ** $Revision: 1.7 $ ** $Date: 1996/07/26 21:15:24 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #include #include #include #include "message.h" #include "futil.h" #include "regexp.h" #include "sm.h" #include "toklist.h" #include "cursor.h" /**api* CursorNew *************************************************** ** ** Create a new cursor object. ** ** INPUT: ** ** RETURNS: cursor object */ CURSORo *CursorNew() { CURSORo *cursor; if( (cursor = (CURSORo *) calloc (sizeof(CURSORo), 1)) == NULL ) _ErrExit2 (e__allocfail, "Cursor object"); return(cursor); } /**api* CursorDelete *************************************************** ** ** Delete the cursor object. ** ** INPUT: address of cursor object [W] ** ** IMPLICIT: ** ** RETURNS: */ void CursorDelete(CURSORo **cursor) { if (*cursor) free (*cursor); *cursor = NULL; } /**api* CursorSave *************************************************** ** ** Copy the content of cursor object. ** ** INPUT: target cursor object [W] ** cursor object to be saved [R] ** ** RETURNS: */ void CursorSave(CURSORo *cursorSave, CURSORo *cursor) { memcpy(cursorSave, cursor, sizeof(CURSORo)); } /**api* CursorRestore *************************************************** ** ** ** Restore the content of cursor object. ** ** INPUT: target cursor object [W] ** cursor object to be restored [R] ** ** RETURNS: */ void CursorRestore(CURSORo *cursor, CURSORo *cursorRestore) { memcpy(cursor, cursorRestore, sizeof(CURSORo)); } /**api* CursorAdvance *************************************************** ** ** Move cursor to the next non space position in input stream. ** ** INPUT: o pointer to the cursor object [R] ** o string of the white space characters [R] ** o white space character represented as a regular ** expression. NULL if it is represented as string ** o flag to suppress skipping [R] ** o flag is set to FALSE when skipping is already done ** ** RETURN: o TRUE if cursor can be proceed ** o FALSE if input is exhausted */ INT4 CursorAdvance(CURSORo *cursor, char *skipChars, regexp *re, INT4 isNoSkip, INT4 *doAdvance) { char *string; INT4 len; /* skip white space AND comments using regular expression */ if (!isNoSkip && *skipChars) { while (cursor->len) { *doAdvance = 0; len = MIN(cursor->len, strspn(cursor->current, skipChars)); cursor->len -= len; cursor->current += len; if (re) { /* test regular expr for comments */ if (RegExec (re, cursor->current) == 1) { len = MIN(cursor->len, (INT4)(re->endp[0] - re->startp[0])); cursor->current += len; cursor->len -= len; continue; } } break; } } if (cursor->len ) return(TRUE); else if (!cursor->tokList || !TokGetMore(cursor->tokList, &string, &len)) { return(FALSE); } else { cursor->current = string; cursor->len = len; return(CursorAdvance(cursor, skipChars, re, isNoSkip, doAdvance)); } } /**api* CursorIterate *************************************************** ** ** Move cursor to the next token ignoring the rest ** ** INPUT: o pointer to the cursor object [R] ** o string of the white space characters [R] ** o white space character represented as a regular ** expression. NULL if it is represented as string ** o flag to suppress skipping [R] ** o flag is set to FALSE when skipping is already done ** ** RETURN: o TRUE if cursor can be proceed ** o FALSE if input is exhausted */ INT4 CursorIterate(CURSORo *cursor, char *skipChars, regexp *re, INT4 isNoSkip, INT4 *doAdvance) { char *string; INT4 len; if (!TokGetMore(cursor->tokList, &string, &len) ) return(FALSE); else { cursor->current = string; cursor->len = len; return(CursorAdvance(cursor, skipChars, re, isNoSkip, doAdvance)); } } /**api* CursorResetMatch *************************************************** ** ** This function sets match length to zero ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ void CursorResetMatch (CURSORo *cursor) { cursor->matchLen = 0; } /**api* CursorIncrement *************************************************** ** ** This function must be called after (not) matches. ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ void CursorIncrement(CURSORo *cursor) { cursor->current += cursor->matchLen; cursor->len -= cursor->matchLen; cursor->matchLen = 0; } /**api* CursorMove *************************************************** ** ** This function must be called after move statement ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ void CursorMove(CURSORo *cursor) { cursor->current += cursor->matchLen; cursor->len -= cursor->matchLen; if( cursor->len < 0 ) cursor->len = 0; cursor->matchLen = 0; } /**api* CursorRestrictLength *********************************************** ** ** Restrict the cursor length to some particular size by temporarily ** string terminator. It is required to find correct biggest regular ** expression. See CursorRestoreChar ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ void CursorRestrictLength(CURSORo *cursor) { INT4 length; length = cursor->len; cursor->saveChar = cursor->current[length]; cursor->saveCharPtr = &cursor->current[length]; *cursor->saveCharPtr = '\0'; } /**api* CursorRestrictLength *********************************************** ** ** Restrict the cursor length to some particular size by temporarily ** string terminator. It is required to find correct biggest regular ** expression. See CursorRestoreChar ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ Int4 CursorSetTmpLength (CURSORo *cursor, Int4 len) { return (cursor->len = MIN(len, cursor->len)); } Int4 CursorResetLength (CURSORo *cursor, Int4 length) { cursor->len = length; } void CursorReset (CURSORo *cursor) { cursor->len = 0; } Int4 CursorGetLength (CURSORo *cursor) { return cursor->len; } Int4 CursorSetString (CURSORo *cursor, char *s, Int4 len) { cursor->current = s; cursor->len = len; } Int4 CursorSetFile (CURSORo *cursor, FILEo *file) { char *s; if (file && (s = FileGetLn (file))) CursorSetString (cursor, s, strlen (s)); } /**api* CursorRestoreChar *********************************************** ** ** Restore the temporal string terminator in the input token ** See CursorRestrictLength ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ void CursorRestoreChar(CURSORo *cursor) { *cursor->saveCharPtr = cursor->saveChar; } /**api* CursorDefineAnchor *********************************************** ** ** Set a cursor anchor. The anchor is used for determination of ** global cursor movement. ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: */ void CursorDefineAnchor(CURSORo *cursor, CURSORoANCHOR *anchor) { anchor->begin = cursor->current; anchor->tokListBuff = TokGetBuff (cursor->tokList); } /**api* CursorGetBegin *********************************************** ** ** Get the beginning of the current input token ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: pointer to the beginning of input token */ char *CursorGetBegin(CURSORo *cursor) { return(cursor->begin); } /**api* CursorGetPtr *********************************************** ** ** Get the pointer to the current position the the input token ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: current position the the input token */ char *CursorGetPtr(CURSORo *cursor) { static char *emptyStr = ""; if(cursor->len == 0) return(emptyStr); else return(cursor->current); } /**api* CursorGetMatch *********************************************** ** ** Get the last match and its length ** ** INPUT: pointer to the cursor object [R] ** pointer to the last match [W] ** length of the last match [W] ** ** RETURN: */ void CursorGetMatch(CURSORo *cursor, char **ptr, INT4 *length) { *length = cursor->matchLen; *ptr = cursor->current; } /**api* CursorGetMatchCopy *********************************************** ** ** Get the copy of the current match. It would be store in a static ** buffer until the next call of the function. ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: pointer to copy of the match */ char *CursorGetMatchCopy(CURSORo *cursor) { static SMoBUFF *matchBuff = NULL; matchBuff = BuffInit(matchBuff, TOKxMAXTOKBUFFSIZE); if(cursor->len == 0) return(""); else { BuffCopyNChar(matchBuff, cursor->current, cursor->matchLen); BuffCopyNChar(matchBuff, "\0", 1); return(BuffGetPtr(matchBuff)); } } /**api* CursorSetMatch *********************************************** ** ** Set the match length ** ** INPUT: pointer to the cursor object [W] ** length of the match [R] ** ** RETURN: */ void CursorSetMatch(CURSORo *cursor, INT4 len) { cursor->matchLen = len; } /**api* CursorSetLength *********************************************** ** ** Set the match length ** ** INPUT: pointer to the cursor object [W] ** length of the match [R] ** ** RETURN: */ void CursorSetLength(CURSORo *cursor, INT4 len) { cursor->matchLen = MIN(len, cursor->len); } /**api* CursorReplaceMatch *********************************************** ** ** Replace the match by defined string ** ** INPUT: pointer to the cursor object [W] ** string to replace [R] ** length of the string [R] ** ** RETURN: ** */ void CursorReplaceMatch(CURSORo *cursor, char *newMatch, INT4 newLen) { cursor->current += TokReplaceIn(cursor->tokList, cursor->current, cursor->matchLen, newMatch, newLen); cursor->len += (newLen - cursor->matchLen); cursor->matchLen = newLen; } /**api* CursorSetGlobalMatch *********************************************** ** ** Set the global match ** ** INPUT: pointer to the cursor object [W] ** anchor of the cursor object [R] ** ** RETURN: */ void CursorSetGlobalMatch(CURSORo *cursor, CURSORoANCHOR *anchor) { INT4 len; char *tokListBuff; tokListBuff = TokGetBuff (cursor->tokList); if (tokListBuff && tokListBuff != anchor->tokListBuff) anchor->begin += tokListBuff - anchor->tokListBuff; len = (INT4)(cursor->current - anchor->begin); cursor->matchLen = len; cursor->len += len; cursor->current = anchor->begin; } /**api* CursorLength *********************************************** ** ** Get the the size of the string from current position in the ** token until the end. ** ** INPUT: pointer to the cursor object [W] ** ** RETURN: rest length of input token */ INT4 CursorLength(CURSORo *cursor) { return(cursor->len); } /**api* CursorIsBegin *********************************************** ** ** Check if the cursor is at the beginning of the input token ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: TRUE if cursor points to the token beginning ** FALSE otherwise */ INT4 CursorIsBegin(CURSORo *cursor) { return(cursor->current == cursor->begin); } /**api* CursorIsLineStart *********************************************** ** ** Check if the cursor is at the beginning of the input token ** and if the previous character is the "new line" ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: TRUE if cursor points to the token beginning ** FALSE otherwise */ INT4 CursorIsLineStart(CURSORo *cursor) { return(cursor->begin == cursor->current || cursor->begin[-1] == '\n'); } /**api* CursorIsEnd *********************************************** ** ** Check if the cursor is at the end of the input token ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: TRUE if cursor points to the token end ** FALSE otherwise */ INT4 CursorIsEnd(CURSORo *cursor) { return(cursor->len == 0); } /**api* CursorIsMoved *********************************************** ** ** Check if the cursor is not at the beginning of the input token ** It is opposite to CursorIsBegin function. ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: TRUE if cursor does not point to the token beginning ** FALSE otherwise */ INT4 CursorIsMoved(CURSORo *cursor, CURSORoANCHOR *anchor) { return(cursor->current != anchor->begin); } /**api* CursorIsInstall *********************************************** ** ** Check if the cursor is installed at the beginning of the input token ** ** INPUT: pointer to the cursor object [R] ** ** RETURN: TRUE if cursor installs to the token beginning ** FALSE otherwise */ INT4 CursorIsInstall(CURSORo *cursor) { return(cursor->isInstall); } /**api* CursorInstall *************************************************** ** ** Install the cursor is at the beginning of the input token ** ** INPUT: pointer to the cursor object [W] ** input token [R] ** input token list [R] ** ** RETURN: */ void CursorInstall(CURSORo *cursor, TOKoTOKEN *token, TOKoLIST *tokList) { if(token) { cursor->len = TokGetLength(token); cursor->begin = TokGetString(tokList, token); cursor->isInstall = TRUE; } else { cursor->len = 0; cursor->begin = ""; cursor->isInstall = FALSE; } cursor->current = cursor->begin; cursor->tokList = tokList; } char *current; INT4 len; INT4 matchLen; char saveChar; char *saveCharPtr; char *begin; TOKoLIST *tokList; INT4 isInstall; } CURSORo; typedef struct CURSORoANCHOR { char *begin; char *tokListBuff; } CURSORoANCHOR; typedef struct regexp *dummytointroducestructtagregexp; CURSORo *CursorNew(); INT4 CursorAdvance(CURSORo *cursor, char *skipChars, struct regexp *re, INT4 isNoSkip, INT4 *doAdvance); INT4 CursorIsBegin(CURSORo *cursor); INT4 CursorIsEnd(CURSORo *cursor); INT4 CursorIsLineStart(CURSORo *cursor); INT4 CursorIsMoved(CURSORo *cursor, CURSORoANCHOR *anchor); INT4 CursorIterate(CURSORo *cursor, char *skipChars, struct regexp *re, INT4 isNoSkip, INT4 *doAdvance); INT4 CursorIsInstall(CURSORo *cursor); INT4 CursorLength(CURSORo *cursor); char *CursorGetMatchCopy(CURSORo *cursor); char *CursorGetPtr(CURSORo *cursor); char *CursorGetBegin(CURSORo *cursor); void CursorDefineAnchor(CURSORo *cursor, CURSORoANCHOR *anchor); void CursorDelete(CURSORo **cursor); void CursorGetMatch(CURSORo *cursor, char **ptr, INT4 *length); void CursorMove(CURSORo *cursor); void CursorIncrement(CURSORo *cursor); void CursorInstall(CURSORo *cursor, TOKoTOKEN *token, TOKoLIST *tokList); void CursorResetMatch(CURSORo *cursor); void CursorRestore(CURSORo *cursor, CURSORo *cursorRestore); void CursorRestoreChar(CURSORo *cursor); void CursorRestrictLength(CURSORo *cursor); void CursorSave(CURSORo *cursorSave, CURSORo *cursor); void CursorSetGlobalMatch(CURSORo *cursor, CURSORoANCHOR *anchor); void CursorSetLength(CURSORo *cursor, INT4 len); void CursorSetMatch(CURSORo *cursor, INT4 len); void CursorReplaceMatch(CURSORo *cursor, char *newMatch, INT4 newLen); char def_ID[] = "$Id: def.c,v 1.1 1996/05/06 15:16:23 srs Exp $"; /* ** ** $RCSfile: def.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:23 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** module with general purpose functions. ** file has sections for individual programmers ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "def.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Thure's functions */ /* function is called via _addObj macro */ void *addObj (char **ptr, Int4 *n, Int4 *allocN, Int4 size) { if (*n >= *allocN) { if (!*n) { *allocN = 10; *ptr = malloc (size * *allocN); } else { *allocN *= 2; *ptr = realloc (*ptr, size * *allocN); } } return *ptr + size * (*n)++; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Anatoly's functions */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Giorgio's functions */ char MPtrBuffer[100]; void stopProg(char *msg) { printf(msg); printf("\n"); exit(1); } void checkProg(char *msg) { printf(msg); printf("\n"); } int align(int pos, int sz) { int off; if (sz>=sizeof(Word)) sz=sizeof(Word); off=pos%sz; return off?(sz-off):0; } ************************************************** ** ** $RCSfile: def.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:24 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** this file is included by all SRS modules. ** sections exist for each programmer to insert definitions they ** think should be visible to all modules ** */ #ifndef DEF #define DEF typedef char *ID; typedef char *IDo; typedef unsigned char *IDPTR; typedef unsigned long ULONG; #ifdef dos typedef long INT4; typedef long Int4; typedef unsigned long UINT4; typedef unsigned long Uint4; #else typedef int INT4; typedef int Int4; typedef unsigned int UINT4; typedef unsigned int Uint4; #endif typedef UINT4 FIP; typedef UINT4 Fip; #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #ifndef NULL # define NULL 0L #endif typedef INT4 (*FUNC)(); typedef INT4 (*Func)(); typedef void (*VFUNC)(); typedef struct SMoBUFF *(*BFUNC)(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Thure's definitions */ void *addObj (char **ptr, Int4 *n, Int4 *allocN, Int4 size); #define _addObj(x, n, allocN, type)\ (type *) addObj ((char **) &x, &n, &allocN, sizeof (type)) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Anatoly's definitions */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Giorgio's definitions */ /********************************************* ** MACHINE-DESCRIBING DEFINITIONS */ /* UNIX */ /* description of the register width of the machine ** WORD= int type exactly fitting in one register ** WORD_BITS= number of bits of the register ** also used for alignement purposes */ #ifndef WORD #define WORD unsigned long #define Word unsigned long #define WORD_BITS 32 #endif /* definition of the type which can contain both a pointer ** and an integer value */ typedef WORD IntOrPtr; /********************************************* ** BASIC TYPE DEFINITIONS */ /* the type containing a logical variable ** in bit-fields, the use of unsigned is mandatory */ #ifndef BOOL #define BOOL unsigned int #endif /* good when casting/shifting bits */ #ifndef BYTE #define BYTE unsigned char #endif /* the iterator type, hiding implementation in the ** various data structures... as much as it is efficient */ /* typedef IntOrPtr Iter */ typedef void* Iter; /********************************************* ** LOW-LEVEL UTILITIES */ /* useful for making type-casts in complex pointer expressions ** a bit more readable */ #define cast(ptr,type) ((type)(ptr)) /* makes calls to function pointers more readable */ #define call(funcPtr) (*(funcPtr)) /* makes allocation of structs easier and more readable */ #define typeAlloc(type) ((type*)malloc(sizeof(type))) /* returns the pointer moved of the specified number of bytes ** and casts it to the required type. */ #define offset(ptr,nbyte,type) cast(cast(ptr,char*)+nbyte,type) /* returns the difference in bytes between 2 pointers */ #define displ(ptr1, ptr2) (cast(ptr1, char*)-cast(ptr2, char*)) /* returns the offset of a certain attribute within a struct, ** cl=struct name, attr=name of the attribute ** can only be used in function bodies (cc complains) */ extern char MPtrBuffer[]; #define mPtr(cl, attr) displ(&cast(MPtrBuffer,cl*)->attr, MPtrBuffer) /* function to allocate aligned byte offset of attributes in a struct ** given: ** offset of the end of the struct ** the number of bytes to allocate to the new attribute ** returns: ** the offset where the new attribute starts */ int align(int currOffs, int allocSize); /*********************************************************************** ** DEBUGGING SUPPORT ** ** this macro generate debugging code if DEBUG ** is defined, else they do nothing ***********************************************************************/ /* the function used to stop the program when an exception is thrown. ** Set a breakpoint here if you want to see where the exception comes from */ void stopProg(char *msg); /* throws an exception */ #ifndef THROW #define THROW(except) stopProg(#except) #endif /* if the condition specified is false, throws an exception */ #ifndef ASSERT #define ASSERT(cond,except) ((cond)? (void)0:THROW(except)) #endif /* prints a debug message */ #ifndef TRACE #define TRACE(cmd) ((void)0) #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #endif ** ** MODULE for management of indexes (dictionaries) of pointers ** to structures organized as hash tables ** ** Authors: Giorgio Verde ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: verde@embl-heidelberg.de ** *************************************************************************/ #include "def.h" #include "dict.h" #include "strv.h" #include #include /*********************************************************************** ** DICTIONARY size management */ UINT4 primes[]= { 1,3,7,17,31,61,127,257,509, 1021,2053,4093,8191,16381,32771,65537,131071, 262147,524287,1048573,2097143,4194301,8388617,16777213,33554467, 67108859,134217689,268435459,536870909,1073741827,2147483647,4294967291 }; const int numPrimes=32; UINT4 FindNextPrime(UINT4 num) { /* performs a range search on the prime number array */ int bott,top,curr; bott=0; top=numPrimes; while (top-bott>1) { curr=bott+((top-bott)>>1); if (num==primes[curr]) return primes[curr+1]; if (num1) { curr=bott+((top-bott)>>1); if (num==primes[curr]) return primes[curr-1]; if (nummyClass=c; d->dim=DictCreateDim; DictClear(d); return d; } /**API* DictDestroy ********************************************************* ** ** Destroys a dictionary. It does'nt destroy the dictionary class ** ** INPUT: [W] a DICTv */ void DictDestroy(DICTv dict) { DictClear(dict); free(dict); } /**API* DictCopy ********************************************************* ** ** Creates a dictionary copying another one. ** ** INPUT: a DICTv ** RETURNS: a new dictionary */ DICTv DictCopy(DICTv dict) { int size=sizeof(DICTo)+sizeof(DictElem)*(dict->dim-1); DICTv d=(DICTv)malloc(size); memcpy(d, dict, size); return d; } /**API* DictOffset ********************************************************* ** ** Offsets all valid pointers inside a dictionary by a specified amount. ** Useful when the dictionary is used to index positions in a memory ** buffer which is being reallocated. The user can use this function ** to switch indexing to the new buffer. If not all entries in the DICTv ** are pointing to the buffer, DictOffsetWithin should be used. ** ** INPUT: [W] a DICTv ** a memory offset */ void DictOffset (DICTv dict, int offs) { DictElem* curr; for (curr=dict->tab; currtab+dict->dim; curr++) if (*curr) *(BYTE**)curr+=offs; } /**API* DictOffsetWithin ********************************************************* ** ** Offsets all pointers in a given address range inside a dictionary ** by a specified amount ** Useful when some entries in dictionary index positions in a memory ** buffer which is being reallocated. The user can use this function ** to switch indexing to the new buffer. If all valid entries in the DICTv ** are pointing to the buffer, DictOffset should be used. ** ** INPUT: [W] a DICTv ** the starting address of the memory range ** the length in bytes of the memory range ** the destination address ** */ void DictOffsetWithin(DICTv dict, DictElem buf, int len, DictElem newBuf) { DictElem* curr; DictElem elem; int offs=displ(newBuf,buf); for (curr=dict->tab; currtab+dict->dim; curr++) { elem=*curr; if (elem && elem>=buf && elemmyClass; KeyAccessor toKey=cl->toKey; IntOrPtr toKeyInfo=cl->toKeyInfo; d->myClass=cl; d->num=old->num; d->dim=newDim; ASSERT(d->numtab; currtab+newDim; curr++) *curr=NULL; for (curr=old->tab; currtab+old->dim; curr++) { /* move value to new place */ if (*curr) *DictAddImpl(d, toKey(curr, toKeyInfo))=*curr; } free(old); *dict=d; } /* insertion/removal */ DictElem* DictAddImpl (DICTv dict, void* key) { int dim=dict->dim; DictElem* curr=dict->tab+call(dict->myClass->hash)(key,dim); DictElem* last=dict->tab+dim; while (*curr) if (++curr==last) curr=dict->tab; return curr; } /* get element with same key if present, else add */ DictElem* DictSetImpl(DICTv dict, void* key) { CLASSoDICT* cl=dict->myClass; ValComparer equal=cl->equal; KeyAccessor toKey=cl->toKey; IntOrPtr toKeyInfo=cl->toKeyInfo; int dim=dict->dim; DictElem* curr=dict->tab+call(cl->hash)(key,dim); DictElem* last=dict->tab+dim; while (*curr && !call(equal)(key, toKey(curr, toKeyInfo))) { if (++curr==last) curr=dict->tab; } return curr; } /**API* DictAddGrow ********************************************************* ** ** Allocates a new entry, given the key where to insert. If ** the dictionary class allows repetitions, then more than one ** entry can have the same key. See also DictWith, DictNextWith ** ** INPUT: [W] a pointer to DICTv ** the pointer to the key value ** RETURNS: o the pointer to the entry (a void*) to be assigned ** to the structure to be inserted */ DictElem* DictAddGrow(DICTv* dict,void* key) { DICTv d=*dict; if (d->myClass->repetitions) { if (++d->num>(d->dim*3>>2)) DictResize(dict,FindNextPrime(d->dim)); return DictAddImpl(*dict,key); } else { DictElem* el=DictSetGrow(dict, key); ASSERT(!*el, DuplicateKey); return el; } } /**API* DictSetGrow ********************************************************* ** ** Given a key, allocates a new entry if the key is not found, ** else returns the first entry which has the same key. Useful when ** adding a new element with the same key must replace the old element. ** See also DictAdd ** ** INPUT: [W] a pointer to DICTv ** the pointer to the key value ** RETURNS: o the pointer to the new entry (a void*) to be assigned ** if the key is not found, else a pointer to the already ** present entry */ DictElem* DictSetGrow(DICTv* dict, void* key) { DictElem* elem=DictSetImpl(*dict,key); if (!*elem) { int num=++((*dict)->num); int dim=(*dict)->dim; if (num>(dim*3>>2)) { DictResize(dict,FindNextPrime(dim)); return DictAddImpl(*dict,key); } } return elem; } /**API* DictAddPtr ********************************************************* ** ** Adds a new element to the dictionary. The element must contain ** a valid key. While inserted into the dictionary, the key cannot be ** modified nor the structure reallocated. ** If the user to perform such an operation, it must remove the structure ** with DictRemovePtr, do the operation and insert it again with DictAddPtr. ** To reallocate an array of indexed structure, see DictOffsetWithin. ** ** INPUT: [W] a pointer to DICTv ** the pointer to the element ** RETURNS: o an iterator with the position of the inserted element ** the iterator is only valid until the next dictionary-modifying ** operation is performed */ Iter DictAddPtr(DICTv* dict, DictElem elem) { CLASSoDICT* cl=(*dict)->myClass; void* key=call(cl->toKey)(&elem, cl->toKeyInfo); DictElem* e=DictAddGrow(dict,key); *e=cast(elem, DictElem); return e; } /**API* DictSetPtr ********************************************************* ** ** Adds a new element to the dictionary or substitutes an already present ** element with the same key (see DictSetGrow) ** The element must contain a valid key. While inserted into the ** dictionary, the key cannot be modified nor the structure reallocated. ** If the user to perform such an operation, it must remove the structure ** with DictRemovePtr, do the operation and insert it again with DictAddPtr. ** To reallocate an array of indexed structure, see DictOffsetWithin. ** ** INPUT: [W] a pointer to DICTv ** the pointer to the element ** RETURNS: o an iterator with the position of the inserted/replaced element ** the iterator is only valid until the next dictionary-modifying ** operation is performed */ Iter DictSetPtr(DICTv* dict, DictElem elem) { CLASSoDICT* cl=(*dict)->myClass; void* key=call(cl->toKey)(&elem, cl->toKeyInfo); DictElem* e=DictSetGrow(dict,key); *e=cast(elem, DictElem); return e; } /**API* DictRemove ********************************************************* ** ** Removes the element at a given position ** The iterator can be obtained by using DictAddPtr, DictSetPtr, ** DictWith, DictWithPtr, DictFirst, DictNext, DictNextWith. ** ** INPUT: [W] a pointer to DICTv ** the iterator of the element */ void DictRemove (DICTv* dict, Iter i) { DICTv d=*dict; int dim=d->dim; DictElem* hole=(DictElem*)i; ASSERT(hole && *hole, NoSuchElem); if ((--d->num)<(dim>>2)) { *hole=NULL; DictResize(dict, dim=FindPrevPrime(dim)); } else { CLASSoDICT* dc=d->myClass; ValHasher hash=dc->hash; KeyAccessor toKey=dc->toKey; IntOrPtr toKeyInfo=dc->toKeyInfo; DictElem* curr=hole+1; DictElem* last=d->tab+dim; if (curr==last) curr=d->tab; while (*curr) { DictElem* wanted=d->tab+call(hash)(toKey(curr,toKeyInfo),dim); if ((holecurr): (wanted<=hole && wanted>curr)) { *hole=*curr; hole=curr; } if (++curr==last) curr=d->tab; } *hole=NULL; } } /**API* DictRemoveWith ********************************************************* ** ** Removes the elements having a given key value ** ** INPUT: [W] a pointer to DICTv ** the pointer to the key value */ void DictRemoveWith (DICTv* dict, void* key) { Iter i; while (i=DictWith(*dict,key)) DictRemove(dict,&i); } /**API* DictRemovePtr ********************************************************* ** ** Removes a certain element (identified by it's memory pointer) ** ** INPUT: [W] a pointer to DICTv ** the pointer to the element */ void DictRemovePtr (DICTv* dict, DictElem elem) { DictRemove(dict,DictWithPtr(*dict, elem)); } /**API* DictClear ********************************************************* ** ** Removes all the elements of the dictionary without reallocating it ** ** INPUT: [W] a DICTv */ void DictClear (DICTv dict) { DictElem* curr; for (curr=dict->tab; currtab+dict->dim; curr++) *curr=NULL; dict->num=0; } /* access */ /**API* DictAtImpl ********************************************************* ** ** Accesses the element at a given key. If repetitions are allowed, ** a run-time check for unicity of the key value is performed. ** A NotSuchElement exception is thrown if the key is not found. ** ** INPUT: a DICTv ** a pointer to the key value ** RETURNS: a pointer to the element */ DictElem* DictAtImpl (DICTv dict, void* key) { Iter i=DictWith(dict, key); ASSERT(i, NoSuchElement); if (dict->myClass->repetitions) { Iter next=i; DictNextWith(dict, key, &next); ASSERT(!next, AmbigousAssociation); } return (DictElem*)i; } /**API* DictKey ********************************************************* ** ** Accesses the key at a given position. The iterator must be valid ** ** INPUT: a DICTv ** an iterator ** RETURNS: a pointer to the key value */ void* DictKey(DICTv dict, Iter i) { CLASSoDICT* cl=dict->myClass; return call(cl->toKey)(*cast(i, DictElem*),cl->toKeyInfo); } /* iterator support */ /**API* DictWith ********************************************************* ** ** Retrieves the iterator position of the first element ** with a given key value. If the key value does'nt ** exist, returns NULL. Useful also for testing the ** presence of a key in the dictionary. The successive elements ** with the same key value can be obtained using DictNextWith. ** ** ** INPUT: a DICTv ** a pointer to the key value ** RETURNS: the iterator */ Iter DictWith (DICTv dict, void* key) { CLASSoDICT* cl=dict->myClass; ValComparer equal=cl->equal; KeyAccessor toKey=cl->toKey; IntOrPtr toKeyInfo=cl->toKeyInfo; int dim=dict->dim; DictElem* curr=dict->tab+call(cl->hash)(key,dim); DictElem* last=dict->tab+dim; while (*curr) { if (call(equal)(key, toKey(curr, toKeyInfo))) return curr; if (++curr==last) curr=dict->tab; } return NULL; } /**API* DictWithPtr ********************************************************* ** ** Retrieves the iterator position given the memory ** pointer to the element. The element must have been ** inserted in the dictionary. ** ** INPUT: a DICTv ** a pointer to the element ** RETURNS: the iterator */ Iter DictWithPtr(DICTv dict, DictElem elem) { CLASSoDICT* cl=dict->myClass; void* key=call(cl->toKey)(&elem,cl->toKeyInfo); DictElem* i=(DictElem*)DictWith(dict, key); if (!i) return NULL; while (*i!=elem) { i++; if (!*i) return NULL; } return i; } /**API* DictFirst ********************************************************* ** ** Retrieves an iterator for scanning the dictionary sequentially. ** No specific ordering is given for the iteration, and the dictionary ** should not be modified while iterating. ** ** INPUT: a DICTv ** RETURNS: the iterator */ Iter DictFirst(DICTv dict) { Iter i=NULL; DictNext(dict,&i); return i; } /**API* DictNext ********************************************************* ** ** Retrieves an iterator for scanning the dictionary sequentially. ** No specific ordering is given for the iteration, and the dictionary ** should not be modified while iterating. The iterator is set to NULL ** when there are no more elements. ** ** INPUT: a DICTv ** [W] a pointer to an iterator */ void DictNext (DICTv dict, Iter* i) { if (*i) (*cast(i, DictElem**))++; else *i=dict->tab; while (*i!=dict->tab+dict->dim) { if (*cast(*i, DictElem*)) return; (*cast(i, DictElem**))++; } *i=NULL; } Iter DictLast (DICTv dict) { Iter i=NULL; DictPrev(dict, &i); return i; } void DictPrev (DICTv dict, Iter* i) { if (*i) (*cast(i, DictElem**))--; else *i=dict->tab+dict->dim; while (*i!=dict->tab-1) { if (*cast(*i, DictElem*)) return; (*cast(i, DictElem**))--; } *i=NULL; } /**API* DictNextWith ********************************************************* ** ** Retrieves an iterator for scanning all insterted elements having ** a given key value. The order of the elements is the insertion order. ** The first element can be obtained using the DictWith function. ** The iterator is set to NULL when there are no more elements. ** ** INPUT: a DICTv ** a pointer to the key value ** [W] a pointer to an iterator */ void DictNextWith (DICTv dict, void* key, Iter* i) { int dim=dict->dim; DictElem* curr=*i; CLASSoDICT* cl=dict->myClass; ValComparer equal=cl->equal; KeyAccessor toKey=cl->toKey; IntOrPtr toKeyInfo=cl->toKeyInfo; if (curr) curr++; else curr=dict->tab+call(cl->hash)(key,dim); while (*curr) { if (call(equal)(key, toKey(curr, toKeyInfo))) { *i=curr; return; } curr++; if (curr==dict->tab+dict->dim) curr=dict->tab; } *i=NULL; } /* information */ /**API* DictCard ********************************************************* ** ** Returns the number of elements in the dictionary ** ** INPUT: a DICTv ** RETURNS: the number of elements */ int DictCard (DICTv dict) { return dict->num; } /**API* DictCardWith ********************************************************* ** ** Returns the number of elements in the dictionary with a given key value ** ** INPUT: a DICTv ** a pointer to the key value ** RETURNS: the number of elements */ int DictCardWith(DICTv dict, void* key) { Iter i; int num=0; for (i=DictWith(dict, key);i;DictNextWith(dict, key, &i)) num++; return num; } /**API* DictEmpty ********************************************************* ** ** Tells whether a dictionary is empty. ** ** INPUT: a DICTv ** RETURNS: TRUE if the dictionary is empty */ BOOL DictEmpty(DICTv dict) { return dict->num!=0; } /**API* DictHas ********************************************************* ** ** Tells weather a dictionary contains an element with the given key. ** See also DictWith ** ** INPUT: a DICTv ** a pointer to a key value ** RETURNS: TRUE if the dictionary contains the key */ BOOL DictHas (DICTv dict, void* key) { return DictWith(dict, key)!=NULL; } /*************************************************************************/ /**API* PolyStrEqual ********************************************************* ** ** Compares 2 pointers to STRv for equality ** ** INPUT: a pointer to STRv ** a pointer to STRv ** RETURNS: TRUE if the STRv's are equal */ BOOL PolyStrEqual(void* s1, void* s2) { return StrEqual(*cast(s1, STRv*), *cast(s2, STRv*)); } /**API* PolyStrHash ********************************************************* ** ** Hashes the STRv identified by a pointer to STRv ** ** INPUT: a pointer to STRv ** RETURNS: an hash value */ int PolyStrHash(void* s, int max) { return StrHash(*cast(s, STRv*), max); } /**API* PolyIntEqual ********************************************************* ** ** Compares 2 pointers to int for equality ** ** INPUT: a pointer to int ** a pointer to int ** RETURNS: TRUE if the int's are equal */ BOOL PolyIntEqual(void* i1, void* i2) { return *cast(i1, int*)==*cast(i2, int*); } /**API* PolyIntHash ********************************************************* ** ** Hashes the int identified by a pointer to int ** ** INPUT: a pointer to int ** RETURNS: an hash value */ int PolyIntHash(void* i, int max) { return *cast(i, int*)%max; } /**API* PolyPtrEqual ********************************************************* ** ** Compares 2 pointers to pointer for equality ** ** INPUT: a pointer to pointer ** a pointer to pointer ** RETURNS: TRUE if the pointed pointers are equal */ BOOL PolyPtrEqual(void* p1, void* p2) { return *cast(p1, void**)==*cast(p2, void**); } /**API* PolyPtrHash ********************************************************* ** ** Hashes the pointer identified by a pointer to pointer ** ** INPUT: a pointer to pointer ** RETURNS: an hash value */ int PolyPtrHash(void* p, int max) { return *cast(p, IntOrPtr*)%max; } #include /**API* strhash ********************************************************* ** ** Hashes a C string ** ** INPUT: a char* ** RETURNS: an hash value */ int strhash(char* s, int max) { WORD h=0, g; while (*s) { h=(h << 4 | (h&0xf0000000L)>>28) ^ *s++; } return h%max; } /**API* strequal ********************************************************* ** ** compares 2 C strings ** ** INPUT: a char* ** a char* ** RETURNS: TRUE if equal */ BOOL strequal(char* s1,char* s2) { return strcmp(s1,s2)==0; } /**API* PtrEqual ********************************************************* ** ** compares 2 pointers ** ** INPUT: a pointer ** a pointer ** RETURNS: TRUE if equal */ BOOL PtrEqual(void* p1, void* p2) { return p1==p2; } /**API* PtrHash ********************************************************* ** ** Hashes a pointer ** ** INPUT: a pointer ** RETURNS: an hash value */ int PtrHash(void* p, int max) { return cast(p, WORD)%max; } /**API* KeyItself ********************************************************* ** ** Used in definitions of dictionary classes, used with DictCreate. ** Defines the dictionary to be a set, so that the entire value of ** elements that are inserted is the key of the dictionary. ** ** INPUT: a pointer to the element (a pointer inside the dictionary) ** RETURNS: a pointer to the key */ void* KeyItself(DictElem* entry) { return *entry; } /**API* KeyOffset ********************************************************* ** ** Used in definitions of dictionary classes, used with DictCreate. ** Defines the dictionary to be a dictionary of structures in which ** one attribute is the key. ** ** INPUT: a pointer to the element (a pointer inside the dictionary) ** RETURNS: a pointer to the key */ void* KeyOffset(DictElem* entry, int offs) { return offset(*entry, offs, void*); } /**API* DictDebug ********************************************************* ** ** Prints the status of the dictionary. Especially useful if the ** dictionary class has been defined using the functions provided ** by this module. ** ** INPUT: a DICTv */ void DictDebug(DICTv d) { printf("DICTv:%p", d); if (d) { DictElem* curr; CLASSoDICT* info=d->myClass; printf("[num:%d dim:%d \n", d->num, d->dim); for (curr=d->tab; currtab+d->dim; curr++) if (*curr) { void* key=call(info->toKey)(curr, info->toKeyInfo); ValComparer equal=info->equal; printf("\t[ix:%d elem:%p ", curr-d->tab, *curr); if (equal==(ValComparer)strequal) printf("key:%s", (char*)key); else if (equal==PtrEqual) printf("key:%p", key); else if (equal==PolyStrEqual) printf("key:%s", Str(*(STRv*)key)); else if (equal==PolyIntEqual) printf("key:%d", *(int*)key); else if (equal==PolyPtrEqual) printf("key:%p", *(void**)key); else printf("key: DontKnow"); printf(" hash:%d ]\n", call(info->hash)(key, d->dim)); } printf("]"); } printf("\n"); } /******************************************************************* ** PROPERTY MANAGEMENT */ DICTv AccessMethods=NULL; DICTv Properties=NULL; typedef struct AccessMethod { KeyAccessor toKey; DICTv accessInfo; } AccessMethod; KeyAccessor* AccessMethodToKey(AccessMethod** entry) { return &(*entry)->toKey; } BOOL PropertyCompare(Prop prop1, Prop prop2) { if (prop1==prop2) return TRUE; else if (prop1->toKey==prop2->toKey && prop1->toKeyInfo==prop2->toKeyInfo && prop1->equal==prop2->equal && prop1->hash==prop2->hash && prop1->repetitions==prop2->repetitions) return TRUE; return FALSE; } int PropertyHash(Prop p, int max) { int val=(cast(p->toKey, WORD)+cast(p->equal, WORD)+cast(p->hash, WORD)+ p->toKeyInfo+p->repetitions)%max; return val; } void InitProperties() { Prop cl=typeAlloc(CLASSoDICT); cl->toKey=(KeyAccessor)AccessMethodToKey; cl->toKeyInfo=NULL; cl->equal=(ValComparer)PolyPtrEqual; cl->hash=(ValHasher)PolyPtrHash; cl->repetitions=FALSE; AccessMethods=DictCreate(cl); cl=typeAlloc(CLASSoDICT); cl->toKey=(KeyAccessor)KeyItself; cl->toKeyInfo=NULL; cl->equal=(ValComparer)PropertyCompare; cl->hash=(ValHasher)PropertyHash; cl->repetitions=FALSE; Properties=DictCreate(cl); } AccessId RegisterAccessMethod(KeyAccessor toKey, ValComparer toKeyInfoEqual, ValHasher toKeyInfoHash) { AccessMethod** am; AccessMethod* m; ASSERT (AccessMethods, NotInitialized); am =&DictSet(&AccessMethods, toKey, AccessMethod*); m =*am; if (!m) { Prop p=typeAlloc(CLASSoDICT); p->toKey=(KeyAccessor)KeyItself; p->toKeyInfo=NULL; p->equal=(ValComparer)toKeyInfoEqual; p->hash=(ValHasher)toKeyInfoHash; m=typeAlloc(AccessMethod); m->toKey=toKey; m->accessInfo=DictCreate(p); *am=m; } else { Prop p=m->accessInfo->myClass; ASSERT(p->equal==toKeyInfoEqual && p->hash==toKeyInfoHash, InconsistentIdMethods); } return m; } void RegisterAccessInfo(AccessId how, void** info) { void** i=&DictSet(&how->accessInfo, info, void*); if (*i) { free (*info); *info=*i; } else *i=*info; } void RegisterProperty(Prop* property) { Prop* p; ASSERT (Properties, NotInitialized); p=&DictSet(&Properties, *property, Prop); if (!*p) *p=*property; else { free(*property); *property=*p; } } BOOL RegisteredProp(Prop property) { return DictWith(Properties, property)!=NULL; } void* GetProp(Prop p, DictElem* elem) { return call(p->toKey)(elem, p->toKeyInfo); } /***********************************************************************************/ DICTv DictCreateKeyStr(int offs, BOOL repetitions) { CLASSoDICT* cl=typeAlloc(CLASSoDICT); cl->equal=(ValComparer)PolyStrEqual; cl->hash=(ValHasher)PolyStrHash; cl->toKey=(KeyAccessor)KeyOffset; cl->toKeyInfo=offs; cl->repetitions=repetitions; return DictCreate(cl); } DICTv DictCreateKeyInt(int offs, BOOL repetitions) { CLASSoDICT* cl=typeAlloc(CLASSoDICT); cl->equal=(ValComparer)PolyIntEqual; cl->hash=(ValHasher)PolyIntHash; cl->toKey=(KeyAccessor)KeyOffset; cl->toKeyInfo=offs; cl->repetitions=repetitions; return DictCreate(cl); } void DictDestroyWithClass(DICTv d) { free(d->myClass); DictDestroy(d); } CLASSoDICT* DictCreateClassStrKey(KeyAccessor toKey, IntOrPtr toKeyInfo, BOOL repetitions) { CLASSoDICT* cl=typeAlloc(CLASSoDICT); cl->equal=(ValComparer)PolyStrEqual; cl->hash=(ValHasher)PolyStrHash; if (toKey) cl->toKey=toKey; else cl->toKey=(KeyAccessor)KeyOffset; cl->toKeyInfo=toKeyInfo; cl->repetitions=repetitions; return cl; } CLASSoDICT* DictCreateClassIntKey(KeyAccessor toKey, IntOrPtr toKeyInfo, BOOL repetitions) { CLASSoDICT* cl=typeAlloc(CLASSoDICT); cl->equal=(ValComparer)PolyIntEqual; cl->hash=(ValHasher)PolyIntHash; if (toKey) cl->toKey=toKey; else cl->toKey=(KeyAccessor)KeyOffset; cl->toKeyInfo=toKeyInfo; cl->repetitions=repetitions; return cl; } CLASSoDICT* DictCreateClassPtrKey(KeyAccessor toKey, IntOrPtr toKeyInfo, BOOL repetitions) { CLASSoDICT* cl=typeAlloc(CLASSoDICT); cl->equal=(ValComparer)PolyPtrEqual; cl->hash=(ValHasher)PolyPtrHash; if (toKey) cl->toKey=toKey; else cl->toKey=(KeyAccessor)KeyOffset; cl->toKeyInfo=toKeyInfo; cl->repetitions=repetitions; return cl; } CLASSoDICT* DictCreateClassSelfPtrKey (BOOL repetitions) { CLASSoDICT* cl=typeAlloc(CLASSoDICT); cl->equal=(ValComparer)PtrEqual; cl->hash=(ValHasher)PtrHash; cl->toKey=(KeyAccessor)KeyItself; cl->repetitions=repetitions; return cl; } #define _DICT_H /******************************************************************************* ** DICTIONARY data structure ** associates values with other values *******************************************************************************/ /* Dictionary is an index built on some other (owning) data structure It is composed by aliases to the indexed values (hmmm. bad, should always be notified on changes on the index in the indexed value) */ typedef void* DictElem; typedef void* (*KeyAccessor)(DictElem* entry, IntOrPtr info); typedef BOOL (*ValComparer)(void* val1, void* val2); typedef int (*ValHasher) (void* val, int N); typedef struct CLASSoDICT { ValComparer equal; /* key compare */ ValHasher hash; /* key hash */ KeyAccessor toKey; IntOrPtr toKeyInfo; BOOL repetitions; } CLASSoDICT; typedef struct DICTo { CLASSoDICT* myClass; int dim; int num; /* num of hashed elements */ DictElem tab[1]; } DICTo; typedef DICTo* DICTv; /* dictionary value is polymorphic */ /* creation/deletion */ DICTv DictCreate(CLASSoDICT* cl); void DictDestroy(DICTv dict); DICTv DictCopy(DICTv dict); void DictOffset(DICTv dict, int offs); void DictOffsetWithin(DICTv dict, DictElem buf, int len, DictElem newBuf); /* insertion/removal */ DictElem* DictAddImpl(DICTv dict, void* key); DictElem* DictSetImpl(DICTv dict, void* key); DictElem* DictAddGrow(DICTv* dict, void* key); DictElem* DictSetGrow(DICTv* dict, void* key); #define DictAdd(dict, key, type) (*cast(DictAddGrow(dict,key), type*)) #define DictSet(dict, key, type) (*cast(DictSetGrow(dict,key), type*)) Iter DictAddPtr(DICTv* dict, DictElem elem); Iter DictSetPtr(DICTv* dict, DictElem elem); void DictRemove (DICTv* dict, Iter i); void DictRemoveWith (DICTv* dict, void* key); void DictRemovePtr (DICTv* dict, DictElem elem); void DictClear (DICTv dict); /* access */ DictElem* DictAtImpl (DICTv dict, void* key); DictElem* DictInImpl (DICTv dict, Iter i); #define DictAt(dict, key, type) (*(type*)DictAtImpl(dict, key)) #define DictIn(iter, type) (*(ASSERT(iter, Undefined), cast(iter,type*))) /* iterator support */ Iter DictWith (DICTv dict, void* key); Iter DictWithPtr(DICTv dict, DictElem elem); void DictNextWith (DICTv dict, void* key, Iter* i); Iter DictFirst(DICTv dict); void DictNext (DICTv dict, Iter* i); Iter DictLast (DICTv dict); void DictPrev (DICTv dict, Iter* i); /* information */ int DictCard (DICTv dict); int DictCardWith(DICTv dict, void* key); BOOL DictEmpty(DICTv dict); BOOL DictHas (DICTv dict, void* key); void* DictKey(DICTv dict, Iter i); /********************************************************* ** Useful support functions */ BOOL PolyStrEqual(void* s1, void* s2); int PolyStrHash(void* s, int max); BOOL PolyIntEqual(void* i1, void* i2); int PolyIntHash(void* i, int max); BOOL PolyPtrEqual(void* p1, void* p2); int PolyPtrHash(void* p, int max); int strhash(char* s, int max); BOOL strequal(char* s1,char* s2); BOOL PtrEqual(void* p1, void* p2); int PtrHash(void* p, int max); void* KeyItself(DictElem* entry); void* KeyOffset(DictElem* entry, int offs); /********************************************************** ** Dictionary class management */ typedef CLASSoDICT* Prop; typedef struct AccessMethod* AccessId; void InitProperties(); AccessId RegisterAccessMethod(KeyAccessor toKey, ValComparer toKeyInfoEqual, ValHasher toKeyInfoHash); void RegisterAccessInfo(AccessId how, void** info); void RegisterProperty(Prop* property); BOOL RegisteredProp(Prop property); void* GetProp(Prop p, DictElem* elem); /********************************************************* ** Useful dictionary constructors/destructors */ DICTv DictCreateKeyStr(int offs, BOOL repetitions); DICTv DictCreateKeyInt(int offs, BOOL repetitions); void DictDestroyWithClass(DICTv d); /******************************************************** ** CLASSoDICT creators ** if toKey is null, then it is assumed that: ** - the dictionary contains pointers to struct ** - toKeyInfo is the offset to the key attribute *******************************************************/ CLASSoDICT* DictCreateClassStrKey(KeyAccessor toKey, IntOrPtr toKeyInfo, BOOL repetitions); CLASSoDICT* DictCreateClassIntKey(KeyAccessor toKey, IntOrPtr toKeyInfo, BOOL repetitions); CLASSoDICT* DictCreateClassPtrKey(KeyAccessor toKey, IntOrPtr toKeyInfo, BOOL repetitions); CLASSoDICT* DictCreateClassSelfPtrKey (BOOL repetitions); #endif *****************************************************************/ char entry_ID[] = "$Id: entry.c,v 1.13 1996/08/14 16:19:26 etzold Exp $"; /* ** ** $RCSfile: entry.c,v $ ** $Revision: 1.13 $ ** $Date: 1996/08/14 16:19:26 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port by Lukas Rosenthaler and Reinhard ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** functions open flat files and indices for read access only - compare ** time stamps and retrieve entry information from ID-indices ** ** Global Parameters: ** "printf" ** "parseTest" ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "sm.h" #include "strv.h" #include "tm.h" #include "futil.h" #include "par.h" #include "id.h" #include "set.h" #include "library.h" #include "entry.h" #include "toklist.h" #include "icarus.h" #include "templ.h" #include "view.h" #include "query.h" #include "regexp.h" #define _SRS #define _SLB #include SRSINCLUDE #define ENTxUNKNOWNFIELD (SLBoFIELD *) 1L /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** private functions */ static FILEo *EntryJobNextFile (char *symName, void* data); static FILEo *EntryJobFile (char *symName, void* data); static void EntryEmptyViewInTable (VIEWoLIB *vlib, Int4 rowN); static void EntryPrintTableField (ENTRYo *entry, SLBoFIELD *field, LIBoFieldFormat *format, Int4 rowN); static INT4 EntryViewInTable (ENTRYo *entry, VIEWo *view, VIEWoLIB *vlib, Int4 entryNo, Int4 isRoot, Int4 rowN); static void EntryViewInList (ENTRYo *entry, VIEWo *view, VIEWoLIB *vlib, Int4 entryNum, Int4 isRoot); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** extern or module wide variables */ static FILE *outFile=NULL; #ifdef sun extern INT4 printf (); #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** default function for printing lines */ static INT4 EntryPrintF (char *formatStr, ...) { va_list ap; va_start (ap, formatStr); vfprintf (outFile, formatStr, ap); va_end (ap); if (formatStr[strlen (formatStr) -1] != '\n') fprintf (outFile, "\n"); return 1; } /**API* EntryOpen ************************************************************* ** ** Creates and returns an entry object which ** is a 'handle' to the 'real' entry ** contained in the flat file ** which can be accessed using functions such as ** EntryPrint, EntryPrintFields. To destroy the entry object again use ** EntryClose. ** ** INPUT: address of ID-object (see SetGetID) [R] ** IMPLICIT: ** ** RETURNS: new entry-object ** NULL if there is a problem with the ID or the ID index */ ENTRYo *EntryOpen (IDoENTRY *id) { ICAoJOB *job; ENTRYo *entry; entry = (ENTRYo *) calloc (1, sizeof (ENTRYo)); if (!(entry->lib = (SLBo *) LibObjById ("library", id->lib_x))) { _ErrMsg2 (e__libidnotknown, id->lib_x); EntryClose(&entry); /*PURIFY*/ return NULL; } entry->id = id; /* ** get information how to access entry within the library flat file */ LibEntryInfo (id->fip, entry->lib, &entry->fip[0], &entry->fip[1], &entry->fileX, &entry->indexTime, entry->entry_nm); if (!entry->lib->job) { job = IcaCreateJob (entry->lib->form->syntax); IcaSetInputStreamer (job, EntryJobFile); entry->lib->job = job; } else job = entry->lib->job; IcaSetInputStreamerData (job, (void*)entry); IcaJobNext (job); IcaSetInputFile (job, NULL); return entry; } /**API* EntryClose ************************************************************ ** ** Closes an entry object by deleting it. Sets entry pointer ** to NULL to prevent freeing it a second time. ** ** INPUT: address of pointer to entry-object [W] ** IMPLICIT: ** ** RETURNS: */ void EntryClose (ENTRYo **entry) { if (*entry) { free(*entry); *entry = NULL; } } void EntryClosePtr (ENTRYo *entry) { free(entry); } LIBoSUBENTRY *EntryGetSubEntry (SLBo *lib, IDoENTRY *id) { return lib->form->subEntries[0]; } /**API* EntryPrintFields ****************************************************** ** ** Prints one ore more of the entry's fields using the "printf" parameter ** function (prints to STDOUT if not defined). ** ** INPUT: address of entry object [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** e__filnotok + ** e__badfile */ INT4 EntryPrintFields (ENTRYo *entry) { LIBoSUBENTRY *subEntry=NULL; SRSoFLD *firstFieldType=NULL; SLBoFIELD *field; TOKoTOKEN *tok; char *tokStr, *code, *com; INT4 rv, c1, subN, subNCurr, (*print)(char *,...) = (INT4(*)(char *,...)) ParGetFunction ("print"); LibSetActiveFields (entry->lib); /** activate fields to be printed */ IcaSetTask (entry->lib->job, "hl", ParGetBool ("isHTMLFormat")); IcaSetTask (entry->lib->job, "html", ParGetBool ("isHTMLFormat")); entry->tokList = IcaGetTokenList (entry->lib->job, "fields"); /* for printing subentries */ if (IdIsSub (entry->id)) { subN = IdGetSubN (entry->id); subEntry = EntryGetSubEntry (entry->lib, entry->id); subNCurr = 0; firstFieldType = subEntry->first; } for (c1=0; (tok = TokNext (entry->tokList, &c1));) { if ((field = LibGetFieldWithCode (entry->lib, TokGetCode (tok))) && (LibIsField (field, "active") || field->type == firstFieldType)) { tokStr = TokGetStringCopy (entry->tokList, tok); if (LibIsField (field, "formatted")) { if ((com = LibGetFieldFormatEval (field))) { IcaEval (com); } } else if (subEntry && LibIsSubField (field, subEntry, "inSubEntry")) { if (LibIsSubField (field, subEntry, "first")) subNCurr++; if (subNCurr == subN || LibIsSubField (field, subEntry, "fromParent")) print (tokStr); } else print (tokStr); } } return 1; } /**API* EntryPrint ****************************************************** ** ** Prints entire entry. ** ** INPUT: address of entry object [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** e__filnotok + ** e__badfile */ INT4 EntryPrint (ENTRYo *entry) { SLBoFIELD *field; LIBoSUBENTRY *subEntry=NULL; TOKoTOKEN *tok; char *tokStr, *code, *com; INT4 rv, c1, c2, subN, subNCurr, (*print)(char *,...) = (INT4(*)(char *,...)) ParGetFunction ("print"); IcaSetTask (entry->lib->job, "hl", ParGetBool ("isHTMLFormat")); IcaSetTask (entry->lib->job, "html", ParGetBool ("isHTMLFormat")); entry->tokList = IcaGetTokenList (entry->lib->job, "fields"); /* for printing subentries */ if (IdIsSub (entry->id)) { subN = IdGetSubN (entry->id); subEntry = EntryGetSubEntry (entry->lib, entry->id); subNCurr = 0; } if (subEntry) for (c1=0; (tok = TokNext (entry->tokList, &c1));) { code = TokCodeToStr (TokGetCode (tok)); for (c2=0; (field = LibNextField (entry->lib, &c2)); ) { if (SmEqs (code, field->code)) { tokStr = TokGetStringCopy (entry->tokList, tok); if (*tokStr) if (LibIsSubField (field, subEntry, "inSubEntry") && subEntry) { if (LibIsSubField (field, subEntry, "first")) subNCurr++; if (subNCurr == subN) print (tokStr); } } } } else for (c1=0; (tok = TokNext (entry->tokList, &c1));) { tokStr = TokGetStringCopy (entry->tokList, tok); field = LibGetFieldWithCode (entry->lib, TokGetCode (tok)); if (LibIsField (field, "formatted")) { if ((com = LibGetFieldFormatEval (field))) IcaEval (com); } else if (*tokStr) print (tokStr); } return 1; } /**API* EntryGetFieldTable **************************************************** ** ** Retrieves the specfied field from the entries record using the ** table token. ** ** INPUT: entry object [W] ** field object [R] ** address of iteration variable [W] ** IMPLICIT: ** ** RETURNS: pointer to the string containing the field */ char *EntryGetField (ENTRYo *entry, SLBoFIELD *field, INT4 *c) { static TOKoLIST *tokList; TOKoTOKEN *tok; char *s=NULL; INT4 rv; if (!entry->tokList) { IcaSetTask (entry->lib->job, "hl", ParGetBool ("isHTMLFormat")); IcaSetTask (entry->lib->job, "html", ParGetBool ("isHTMLFormat")); entry->tokList = IcaGetTokenList (entry->lib->job, "fields"); } if (!*field->tableToken) { if ((tok = TokNextWithCode (entry->tokList, TokStrToCode (field->code), c))) s = TokGetStringCopy (entry->tokList, tok); } else { tokList = IcaGetTokenList (entry->lib->job, field->tableToken); if ((tok = TokNextWithCode (tokList, field->tableTokCode, c))) s = TokGetStringCopy (tokList, tok); } return s; } TOKoLIST *EntryGetTok (ENTRYo *entry, char *name) { INT4 rv; entry->tokList = IcaGetTokenList (entry->lib->job, "fields"); return IcaGetTokenList (entry->lib->job, name); } void EntryViewEntryNamePrint (VIEWo *view, ENTRYo *entry, Int4 entryNo, Int4 rowN, Int4 isRoot) { TemplPrint (isRoot ? "rootName" : "leafName", EntryGetFullName (entry)); } /**API* EntryView ************************************************************ ** ** Print a single entry with selected root library ** fields, links with leaf libraries and prints leaf ** library entries with selected fields in a tabular format. ** Needs the "view" from Www?. ** ** INPUT: entry object [W] ** view object [R] */ void EntryView (ENTRYo *entry, VIEWv view) { static Int4 entryNum=0; SETo *set; IDoENTRY id; ENTRYo *leafEntry; VIEWoLIB *vlib; VIEWoLEAFSET *leaves[50], *leaf; INT4 n, i, maxEntryN=1, leafLibsN=0, isTable=ViewIsTable (view); if (!view->entryNamePrint) /* improve !!!te*/ ViewSetEntryNamePrint (view, EntryViewEntryNamePrint); ViewTemplateBegin (view); /* do the link to the leaf libs and collect the resulting sets */ for (n=0; (vlib = ViewGetNextLeafLib (view, &n)); ) { set = Query (ViewGetLeafQuery (vlib, entry), NULL); leaf = (VIEWoLEAFSET *) malloc (sizeof (VIEWoLEAFSET)); leaf->vlib = vlib; leaf->set = set; leaf->entryN = set ? SetGetSize (set) : 0; if (leaf->entryN > maxEntryN && !ViewLeafIsOnlyEntryN (leaf->vlib)) maxEntryN = leaf->entryN; leaves[leafLibsN++] = leaf; } leaves[leafLibsN] = NULL; /* print the root entry */ for (i=0, vlib=NULL; (vlib = ViewGetNextRootLib (view, &i));) if (EntryGetLib (entry) == vlib->lib) break; if (isTable) EntryViewInTable (entry, view, vlib, ++entryNum, 1, maxEntryN); else EntryViewInList (entry, view, vlib, ++entryNum, 1); /* print the leaf entries */ if (!maxEntryN) TemplPrint ("tail"); else { for (n=1; n <= maxEntryN; n++) { for (i=0; (leaf = leaves[i]); i++) { if (n > leaf->entryN) { if (isTable && n==1) /* no linked entries */ EntryEmptyViewInTable (leaf->vlib, maxEntryN); continue; } #ifdef xxx if (ViewLeafIsOnlyEntryN (leaf->vlib)) { EntryViewPrintN (leaf, entry, maxEntryN); leaf->entryN = 0; /* prevent printing of more entries from set */ } else #endif { SetGetID (leaf->set, n, &id); leafEntry = EntryOpen (&id); if (isTable) EntryViewInTable (leafEntry, view, leaf->vlib, ++entryNum, 0, n==leaf->entryN ? maxEntryN-n+1 : 1); else EntryViewInList (leafEntry, view, leaf->vlib, ++entryNum, 0); EntryClose (&leafEntry); } } TemplPrint ("tail"); } } SetClean (); /* remove temp. sets */ ViewTemplateEnd (view); } /****** WwwViewEntryInTable *************************************************** ** ** Prints an entry view inside a table. ** ** INPUT: entry object [R] ** view object [R] ** ** RETURNS: number of fields printed for the entry */ static INT4 EntryViewInTable (ENTRYo *entry, VIEWo *view, VIEWoLIB *vlib, Int4 entryNo, Int4 isRoot, Int4 rowN) { SLBoFIELD *field; INT4 k, fieldsN; ViewEntryNamePrint (view, entry, entryNo, rowN, isRoot); for(k=0, fieldsN=1; (field = ViewGetNextField (vlib, &k)); fieldsN++) { TemplWith (ViewGetTemplate (view), "value"); EntryPrintTableField (entry, field, LibIsField (field, "formatted") ? ViewGetFieldFormat (vlib, field) : NULL, rowN); TemplEndWith (); } return fieldsN; } /****** EntryEmptyViewInTable ************************************************ ** ** Prints an empty entry inside a table. ** ** INPUT: view library object [R] ** number of rows entry should span [R] */ static void EntryEmptyViewInTable (VIEWoLIB *vlib, Int4 rowN) { SLBoFIELD *field; INT4 k; TemplPrint ("emptyValue", rowN); for(k=0; (field = ViewGetNextField (vlib, &k));) TemplPrint ("emptyValue", rowN); } void EntryViewPrintEnvelope (ENTRYo *entry, char *option) { if (option[0] == 'h') /* head */ switch (entry->lib->form->printFormat) { case LIBxTOPICLIST: TemplPrint ("$entry.inList.envelope.head.topicList"); break; case LIBxTABLE: TemplPrint ("$entry.inList.envelope.head.table"); break; default: TemplPrint ("$entry.inList.envelope.head.preformatted"); } else /* tail */ switch (entry->lib->form->printFormat) { case LIBxTOPICLIST: TemplPrint ("$entry.inList.envelope.tail.topicList"); break; case LIBxTABLE: TemplPrint ("$entry.inList.envelope.tail.table"); break; default: TemplPrint ("$entry.inList.envelope.tail.preformatted"); } } /****** EntryViewInList ****************************************************** ** ** Prints an entry view inside a list. ** ** INPUT: template object [W] ** entry object [R] ** */ static void EntryViewInList (ENTRYo *entry, VIEWo *view, VIEWoLIB *vlib, Int4 entryNo, Int4 isRoot) { LIBoFieldFormat *format; SLBoFIELD *field; INT4 k; if (ViewIsEntryNamePrinting (view)) ViewEntryNamePrint (view, entry, entryNo, 1, isRoot); ParDefStr ("fieldList", "reset"); for(k=0; (field = ViewGetNextField (vlib, &k));) { ParDefStr ("fieldList", LibGetFieldName (field)); if (LibIsField (field, "formatted")) { format = ViewGetFieldFormat (vlib, field); LibSelectFieldFormat (field->type, format->name); } } EntryViewPrintEnvelope (entry, "head"); EntryPrintFields (entry); EntryViewPrintEnvelope (entry, "tail"); ParDefStr ("fieldList", "reset"); } /****** WwwPrintTableField **************************************************** ** ** Prints a data field inside a table. ** ** INPUT: entry object [R] ** field object [R] ** the field format object [R] or NULL ** number of rows the cell should span [R} */ static void EntryPrintTableField (ENTRYo *entry, SLBoFIELD *field, LIBoFieldFormat *format, Int4 rowN) { char *tmp; INT4 c, type, l, k; switch (type = LibGetFieldFormat (entry->lib, field)) { case LIBxLEFT: TemplPrint ("leftAlign", rowN); break; case LIBxRIGHT: TemplPrint ("rightAlign", rowN); break; case LIBxCENTER: TemplPrint ("center", rowN); break; case LIBxLISTING: TemplPrint ("listing", rowN); break; } for (c=0, k=0; (tmp=EntryGetField (entry, field, &c)); k++) { if (k) TemplPrint ("next"); if (format) { char *com; if ((com = format->eval)) { IcaEval (com); } } else { l = strlen (tmp); if (tmp[l-1] == '\n') tmp[l-1] = '\0'; TemplPrint ("value", tmp); } } if (!k) TemplPrint ("empty"); TemplPrint ("tail"); } INT4 EntryPrintSet (char *setName, INT4 firstN, INT4 printN) { ENTRYo *entry; SETo *set; IDoENTRY id; INT4 k, n, (*printEntry)(); set = SetGet (setName); if (!printN) printN = set->n; for (n=0, k=firstN; k < firstN + printN; k++, n++) { SetGetID (set, k, &id); entry = EntryOpen (&id); if (entry) { if ((printEntry = (INT4(*)()) id.id_d->cpy)) (*printEntry) (entry, set->nam, printN, n); EntryClose (&entry); } } return printN; } /**api* EntrySourceName ******************************************************* ** ** returns the name of the entry source...is resolved in the following ** order: the logical name of the flatfile (GCG), the logical name of ** the whole library, just the library name ** ** INPUT: address of entry objcect [R] ** address of output string receiving the source name [W] ** IMPLICIT: ** ** RETURNS: */ void EntrySourceName (ENTRYo *entry, char *source_nm) { char *name; if (*(name = (entry->lib->fil[ entry->fileX ].lnam)) || *(name = entry->lib->lnam[0]) || (name = entry->lib->nam)) strcpy (source_nm, name); } FILEo *EntryGetNextJobFile (ENTRYo *entry, char *name) { } /**api* EntryJobFile ********************************************************** ** ** Opens the file to access access the current entry. ** ** INPUT: entry object [R] ** symbolic file name [R] ** ** RETURNS: file object ** NULL: end of input stream */ static FILEo *EntryJobFile (char *symName, void* data) { ENTRYo *entry=(ENTRYo*)data; SRSoFILTYP *ft; FILEo **file; Int4 ftX, rv; ft=LibGetFileType (EntryGetLib (entry), symName, &ftX); file = &entry->file[ftX]; /* single file per entry */ if (LibIsFilePerEntry (entry->lib)) { if (LibOpenEntryFile (EntryGetLib (entry), file, ft, EntryGetName (entry))) return *file; else return NULL; } /* entry is in flat file */ else { if (!(*file = LibOpenFlatFile (entry->lib, entry->fileX, ft, &rv))) _ErrExit2 (rv, FileGetName (*file, "full")); FileSeek (*file, entry->fip[ftX]); return *file; } } /**api* EntryJobNextFile ***************************************************** ** ** Opens the next entry file mathing some criterion. To be used only ** as argument for IcaSetInputStreamer and for databanks where entries ** reside in separate files. See also EntryJobFile. ** ** INPUT: entry object [R] ** symbolic file name [R] ** ** RETURNS: file object ** NULL: end of input stream */ FILEo *EntryJobNextFile (char *symName, void* data) { ENTRYo *entry=(ENTRYo*)data; SLBo *lib=EntryGetLib (entry); FILEo **file; SRSoFILTYP *ft; Int4 x, rv; ft=LibGetFileType (lib, symName, &x); file = &entry->file[x]; /* single file per entry */ if (LibIsFilePerEntry (lib)) { if (LibOpenNextEntryFile (lib, file, ft)) { strcpy (entry->entry_nm, FileGetName (*file, "name")); return *file; } } /* entry is in flat file */ else { if (!(rv = LibOpenNextFlatFile (lib, file, ft, &entry->fileX))) return NULL; else if (rv == -1) _ErrExit2 (e__filnotok, FileGetName (*file, "full")); else if (rv == 1) return *file; else if (rv == 2) { _ErrMsg2 (i__processing, FileGetName (*file, "full")); FileSetGetFip (*file, 1); return *file; } } return NULL; } /**API* EntryOpenStream ******************************************************* ** ** Opens an entry stream. Entries can be read in sequential order with ** "EntryNext" ** ** INPUT: address of library object [R] ** IMPLICIT: ** ** RETURNS: entry object */ ENTRYo *EntryOpenStream (SLBo *lib) { ENTRYo *entry; if ((entry = (ENTRYo *) calloc (1, sizeof (ENTRYo))) == NULL) _ErrExit2 (e__allocfail, "entry-object"); if ((entry->id = (IDoENTRY *) calloc (1, sizeof (IDoENTRY))) == NULL) _ErrExit2 (e__allocfail, "id-object"); entry->id->id_d = (IDoTYPE*) LibObjByName ("idtype", "Entry-ID"); entry->lib = lib; entry->lib->job = IcaCreateJob (lib->form->syntax); entry->lib->allEntryCnt=0; IcaSetInputStreamer (entry->lib->job, EntryJobNextFile); IcaSetInputStreamerData (entry->lib->job, (void*)entry); entry->fileX = -1; return entry; } /**API* EntryNext ************************************************************* ** ** Opens next entry in the entry stream (opened by "EntryOpenStream"). ** ** INPUT: address of entry object [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if all entries have been accessed */ INT4 EntryNext (ENTRYo *entry) { ICAoJOB *job=entry->lib->job; if (IcaIsInputEnd (job)) { IcaEndJob (job); return 0; } IcaJobNext (job); if (!job->file) IcaSetInputFile (job, NULL); entry->lib->allEntryCnt++; return 1; } /**API* EntryGetName ******************************************************* ** ** Returns the plain entry name without the library name prefixed. ** ** INPUT: address of entry object [R] ** ** RETURNS: entry name */ char *EntryGetName (ENTRYo *entry) { return entry->entry_nm; } /**API* EntryGetFullName ***************************************************** ** ** Returns the full entry name: databank name ':' entry name. ** ** INPUT: address of entry object [R] ** ** RETURNS: address of entry name */ char *EntryGetFullName (ENTRYo *entry) { if (!*entry->full_nm) sprintf (entry->full_nm, "%s:%s", LibName (entry->lib), entry->entry_nm); return entry->full_nm; } /**API* EntryGetGCGName ******************************************************* ** ** Returns the full entry name in GCG style. ** ** INPUT: address of entry object [R] ** ** RETURNS: address of entry name */ char *EntryGetGCGName (ENTRYo *entry) { static char name[200]; char libName[40]; EntrySourceName (entry, libName); sprintf (name, "%s:%s", libName, EntryGetName (entry)); return name; } /**API* EntryGetLib *********************************************************** ** ** Returns the library object of entry's source databank; ** ** INPUT: address of entry object [R] ** ** RETURNS: library object */ SLBo *EntryGetLib (ENTRYo *entry) { return entry->lib; } /**API* EntryGetJob *********************************************************** ** ** Returns the library object of entry's source databank; ** ** INPUT: address of entry object [R] ** ** RETURNS: library object */ ICAoJOB *EntryGetJob (ENTRYo *entry) { return entry->lib->job; } /**API* EntryGetId *********************************************************** ** ** Returns the entry's ID object. ** ** INPUT: address of entry object [R] ** ** RETURNS: ID object */ IDoENTRY *EntryGetId (ENTRYo *entry) { return entry->id; } /**API* EntryGetAuxInfo ******************************************************* ** ** Returns auxilliary information about an entry. ** ** INPUT: address of entry object [R] ** ** RETURNS: buffer object */ SMoBUFF *EntryGetAuxInfo (ENTRYo *entry) { static SMoBUFF *buff=NULL; buff = BuffInit (buff, 100); LibGetEntryAuxInfo (entry->id->fip, entry->lib, buff); return buff; } void EntryIopSetFieldFormat (Int4 runTime, STRv fieldName, STRv formatName) { LIBoFieldFormat *format; SRSoFLD *fieldType; Int4 c, isFound=0; if (runTime) IargGetArgs ("field|set", &fieldName, &formatName); if (!StrLen(fieldName) || !StrLen(formatName)) return; /* return if empty strings */ if (!(fieldType = (SRSoFLD*)LibObjByName ("fieldType", _Str(fieldName)))) _ErrExit3 (e__objectunknown, "field type", _Str (fieldName)); for (c=0; (format = LibNextFieldFormat (fieldType, &c));) { if (SmEqs (format->name, _Str(formatName))) { isFound=1; format->isSelected = 1; } else format->isSelected = 0; } if (!isFound) _ErrExit3 (e__unknownformat, _Str(fieldName), _Str(formatName)); StrDel (fieldName); StrDel (formatName); } ** ** $RCSfile: entry.h,v $ ** $Revision: 1.4 $ ** $Date: 1996/08/11 22:47:03 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** */ #define ENTxXLBL 5 /* max no of field recognition labels */ #define ENTxXSUBLN 20 /* max no of lines describing subentry */ enum CheckInField {ENTxFIELDLEN=1, ENTxINFIELD, ENTxINSUBFIELD, ENTxENDFIELD}; #define ENTxNOTOUCH -1 enum ent_section {ENTxTEXT=0, ENTxDATA}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Describes an entry in a flat file opened for read access. All ** different sections (eg, text, data) can be opened simultaneously. */ typedef struct ENTRYo { struct IDoENTRY *id; /* pointer to ID-object */ struct SLBo *lib; /* (API) address of library object */ char entry_nm[132]; /* unique entry name */ char full_nm[132]; /* unique entry name */ FIP fip[2]; /* file ptr to the section in flat file */ struct FILEo *file[2]; /* file descriptor for a section */ struct SLBoFIELD *field; struct TOKoLIST *tokList; /* token list with the "field" tokens */ Int4 fileX; UINT4 indexTime; UINT4 fileCreTime[2]; } ENTRYo; #ifndef _VIEWo typedef struct VIEWo *dummytointroducestructtagVIEWo; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ /* accessing an entry */ ENTRYo *EntryOpen (struct IDoENTRY *id); INT4 EntryOpenText (ENTRYo *entry); INT4 EntryOpenData (ENTRYo *entry); void EntryClose (ENTRYo **entry); INT4 EntryBeginSub (ENTRYo *entry); INT4 EntryNextSub (ENTRYo *entry); ENTRYo *EntryOpenStream (struct SLBo *lib); INT4 EntryNext (ENTRYo *entry); struct SLBoFIELD *EntryNextField (ENTRYo *entry, INT4 doLabelRemove, INT4 doNotReadLine); char *EntryGetFieldTable (ENTRYo *entry, struct SLBoFIELD *field, INT4 *c); /* printing entries */ INT4 EntryPrint (ENTRYo *entry); INT4 EntryPrintFields (ENTRYo *entry); void EntryView (ENTRYo *, struct VIEWo *); /* some info */ INT4 EntryIsSub (); INT4 EntryIsEndLine (ENTRYo *entry); void EntrySourceName (ENTRYo *entry, char *source_nm); char *EntryGetFullName (ENTRYo *entry); char *EntryGetName (ENTRYo *entry); char *EntryGetGCGName (ENTRYo *entry); struct SLBo *EntryGetLib (ENTRYo *entry); struct SMoBUFF *EntryGetAuxInfo (ENTRYo *entry); struct TOKoLIST *EntryGetTok (ENTRYo *entry, char *name); struct ICAoJOB *EntryGetJob (ENTRYo *entry); struct IDoENTRY *EntryGetId (ENTRYo *entry); #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "toklist.h" #include "cursor.h" #include "error.h" /******* ErrPop *************************************************** ** */ static ERRo *ErrPop(ERRoSTACK *errStack) { if(errStack->current > errStack->top) return(--errStack->current); else return(NULL); } /******* ErrPush *************************************************** ** */ static ERRo *ErrPush(ERRoSTACK *errStack) { if(errStack->current <= errStack->bottom) return(errStack->current++); else return(NULL); } /******* ErrNewStack *************************************************** ** */ ERRoSTACK *ErrNewStack() { ERRoSTACK *errStack; if( (errStack = (ERRoSTACK *)malloc(sizeof(ERRoSTACK))) == NULL ) _ErrExit2 (e__allocfail, "Error object"); memset(errStack, NULL, sizeof(ERRoSTACK)); errStack->top = errStack->error; errStack->bottom = errStack->error+1-1; /* maxstacksize not needed any more?*/ errStack->current = errStack->top; return(errStack); } /******* ErrErase *************************************************** ** */ void *ErrErase(ERRoSTACK *errStack) { errStack->current = errStack->top; /* printf("*********** ERASE **********************\n"); */ return; } /******* ErrIsFound *************************************************** ** */ INT4 ErrIsFound(ERRoSTACK *errStack, INT4 code) { ERRo *error; error = errStack->top; while(error <= errStack->current && error->code != code) error++; error--; return(errStack->current != error); } /******* ErrThrow *************************************************** ** */ void *ErrThrow(ERRoSTACK *errStack, char *pattern, INT4 code) { ERRo *error; if( (error = ErrPush(errStack)) ) { error->pattern = pattern; error->code = code; /* printf("Throw error now\t\t%s\n", pattern); */ } /* else */ /* _ErrMsg2 (e__overflowstack, MAXSTACKSIZE); */ return; } /******* ErrCatch *************************************************** ** */ ERRo *ErrCatch(ERRoSTACK *errStack, INT4 code) { ERRo *error; while( (error = ErrPop(errStack)) && code != error->code) ; return(error); } /******* ErrPrint *************************************************** ** */ void *ErrPrint(ERRoSTACK *errStack, char *name, INT4 code) { static char line[ERRxMAXPRINTSIZE+1], dots[ERRxMAXPRINTSIZE+1]; char *begin, *position, *ptr; INT4 len; ERRo *error; memset(line, NULL, ERRxMAXPRINTSIZE); memset(dots, NULL, ERRxMAXPRINTSIZE); begin = CursorGetBegin(Cursor); position = CursorGetPtr(Cursor); ptr = position; len = 0; while(ptr > begin && len < ERRxMAXPRINTSIZE/2 && *ptr != '\n') { len++; ptr--; } if(*ptr == '\n' && len) { ptr++; len--; } if(len) { strncpy(line, ptr, len); memset(dots, '.', len); } strcat(dots, "^"); ptr = position; len = 1; while(ptrcode, name, line, dots); do { printf(" |%s|\n", error->pattern); } while( error = ErrCatch(errStack, code) ); printf(" did not succeed to fit.\n"); } return; } #ifdef MAIN /* USAGE: cc -g -L /home/srs/srs5/bin/irix -I/home/srs/srs5/src -DSRSINCLUDE=\"srswin.h\" -DMAIN error.c */ static char *Test1 = "1234567890 Test String #1"; static char *Test2 = "1234567890 Test Long Long Long Long Long Long Long Long Long Long Long Long Long Long Long Long String #2"; static char *Test3 = "\n1234567890 Empty Test String #3"; static char *Test4 = "1234567890\nTest String with NewLine \n Continue #4"; char *ErrStrBegin, *ErrStrPtr; CURSORo *Cursor = NULL; /******make SRS happy*****/ char *CursorGetBegin(CURSORo *cursor){ return(ErrStrBegin); } char *CursorGetPtr(CURSORo *cursor){ return(ErrStrPtr); } INT4 Message (INT4 i, INT4 j, INT4 k, ...){ printf("Mess: %d %d %d\n",i,j,k); } FUNC SDL_fnct[1]; main() { ERRoSTACK *errStack; errStack = ErrNewStack(); printf("******* Test1 *******\n"); ErrStrBegin = Test1; ErrStrPtr = Test1 + 5; ErrErase(errStack); ErrThrow(errStack, "err1.1", 1); ErrThrow(errStack, "err1.2", 1); ErrThrow(errStack, "err1.3", 1); ErrThrow(errStack, "err1.4", 1); if(ErrIsFound(errStack, 1)) ErrPrint(errStack, "Dummy", 1); printf("******* Test2 *******\n"); ErrStrBegin = Test2; ErrStrPtr = Test2 + 80; ErrErase(errStack); ErrThrow(errStack, "err2.1", 1); ErrThrow(errStack, "err2.2", 2); ErrThrow(errStack, "err2.3", 1); ErrThrow(errStack, "err2.4", 2); ErrPrint(errStack, "Dummy", 2); printf("******* Test3 *******\n"); ErrStrBegin = Test3; ErrStrPtr = Test3; ErrErase(errStack); ErrThrow(errStack, "err3.1", 3); ErrThrow(errStack, "err3.2", 1); ErrThrow(errStack, "err3.3", 1); ErrThrow(errStack, "err3.4", 1); ErrPrint(errStack, "Dummy", 3); printf("******* Test4 *******\n"); ErrStrBegin = Test4; ErrStrPtr = Test4 + 9; ErrErase(errStack); ErrThrow(errStack, "err4.1", 1); ErrThrow(errStack, "err4.2", 1); ErrThrow(errStack, "err4.3", 1); ErrThrow(errStack, "err4.4", 4); ErrPrint(errStack, "Dummy", 4); printf("******* Test5 *******\n"); ErrStrBegin = Test1; ErrStrPtr = Test1+4; ErrErase(errStack); ErrThrow(errStack, "err4.1", 1); ErrThrow(errStack, "err4.2", 1); ErrThrow(errStack, "err4.3", 1); ErrThrow(errStack, "err4.4", 1); if( ErrIsFound(errStack, 5) ) ErrPrint(errStack, "Dummy", 5); else printf("No error level 5 was detected\n"); } #endif ** ** $RCSfile: error.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/05/06 19:20:33 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #define ERRxMAXPRINTSIZE 72 typedef struct ERRo { char *pattern; /* patternt that does not fit */ INT4 code; /* error code */ } ERRo; typedef struct ERRoSTACK { ERRo error[1]; /* not needed any more ? */ ERRo *top; ERRo *bottom; ERRo *current; } ERRoSTACK; /* prototypes and external */ extern CURSORo *Cursor; ERRoSTACK *ErrNewStack(); void *ErrErase(ERRoSTACK *errStack); void *ErrThrow(ERRoSTACK *errStack, char *pattern, INT4 code); ERRo *ErrCatch(ERRoSTACK *errStack, INT4 code); void *ErrPrint(ERRoSTACK *errStack, char *name, INT4 code); INT4 ErrIsFound(ERRoSTACK *errStack, INT4 code); char file_srs_ID[] = "$Id: futil.c,v 1.15 1996/08/12 20:24:26 etzold Exp $"; /* ** ** $RCSfile: futil.c,v $ ** $Revision: 1.15 $ ** $Date: 1996/08/12 20:24:26 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: This module has been modified in major parts ** by Lukas Rosenthaler and Reinhard ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** contains routines for opening files, testing filenames; ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "regexp.h" #ifdef dos #else # ifdef VMS # include # include # include # include "rtl.h" # else # include # include # include # include # include # define TMPSTR_LEN 256 # endif #endif #include "futil.h" #include "sm.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** defining file with variable record length under VMS */ #ifdef VMS # define VARFILE , "rat=cr", "rfm=var" # define READ "r" #else # define VARFILE # define READ "rb" #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** objectwide variables */ #ifndef VMS static char *FilTranslate (char *, INT4); char *(*filTranslate)(char *, INT4) = FilTranslate; # define PATH_BUF_LEN 132 /* maximal length of pathname */ /**api* FilTranslate ********************************************************** ** ** called using the macro _FilLN; ** converts a name containing logicals into the expanded name, works ** with both VMS and UNIX syntax; overwrites input name!!! and ** assumes that input character array is large enough to handle output; ** ** INPUT: o address of file name string [W] ** o TRUE if output should not overwrite input - instead ** functions own static array is used - be sure you ** don't need output name after next call! [R] ** ** RETURNS: address of translated string - same address as input */ static char *FilTranslate (char *fileName, int isTemp) { static int count=0; static char tmpNames[5][PATH_BUF_LEN+1], *tmp; extern int LogNameTranslate (char *name, char *trans_name, int len); tmp = tmpNames[count++%5]; LogNameTranslate (fileName, tmp, PATH_BUF_LEN); if (!isTemp) { strcpy (fileName, tmp); return fileName; } else return tmp; } #endif /**api* FilOpenR ************************************************************** ** ** open file for read access; has the "b" option for opening binary files ** under DOS; ** ** INPUT: address of file name [R] ** address of error code [W] or NULL ** e__filnotok ** IMPLICIT: ** ** RETURNS: file pointer ** ...NULL if not successfull */ FILE *FilOpenR (char *fnam, int *errCode) { FILE *fptr; if ((fptr = fopen (_FilTempLN (fnam), "rb")) == NULL) { _ErrSet (errCode, e__filnotok); return NULL; } rewind (fptr); _ErrSet (errCode, 1); return fptr; } /**api* FilOpenRF ************************************************************* ** ** open file for read access; has the "b" option for opening binary files ** under DOS + varible record format under VMS; ** ** INPUT: address of file name [R] ** address of error code [W] or NULL ** e__filnotok ** IMPLICIT: ** ** RETURNS: file pointer ** ...NULL if not successfull */ FILE *FilOpenRF (char *fnam, int *errCode) { FILE *fptr; if ((fptr = fopen (_FilTempLN (fnam), READ)) == NULL) { _ErrSet (errCode, e__filnotok); return NULL; } rewind (fptr); _ErrSet (errCode, 1); return fptr; } /**api* FilOpenWV ************************************************************* ** ** open file in variable record format for write access ** ** INPUT: address of file name [R] ** address of error code [W] or NULL ** e__filnotok ** IMPLICIT: ** ** RETURNS: file pointer ** ...NULL if not successfull */ FILE *FilOpenWV (char *fileName, int *errCode) { FILE *file_d; if ((file_d = fopen (_FilTempLN (fileName), "w" VARFILE)) == NULL) { _ErrSet (errCode, e__filnotok); return NULL; } rewind (file_d); _ErrSet (errCode, 1); return file_d; } /**api* FilOpenW ************************************************************* ** ** open file for write access ** ** INPUT: address of file name [R] ** address of error code [W] or NULL ** e__filnotok ** IMPLICIT: ** ** RETURNS: file pointer ** ...NULL if not successfull */ FILE *FilOpenW (char *fileName, int *errCode) { FILE *file_d; if ((file_d = fopen (_FilTempLN (fileName), "wb+")) == NULL) { _ErrSet (errCode, e__filnotok); return NULL; } rewind (file_d); _ErrSet (errCode, 1); return file_d; } /**api* FilOpenU ************************************************************* ** ** open file for write access ** ** INPUT: address of file name [R] ** address of error code [W] or NULL ** e__filnotok ** IMPLICIT: ** ** RETURNS: file pointer ** ...NULL if not successfull */ FILE *FilOpenU (char *fileName, int *errCode) { FILE *file_d; if ((file_d = fopen (_FilTempLN (fileName), "r+")) == NULL) { _ErrSet (errCode, e__filnotok); return NULL; } fseek (file_d, 0, 2); _ErrSet (errCode, 1); return file_d; } /**api* FilTestW ************************************************************** ** ** tests whether a file can be opened (created) for write access; ** tests also a directory specification; ** ** INPUT: address of file name [R] ** ** RETURNS: 1 if ok ** e__invalofn */ INT4 FilTestW (char *fileName) { FILE *fil; char tmpName[FILxXNAM+1], testName[FILxXNAM+1]; char tmp2Name[256]; strcpy (testName, _FilTempLN (fileName)); if ((fil = fopen (testName, "w")) == NULL) return e__invalofn; #ifdef VMS fgetname (fil, tmpName, 1); /* delete correct file */ fclose( fil); if (delete (tmpName) != 0) return e__invalofn; #else fclose (fil); unlink (testName); #endif if (!FilParse (tmpName, tmp2Name, FILxNAME)) return e__invalofn; return 1; } /**api* FilTestDirW *********************************************************** ** ** tests whether a directory can be opened for write access; ** ** INPUT: address of file name [R] ** name option: FILxNAME, FILxDEST [R] ** ** RETURNS: 1 if ok ** e__invalofn */ INT4 FilTestDirW (char *fileName) { FILE *fil; char tmpName[FILxXNAM+1], testName[FILxXNAM+1]; char tmp2Name[256]; if (!FilParse (_FilTempLN (fileName), testName, FILxDEST)) return e__invalofn; strcat(testName, "x.x"); /** conv. to ordinary filspec */ FilParse (testName, tmp2Name, FILxNAME); if ((fil = fopen (testName, "w")) == NULL) return e__invalofn; #ifdef VMS fgetname (fil, tmpName, 1); /* delete correct file */ fclose( fil); if (delete (tmpName) != 0) return e__invalofn; #else fclose (fil); unlink (testName); #endif if (!FilParse (tmpName, tmp2Name, FILxNAME)) return e__invalofn; return 1; } /**api* FilTestR ************************************************************** ** ** tests whether a file can be accessed for reading; ** ** INPUT: name of file ** ** RETURNS: 1 if ok ** e__invalifn */ INT4 FilTestR(char *fileName) { if (access (_FilTempLN (fileName), 4) == EOF) return e__invalifn; return 1; } /**api* FilParse ************************************************************** ** ** parses a file name and returns: ** FILxNODE, FILxDEV, FILxROOT, FILxDIR, FILxNAME, FILxTYPE, FILxVERS ** ** INPUT: address of file name [R] ** address where to put part of file name [W] ** type (see above) [R] ** ** RETURNS: 1 if successful ** 0 if specified part was not found */ INT4 FilParse(char *innam, char *outnam, INT4 typ) { #ifdef VMS struct itemdesc { unsigned short len; unsigned short code; char *item; } itemd[8]; INT4 k, ret, len; itemd[FILxNODE].code = FSCN$_NODE; itemd[FILxDEV].code = FSCN$_DEVICE; itemd[FILxROOT].code = FSCN$_ROOT; itemd[FILxDIR].code = FSCN$_DIRECTORY; itemd[FILxNAME].code = FSCN$_NAME; itemd[FILxTYPE].code = FSCN$_TYPE; itemd[FILxVERS].code = FSCN$_VERSION; itemd[7].len = 0; /* longword at end of list = 0 */ itemd[7].code = 0; ret = sys$filescan ( _Psi(innam), itemd, 0); _StopIfEven(ret); if (typ == FILxDEST) { for (k = FILxDEV; k <= FILxNAME && itemd[k].item == NULL; k++) ; if (k == FILxNAME) return 0; len = itemd[FILxDEV].len + itemd[FILxROOT].len + itemd[FILxDIR].len; strncpy(outnam, itemd[k].item, len); } else if (typ == FILxSPEC) { for (k = FILxNAME; k <= FILxVERS && itemd[k].item == NULL; k++) ; if (k == FILxVERS) return 0; len = itemd[FILxNAME].len + itemd[FILxTYPE].len; strncpy(outnam, itemd[k].item, len); } else { if (itemd[typ].item == NULL) return 0; len = itemd[typ].len; strncpy(outnam, itemd[typ].item, len); } outnam[len] = '\0'; #else #define DIR_LEN 256 char cwd[DIR_LEN], t_innam[DIR_LEN]; INT4 i; strcpy (t_innam, innam); (void) getcwd (cwd, DIR_LEN); switch (typ) { /* ** return node name only (void on UNIX) */ case FILxNODE : { (void) strcpy (outnam, ""); break; } /* ** return device (void on UNIX) */ case FILxDEV : { (void) strcpy (outnam, ""); break; } /* * return root directory (current working directory on UNIX) */ case FILxROOT : { (void) strcpy (outnam, cwd); break; } /* * get directory path of file */ case FILxDIR : { for (i = strlen (_FilLN (t_innam)) - 1; (i >= 0) && (t_innam[i] != '/'); i--); if (t_innam[0] != '/') { /* * relative path, add absolute path of current working directory */ strcpy (outnam, cwd); strcat (outnam, "/"); if (i > 0) strncat (outnam, t_innam, i); } else { /* * absolute path */ (void) strncpy (outnam, t_innam, i); outnam[i] = '\0'; } break; } /* * return filename only without extension */ case FILxNAME : { for (i = strlen (t_innam) - 1; (i >= 0) && !strchr ("/:", t_innam[i]); i--) ; strcpy (outnam, &(t_innam[i+1])); for (i = strlen (outnam) - 1; (i >= 0) && (outnam[i] != '.'); i--); outnam[i] = '\0'; break; } /* * return file type (extension of the form file.ext) * ^^^ */ case FILxTYPE : { /* * scan file name from tail. If a '.' or a '/' is encountered, stop! */ for (i = strlen (t_innam) - 1; (i >= 0) && (t_innam[i] != '.') && (t_innam[i] != '/'); i--) ; if ((i <= 0) || (t_innam[i] == '/')) { /* no "file type"... */ (void) strcpy (outnam, ""); } else { (void) strcpy (outnam, &(t_innam[i+1])); /* o.k, "file type" found */ } break; } /* * file version (void on UNIX) */ case FILxVERS : { (void) strcpy (outnam, ""); break; } /* * full directory path */ case FILxDEST : { for (i = strlen (t_innam) - 1; (i >= 0) && (t_innam[i] != '/'); i--) ; if (t_innam[0] != '/') { /* relative path */ strcpy (outnam, cwd); strcat (outnam, "/"); if (i > 0) strncat (outnam, t_innam, i - 1); } else { if (i > 1) { (void) strncpy (outnam, t_innam, i); outnam[i] = '\0'; } else { (void) strncpy (outnam, t_innam, 1); outnam[1] = '\0'; } } break; } /* * full file name with extension (but without preceeding directory) */ case FILxSPEC : { for (i = strlen (t_innam) - 1; (i >= 0) && (t_innam[i] != '/'); i--); if (i >= 0) { (void) strcpy (outnam, &(t_innam[i+1])); } else { (void) strcpy (outnam, ""); } break; } } #endif return 1; } /**api* FilReadLn ************************************************************* ** ** reads a line and discards new line character; ** ** INPUT: address of file pointer ** address of output string ** max number of characters to be read ** ** RETURNS: 1 if success ** e__filnotok if not */ INT4 FilReadLn(FILE *fil, char *ln, INT4 nchar) { INT4 len; if (fgets(ln, nchar, fil) == NULL) return e__filnotok; len = strlen(ln); if (ln[len-1] == '\n') ln[len-1] = '\0'; return 1; } /**api* FilUOpen ************************************************************** ** ** opens file for read access and allocates an array that is to hold ** the lines read and reads first line ** ** INPUT: address of FILo ** address of file name ** max line length ** file type: FILxSTREAM or FILxVAR ** ** RETURNS 1 if success ** e__filopenerr ** e__allocfail ** e__eof ** e__filnotok ** e__ltoolong if line len > max len ** */ INT4 FilUOpen (FILo *file, char *fileName, INT4 len, INT4 ft) { INT4 rv; if (ft == FILxVAR) { if ((file->fil = fopen (_FilTempLN (fileName), READ)) == NULL) return e__filnotok; } else if ((file->fil = fopen (_FilTempLN (fileName), READ)) == NULL) return e__filopenerr; rewind (file->fil); if ((file->ln = malloc(len)) == 0) return e__allocfail; (void) strcpy (file->nam, _FilTempLN (fileName)); file->n = 0; file->len = len; file->eof = FALSE; file->c_s = 0; file->isPipe = 0; /* ** read first line of file...if that fails free the buffer for the ** current line and return error */ rv = FilURead (file); /* read first line */ _ErrIf (rv) free (file->ln); return rv; } /**api* FilUOpenPipe ********************************************************** ** ** opens a pipe for read access and allocates an array that is to hold ** the lines read and reads first line ** ** INPUT: address of FILo ** address of file name ** max line length ** file type: FILxSTREAM or FILxVAR ** ** RETURNS 1 if success ** e__filopenerr ** e__allocfail ** e__eof ** e__filnotok ** e__ltoolong if line len > max len ** */ INT4 FilUOpenPipe (FILo *file, char *fileName, char *comFormat, INT4 maxLen) { INT4 rv; char com[500]; sprintf (com, comFormat, _FilTempLN (fileName)); #ifndef VMS if (!(file->fil = popen (com , "r"))) return e__filopenerr; #endif if ((file->ln = malloc (maxLen)) == 0) return e__allocfail; (void) strcpy (file->nam, _FilTempLN (fileName)); file->n = 0; file->len = maxLen; file->eof = FALSE; file->c_s = 0; file->isPipe = 1; /* ** read first line of file...if that fails free the buffer for the ** current line and return error */ rv = FilURead (file); /* read first line */ _ErrIf (rv) free (file->ln); return rv; } /**api* FilUOpen2 ************************************************************* ** ** should become obsolete! ** Allocates file-descriptor, ** opens file for read access and allocates an array that is to hold ** the lines read and reads first line ** ** ** INPUT: address of pointer to FILo [W] ** address of file name [R] ** max line length [R] ** file type: FILxSTREAM or FILxVAR [R] ** ** RETURNS 1 if success ** e__filopenerr ** e__allocfail ** e__eof ** e__filnotok ** e__ltoolong if line len > max len ** */ INT4 FilUOpen2 (FILo **file_p, char *fileName, INT4 len, INT4 ft) { FILo *file; INT4 rv; if ((file = malloc (sizeof (FILo))) == 0) { return e__allocfail; } if (ft == FILxVAR) { if ((file->fil = fopen (_FilTempLN (fileName), READ)) == NULL) return e__filnotok; } else if ((file->fil = fopen (_FilTempLN (fileName), READ)) == NULL) { free (file); return e__filopenerr; } rewind (file->fil); if ((file->ln = malloc(len)) == 0) return e__allocfail; (void) strcpy (file->nam, fileName); file->n = 0; file->len = len; file->eof = FALSE; file->svn = 0; file->c_s = '\0'; file->isPipe = 0; *file_p = file; /* ** read first line of file...if that fails free the buffer for the ** current line and return error */ rv = FilURead (file); /* read first line */ _ErrIf (rv) free (file->ln); return rv; } /**api* FilUClose ************************************************************* ** ** closes file opened with FilUOpen and frees again the line buffer; ** ** INPUT: address of file descr. (FILo) ** ** RETURNS: 1 if ok ** e__freefail + */ INT4 FilUClose (FILo *file) { if (file == NULL) return 1; if (file->fil != NULL) { #ifndef VMS if (file->isPipe) pclose (file->fil); else #endif fclose (file->fil); file->fil = NULL; } if (file->ln) free (file->ln); return 1; } /**api* FilUClose2 ************************************************************ ** ** should become obsolete! ** closes file opened with FilUOpen and frees again the line buffer; ** frees storage used by FILo; ** ** INPUT: address of file descr. (FILo) ** ** RETURNS: 1 if ok ** e__freefail + */ INT4 FilUClose2 (FILo *file) { if (file == NULL) return 1; if (file->fil != NULL) fclose (file->fil); free (file->ln); free (file); file = NULL; return 1; } /**api* FilURead ************************************************************** ** ** reads a line in file; input and output ATTRIBUTEs are contained in ** FILo; checks whether read line ends with a '\n' if not ** error is reported and f->n is not incremented; ** ** INPUT: address of FILo ** ** RETURNS: e__eof <> ** e__filnotok <> ** e__ltoolong <> ** 1 if successful */ INT4 FilURead (FILo *f) { INT4 rv = 1; f->crfdd = ftell(f->fil); /* save file address */ if (fgets(f->ln, f->len, f->fil) == NULL) { if (feof(f->fil) != 0) { f->eof = TRUE; *f->ln = '\n'; *(f->ln+1) = '\0'; f->l = f->ln; return e__eof; } return e__filnotok; } /* if (f->ln[strlen(f->ln) - 1] != '\n') rv = e__ltoolong; */ f->l = f->ln; if (rv == 1) (f->n)++; return rv; } /**api* FilUSave ************************************************************** ** ** saves info about current line + offset so that it can be restored ** again with FilUBack ** ** INPUT: address of FILo ** address of FILoL_S ** ** RETURNS: 1 */ INT4 FilUSave (FILo *f, FILoL_S *svl) { svl->svfdd = f->crfdd; svl->svoff = f->l - &(f->ln)[0]; svl->svn = f->n; return 1; } /**api* FilUSave2 ************************************************************* ** ** should be removed again! ** saves info about current line + offset so that it can be restored ** again with FilUBack ** ** INPUT: address of FILo [W] ** ** RETURNS: 1 */ INT4 FilUSave2 (FILo *f) { f->svfdd = f->crfdd; f->svoff = f->l - &(f->ln)[0]; f->svn = f->n; return 1; } /**api* FilUBack ************************************************************** ** ** restores line saved by FilUSave - i.e. goes back in the file ** ** INPUT: address of FILo ** address of FILoL_S ** ** RETURNS: 1 ** e__lnotsaved if info is missing */ INT4 FilUBack (FILo *f, FILoL_S *svl) { INT4 rv; if (svl->svn == 0) return e__lnotsaved; if (svl->svn != f->n) { fseek(f->fil, svl->svfdd, 0); rv = FilURead(f); _ErrRet(rv); f->n = svl->svn; } f->l = f->ln + svl->svoff; return 1; } /**api* FilUBack2 ************************************************************* ** ** should be removed again! ** restores line saved by FilUSave - i.e. goes back in the file ** ** INPUT: address of FILo ** ** RETURNS: 1 ** e__lnotsaved if info is missing */ INT4 FilUBack2 (FILo *f) { INT4 rv; if (f->svn == 0) return e__lnotsaved; if (f->svn != f->n) { fseek(f->fil, f->svfdd, 0); rv = FilURead(f); _ErrRet(rv); f->n = f->svn; } f->l = f->ln + f->svoff; return 1; } /**api* FilEof **************************************************************** ** ** checks whether end of file has been reached and sets f->eof flag to ** FALSE; ** ** INPUT: address of FILo ** ** RETURNS: TRUE (EOF) ** FALSE */ INT4 FilEof(FILo *f) { if (f->eof) { f->eof = FALSE; return TRUE; } return FALSE; } #ifndef dos /**api* FilSearch ************************************************************* ** ** returns full specification for a file - if name has a wildcard ** then the first is found and context is returned for further calls; ** ** INPUT: address of input name [R] ** address of output name [W] or NULL ** address of search context [W] (0 if first call) or NULL ** IMPLICIT: ** ** RETURNS: 1 if name contains no wildcard ** 2 if yes ** 0 if no more file found */ INT4 FilSearch (char *wildfileName, char *efileName, UINT4 *c) #ifdef VMS { char fileName[FILxXNAM+1]; UINT4 c2=0; INT4 k, rv; if (efileName == NULL) efileName = fileName; if (c == NULL) c = &c2; rv = lib$find_file ( _Psi (wildfileName), _Pso (efileName), c); if (rv == RMS$_NMF) { lib$find_file_end ( c); return 0; } else if (rv%2 == 0) /** file not found */ return 0; for (k=0; efileName[k] != ' '; k++) ; efileName[k] = '\0'; if (strpbrk (wildfileName, "%*") == NULL) return 1; else return 2; } #else /* ** UNIX implementation */ { regexp *regExp; char dirName[DIR_LEN], fil_str[DIR_LEN], regexp_str[DIR_LEN]; char twildfileName[DIR_LEN], tmp_nm[DIR_LEN]; static char fileName[FILxXNAM+1]; static DIR *dirStream = NULL; struct dirent *dirEntry; INT4 i; if (efileName == NULL) efileName = fileName; strcpy (twildfileName, wildfileName); /* ** first get the directory part of "twildfileName"; ** if it is a relative path (does not start with '/') then add the ** absolute path of the current working directory */ for (i=strlen (_FilLN (twildfileName)) - 1; (i >= 0) && (twildfileName[i] != '/'); i--); if (twildfileName[0] != '/') { (void) getcwd (dirName, DIR_LEN); if (i > 0) { if ((i - 1) > 0) { (void) strcat (dirName, "/"); (void) strncat (dirName, twildfileName, i); } } } else { /** absolute path */ if (i > 0) { (void) strncpy (dirName, twildfileName, i); dirName[i] = '\0'; } else { (void) strcpy (dirName, "/"); } } /* ** now get file part (including wildcarts a la regexp) */ for (i=strlen (twildfileName) - 1; (i >= 0) && (twildfileName[i] != '/'); i--); if ((i > 0) || (strpbrk (twildfileName, "?*") != NULL)) { (void) strcpy (fil_str, &(twildfileName[i+1])); } else { (void) strcpy (fil_str, twildfileName); /** used to be "./" ??? */ } RegWildToRegexp (fil_str, regexp_str, 1); regExp = RegComp (regexp_str); if (regExp == NULL) _ErrRet2 (e__regerror, "regcomp failure"); /* ** open directory, read all file names and compare each name to the ** regular expression - if match then construct the complete file name ** and return; ** */ if (!c || *c == 0) { if ((dirStream = opendir (dirName)) == NULL) { return (0); } if (c) *c = 1; } while ((dirEntry = readdir (dirStream)) != NULL) { strcpy(tmp_nm, dirEntry->d_name); if (!RegExec (regExp, tmp_nm)) continue; /** get next entry */ strcpy (efileName, dirName); /** construct complete file name */ if (dirName[strlen (dirName) - 1] != '/') strcat (efileName, "/"); strcat (efileName, tmp_nm); if (!c) closedir (dirStream); return (strpbrk (twildfileName, "?*") == NULL) ? 1 : 2; } /* no more matching files can be found */ if (c) *c = 0; closedir (dirStream); free (regExp); return (0); } #endif #endif /**api* FilCutLn ************************************************************** ** ** makes a line look shorter as is - line can be restored to full ** length by FilRestoreLn - line can be cut at both ends; ** ** INPUT: address of file-dsc [W] ** begin of cut line [R] first col=1 ** length of cut line [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 if beg + length is greater than actual line ** e__novalnum + */ INT4 FilCutLn (FILo *file, INT4 beg, INT4 len) { INT4 ln_z; ln_z = strlen (file->ln); if (ln_z < beg) _ErrRet2 (e__novalnum, beg); file->l = &(file->ln[--beg]); if (strlen (file->ln) < beg + len) return 0; file->c_sp = &(file->ln[beg+len]); file->c_s = *file->c_sp; *(file->c_sp) = '\0'; file->n_s = file->n; return 1; } /**api* FilUSeek ************************************************************** ** ** goes to file address and reads first line; current line number (FILo.n) ** is set to 0 (-> of no use any more) ** ** INPUT: address of file descriptor [W] ** file address [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 FilUSeek (FILo *file, UINT4 fadd) { if (!file->isPipe) { fseek (file->fil, fadd, 0); file->n = 0; return FilURead (file); } } /**api* FilRestoreLn ********************************************************** ** ** restores cut line to full length line - does not if context (line nr.) ** different. ** ** INPUT: address of file->dsc [W] ** IMPLICIT: ** ** RETURNS: 1 if restored ** 0 if not */ INT4 FilRestoreLn (FILo *file) { if (file->n != file->n_s) return 0; *(file->c_sp) = file->c_s; file->c_s = 0; return 0; } /****** FilMsg **************************************************************** ** ** forms string for error message containg erroneous line + position wher; ** ** INPUT: address of FILo ** ** RETURNS: pointer to message string */ char *FilMsg (FILo *file) { static char msgLine[2*MSGxXLN+2]; char spacer[MSGxXLN+1]; INT4 len; len = strlen (file->ln) - strlen (file->l); SmFill(spacer, len MSGxXLN) file->ln[MSGxXLN]='\0'; sprintf (msgLine, "%s%s^\n", file->ln, spacer); SmEdit (msgLine, SMxDETAB); return &msgLine[0]; } /****** FilChMod ************************************************************** ** ** changes file mod to executable...function ignores second argument... ** expandable; ** ** INPUT: file name [R] ** mode specifier [R] ...ignored ** ** RETURNS: */ void FilChMod (char *fileName, char *mode) { #ifndef VMS chmod (_FilTempLN(fileName), 00744); /* no need to do that under VMS */ #endif } /**API* FilSetTranslate ******************************************************* ** ** Sets a new function for the translation of filenames of the ** form "someName:fileName" where "someName" is an environment ** variable or a logical name defining a directory location. File ** names in this format render SRS independent of the different naming ** conventions of the operating systems supported. ** ** ** INPUT: o address of the function to supersede the default ** function [W] ** ** RETURNS: */ void FilSetTranslate (char *(*translate)(char *, INT4)) { #ifndef vms if (translate) filTranslate = translate; #endif } /*****************************************************************************/ /*******the better futil starts from here! ***********************************/ /*****************************************************************************/ #define _Index(x,y) ( ((x)-'a'+1) << 5) +((y)-'a'+1) static void FileInitNames (FILEo *file); /**api* FileNew *************************************************************** ** ** Creates a new file object. Use FileOpen to open the file, FileClose ** to close it again and FileDelete to delete the object. **
    The file name is optional and can be also set with FileSetName. ** ** INPUT: the file name (or NULL) [R] ** ** RETURNS: the new file object ** */ FILEo *FileNew (char *fileName) { FILEo *file; if (!(file = (FILEo *) calloc (1, sizeof (FILEo)))) _ErrExit2 (e__allocfail, "file object"); file->isRead = 1; file->fullName = BuffNew (0); file->dirName = BuffNew (0); file->fileName = BuffNew (0); file->extName = BuffNew (0); file->name = BuffNew (0); file->ln = NULL; file->lnMaxLength = 2000; file->fd = -1; if (fileName) BuffCopyString (file->fullName, fileName); return file; } /**api* FileSetMaxLine ******************************************************** ** ** Sets the size of the longest line in the file for read operations. ** ** INPUT: the file object [W] ** the maximum line length [R] ** ** RETURNS: the file object ** */ FILEo *FileSetMaxLine (FILEo *file, INT4 length) { file->lnMaxLength = length; return file; } /**api* FileSetName *********************************************************** ** ** Sets the entire ("full") or specified part of the name for the file. ** See also FileGetName. ** ** INPUT: file object [W] ** option: "full", "dir", "file", "name", "ext" ** the name [R] ** */ void FileSetName (FILEo *file, char *opt, char *name) { switch (_Index (tolower(opt[0]), tolower (opt[1]))) { case _Index('f','u'): /* full */ BuffReset (file->fullName); BuffCopyString (file->fullName, name); break; case _Index('d','i'): /* dir */ BuffReset (file->dirName); BuffCopyString (file->dirName, name); if (BuffMatch (file->dirName, "[^/]$")) BuffCopyString (file->dirName, "/"); break; case _Index('f','i'): /* file */ BuffReset (file->fileName); BuffCopyString (file->fileName, name); break; case _Index('e','x'): /* ext */ BuffReset (file->extName); BuffCopyString (file->extName, name); break; case _Index('n','a'): /* name */ BuffReset (file->fileName); BuffReset (file->name); BuffCopyString (file->name, name); break; default: _ErrExit2 (e__unknownoption, opt); } file->isNameInit = 0; } /**api* FileSetMode *********************************************************** ** ** Sets the access mode for the file. The mode is specified as a ** string with 9 letters for owner, group and world access. ** The first in a triple must be 'r' (read) followed by 'w' (write) and ** 'x' (execute). Missing characteristics must be indicated by '-'. ** Eg, "rw-r--r--" or "rwxr-x--x" ** ** INPUT: the file object [W] ** the mode string [R] ** */ void FileSetMode (FILEo *file, char *mode) { strcpy (file->mode, mode); } /**api* FileOpen ************************************************************** ** ** Opens a file described by the file object created by FileNew. ** The file object can be further described or modified before opening ** with FileSetName, FileSetUpdate, FileSetWrite, FileSetMaxLine, ** FileSetGetFip, FileSetUnixIo, FileSetWrite. ** ** INPUT: the file object [W] ** ** RETURNS: the file object ** NULL: if not successful ** */ FILEo *FileOpen (FILEo *file) { char *fileName, *optStr; Int4 option; if (!file->isNameInit) FileInitNames (file); FileClose (file); /* in case object is reused */ if (!file->ln) if (!(file->ln = (char *) malloc (file->lnMaxLength+1))) _ErrExit2 (e__allocfail, "file line"); *file->ln = '\0'; fileName = FileGetName (file, "path"); if (file->isUnixIo) { if (file->isRead && file->isWrite) option = O_RDWR; else if (file->isWrite) option = O_WRONLY | O_CREAT | O_TRUNC; else option = O_RDONLY; if ((file->fd = open (fileName, option, 0666)) == -1) return NULL; } else { if (!*fileName) file->file = file->isWrite ? stdout : stdin; else { if (file->isRead && file->isWrite) optStr = "r+"; else if (file->isWrite) optStr = "w"; else optStr = "r"; if (!(file->file = fopen (fileName, optStr))) return NULL; } } return file; } /**api* FileReadLn ************************************************************ ** ** ** INPUT: the file object [W] ** ** RETURNS: the address of the line just read. ** */ char *FileReadLn (FILEo *file) { if (file->doGetFip) file->fip = ftell (file->file); if (fgets (file->ln, file->lnMaxLength, file->file) == NULL) { if (feof (file->file) != 0) file->isEof = 1; *file->ln = '\0'; return NULL; } file->lnN++; return file->ln; } /**api* FileWrite ************************************************************* ** ** Writes specified number of bytes to the stream. ** ** INPUT: the file object [W] ** the input buffer [R] ** the number of bytes to write [R] ** */ void FileWrite (FILEo *file, char *buff, Int4 nBytes) { Int4 nWriteBytes; if (file->isUnixIo) write (file->fd, buff, nBytes); else nWriteBytes = fwrite (buff, 1, nBytes, file->file); } /**api* FileRead ************************************************************** ** ** Reads specified number of bytes from the stream. ** ** INPUT: the file object [W] ** the output buffer [W] ** the number of bytes to read [R] ** ** RETURNS: 1 if the read operation was successful ** 0 if at the end of the file ** */ char *FileRead (FILEo *file, char *buff, Int4 nBytes) { Int4 nReadBytes; if (file->isUnixIo) nReadBytes = read (file->fd, buff, nBytes); else nReadBytes = fread (buff, 1, nBytes, file->file); if (!nReadBytes) file->isEof = 1; return file->isEof ? NULL : buff; } /**api* FileIsEof ************************************************************* ** ** ** INPUT: a ** ** RETURNS: 1 or 0 ** */ INT4 FileIsEof (FILEo *file) { return file->isEof; } /**api* FileDelete ************************************************************ ** ** Deletes a file object created with FileNew and closes it if ** the file object describes a still opened file. ** ** INPUT: the file object [W] ** ** RETURNS: NULL ** */ FILEo *FileDelete (FILEo *file) { if (file->ln) free (file->ln); BuffDelete (&file->fullName); BuffDelete (&file->dirName); BuffDelete (&file->fileName); FileClose (file); free (file); return NULL; } /**api* FileClose ************************************************************* ** ** Closes the file but checks first if there is a file to be closed ** at all. ** ** INPUT: file object [W] */ void FileClose (FILEo *file) { if (file->isUnixIo) { if (!(file->fd == -1)){ close (file->fd); file->fd = -1; } } else if (file->file) { fclose (file->file); file->file = NULL; } file->lnN = 0; file->fip = 0; file->fd = -1; file->isEof = FALSE; if (*file->mode) /* improve !!!te*/ chmod (FileGetName (file, "path"), 00755); } /**api* FileGetLn ************************************************************* ** ** Returns the most recently read line. ** ** INPUT: file object [R] ** ** RETURNS: the current line */ char *FileGetLn (FILEo *file) { if (file->ln) return file->ln; } /**api* FileGetName *********************************************************** ** ** Returns the full file name or optionally parses it and returns parts ** of it. ** ** INPUT: file object [R] ** option: "full", "dir", "file", "name", "ext", "path" ** ** RETURNS: the requested name */ char *FileGetName (FILEo *file, char *opt) { if (!file->isNameInit) FileInitNames (file); switch (_Index (tolower(opt[0]), tolower (opt[1]))) { case _Index('f','u'): /* full */ return BuffGetPtr (file->fullName); case _Index('p','a'): /* full */ return _FilTempLN (BuffGetPtr (file->fullName)); case _Index('d','i'): /* dir */ BuffMatch (file->fullName, "^(.+/)[^/]+$"); return BuffGetMatch (1); case _Index('f','i'): /* file */ BuffMatch (file->fullName, "^(.+/)?([^/]+)$"); return BuffGetMatch (2); case _Index('e','x'): /* ext */ BuffMatch (file->fullName, "^.+/[^\\.]+\\.([^/]+)$"); return BuffGetMatch (1); case _Index('n','a'): /* name */ BuffMatch (file->fullName, "^.+/([^\\.]+)\\.[^/]+$"); return BuffGetMatch (1); default: _ErrExit2 (e__unknownoption, opt); return NULL; } } /**api* FileGetTime ********************************************************** ** ** Returns various times (in seconds after 1.jan 1970) for a file ** which must have been opened with FileOpen. ** the "create" time corresponds to the "status change" time returned ** by fstat. ** ** INPUT: the file object [R] ** option: "create", "mod", "access". ** ** RETURNS: the time of specified type ** */ Int4 FileGetTime (FILEo *file, char *option) { struct stat buff; Int4 fileNo; fileNo = fileno (file->file); fstat (fileNo, &buff); switch (option[0]) { case 'c': /* create */ return buff.st_ctime; case 'm': /* mod */ return buff.st_mtime; case 'a': /* access - last access */ return buff.st_atime; default: _ErrExit3 (e__novalopt, option, "FileGetTime"); } } /**api* FileGetFile *********************************************************** ** ** Returns the 'real' file descriptor as returned by fopen. ** ** INPUT: the file object [R] ** ** RETURNS: the stdio ('FILE') file descriptor ** */ FILE *FileGetFile (FILEo *file) { return file->file; } /**api* FileGetFileN ********************************************************** ** ** Returns the number of a file during an iteration with FileNext. ** ** INPUT: the file object [R] ** ** RETURNS: the iteration number ** */ INT4 FileGetFileN (FILEo *file) { return file->fileN; } /**api* FileGetFileN ********************************************************** ** ** Returns the number of the last line read from the file. ** ** INPUT: file object [W] ** ** RETURNS: the line number ** */ INT4 FileGetLineN (FILEo *file) { return file->lnN; } /**api* FileGetFip ************************************************************ ** ** Returns the file pointer to the position in the file BEFORE the ** last line read. ** ** INPUT: file object ** ** RETURNS: the current file pointer ** */ FIP FileGetFip (FILEo *file) { return file->fip; } /**api* FileSetPipe *********************************************************** ** ** Sets a command to be opened as a pipe. The command must have up ** to three "%s" wherever the file name should be inserted. ** ** INPUT: file object [W] ** the pipe command [R] ** */ void FileSetPipe (FILEo *file, char *command) { file->pipeCom=NULL; } /**api* FileSetGetFip ********************************************************* ** ** Selects whether the file pointer should be memorized after each ** reading a line from the file. ** ** INPUT: file object [W] ** true or false [R] ** */ void FileSetGetFip (FILEo *file, INT4 flag) { if (file) file->doGetFip = flag; } /**api* FileSetWrite ********************************************************** ** ** Selects write access for the file. ** ** INPUT: file object [W] ** ** RETURNS: the file object */ FILEo *FileSetWrite (FILEo *file) { file->isRead = 0; file->isWrite = 1; return file; } /**api* FileSetUpdate ********************************************************* ** ** Selects "update" access for the file. ** ** INPUT: file object [W] ** ** RETURNS: the file object */ FILEo *FileSetUpdate (FILEo *file) { file->isRead = 1; file->isWrite = 1; return file; } /**api* FileSetUnixIo ********************************************************* ** ** Selects the file to be opened with UNIX/IO functions. ** ** INPUT: file object [W] ** ** RETURNS: the file object */ FILEo *FileSetUnixIo (FILEo *file) { file->isUnixIo = 1; return file; } /**api* FileNext ************************************************************** ** ** Opens the next file that matches a file name that may ** contain '*' and '?' as wildcards. ** ** INPUT: the file object [W} ** ** RETURNS: the number of the file found ** 0: no more files found */ INT4 FileNext (FILEo *file) { struct dirent *dirEntry; char reStr[512]; if (file->fileN && !file->isWildFile) return 0; if (!file->isNameInit) { FileInitNames (file); if (file->regExp) { free (file->regExp); file->regExp = NULL; } BuffReset (file->dirName); BuffCopyString (file->dirName, FileGetName (file, "dir")); BuffReset (file->fileName); BuffCopyString (file->fileName, FileGetName (file, "file")); if (RegWildToRegexp (BuffGetPtr (file->fileName), reStr, 1)) { file->isWildFile = 1; } } if (!file->regExp && file->isWildFile) { file->fileN = 0; RegWildToRegexp (BuffGetPtr (file->fileName), reStr, 1); if (!(file->regExp = RegComp (reStr))) { _ErrMsg2 (e__regerror, "regcomp failure"); return 0; } if (!(file->dirStream = opendir (BuffGetPtr (file->dirName)))) { _ErrMsg2 (e__filopenerr, BuffGetPtr (file->dirName)); return 0; } } if (file->isWildFile) { while ((dirEntry = readdir ((DIR *) file->dirStream))) { if (!RegExec (file->regExp, dirEntry->d_name)) continue; BuffReset (file->fullName); BuffPrintF (file->fullName, "%s%s", BuffGetPtr (file->dirName), dirEntry->d_name); FileOpen (file); return ++file->fileN; } closedir (file->dirStream); } else { file->fileN = 1; FileOpen (file); return 1; } return 0; } /****** FileInitNames ********************************************************* ** ** ** INPUT: a ** ** RETURNS: 1 ** */ static void FileInitNames (FILEo *file) { if (BuffLength (file->dirName)) { BuffReset (file->fullName); BuffCat (file->fullName, file->dirName); } if (BuffLength (file->fileName)) BuffCat (file->fullName, file->fileName); else { if (BuffLength (file->name)) BuffCat (file->fullName, file->name); if (BuffLength (file->extName)) { BuffCopyString (file->fullName, "."); BuffCat (file->fullName, file->extName); } } file->isNameInit = 1; } /**api* FileSeek ************************************************************** ** ** ** INPUT: file object [W] ** file address relative from file start [R] ** ** RETURNS: 1 ** */ void FileSeek (FILEo *file, FIP fip) { if (file->isUnixIo) lseek (file->fd, fip, 0); else fseek (file->file, fip, 0); file->fip = fip; file->ln[0] = '\0'; file->isEof = 0; } /**api* FileSeekEnd *********************************************************** ** ** ** INPUT: file object [W] ** file address relative from file start [R] ** ** RETURNS: 1 ** */ void FileSeekEnd (FILEo *file, FIP fip) { if (file->isUnixIo) lseek (file->fd, fip, 2); else fseek (file->file, fip, 2); file->fip = fip; file->ln[0] = '\0'; } ** ** $RCSfile: futil.h,v $ ** $Revision: 1.6 $ ** $Date: 1996/08/12 20:24:27 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** different parts of the file name; ** DEST = NODE+DEV+ROOT+DIR, SPEC = NAME+TYPE+VERS */ enum fil_nametag {FILxNODE=0, FILxDEV, FILxROOT, FILxDIR, FILxNAME, FILxTYPE, FILxVERS, FILxDEST, FILxSPEC}; #define FILxXNAM 132 /* max size of a file name */ #define FILxVAR 1 /* variable record format */ #define FILxSTREAM 2 /* c-stream file */ #define FILxWRITE 1 #define FILxREAD 2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macro that calls FilLogicName on UNIX but not on VMS */ #ifndef VMS extern char * (*filTranslate)(char *, INT4); # define _FilLN(x) (char *) (*filTranslate) (x, 0) # define _FilTempLN(x) (char *) (*filTranslate) (x, 1) #else # define _FilLN(x) x # define _FilTempLN(x) x #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** descriptor of a file opened with FilUOpen */ typedef struct FILo { FILE *fil; /* C-lib file descriptor */ char nam[FILxXNAM+1]; /* file name */ char *ln; /* current line = line buffer */ char *l; /* read pointer within current line */ INT4 n; /* no of lines */ INT4 len; /* length of line buffer */ UINT4 crfdd; /* current file address */ char eof; /* flag if eof has been reached */ char c_s; /* saved character at CUT position */ char *c_sp; /* pointer to CUT position */ INT4 n_s; /* line no of CUT line */ UINT4 svfdd; /* saved file offset of line */ INT4 svoff; /* saved offset within saved line */ INT4 svn; /* saved line no */ INT4 isPipe; /* flag if file was opened as pipe */ } FILo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** structure to save a read position within a file opened by FilUSave */ typedef struct { UINT4 svfdd; /* saved file offset of line */ INT4 svoff; /* saved offset within saved line */ INT4 svn; /* saved line no */ } FILoL_S; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ FILE *FilOpenW (char *, int *errCode); FILE *FilOpenU (char *, int *errCode); FILE *FilOpenR (char *, int *errCode); FILE *FilOpenRF (char *, int *errCode); FILE *FilOpenWV (char *, int *errCode); INT4 FilUOpen (FILo *f, char *fil_nm, INT4 len, INT4 ft); INT4 FilUOpen2 (FILo **f, char *fil_nm, INT4 len, INT4 ft); INT4 FilURead (FILo *f); INT4 FilUSeek (FILo *file, UINT4 fip); INT4 FilUClose (FILo *f); INT4 FilUClose2 (FILo *f); INT4 FilEof(FILo *f); void FilChMod (char *fileName, char *mode); INT4 FilSearch (char *wildfil_nm, char *efil_nm, UINT4 *cntxt); INT4 FilParse (char *innam, char *outnam, INT4 typ); INT4 FilUSave (FILo *f, FILoL_S *svl); INT4 FilUSave2 (FILo *f); INT4 FilUBack (FILo *f, FILoL_S *svl); INT4 FilUBack2 (FILo *f); char *FilMsg (FILo *file); INT4 FilCutLn (FILo *file, INT4 beg, INT4 len); INT4 FilRestoreLn (FILo *file); void FilSetTranslate (char *(*translate)(char *, INT4)); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** descriptor of a file opened with FilNew/FilOpen */ typedef struct FILEo { FILE *file; /* C-lib file descriptor */ Int4 fd; struct SMoBUFF *fullName; struct SMoBUFF *dirName; struct SMoBUFF *fileName; struct SMoBUFF *extName; struct SMoBUFF *name; struct SMoBUFF *pipeCom; struct regexp *regExp; void *dirStream; char *ln; /* line buffer */ INT4 lnMaxLength; /* max length of line read from file */ INT4 lnN; /* no of lines currently read */ INT4 fileN; /* number of file in 'search' context */ FIP fip; /* file address of current line */ char isEof; /* flag if eof has been reached */ char isPipe; /* flag if file was opened as pipe */ char isWildFile; char isNameInit; char isWrite; char isRead; char isUnixIo; char doGetFip; char mode[20]; } FILEo; /* create, set and delete files */ FILEo* FileNew (char *fileName); FILEo* FileOpen (FILEo *file); void FileClose (FILEo *file); FILEo* FileDelete (FILEo *file); INT4 FileNext (FILEo *file); /* set characteristics */ FILEo* FileSetWrite (FILEo *file); FILEo* FileSetUpdate (FILEo *file); FILEo* FileSetMaxLine (FILEo *file, INT4 length); void FileSetPipe (FILEo *file, char *pipeCommand); void FileSetName (FILEo *file, char *opt, char *name); FILEo* FileSetUnixIo (FILEo *file); /* read and write and set position */ char* FileReadLn (FILEo *file); char* FileRead (FILEo *file, char *buff, Int4 nBytes); void FileWrite (FILEo *file, char *buff, Int4 nBytes); void FileSeek (FILEo *file, FIP fip); /* get info */ INT4 FileIsEof (FILEo *file); INT4 FileGetFileN (FILEo *file); char* FileGetName (FILEo *file, char *opt); void FileSetGetFip (FILEo *file, INT4 flag); FIP FileGetFip (FILEo *file); INT4 FileGetLineN (FILEo *file); Int4 FileGetTime (FILEo *file, char *option); FILE* FileGetFile (FILEo *file); char* FileGetLn (FILEo *file); #ifdef ready void FileSetTranslate (); void FileChangeMod (); #endif char gd_ID[] = "$Id: gd.c,v 1.1 1996/05/06 15:16:31 srs Exp $"; /* ** ** $RCSfile: gd.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:31 $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Written by Tom Boutell, 5/94. ** Copyright 1994, Cold Spring Harbor Labs. ** Permission granted to use this code in any fashion provided ** that this notice is retained and any alterations are ** labeled as such. It is requested, but not required, that ** you share extensions to this module with us so that we ** can incorporate them into new versions. ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** The original file "gd.c" was modified ...it now contains also gdfontl.c ** gdfonts.c and mtables.c by thure etzold, March 10, 1995 */ #include #include #include #include #include #include "gd.h" /* begin of gdfontl.c */ char gdFontLargeData[] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,1,0,0,0,0, 0,1,1,0,1,1,0,0, 0,1,1,0,1,1,0,0, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 0,1,0,0,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,1,0, 0,0,0,1,0,0,1,0, 0,0,0,1,0,0,1,0, 0,1,1,1,1,1,1,1, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 1,1,1,1,1,1,1,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,1,0,1,0,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,1,1,0, 1,0,0,1,0,0,0,0, 0,1,0,1,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,1,0,1,0,0, 0,0,0,1,0,0,1,0, 1,1,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,1,0,0, 0,1,1,1,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,1,0, 0,1,1,0,0,0,1,0, 1,0,0,1,0,1,0,0, 1,0,0,1,0,1,0,0, 1,0,0,1,0,1,0,0, 1,0,0,1,1,0,0,0, 0,1,1,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,1,1,0,0, 0,0,1,1,0,0,1,0, 0,1,0,1,0,0,1,0, 0,1,0,1,0,0,1,0, 0,1,0,1,0,0,1,0, 1,0,0,0,1,1,0,0, 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,0,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,1,1,1,0, 0,1,0,1,0,1,0,0, 0,1,0,1,0,1,0,0, 1,0,0,1,0,1,0,0, 1,0,0,0,1,0,0,0, 1,0,0,0,1,1,0,0, 0,1,1,1,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,0,0,0,0, 1,1,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 1,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,0,1,0, 1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,1,1,0,0,0, 1,0,0,1,0,0,1,0, 1,1,0,1,0,1,1,0, 0,0,1,1,1,0,0,0, 1,1,0,1,0,1,1,0, 1,0,0,1,0,0,1,0, 0,0,1,1,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,0,0,0,0, 1,1,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 1,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,1,1,0,0,0,0,0, 1,1,1,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,1,0,0,0, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,0,1,0,0,1,0,0, 0,0,1,0,0,1,0,0, 0,0,0,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,1,1,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,1,0,0,0, 0,0,1,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,1,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 1,0,0,0,1,0,0,0, 1,0,0,0,1,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,1,1,1,0,0,0, 1,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 1,1,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,1,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,1,1,1,0,0,0, 1,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,1,0, 0,0,1,1,1,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,1,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,1,0,0,0,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,1,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0, 0,1,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,1,1,0,1,0, 1,0,1,0,0,1,1,0, 1,0,1,0,0,0,1,0, 1,0,1,0,0,0,1,0, 1,0,1,0,0,0,1,0, 1,0,1,0,0,1,1,0, 1,0,0,1,1,0,1,0, 1,0,0,0,0,0,0,0, 0,1,0,0,0,0,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,1,1,1,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,0, 0,1,0,0,0,1,1,0, 0,1,0,0,0,0,1,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 1,1,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,1,0,1,0, 0,0,1,0,0,1,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,1,1,1,1, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,1,0,0,1,1,0, 0,0,0,1,1,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,0,1,1,1, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,1,1,1,1,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,0,0,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,1,1,1,1, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,0,1,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,1,1,0,0,0,0, 0,1,0,1,0,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 1,1,1,0,0,0,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,1,1,0, 1,0,1,0,1,0,1,0, 1,0,1,0,1,0,1,0, 1,0,1,0,1,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,0,0,0,1,1,1, 1,1,0,0,0,0,1,0, 1,0,1,0,0,0,1,0, 1,0,1,0,0,0,1,0, 1,0,1,0,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,0,1,0,1,0, 1,0,0,0,1,0,1,0, 1,0,0,0,1,0,1,0, 1,0,0,0,0,1,1,0, 1,1,0,0,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,1,1,1,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,0,1,1,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 1,1,1,0,0,0,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,0,1,0,0, 0,1,0,0,1,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,1,1,0,0,0,0,0, 0,0,0,1,1,0,0,0, 0,0,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,1,0,0, 1,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,0,1,1,1, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,1,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,1,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,1,0,1,0,1,0, 1,0,1,0,1,0,1,0, 1,0,1,0,1,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,1,1,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,1,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 1,0,0,0,0,1,0,0, 1,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,1,1,1,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,1,1,1,0, 0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,0,0, 1,1,1,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 1,1,1,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,1,1,0,0,0,0, 0,0,1,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,1,0,0, 0,1,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,1,1,1,1,1,0, 0,1,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,1,1,0, 0,1,1,1,1,0,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,0, 0,1,0,0,0,1,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,1,1,1,1,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,1,1,1,1,1,1,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,1,1,1,0, 0,0,0,1,0,0,0,1, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 1,1,1,1,1,1,1,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,1, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,0,0,0, 0,1,1,1,1,0,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,1,1,1,0,0, 0,1,1,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,0,0,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,1,1,0,0,0, 0,0,0,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,1,1,1,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,0, 0,0,0,0,0,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,1,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 0,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,1,0,0,0, 0,1,0,1,1,0,0,0, 0,1,1,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,0,0,0,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,1,1,1,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,1,0,1,1,0,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,1,1,1,0,0, 0,1,1,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,0,0,1,1,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,1,1,0,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,1,1,1,0,0,0, 0,1,0,0,0,0,0,0, 0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,1,1,0, 0,1,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 1,0,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,0,0,1,0,0, 0,0,0,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,1,1,0,0, 0,0,1,1,0,0,1,0, 0,0,1,0,0,0,1,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 1,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,0, 0,1,0,0,0,1,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,0,0, 0,0,1,1,1,1,0,0, 0,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 1,1,0,0,0,0,1,0, 1,0,1,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 1,1,1,1,1,1,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,1,0, 0,0,1,0,0,0,1,0, 0,0,0,1,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,1,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,0,1,0, 0,1,0,0,0,1,1,0, 0,0,1,1,1,0,0,1, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,0,0,0,1,1,0, 1,0,0,0,0,0,1,0, 1,0,0,0,0,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,0,1,0,0,1,0, 1,0,1,0,1,0,1,0, 1,0,1,0,1,0,1,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,1,0,0,0,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,1,1,1,0, 0,1,0,0,0,1,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,1,0,0,0, 0,0,1,0,1,0,0,0, 0,1,0,0,0,1,0,0, 1,1,1,0,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 1,1,1,0,0,1,1,1, 0,1,0,0,0,0,1,0, 0,0,1,0,0,0,1,0, 0,0,1,0,0,1,0,0, 0,0,0,1,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 1,0,0,1,0,0,0,0, 1,0,1,0,0,0,0,0, 0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,1,1,1,1,1,1,0, 0,1,0,0,0,1,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,1,0, 0,1,0,0,0,0,1,0, 1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,0,0,1,1,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,0, 1,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 0,0,1,0,0,0,0,0, 1,1,0,0,0,0,0,0, 0,1,1,0,0,0,0,0, 1,0,0,1,0,0,1,0, 0,0,0,0,1,1,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; gdFont gdFontLargeRep = { 96, 32, 8, 16, gdFontLargeData }; gdFontPtr gdFontLarge = &gdFontLargeRep; /* end of gdfontl.c */ /* begin of gdfonts.c */ char gdFontSmallData[] = { 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,0,1,0,0, 0,1,0,1,0,0, 0,1,0,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,0,1,0,0, 1,1,1,1,1,0, 0,1,0,1,0,0, 0,1,0,1,0,0, 1,1,1,1,1,0, 0,1,0,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,1,1,1,0,0, 1,0,1,0,1,0, 1,0,1,0,0,0, 0,1,1,1,0,0, 0,0,1,0,1,0, 1,0,1,0,1,0, 0,1,1,1,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 1,1,0,0,1,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 1,0,0,1,1,0, 1,0,0,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,0,0,0,0, 1,0,1,0,0,0, 1,0,1,0,0,0, 0,1,0,0,0,0, 1,0,1,0,1,0, 1,0,0,1,0,0, 0,1,1,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 1,1,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 1,0,1,0,1,0, 0,1,1,1,0,0, 0,0,1,0,0,0, 0,1,1,1,0,0, 1,0,1,0,1,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 1,1,1,1,1,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 1,1,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,1,1,0, 1,0,1,0,1,0, 1,1,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,1,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 0,0,0,0,1,0, 0,0,1,1,0,0, 0,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,1,0,0, 0,0,1,1,0,0, 0,1,0,1,0,0, 1,0,0,1,0,0, 1,1,1,1,1,0, 0,0,0,1,0,0, 0,0,0,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,1,0,0, 0,1,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,1,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 0,1,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 0,0,0,0,0,0, 0,1,1,0,0,0, 0,1,1,0,0,0, 1,1,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,1,1,1,0, 1,0,1,0,1,0, 1,0,1,1,1,0, 1,0,0,0,0,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,0,0, 0,1,0,0,1,0, 0,1,0,0,1,0, 0,1,0,0,1,0, 0,1,0,0,1,0, 0,1,0,0,1,0, 1,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,1,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,1,0,0, 1,0,1,0,0,0, 1,1,0,0,0,0, 1,0,1,0,0,0, 1,0,0,1,0,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,1,0,1,1,0, 1,0,1,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,0,0,1,0, 1,0,1,0,1,0, 1,0,0,1,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,1,0,1,0, 1,0,0,1,0,0, 0,1,1,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 1,0,1,0,0,0, 1,0,0,1,0,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0, 0,1,1,1,0,0, 0,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,0,1,0,0, 0,1,0,1,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,1,0,1,0, 1,1,0,1,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,0,1,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,0,1,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 1,1,1,1,1,0, 0,1,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,1,1,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 1,1,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,1,0,0, 0,0,1,1,0,0, 0,0,0,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 0,0,0,0,1,0, 0,1,1,1,1,0, 1,0,0,0,1,0, 0,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 0,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,1,1,1,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 1,0,0,0,0,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,1,0,0, 0,1,0,0,1,0, 0,1,0,0,0,0, 1,1,1,0,0,0, 0,1,0,0,0,0, 0,1,0,0,0,0, 0,1,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,1,0, 0,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,1,0,0, 1,1,1,0,0,0, 1,0,0,1,0,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,0,1,0,0, 1,0,1,0,1,0, 1,0,1,0,1,0, 1,0,1,0,1,0, 1,0,1,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,1,1,0,0, 1,1,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,1,0, 0,0,0,0,1,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,1,1,0,0, 1,1,0,0,1,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,1,1,0, 1,0,0,0,0,0, 0,1,1,1,0,0, 0,0,0,0,1,0, 1,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 1,1,1,1,1,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,0,1,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,1,0,1,0, 1,0,1,0,1,0, 0,1,0,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 0,1,0,1,0,0, 0,0,1,0,0,0, 0,1,0,1,0,0, 1,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 0,1,0,1,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,1,1,1,1,0, 0,0,0,1,0,0, 0,1,1,1,0,0, 0,1,0,0,0,0, 1,1,1,1,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,1,0,0, 0,0,0,1,0,0, 0,0,0,1,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,0,1,0,0, 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,1,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 0,1,0,0,0,0, 0,1,0,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,1,0,0,0,0, 0,1,0,0,0,0, 0,1,0,0,0,0, 1,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,1,1,0,1,0, 1,0,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 1,0,0,0,0,0, 1,0,0,0,0,0, 1,1,1,1,0,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,0,0,0,1,0, 1,1,1,1,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,0,0,0 }; gdFont gdFontSmallRep = { 96, 32, 6, 12, gdFontSmallData }; gdFontPtr gdFontSmall = &gdFontSmallRep; /* end of gdfonts.c */ /* begin of mtables.c */ #define costScale 1024 int cost[] = { 1024, 1023, 1023, 1022, 1021, 1020, 1018, 1016, 1014, 1011, 1008, 1005, 1001, 997, 993, 989, 984, 979, 973, 968, 962, 955, 949, 942, 935, 928, 920, 912, 904, 895, 886, 877, 868, 858, 848, 838, 828, 817, 806, 795, 784, 772, 760, 748, 736, 724, 711, 698, 685, 671, 658, 644, 630, 616, 601, 587, 572, 557, 542, 527, 512, 496, 480, 464, 448, 432, 416, 400, 383, 366, 350, 333, 316, 299, 282, 265, 247, 230, 212, 195, 177, 160, 142, 124, 107, 89, 71, 53, 35, 17, 0, -17, -35, -53, -71, -89, -107, -124, -142, -160, -177, -195, -212, -230, -247, -265, -282, -299, -316, -333, -350, -366, -383, -400, -416, -432, -448, -464, -480, -496, -512, -527, -542, -557, -572, -587, -601, -616, -630, -644, -658, -671, -685, -698, -711, -724, -736, -748, -760, -772, -784, -795, -806, -817, -828, -838, -848, -858, -868, -877, -886, -895, -904, -912, -920, -928, -935, -942, -949, -955, -962, -968, -973, -979, -984, -989, -993, -997, -1001, -1005, -1008, -1011, -1014, -1016, -1018, -1020, -1021, -1022, -1023, -1023, -1024, -1023, -1023, -1022, -1021, -1020, -1018, -1016, -1014, -1011, -1008, -1005, -1001, -997, -993, -989, -984, -979, -973, -968, -962, -955, -949, -942, -935, -928, -920, -912, -904, -895, -886, -877, -868, -858, -848, -838, -828, -817, -806, -795, -784, -772, -760, -748, -736, -724, -711, -698, -685, -671, -658, -644, -630, -616, -601, -587, -572, -557, -542, -527, -512, -496, -480, -464, -448, -432, -416, -400, -383, -366, -350, -333, -316, -299, -282, -265, -247, -230, -212, -195, -177, -160, -142, -124, -107, -89, -71, -53, -35, -17, 0, 17, 35, 53, 71, 89, 107, 124, 142, 160, 177, 195, 212, 230, 247, 265, 282, 299, 316, 333, 350, 366, 383, 400, 416, 432, 448, 464, 480, 496, 512, 527, 542, 557, 572, 587, 601, 616, 630, 644, 658, 671, 685, 698, 711, 724, 736, 748, 760, 772, 784, 795, 806, 817, 828, 838, 848, 858, 868, 877, 886, 895, 904, 912, 920, 928, 935, 942, 949, 955, 962, 968, 973, 979, 984, 989, 993, 997, 1001, 1005, 1008, 1011, 1014, 1016, 1018, 1020, 1021, 1022, 1023, 1023 }; #define sintScale 1024 int sint[] = { 0, 17, 35, 53, 71, 89, 107, 124, 142, 160, 177, 195, 212, 230, 247, 265, 282, 299, 316, 333, 350, 366, 383, 400, 416, 432, 448, 464, 480, 496, 512, 527, 542, 557, 572, 587, 601, 616, 630, 644, 658, 671, 685, 698, 711, 724, 736, 748, 760, 772, 784, 795, 806, 817, 828, 838, 848, 858, 868, 877, 886, 895, 904, 912, 920, 928, 935, 942, 949, 955, 962, 968, 973, 979, 984, 989, 993, 997, 1001, 1005, 1008, 1011, 1014, 1016, 1018, 1020, 1021, 1022, 1023, 1023, 1024, 1023, 1023, 1022, 1021, 1020, 1018, 1016, 1014, 1011, 1008, 1005, 1001, 997, 993, 989, 984, 979, 973, 968, 962, 955, 949, 942, 935, 928, 920, 912, 904, 895, 886, 877, 868, 858, 848, 838, 828, 817, 806, 795, 784, 772, 760, 748, 736, 724, 711, 698, 685, 671, 658, 644, 630, 616, 601, 587, 572, 557, 542, 527, 512, 496, 480, 464, 448, 432, 416, 400, 383, 366, 350, 333, 316, 299, 282, 265, 247, 230, 212, 195, 177, 160, 142, 124, 107, 89, 71, 53, 35, 17, 0, -17, -35, -53, -71, -89, -107, -124, -142, -160, -177, -195, -212, -230, -247, -265, -282, -299, -316, -333, -350, -366, -383, -400, -416, -432, -448, -464, -480, -496, -512, -527, -542, -557, -572, -587, -601, -616, -630, -644, -658, -671, -685, -698, -711, -724, -736, -748, -760, -772, -784, -795, -806, -817, -828, -838, -848, -858, -868, -877, -886, -895, -904, -912, -920, -928, -935, -942, -949, -955, -962, -968, -973, -979, -984, -989, -993, -997, -1001, -1005, -1008, -1011, -1014, -1016, -1018, -1020, -1021, -1022, -1023, -1023, -1024, -1023, -1023, -1022, -1021, -1020, -1018, -1016, -1014, -1011, -1008, -1005, -1001, -997, -993, -989, -984, -979, -973, -968, -962, -955, -949, -942, -935, -928, -920, -912, -904, -895, -886, -877, -868, -858, -848, -838, -828, -817, -806, -795, -784, -772, -760, -748, -736, -724, -711, -698, -685, -671, -658, -644, -630, -616, -601, -587, -572, -557, -542, -527, -512, -496, -480, -464, -448, -432, -416, -400, -383, -366, -350, -333, -316, -299, -282, -265, -247, -230, -212, -195, -177, -160, -142, -124, -107, -89, -71, -53, -35, -17 }; /* end of mtables.c */ static void gdImageBrushApply(/* gdImagePtr im, int x, int y */); static void gdImageTileApply(/* gdImagePtr im, int x, int y */); gdImagePtr gdImageCreate(sx, sy) int sx; int sy; { int i; gdImagePtr im; im = (gdImage *) malloc(sizeof(gdImage)); im->pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx); im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; im->tile = 0; im->style = 0; for (i=0; (ipixels[i] = (unsigned char *) calloc( sy, sizeof(unsigned char)); } im->sx = sx; im->sy = sy; im->colorsTotal = 0; im->transparent = (-1); im->interlace = 0; return im; } void gdImageDestroy(im) gdImagePtr im; { int i; for (i=0; (isx); i++) { free(im->pixels[i]); } free(im->pixels); if (im->polyInts) { free(im->polyInts); } if (im->style) { free(im->style); } free(im); } int gdImageColorClosest(im, r, g, b) gdImagePtr im; int r; int g; int b; { int i; long rd, gd, bd; int ct = (-1); long mindist; for (i=0; (i<(im->colorsTotal)); i++) { long dist; if (im->open[i]) { continue; } rd = (im->red[i] - r); gd = (im->green[i] - g); bd = (im->blue[i] - b); dist = rd * rd + gd * gd + bd * bd; if ((i == 0) || (dist < mindist)) { mindist = dist; ct = i; } } return ct; } int gdImageColorExact(im, r, g, b) gdImagePtr im; int r; int g; int b; { int i; for (i=0; (i<(im->colorsTotal)); i++) { if (im->open[i]) { continue; } if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b)) { return i; } } return -1; } int gdImageColorAllocate(im, r, g, b) gdImagePtr im; int r; int g; int b; { int i; int ct = (-1); for (i=0; (i<(im->colorsTotal)); i++) { if (im->open[i]) { ct = i; break; } } if (ct == (-1)) { ct = im->colorsTotal; if (ct == gdMaxColors) { return -1; } im->colorsTotal++; } im->red[ct] = r; im->green[ct] = g; im->blue[ct] = b; im->open[ct] = 0; return ct; } void gdImageColorDeallocate(im, color) gdImagePtr im; int color; { /* Mark it open. */ im->open[color] = 1; } void gdImageColorTransparent(im, color) gdImagePtr im; int color; { im->transparent = color; } void gdImageSetPixel(im, x, y, color) gdImagePtr im; int x; int y; int color; { int p; switch(color) { case gdStyled: if (!im->style) { /* Refuse to draw if no style is set. */ return; } else { p = im->style[im->stylePos++]; } if (p != (gdTransparent)) { gdImageSetPixel(im, x, y, p); } im->stylePos = im->stylePos % im->styleLength; break; case gdStyledBrushed: if (!im->style) { /* Refuse to draw if no style is set. */ return; } p = im->style[im->stylePos++]; if ((p != gdTransparent) && (p != 0)) { gdImageSetPixel(im, x, y, gdBrushed); } im->stylePos = im->stylePos % im->styleLength; break; case gdBrushed: gdImageBrushApply(im, x, y); break; case gdTiled: gdImageTileApply(im, x, y); break; default: if (gdImageBoundsSafe(im, x, y)) { im->pixels[x][y] = color; } break; } } static void gdImageBrushApply(im, x, y) gdImagePtr im; int x; int y; { int lx, ly; int hy; int hx; int x1, y1, x2, y2; int srcx, srcy; if (!im->brush) { return; } hy = gdImageSY(im->brush)/2; y1 = y - hy; y2 = y1 + gdImageSY(im->brush); hx = gdImageSX(im->brush)/2; x1 = x - hx; x2 = x1 + gdImageSX(im->brush); srcy = 0; for (ly = y1; (ly < y2); ly++) { srcx = 0; for (lx = x1; (lx < x2); lx++) { int p; p = gdImageGetPixel(im->brush, srcx, srcy); /* Allow for non-square brushes! */ if (p != gdImageGetTransparent(im->brush)) { gdImageSetPixel(im, lx, ly, im->brushColorMap[p]); } srcx++; } srcy++; } } static void gdImageTileApply(im, x, y) gdImagePtr im; int x; int y; { int srcx, srcy; int p; if (!im->tile) { return; } srcx = x % gdImageSX(im->tile); srcy = y % gdImageSY(im->tile); p = gdImageGetPixel(im->tile, srcx, srcy); /* Allow for transparency */ if (p != gdImageGetTransparent(im->tile)) { gdImageSetPixel(im, x, y, im->tileColorMap[p]); } } int gdImageGetPixel(im, x, y) gdImagePtr im; int x; int y; { if (gdImageBoundsSafe(im, x, y)) { return im->pixels[x][y]; } else { return 0; } } /* Bresenham as presented in Foley & Van Dam */ void gdImageLine(im, x1, y1, x2, y2, color) gdImagePtr im; int x1; int y1; int x2; int y2; int color; { int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; dx = abs(x2-x1); dy = abs(y2-y1); if (dy <= dx) { d = 2*dy - dx; incr1 = 2*dy; incr2 = 2 * (dy - dx); if (x1 > x2) { x = x2; y = y2; ydirflag = (-1); xend = x1; } else { x = x1; y = y1; ydirflag = 1; xend = x2; } gdImageSetPixel(im, x, y, color); if (((y2 - y1) * ydirflag) > 0) { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y++; d+=incr2; } gdImageSetPixel(im, x, y, color); } } else { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y--; d+=incr2; } gdImageSetPixel(im, x, y, color); } } } else { d = 2*dx - dy; incr1 = 2*dx; incr2 = 2 * (dx - dy); if (y1 > y2) { y = y2; x = x2; yend = y1; xdirflag = (-1); } else { y = y1; x = x1; yend = y2; xdirflag = 1; } gdImageSetPixel(im, x, y, color); if (((x2 - x1) * xdirflag) > 0) { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x++; d+=incr2; } gdImageSetPixel(im, x, y, color); } } else { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x--; d+=incr2; } gdImageSetPixel(im, x, y, color); } } } } /* As above, plus dashing */ #define dashedSet \ { \ dashStep++; \ if (dashStep == gdDashSize) { \ dashStep = 0; \ on = !on; \ } \ if (on) { \ gdImageSetPixel(im, x, y, color); \ } \ } void gdImageDashedLine(im, x1, y1, x2, y2, color) gdImagePtr im; int x1; int y1; int x2; int y2; int color; { int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; int dashStep = 0; int on = 1; dx = abs(x2-x1); dy = abs(y2-y1); if (dy <= dx) { d = 2*dy - dx; incr1 = 2*dy; incr2 = 2 * (dy - dx); if (x1 > x2) { x = x2; y = y2; ydirflag = (-1); xend = x1; } else { x = x1; y = y1; ydirflag = 1; xend = x2; } dashedSet; if (((y2 - y1) * ydirflag) > 0) { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y++; d+=incr2; } dashedSet; } } else { while (x < xend) { x++; if (d <0) { d+=incr1; } else { y--; d+=incr2; } dashedSet; } } } else { d = 2*dx - dy; incr1 = 2*dx; incr2 = 2 * (dx - dy); if (y1 > y2) { y = y2; x = x2; yend = y1; xdirflag = (-1); } else { y = y1; x = x1; yend = y2; xdirflag = 1; } dashedSet; if (((x2 - x1) * xdirflag) > 0) { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x++; d+=incr2; } dashedSet; } } else { while (y < yend) { y++; if (d <0) { d+=incr1; } else { x--; d+=incr2; } dashedSet; } } } } int gdImageBoundsSafe(im, x, y) gdImagePtr im; int x; int y; { return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx)))); } void gdImageChar(im, f, x, y, c, color) gdImagePtr im; gdFontPtr f; int x; int y; int c; int color; { int cx, cy; int px, py; int fline; cx = 0; cy = 0; if ((c < f->offset) || (c >= (f->offset + f->nchars))) { return; } fline = (c - f->offset) * f->h * f->w; for (py = y; (py < (y + f->h)); py++) { for (px = x; (px < (x + f->w)); px++) { if (f->data[fline + cy * f->w + cx]) { gdImageSetPixel(im, px, py, color); } cx++; } cx = 0; cy++; } } void gdImageCharUp(im, f, x, y, c, color) gdImagePtr im; gdFontPtr f; int x; int y; char c; int color; { int cx, cy; int px, py; int fline; cx = 0; cy = 0; if ((c < f->offset) || (c >= (f->offset + f->nchars))) { return; } fline = (c - f->offset) * f->h * f->w; for (py = y; (py > (y - f->w)); py--) { for (px = x; (px < (x + f->h)); px++) { if (f->data[fline + cy * f->w + cx]) { gdImageSetPixel(im, px, py, color); } cy++; } cy = 0; cx++; } } void gdImageString(im, f, x, y, s, color) gdImagePtr im; gdFontPtr f; int x; int y; char *s; int color; { int i; int l; l = strlen(s); for (i=0; (iw; } } void gdImageStringUp(im, f, x, y, s, color) gdImagePtr im; gdFontPtr f; int x; int y; char *s; int color; { int i; int l; l = strlen(s); for (i=0; (iw; } } /* s and e are integers modulo 360 (degrees), with 0 degrees being the rightmost extreme and degrees changing clockwise. cx and cy are the center in pixels; w and h are the horizontal and vertical diameter in pixels. Nice interface, but slow, since I don't yet use Bresenham (I'm using an inefficient but simple solution with too much work going on in it; generalizing Bresenham to ellipses and partial arcs of ellipses is non-trivial, at least for me) and there are other inefficiencies (small circles do far too much work). */ void gdImageArc(im, cx, cy, w, h, s, e, color) gdImagePtr im; int cx; int cy; int w; int h; int s; int e; int color; { int i; int smod, emod; int lx, ly; int w2, h2; w2 = w/2; h2 = h/2; while (e < s) { e += 360; } for (i=s; (i <= e); i++) { int x, y; x = ((long)cost[i % 360] * (long)w2 / costScale) + cx; y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy; if (i != s) { gdImageLine(im, lx, ly, x, y, color); } lx = x; ly = y; } } #if 0 /* Bresenham octant code, which I should use eventually */ int x, y, d; x = 0; y = w; d = 3-2*w; while (x < y) { gdImageSetPixel(im, cx+x, cy+y, color); if (d < 0) { d += 4 * x + 6; } else { d += 4 * (x - y) + 10; y--; } x++; } if (x == y) { gdImageSetPixel(im, cx+x, cy+y, color); } #endif void gdImageFillToBorder(im, x, y, border, color) gdImagePtr im; int x; int y; int border; int color; { int lastBorder; /* Seek left */ int leftLimit, rightLimit; int i; leftLimit = (-1); if (border < 0) { /* Refuse to fill to a non-solid border */ return; } for (i = x; (i >= 0); i--) { if (gdImageGetPixel(im, i, y) == border) { break; } gdImageSetPixel(im, i, y, color); leftLimit = i; } if (leftLimit == (-1)) { return; } /* Seek right */ rightLimit = x; for (i = (x+1); (i < im->sx); i++) { if (gdImageGetPixel(im, i, y) == border) { break; } gdImageSetPixel(im, i, y, color); rightLimit = i; } /* Look at lines above and below and start paints */ /* Above */ if (y > 0) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel(im, i, y-1); if (lastBorder) { if ((c != border) && (c != color)) { gdImageFillToBorder(im, i, y-1, border, color); lastBorder = 0; } } else if ((c == border) || (c == color)) { lastBorder = 1; } } } /* Below */ if (y < ((im->sy) - 1)) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel(im, i, y+1); if (lastBorder) { if ((c != border) && (c != color)) { gdImageFillToBorder(im, i, y+1, border, color); lastBorder = 0; } } else if ((c == border) || (c == color)) { lastBorder = 1; } } } } void gdImageFill(im, x, y, color) gdImagePtr im; int x; int y; int color; { int lastBorder; int old; int leftLimit, rightLimit; int i; old = gdImageGetPixel(im, x, y); if (color == gdTiled) { /* Tile fill -- got to watch out! */ int p, tileColor; int srcx, srcy; if (!im->tile) { return; } /* Refuse to flood-fill with a transparent pattern -- I can't do it without allocating another image */ if (gdImageGetTransparent(im->tile) != (-1)) { return; } srcx = x % gdImageSX(im->tile); srcy = y % gdImageSY(im->tile); p = gdImageGetPixel(im->tile, srcx, srcy); tileColor = im->tileColorMap[p]; if (old == tileColor) { /* Nothing to be done */ return; } } else { if (old == color) { /* Nothing to be done */ return; } } /* Seek left */ leftLimit = (-1); for (i = x; (i >= 0); i--) { if (gdImageGetPixel(im, i, y) != old) { break; } gdImageSetPixel(im, i, y, color); leftLimit = i; } if (leftLimit == (-1)) { return; } /* Seek right */ rightLimit = x; for (i = (x+1); (i < im->sx); i++) { if (gdImageGetPixel(im, i, y) != old) { break; } gdImageSetPixel(im, i, y, color); rightLimit = i; } /* Look at lines above and below and start paints */ /* Above */ if (y > 0) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel(im, i, y-1); if (lastBorder) { if (c == old) { gdImageFill(im, i, y-1, color); lastBorder = 0; } } else if (c != old) { lastBorder = 1; } } } /* Below */ if (y < ((im->sy) - 1)) { lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { int c; c = gdImageGetPixel(im, i, y+1); if (lastBorder) { if (c == old) { gdImageFill(im, i, y+1, color); lastBorder = 0; } } else if (c != old) { lastBorder = 1; } } } } #ifdef TEST_CODE void gdImageDump(im) gdImagePtr im; { int i, j; for (i=0; (i < im->sy); i++) { for (j=0; (j < im->sx); j++) { printf("%d", im->pixels[j][i]); } printf("\n"); } } #endif /* Code drawn from ppmtogif.c, from the pbmplus package ** ** Based on GIFENCOD by David Rowley . A ** Lempel-Zim compression based on "compress". ** ** Modified by Marcel Wijkstra ** ** Copyright (C) 1989 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. ** ** The Graphics Interchange Format(c) is the Copyright property of ** CompuServe Incorporated. GIF(sm) is a Service Mark property of ** CompuServe Incorporated. */ /* * a code_int must be able to hold 2**GIFBITS values of type int, and also -1 */ typedef int code_int; #ifdef SIGNED_COMPARE_SLOW typedef unsigned long int count_int; typedef unsigned short int count_short; #else /*SIGNED_COMPARE_SLOW*/ typedef long int count_int; #endif /*SIGNED_COMPARE_SLOW*/ static int colorstobpp(/* int colors */); static void BumpPixel (/* void */); static int GIFNextPixel (/* gdImagePtr im */); static void GIFEncode (/* FILE* fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int* Red, int* Green, int* Blue, gdImagePtr im */); static void Putword (/* int w, FILE* fp */); static void compress (/* int init_bits, FILE* outfile, gdImagePtr im */); static void output (/* code_int code */); static void cl_block (/* void */); static void cl_hash (/* count_int hsize */); static void char_init (/* void */); static void char_out (/* int c */); static void flush_char (/* void */); /* Allows for reuse */ static void init_statics(/* void */); void gdImageGif(im, out) gdImagePtr im; FILE *out; { int interlace, transparent, BitsPerPixel; interlace = im->interlace; transparent = im->transparent; BitsPerPixel = colorstobpp(im->colorsTotal); /* Clear any old values in statics strewn through the GIF code */ init_statics(); /* All set, let's do it. */ GIFEncode( out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel, im->red, im->green, im->blue, im); } static int colorstobpp( colors ) int colors; { int bpp; if ( colors <= 2 ) bpp = 1; else if ( colors <= 4 ) bpp = 2; else if ( colors <= 8 ) bpp = 3; else if ( colors <= 16 ) bpp = 4; else if ( colors <= 32 ) bpp = 5; else if ( colors <= 64 ) bpp = 6; else if ( colors <= 128 ) bpp = 7; else if ( colors <= 256 ) bpp = 8; return bpp; } /***************************************************************************** * * GIFENCODE.C - GIF Image compression interface * * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent, * BitsPerPixel, Red, Green, Blue, gdImagePtr ) * *****************************************************************************/ #define TRUE 1 #define FALSE 0 static int Width, Height; static int curx, cury; static long CountDown; static int Pass = 0; static int Interlace; /* * Bump the 'curx' and 'cury' to point to the next pixel */ static void BumpPixel() { /* * Bump the current X position */ ++curx; /* * If we are at the end of a scan line, set curx back to the beginning * If we are interlaced, bump the cury to the appropriate spot, * otherwise, just increment it. */ if( curx == Width ) { curx = 0; if( !Interlace ) ++cury; else { switch( Pass ) { case 0: cury += 8; if( cury >= Height ) { ++Pass; cury = 4; } break; case 1: cury += 8; if( cury >= Height ) { ++Pass; cury = 2; } break; case 2: cury += 4; if( cury >= Height ) { ++Pass; cury = 1; } break; case 3: cury += 2; break; } } } } /* * Return the next pixel from the image */ static int GIFNextPixel( im ) gdImagePtr im; { int r; if( CountDown == 0 ) return EOF; --CountDown; r = gdImageGetPixel(im, curx, cury); BumpPixel(); return r; } /* public */ static void GIFEncode( fp, GWidth, GHeight, GInterlace, Background, Transparent, BitsPerPixel, Red, Green, Blue, im ) FILE* fp; int GWidth, GHeight; int GInterlace; int Background; int Transparent; int BitsPerPixel; int Red[], Green[], Blue[]; gdImagePtr im; { int B; int RWidth, RHeight; int LeftOfs, TopOfs; int Resolution; int ColorMapSize; int InitCodeSize; int i; Interlace = GInterlace; ColorMapSize = 1 << BitsPerPixel; RWidth = Width = GWidth; RHeight = Height = GHeight; LeftOfs = TopOfs = 0; Resolution = BitsPerPixel; /* * Calculate number of bits we are expecting */ CountDown = (long)Width * (long)Height; /* * Indicate which pass we are on (if interlace) */ Pass = 0; /* * The initial code size */ if( BitsPerPixel <= 1 ) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Set up the current x and y position */ curx = cury = 0; /* * Write the Magic header */ fwrite( Transparent < 0 ? "GIF87a" : "GIF89a", 1, 6, fp ); /* * Write out the screen width and height */ Putword( RWidth, fp ); Putword( RHeight, fp ); /* * Indicate that there is a global colour map */ B = 0x80; /* Yes, there is a color map */ /* * OR in the resolution */ B |= (Resolution - 1) << 5; /* * OR in the Bits per Pixel */ B |= (BitsPerPixel - 1); /* * Write it out */ fputc( B, fp ); /* * Write out the Background colour */ fputc( Background, fp ); /* * Byte of 0's (future expansion) */ fputc( 0, fp ); /* * Write out the Global Colour Map */ for( i=0; i= 0 ) { fputc( '!', fp ); fputc( 0xf9, fp ); fputc( 4, fp ); fputc( 1, fp ); fputc( 0, fp ); fputc( 0, fp ); fputc( Transparent, fp ); fputc( 0, fp ); } /* * Write an Image separator */ fputc( ',', fp ); /* * Write the Image header */ Putword( LeftOfs, fp ); Putword( TopOfs, fp ); Putword( Width, fp ); Putword( Height, fp ); /* * Write out whether or not the image is interlaced */ if( Interlace ) fputc( 0x40, fp ); else fputc( 0x00, fp ); /* * Write out the initial code size */ fputc( InitCodeSize, fp ); /* * Go and actually compress the data */ compress( InitCodeSize+1, fp, im ); /* * Write out a Zero-length packet (to end the series) */ fputc( 0, fp ); /* * Write the GIF file terminator */ fputc( ';', fp ); } /* * Write out a word to the GIF file */ static void Putword( w, fp ) int w; FILE* fp; { fputc( w & 0xff, fp ); fputc( (w / 256) & 0xff, fp ); } /*************************************************************************** * * GIFCOMPR.C - GIF Image compression routines * * Lempel-Ziv compression based on 'compress'. GIF modifications by * David Rowley (mgardi@watdcsu.waterloo.edu) * ***************************************************************************/ /* * General DEFINEs */ #define GIFBITS 12 #define HSIZE 5003 /* 80% occupancy */ #ifdef NO_UCHAR typedef char char_type; #else /*NO_UCHAR*/ typedef unsigned char char_type; #endif /*NO_UCHAR*/ /* * * GIF Image compression - modified 'compress' * * Based on: compress.c - File compression ala IEEE Computer, June 1984. * * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) * Jim McKie (decvax!mcvax!jim) * Steve Davies (decvax!vax135!petsd!peora!srd) * Ken Turkowski (decvax!decwrl!turtlevax!ken) * James A. Woods (decvax!ihnp4!ames!jaw) * Joe Orost (decvax!vax135!petsd!joe) * */ #include #define ARGVAL() (*++(*argv) || (--argc && *++argv)) static int n_bits; /* number of bits/code */ static int maxbits = GIFBITS; /* user settable max # bits/code */ static code_int maxcode; /* maximum code, given n_bits */ static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */ #ifdef COMPATIBLE /* But wrong! */ # define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1) #else /*COMPATIBLE*/ # define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) #endif /*COMPATIBLE*/ static count_int htab [HSIZE]; static unsigned short codetab [HSIZE]; #define HashTabOf(i) htab[i] #define CodeTabOf(i) codetab[i] static code_int hsize = HSIZE; /* for dynamic table sizing */ /* * To save much memory, we overlay the table used by compress() with those * used by decompress(). The tab_prefix table is the same size and type * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We * get this from the beginning of htab. The output stack uses the rest * of htab, and contains characters. There is plenty of room for any * possible stack (stack used to be 8000 characters). */ #define tab_prefixof(i) CodeTabOf(i) #define tab_suffixof(i) ((char_type*)(htab))[i] #define de_stack ((char_type*)&tab_suffixof((code_int)1< 0 ) goto probe; nomatch: output ( (code_int) ent ); ++out_count; ent = c; #ifdef SIGNED_COMPARE_SLOW if ( (unsigned) free_ent < (unsigned) maxmaxcode) { #else /*SIGNED_COMPARE_SLOW*/ if ( free_ent < maxmaxcode ) { /* } */ #endif /*SIGNED_COMPARE_SLOW*/ CodeTabOf (i) = free_ent++; /* code -> hashtable */ HashTabOf (i) = fcode; } else cl_block(); } /* * Put out the final code. */ output( (code_int)ent ); ++out_count; output( (code_int) EOFCode ); } /***************************************************************** * TAG( output ) * * Output the given code. * Inputs: * code: A n_bits-bit integer. If == -1, then EOF. This assumes * that n_bits =< (long)wordsize - 1. * Outputs: * Outputs code to the file. * Assumptions: * Chars are 8 bits long. * Algorithm: * Maintain a GIFBITS character long buffer (so that 8 codes will * fit in it exactly). Use the VAX insv instruction to insert each * code in turn. When the buffer fills up empty it and start over. */ static unsigned long cur_accum = 0; static int cur_bits = 0; static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; static void output( code ) code_int code; { cur_accum &= masks[ cur_bits ]; if( cur_bits > 0 ) cur_accum |= ((long)code << cur_bits); else cur_accum = code; cur_bits += n_bits; while( cur_bits >= 8 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. */ if ( free_ent > maxcode || clear_flg ) { if( clear_flg ) { maxcode = MAXCODE (n_bits = g_init_bits); clear_flg = 0; } else { ++n_bits; if ( n_bits == maxbits ) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits); } } if( code == EOFCode ) { /* * At EOF, write the rest of the buffer. */ while( cur_bits > 0 ) { char_out( (unsigned int)(cur_accum & 0xff) ); cur_accum >>= 8; cur_bits -= 8; } flush_char(); fflush( g_outfile ); if( ferror( g_outfile ) ) exit(1); } } /* * Clear out the hash table */ static void cl_block () /* table clear for block compress */ { cl_hash ( (count_int) hsize ); free_ent = ClearCode + 2; clear_flg = 1; output( (code_int)ClearCode ); } static void cl_hash(hsize) /* reset code table */ register count_int hsize; { register count_int *htab_p = htab+hsize; register long i; register long m1 = -1; i = hsize - 16; do { /* might use Sys V memset(3) here */ *(htab_p-16) = m1; *(htab_p-15) = m1; *(htab_p-14) = m1; *(htab_p-13) = m1; *(htab_p-12) = m1; *(htab_p-11) = m1; *(htab_p-10) = m1; *(htab_p-9) = m1; *(htab_p-8) = m1; *(htab_p-7) = m1; *(htab_p-6) = m1; *(htab_p-5) = m1; *(htab_p-4) = m1; *(htab_p-3) = m1; *(htab_p-2) = m1; *(htab_p-1) = m1; htab_p -= 16; } while ((i -= 16) >= 0); for ( i += 16; i > 0; --i ) *--htab_p = m1; } /****************************************************************************** * * GIF Specific routines * ******************************************************************************/ /* * Number of characters so far in this 'packet' */ static int a_count; /* * Set up the 'byte output' routine */ static void char_init() { a_count = 0; } /* * Define the storage for the packet accumulator */ static char accum[ 256 ]; /* * Add a character to the end of the current packet, and if it is 254 * characters, flush the packet to disk. */ static void char_out( c ) int c; { accum[ a_count++ ] = c; if( a_count >= 254 ) flush_char(); } /* * Flush the packet to disk, and reset the accumulator */ static void flush_char() { if( a_count > 0 ) { fputc( a_count, g_outfile ); fwrite( accum, 1, a_count, g_outfile ); a_count = 0; } } static void init_statics() { /* Some of these are properly initialized later. What I'm doing here is making sure code that depends on C's initialization of statics doesn't break when the code gets called more than once. */ Width = 0; Height = 0; curx = 0; cury = 0; CountDown = 0; Pass = 0; Interlace = 0; a_count = 0; cur_accum = 0; cur_bits = 0; g_init_bits = 0; g_outfile = 0; ClearCode = 0; EOFCode = 0; free_ent = 0; clear_flg = 0; offset = 0; in_count = 1; out_count = 0; hsize = HSIZE; n_bits = 0; maxbits = GIFBITS; maxcode = 0; maxmaxcode = (code_int)1 << GIFBITS; } /* +-------------------------------------------------------------------+ */ /* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */ /* | Permission to use, copy, modify, and distribute this software | */ /* | and its documentation for any purpose and without fee is hereby | */ /* | granted, provided that the above copyright notice appear in all | */ /* | copies and that both that copyright notice and this permission | */ /* | notice appear in supporting documentation. This software is | */ /* | provided "as is" without express or implied warranty. | */ /* +-------------------------------------------------------------------+ */ #define MAXCOLORMAPSIZE 256 #define TRUE 1 #define FALSE 0 #define CM_RED 0 #define CM_GREEN 1 #define CM_BLUE 2 #define MAX_LWZ_BITS 12 #define INTERLACE 0x40 #define LOCALCOLORMAP 0x80 #define BitSet(byte, bit) (((byte) & (bit)) == (bit)) #define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0) #define LM_to_uint(a,b) (((b)<<8)|(a)) static struct { unsigned int Width; unsigned int Height; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned int BitPixel; unsigned int ColorResolution; unsigned int Background; unsigned int AspectRatio; } GifScreen; static struct { int transparent; int delayTime; int inputFlag; int disposal; } Gif89 = { -1, -1, -1, 0 }; static int ReadColorMap ( /* FILE *fd, int number, gdImagePtr im, int *flag */); static int DoExtension (/* FILE *fd, int label */); static int GetDataBlock (/* FILE *fd, unsigned char *buf */); static int GetCode (/* FILE *fd, int code_size, int flag */); static int LWZReadByte (/* FILE *fd, int flag, int input_code_size */); static void ReadImage (/* gdImagePtr im, FILE *fd, int len, int height, int interlace, int ignore */); int ZeroDataBlock; gdImagePtr gdImageCreateFromGif(fd) FILE *fd; { int imageNumber; int BitPixel; int ColorResolution; int Background; int AspectRatio; int Transparent = (-1); unsigned char buf[16]; unsigned char c; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; int imw, imh; int useGlobalColormap; int bitPixel; int imageCount = 0; char version[4]; gdImagePtr im; ZeroDataBlock = FALSE; imageNumber = 1; if (! ReadOK(fd,buf,6)) { return 0; } if (strncmp((char *)buf,"GIF",3) != 0) { return 0; } strncpy(version, (char *)buf + 3, 3); version[3] = '\0'; if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { return 0; } if (! ReadOK(fd,buf,7)) { return 0; } BitPixel = 2<<(buf[4]&0x07); ColorResolution = (((buf[4]&0x70)>>3)+1); Background = buf[5]; AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (ReadColorMap(fd, BitPixel, ColorMap)) { return 0; } } for (;;) { if (! ReadOK(fd,&c,1)) { return 0; } if (c == ';') { /* GIF terminator */ int i; if (imageCount < imageNumber) { return 0; } /* Check for open colors at the end, so we can reduce colorsTotal and ultimately BitsPerPixel */ for (i=((im->colorsTotal-1)); (i>=0); i--) { if (im->open[i]) { im->colorsTotal--; } else { break; } } return im; } if (c == '!') { /* Extension */ if (! ReadOK(fd,&c,1)) { return 0; } DoExtension(fd, c, &Transparent); continue; } if (c != ',') { /* Not a valid start character */ continue; } ++imageCount; if (! ReadOK(fd,buf,9)) { return 0; } useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP); bitPixel = 1<<((buf[8]&0x07)+1); imw = LM_to_uint(buf[4],buf[5]); imh = LM_to_uint(buf[6],buf[7]); if (!(im = gdImageCreate(imw, imh))) { return 0; } im->interlace = BitSet(buf[8], INTERLACE); if (! useGlobalColormap) { if (ReadColorMap(fd, bitPixel, localColorMap)) { return 0; } ReadImage(im, fd, imw, imh, localColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber); } else { ReadImage(im, fd, imw, imh, ColorMap, BitSet(buf[8], INTERLACE), imageCount != imageNumber); } if (Transparent != (-1)) { gdImageColorTransparent(im, Transparent); } } } static int ReadColorMap(fd,number,buffer) FILE *fd; int number; unsigned char buffer[3][MAXCOLORMAPSIZE]; { int i; unsigned char rgb[3]; for (i = 0; i < number; ++i) { if (! ReadOK(fd, rgb, sizeof(rgb))) { return TRUE; } buffer[CM_RED][i] = rgb[0] ; buffer[CM_GREEN][i] = rgb[1] ; buffer[CM_BLUE][i] = rgb[2] ; } return FALSE; } static int DoExtension(fd, label, Transparent) FILE *fd; int label; int *Transparent; { static char buf[256]; switch (label) { case 0xf9: /* Graphic Control Extension */ (void) GetDataBlock(fd, (unsigned char*) buf); Gif89.disposal = (buf[0] >> 2) & 0x7; Gif89.inputFlag = (buf[0] >> 1) & 0x1; Gif89.delayTime = LM_to_uint(buf[1],buf[2]); if ((buf[0] & 0x1) != 0) *Transparent = buf[3]; while (GetDataBlock(fd, (unsigned char*) buf) != 0) ; return FALSE; default: break; } while (GetDataBlock(fd, (unsigned char*) buf) != 0) ; return FALSE; } static int GetDataBlock(fd, buf) FILE *fd; unsigned char *buf; { unsigned char count; if (! ReadOK(fd,&count,1)) { return -1; } ZeroDataBlock = count == 0; if ((count != 0) && (! ReadOK(fd, buf, count))) { return -1; } return count; } static int GetCode(fd, code_size, flag) FILE *fd; int code_size; int flag; { static unsigned char buf[280]; static int curbit, lastbit, done, last_byte; int i, j, ret; unsigned char count; if (flag) { curbit = 0; lastbit = 0; done = FALSE; return 0; } if ( (curbit+code_size) >= lastbit) { if (done) { if (curbit >= lastbit) { /* Oh well */ } return -1; } buf[0] = buf[last_byte-2]; buf[1] = buf[last_byte-1]; if ((count = GetDataBlock(fd, &buf[2])) == 0) done = TRUE; last_byte = 2 + count; curbit = (curbit - lastbit) + 16; lastbit = (2+count)*8 ; } ret = 0; for (i = curbit, j = 0; j < code_size; ++i, ++j) ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; curbit += code_size; return ret; } static int LWZReadByte(fd, flag, input_code_size) FILE *fd; int flag; int input_code_size; { static int fresh = FALSE; int code, incode; static int code_size, set_code_size; static int max_code, max_code_size; static int firstcode, oldcode; static int clear_code, end_code; static int table[2][(1<< MAX_LWZ_BITS)]; static int stack[(1<<(MAX_LWZ_BITS))*2], *sp; register int i; if (flag) { set_code_size = input_code_size; code_size = set_code_size+1; clear_code = 1 << set_code_size ; end_code = clear_code + 1; max_code_size = 2*clear_code; max_code = clear_code+2; GetCode(fd, 0, TRUE); fresh = TRUE; for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1< stack) return *--sp; while ((code = GetCode(fd, code_size, FALSE)) >= 0) { if (code == clear_code) { for (i = 0; i < clear_code; ++i) { table[0][i] = 0; table[1][i] = i; } for (; i < (1< 0) ; if (count != 0) return -2; } incode = code; if (code >= max_code) { *sp++ = firstcode; code = oldcode; } while (code >= clear_code) { *sp++ = table[1][code]; if (code == table[0][code]) { /* Oh well */ } code = table[0][code]; } *sp++ = firstcode = table[1][code]; if ((code = max_code) <(1<= max_code_size) && (max_code_size < (1< stack) return *--sp; } return code; } static void ReadImage(im, fd, len, height, cmap, interlace, ignore) gdImagePtr im; FILE *fd; int len, height; unsigned char cmap[3][MAXCOLORMAPSIZE]; int interlace, ignore; { unsigned char c; int v; int xpos = 0, ypos = 0, pass = 0; int i; /* Stash the color map into the image */ for (i=0; (ired[i] = cmap[CM_RED][i]; im->green[i] = cmap[CM_GREEN][i]; im->blue[i] = cmap[CM_BLUE][i]; im->open[i] = 1; } /* Many (perhaps most) of these colors will remain marked open. */ im->colorsTotal = gdMaxColors; /* ** Initialize the Compression routines */ if (! ReadOK(fd,&c,1)) { return; } if (LWZReadByte(fd, TRUE, c) < 0) { return; } /* ** If this is an "uninteresting picture" ignore it. */ if (ignore) { while (LWZReadByte(fd, FALSE, c) >= 0) ; return; } while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) { /* This how we recognize which colors are actually used. */ if (im->open[v]) { im->open[v] = 0; } gdImageSetPixel(im, xpos, ypos, v); ++xpos; if (xpos == len) { xpos = 0; if (interlace) { switch (pass) { case 0: case 1: ypos += 8; break; case 2: ypos += 4; break; case 3: ypos += 2; break; } if (ypos >= height) { ++pass; switch (pass) { case 1: ypos = 4; break; case 2: ypos = 2; break; case 3: ypos = 1; break; default: goto fini; } } } else { ++ypos; } } if (ypos >= height) break; } fini: if (LWZReadByte(fd,FALSE,c)>=0) { /* Ignore extra */ } } void gdImageRectangle(im, x1, y1, x2, y2, color) gdImagePtr im; int x1; int y1; int x2; int y2; { gdImageLine(im, x1, y1, x2, y1, color); gdImageLine(im, x1, y2, x2, y2, color); gdImageLine(im, x1, y1, x1, y2, color); gdImageLine(im, x2, y1, x2, y2, color); } void gdImageFilledRectangle(im, x1, y1, x2, y2, color) gdImagePtr im; int x1; int y1; int x2; int y2; int color; { int x, y; for (y=y1; (y<=y2); y++) { for (x=x1; (x<=x2); x++) { gdImageSetPixel(im, x, y, color); } } } void gdImageCopy(dst, src, dstX, dstY, srcX, srcY, w, h) gdImagePtr dst; gdImagePtr src; int dstX; int dstY; int srcX; int srcY; int w; int h; { int c; int x, y; int tox, toy; int i; int colorMap[gdMaxColors]; for (i=0; (ired[c], src->green[c], src->blue[c]); } if (nc == (-1)) { /* No, so try to allocate it */ nc = gdImageColorAllocate(dst, src->red[c], src->green[c], src->blue[c]); /* If we're out of colors, go for the closest color */ if (nc == (-1)) { nc = gdImageColorClosest(dst, src->red[c], src->green[c], src->blue[c]); } } colorMap[c] = nc; } gdImageSetPixel(dst, tox, toy, colorMap[c]); tox++; } toy++; } } #ifdef xxx /* missing function 'floor' */ void gdImageCopyResized(dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH) gdImagePtr dst; gdImagePtr src; int dstX; int dstY; int srcX; int srcY; int dstW; int dstH; int srcW; int srcH; { int c; int x, y; int tox, toy; int ydest; int i; int colorMap[gdMaxColors]; /* Stretch vectors */ int *stx; int *sty; /* We only need to use floating point to determine the correct stretch vector for one line's worth. */ double accum; stx = (int *) malloc(sizeof(int) * srcW); sty = (int *) malloc(sizeof(int) * srcH); accum = 0; for (i=0; (i < srcW); i++) { int got; accum += (double)dstW/(double)srcW; got = floor(accum); stx[i] = got; accum -= got; } accum = 0; for (i=0; (i < srcH); i++) { int got; accum += (double)dstH/(double)srcH; got = floor(accum); sty[i] = got; accum -= got; } for (i=0; (ired[c], src->green[c], src->blue[c]); } if (nc == (-1)) { /* No, so try to allocate it */ nc = gdImageColorAllocate(dst, src->red[c], src->green[c], src->blue[c]); /* If we're out of colors, go for the closest color */ if (nc == (-1)) { nc = gdImageColorClosest(dst, src->red[c], src->green[c], src->blue[c]); } } colorMap[c] = nc; } for (i=0; (i < stx[x - srcX]); i++) { gdImageSetPixel(dst, tox, toy, colorMap[c]); tox++; } } toy++; } } free(stx); free(sty); } #endif int gdGetWord(result, in) int *result; FILE *in; { int r; r = getc(in); if (r == EOF) { return 0; } *result = r << 8; r = getc(in); if (r == EOF) { return 0; } *result += r; return 1; } void gdPutWord(w, out) int w; FILE *out; { putc((unsigned char)(w >> 8), out); putc((unsigned char)(w & 0xFF), out); } int gdGetByte(result, in) int *result; FILE *in; { int r; r = getc(in); if (r == EOF) { return 0; } *result = r; return 1; } gdImagePtr gdImageCreateFromGd(in) FILE *in; { int sx, sy; int x, y; int i; gdImagePtr im; if (!gdGetWord(&sx, in)) { goto fail1; } if (!gdGetWord(&sy, in)) { goto fail1; } im = gdImageCreate(sx, sy); if (!gdGetByte(&im->colorsTotal, in)) { goto fail2; } if (!gdGetWord(&im->transparent, in)) { goto fail2; } if (im->transparent == 257) { im->transparent = (-1); } for (i=0; (ired[i], in)) { goto fail2; } if (!gdGetByte(&im->green[i], in)) { goto fail2; } if (!gdGetByte(&im->blue[i], in)) { goto fail2; } } for (y=0; (ypixels[x][y] = ch; } } return im; fail2: gdImageDestroy(im); fail1: return 0; } void gdImageGd(im, out) gdImagePtr im; FILE *out; { int x, y; int i; int trans; gdPutWord(im->sx, out); gdPutWord(im->sy, out); putc((unsigned char)im->colorsTotal, out); trans = im->transparent; if (trans == (-1)) { trans = 257; } gdPutWord(trans, out); for (i=0; (ired[i], out); putc((unsigned char)im->green[i], out); putc((unsigned char)im->blue[i], out); } for (y=0; (y < im->sy); y++) { for (x=0; (x < im->sx); x++) { putc((unsigned char)im->pixels[x][y], out); } } } gdImagePtr gdImageCreateFromXbm(fd) FILE *fd; { gdImagePtr im; int bit; int w, h; int bytes; int ch; int spaceat; int i, x, y; int bits; char *sp; char s[161]; if (!fgets(s, 160, fd)) { return 0; } sp = &s[0]; /* Skip #define */ sp = strchr(sp, ' '); if (!sp) { return 0; } /* Skip width label */ sp++; sp = strchr(sp, ' '); if (!sp) { return 0; } /* Get width */ w = atoi(sp + 1); if (!w) { return 0; } if (!fgets(s, 160, fd)) { return 0; } sp = s; /* Skip #define */ sp = strchr(sp, ' '); if (!sp) { return 0; } /* Skip height label */ sp++; sp = strchr(sp, ' '); if (!sp) { return 0; } /* Get height */ h = atoi(sp + 1); if (!h) { return 0; } /* Skip declaration line */ if (!fgets(s, 160, fd)) { return 0; } bytes = (w * h / 8) + 1; im = gdImageCreate(w, h); gdImageColorAllocate(im, 255, 255, 255); gdImageColorAllocate(im, 0, 0, 0); x = 0; y = 0; for (i=0; (i < bytes); i++) { char h[3]; int b; /* Skip spaces, commas, CRs, 0x */ while(1) { ch = getc(fd); if (ch == EOF) { goto fail; } if (ch == 'x') { break; } } /* Get hex value */ ch = getc(fd); if (ch == EOF) { goto fail; } h[0] = ch; ch = getc(fd); if (ch == EOF) { goto fail; } h[1] = ch; h[2] = '\0'; sscanf(h, "%x", &b); for (bit = 1; (bit <= 128); (bit = bit << 1)) { gdImageSetPixel(im, x++, y, b & bit); if (x == im->sx) { x = 0; y++; if (y == im->sy) { return im; } } } } /* Shouldn't happen */ fprintf(stderr, "Error: bug in gdImageCreateFromXbm!\n"); return 0; fail: gdImageDestroy(im); return 0; } void gdImagePolygon(im, p, n, c) gdImagePtr im; gdPointPtr p; int n; int c; { int i; int lx, ly; if (!n) { return; } lx = p->x; ly = p->y; gdImageLine(im, lx, ly, p[n-1].x, p[n-1].y, c); for (i=1; (i < n); i++) { p++; gdImageLine(im, lx, ly, p->x, p->y, c); lx = p->x; ly = p->y; } } int gdCompareInt(/* int *a, int *b */); void gdImageFilledPolygon(im, p, n, c) gdImagePtr im; gdPointPtr p; int n; int c; { int i; int y; int y1, y2; int ints; if (!n) { return; } if (!im->polyAllocated) { im->polyInts = (int *) malloc(sizeof(int) * n); im->polyAllocated = n; } if (im->polyAllocated < n) { while (im->polyAllocated < n) { im->polyAllocated *= 2; } im->polyInts = (int *) realloc(im->polyInts, sizeof(int) * im->polyAllocated); } y1 = p[0].y; y2 = p[0].y; for (i=1; (i < n); i++) { if (p[i].y < y1) { y1 = p[i].y; } if (p[i].y > y2) { y2 = p[i].y; } } for (y=y1; (y <= y2); y++) { int interLast; int dirLast; int interFirst = 1; ints = 0; for (i=0; (i <= n); i++) { int x1, x2; int y1, y2; int dir; int ind1, ind2; if ((i == n) || (!i)) { ind1 = n-1; ind2 = 0; } else { ind1 = i-1; ind2 = i; } y1 = p[ind1].y; y2 = p[ind2].y; if (y1 < y2) { y1 = p[ind1].y; y2 = p[ind2].y; x1 = p[ind1].x; x2 = p[ind2].x; dir = -1; } else if (y1 > y2) { y2 = p[ind1].y; y1 = p[ind2].y; x2 = p[ind1].x; x1 = p[ind2].x; dir = 1; } else { /* Horizontal; just draw it */ gdImageLine(im, p[ind1].x, y1, p[ind2].x, y1); continue; } if ((y >= y1) && (y <= y2)) { int inter = (y-y1) * (x2-x1) / (y2-y1) + x1; /* Only count intersections once except at maxima and minima */ if (!interFirst) { if (inter == interLast) { if (dir == dirLast) { continue; } } } if (i > 0) { im->polyInts[ints++] = inter; } dirLast = dir; interLast = inter; interFirst = 0; } } qsort(im->polyInts, ints, sizeof(int), gdCompareInt); for (i=0; (i < (ints-1)); i+=2) { gdImageLine(im, im->polyInts[i], y, im->polyInts[i+1], y, c); } } } int gdCompareInt(a, b) int *a; int *b; { return *a - *b; } void gdImageSetStyle(im, style, noOfPixels) gdImagePtr im; int *style; int noOfPixels; { if (im->style) { free(im->style); } im->style = (int *) /* used to be unsigned int ...fixed by Thure Etzold */ malloc(sizeof(int) * noOfPixels); memcpy(im->style, style, sizeof(unsigned int) * noOfPixels); im->styleLength = noOfPixels; im->stylePos = 0; } void gdImageSetBrush(im, brush) gdImagePtr im; gdImagePtr brush; { int i; im->brush = brush; for (i=0; (i < gdImageColorsTotal(brush)); i++) { int index; index = gdImageColorExact(im, gdImageRed(brush, i), gdImageGreen(brush, i), gdImageBlue(brush, i)); if (index == (-1)) { index = gdImageColorAllocate(im, gdImageRed(brush, i), gdImageGreen(brush, i), gdImageBlue(brush, i)); if (index == (-1)) { index = gdImageColorClosest(im, gdImageRed(brush, i), gdImageGreen(brush, i), gdImageBlue(brush, i)); } } im->brushColorMap[i] = index; } } void gdImageSetTile(im, tile) gdImagePtr im; gdImagePtr tile; { int i; im->tile = tile; for (i=0; (i < gdImageColorsTotal(tile)); i++) { int index; index = gdImageColorExact(im, gdImageRed(tile, i), gdImageGreen(tile, i), gdImageBlue(tile, i)); if (index == (-1)) { index = gdImageColorAllocate(im, gdImageRed(tile, i), gdImageGreen(tile, i), gdImageBlue(tile, i)); if (index == (-1)) { index = gdImageColorClosest(im, gdImageRed(tile, i), gdImageGreen(tile, i), gdImageBlue(tile, i)); } } im->tileColorMap[i] = index; } } void gdImageInterlace(im, interlaceArg) gdImagePtr im; int interlaceArg; { im->interlace = interlaceArg; } ** ** $RCSfile: gd.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:32 $ ** ** $Locker: $ ** $State: Exp $ ** ** ** ** gd.h: declarations file for the gifdraw module. ** ** Written by Tom Boutell, 5/94. ** Copyright 1994, Cold Spring Harbor Labs. ** Permission granted to use this code in any fashion provided ** that this notice is retained and any alterations are ** labeled as such. It is requested, but not required, that ** you share extensions to this module with us so that we ** can incorporate them into new versions. ** ** ** this file was modified so that it now contains also the include files ** gdfonts.h and gdfontl.h by thure etzold, March 10, 1995 */ /* This can't be changed, it's part of the GIF specification. */ #define gdMaxColors 256 /* Image type. See functions below; you will not need to change the elements directly. Use the provided macros to access sx, sy, the color table, and colorsTotal for read-only purposes. */ typedef struct gdImageStruct { unsigned char ** pixels; int sx; int sy; int colorsTotal; int red[gdMaxColors]; int green[gdMaxColors]; int blue[gdMaxColors]; int open[gdMaxColors]; int transparent; int *polyInts; int polyAllocated; struct gdImageStruct *brush; struct gdImageStruct *tile; int brushColorMap[gdMaxColors]; int tileColorMap[gdMaxColors]; int styleLength; int stylePos; int *style; int interlace; } gdImage; typedef gdImage * gdImagePtr; typedef struct { /* # of characters in font */ int nchars; /* First character is numbered... (usually 32 = space) */ int offset; /* Character width and height */ int w; int h; /* Font data; array of characters, one row after another. Easily included in code, also easily loaded from data files. */ char *data; } gdFont; /* Text functions take these. */ typedef gdFont *gdFontPtr; /* For backwards compatibility only. Use gdImageSetStyle() for MUCH more flexible line drawing. Also see gdImageSetBrush(). */ #define gdDashSize 4 /* Special colors. */ #define gdStyled (-2) #define gdBrushed (-3) #define gdStyledBrushed (-4) #define gdTiled (-5) /* NOT the same as the transparent color index. This is used in line styles only. */ #define gdTransparent (-6) /* Functions to manipulate images. */ gdImagePtr gdImageCreate(/* int sx, int sy */); gdImagePtr gdImageCreateFromGif(/* FILE *fd */); gdImagePtr gdImageCreateFromGd(/* FILE *fd */); gdImagePtr gdImageCreateFromXbm(/* FILE *fd */); void gdImageDestroy(/* gdImagePtr im */); void gdImageSetPixel(/* gdImagePtr im, int x, int y, int color */); int gdImageGetPixel(/* gdImagePtr im, int x, int y */); void gdImageLine(/* gdImagePtr im, int x1, int y1, int x2, int y2, int color */); /* For backwards compatibility only. Use gdImageSetStyle() for much more flexible line drawing. */ void gdImageDashedLine(/* gdImagePtr im, int x1, int y1, int x2, int y2, int color */); /* Corners specified (not width and height). Upper left first, lower right second. */ void gdImageRectangle(/* gdImagePtr im, int x1, int y1, int x2, int y2, int color */); /* Solid bar. Upper left corner first, lower right corner second. */ void gdImageFilledRectangle(/* gdImagePtr im, int x1, int y1, int x2, int y2, int color */); int gdImageBoundsSafe(/* gdImagePtr im, int x, int y */); void gdImageChar(/* gdImagePtr im, gdFontPtr font, int x, int y, int c, int color */); void gdImageCharUp(/* gdImagePtr im, gdFontPtr font, int x, int y, int c, int color */); void gdImageString(/* gdImagePtr im, gdFontPtr font, int x, int y, char *s, int color */); void gdImageStringUp(/* gdImagePtr im, gdFontPtr font, int x, int y, char *s, int color */); /* Point type for use in polygon drawing. */ typedef struct { int x, y; } gdPoint, *gdPointPtr; void gdImagePolygon(/* gdImagePtr im, gdPointPtr p, int pointsTotal, int color */); void gdImageFilledPolygon(/* gdImagePtr im, gdPointPtr p, int pointsTotal, int color */); int gdImageColorAllocate(/* gdImagePtr im, int r, int g, int b */); int gdImageColorClosest(/* gdImagePtr im, int r, int g, int b */); int gdImageColorExact(/* gdImagePtr im, int r, int g, int b */); void gdImageColorDeallocate(/* gdImagePtr im, int color */); void gdImageColorTransparent(/* gdImagePtr im, int color */); void gdImageGif(/* gdImagePtr im, FILE *out */); void gdImageGd(/* gdImagePtr im, FILE *out */); void gdImageArc(/* gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color */); void gdImageFillToBorder(/* gdImagePtr im, int x, int y, int border, int color */); void gdImageFill(/* gdImagePtr im, int x, int y, int color */); void gdImageCopy(/* gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h */); /* Stretches or shrinks to fit, as needed */ void gdImageCopyResized(/* gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int destw, int desth, int srcw, int srch */); void gdImageSetBrush(/* gdImagePtr im, gdImagePtr brush */); void gdImageSetTile(/* gdImagePtr im, gdImagePtr tile */); void gdImageSetStyle(/* gdImagePtr im, int *style, int noOfPixels */); /* On or off (1 or 0) */ void gdImageInterlace(/* gdImagePtr im, int interlace */); /* Macros to access information about images. READ ONLY. Changing these values will NOT have the desired result. */ #define gdImageSX(im) ((im)->sx) #define gdImageSY(im) ((im)->sy) #define gdImageColorsTotal(im) ((im)->colorsTotal) #define gdImageRed(im, c) ((im)->red[(c)]) #define gdImageGreen(im, c) ((im)->green[(c)]) #define gdImageBlue(im, c) ((im)->blue[(c)]) #define gdImageGetTransparent(im) ((im)->transparent) #define gdImageGetInterlaced(im) ((im)->interlace) /* formerly gdfontl.h */ /* 8x16 font derived from a public domain font in the X distribution. Only contains the 96 standard ascii characters, sorry. Feel free to improve on this. */ extern gdFontPtr gdFontLarge; /* formerly gdfonts.h */ /* 6x12 font derived from a public domain font in the X distribution. Only contains the 96 standard ascii characters, sorry. Feel free to improve on this. */ extern gdFontPtr gdFontSmall; char getz_ID[] = "$Id: getz.c,v 1.5 1996/08/11 22:47:04 etzold Exp $"; /* ** $RCSfile: getz.c,v $ ** $Revision: 1.5 $ ** $Date: 1996/08/11 22:47:04 $ ** $Author: etzold $ ** ** Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "srs.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _ODD #define _FUNCTION #include "oddclass.h" static VIEWo *BuildView (SETo *set); int main(int argc, char **argv) { ARGoLIST *argList; TEMPLv templ; SETo *set; VIEWo *view; ENTRYo *entry; IDoENTRY id; INT4 i; SrsEnv (); LibOpen ("srs5"); OddInit (def, 1); IcaInitSyntax (LibObjByName ("syntax", "icarus")); MsgSetFnct ((FUNC)IcaPrintMessage); templ = TemplOpen ("SRSICA:ascii.it", NULL); /* process command line */ argList = (ARGoLIST*) LibObjByName ("arglist", "getz"); argc = ArgGet (argList, argc, argv); if (ParGetNum ("printLibInfo") && argc == 2) { /* print only info ? */ LibPrintInfo (argv[1]); exit (0); } else if (ParGetNum ("printLibs")) { LibPrintLibs (); exit (0); } else if (ParGetNum ("getStartupInfo")) { LibPrintStartupInfo (); exit (0); } else if (argc != 2) { ArgUsage (argList); exit (0); } /* do the query */ TemplWith (templ, "$queryReport"); if ((set = Query (argv[1], "Q1"))) { view = BuildView (set); /* iterate over elements in the retrieved set */ for (i=1; i <= set->n; i++) { SetGetID (set, i, &id); entry = EntryOpen (&id); if (view) EntryView (entry, view); else if (ParGetBool ("printEntireEntry")) EntryPrint (entry); else if (*ParGetStr ("fieldList")) EntryPrintFields (entry); else printf ("%s\n", EntryGetFullName (entry)); EntryClose (&entry); } } TemplEndWith (); exit (0); } static VIEWo *BuildView (SETo *set) { VIEWo *view; SRSoFLD *ft; char *libName, *name, *tmp; Int4 k; if (*(tmp = ParGetStr ("viewFieldList"))) { view = ViewNew (1, "getz"); ViewSetFormat (view, "table"); for (k=0; SetGetNextLibStat (SetGetName (set), &libName, &k);) ViewAddRootLib (view, LibObjByName ("library", libName)); while ((name = strtok (tmp, " "))) { tmp = NULL; if (!(ft = LibGetFieldType (libName, name))) _ErrExit3 (e__objectunknown, "data-field", name); ViewAddRootField (view, ft); } } else view=NULL; return view; } char hash_srs_ID[] = "$Id: hash.c,v 1.1 1996/05/06 15:16:33 srs Exp $"; /* ** ** $RCSfile: hash.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:33 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.1 Copyright by Thure Etzold ** Unix port by Lukas Rosenthaler and Reinhard ** ** Author: Gerald Schaefer ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387372 ** Email: schaefer@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** implementation of a hash table used for generating indices ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include /* #include SRSINCLUDE */ #include "message.h" #include "hash.h" #define HSHxDEFHASHSIZE 111 #define HSHxDEFMAXFILL 80 /* ** HSHxHFREE means that this hash table element was never used before ** HSHxHDEL means that the element was used before but deleted now */ #define HSHxHFREE (void*)1L #define HSHxHDEL (void*)0L INT4 (*compare)(void *, void *) = NULL; /**************************************************************** * heap_sort: original by J.F.Korsh, L.J.Garrett * * Data Structures, Algorithms, and Program Style using C * * modification: ascendant order, list contains object pointers * * ****************************************************************/ /* function prototypes */ void heapsort(void **list, INT4 n); void shift(void **list, INT4 root, INT4 last); /* sorts the n elements of list in ascendant order */ void heapsort(void **list, INT4 n) { INT4 root, last; void *temp; list--; /* because the algorithm works from 1 to n */ root = n/2; last = n; while (root > 0) { shift(list, root, last); root--; } root = 1; while (last > 1) { /* interchange(list,1,last) */ temp = list[1]; list[1] = list[last]; list[last] = temp; last--; shift(list, root, last); } } /****************************************************************** * Makes the subtree of the root into a heap (min heap). * The left and right subtrees of root must be heaps. * All subtrees are stored in array list in sequential representation. * Only the nodes between root and last are considered to be * in the subtrees. ******************************************************************/ void shift(void **list, INT4 root, INT4 last) { INT4 ptr, succ; void *rootptr; ptr = root; succ = 2 * ptr; if (succ < last) if (compare(list[succ+1],list[succ]) > 0) /* ascendant order */ succ++; rootptr = list[root]; while ((succ <= last) && (compare(list[succ],rootptr) > 0)) { /* asc. */ list[ptr] = list[succ]; /*copy*/ ptr = succ; succ = 2 * ptr; if (succ < last) if (compare(list[succ+1],list[succ]) > 0) /* ascendant */ succ++; } list[ptr] = rootptr; /*copy*/ } INT4 dummy_func(void *obj) { #if defined (TRACE1) printf("*** dummy function called ***\n"); #endif return 1; } INT4 dummy_func2(void *obj1, void *obj2) { #if defined (TRACE1) printf("*** dummy2 function called ***\n"); #endif return 1; } /****** HshFunc *********************************************************** ** ** computes a hash index for a given string object. ** Needs the hash table manager object ** to get the maximum size of the hash table. ** ** INPUT: address of an existing hash table object [R] ** address of a string object to hash [R] ** IMPLICIT: ** ** RETURNS: the computed hash index */ static INT4 HshFunc (HSHo *table, void *s) { register unsigned long h=0, g; register char *p = (char *) s; while (*p) { h= (h << 4) + *p++; if ((g= (h & 0xf0000000))) h= (h ^ (g >> 24)) ^ g; } #ifdef xxxx while (*s) h = (h<<5) + *s++; /* horner's function ...segdewick */ /* h = (h << 1) ^ *s++; */ #endif return (INT4) h % table->max_hash_elem; } /**api* HshNewTable ******************************************************** ** ** creates and initializes a hash table manager object for a new ** hash table and allocates memory for an array, later used to ** store addresses of objects. ** ** INPUT: maximum size of hash table [R] ** maximum fill in percentage [R] ** address of a hash function [R] ** address of a compare function [R] ** address of a print function [R] ** address of a delete function [R] ** IMPLICIT: ** ** RETURNS: address of the hash table manager object on success, ** NULL otherwise */ HSHo *HshNewTable(INT4 size, INT4 fill, INT4 (*hash_func)(HSHo *, void *), INT4 (*compare_func)(void *, void *), INT4 (*print_func) (void *), INT4 (*delete_func) (void *) ) { INT4 i; HSHo *table = (HSHo*) malloc(sizeof(HSHo)); if (!table) return NULL; /* error handling ... */ /* ** initialize hash table */ if (size > 0) table->max_hash_elem = size; else table->max_hash_elem = HSHxDEFHASHSIZE; if (fill>=50 && fill<=100) table->max_fill = fill; else table->max_fill = HSHxDEFMAXFILL; table->hash_list = (void**)malloc(table->max_hash_elem*sizeof(void*)); if (!table->hash_list) { free(table); return NULL; /* error handling ... */ } table->cur_hash_elem = 0; for (i=0; i < table->max_hash_elem; i++) table->hash_list[i] = HSHxHFREE; table->hash_f = hash_func ? hash_func : HshFunc; table->compare_f = compare_func ? compare_func : dummy_func2; table->print_f = print_func ? print_func : dummy_func; table->delete_f = delete_func ? delete_func : dummy_func; /* ** allow insert and search operations (after compressing ** and sorting disabled !) */ table->insert_search_allowed = 1; return table; } /****** HshHashObject ********************************************************* ** ** puts an existing object into the hash table. ** If there exists a collision with the hash index the next free ** position will be occupied (round robin). ** ** INPUT: address of an existing hash table object [R] ** address of an existing object [R] ** IMPLICIT: ** modifies hash table ** ** RETURNS: 1 */ static INT4 HshHashObject(HSHo *table, void *obj) { INT4 i; INT4 hash_index; /* get hash index */ hash_index = (*table->hash_f)(table, obj); #if defined(TRACE1) printf("hash_index is %d\n", hash_index); #endif /* search for next free place */ for (i=hash_index; imax_hash_elem; i++) if (table->hash_list[i] <= HSHxHFREE) { table->hash_list[i] = obj; /* no entry yet */ table->cur_hash_elem++; return 1; } /* if no free slot until end ...try from begin of table */ for (i=0; ihash_list[i] <= HSHxHFREE) { table->hash_list[i] = obj; /* no entry yet */ table->cur_hash_elem++; return 1; } return 1; } /**api* HshInsertObject **************************************************** ** ** inserts the new object into the hash table. ** If the hash table is not big enough, it will be doubled before ** hashing objects. ** ** INPUT: address of an existing hash table manager object [R] ** address of the new object [R] ** IMPLICIT: ** modifies hash table ** ** RETURNS: 1 if the object has been successfully inserted, ** 0 otherwise */ INT4 HshInsertObject(HSHo *table, void *obj) { INT4 i, rv=1; void **old_hash_list = table->hash_list; INT4 old_max_hash_elem = table->max_hash_elem; if (!table || !obj) { printf("ERROR: hash table or object is NULL\n"); return 0; } /* be sure that hash table is big enough */ if (table->cur_hash_elem > table->max_hash_elem * table->max_fill / 100) { void **tmp; /* extend hash table and rehash all elements in list */ table->max_hash_elem = table->max_hash_elem * 2 + 7; #if defined(TRACE2) printf("*** INFO: Expanding hash table from %d to %d elements ***\n", old_max_hash_elem, table->max_hash_elem); #endif tmp = (void**) malloc(table->max_hash_elem * sizeof(void*)); if (!tmp) return 0; /* no errror message to keep list module independent from other modules */ table->hash_list = tmp; /* use new array */ /* mark all elements as unused */ for (i=0; i < table->max_hash_elem; i++) table->hash_list[i] = HSHxHFREE; table->cur_hash_elem = 0; /* hash all already used old elements */ for (i = 0; i < old_max_hash_elem; i++) if (old_hash_list[i] > HSHxHFREE) /* NULL check would fail */ rv &= HshHashObject(table, old_hash_list[i]); free(old_hash_list); /* free old array */ } /* hash new object */ rv &= HshHashObject(table, obj); return rv; } /**api* HshSearchObject *************************************************** ** ** checks if an object with the same key value as the specified object ** is already in the hash table. ** Passes the address of the found object back to the calling function. ** ** INPUT: address of an existing hash table manager object [R] ** address of an object to search for duplicate [R] ** IMPLICIT: ** ** RETURNS: address of an existing object, if found ** 0 otherwise */ void *HshSearchObject(HSHo *table, void *obj) { void* tmp; INT4 i; INT4 stop_search = 0; INT4 hash_index; if (!table || !obj) { printf("ERROR: hash table or object is NULL\n"); return 0; } /* get hash index for the specified object */ hash_index = (*table->hash_f)(table, obj); #if defined(TRACE1) printf("hash_index is %d\n", hash_index); #endif /* search for object in hash table beginning with hash index */ for (i=hash_index; imax_hash_elem; i++) { tmp = table->hash_list[i]; if (tmp == HSHxHFREE) {stop_search = 1; break;} if (tmp == HSHxHDEL) continue; if (!(*table->compare_f)(tmp, obj)) { /* object found */ return tmp; } } if (!stop_search) for (i=0; ihash_list[i]; if (tmp == HSHxHFREE) {stop_search = 1; break;} if (tmp == HSHxHDEL) continue; if (!(*table->compare_f)(tmp, obj)) { /* object found */ return tmp; } } return 0; /* duplicate object not found */ } /**api* HshRehash ****************************************************** ** ** rehashes a (e.g. sorted) hash table. Inserting of and searching ** for objects is possible again, afterwards. ** ** INPUT: address of an existing hash table manager object [R] ** IMPLICIT: ** modifies hash table ** ** RETURNS: 1 on success, ** 0 otherwise */ INT4 HshRehash(HSHo *table) { INT4 i, rv=1; void **old_hash_list = table->hash_list; INT4 old_max_hash_elem = table->max_hash_elem; void **tmp; if (!table) { printf("*** ERROR: hash table does not exist !!! \n"); return 0; } tmp = (void**) malloc(table->max_hash_elem * sizeof(void*)); if (!tmp) return 0; /* no errror message to keep list module independent from other modules */ table->hash_list = tmp; /* use new array */ /* mark all elements as unused */ for (i=0; i < table->max_hash_elem; i++) table->hash_list[i] = HSHxHFREE; table->cur_hash_elem = 0; /* hash all old elements */ for (i = 0; i < old_max_hash_elem; i++) if (old_hash_list[i]) rv &= HshHashObject(table, old_hash_list[i]); /* ** enable insert and search operations after successful rehashing */ if (rv) { table->insert_search_allowed = 1; free(old_hash_list); /* free old array */ } else { table->hash_list = old_hash_list; free(tmp); } return rv; } /**api* HshCompress ***************************************************** ** ** compresses the specified hash table. Inserting of and searching ** for objects is not possible before rehashing. ** ** INPUT: address of an existing hash table manager object [R] ** IMPLICIT: ** ** RETURNS: 1 on success ** 0 otherwise */ INT4 HshCompress(HSHo *table) { INT4 i,j; void **list; if (!table) { printf("*** ERROR: hash table does not exist !!! \n"); return 0; } /* ** compress hash table */ list = table->hash_list; for (i=0,j=table->max_hash_elem-1; i HSHxHFREE) i++; while (list[j] <= HSHxHFREE) j--; if (i>j) break; list[i] = list[j]; list[j] = NULL; } /* ** disable insert and search operations after compressing */ table->insert_search_allowed = 0; return 1; } /**api* HshSort ********************************************************* ** ** compresses and sorts the specified hash table. ** Inserting of and searching for objects is no more possible. ** ** INPUT: address of an existing hash table manager object [R] ** IMPLICIT: ** ** RETURNS: 1 on success ** 0 otherwise */ INT4 HshSort(HSHo *table) { int rv = 1; if (!table) { printf("*** ERROR: hash table does not exist !!! \n"); return 0; } rv = HshCompress(table); /* ** sort compressed hash table using heap sort */ compare = table->compare_f; /* set global function pointer */ heapsort(table->hash_list, table->cur_hash_elem); /* ** disable insert and search operations after compressing ** and sorting */ table->insert_search_allowed = 0; return rv; } /**api* HshDeleteAll ******************************************************* ** ** HshDeleteAll may be called externally to delete all hashed objects ** inclusive the hash table manager object. A NULL pointer is given back ** to the calling function, so that the old pointer to the hash table ** can not be used anymore. ** ** INPUT: address of an address of an existing hash table object [R,W] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 HshDeleteAll(HSHo **table_pt) { HSHo *table; INT4 i; if ( !table_pt || !(table = *table_pt) ) { printf("*** ERROR: hash table does not exist !!! \n"); return 0; } /* ** delete all objects in the hash table */ for (i=0; i < table->max_hash_elem; i++) { if (table->hash_list[i] <= HSHxHFREE) continue; (*table->delete_f)(table->hash_list[i]); } /* ** delete the hash table array and the manager object */ free(table->hash_list); /* delete hash table */ free(table); /* delete hash table manager object */ /* ** modify the hash table pointer to signal that the hash table ** has been destroyed */ *table_pt = NULL; return 1; } /**api* HshPrintAll *********************************************************** ** ** Prints the attribute values of the hash table manager object and the ** attribute values of all objects in the hash table. ** ** INPUT: address of an existing hash table manager object [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 HshPrintAll(HSHo *table) { INT4 i; if (!table) { printf("*** ERROR: hash table does not exist !!! \n"); return 0; } printf("********** HASH TABLE DUMP *********************\n"); printf("* Table has %d entries:\n", table->cur_hash_elem); printf("* Table could have %d entries:\n", table->max_hash_elem); printf("* Table will be extended, if more than %d %% of the elements used\n", table->max_fill); /* ** print the attribute values of all objects in the hash table */ for (i=0; i < table->max_hash_elem; i++) { if (table->hash_list[i] <= HSHxHFREE) continue; printf("%8d", i); (*table->print_f)(table->hash_list[i]); } return 1; } /**api* HshLength ******************************************************** ** ** returns the current number of elements if the hash table exists. ** ** INPUT: address of an existing hash table object [R] ** IMPLICIT: ** ** RETURNS: current number of elements on success, 0 otherwise */ INT4 HshLength(HSHo *table) { if (!table) { printf("*** ERROR: hash table does not exist !!! \n"); return 0; } #if defined(TRACE1) printf("*** List has %d entries (max. is %d)***\n", table->cur_hash_elem, table->max_hash_elem); #endif return table->cur_hash_elem; } * File: hash_ind.h * implementation of a hash table used for generating indices * * structures and prototypes * *******************************************************************/ /* ** structure definition of the hash table manager object */ typedef struct HSHo { INT4 max_hash_elem; /* max. number of objects in the hash table */ INT4 cur_hash_elem; /* current number of objects in the hash table */ void **hash_list; /* address of an array of void pointers */ /* pointing to the objects. The array is */ /* automatically doubled, if overflow */ INT4 max_fill; /* determines when hash table should be extended */ INT4 insert_search_allowed; /* insert and search allowed (before sort) */ INT4 (*hash_f)(struct HSHo *, void *); /* pointer to hash function */ INT4 (*compare_f)(void *, void *); /* pointer to compare function */ INT4 (*print_f)(void *); /* pointer to print function for objects */ INT4 (*delete_f)(void *); /* pointer to delete function for objects */ /* INT4 isUnused; e.g. HSHxHFREE INT4 isFreed; e.g. HSHxHDEL */ } HSHo; void *HshSearchObject(HSHo *table, void *obj); INT4 HshInsertObject(HSHo *table, void *obj); HSHo *HshNewTable(INT4 size, INT4 fill, INT4 (*hash_func)(HSHo *, void *), INT4 (*compare_func)(void *, void *), INT4 (*print_func) (void *), INT4 (*delete_func) (void *) ) ; INT4 HshRehash(HSHo *table); INT4 HshLength(HSHo *table); INT4 HshPrintAll(HSHo *table); INT4 HshCompress(HSHo *table); INT4 HshSort(HSHo *table); INT4 HshDeleteAll(HSHo **table_pt); char ica__ID[] = "$Id: ica.c,v 1.2 1996/07/18 09:10:23 ulyanov Exp $"; /* ** ** $RCSfile: ica.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/07/18 09:10:23 $ ** $Author: ulyanov $ ** ** $Locker: $ ** $State: Exp $ ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #include #include #include #include "def.h" #include "srs.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _ODD #define _FUNCTION #include "oddclass.h" ICAoSYNTAX *IcaInitSyntax(ICAoSYNTAX *); main(int argc, char **argv) { ARGoLIST *arglist; FILEo *dataFile; ICAoJOB *job; ICAoSYNTAX *syntax; char line[MAXLINESIZE], *tokStr, *name; INT4 printAll, tokCode, c, rv; SrsEnv (); LibOpen ("srs5"); arglist = LibObjByName ("arglist", "try"); argc = ArgGet (arglist, argc, argv); if (argc != 2) { ArgUsage (arglist); _ErrorExit (); } OddInit (def, 1); name = ParGetStr ("syntaxName"); dataFile = FileNew(argv[1]); if( !FileOpen (dataFile) ) _ErrExit2(e__filopenerr, argv[1]); if( !ParGetBool("useIni") ) { syntax = IcaInitSyntax(LibObjByName("syntax", "icarus")); syntax->ign = " \t\n"; job = IcaCreateJob (syntax); IcaNewJob (job, dataFile, NULL); if ( strcmp(name,"") != 0 ) IcaDoJob(job, name); else IcaDoJob(job, "prog"); IcaEndJob (job); VarExec (job->prog); exit(0); } if ( strcmp(name,"") != 0 ) syntax = (ICAoSYNTAX *)LibObjByName ("syntax", name); else syntax = (ICAoSYNTAX*)LibObjByName ("syntax", "icarus"); job = IcaCreateJob (syntax); IcaNewJob (job, dataFile, NULL); IcaGetTokenList ("prog"); IcaEndJob (job); if( job->prog ) VarExec(job->prog); } char ica2c_ID[] = "$Id: ica2c.c,v 1.6 1996/07/14 16:21:14 etzold Exp $"; /* ** $RCSfile: ica2c.c,v $ ** $Revision: 1.6 $ ** $Date: 1996/07/14 16:21:14 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Module Code: i2c ** ** Description ** =========== ** ** Writes out an icarus program into a C program. ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "message.h" #include "sm.h" #include "futil.h" #include "templ.h" #include "strv.h" #include "variable.h" #include "icarus.h" #include "icaarg.h" static char* I2cFunctionName (VARo *var); static void I2cStmnt (VARo *var); static void I2cExpr (VARo *var, INT4 type); static void I2cFor (VARo *var); static void I2cCall (VARo *var, INT4 type, Int4 isConvertOK); static void I2cFunc (VARo *var); static INT4 I2cTypeConvert (INT4 type, INT4 newType); static void I2cProtoTypes (); static struct TEMPLo *i2cTempl=NULL; void I2cSetTemplate (struct TEMPLo *templ) { i2cTempl = templ; } char *I2cProg (VARo *var) { static INT4 funcN=0; static char funcName[100]; VARo **arg; sprintf (funcName, "IcarusProg%d", ++funcN); TemplPrint ("function.head", funcName); /* the first argument has the program name */ for (arg=VarGetArgs (var) + 1; *arg; arg++) I2cStmnt (*arg); TemplPrint ("function.tail"); return funcName; } char *I2cBody (VARo *var) { static INT4 funcN=0; static char funcName[100]; VARo **arg, **arg2; sprintf (funcName, "IcarusBody%d", ++funcN); TemplWith (i2cTempl, "$prog"); TemplPrint ("body.head", funcName); /* the first argument has the program name */ for (arg=VarGetArgs (var); *arg; arg++) { if ((*arg)->isReadFunction && SmEqs (IcaFunctionName ((*arg)->v.intGet), "IopBody")) { for (arg2=VarGetArgs (*arg); *arg2; arg2++) I2cStmnt (*arg2); /* nested body */ } else I2cStmnt (*arg); } TemplPrint ("body.tail"); TemplEndWith (); return funcName; } static void I2cStmnt (VARo *var) { char *funcName; TemplPrint ("stmnt.head"); funcName = I2cFunctionName (var); if (funcName && SmEqs (funcName, "IopFor")) I2cFor (var); else { I2cExpr (var, 0); TemplPrint ("stmnt.tail"); } } static void I2cExpr (VARo *var, INT4 type) { STRv str; INT4 isConvert=0; if (var->type) isConvert = I2cTypeConvert (var->type, type); if (VarGetCode (var) & IARGxCALL) I2cCall (var, type, isConvert); else if (var->isDelayedType || var->isReadFunction) I2cFunc (var); else switch (var->type) { case VARxINT: TemplPrint ("call.argint", VarGetInt (var)); break; case VARxSTRING: TemplPrint ("call.argstr", VarGetStr (var)); break; case VARxSTRV: str = VarGetStrV (var); TemplPrint ("call.argstrv", _Str (StrEncode (&str))); break; case VARxLIST: case VARxOBJECT: TemplPrint ("call.argstr", "NULL"); break; case VARxALIAS: TemplPrint ("call.argvar", VarGetName (var)); break; default: _ErrExit2 (e__unknownoption, "type in I2cCall"); } if (isConvert) TemplPrint ("convert.tail"); } static void I2cCall (VARo *var, INT4 type, Int4 isConvertOK) { VARo **args=VarGetArgs (var); IARGoCOM *com; IARGoVALUE *arg; char *funcName; INT4 k, isConvert=0; funcName = I2cFunctionName (var); if (SmEqs (funcName, "IopExecCom")) com = (IARGoCOM *) VarGetObject (NULL, args[0]); else com = (IARGoCOM *) IargFunc2Com (funcName); if (com->returnType && !isConvertOK) isConvert = I2cTypeConvert (com->returnType, type); TemplPrint ("call.name", com->functionName); if (args[0]) IargBuildArgs (com, &args[1], TRUE); for (k=0; k < com->argsN; k++) { if (!(k == com->argsN)) TemplPrint ("call.argsep"); arg = &com->args[k]; if (arg->isSet) I2cExpr (arg->val, arg->type); else /* argument not defined, default value */ switch (arg->type) { case VARxINT: TemplPrint ("call.argint", arg->defInt); break; case VARxSTRING: case VARxSTRV: case VARxLIST: case VARxOBJECT: case VARxVAR: TemplPrint ("call.argval", "NULL"); break; default: _ErrExit2 (e__unknownoption, "type in I2cCall"); } } TemplPrint ("call.tail"); if (isConvert) TemplPrint ("convert.tail"); } static void I2cFunc (VARo *var) { VARo **arg; IARGoCOM *com; char *funcName; INT4 k; funcName = I2cFunctionName (var); com = (IARGoCOM *) IargFunc2Com (funcName); if (SmEqs (com->name, "=")) { arg=VarGetArgs (var); I2cExpr (arg[0], com->args[0].type); TemplPrint ("binop.="); I2cExpr (arg[1], com->args[1].type); } else { TemplPrint ("call.name", funcName); for (k=0, arg=VarGetArgs (var); *arg; arg++) { TemplPrint ("call.argsep"); if (com) I2cExpr (*arg, com->args[k++].type); else I2cExpr (*arg, 0); } TemplPrint ("call.tail"); } } static void I2cFor (VARo *var) { ; } #define _cvt(x,y) ((x) << 4) +(y) static INT4 I2cTypeConvert (INT4 type, INT4 newType) { if (!newType || type == newType) return 0; switch (_cvt(type, newType)) { case _cvt (VARxALIAS, VARxVAR): return 0; case _cvt (VARxINT, VARxVAR): return 0; /* TemplPrint ("convert.int.var"); break; */ case _cvt (VARxINT, VARxSTRING): TemplPrint ("convert.int.string"); break; case _cvt (VARxSTRING, VARxVAR): TemplPrint ("convert.int.var"); break; case _cvt (VARxSTRING, VARxSTRV): TemplPrint ("convert.string.strv"); break; case _cvt (VARxSTRV, VARxSTRING): TemplPrint ("convert.strv.string"); break; case _cvt (VARxSTRV, VARxVAR): TemplPrint ("convert.strv.var"); break; case _cvt (VARxOBJECT, VARxVAR): TemplPrint ("convert.object.var"); break; case _cvt (VARxVAR, VARxOBJECT): TemplPrint ("convert.var.object"); break; case _cvt (VARxVAR, VARxSTRV): TemplPrint ("convert.var.strv"); break; case _cvt (VARxALIAS, VARxOBJECT): TemplPrint ("convert.alias.object"); break; case _cvt (VARxALIAS, VARxINT): return 0; /* TemplPrint ("convert.alias.int"); break; */ default: printf ("conversion is not possible\n"); exit (0); } return 1; } static char *I2cFunctionName (VARo *var) { if (var->isDelayedType) return IcaFunctionName ((FUNC) var->typeGet); else if (var->isReadFunction) return IcaFunctionName (var->v.intGet); return NULL; } void I2cProtoTypes () { } ** ** $RCSfile: ica2c.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:35 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** */ void I2cOpen (char *fileName); char *I2cProg (VARo *var); char *I2cBody (VARo *var); char icarg_ID[] = "$Id: icaarg.c,v 1.4 1996/07/07 10:59:24 ulyanov Exp $"; /* ** ** $RCSfile: icaarg.c,v $ ** $Revision: 1.4 $ ** $Date: 1996/07/07 10:59:24 $ ** $Author: ulyanov $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** The functions in this module let the user define his own commands in ** icarus command lists. ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include "message.h" #include "sm.h" #include "lst.h" #include "dict.h" #include "templ.h" #include "futil.h" #include "toklist.h" #include "strv.h" #include "variable.h" #include "regexp.h" #include "icarus.h" #include "icaprog.h" #define _INITOBJS #include "icaarg.h" #undef _INITOBJS #define _SRS #include SRSINCLUDE /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions and modulewide variables */ static void IargAddOrder (IARGoCOM *command, IARGoVALUE *arg); static void* IargToKey (DictElem* e) { return (*(IARGoCOM **)e)->name; } extern ICAoJOB *Job; static IARGoCOM *comCurr=NULL; static VARoSTACK *stack; static DICTv comDict=0; static CLASSoDICT IargDictClass = { (ValComparer)strequal, (ValHasher)strhash, (KeyAccessor)IargToKey, NULL, 0 }; IargComStack (IARGoCOM *com, char *option) { static INT4 count=-1; static IARGoCOM *stack[100]; if (option[1] == 'u') {/* push */ if (count >= 100 - 1) _ErrExit3 (f__limitexceeded, "command objects", 100); stack[++count] = comCurr; comCurr = com; } else comCurr = stack[--count]; } void IargInit () { static INT4 isInit=0; IARGoCOM *com; INT4 k, l; if (isInit) return; comDict = DictCreate (&IargDictClass); for (k=0; (*(com = &IARGCOM[k])->name); k++) { DictSet (&comDict, com->name, IARGoCOM*) = com; com->function = IcaGetFunction (com->functionName); } isInit=1; } /**API* IargSetCom ************************************************************ ** ** Declares a new command or overwrites existing command. ** ** INPUT: command object [R] ** command name [R] ** IMPLICIT: ** comDict (DICTv) ** ** RETURNS: */ void IargSetCom (IARGoCOM *com, char *name) { IargInit (); DictSet (&comDict, name, IARGoCOM*) = com; } /**API* IargGetCom ************************************************************ ** ** Gets the command object for specified command name. ** ** INPUT: command name [R] ** IMPLICIT: ** comDict (DICTv) ** ** RETURNS: command object */ IARGoCOM *IargGetCom (char *name) { IARGoCOM **com; IargInit (); com = (IARGoCOM**) DictWith (comDict, name); return com ? *com : NULL; } char *IargGetComName (IARGoCOM *com) { return com->name; } /**API* IargFunc2Com ************************************************************* ** ** Gets the command object for specified C function name. ** ** INPUT: C-function name [R] ** IMPLICIT: ** comDict (DICTv) ** ** RETURNS: command object ** NULL if not found */ IARGoCOM *IargFunc2Com (char *name) { Iter i; IARGoCOM *com; for (i=DictFirst (comDict); i; DictNext (comDict, &i)) { com = DictIn (i, IARGoCOM*); if (SmEqs (com->functionName, name)) return com; } return NULL; } /**API* IargGetArgs *********************************************************** ** ** This function must be called from the C-function associated to ** an Iargrus command in order to obtain the input parameters. ** The first argument specifies the names and order of the arguments, ** the following arguments are pointers that will be set to the ** respective values. ** ** INPUT: name of command within icarus [R] ** name of C function [R] ** IMPLICIT: ** comCurr (IARGoVALUE) ** ** RETURNS: 1 if success ** 0 if not */ INT4 IargGetArgs (char *orderList, ...) { va_list ap; VARo **var, **list, *varSave; IARGoVALUE *arg; STRv *str; char *argName, *s, tmp[132], *opt; void **p; INT4 k, *i, l; if (!comCurr) _ErrExit (e__fatal); else arg = comCurr->args; /* ** initialize order list */ if (!comCurr->orderN) { strcpy (tmp, orderList); /* SmStrTok modifies string */ while ((argName = SmStrTok (tmp, "|"))) { for (k=0; k < comCurr->argsN; k++) { arg = &comCurr->args[k]; if (SmEqs (argName, arg->name)) break; } if (k == comCurr->argsN) { _ErrMsg3 (e__unknownarg, argName, comCurr->name); return 0; } IargAddOrder (comCurr, arg); } } va_start (ap, orderList); for (k=0; k < comCurr->orderN; k++) { arg = comCurr->order[k]; varSave = arg->val; /* save in case it gets changed by underlying function */ /* execute in case it is 'type executed' */ if (arg->isSet) VarGetType (arg->val); if (arg->isSet) arg->val = VarGetVar (varSave, 1); switch (arg->type) { case IARGxSTRING: s = va_arg (ap, char *); if (arg->isSet) strcpy (s, VarGetStr (arg->val)); else *s = '\0'; break; case VARxSTRV: str = va_arg (ap, STRv *); *str = arg->isSet ? VarGetStrV (arg->val) : NULL; break; case IARGxINT: i = va_arg (ap, INT4 *); if (arg->valsN && arg->isSet) { for (opt = VarGetStr (arg->val), l=0; l < arg->valsN; l++) if (SmEqs (opt, arg->vals[l].name)) *i = arg->vals[l].n; } else *i = arg->isSet ? VarGetInt (arg->val) : arg->defInt; break; case IARGxOBJECT: p = va_arg (ap, void **); *p = arg->isSet ? VarGetObject (NULL, VarFreeze(arg->val)) : NULL; break; case IARGxLIST: list = va_arg (ap, VARo **); *list = arg->isSet ? arg->val: NULL; break; case IARGxVAR: var = va_arg (ap, VARo **); *var = arg->isSet ? arg->val : NULL; break; default: break; } } va_end (ap); return 0; } /**API* IargReturn ************************************************************* ** ** This function must be called from the C-function associated to ** an Icarus command in order to obtain the input parameters. ** The first argument specifies the names and order of the arguments, ** the following arguments are pointers that will be set to the ** respective values. ** ** INPUT: name of command within icarus [R] ** name of C function [R] ** IMPLICIT: ** comCurr (IARGoCOM *) [R] ** stack (IARGoSTACK ** ** RETURNS: 1 if success ** 0 if not */ INT4 IargReturn (char *orderList, ...) { static VARo value; va_list ap; VarReset (&value); va_start (ap, orderList); switch (comCurr->returnType) { case IARGxSTRING: VarSetStr (&value, va_arg (ap, char *)); break; case IARGxINT: VarSetInt (&value, va_arg (ap, INT4)); break; case IARGxOBJECT: VarSetObject (NULL, &value, va_arg (ap, void *)); break; default: break; } va_end (ap); VarPushCopy (stack, &value); return 0; } VARo *retVal; INT4 IcaReturn (char *typeName, ...) { static VARo value; STRv str; va_list ap; VarReset (&value); retVal = &value; va_start (ap, typeName); switch (comCurr->returnType) { case VARxSTRING: VarSetStr (&value, va_arg (ap, char *)); break; case VARxSTRV: str = va_arg(ap, STRv); VarSetStrV (&value, str); StrDel (str); break; case VARxINT: VarSetInt (&value, va_arg (ap, INT4)); break; case VARxOBJECT: VarSetObject (NULL, &value, va_arg (ap, void *)); break; case VARxVAR: VarSetVar (&value, va_arg (ap, VARo *)); break; default: _ErrExit2 (e__unknownoption, "type in IcaReturn"); break; } va_end (ap); return 0; } /**api* IargNewCommand ********************************************************* ** ** ** INPUT: name of command within icarus [R] ** name of C function [R] ** IMPLICIT: ** comCurr (IARGoCOM *) [W] ** ** RETURNS: */ IARGoCOM *IargNewCommand (char *name, char *funName, IARGoCOM **c) { #ifdef xxx static INT4 classId=0; if(!classId) LstManageClass (&classId, sizeof (IARGoCOM), NULL, NULL, NULL); LstNewNamed ((void **) c, classId, name); command = *c; command->function = IargGetFunction (funName); command->arg = NULL; command->retVal = NULL; command->unNamedArg = NULL; command->orderN = 0; command->orderAllocN = 0; command->order = NULL; #endif return comCurr; } /**api* IargMakeValue ********************************************************** ** ** ** INPUT: type of value: "arg" or "value" [R] ** name of value [R] ** type of value content: "string", "int", "object" [R] ** flag if value can occur unnamed [R] ** flag if value is required [R] ** name of the class (for value type "object") [R] ** IMPLICIT: ** command (IARGoCOM *) [R] ** ** RETURNS: */ void IargAddValue (char *valType, char *name, char *type, INT4 isUnNamed, INT4 isRequired, char *className) { #ifdef xxx static INT4 classId=0; IARGoVALUE *value; if (!command) _ErrExit2 (e__nocurrentcommand, name); if(!classId) LstManageClass (&classId, sizeof (IARGoVALUE), NULL, NULL, NULL); /* ** create a new value and insert in 'arg' or 'return' list */ switch (tolower (valType[0])) { case 'a': /* argument */ LstNewNamed ((void **) &(command->arg), classId, name); value = command->arg; break; case 'r': /* retVal */ LstNewNamed ((void **) &(command->retVal), classId, name); value = command->retVal; break; default: _ErrExit2 (e__unknownoption, type); } /* ** build the value descriptor */ if (isUnNamed) { if (command->unNamedArg) _ErrExit3 (e__onlyoneunnamed, value->name, command->name); command->unNamedArg = value; } value->isRequired = isRequired; switch (tolower (type[0])) { case 's': /* string */ value->type = IARGxSTRING; break; case 'i': /* int */ value->type = IARGxINT; break; case 'o': /* object */ value->type = IARGxOBJECT; strcpy (value->className, className); break; default: _ErrExit2 (e__unknownoption, type); } #endif } /**api* IargBuildArgs ********************************************************* ** ** ** INPUT: command object [W] ** array of pointers to values (last is NULL pointer) [R] ** IMPLICIT: ** comCurr (IARGoCOM *) [W] ** ** RETURNS: */ void IargBuildArgs (IARGoCOM *com, VARo **val, Int4 isInfo) { IARGoVALUE *arg; VARo *tmp; INT4 k; comCurr = com; if (!com->function && !isInfo) if (!(com->function = IcaGetFunction (com->functionName))) _ErrExit3 (e__objectunknown, "Icarus user function", com->functionName); /* initialize all argument values */ for (k=0; k < comCurr->argsN; k++) comCurr->args[k].isSet = 0; /* process arguments on the stack */ while ((tmp = *val++)) { for (k=0; k < comCurr->argsN; k++) { arg = &comCurr->args[k]; if (SmEqs (arg->name, tmp->name)||(*tmp->name == ':' && arg->isUnnamed)) break; } if (k == comCurr->argsN) { _ErrMsg3 (e__unknownarg, tmp->name, comCurr->name); return; } arg->isSet = 1; arg->val = tmp; } } /**api* IargExecCommand ******************************************************** ** ** ** INPUT: name of command within icarus [R] ** name of C function [R] ** IMPLICIT: ** comCurr (IARGoCOM *) [R] ** stack (VARoSTACK *) [W] ** ** RETURNS: */ void IargExecCommand (char *comName, VARoSTACK *s) { IARGoVALUE *arg; VARo *value; INT4 listSize, k; char *argName; IargInit (); comCurr = DictAt (comDict, comName, IARGoCOM*); stack = s; /* initialize all argument values */ for (k=0; k < comCurr->argsN; k++) comCurr->args[k].isSet = 0; /* process arguments on the stack */ while ((value = VarNextArg (stack, &argName, &listSize))) { for (k=0; k < comCurr->argsN; k++) { arg = &comCurr->args[k]; if (SmEqs (arg->name, argName) || (*argName == ':' && arg->isUnnamed)) break; } if (k == comCurr->argsN) { _ErrMsg3 (e__unknownarg, argName, comCurr->name); return; } arg->isSet = 1; arg->val = value; } (*comCurr->function)(); } /**api* IargAddOrder ********************************************************** ** ** Adds a new element to the dynamically growing order list. ** ** INPUT: name of command within icarus [R] ** name of C function [R] ** IMPLICIT: ** ** RETURNS: */ static void IargAddOrder (IARGoCOM *command, IARGoVALUE *arg) { if (!command->orderAllocN) { if ((command->order = (void *) malloc (2 * sizeof (void *))) == NULL) _ErrExit2 (e__allocfail, "command order list"); command->orderN = 0; command->orderAllocN = 2; } else if (command->orderN >= command->orderAllocN) { command->orderAllocN *= 2; if ((command->order= (void *) realloc (command->order, command->orderAllocN * sizeof (void *))) == NULL) _ErrExit2 (e__allocfail, "command order list"); } command->order[command->orderN++] = arg; } /**api* IargPrintInfo ********************************************************* ** ** Prints out information for all Icarus commands. ** */ void IargPrintInfo () { TEMPLv templ; IARGoCOM *com; IARGoVALUE *arg; INT4 k, l, i; templ = TemplOpen ("SRSICA:srswww.i", NULL); TemplWith (templ, "$icarusCommand"); TemplPrint ("title"); for (k=0; (*(com = &IARGCOM[k])->name); k++) { if (!com->isShow) continue; TemplPrint("head", com->name, com->name, com->rem); if (!com->argsN) TemplPrint ("noArgs"); else { TemplWith (templ, "arglist"); for (l=0; largsN; l++) { arg = &com->args[l]; TemplPrint ("name", arg->name); /* argument type */ TemplWith (templ, "type"); if (arg->valsN) { TemplPrint ("enum.head"); for (i=0; i < arg->valsN; i++) TemplPrint ("enum.value", arg->vals[i].name); TemplPrint ("enum.tail"); } else if (arg->type == VARxOBJECT) TemplPrint (TemplN (arg->type, NULL), arg->className); else TemplPrint (TemplN (arg->type, NULL)); TemplEndWith (); TemplPrint (arg->isUnnamed ? "unnamed" : "named"); TemplPrint (arg->isRequired ? "required" : "optional"); /* default value */ if (arg->defInt) TemplPrint ("defaultNum", arg->defInt); else if (*arg->defaultStr) TemplPrint ("defaultStr", arg->defaultStr); else TemplPrint ("empty"); if (*arg->rem) TemplPrint ("comment", arg->rem); else TemplPrint ("empty"); TemplPrint ("tail"); } TemplEndWith (); } TemplWith (templ, "return"); TemplPrint ("head"); if (com->returnType) { TemplPrint ("preType"); /* return value type */ if (com->returnType) { TemplWith (templ, "$icarusCommand.arglist.type"); if (com->returnType == VARxOBJECT) TemplPrint (TemplN (com->returnType, NULL), com->returnClass); else TemplPrint (TemplN (com->returnType, NULL)); TemplEndWith (); TemplPrint ("postType"); } else TemplPrint ("nothing"); TemplEndWith (); TemplPrint ("tail"); } } TemplEndWith (); } *************************************** ** ** $RCSfile: icaarg.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/07/09 20:38:13 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** */ #include "builtin.h" #define IARGxCALL 16 #define IARGxINDIRECTCALL 32 #define IARGxODD 1 #define IARGxINIT 2 #define IARGxPRE 4 #define IARGxPOST 8 /* this is now exactly the same as the VARxINT...enum - should be replaced */ typedef enum {IARGxINT=1, IARGxSTRING, IARGxOBJECT, IARGxREAL, IARGxALIAS, IARGxVAR, IARGxANY, IARGxSTRV, IARGxLIST=16} IARGeType; typedef struct IARGoCOM *IARGvCOM; /* API */ INT4 IcaGetArgs (char *orderList, ...); struct IARGoCOM *IargFunc2Com (char *name); /* build time */ IARGvCOM IargGetCom (char *name); char *IargGetComName (struct IARGoCOM *com); void IargSetCom (struct IARGoCOM *com, char *name); struct ICAoCOMMAND *IcaNewCommand (char *name, char *funName, struct ICAoCOMMAND **c); void IcaAddValue (char *valType, char *name, char *type, INT4 isUnNamed, INT4 isRequired, char *className); /* ececution time */ typedef struct VARoSTACK *dummytointroducestructtagVARoSTACK; void IcaExecCommand (struct ICAoCOMMAND *command, struct VARoSTACK *stack); void IargBuildArgs (struct IARGoCOM *com, struct VARo **val, Int4 isInfo); /* the extra arguments are in case variables are defined as parameters */ #define _IargCall(com) (*(com)->function)(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) ***************/ char icabnf_ID[] = "$Id: icabnf.c,v 1.13 1996/08/12 11:21:59 etzold Exp $"; /* ** ** $RCSfile: icabnf.c,v $ ** $Revision: 1.13 $ ** $Date: 1996/08/12 11:21:59 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Authors: Anatoly Ulyanov ** Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** ** ** ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include "message.h" #include "regexp.h" #include "futil.h" #include "library.h" #include "sm.h" #include "strv.h" #include "lst.h" #include "variable.h" #include "toklist.h" #include "cursor.h" #include "icaprog.h" #include "icatask.h" #include "icarus.h" #include "icaarg.h" #include "icabnf.h" #include "icadebug.h" #define _ErrCheckJump() if(Job->parseError) return(FALSE) #define _ErrThrow(x) Job->parseError = (x) #define _ErrCatch() Job->parseError = 0 #define _SRS #include SRSINCLUDE extern ICAoJOB *Job; extern VARoStack icaStack2[6]; extern INT4 NameListId; extern ICAoSYNTAX *newSyntax; static INT4 TokCode; /* build time curr token code */ static char *BuffPtr; /* build time Ptr to syntax buff */ static char *BuffBegin; /* save the beginnig of syntax buff */ static char TokStr[10000]; /* build time curr token */ ICAoSYNTAX *Syntax; static INT4 BnfCompareLiteral(CURSORo *, INT4, char *); static INT4 BnfCompareRegExp(CURSORo *, regexp *); static void BnfLinkBnfNet(); static void BnfNextToken(); static void BnfPrintTree(BNFoCHOICE *); static void BnfTrace(INT4, char *, char *); void BnfInitRules (ICAoSYNTAX *, INT4); /**api* BnfBuild ************************************************************** ** ** function calls recursively BnfMakeTree function until all the ** parser syntaxes will be obtained. ** ** INPUT: syntax to build up BNF tree */ void BnfBuild(ICAoSYNTAX *syntax) { FILEo *file; ICAoJOB *job; if (*syntax->cmnt && ! syntax->cmntRe) if ((syntax->cmntRe = RegComp (syntax->cmnt)) == NULL) _ErrExit2 (e__regerror, syntax->cmntRe); if (!FileOpen ((file = FileNew (syntax->fileName)))) _ErrExit2 (e__filnotok, syntax->fileName); job = IcaCreateJob ((ICAoSYNTAX *)LibObjByName ("syntax", "icarus")); IcaNewJob (job, file, NULL); IcaGetTokenList (job, "prog"); syntax->prod = VarGet (&job->scope, "rules"); IcaEndJob (job); IcaExecProg (job); syntax->scope = (VARoSCOPE *)VarCopyScope (job->scope); return; } /****** BnfGetProduction ***************************************************** ** ** if a new name ** allocate memory for production and put into ** production list ** else ** return pointer ** INPUT: production name ** IMPLICIT: ** ** RETURNS: */ BNFoPRODUCTION *BnfGetProduction (ICAoSYNTAX *syntax, char *name, enum classtype type ) { BNFoPRODUCTION *production; if (!syntax) syntax = Syntax; if (syntax->prod) { /* level 3 */ VARo *var; if (!(var = VarGetListAssoc (syntax->prod, name))) production = NULL; else production = VarGetObject (NULL, var); } else if( LstHashSearch((void **) &syntax->prodList, name) ) { if( syntax->prodList->isInit && type == Production) _ErrExit3(e__icabnfGetProd, name, BuffPtr); production = syntax->prodList->pointer; } return(production); } /****** BnfExecTask ************************************************************ ** ** prepare and make local parser task. The parser should parse line ** with instruction and create token list. This list is an input of ** BnfStackProgram ** ** INPUT: string cointains BNF action commands ** corresponding production node pointer ** IMPLICIT: ** ** RETURNS: */ static void BnfExecTask(BNFoPRODUCTION *taskNode) { BNFoPRODUCTION *node; TOKoLIST *inTokList; CURSORo cursorSave; INT4 c; /* output token list of taskNode is input for dependent tasks */ inTokList = taskNode->wrtTokList; for (c=0; (node = TaskNextActiveNode(taskNode->taskLinks, &c));) { CursorSave(&cursorSave, Job->cursor); Job->cursor = CursorNew(); CursorInstall(Job->cursor, TokGetFirst(inTokList), inTokList); BnfParseProdLoop(node); CursorRestore(Job->cursor, &cursorSave); } } /****** BnfParseProduction **************************************************** ** ** parse production: do pre-parsing actions, shift cursor to fist ** non space character, save it position, parse and if the parser ** succeed restore cursor and do post-parsing actions, move cursor ** in new position. ** ** INPUT: production pointer ** IMPLICIT: ** ** RETURNS: TRUE if parser succeed ** FALSE otherwise */ INT4 BnfParseProduction(BNFoPRODUCTION *production) { BNFoNODE *node; CURSORoANCHOR anchor; INT4 rv; Job->currNode = (BNFoNODE *)production; _BnfExecPre (production); if (!Job->doAdvance || CursorAdvance(Job->cursor, Job->syntax->ign, Job->syntax->cmntRe, production->action&BNFxNOSKIP, &Job->doAdvance) ){ CursorDefineAnchor(Job->cursor, &anchor); node = production->node; rv = (*node->parse) (node); if (Job->parseError) switch(Job->parseError) { case(ICAxNEWPARSEERROR): _ErrCatch(); IcaErrPrint(production->name, Job->failPattern, CursorGetBegin(Job->cursor), CursorGetPtr(Job->cursor)); _ErrThrow(ICAxPARSEERROR); /*te!!! why???*/ return(FALSE); break; case(ICAxPARSEERROR): return(FALSE); break; } if( rv == TRUE ) { Job->failPattern = NULL; CursorSetGlobalMatch(Job->cursor, &anchor); _BnfExecPost (production); CursorIncrement(Job->cursor); } if(production->taskLinks) /* should task be executed even if production failed? te!!! */ BnfExecTask(production); return(rv); } return(FALSE); } /****** BnfParseProdLoop **************************************************** ** ** parse production in loop. It takes corresponded token list ** and parse all the token with corresponded token-coder in it, do ** pre-parsing actions, shift cursor to fist non space character, ** save it position, parse and if the parser succeed restore cursor ** and do post-parsing actions, move cursor in new position. ** ** INPUT: production pointer ** IMPLICIT: ** ** RETURNS: TRUE if all tokens was parsed ** FALSE otherwise */ INT4 BnfParseProdLoop(BNFoPRODUCTION *production) { BNFoNODE *node; CURSORoANCHOR anchor; INT4 rv, isExcept; TokRewindList(production->rdTokList); while (TRUE) { Job->currNode = (BNFoNODE *)production; _BnfExecPre (production); if (Job->parseError) { _ErrCatch(); isExcept = 1; } else isExcept =0; if (!isExcept && !Job->doAdvance || CursorAdvance(Job->cursor, Job->syntax->ign, Job->syntax->cmntRe, production->action&BNFxNOSKIP, &Job->doAdvance)){ CursorDefineAnchor(Job->cursor, &anchor); node = production->node; rv = (*node->parse) (node); if(Job->parseError) switch(Job->parseError) { case(ICAxNEWPARSEERROR): _ErrCatch(); IcaErrPrint(production->name, Job->failPattern, CursorGetBegin(Job->cursor), CursorGetPtr(Job->cursor)); continue; break; default: continue; break; } if( rv == TRUE ) { Job->failPattern = NULL; CursorSetGlobalMatch(Job->cursor, &anchor); Job->currNode = (BNFoNODE *)production; _BnfExecPost (production); CursorIncrement(Job->cursor); if(production->taskLinks) BnfExecTask(production); } } else if (!CursorIterate(Job->cursor,Job->syntax->ign, Job->syntax->cmntRe, production->action&BNFxNOSKIP, &Job->doAdvance)) return(TRUE); } } /****** BnfParseProdName ****************************************************** ** ** parse production name: do pre-parsing actions, shift cursor ** to fist non space character, save it position, call the ** production parser and if the parser succeed restore cursor ** and do post-parsing actions, move cursor in new position. if ** production name is optiinal restore the cursor. ** ** INPUT: production name pointer ** IMPLICIT: ** ** RETURNS: TRUE if parser succeed ** FALSE otherwise */ INT4 BnfParseProdName(BNFoPRODNAME *prodName) { BNFoPRODUCTION *production; CURSORo cursorSave; CURSORoANCHOR anchor; INT4 rv; Job->currNode = (BNFoNODE *)prodName; _BnfExecPre (prodName); if(!Job->doAdvance || CursorAdvance(Job->cursor, Job->syntax->ign, Job->syntax->cmntRe, prodName->action&BNFxNOSKIP, &Job->doAdvance) ){ production = prodName->production; if(prodName->optional) { CursorSave(&cursorSave, Job->cursor); Job->isOptional = TRUE; } CursorDefineAnchor(Job->cursor, &anchor); rv = (*production->parse) (production); _ErrCheckJump(); if( rv == TRUE ) { Job->currNode = (BNFoNODE *)prodName; CursorSetGlobalMatch(Job->cursor, &anchor); _BnfExecPost (prodName); CursorIncrement(Job->cursor); } else if(prodName->optional) { Job->isOptional = FALSE; CursorRestore(Job->cursor, &cursorSave); } return(rv); } return(FALSE); } /****** BnfParseRegExp ******************************************************** ** ** parse regular expression: do pre-parsing actions, shift cursor ** to fist non space character, compare input parsing string with ** the regular expression, and if it fits do post-parsing actions, ** move cursor in new position. The "NOT" action has special treatment. ** ** INPUT: regular expression name pointer ** IMPLICIT: ** ** RETURNS: TRUE if regular expression succeed ** FALSE otherwise ** attention! NOT action reverse RETURN value */ INT4 BnfParseRegExp(BNFoREGEXP *pattern) { INT4 rv; Job->currNode = (BNFoNODE *)pattern; _BnfExecPre (pattern); if(!Job->doAdvance || CursorAdvance(Job->cursor, Job->syntax->ign, Job->syntax->cmntRe, pattern->action&BNFxNOSKIP, &Job->doAdvance) ){ rv = BnfCompareRegExp(Job->cursor, pattern->expression); if(pattern->action&BNFxNOT) {/* NOT action is only a probe */ if (!rv) { /* braces, macro! te!!! */ _BnfExecPost (pattern); } return(!rv); /* comparision. no any action ...why not? te!!!*/ } if(rv) { Job->regExp = pattern->expression; _BnfExecPost (pattern); if( Job->isTrace & 1 ) BnfTrace(1, "RegExp", pattern->name); CursorIncrement(Job->cursor); Job->doAdvance = 1; } else { Job->doAdvance = Job->cursor->len ? 1 : 1; Job->failPattern = pattern->name; } return(rv); } return(FALSE); } /****** BnfParseLiteral ******************************************************* ** ** parse literal expression: do pre-parsing actions, shift cursor ** to fist non space character, compare input parsing string with ** the literal expression, and if it fits do post-parsing actions, ** move cursor in new position. The "NOT" action has special treatment. ** ** INPUT: literal expression pointer ** IMPLICIT: ** ** RETURNS: TRUE if literal expression succeed ** FALSE otherwise ** attention! NOT action reverse RETURN value */ INT4 BnfParseLiteral(BNFoLITERAL *literal) { INT4 rv; Job->currNode = literal; _BnfExecPre (literal); if (!Job->doAdvance || CursorAdvance(Job->cursor, Job->syntax->ign, Job->syntax->cmntRe, literal->action&BNFxNOSKIP, &Job->doAdvance) ){ rv = BnfCompareLiteral(Job->cursor, literal->action, literal->name); if(literal->action&BNFxNOT) { /* NOT is only probe */ CursorResetMatch (Job->cursor); return(!rv); /* no action at all! */ } if(rv) { _BnfExecPost (literal); if( Job->isTrace & 1 ) BnfTrace(1, "Literal", literal->name); CursorIncrement(Job->cursor); Job->doAdvance = 1; } else { Job->doAdvance = Job->cursor->len ? 1 : 1; Job->failPattern = literal->name; } return(rv); } return(FALSE); } /****** BnfParseCommand ******************************************************* ** ** parse asterisk expression: do pre-parsing actions do ** post-parsing actions, move cursor in new position. ** ** INPUT: command node pointer ** IMPLICIT: ** ** RETURNS: TRUE if input is expire */ INT4 BnfParseCommand(BNFoNODE *node) { INT4 flag; flag = CursorIsEnd(Job->cursor); Job->currNode = node; _BnfExecPre (node); _BnfExecPost (node); if (Job->parseError) { _ErrCatch(); return 0; } CursorIncrement(Job->cursor); /* program may set a match */ if(flag) return(TRUE); else return( !CursorIsEnd(Job->cursor) ); } /****** BnfParseInputEnd ***************************************************** ** ** check end of the input stream condition. ** It check end of file/token_list ** ** INPUT: end of input node pointer ** IMPLICIT: ** ** RETURNS: TRUE if ther is nothing to read ** FALSE otherwise */ INT4 BnfParseInputEnd(BNFoNODE *node) { Job->currNode = node; if ( CursorAdvance(Job->cursor, Job->syntax->ign, Job->syntax->cmntRe, node->action&BNFxNOSKIP, &Job->doAdvance) ){ _ErrThrow(ICAxPARSEERROR); IcaErrPrint(node->name, ENDOFINPUT, CursorGetBegin(Job->cursor), CursorGetPtr(Job->cursor)); return(FALSE); } else { _BnfExecPre (node); _BnfExecPost (node); return(TRUE); } } /****** BnfParseLineStart ***************************************************** ** ** check the cursor position, if it at the beginning of the line do ** pre/post-parsing action. ** ** INPUT: line start node pointer ** IMPLICIT: ** ** RETURNS: TRUE if literal expression succeed ** FALSE otherwise */ INT4 BnfParseLineStart(BNFoNODE *node) { INT4 rv; Job->currNode = node; rv = CursorIsLineStart(Job->cursor); if( rv == TRUE ) { _BnfExecPre (node); _BnfExecPost (node); CursorIncrement(Job->cursor); /* program may set a match */ } return(rv); } /****** BnfParseTerm ********************************************************** ** ** a term node has a list of nodes that should be parsed ** one by one. In the loop it calls all the nodes and checks the ** return value. The return value can be changed depending on the ** type of node. ** ** INPUT: term node pointer ** IMPLICIT: ** ** RETURNS: TRUE if term succeed ** FALSE otherwise */ INT4 BnfParseTerm(BNFoTERM *term) { INT4 rv, trueCount; BNFoREPORT *factor; BNFoNODE *node; enum repeat counter; rv = TRUE; trueCount = 0; factor = term->factorList; while( factor->node != NULL && rv == TRUE) { node = factor->node; counter = factor->counter; rv = (*node->parse) (node); _ErrCheckJump(); if(rv) trueCount++; switch(counter) { case One: if(trueCount >= 1 && !rv) { _ErrThrow(ICAxNEWPARSEERROR); return(FALSE); } break; case ZeroOrOne: rv = TRUE; break; case ZeroOrMore: if( rv == TRUE ) while( (*node->parse)(node) ); _ErrCheckJump(); rv = TRUE; break; case OneOrMore: if(trueCount >= 1 && !rv) { _ErrThrow(ICAxNEWPARSEERROR); return(FALSE); } if( rv == TRUE ) while( (*node->parse)(node) ); _ErrCheckJump(); break; } factor++; } return(rv); } /****** BnfParseChoice ******************************************************** ** ** a choice node has a list of nodes that should be parsed one by ** one until some of them does not succeed. It calls all the nodes ** and checks the return value. If the return value is TRUE - stop ** and return TRUE. If no one node in choise list did not succeed - ** restore the cursor position and return FALSE ** ** INPUT: choice node pointer ** IMPLICIT: ** ** RETURNS: TRUE if choice succeed ** FALSE otherwise */ INT4 BnfParseChoice(BNFoCHOICE *choice) { INT4 rv; CURSORoANCHOR anchor; BNFoNODE *node, **termList; termList = choice->termList; rv = FALSE; CursorDefineAnchor(Job->cursor, &anchor); while(*termList != NULL && rv == FALSE) { node = *termList; rv = (*node->parse) (node); _ErrCheckJump(); termList++; } return(rv); } /****** BnfCompareLiteral ***************************************************** ** ** compare to strings. One defined by cursor the other is given ** as the argument. If "NOCASE" flag sets on case unsensitive ** comparison will be done. ** ** INPUT: pointer to cursor function ** action flag ** string to compare ** IMPLICIT: ** ** RETURNS: TRUE if strings are equal ** FALSE otherwise */ static INT4 BnfCompareLiteral(CURSORo *cursor, INT4 action, char *literal) { char *string1, *string2; INT4 len, l; len = strlen(literal); if( len > CursorLength(cursor) ) return(FALSE); string1 = literal; string2 = CursorGetPtr(cursor); if(BNFxNOCASE&action) { l = 0; while( (toupper(*string1++) == toupper(*string2++)) && l++ <= len ); if(l != len) return(FALSE); } else if( memcmp(string1, string2, len) != 0) return(FALSE); CursorSetMatch(cursor, len); return(TRUE); } /****** BnfCompareRegExp ****************************************************** ** ** function trys to fit given regular expression to the string ** defined by cursor every time starting from the fist character. ** Every regExp should have ^ at the beginning. To be certain the ** next to last character in the line temporary substitute to NULL. ** ** INPUT: pointer to cursor function ** string to compare ** IMPLICIT: ** ** RETURNS: TRUE if strings are equal ** ** function trys to fit given regular expresiion fo the string defined by cursor. To be certain the next to last character in the line temporary substitude to NULL. ** FALSE otherwise */ static INT4 BnfCompareRegExp(CURSORo *cursor, regexp *regExp) { INT4 rv; CursorRestrictLength(cursor); rv = RegExec(regExp, CursorGetPtr(cursor)); CursorRestoreChar(cursor); if( rv == 1 ) { CursorSetMatch(cursor,(INT4)(regExp->endp[0] - regExp->startp[0])); return(TRUE); } return(FALSE); } /****** BnfTrace ************************************************************** ** ** produce debug output */ static void BnfTrace(INT4 mode, char *tag, char *name) { #define MAXLEN 1000 char *token, *listInName, *listOutName, str[MAXLEN]; INT4 i; token = CursorGetMatchCopy(Job->cursor); i = MIN(MAXLEN-1, strlen(token)); memset(str, 0,MAXLEN); listInName = VarGetStr(VarGet(&Job->scope, VARTOKLISTIN)); listOutName = VarGetStr(VarGet(&Job->scope, VARTOKLISTOUT)); switch(mode) { case 0: printf("Input: %s\n",listInName); break; case 1: printf("Input: %s Output: %s\n", listInName, listOutName); break; } printf("%s shift: %s |%s|\n", tag, name, strncpy(str, token ,i)); } /****** BnfIsNodeActive ******************************************************* ** */ static INT4 BnfIsNodeActive(BNFoNODE *node) { if(node->exec[0] || node->exec[1] || node->exec[2]) return(TRUE); return(FALSE); } /****** BnfPruneTree ********************************************************** ** */ void BnfPruneTree(BNFoNODE *node) { BNFoPRODUCTION *production; BNFoREPORT *report; BNFoNODE *nextNode, **termList; if(node->type == Choice ) { termList = ((BNFoCHOICE *)node)->termList; while( *termList != NULL) { nextNode = *termList; if(nextNode->type == ProdName && !BnfIsNodeActive(nextNode)) { production = BnfGetProduction(Syntax, nextNode->name, ProdName); if( !BnfIsNodeActive((BNFoNODE *)production) ) *termList = BnfGetProduction(Syntax, nextNode->name, ProdName)->node; } else BnfPruneTree(nextNode); termList++; } } else if(node->type == Term) { report = ((BNFoTERM *)node)->factorList; while( report->node != NULL) { nextNode = report->node; if(nextNode->type == ProdName && !BnfIsNodeActive(nextNode)) { production = BnfGetProduction(Syntax, nextNode->name, ProdName); if( !BnfIsNodeActive((BNFoNODE *)production) ) report->node = BnfGetProduction(Syntax, nextNode->name, ProdName)->node; } else BnfPruneTree(nextNode); report++; } } else if(node->type == Production) BnfPruneTree(((BNFoPRODUCTION *)node)->node); LstSetObjCurrent((void **) &Syntax->prodList, node); } /****** BnfLinkBnfNet ********************************************************* ** */ static void BnfLinkBnfNet() { LstFirst((void **) &Syntax->prodList); do { if( !Syntax->prodList->isInit ) _ErrExit2(e__icabnfLinkBnfNet, Syntax->prodList->name); /* BnfPruneTree(Syntax->prodList->pointer); */ } while( LstNext((void **) &Syntax->prodList) ); } /****** BnfPrintTree ********************************************************** ** */ static char *tabs = " "; static INT4 Level = 1; static void BnfPrintTree(BNFoCHOICE *choiceNode) { BNFoREPORT *report; BNFoCHOICE *choice; BNFoTERM *term; BNFoNODE *node, **termList; BNFoPRODUCTION *production, *extendNode; enum repeat counter; char marg[MAXPRINTSIZE], edit[MAXPRINTSIZE]; strcpy(marg, tabs); marg[Level] = '\0'; if(choiceNode->name != NULL) { strcpy(edit,choiceNode->name); SmSwapS(edit,"\n","$"); } printf("%sLevel: %d\n%s%s ", marg, Level, marg, edit); extendNode = (BNFoPRODUCTION *)choiceNode; switch(choiceNode->type) { case ProdName: printf("ProdName\n"); break; case Production: printf("Production\n"); break; case Literal: printf("Literal\n"); break; case Regexp: printf("RegExp\n"); break; case Term: printf("Term\n"); break; case Choice: printf("Choice\n"); break; case Command: printf("Command\n"); break; case LineStart: printf("LineStart\n"); break; default: printf("%s unknown\n" ,marg); break; } Level++; if(choiceNode->type == Production) { production = (BNFoPRODUCTION *)choiceNode; choice = (BNFoCHOICE *)production->node; BnfPrintTree(choice); } else if(choiceNode->type == Choice ) { termList = choiceNode->termList; while( *termList != NULL) { printf("%s======= Choice =======\n", marg); node = *termList; choice = (BNFoCHOICE *)node; BnfPrintTree(choice); termList++; } } else if(choiceNode->type == Term) { term = (BNFoTERM *)choiceNode; report = term->factorList; while( report->node != NULL) { node = report->node; counter = report->counter; switch(counter) { case ZeroOrOne: printf("%s======= ZeroOrOne =======\n", marg); break; case One: printf("%s======= One =======\n", marg); break; case ZeroOrMore: printf("%s======= ZeroOrMore =======\n", marg); break; } choice = (BNFoCHOICE *)node; BnfPrintTree(choice); report++; } } Level--; } /*****************************************************************************/ /* for 2nd bootstrapping of icarus */ /*****************************************************************************/ /******************* making syntax tree **********************************/ static BNFoPRODUCTION *currProduction; INT4 IopBody (VARo *var); BNFoNODE *IopNodeProg_ (Int4 runTime, BNFoNODE *node, VARo *nodeProg) { VARo *prog[3], **stmnt[3], **tmp; INT4 count[3], k, time; if (runTime) IargGetArgs ("node|prog", &node, &nodeProg); /* ** find out how many statements for each execution time ** commands can have multiple execution times! */ count[0]=count[1]=count[2]=0; if (nodeProg) for (tmp = VarGetArgs (nodeProg); *tmp; tmp++){ time = VarGetCode (*tmp); if (time & IARGxINIT) count[0]++; if (time & IARGxPRE) count[1]++; if (time & IARGxPOST || !time) count[2]++; } if (ParGetBool ("icaIsDebug")) { count[1]++; count[2]++; } /* allocate program vars and argument lists */ for (k=0; k < 3; k++) if (count[k]) { prog[k] = VarNew (); stmnt[k] = (VARo **) malloc ((count[k] + 1) * sizeof (void *)); VarSetArgs (prog[k], stmnt[k]); VarSetReadInt (prog[k], (FUNC)IopBody); } else prog[k] = NULL; count[0]=count[1]=count[2]=0; if (ParGetBool ("icaIsDebug")) { stmnt[1][count[1]++] = DbgGetStatement (IARGxPRE); stmnt[2][count[2]++] = DbgGetStatement (IARGxPOST); } /* distribute statements into time specific programs */ if (nodeProg) for (tmp = VarGetArgs (nodeProg); *tmp; tmp++){ time = VarGetCode (*tmp); if (time & IARGxINIT) stmnt[0][count[0]++] = *tmp; if (time & IARGxPRE) stmnt[1][count[1]++] = *tmp; if (time & IARGxPOST || !time) stmnt[2][count[2]++] = *tmp; } for (k=0; k < 3; k++) if (count[k]) stmnt[k][count[k]] = NULL; for (k=0; k < 3; k++) node->exec[k] = prog[k]; if (runTime) IcaReturn ("node", node); else return node; } BNFoNODE *IopProd_ (Int4 runTime) { BNFoPRODUCTION *prod; BNFoNODE *node; prod = (BNFoPRODUCTION *) calloc (sizeof(BNFoPRODUCTION), 1); prod->type = Production; prod->parse = BnfParseProduction; if (runTime) IcaReturn ("node", prod); else return (BNFoNODE*)prod; } VARo *IopEndProd_ (Int4 runTime, BNFoNODE *node, BNFoPRODUCTION *prod) { VARo *var; if (runTime) IargGetArgs ("node|prod", &node, &prod); prod->node = node; var = VarNew (); VarSetObject ("production", var, prod); if (runTime) IcaReturn ("var", var); else return var; } BNFoNODE *IopExpr_ (Int4 runTime) { static VARoStack *stack=NULL; VARo *tmp; BNFoCHOICE *node; INT4 k, l; /* init tmp stack and copy from userstack until NULLNODE is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[3])); k++){ if (((BNFoNODE *) VarGetObject (NULL, VarFreeze(tmp)))->type == NullNode) break; VarPush2 (stack, tmp); } if (k == 1) /* no use creating choice with one node only */ node = (BNFoCHOICE *) VarGetObject (NULL, VarFreeze(VarPop2 (stack))); else { /* create a 'term' node */ node = (BNFoCHOICE *) calloc (sizeof(BNFoCHOICE), 1); node->type = Choice; node->parse = BnfParseChoice; node->termList = malloc ((k+1) * sizeof (BNFoNODE *)); /* pop nodes and assign them to the factor list */ for (l=0; k && (tmp = VarPop2 (stack)); k-- , l++){ node->termList[l] = (BNFoNODE *) VarGetObject (NULL, VarFreeze(tmp)); } node->termList[l] = NULL; } if (runTime) IcaReturn ("node", node); else return (BNFoNODE*)node; } BNFoNODE *IopTerm_ (Int4 runTime) { static VARoStack *stack=NULL; VARo *tmp; BNFoTERM *node; INT4 k, l; /* init tmp stack and copy from userstack until NULLNODE is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[3])); k++){ if (((BNFoNODE *) VarGetObject (NULL, VarFreeze (tmp)))->type == NullNode) break; node = VarGetObject (NULL, VarFreeze(tmp)); VarPush2 (stack, tmp); } if (k == 100000 && !node->counter) /* no use creating term with one node only */ node = (BNFoTERM *) VarGetObject (NULL, VarFreeze(VarPop2 (stack))); else { /* create a 'term' node */ node = (BNFoTERM *) calloc (sizeof(BNFoTERM), 1); node->type = Term; node->parse = BnfParseTerm; node->factorList = malloc ((k+1) * sizeof (BNFoREPORT)); /* pop nodes and assign them to the factor list */ for (l=0; k && (tmp = VarPop2 (stack)); k-- , l++){ tmp->isTypeEval = 1; node->factorList[l].node = (BNFoNODE *) VarGetObject (NULL, VarFreeze(tmp)); node->factorList[l].counter = node->factorList[l].node->counter; } node->factorList[l].node = NULL; } if (runTime) IcaReturn ("node", node); else return (BNFoNODE*)node; } BNFoNODE *IopNullNode_ (Int4 runTime) { static BNFoNODE node; node.type = NullNode; if (runTime) IcaReturn ("node", &node); else return &node; } BNFoNODE *IopProdName_ (Int4 runTime, STRv name, Int4 isLookAhead) { BNFoPRODNAME *node; if (runTime) IargGetArgs ("name|lookahead", &name, &isLookAhead); node = (BNFoPRODNAME *) calloc (sizeof (BNFoPRODNAME), 1); node->name = (char *) malloc (strlen (_Str(name)) + 1); strcpy (node->name, _Str(name)); node->type = ProdName; node->parse= BnfParseProdName; node->optional = isLookAhead; if (runTime) IcaReturn ("node", node); else return (BNFoNODE*)node; } BNFoNODE *IopRegexp_ (Int4 runTime, STRv reStr) { BNFoREGEXP *node; if (runTime) IargGetArgs ("reStr", &reStr); StrDecode (&reStr); node = (BNFoREGEXP *) calloc (sizeof(BNFoREGEXP), 1); node->name = (char *) malloc (strlen (_Str(reStr))+2); node->name[0] = '^'; strcpy (node->name + 1, _Str(reStr)); node->type = Regexp; node->parse = BnfParseRegExp; if ((node->expression = RegComp (node->name)) == NULL) _ErrExit2 (e__regerror, node->name); if (runTime) IcaReturn ("node", node); else return (BNFoNODE*)node; } BNFoNODE *IopLiteral_ (Int4 runTime, STRv litStr) { BNFoLITERAL *node; if (runTime) IargGetArgs ("name", &litStr); StrDecode (&litStr); node = (BNFoLITERAL *) calloc (sizeof (BNFoLITERAL), 1); node->name = (char *) malloc (strlen (_Str(litStr))+1); strcpy (node->name, _Str(litStr)); node->type = Literal; node->parse = BnfParseLiteral; if (runTime) IcaReturn ("node", node); else return (BNFoNODE*)node; } BNFoNODE *IopCommand_ (Int4 runTime) { BNFoNODE *node; node = (BNFoNODE *) calloc (sizeof (BNFoNODE), 1); node->type = Command; node->parse = BnfParseCommand; if (runTime) IcaReturn ("node", node); else return node; } BNFoNODE *IopInputEnd_ (Int4 runTime) { BNFoNODE *node; node = (BNFoNODE *) calloc (sizeof (BNFoNODE), 1); node->type = EndOfInput; node->parse = BnfParseInputEnd; if (runTime) IcaReturn ("node", node); else return node; } BNFoNODE *IopMakeOpt_ (Int4 runTime, BNFoNODE *node, STRv type) { if (runTime) IargGetArgs ("node|t", &node, &type); switch (_Str(type)[2]) { case 'c': /* once */ node->counter = ZeroOrOne; break; case 'l': /* multi */ node->counter = ZeroOrMore; break; case 'e': /* onemore */ node->counter = OneOrMore; break; default: _ErrExit2 (e__unknownoption, _Str(type)); } if (runTime) IcaReturn ("node", node); else return node; } void BnfPrintNode (BNFoNODE *node, INT4 level); void BnfTreeTraverse (BNFoNODE *node, INT4 (*func)(BNFoNODE*, INT4 level), INT4 level) { BNFoPRODUCTION *production; BNFoNODE *nextNode, **term; INT4 k; (*func)((BNFoNODE *) node, level); if (node->type == Choice ) for (term=((BNFoCHOICE *)node)->termList; (nextNode = *term); term++) BnfTreeTraverse (nextNode, func, level+1); else if (node->type == Term) for (k=0; (nextNode = ((BNFoTERM *)node)->factorList[k].node); k++) BnfTreeTraverse (nextNode, func, level+1); else if(node->type == Production) BnfTreeTraverse (((BNFoPRODUCTION *)node)->node, func, level+1); } void BnfLinkProdName (BNFoNODE *node, INT4 level) { BNFoPRODNAME *prodName; Job->currNode = node; /* sets the context for the node programs */ switch (node->type) { case ProdName: prodName = (BNFoPRODNAME *) node; if (!(prodName->production = BnfGetProduction (Syntax, prodName->name, 0))) _ErrMsg3 (e__objectunknown, "production", prodName->name); _BnfExecInit (node); break; case Production: case Literal: case Regexp: case Command: _BnfExecInit (node); break; } } void BnfInitRules (ICAoSYNTAX *syntax, INT4 doPrintTree) { VARo *var; BNFoPRODUCTION *prod; INT4 c; Syntax = syntax; for (c=0; (var = VarNextInList (syntax->prod, &c)); ) { prod = VarGetObject (NULL, var); prod->name = VarGetName (var); if (doPrintTree) BnfTreeTraverse ((BNFoNODE *) prod, (FUNC)BnfPrintNode, 1); BnfTreeTraverse ((BNFoNODE *) prod, (FUNC)BnfLinkProdName, 1); } } INT4 IopParse (Int4 runTime, VARo *prod, STRv str, STRv startName, STRv fileName, Int4 doPrintTree, STRv skip, STRv cmnt) { static ICAoSYNTAX syntax; FILEo *file; BNFoPRODUCTION *start; ICAoJOB *job; if (runTime) IargGetArgs ("prod|string|start|fileName|tree|skip|comment", &prod, &str, &startName, &fileName, &doPrintTree, &skip, &cmnt); if (fileName) { file = FileNew (_Str(fileName)); if (!FileOpen (file)) _ErrExit2 (e__filnotok, _Str (fileName)); } else file = NULL; memset (&syntax, 0, sizeof (ICAoSYNTAX)); syntax.ign = skip ? _Str (skip) : ""; syntax.ignAlt = ""; syntax.cmnt = cmnt ? _Str (cmnt) : ""; syntax.commandSyntax = (ICAoSYNTAX *) LibObjByName ("syntax", "icarus"); syntax.prod = prod; BnfInitRules (&syntax, doPrintTree); job = IcaCreateJob (&syntax); /* retain variable scope of calling context */ job->scope = Job->scope; job->fileName = IcaGetCurrFileName ("progFlag"); if (str) IcaJobSetString (job, _Str(str)); else if (file) IcaJobSetFile (job, file); else _ErrExit2 (e__error, "IopParse"); if (startName) IcaDoJob (job, _Str(startName)); else _ErrExit2 (e__error, "IopParse"); job->scope = NULL; /* scope was 'borrowed' from parent job */ IcaJobDestroy (&job); StrDel (str); StrDel (startName); StrDel (fileName); StrDel (skip); StrDel (cmnt); } char *BnfNodeString (BNFoNODE *node) { static STRv s=NULL; if (!s) s = StrNew (); else StrClear (&s); switch(node->type) { case ProdName: StrPrintf (&s, "PN::%s", node->name); break; case Production: StrPrintf (&s, "P::%s", node->name); break; case Literal: StrPrintf (&s, "L::'%s'", node->name); break; case Regexp: StrPrintf (&s, "RE::/%s/", node->name); break; case Term: StrPrintf (&s, "TERM"); break; case Choice: StrPrintf (&s, "CHOICE"); break; case Command: StrPrintf (&s, "X"); break; default: StrPrintf (&s, "UNKNOWN"); break; } return _Str (StrEncode (&s)); } /******************* making syntax tree - END ********************************/ INT4 BnfSetOpFunctions () { IcaSetFunction("IopProd_", (Func)IopProd_); IcaSetFunction("IopEndProd_", (Func)IopEndProd_); IcaSetFunction("IopExpr_", (Func)IopExpr_); IcaSetFunction("IopTerm_", (Func)IopTerm_); IcaSetFunction("IopNullNode_", (Func)IopNullNode_); IcaSetFunction("IopRegexp_", (Func)IopRegexp_); IcaSetFunction("IopProdName_", (Func)IopProdName_); IcaSetFunction("IopLiteral_", (Func)IopLiteral_); IcaSetFunction("IopCommand_", (Func)IopCommand_); IcaSetFunction("IopInputEnd_", (Func)IopInputEnd_); IcaSetFunction("IopMakeOpt_", (Func)IopMakeOpt_); IcaSetFunction("IopNodeProg_", (Func)IopNodeProg_); IcaSetFunction("IopParse", IopParse); } ** ** $RCSfile: icabnf.h,v $ ** $Revision: 1.4 $ ** $Date: 1996/08/11 22:47:05 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ enum repeat {One, ZeroOrMore, ZeroOrOne, OneOrMore}; enum tokCode {BNFxNAM=1, BNFxCOM, BNFxLSTART, BNFxACT, BNFxLIT, BNFxREG, BNFxEQUAL='=', BNFxEOT='.', BNFxEOS=';'}; enum classtype {Production, ProdName, Literal, Regexp, Term, Choice, Command, LineStart, EndOfInput, ProdLoop, NullNode}; #define BNFxNOACTION 0 /* all action is turned off */ #define BNFxACTION 8 /* an action is associated with token */ #define BNFxNOT 16 /* match inversion */ #define BNFxNOSKIP 32 /* do not skip whitespaces till next token */ #define BNFxNOCASE 64 /* disregard case */ #define BNFxUNIQ 128 /* token must be uniq */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** MACROs for common elements of structures */ #define BASECLASS \ char *name; /* name, literal, regexp ... */ \ enum classtype type; /* Production Regexp Term Choice ... */ \ char dbgBreak; /* for the debugger */ \ enum repeat counter; /* loop counter(), {}, [] or {} */ \ INT4 (*parse)() /* method to parse */ \ #define BASEACTION \ INT4 action; /* action mask */ \ struct TOKoLIST *rdTokList; /* toklist to be read */ \ struct TOKoLIST *wrtTokList; /* toklist where to write */ \ struct PROGo *prog; /* program attached to node */ \ struct VARo *exec[3] /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** definition of main classes */ typedef struct BNFoNODE { BASECLASS; BASEACTION; } BNFoNODE, BNFoLITERAL; typedef struct BNFoPRODUCTION { BASECLASS; BASEACTION; struct BNFoNODE *node; struct TASKoLINKS *taskLinks; } BNFoPRODUCTION; typedef struct BNFoPRODNAME { BASECLASS; BASEACTION; struct BNFoPRODUCTION *production; /* pointer to coresponded production */ INT4 optional; /* optinal `?' operation TRUE/FALSE*/ } BNFoPRODNAME; typedef struct BNFoREGEXP { BASECLASS; BASEACTION; struct regexp *expression; } BNFoREGEXP; typedef struct BNFoTERM { BASECLASS; struct BNFoREPORT *factorList; } BNFoTERM; typedef struct BNFoCHOICE { BASECLASS; struct BNFoNODE **termList; } BNFoCHOICE; typedef struct BNFoREPORT { enum repeat counter; /* loop counter(), {}, [] or {} */ struct BNFoNODE *node; } BNFoREPORT; /* module prototypes ***************************************/ void BnfBuild(ICAoSYNTAX *); INT4 BnfParseProduction(BNFoPRODUCTION *); BNFoPRODUCTION *BnfGetProduction (ICAoSYNTAX *syntax, char *, enum classtype); char *BnfNodeString (struct BNFoNODE *node); #define _BnfExecInit(node) \ if ((node)->exec[0]) \ VarExec ((node)->exec[0]) #define _BnfExecPre(node) \ if (Job->isDebug) IopDebug (PROGxPREPARSE);\ if ((node)->exec[1]) \ VarExec ((node)->exec[1]) #define _BnfExecPost(node) \ if (Job->isDebug) IopDebug (PROGxPOSTPARSE);\ if ((node)->exec[2]) \ VarExec ((node)->exec[2]) char icaop_ID[] = "$Id: icaop.c,v 1.19 1996/08/13 13:42:48 etzold Exp $"; /* ** $RCSfile: icaop.c,v $ ** $Revision: 1.19 $ ** $Date: 1996/08/13 13:42:48 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Authors: Anatoly Ulyanov ** Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include #include #include "message.h" #include "regexp.h" #include "futil.h" #include "sm.h" #include "lst.h" #include "par.h" #include "strv.h" #include "variable.h" #include "toklist.h" #include "cursor.h" #include "icarus.h" #include "icabnf.h" #include "icaarg.h" #include "icaprog.h" #include "print.h" #include "icatask.h" #include "odd.h" #define _SRS #include SRSINCLUDE #define IOPxMARK 111 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external and modulewide variables */ extern ICAoJOB *Job; extern VARoSCOPE *globalScope; extern ICAoSYNTAX *Syntax; static char *currObjId=NULL; VARoSTACK *icaStack[6]={NULL, NULL, NULL, NULL, NULL, NULL}; VARoSTACK *icaStack1[6]={NULL, NULL, NULL, NULL, NULL, NULL}; VARoStack icaStack2[6]; void IcaOpSprintF (SMoBUFF *, char *, VARo *, INT4); /***************** stack for variable.c **************/ VARoStack *VarStackInit (VARoStack *stack) { if (!stack) stack = calloc (1, sizeof (VARoStack)); stack->n = 0; return stack; } void VarPush2 (VARoStack *stack, VARo *var) { *(_addObj (stack->ptr, stack->n, stack->allocN, VARo*)) = var; } VARo *VarPop2 (VARoStack *stack) { return (!stack->n) ? NULL : stack->ptr[--stack->n]; } /*********** end of stack ****************/ /****** IopSystem ************************************************************* ** ** Take the string as a unix command, execute it and return result ** as a string ** ** INPUT: ** ** RETURNS: output of unix command */ INT4 IopSystem() { STRv str; char command[BUFSIZ], s[BUFSIZ]; Int4 flag, fd; FILE *fp; str = StrNew(); IargGetArgs("com|off", command, &flag); if (flag) { fd = open("/dev/null", O_WRONLY); switch(flag) { case 1: /* out */ close(1); dup(fd); break; case 2: /* err */ close(2); dup(fd); break; case 3: /* all */ close(1); dup(fd); close(2); dup(fd); break; } } if((fp = popen(command, "r")) != NULL) while (fgets(s, BUFSIZ, fp) != NULL) StrAppS (&str, s); IcaReturn("strv", str); return(TRUE); } /****** IcaFunSetToken ****************************************************** ** ** Returns the 'current token' as string buffer. */ SMoBUFF *IcaFunSetToken(VARo *arg) { static SMoBUFF *buff; buff = BuffInit (buff, 20); BuffCopyString (buff, CursorGetMatchCopy (Job->cursor)); return buff; } /****** IcaFunSetMatch ****************************************************** */ SMoBUFF *IcaFunSetMatch(VARo *arg) { static SMoBUFF *buff; INT4 number; number = atoi(VarGetName(arg)); buff = BuffInit (buff, 20); BuffCopyNChar(buff, Job->regExp->startp[number], (INT4)(Job->regExp->endp[number] - Job->regExp->startp[number])); BuffCopyChar(buff, '\0'); return(buff); } /****** IcaFunGetFip ********************************************************** ** ** Gets the current file pointer. ** ** INPUT: ** ** RETURNS: */ INT4 IcaFunGetFip () { return (INT4) FileGetFip (Job->file); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Strings Library */ INT4 IcaOpSubStr() { STRv str; Int4 start, len; IargGetArgs("str|s|l", &str, &start, &len); if(len) IcaReturn("strv", StrSub(str, start-1, len)); else IcaReturn("strv", StrRight(str, start-1)); return(TRUE); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** functions for building the icarus interpreted stacks */ #ifdef __ODD INT4 IopObject (VARo *var); INT4 IopReference (VARo *var); #endif #define _Index(x,y) ( ((x)-'a'+1) << 5) +((y)-'a'+1) VARo *IopFile_ (Int4 runTime, VARo *var) { FILEo *file; ICAoJOB *job; VARo *prog; char *fileName; if (runTime) IargGetArgs ("file", &var); fileName = VarGetStr (var); file = FileNew (fileName); if (!FileOpen (file) ) _ErrExit2 (e__filnotok, fileName); /* create new job with current job's syntax */ job = IcaCreateJob (Job->syntax); job->scope = Job->scope; IcaJobSetFile (job, file); IcaGetTokenList (job, "prog"); /* IcaJobDestroy (job);*/ Job->scope = job->scope; job->file = FileDelete (job->file); if (runTime) IargReturn ("var", job->prog); else return job->prog; } VARo *IopRef_ (Int4 runTime, VARo *name, Int4 index) { VARo *var, *val, **args; if (runTime) IargGetArgs("name|opt", &name, &index); var = VarNew (); VarSetReadInt (var, (FUNC)IopReference); args = (VARo **) malloc (2*sizeof (void *)); VarSetArgs (var, args); val = VarNew (); VarSetInt (val, index); args[0] = val; val = VarNew (); VarSetStr (val, VarGetStr (name)); args[1] = val; if (runTime) IcaReturn ("var", var); else return var; } VARo *IopOpnd_ (Int4 runTime, STRv opnd, STRv type) { IARGvCOM com; FUNC function; VARo *var, *istr, **args, *func, *val; char *t; void *tmp; if (runTime) IargGetArgs("opnd|t", &opnd, &type); var = VarNew (); t = _Str (type); switch (_Index(t[0], t[1])) { case _Index('i','n'): /* int */ VarSetType (var, VARxINT); VarSetStr (var, _Str(opnd)); break; case _Index('s','t'): /* string */ VarSetType (var, VARxSTRING); VarSetStr (var, _Str(opnd)); break; case _Index('n','u'): /* null */ VarSetInt (var, 0); break; case _Index('m','a'): /* mark */ VarSetInt (var, 0); VarSetCode (var, IOPxMARK); break; case _Index('i','d'): /* ident */ /* check if the name is a class name */ if (OddIsActive () && (tmp = (void *) OddGetClass (_Str(opnd)))) { OddRegisterObj ((struct SDLoOBJ *) tmp); function = IopObject; VarSetClassName (var, OddGetClassName ((struct SDLoOBJ *) tmp)); VarSetReadType (var, function); VarSetCode (var, IARGxCALL | IARGxODD); } /* or a function name */ else if ((com = IargGetCom (_Str(opnd)))) { if (com->isDirectCall) { VarSetCode (var, IARGxCALL | com->time); switch (com->returnType) { case 1: VarSetReadInt (var, com->function); break; case 2: VarSetReadStr (var, (BFUNC)com->function); break; } args = (VARo **) malloc (1*sizeof (void *)); args[0] = NULL; VarSetArgs (var, args); } else { /* generate new function if call is indirect */ VarSetObject (NULL, var, (void *) com); func = VarNew (); VarSetCode (func, IARGxINDIRECTCALL | IARGxCALL | com->time); VarSetReadType (func, IcaGetFunction ("IopExecCom")); args = (VARo **) malloc (2*sizeof (void *)); args[0] = var; args[1] = NULL; VarSetArgs (func, args); var = func; } } /* else it is a variable */ else { VARo *tmp; var = VarNew (); tmp = VarGet (&Job->scope, _Str(opnd)); VarSetAlias (var, tmp, Job->scope); } break; default: _ErrExit2 (e__unknownoption, type); } VarSetLineN (var, IcaGetCurrLineN ("input")); if (runTime) IcaReturn ("val", var); return var; } Int4 IopGetBinOperator (char *op, VARo *a, VARo *b, Func *func) { IARGoCOM *com; char funcName[80]="IopAss"; if (!(com = IargGetCom (op))) _ErrExit3 (e__objectunknown, "Icarus function", op); if (!(*func = IcaGetFunction (com->functionName))) _ErrExit3 (e__objectunknown, "icarus function", com->functionName); return com->returnType; } VARo *IopBinop_ (Int4 runTime, STRv opName, VARo *a, VARo *b) { Func func; VARo *var, **args; Int4 type; if (runTime) IargGetArgs("op|a|b", &opName, &a, &b); var = VarNew (); VarSetLineN (var, IcaGetCurrLineN ("input")); args = (VARo **) malloc (3*sizeof (void *)); args[0] = a; args[1] = b; args[2] = NULL; VarSetArgs (var, args); switch ((type = IopGetBinOperator (_Str(opName), a, b, &func))) { case VARxINT: VarSetReadInt (var, func); break; case VARxVAR: VarSetReadType (var, func); break; default: _ErrExit2 (e__unknownoption, "type in IopBinop"); } if (runTime) IcaReturn ("var", var); else return var; } VARo *IopInit_ (Int4 runTime, VARo *body) { if (runTime) IargGetArgs("body", &body); VarSetCode (body, VarGetCode (body) | IARGxINIT); if (runTime) IcaReturn ("var", body); else return body; } VARo *IopPre_ (Int4 runTime, VARo *body) { if (runTime) IargGetArgs("body", &body); VarSetCode (body, VarGetCode (body) | IARGxPRE); if (runTime) IcaReturn ("var", body); else return body; } VARo *IopFor_ (Int4 runTime, VARo *i, VARo *c, VARo *u, VARo *b) { FUNC function; VARo *var, **args; var = VarNew (); if (runTime) IargGetArgs("i|c|u|b", &i, &c, &u, &b); if (!(function = IcaGetFunction ("IopFor"))) _ErrExit3 (e__objectunknown, "function", "IopFor"); VarSetReadInt (var, function); args = (VARo **) malloc (4*sizeof (void *)); args[0] = i; args[1] = c; args[2] = u; args[3] = b; VarSetArgs (var, args); VarSetLineN (var, IcaGetCurrLineN ("input")); if (runTime) IcaReturn ("var", var); else return var; } VARo *IopForeach_ (Int4 runTime, VARo *body, VARo *list, VARo *val) { FUNC function; VARo *var, **args; var = VarNew (); if (runTime) IargGetArgs("body|list|var", &body, &list, &val); if (!(function = IcaGetFunction ("IopForeach"))) _ErrExit3 (e__objectunknown, "function", "IopForeach"); VarSetReadInt (var, function); args = (VARo **) malloc (3*sizeof (void *)); args[0] = val; args[1] = list; args[2] = body; VarSetArgs (var, args); VarSetLineN (var, IcaGetCurrLineN ("input")); if (runTime) IcaReturn ("var", var); else return var; } VARo *IopWhile_ (Int4 runTime, VARo *b, VARo *c) { FUNC function; VARo *var, **args; var = VarNew (); if (runTime) IargGetArgs("c|b", &c, &b); if (!(function = IcaGetFunction ("IopWhile"))) _ErrExit3 (e__objectunknown, "function", "IopWhile"); VarSetReadInt (var, function); args = (VARo **) malloc (2*sizeof (void *)); args[0] = c; args[1] = b; VarSetArgs (var, args); VarSetLineN (var, IcaGetCurrLineN ("input")); if (runTime) IcaReturn ("var", var); else return var; } VARo *IopIf_ (Int4 runTime) { static VARoStack *stack=NULL; FUNC function; VARo *var, *tmp, **args; INT4 k, l; var = VarNew (); if (!(function = IcaGetFunction ("IopIf"))) _ErrExit3 (e__objectunknown, "function", "IopIf"); VarSetReadInt (var, function); /* init tmp stack and copy from userstack until NULLNODE is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[0])); k++){ tmp = VarGetVar (tmp, 0); if (VarGetCode (tmp) == IOPxMARK) break; VarPush2 (stack, tmp); } /* allocate a list of pointers to the statements whose number is known now */ args = (VARo **) malloc ((k+1)*sizeof (void *)); VarSetArgs (var, args); /* pop nodes and assign them to the factor list */ for (l=0; k && (tmp = VarPop2 (stack)); k-- , l++){ args[l] = tmp; } args[l] = NULL; VarSetLineN (var, IcaGetCurrLineN ("input")); if (runTime) IcaReturn ("var", var); else return var; } VARo *IopAssoc_ (Int4 runTime, VARo *val, VARo *key) { FUNC function; char *tmp; if (runTime) IargGetArgs("key|val", &key, &val); tmp = malloc (strlen (VarGetStr (key))+1); strcpy (tmp, VarGetStr (key)); SmEdit(tmp, SMxDECODE); VarSetName (val, tmp); if (VarGetCode (val) & (IARGxODD|IARGxCALL)) { /* name is object-id */ VarGetClassName (val); OddIdRegister (OddGetClass (VarGetClassName (val)), tmp); } if (runTime) IcaReturn ("var", val); else return val; } VARo *IopList_ (Int4 runTime) { static VARoStack *stack=NULL; VARo *varList, *tmp; INT4 k; /* init tmp stack and copy from user stack until NULLNODE is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[0])); k++){ tmp = VarGetVar (tmp, 0); if (VarGetCode (tmp) == IOPxMARK) break; VarPush2 (stack, tmp); } /* initialize type of list variable in case there are no nodes to pop. pop nodes and insert them into the list */ for (varList=VarNew (), varList->type = VARxLIST; k && (tmp = VarPop2 (stack)); k--) VarListInsert (varList, tmp); if (runTime) IcaReturn ("var", varList); else return varList; } VARo *IopSelect_ (Int4 runTime, VARo *key, VARo *index, VARo *var) { VARo *val, **args; val = VarNew (); if (runTime) IargGetArgs("key|index|var", &key, &index, &var); args = (VARo **) malloc (2*sizeof (void *)); args[0] = var; if (key) { VarSetReadVar (val, IcaGetFunction ("IopSelectAssoc")); args[1] = key; } else if (index) { VarSetReadVar (val, IcaGetFunction ("IopSelect")); args[1] = index; } VarSetArgs (val, args); if (runTime) IcaReturn ("var", val); else return val; } VARo *IopMakeArg_ (Int4 runTime, VARo *val, VARo *name) { if (runTime) IargGetArgs("val|name", &val, &name); name = VarGetVar (name, 1); VarDefName (val, VarGetStr (name)); if (runTime) IcaReturn ("opnd", val); else return val; } VARo *IopFunc_ (Int4 runTime) { static VARoStack *stack=NULL; VARo *func, *tmp, **args; INT4 k, l, code, lineN; /* init stack and copy from user stack until mark is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[0])); k++){ tmp = VarGetVar (tmp, 0); if (VarGetCode (tmp) == IOPxMARK) { func = VarPop2 (&icaStack2[0]); break; } VarPush2 (stack, tmp); } if (VarIsAlias (func)) { tmp = VarNew (); lineN = VarGetLineN (func); VarSetStr (tmp, VarGetName (VarGetAlias (func, Job->scope))); func = VarNew (); VarSetLineN (func, lineN); args = (VARo **) malloc (2*sizeof (void *)); args[0] = tmp; args[1] = NULL; VarSetArgs (func, args); VarSetCode (func, IARGxINDIRECTCALL | IARGxCALL | IARGxPOST); VarSetReadType (func, IcaGetFunction ("IopExecCom")); } if ((VarGetCode (func)) & IARGxINDIRECTCALL) { args = VarGetArgs (func); /* has already a list with the 'com' object */ args = (VARo **) realloc (args, (k+2)*sizeof (void *)); VarSetArgs (func, args); args++; /* set it past the 'com' object */ } else { args = (VARo **) malloc ((k+1)*sizeof (void *)); VarSetArgs (func, args); } /* pop nodes and assign them to the argument list */ for (l=0; k && (tmp = VarPop2 (stack)); k-- , l++){ args[l] = tmp; } args[l] = NULL; if (runTime) IcaReturn ("var", func); else return func; } INT4 IopProg_ () { static VARoStack *stack=NULL; FUNC function; VARo *prog, *tmp, **args; INT4 k, l; /* init tmp stack and copy from user stack until end mark is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[0])); k++){ tmp = VarGetVar (tmp, 0); if (VarGetCode (tmp) == IOPxMARK) break; VarPush2 (stack, tmp); } /* allocate a list of pointers to the statements whose number is known now */ if (!(function = IcaGetFunction ("IopProg"))) _ErrExit3 (e__objectunknown, "function", "IopProg"); prog = VarNew (); VarSetReadInt (prog, function); args = (VARo **) malloc ((k+2) * sizeof (VARo *)); VarSetArgs (prog, args); /* add file name of program to program variable */ args[0] = VarNew(); if (Job->file) VarSetStr (args[0], FileGetName (Job->file, "full")); /* pop nodes and add them to the statement list */ for (l=1; k && (tmp = VarPop2 (stack)); k--, l++) args[l] = tmp; args[l] = NULL; Job->prog = prog; return 1; } VARo *IopStrMake_ (Int4 runTime) { static VARoStack *stack=NULL; static VARoStack *varStack=NULL; STRv str; VARo *tmp, *var, *val, **args; char *s; INT4 strN, varN, len, l; /* init tmp stack and copy from user stack until end mark is found */ stack = VarStackInit (stack); varStack = VarStackInit (varStack); for (strN=varN=0; (tmp = VarPop2 (&icaStack2[0]));){ tmp = VarGetVar (tmp, 0); if (VarGetCode (tmp) == IOPxMARK) break; if (VarIsAlias (tmp) || VarGetCode (tmp) & IARGxCALL) { VarPush2 (varStack, tmp); varN++; } else { VarPush2 (stack, tmp); strN++; } } /* concatenate the string: '\' at end of line removes the line feed */ str = StrNew (); for (; strN && (tmp = VarPop2 (stack)); strN--) { s = VarGetStr (tmp); len = strlen (s); if (s[len-2] == '\\' && s[len-1] == '\n') s[len-2] = '\0'; StrAppS (&str, s); } StrDecode (&str); var = VarNew (); VarSetStrV (var, str); /* get all variables inside string for interpretation and create new var */ if (varN) { val = var; var = VarNew (); VarSetReadStrV (var, (BFUNC)IcaGetFunction ("IopInterpStr_")); args = (VARo **) malloc ((varN+2)*sizeof (void *)); VarSetArgs (var, args); args[0] = val; for (l=1; varN && (tmp = VarPop2 (varStack)); varN-- , l++){ args[l] = tmp; } args[l] = NULL; } if (runTime) IcaReturn ("var", var); else return var; } VARo *IopBody_ (Int4 runTime) { static VARoStack *stack=NULL; FUNC function; VARo *var, *tmp, **args; INT4 k, l; var = VarNew (); if (!(function = IcaGetFunction ("IopBody"))) _ErrExit3 (e__objectunknown, "function", "IopBody"); VarSetReadInt (var, function); /* init tmp stack and copy from userstack until NULLNODE is found */ stack = VarStackInit (stack); for (k=0; (tmp = VarPop2 (&icaStack2[0])); k++){ tmp = VarGetVar (tmp, 0); if (VarGetCode (tmp) == IOPxMARK) break; VarPush2 (stack, tmp); } /* allocate a list of pointers to the statements whose number is known now */ args = (VARo **) malloc ((k+1)*sizeof (void *)); VarSetArgs (var, args); /* pop nodes and assign them to the factor list */ for (l=0; k && (tmp = VarPop2 (stack)); k-- , l++){ args[l] = tmp; } args[l] = NULL; if (runTime) IcaReturn ("var", var); else return var; } /* functions for level 3 icarus commands */ STRv IopInterpStr_ (VARo *var, STRv str, ...) { va_list ap; VARo **arg; STRv tmp; char *s; INT4 k, i, begin; if (var) { arg=VarGetArgs (var); str = VarGetStrV (arg[0]); } else va_start (ap, str); StrBufChange (&str, 0, 0); for (s = _Str(str), i=0, k=1; s[i];) { i += strcspn (&s[i], "\2"); if (s[i] == '\0') break; else { /* replace the mark with variables content */ tmp = VarGetStrV (var ? arg[k++] : va_arg (ap, VARo*)); StrSubst (&str, i, 1, tmp); i += StrLen (tmp); StrDel (tmp); s = _Str(str); } } if (!var) va_end (ap); return str; } Int4 IopExecCom (VARo *var) { extern VARo *retVal; VARo **args=VarGetArgs (var); IARGvCOM com; STRv str; if (VarType (args[0]) == VARxSTRING) { if (!(com = IargGetCom (VarGetStr (args[0])))) _ErrExit3 (e__objectunknown, "Icarus function",VarGetStr (args[0])); } else com = (IARGvCOM) VarGetObject (NULL, args[0]); IargBuildArgs (com, &args[1], 0); retVal = NULL; IargComStack (com, "push"); _IargCall (com); IargComStack (com, "pop"); if (retVal) { switch (VarType (retVal)) { case 0: /* function returns nothing */ break; case VARxINT: VarSetInt (var, (VarGetInt (retVal))); break; case VARxSTRING: VarSetStr (var, (VarGetStr (retVal))); break; case VARxSTRV: str = VarGetStrV (retVal); VarSetStrV (var, str); StrDel (str); break; case VARxOBJECT: VarSetObject (NULL, var, (VarGetObject (NULL, retVal))); break; case VARxREAL: break; case VARxLIST: VarSetList (var, (VarGetList (retVal))); break; case VARxVAR: var = VarSetVar (var, VarGetVar (retVal, 1)); break; default: _ErrExit2 (e__unknownoption, "type in IopExecCom"); } } return 1; } INT4 IopProg (VARo *var) { static ICAoSYNTAX syntax; static INT4 i2cFlag = TRUE; INT4 k; VARo **arg=VarGetArgs (var); char *fileNameSave = Job->fileName; globalScope = Job->scope; Job->fileName = VarGetStr (arg[0]); for (k=1; arg[k] != NULL; k++) { Job->lineN = VarGetLineN (arg[k]); VarExec (arg[k]); if( *ParGetStr("ica2cName") && i2cFlag) { i2cFlag = FALSE; syntax.prod = VarGet(&globalScope, "rules"); BnfInitRules (&syntax, FALSE); I2cBnfGenerator(syntax.prod); exit(0); } } Job->fileName = fileNameSave; /* nested progs with "file" command */ return 1; } INT4 IopTest () { INT4 x, y; char color[44]; IargGetArgs ("x|y|color", &x, &y, color); printf ("x:%d y:%d color:%s\n", x, y, color); return 1; } INT4 IopBody (VARo *var) { INT4 k; VARo **arg=VarGetArgs (var); for (k=0; arg[k] != NULL; k++) { Job->lineN = VarGetLineN (arg[k]); VarExec (arg[k]); } return 1; } INT4 IopAss (VARo *var, VARo *store, VARo *val) { VARo **arg; INT4 type, tmpInt; STRv str; if (var) { arg = VarGetArgs (var); store = arg[0]; val = arg[1]; } _VarGetType (val, type); switch (type) { case VARxINT: tmpInt = VarGetInt (val); VarSetInt (store, tmpInt); break; case VARxSTRING: VarSetStr (store, VarGetStr (val)); break; case VARxSTRV: str = VarGetStrV (val); VarSetStrV (store, str); StrDel (str); break; case VARxLIST: VarSetList (store, VarGetList (val)); break; case VARxOBJECT: VarSetObject (NULL, store, VarGetObject (NULL, val)); break; case VARxUNKNOWN: _ErrExit3 (e__objectunknown, "variable", VarGetName (val)); default: _ErrExit2 (e__unknownoption, "type in IopAss"); } return 1; } INT4 IopMul (VARo *var) { VARo **args=VarGetArgs (var); return VarGetInt (args[0]) * VarGetInt (args[1]); } INT4 IopAdd (VARo *var , VARo *val1, VARo *val2) { VARo **arg; if (var) { arg = VarGetArgs (var); val1 = arg[0]; val2 = arg[1]; } return VarGetInt (val1) + VarGetInt (val2); } INT4 IopDivide (VARo *var) { VARo **args=VarGetArgs (var); return VarGetInt (args[0]) / VarGetInt (args[1]); } INT4 IopSubt (VARo *var) { VARo **args=VarGetArgs (var); return VarGetInt (args[0]) - VarGetInt (args[1]); } INT4 IopAddAss (VARo *var) { VARo **arg=VarGetArgs (var); if (VarType (arg[0]) == VARxLIST) { VarListInsert (arg[0], VarCopy (arg[1], NULL)); return 0; } else { VarSetInt (arg[0], VarGetInt (arg[0]) + VarGetInt (arg[1])); return VarGetInt (arg[0]); } } INT4 IopEq (VARo *var) { VARo **arg=VarGetArgs (var); INT4 typ1, typ2; typ1 = VarGetType (arg[0]); typ2 = VarGetType (arg[1]); if ((typ1 == VARxSTRING || typ1 == VARxSTRV) || (typ2 == VARxSTRING || typ2 == VARxSTRV)) return SmEqs (VarGetStr (arg[0]), VarGetStr (arg[1])); else return (VarGetInt (arg[0]) == VarGetInt (arg[1])); } INT4 IopNEq (VARo *var) { VARo **arg=VarGetArgs (var); INT4 typ1, typ2; typ1 = VarGetType (arg[0]); typ2 = VarGetType (arg[1]); if ((typ1 == VARxSTRING || typ1 == VARxSTRV) || (typ2 == VARxSTRING || typ2 == VARxSTRV)) return !SmEqs (VarGetStr (arg[0]), VarGetStr (arg[1])); else return !(VarGetInt (arg[0]) == VarGetInt (arg[1])); } INT4 IopLogAnd (VARo *var) { VARo **arg=VarGetArgs (var); INT4 typ1, typ2; if (!VarGetInt (arg[0])) return 0; if (!VarGetInt (arg[1])) return 0; return 1; } INT4 IopLogOr (VARo *var) { VARo **arg=VarGetArgs (var); INT4 typ1, typ2; if (VarGetInt (arg[0])) return 1; if (VarGetInt (arg[1])) return 1; return 0; } INT4 IopLT (VARo *var) { VARo **args=VarGetArgs (var); return (VarGetInt (args[0]) < VarGetInt (args[1])); } INT4 IopGT (VARo *var) { VARo **args=VarGetArgs (var); return (VarGetInt (args[0]) > VarGetInt (args[1])); } INT4 IopFor (VARo *var) { VARo **args=VarGetArgs (var); VarExec (args[0]); while (VarGetInt (args[1])) { VarExec (args[3]); VarExec (args[2]); } return 1; } INT4 IopForeach (VARo *any) { STRv str; VARo *list, *var, *tmp, **arg=VarGetArgs (any); Int4 c; var = arg[0]; list = arg[1]; tmp = list; for (c=0; (tmp = VarGetType (list) == VARxLIST ? VarNextInList (list, &c) : tmp);){ switch (VarGetType (tmp)) { case VARxSTRING: VarSetStr (var, VarGetStr (tmp)); break; case VARxSTRV: str = VarGetStrV (tmp); VarSetStrV (var, str); StrDel (str); break; case VARxINT: VarSetInt (var, VarGetInt (tmp)); break; case VARxOBJECT: VarSetObject (NULL, var, VarGetObject (NULL, tmp)); break; case VARxVAR: VarSetVar (var, VarGetVar (tmp, 0)); break; case VARxLIST: VarSetList (var, VarGetList (tmp)); break; case VARxUNKNOWN: return 0; default: _ErrExit2 (e__unknownoption, "type in IopForeach"); break; } VarExec (arg[2]); if (tmp == list) break; } return 1; } INT4 IopWhile (VARo *var) { VARo **args=VarGetArgs (var); while (VarGetInt (args[1])) { VarGetInt (args[0]); } return 1; } INT4 IopExit () { INT4 val; IargGetArgs ("val", &val); exit (val); } INT4 IopIf (VARo *var) { VARo **arg; for (arg=VarGetArgs (var); *arg; arg++) if (VarGetInt (*arg++)) { VarGetInt (*arg); break; } return 1; } VARo *IopSelect (VARo *var) { VARo **arg=VarGetArgs (var), *val; return (val = VarGetListIndex (VarGetList (arg[0]), VarGetInt (arg[1])-1)); } VARo *IopSelectAssoc (VARo *var) { VARo **arg=VarGetArgs (var), *val; return VarGetListAssoc (arg[0], VarGetStr (arg[1])); } /* only for ODD compiler */ #ifdef __ODD extern ODDoCDEFINE cDefine[100]; extern INT4 cDefineN; INT4 IopCDefine () { char name[80]; INT4 k, n; IargGetArgs("n|name", &n, name); for (k=0; k < cDefineN; k++) if (SmEqs (name, cDefine[k].name)) return; strcpy (cDefine[cDefineN].name, name); cDefine[cDefineN].n = n; cDefineN++; } INT4 IopReference (VARo *var) { VARo **arg=VarGetArgs (var); return OddIdRetrieve (VarGetStr (arg[1]), VarGetInt (arg[0])); } INT4 IopObject (VARo *var) { struct SDLoOBJ *class; VARo *tmp, *attr, **arg=VarGetArgs (var); char *className; void *obj; INT4 c, k; OddInitDepot (); Job->lineN = VarGetLineN (var); className = VarGetClassName (var); if (!(class = (struct SDLoOBJ *)OddGetClass (className))) _ErrExit3 (e__objectunknown, "class", className); OddRegisterObj (class); while (arg && (attr = *arg++)) { if (OddIsPartOfList (class, VarGetRealName (attr))) { for (k=0,c=0; (tmp = VarNextInList (attr, &c)); k++) VarGetType (tmp); OddSetObjListSize (class, VarGetRealName (attr), k); } else OddObjAttribute (class, VarGetRealName (attr), attr); } VarSetObject (NULL, var, (obj = OddFinishObj (class))); if (SmEqs (className, "com")) IargSetCom ((struct IARGoCOM *)obj, IargGetComName ((struct IARGoCOM *)obj)); return 1; } #endif typedef struct { INT4 count; } BNFoLEVEL; INT4 BnfPrintProgs (BNFoNODE *node, SMoBUFF *buff) { VARo **stmnt; INT4 n[3], k; for (k=0, n[0]=n[1]=n[2]=0; k<3; k++) { if (node->exec[k]) { stmnt = VarGetArgs (node->exec[k]); for (n[k]=0; stmnt && *stmnt; stmnt++, n[k]++) ; } } if (n[0]+n[1]+n[2]) BuffPrintF (buff, " Prog:", n[0]); if (n[0]) BuffPrintF (buff, " init=%d", n[0]); if (n[1]) BuffPrintF (buff, " pre=%d", n[1]); if (n[2]) BuffPrintF (buff, " post=%d", n[2]); return (n[0]+n[1]+n[2]); } void BnfPrintNode (BNFoNODE *node, INT4 level) { static SMoBUFF *buff=NULL; static STRv str=NULL; char c; buff = BuffInit (buff, 40); if (!str) str = StrNew (); switch (node->counter) { case 0: c = ' '; break; case ZeroOrOne: c = '?'; break; case ZeroOrMore: c = '*'; break; case OneOrMore: c = '+'; break; } if (node->name) { StrSetS (&str, node->name); StrEncode (&str); } switch(node->type) { case ProdName: BuffPrintF (buff, "ProdName: %s %c", _Str(str), c); BnfPrintProgs (node, buff); break; case Production: BuffPrintF (buff, "Production: %s %c", node->name ? node->name : "?", c); BnfPrintProgs (node, buff); break; case Literal: BuffPrintF (buff, "Literal: '%s' %c", _Str(str), c); BnfPrintProgs (node, buff); break; case Regexp: BuffPrintF (buff, "RegExp: /%s/ %c", _Str(str), c); BnfPrintProgs (node, buff); break; case Term: BuffPrintF (buff, "Term %c", c); break; case Choice: BuffPrintF (buff, "Choice %c", c); break; case Command: BuffPrintF (buff, "Command %c", c); BnfPrintProgs (node, buff); break; case LineStart: BuffPrintF (buff, "LineStart %c", c); break; default: BuffPrintF (buff, "unknown %c", c); break; } printf ("%s\n", BuffFormat (buff, 80, level*4, level*4, NULL)); } INT4 IopPrintProduction (VARo *var) { BNFoPRODUCTION *prod; IargGetArgs("prod", &prod); BnfTreeTraverse ((BNFoNODE *) prod, BnfPrintNode, 1); } INT4 IopPrint (INT4 runTime, VARo *val, FILEo *file, Int4 mode) { STRv str; if (runTime) IargGetArgs("s|f|mode", &val, &file, &mode); str = VarPrintf (val); if (file) fwrite (_Str (str), StrLen (str), 1, file->file); else printf ("%s", _Str (str)); StrDel (str); return 1; } INT4 IopOut (INT4 runTime, STRv name) { char *tableName; if (Job->isBuildTime) { if (runTime) IargGetArgs("name", &name); tableName = name ? _Str(name) : Job->currNode->name; Job->tokList = TokGetList (tableName, &Job->tokList); Job->currNode->wrtTokList = Job->outTokList = Job->tokList; TokSetStyle(Job->currNode->wrtTokList, COPYSTYLE); if (name) StrDel (name); } else /*Job->tokList =*/ Job->outTokList = Job->currNode->wrtTokList; return 1; } INT4 IopNot () { Job->currNode->action |= BNFxNOT; return 1; } INT4 IopNoskip () { Job->currNode->action |= BNFxNOSKIP; return 1; } INT4 IopProd () { BNFoPRODUCTION *prod; char name[80]; IargGetArgs("name", name); if (!(prod = BnfGetProduction (Job->syntax, name, 0))) _ErrMsg3 (e__objectunknown, "production", name); BnfParseProduction (prod); } INT4 IopIn (Int4 runTime, STRv in, STRv codeName, Int4 code, STRv prodName, STRv inFileName, STRv task, STRv countCodeName, VARo *countVar) { static INT4 c = TRUE, tokCount; BNFoPRODUCTION *prod; TOKoLIST *tokList; TOKoTOKEN *tok; INT4 countCode=-1, codeCurr; if (runTime) IargGetArgs("in|c|n|p|file|t|count|var", &in, &codeName, &code, &prodName, &inFileName, &task, &countCodeName, &countVar); /* INIT and PRE time */ if (in) { if (codeName) code = TokStrToCode (_Str(codeName)); if (countCodeName) countCode = TokStrToCode (_Str(countCodeName)); tokList = TokGetList (_Str(in), &Job->tokList); Job->tokList = Job->currNode->rdTokList = tokList; } if (Job->isBuildTime) { if (inFileName) ; else if (task) { if (prodName) prod = BnfGetProduction (NULL, _Str(prodName), 0); else prod = IcaGetSupplyNode (Job->currNode->rdTokList->name); prod->taskLinks = TaskRequestLink (&Job->syntax->taskList, _Str(task), (BNFoPRODUCTION *) Job->currNode, prod->taskLinks); } } /* PRE time only */ else { if (inFileName) { if (!(Job->file = (*Job->inputStreamer) (_Str (inFileName), Job->inputStreamerData))) IcaSetInputEnd (Job); IcaSetInputFile (Job, Job->file); } else if (TokIsListActive (tokList)) { if (countCodeName) { /* client asked for a counter */ if (TokIsListStart (tokList)) tokCount = 0; while ((tok = TokNext (tokList, &c))) { if ((codeCurr = TokGetCode (tok)) == countCode) tokCount++; if (codeCurr == code || code == ICAxUNDEFCODE) { VarSetInt (countVar, tokCount); break; } } Job->inToken = tok; CursorInstall (Job->cursor, tok, tokList); } else { Job->inToken = TokNextWithCode (tokList, code, &c); CursorInstall (Job->cursor, Job->inToken, tokList); } } } if (in) StrDel (in); if (codeName) StrDel (codeName); if (codeName) StrDel (prodName); if (inFileName) StrDel (inFileName); if (task) StrDel (task); if (countCodeName) StrDel (countCodeName); } void IopSetDebug (Int4 runTime, Int4 isOn) { if (runTime) IargGetArgs ("state", &isOn); Job->isDebug = isOn; } void IopDebug (Int4 time) { static STRv str=NULL; BNFoNODE *node; char input[100]; if (!str) str = StrNew (); if (time == PROGxPREPARSE) printf (" * before *\n"); else if (time == PROGxPOSTPARSE) printf (" * after *\n"); if (Job->isDebug) { node = Job->currNode; BnfPrintNode (node, 1); strncpy (input, Job->cursor->current, 50); input[50] = '\0'; StrSetS (&str, input); StrEncode (&str); printf (" Input: |%s|\n", _Str(str)); } } INT4 IopWrt (VARo *var) { TOKoLIST *tokList; char *match, *s=NULL, *c=NULL; INT4 code=0, k, length; VARo **arg=VarGetArgs (var); STRv str=NULL; if (arg) for (k=0; arg[k] != NULL; k++) switch (VarGetRealName (arg[k])[0]) { case 's': str = VarPrintf (arg[k]); s = _Str (str); break; case 'c': case ':': c = VarGetStr (arg[k]); code = TokStrToCode (c); break; case 'n': code = VarGetInt (arg[k]); break; default: _ErrExit2 (e__unknownoption, "IopWrt"); } tokList = Job->outTokList; if (s) TokAdd (tokList, s, strlen (s), code); else { CursorGetMatch (Job->cursor, &match, &length); TokAdd (tokList, match, length, code); } if (str) StrDel (str); return 1; } void IopUniq (VARo *var) { TOKoLIST *tokList; char *match, *s=NULL, *c=NULL; INT4 code=0, k, length; VARo **arg=VarGetArgs (var); STRv str=NULL; if (arg) for (k=0; arg[k] != NULL; k++) switch (VarGetRealName (arg[k])[0]) { case 's': str = VarPrintf (arg[k]); s = _Str (str); break; case 'c': case ':': c = VarGetStr (arg[k]); code = TokStrToCode (c); break; case 'n': code = VarGetInt (arg[k]); break; default: _ErrExit2 (e__unknownoption, "IopWrt"); } tokList = Job->outTokList; if (s) { if (TokIsUniq (tokList, s, (length=strlen(s)), code)) TokAdd (tokList, s, length, code); } else { CursorGetMatch (Job->cursor, &match, &length); if (TokIsUniq (tokList, match, length, code)) TokAdd (tokList, match, length, code); } if (str) StrDel (str); } INT4 IopApp (VARo *var) { VARo **arg=VarGetArgs (var); char *match, *s=NULL; INT4 length, k; STRv str=NULL; if (arg) for (k=0; arg[k] != NULL; k++) switch (VarGetRealName (arg[k])[0]) { case 's': str = VarPrintf (arg[k]); s = _Str (str); break; } if (s) TokAppend (Job->outTokList, s, strlen (s)); else { CursorGetMatch (Job->cursor, &match, &length); TokAppend (Job->outTokList, match, length); } if (str) StrDel (str); } INT4 IopRep (Int4 runTime, VARo *list) { VARo *value; STRv str; if (runTime) IargGetArgs("s", &list); str = VarPrintf (list); CursorReplaceMatch (Job->cursor, _Str (str), StrLen (str)); StrDel (str); } STRv IopStrTrim (Int4 runTime, STRv str, STRv skip) { static char ws[10]=" \n\t"; STRv tStr; char *s, *skipSet; Int4 k, l, len; if (runTime) IargGetArgs("s|skip", &str, &skip); len = StrLen (str); skipSet = skip ? _Str (skip) : ws; s = _Str (str); for (k=0; k < len && strchr (skipSet, s[k]); k++) ; for (l=len-1; l>0 && strchr (skipSet, s[l]); l--) ; len = l-k+1; tStr = StrSub (str, k, len < 0 ? 0 : len); StrDel (str); if (runTime) IcaReturn ("strv", tStr); return tStr; } INT4 IopGetc (VARo *var) { VARo **arg=VarGetArgs (var); CursorSetLength (Job->cursor, VarGetInt (arg[0])); return 1; } void IopRestrictLength (VARo *var) { static BNFoNODE *node=NULL; static Int4 cursorLenSave, tmpLenSave; VARo **arg=VarGetArgs (var); Int4 len; len = arg[0] ? VarGetInt (arg[0]) : 0; if (node != Job->currNode) node = NULL; if (len && Job->currNode) { if (!node) { node = Job->currNode; cursorLenSave = CursorGetLength (Job->cursor); tmpLenSave = CursorSetTmpLength (Job->cursor, len); } else { CursorSetMatch (Job->cursor, CursorGetLength (Job->cursor)); CursorIncrement (Job->cursor); CursorResetLength (Job->cursor, cursorLenSave - tmpLenSave); node = NULL; } } } void IopMove (VARo *var) { VARo **arg=VarGetArgs (var); Int4 len= arg[0] ? VarGetInt(arg[0]) : 0; if (len > CursorGetLength (Job->cursor)) Job->parseError = 1; else { CursorSetLength (Job->cursor, VarGetInt (arg[0])); CursorMove (Job->cursor); } } INT4 IopRequest () { TOKoLIST *tokList, *tokListCurr; char name[80]; IargGetArgs("name", name); tokListCurr = Job->outTokList; tokList = IcaGetTokenList (Job, name); Job->outTokList = tokListCurr; return 1; } INT4 IopJobTokens () { FILEo *outFile; ICAoJOB *job; TOKoLIST *tokList; TOKoTOKEN *tok; char name[80], codeName[80], taskName[80], *s; INT4 c, code, doPrint, withCode; IargGetArgs("job|name|n|code|print|task|withCode|outFile", &job, name, &code, codeName, &doPrint, taskName, &withCode, &outFile); if (*codeName) code = TokStrToCode (codeName); else code = -1; if (IcaIsJobEnd (job)) IcaReturn ("int", 0); else { if (*taskName) IcaSetTask (job, taskName, 1); if ((tokList = IcaGetTokenList (job, name))) if (doPrint) for (c=0; (tok = TokNextWithCode (tokList, code, &c));) { if (withCode) printf ("code: %s string: |%s|\n", TokCodeToStr (TokGetCode (tok)), TokGetStringCopy (tokList, tok)); else { s = TokGetStringCopy (tokList, tok); fwrite (s, strlen (s), 1, outFile ? FileGetFile (outFile) : stdout); } } /* IcaContext ("pop"); */ IcaReturn ("int", 1); } } void IopFail (Int4 runTime) { Job->parseError = 1; Job->doAdvance = 1; } INT4 IopSetSkip (Int4 runTime, Int4 state, STRv ws) { char *tmp; if (runTime) IargGetArgs("state|s", &state, &ws); if (ws) { Job->syntax->ign = malloc (StrLen(ws) + 1); strcpy (Job->syntax->ign, _Str(ws)); StrDel (ws); } if ((!state && *Job->syntax->ign) || (state && !*Job->syntax->ign)) { tmp = Job->syntax->ign; Job->syntax->ign = Job->syntax->ignAlt; Job->syntax->ignAlt = tmp; } } Int4 IopFip (INT4 runTime, Int4 flag) { Int4 fip; if (runTime) IargGetArgs ("switch", &flag); if (flag) FileSetGetFip (Job->file, (flag == 1) ? 1 : 0); else { fip = (Int4) FileGetFip (Job->file); if (runTime) IcaReturn ("int", fip); else return fip; } } STRv IopSubMatch (INT4 runTime, INT4 n) { static STRv str=NULL; if (!str) str = StrNew (); if (runTime) IargGetArgs("n", &n); StrNSetS(&str, Job->regExp->startp[n], (Int4)(Job->regExp->endp[n] - Job->regExp->startp[n])); if (runTime) IcaReturn ("strv", str); else return str; } /* should be called directly */ STRv IopCurrToken (INT4 runTime) { static STRv str=NULL; if (!str) str = StrNew (); StrSetS (&str, CursorGetMatchCopy (Job->cursor)); if (runTime) IcaReturn ("strv", str); else return str; } STRv IopInTokenCode (INT4 runTime) { static STRv str=NULL; if (!str) str = StrNew (); if (Job->inToken) StrSetS (&str, TokCodeToStr (TokGetCode (Job->inToken))); else StrClear (&str); if (runTime) IcaReturn ("strv", str); else return str; } STRv IopInToken (INT4 runTime, Int4 n) { static STRv str=NULL; if (runTime) IargGetArgs ("n", &n); if (!str) str = StrNew (); else StrClear (&str); if (n) StrAppN (&str, Job->cursor->current, n); else StrSetS (&str, Job->cursor->current); if (runTime) IcaReturn ("strv", str); else return str; } char *IopKey () { static STRv str=NULL; VARo *val; char *tmp; if (!str) str = StrNew (); else StrClear (&str); IargGetArgs ("val", &val); if ((tmp = VarGetName (val))) StrSetS (&str, tmp); IcaReturn ("strv", str); } void IopPush_ (INT4 runTime, VARo *var, INT4 stackN) { VARoStack *stack; if (runTime) IargGetArgs ("value|stack", &var, &stackN); VarPush2 (&icaStack2[stackN], VarDuplicate(var)); } VARo *IopPop_ (INT4 runTime, INT4 stackN) { VARo *var; if (runTime) IargGetArgs ("stack", &stackN); if (!(var = VarPop2 (&icaStack2[stackN]))) _ErrExit2 (e__icastackempty, stackN); if (runTime) IcaReturn ("var", var); else return var; } INT4 IopPush (INT4 runTime, VARo *var, INT4 stackN) { VARoSTACK *stack; VARo *tmp; if (runTime) IargGetArgs ("value|stack", &var, &stackN); stack = icaStack[stackN]; if (!stack) { stack = VarStackNew (10); icaStack[stackN] = stack; } tmp = VarPushNew (stack); switch (VarGetType (var)) { case VARxSTRING: VarSetStr (tmp, VarGetStr (var)); break; case VARxINT: VarSetInt (tmp, VarGetInt (var)); break; case VARxOBJECT: VarSetObject (NULL, tmp, VarGetObject (NULL, var)); break; case VARxSTRV: VarSetStr (tmp, VarGetStr (var)); break; default: _ErrExit2 (e__unknownoption, "type in IopPush"); } } VARo *IopPop (INT4 runTime, INT4 stackN) { VARo *var; if (runTime) IargGetArgs ("stack", &stackN); if (!icaStack[stackN] || !(var = VarPop (icaStack[stackN]))) _ErrExit2 (e__icastackempty, stackN); if (runTime) IcaReturn ("var", var); else return var; } INT4 IopSetFunctions () { FUNC function; char name[132]; IargGetArgs ("name", name); if (!(function = IcaGetFunction (name))) _ErrExit3 (e__objectunknown, "function", name); (*function)(); return 1; } /* gcg programs */ INT4 GCGWordsearch () { static SMoBUFF *buff=NULL; FUNC function; char inFile1Name[132], inFile2Name[132]; buff = BuffInit (buff, 100); IargGetArgs ("inFile1|inFile2", inFile1Name, inFile2Name); BuffPrintF (buff, "wordsearch "); BuffPrintF (buff, "-infile1=%s ", inFile1Name); BuffPrintF (buff, "-infile2=%s ", inFile2Name); BuffPrintF (buff, "-def "); printf ("%s\n", BuffGetPtr (buff)); system (BuffGetPtr (buff)); return 1; } INT4 IopParDel (Int4 runTime, STRv name) { if (runTime) IargGetArgs ("name", &name); if (name) { ParDeleteMatch (_Str (name)); StrDel (name); } } INT4 IopParStr (Int4 runTime, STRv name, STRv set) { if (runTime) IargGetArgs ("name|set", &name, &set); if (set) { ParDefStr (_Str(name), _Str(set)); StrDel (set); } else IcaReturn ("strv", StrCpyS (ParGetStr (_Str(name)))); StrDel (name); } INT4 IopParInt (Int4 runTime, STRv name, Int4 set) { if (runTime) IargGetArgs ("name|set", &name, &set); if (set != 2) ParDefNum (_Str(name), set); else IcaReturn ("int", ParGetNum (_Str(name))); StrDel (name); } INT4 IopHtmlSpace () { static SMoBUFF *buff=NULL; INT4 bigN, sn=0, n, ln=0, s, l; buff=BuffInit (buff, 20); /* question: represent a number n of 1/4 or 1/3 characters by a combination of 3/4 and 4/4 or 2/3 and 3/3 resp. solution: s is the smaller of 3,4 or 2,3 -> 3 or 2 l is the larger of the pair -> 3 or 4 sn, ln refers to the numbers in the combination ln = n % s; sn = n - (ln*l) / s */ /* s=3; l=4;*/ IargGetArgs ("thirds|s|l", &n, &s, &l); if (n == s) sn = 1; else if (n == l && n < 2*s) /* an approximation here */ ln = 1; else if (n >= 2*s) if (n) { ln = n%s; sn = (n - ln*l) / s; } if (ln) BuffFill (buff, ln, ' '); if (sn) { BuffCopyString (buff, ""); BuffFill (buff, sn, ' '); BuffCopyString (buff, ""); } IcaReturn ("string", BuffGetPtr (buff)); } INT4 IopStrlen () { char s[500]; IargGetArgs ("s", s); IcaReturn ("int", strlen(s)); } INT4 IopFileOpen () { FILEo *file; STRv name; STRv mode; IargGetArgs ("name|mode", &name, &mode); file = FileNew (_Str(name)); if (mode && tolower ((_Str(mode))[0]) == 'w') FileSetWrite (file); if (!FileOpen (file) ) _ErrExit2 (e__filnotok, _Str(name)); StrDel (name); StrDel (mode); IcaReturn ("file", file); } void IopFileClose () { FILEo *file; IargGetArgs ("file", &file); if (file) { FileDelete (file); } } ICAoJOB *IopJobNew (Int4 runTime, VARo *prod, STRv skip, STRv comment, FILEo *file, STRv str, Int4 doShow, Int4 doTree) { ICAoSYNTAX *syntax; ICAoJOB *job; if (runTime) IargGetArgs ("prod|skip|comment|file|str|show|tree", &prod, &skip, &comment, &file, &str, &doShow, &doTree); /* new syntax object */ if ((syntax = (ICAoSYNTAX *) calloc (sizeof(ICAoSYNTAX), 1)) == NULL) _ErrExit2 (e__allocfail, "syntax object");; syntax->ign = skip ? _Str (skip) : ""; syntax->ignAlt = ""; syntax->cmnt = comment ? _Str (comment) : ""; syntax->prod = prod; /* new job object */ if ((job = (ICAoJOB *) calloc (sizeof(ICAoJOB), 1)) == NULL) _ErrExit2 (e__allocfail, "job object"); IcaContext ("push", &job); job->syntax = syntax; job->isBuildTime = 1; BnfInitRules (syntax, doTree); job->isBuildTime = 0; IcaContext ("pop", NULL); if (file) IcaJobSetFile (job, file); else if (str) IcaJobSetString (job, _Str (str)); if (runTime) IcaReturn ("job", job); else return job; } INT4 IopJobNext (Int4 runTime, ICAoJOB *job, FILEo *file) { if (runTime) IargGetArgs ("job|file", &job, &file); if (file) IcaJobSetFile (job, file); IcaJobNext (job); } INT4 IopJobEnd () { ICAoJOB *job; IargGetArgs ("job", &job); IcaEndJob (job); } void IopBreak () { Job->currNode->dbgBreak = IARGxPRE | IARGxPOST; } void IopContinue () { DbgSetContinue (); } void IopNext () { DbgSetNext (); } void EntryIopSetFieldFormat (); INT4 QuerySetFunctions (); INT4 SeqIopNew (); INT4 SeqIopApp (); INT4 SeqIopPrint (); INT4 SeqIopMake (); /****** IcaOpLibrary ****************************************************** */ INT4 IcaOpLibrary() { /* for icarus interpreter */ IcaSetFunction("IcaOpSubStr", (FUNC)IcaOpSubStr); /* for icarus interpreter but level 4 */ IcaSetFunction("IopLst_", (Func)IopList_); IcaSetFunction("IopProg_", (Func)IopProg_); IcaSetFunction("IopBinop_", (Func)IopBinop_); IcaSetFunction("IopStrMake_", (Func)IopStrMake_); IcaSetFunction("IopPush_", (Func)IopPush_); IcaSetFunction("IopPop_", (Func)IopPop_); IcaSetFunction("IopOpnd_", (Func)IopOpnd_); IcaSetFunction("IopAssoc_", (Func)IopAssoc_); IcaSetFunction("IopBody_", (Func)IopBody_); IcaSetFunction("IopSelect_", (Func)IopSelect_); IcaSetFunction("IopFunc_", (Func)IopFunc_); IcaSetFunction("IopMakeArg_", (Func)IopMakeArg_); IcaSetFunction("IopRef_", (Func)IopRef_); IcaSetFunction("IopPre_", (Func)IopPre_); IcaSetFunction("IopInit_", (Func)IopInit_); IcaSetFunction("IopFor_", (Func)IopFor_); IcaSetFunction("IopForeach_", (Func)IopForeach_); IcaSetFunction("IopWhile_", (Func)IopWhile_); IcaSetFunction("IopIf_", (Func)IopIf_); IcaSetFunction("IopFile_", (Func)IopFile_); /* new level 3 icarus commands */ IcaSetFunction("IopSystem", (FUNC)IopSystem); IcaSetFunction("IopInterpStr_", (FUNC)IopInterpStr_); IcaSetFunction("IopTest", (FUNC)IopTest); IcaSetFunction("IopExecCom", (FUNC)IopExecCom); IcaSetFunction("IopProg", (FUNC)IopProg); IcaSetFunction("IopBody", (FUNC)IopBody); IcaSetFunction("IopFor", (FUNC)IopFor); IcaSetFunction("IopForeach", (FUNC)IopForeach); IcaSetFunction("IopIf", (FUNC)IopIf); IcaSetFunction("IopWhile", (FUNC)IopWhile); IcaSetFunction("IopExit", (FUNC)IopExit); IcaSetFunction("IopMul", (FUNC)IopMul); IcaSetFunction("IopAdd", (FUNC)IopAdd); IcaSetFunction("IopDivide", (FUNC)IopDivide); IcaSetFunction("IopSubt", (FUNC)IopSubt); IcaSetFunction("IopAss", (FUNC)IopAss); IcaSetFunction("IopAddAss", (FUNC)IopAddAss); IcaSetFunction("IopEq", (FUNC)IopEq); IcaSetFunction("IopNEq", (FUNC)IopNEq); IcaSetFunction("IopLogAnd", (FUNC)IopLogAnd); IcaSetFunction("IopLogOr", (FUNC)IopLogOr); IcaSetFunction("IopLT", (FUNC)IopLT); IcaSetFunction("IopGT", (FUNC)IopGT); IcaSetFunction("IopSetSkip", (FUNC)IopSetSkip); IcaSetFunction("IopSelect", (FUNC)IopSelect); IcaSetFunction("IopSelectAssoc", (FUNC)IopSelectAssoc); IcaSetFunction("IopPrintProduction", (FUNC)IopPrintProduction); IcaSetFunction("IopPrint", (FUNC)IopPrint); IcaSetFunction("IopOut", (FUNC)IopOut); IcaSetFunction("IopIn", (FUNC)IopIn); IcaSetFunction("IopGetc", (FUNC)IopGetc); IcaSetFunction("IopRestrictLength", (FUNC)IopRestrictLength); IcaSetFunction("IopMove", (FUNC)IopMove); IcaSetFunction("IopWrt", (FUNC)IopWrt); IcaSetFunction("IopUniq", (FUNC)IopUniq); IcaSetFunction("IopApp", (FUNC)IopApp); IcaSetFunction("IopRep", (FUNC)IopRep); IcaSetFunction("IopNot", (FUNC)IopNot); IcaSetFunction("IopProd", (FUNC)IopProd); IcaSetFunction("IopNoskip", (FUNC)IopNoskip); IcaSetFunction("IopRequest", (FUNC)IopRequest); IcaSetFunction("IopJobTokens", (FUNC)IopJobTokens); IcaSetFunction("IopFileOpen", (FUNC)IopFileOpen); IcaSetFunction("IopFileClose", (FUNC)IopFileClose); IcaSetFunction("IopCurrToken", (FUNC)IopCurrToken); IcaSetFunction("IopInTokenCode", (FUNC)IopInTokenCode); IcaSetFunction("IopInToken", (FUNC)IopInToken); IcaSetFunction("IopFail", (FUNC)IopFail); IcaSetFunction("IopFip", (FUNC)IopFip); IcaSetFunction("IopKey", (FUNC)IopKey); IcaSetFunction("IopPush", (FUNC)IopPush); IcaSetFunction("IopPop", (FUNC)IopPop); IcaSetFunction("IopSubMatch", (FUNC)IopSubMatch); IcaSetFunction("IopSetFunctions", (FUNC)IopSetFunctions); IcaSetFunction("IopCDefine", (FUNC)IopCDefine); IcaSetFunction("IopHtmlSpace", (FUNC)IopHtmlSpace); IcaSetFunction("IopStrlen", (FUNC)IopStrlen); IcaSetFunction("IopStrTrim", (FUNC)IopStrTrim); IcaSetFunction("IopJobNew", (FUNC)IopJobNew); IcaSetFunction("IopJobNext", (FUNC)IopJobNext); IcaSetFunction("IopJobEnd", (FUNC)IopJobEnd); IcaSetFunction("IopParStr", (FUNC)IopParStr); IcaSetFunction("IopParInt", (FUNC)IopParInt); IcaSetFunction("IopParDel", (FUNC)IopParDel); IcaSetFunction("IopSetDebug", (FUNC)IopSetDebug); IcaSetFunction("IopBreak", (FUNC)IopBreak); IcaSetFunction("IopContinue", (FUNC)IopContinue); IcaSetFunction("IopNext", (FUNC)IopNext); IcaSetFunction("QuerySetFunctions", (FUNC)QuerySetFunctions); IcaSetFunction("GCGWordsearch", (FUNC)GCGWordsearch); IcaSetFunction("SeqIopNew", (FUNC)SeqIopNew); IcaSetFunction("SeqIopApp", (FUNC)SeqIopApp); IcaSetFunction("SeqIopPrint", (FUNC)SeqIopPrint); IcaSetFunction("SeqIopMake", (FUNC)SeqIopMake); IcaSetFunction("EntryIopSetFieldFormat", (FUNC)EntryIopSetFieldFormat); return(TRUE); } #include #include #include "message.h" #include "sm.h" #include "dict.h" #include "strv.h" #include "variable.h" #include "icarus.h" #include "icabnf.h" #include "icaarg.h" #define _SRS #include SRSINCLUDE typedef struct IDBGoStatus { ICAoJOB *job; struct DBGoBreak *breaks; Int4 breaksN; Int4 breaksAllocN; Int4 isNext; Int4 isBreak; Int4 isContinue; Int4 time; } DBGoStatus; extern ICAoJOB *Job; static DBGoStatus dbgStatusBuff; static DBGoStatus *dbgStatus=&dbgStatusBuff; void DbgSetNext () { dbgStatus->isBreak = 1; dbgStatus->isContinue = 1; } void DbgSetContinue () { dbgStatus->isBreak = 0; dbgStatus->isContinue = 1; } Int4 DbgIsBreak (DBGoStatus *dbgStatus) { if (dbgStatus->isBreak) { dbgStatus->isBreak = 0; return 1; } else if (dbgStatus->time & dbgStatus->job->currNode->dbgBreak) return 1; else return 0; } Int4 DbgIsContinue (DBGoStatus *dbgStatus) { if (dbgStatus->isContinue) { dbgStatus->isContinue = 0; return 1; } else return 0; } static Int4 DbgIopStatement (VARo *var) { VARo **arg=VarGetArgs (var); Int4 time; char command[500]; time = VarGetInt (arg[0]); dbgStatus->job = Job; dbgStatus->time = time; if (DbgIsBreak (dbgStatus)) { while (!DbgIsContinue (dbgStatus)) { printf ("[%s::%s]> ", BnfNodeString (Job->currNode), time == IARGxPRE ? "pre" : "post"); gets (command); IcaEvalInJob (command, Job); } } } VARo *DbgGetStatement (Int4 time) { VARo **args, *stmnt = VarNew (), *val; /* one argument with execution time */ args = (VARo **) malloc (2*sizeof (void *)); val = VarNew (); VarSetInt (val, time); args[0] = val; args[1] = NULL; VarSetArgs (stmnt, args); VarSetCode (stmnt, IARGxCALL | IARGxPOST); VarSetReadInt (stmnt, (Func)DbgIopStatement); return stmnt; } #include #include #include #include #include #define DECLARE_ONLY #define DEFIGNORE " \n\t" #define DEFCOMMENT "^#[^\n]*\n" #include "srs.h" #include "regexp.h" static VARoSCOPE *scope = NULL; extern ICAoJOB *Job; extern ICAoSYNTAX *Syntax; INT4 BnfParseProduction(BNFoPRODUCTION *); INT4 BnfParseProdLoop(BNFoPRODUCTION *); INT4 BnfParseRegExp(BNFoREGEXP *); INT4 BnfParseLiteral(BNFoLITERAL *); INT4 BnfParseCommand(BNFoNODE *); INT4 BnfParseLineStart(BNFoNODE *); INT4 BnfParseInputEnd(BNFoNODE *); INT4 BnfParseTerm(BNFoTERM *); INT4 BnfParseChoice(BNFoCHOICE *); INT4 BnfParseProdName(BNFoPRODNAME *); void BnfPruneTree(BNFoNODE *); VARo *IopPop_(INT4, INT4); VARo *IopBody_ (Int4 runTime); STRv IopInterpStr_(VARo *var, STRv str, ...); STRv IopInterpStr2(VARo *var, STRv str, ...); STRv IopSubMatch(INT4, INT4); STRv IopCurrToken(); /* Declaration of C variables used by some translated functions */ VARo *a, *b, *c, *d, *e, *u, *i; Int4 opt; INT4 IcarusBody1 () { IopOut (0, NULL); } INT4 IcarusBody2 () { IopOut (0, NULL); IopFip (0, 1); IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody3 () { IopProg_ (0); } INT4 IcarusBody4 () { TemplIcaAddLabel (0, IopSubMatch (0, 1), IopFip (0, 0)); } INT4 IcarusBody5 () { IopNoskip (0); } INT4 IcarusBody6 () { IopProg_ (0); } INT4 IcarusBody7 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("string")), 1); } INT4 IcarusBody8 () { b = IopPop_ (0, 0); IopPush_ (0, IopBinop_ (0, VarGetStrV (IopPop_ (0, 1)), IopPop_ (0, 0), b), 0); } INT4 IcarusBody9 () { IopOut (0, NULL); } INT4 IcarusBody10 () { IopOut (0, NULL); IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody11 () { IopProg_ (0); } INT4 IcarusBody12 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody13 () { IopPush_ (0, IopBody_ (0), 0); } INT4 IcarusBody14 () { IopPush_ (0, IopOpnd_ (0, IopSubMatch (0, 1), StrCpyS ("string")), 5); } INT4 IcarusBody15 () { IopPush_ (0, IopAssoc_ (0, IopPop_ (0, 0), IopPop_ (0, 5)), 0); } INT4 IcarusBody16 () { b = IopPop_ (0, 0); IopPush_ (0, IopBinop_ (0, VarGetStrV (IopPop_ (0, 1)), IopPop_ (0, 0), b), 0); } INT4 IcarusBody17 () { IopNot (0); } INT4 IcarusBody18 () { b = IopPop_ (0, 0); IopPush_ (0, IopBinop_ (0, VarGetStrV (IopPop_ (0, 1)), IopPop_ (0, 0), b), 0); } INT4 IcarusBody19 () { b = IopPop_ (0, 0); IopPush_ (0, IopBinop_ (0, VarGetStrV (IopPop_ (0, 1)), IopPop_ (0, 0), b), 0); } INT4 IcarusBody20 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("null")), 0); } INT4 IcarusBody21 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody22 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody23 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody24 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody25 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody26 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody27 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 1); } INT4 IcarusBody28 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody29 () { IopPush_ (0, IopList_ (0), 0); } INT4 IcarusBody30 () { IopPush_ (0, IopAssoc_ (0, IopPop_ (0, 0), IopPop_ (0, 5)), 0); } INT4 IcarusBody31 () { IopPush_ (0, IopOpnd_ (0, IopSubMatch (0, 1), StrCpyS ("string")), 5); } INT4 IcarusBody32 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("int")), 0); } INT4 IcarusBody33 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 0); } INT4 IcarusBody34 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("ident")), 0); } INT4 IcarusBody35 () { IopPush_ (0, IopSelect_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), NULL, IopPop_ (0, 0)), 0); } INT4 IcarusBody36 () { a = IopPop_ (0, 0); IopPush_ (0, IopSelect_ (0, a, NULL, IopPop_ (0, 0)), 0); } INT4 IcarusBody37 () { a = IopPop_ (0, 0); IopPush_ (0, IopSelect_ (0, a, NULL, IopPop_ (0, 0)), 0); } INT4 IcarusBody38 () { a = IopPop_ (0, 0); IopPush_ (0, IopSelect_ (0, a, NULL, IopPop_ (0, 0)), 0); } INT4 IcarusBody39 () { i = IopPop_ (0, 0); IopPush_ (0, IopSelect_ (0, NULL, i, IopPop_ (0, 0)), 0); } INT4 IcarusBody40 () { IopPush_ (0, IopFunc_ (0), 0); } INT4 IcarusBody41 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody42 () { IopPush_ (0, IopMakeArg_ (0, IopPop_ (0, 0), IopOpnd_ (0, StrCpyS (":::::"), StrCpyS ("str"))), 0); } INT4 IcarusBody43 () { IopPush_ (0, IopOpnd_ (0, IopSubMatch (0, 1), StrCpyS ("str")), 0); } INT4 IcarusBody44 () { a = IopPop_ (0, 0); IopPush_ (0, IopMakeArg_ (0, a, IopPop_ (0, 0)), 0); } INT4 IcarusBody45 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("int")), 0); } INT4 IcarusBody46 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 0); } INT4 IcarusBody47 () { opt = 1; } INT4 IcarusBody48 () { opt = 0; } INT4 IcarusBody49 () { IopPush_ (0, IopRef_ (0, VarSetStrV (VarTemp (), IopCurrToken (0)), opt), 0); } INT4 IcarusBody50 () { IopPush_ (0, IopStrMake_ (0), 0); } INT4 IcarusBody51 () { IopNot (0); } INT4 IcarusBody52 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody53 () { IopSetSkip (0, 0, NULL); } INT4 IcarusBody54 () { IopSetSkip (0, 1, NULL); IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 0); } INT4 IcarusBody55 () { IopNoskip (0); } INT4 IcarusBody56 () { IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 0); } INT4 IcarusBody57 () { IopSetSkip (0, 0, NULL); } INT4 IcarusBody58 () { IopSetSkip (0, 1, NULL); IopPush_ (0, IopOpnd_ (0, IopCurrToken (0), StrCpyS ("str")), 0); } INT4 IcarusBody59 () { IopRep (0, VarSetStrV (VarTemp (), StrCpyS ("\2"))); } INT4 IcarusBody60 () { IopSetSkip (0, 1, NULL); } INT4 IcarusBody61 () { IopSetSkip (0, 0, NULL); } INT4 IcarusBody62 () { IopRep (0, VarSetStrV (VarTemp (), StrCpyS ("\2"))); } INT4 IcarusBody63 () { IopPush_ (0, IopOpnd_ (0, IopSubMatch (0, 1), StrCpyS ("ident")), 0); } INT4 IcarusBody64 () { IopPush_ (0, IopFile_ (0, IopPop_ (0, 0)), 0); } INT4 IcarusBody65 () { IopPush_ (0, IopPre_ (0, IopPop_ (0, 0)), 0); } INT4 IcarusBody66 () { IopPush_ (0, IopInit_ (0, IopPop_ (0, 0)), 0); } INT4 IcarusBody67 () { a = IopPop_ (0, 0); b = IopPop_ (0, 0); IopPush_ (0, IopForeach_ (0, a, b, IopPop_ (0, 0)), 0); } INT4 IcarusBody68 () { b = IopPop_ (0, 0); u = IopPop_ (0, 0); c = IopPop_ (0, 0); IopPush_ (0, IopFor_ (0, IopPop_ (0, 0), c, u, b), 0); } INT4 IcarusBody69 () { b = IopPop_ (0, 0); IopPush_ (0, IopWhile_ (0, IopPop_ (0, 0), b), 0); } INT4 IcarusBody70 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody71 () { IopPush_ (0, IopOpnd_ (0, StrCpyS ("1"), StrCpyS ("int")), 0); } INT4 IcarusBody72 () { IopPush_ (0, IopIf_ (0), 0); } INT4 IcarusBody73 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopProd_ (0)), 3); } INT4 IcarusBody74 () { a = IopPop_ (0, 3); IopPush_ (0, IopEndProd_ (0, VarGetObject (NULL, (void*)a), VarGetObject (NULL, (void*)IopPop_ (0, 3))), 0); } INT4 IcarusBody75 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopNullNode_ (0)), 3); } INT4 IcarusBody76 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopExpr_ (0)), 3); } INT4 IcarusBody77 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopNullNode_ (0)), 3); } INT4 IcarusBody78 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopTerm_ (0)), 3); } INT4 IcarusBody79 () { IopSetSkip (0, 1, NULL); } INT4 IcarusBody80 () { IopSetSkip (0, 0, NULL); } INT4 IcarusBody81 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopRegexp_ (0, IopCurrToken (0))), 3); } INT4 IcarusBody82 () { IopSetSkip (0, 1, NULL); } INT4 IcarusBody83 () { IopSetSkip (0, 0, NULL); } INT4 IcarusBody84 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopLiteral_ (0, IopCurrToken (0))), 3); } INT4 IcarusBody85 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopCommand_ (0)), 3); } INT4 IcarusBody86 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopInputEnd_ (0)), 3); } INT4 IcarusBody87 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopMakeOpt_ (0, VarGetObject (NULL, (void*)IopPop_ (0, 3)), StrCpyS ("once"))), 3); } INT4 IcarusBody88 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopMakeOpt_ (0, VarGetObject (NULL, (void*)IopPop_ (0, 3)), StrCpyS ("multi"))), 3); } INT4 IcarusBody89 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopMakeOpt_ (0, VarGetObject (NULL, (void*)IopPop_ (0, 3)), StrCpyS ("onemore"))), 3); } INT4 IcarusBody90 () { a = 0; } INT4 IcarusBody91 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopNodeProg_ (0, VarGetObject (NULL, (void*)IopPop_ (0, 3)), a)), 3); } INT4 IcarusBody92 () { IopPush_ (0, IopOpnd_ (0, NULL, StrCpyS ("mark")), 0); } INT4 IcarusBody93 () { a = IopBody_ (0); } INT4 IcarusBody94 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopProdName_ (0, IopCurrToken (0), 0)), 3); } INT4 IcarusBody95 () { IopPush_ (0, VarSetObject (NULL, VarTemp (), (void*)IopProdName_ (0, IopCurrToken (0), 1)), 3); } #define PRODNUM 68 #define PRODNNUM 120 #define LITLNUM 66 #define REGNUM 40 #define TERMNUM 158 #define CHOINUM 28 #define COMMNUM 7 #define NAMENUM 7 char *_scopeName[] = { "rules", "b", "a", "i", "opt", "u", "c" }; VARo _var[] = { { 0,0,0,1,0,1,1,0,0, IcarusBody1 }, { 0,0,0,1,0,1,1,0,0, IcarusBody2 }, { 0,0,0,1,0,1,1,0,0, IcarusBody3 }, { 0,0,0,1,0,1,1,0,0, IcarusBody4 }, { 0,0,0,1,0,1,1,0,0, IcarusBody5 }, { 0,0,0,1,0,1,1,0,0, IcarusBody6 }, { 0,0,0,1,0,1,1,0,0, IcarusBody7 }, { 0,0,0,1,0,1,1,0,0, IcarusBody8 }, { 0,0,0,1,0,1,1,0,0, IcarusBody9 }, { 0,0,0,1,0,1,1,0,0, IcarusBody10 }, { 0,0,0,1,0,1,1,0,0, IcarusBody11 }, { 0,0,0,1,0,1,1,0,0, IcarusBody12 }, { 0,0,0,1,0,1,1,0,0, IcarusBody13 }, { 0,0,0,1,0,1,1,0,0, IcarusBody14 }, { 0,0,0,1,0,1,1,0,0, IcarusBody15 }, { 0,0,0,1,0,1,1,0,0, IcarusBody16 }, { 0,0,0,1,0,1,1,0,0, IcarusBody17 }, { 0,0,0,1,0,1,1,0,0, IcarusBody18 }, { 0,0,0,1,0,1,1,0,0, IcarusBody19 }, { 0,0,0,1,0,1,1,0,0, IcarusBody20 }, { 0,0,0,1,0,1,1,0,0, IcarusBody21 }, { 0,0,0,1,0,1,1,0,0, IcarusBody22 }, { 0,0,0,1,0,1,1,0,0, IcarusBody23 }, { 0,0,0,1,0,1,1,0,0, IcarusBody24 }, { 0,0,0,1,0,1,1,0,0, IcarusBody25 }, { 0,0,0,1,0,1,1,0,0, IcarusBody26 }, { 0,0,0,1,0,1,1,0,0, IcarusBody27 }, { 0,0,0,1,0,1,1,0,0, IcarusBody28 }, { 0,0,0,1,0,1,1,0,0, IcarusBody29 }, { 0,0,0,1,0,1,1,0,0, IcarusBody30 }, { 0,0,0,1,0,1,1,0,0, IcarusBody31 }, { 0,0,0,1,0,1,1,0,0, IcarusBody32 }, { 0,0,0,1,0,1,1,0,0, IcarusBody33 }, { 0,0,0,1,0,1,1,0,0, IcarusBody34 }, { 0,0,0,1,0,1,1,0,0, IcarusBody35 }, { 0,0,0,1,0,1,1,0,0, IcarusBody36 }, { 0,0,0,1,0,1,1,0,0, IcarusBody37 }, { 0,0,0,1,0,1,1,0,0, IcarusBody38 }, { 0,0,0,1,0,1,1,0,0, IcarusBody39 }, { 0,0,0,1,0,1,1,0,0, IcarusBody40 }, { 0,0,0,1,0,1,1,0,0, IcarusBody41 }, { 0,0,0,1,0,1,1,0,0, IcarusBody42 }, { 0,0,0,1,0,1,1,0,0, IcarusBody43 }, { 0,0,0,1,0,1,1,0,0, IcarusBody44 }, { 0,0,0,1,0,1,1,0,0, IcarusBody45 }, { 0,0,0,1,0,1,1,0,0, IcarusBody46 }, { 0,0,0,1,0,1,1,0,0, IcarusBody47 }, { 0,0,0,1,0,1,1,0,0, IcarusBody48 }, { 0,0,0,1,0,1,1,0,0, IcarusBody49 }, { 0,0,0,1,0,1,1,0,0, IcarusBody50 }, { 0,0,0,1,0,1,1,0,0, IcarusBody51 }, { 0,0,0,1,0,1,1,0,0, IcarusBody52 }, { 0,0,0,1,0,1,1,0,0, IcarusBody53 }, { 0,0,0,1,0,1,1,0,0, IcarusBody54 }, { 0,0,0,1,0,1,1,0,0, IcarusBody55 }, { 0,0,0,1,0,1,1,0,0, IcarusBody56 }, { 0,0,0,1,0,1,1,0,0, IcarusBody57 }, { 0,0,0,1,0,1,1,0,0, IcarusBody58 }, { 0,0,0,1,0,1,1,0,0, IcarusBody59 }, { 0,0,0,1,0,1,1,0,0, IcarusBody60 }, { 0,0,0,1,0,1,1,0,0, IcarusBody61 }, { 0,0,0,1,0,1,1,0,0, IcarusBody62 }, { 0,0,0,1,0,1,1,0,0, IcarusBody63 }, { 0,0,0,1,0,1,1,0,0, IcarusBody64 }, { 0,0,0,1,0,1,1,0,0, IcarusBody65 }, { 0,0,0,1,0,1,1,0,0, IcarusBody66 }, { 0,0,0,1,0,1,1,0,0, IcarusBody67 }, { 0,0,0,1,0,1,1,0,0, IcarusBody68 }, { 0,0,0,1,0,1,1,0,0, IcarusBody69 }, { 0,0,0,1,0,1,1,0,0, IcarusBody70 }, { 0,0,0,1,0,1,1,0,0, IcarusBody71 }, { 0,0,0,1,0,1,1,0,0, IcarusBody72 }, { 0,0,0,1,0,1,1,0,0, IcarusBody73 }, { 0,0,0,1,0,1,1,0,0, IcarusBody74 }, { 0,0,0,1,0,1,1,0,0, IcarusBody75 }, { 0,0,0,1,0,1,1,0,0, IcarusBody76 }, { 0,0,0,1,0,1,1,0,0, IcarusBody77 }, { 0,0,0,1,0,1,1,0,0, IcarusBody78 }, { 0,0,0,1,0,1,1,0,0, IcarusBody79 }, { 0,0,0,1,0,1,1,0,0, IcarusBody80 }, { 0,0,0,1,0,1,1,0,0, IcarusBody81 }, { 0,0,0,1,0,1,1,0,0, IcarusBody82 }, { 0,0,0,1,0,1,1,0,0, IcarusBody83 }, { 0,0,0,1,0,1,1,0,0, IcarusBody84 }, { 0,0,0,1,0,1,1,0,0, IcarusBody85 }, { 0,0,0,1,0,1,1,0,0, IcarusBody86 }, { 0,0,0,1,0,1,1,0,0, IcarusBody87 }, { 0,0,0,1,0,1,1,0,0, IcarusBody88 }, { 0,0,0,1,0,1,1,0,0, IcarusBody89 }, { 0,0,0,1,0,1,1,0,0, IcarusBody90 }, { 0,0,0,1,0,1,1,0,0, IcarusBody91 }, { 0,0,0,1,0,1,1,0,0, IcarusBody92 }, { 0,0,0,1,0,1,1,0,0, IcarusBody93 }, { 0,0,0,1,0,1,1,0,0, IcarusBody94 }, { 0,0,0,1,0,1,1,0,0, IcarusBody95 } }; BNFoLITERAL _lit[] = { {"=",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[6] }, {"{",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"}",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"(",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {")",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"{",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[27] }, {"}",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[28] }, {"~",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"~",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {".",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"(",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {")",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[35] }, {"[",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"]",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[38] }, {"$",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[40] }, {"[",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"]",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"@",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"?",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[46] }, {"\"",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[52] }, {"\"",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"|",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[56] }, {"\n",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"(",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"($",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {")",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"file",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"pre",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"init",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"foreach",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"[",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"in",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"]",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"for",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"{",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"}",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"while",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"if",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[69] }, {"elif",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {":",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"else",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[70] }, {"(",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {")",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"{",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"}",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"[",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"]",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"|",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"(",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {")",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {"/",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[79] }, {"/",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 }, {".",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[85] }, {"?",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[86] }, {"*",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[87] }, {"+",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[88] }, {"{",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[91] }, {"}",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, &_var[92] }, {"_",2,0,0, BnfParseLiteral, 0,0,0,0, 0, 0, 0 } }; BNFoREGEXP _reg[] = { {"^\\$([a-zA-Z0-9]+) *= *{",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[3] }, {"^ *[a-zA-Z0-9]+:| *\\|| *}",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[^\n]*",3,0,0, BnfParseRegExp, 0,0,0,0, &_var[4], 0, 0 }, {"^[^\n]*\n",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[0-9]+\\.[0-9]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[a-zA-Z0-9_]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[+%-][^=]",3,0,0, BnfParseRegExp, 0,0,0,0, &_var[16], 0, 0 }, {"^(&&|\\|\\|)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[20] }, {"^(\\+=|=|-=|\\*=|/=)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[21] }, {"^(<=|=<|>=|=>|<|>|==|!=)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[22] }, {"^[%+-]",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[23] }, {"^(\\*|/)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[24] }, {"^(\\+\\+|--|\\+)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[25] }, {"^(\\+\\+|--)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[26] }, {"^([a-zA-Z0-9_]+):",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^'(([^']+|\\\\.)*)':",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^-?[0-9]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[a-zA-Z0-9_]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^([a-zA-Z_0-9]+) *:",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[42] }, {"^[a-zA-Z0-9_]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[a-zA-Z_][a-zA-Z0-9_]*",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[45] }, {"^[^\"'|]",3,0,0, BnfParseRegExp, 0,0,0,0, &_var[50], 0, &_var[51] }, {"^'",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[^']*",3,0,0, BnfParseRegExp, 0,0,0,0, &_var[54], 0, &_var[55] }, {"^'",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[^\n\\$(]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^\\\\[^\n]",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[^\n]",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[^\"\\$(]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^\\\\.",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^\\$([a-zA-Z0-9_]+)",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[62] }, {"^[^/\\]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^\\\\.",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^'",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[82] }, {"^'",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^[^'\\]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^\\\\.",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, 0 }, {"^x:?",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[84] }, {"^[a-zA-Z0-9_]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[93] }, {"^[a-zA-Z0-9_]+",3,0,0, BnfParseRegExp, 0,0,0,0, 0, 0, &_var[94] } }; BNFoTERM _term[] = { {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm }, {"TERM",4,0,0, BnfParseTerm } }; BNFoCHOICE _choi[] = { {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice }, {"CHOI",5,0,0, BnfParseChoice } }; BNFoNODE _comm[] = { {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[10] }, {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[11] }, {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[12] }, {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[18] }, {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[19] }, {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[47] }, {"COMM",6,0,0, BnfParseCommand, 0,0,0,0, 0, 0, &_var[71] } }; BNFoPRODUCTION _prod[] = { {"scan",0,0,0, BnfParseProduction, 0,0,0,0, &_var[0], &_var[1], &_var[2], (BNFoNODE*)&_term[0]}, {"arr",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[4]}, {"ln",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[6]}, {"real",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[7]}, {"str",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[8]}, {"template",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[5], (BNFoNODE*)&_term[9]}, {"prog",0,0,0, BnfParseProduction, 0,0,0,0, &_var[8], &_var[9], 0, (BNFoNODE*)&_term[10]}, {"body",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[11]}, {"stmnt",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[14]}, {"stassoc",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[24]}, {"expr",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[25]}, {"term1",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[27]}, {"term2",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[31]}, {"term3",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[35]}, {"term4",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[5]}, {"makeop",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[39]}, {"nullopnd",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[40]}, {"logop",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[41]}, {"assop",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[42]}, {"compop",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[43]}, {"op1",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[44]}, {"op2",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[45]}, {"unopleft",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[46]}, {"unopright",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[47]}, {"list",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[48]}, {"assoc",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[29], (BNFoNODE*)&_term[51]}, {"key",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[8]}, {"value",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[9]}, {"int",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[62]}, {"name",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[63]}, {"path",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[64]}, {"ident",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[72]}, {"args",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[73]}, {"unnamed",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[78]}, {"named",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[79]}, {"argvalue",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[14]}, {"name",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[83]}, {"strname",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[84]}, {"reference",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[85]}, {"string",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[49], (BNFoNODE*)&_term[88]}, {"sqString",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[92]}, {"bqString",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[93]}, {"bqLine",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[95]}, {"dqString",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[101]}, {"var2",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[58], (BNFoNODE*)&_term[107]}, {"var",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[61], (BNFoNODE*)&_term[108]}, {"file",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[109]}, {"pre",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[110]}, {"init",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[111]}, {"foreach",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[112]}, {"for",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[113]}, {"while",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[120]}, {"if",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[121]}, {"cond",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[22]}, {"production",0,0,0, BnfParseProduction, 0,0,0,0, 0, &_var[72], 0, (BNFoNODE*)&_term[128]}, {"bnfExpr",0,0,0, BnfParseProduction, 0,0,0,0, 0, &_var[74], &_var[75], (BNFoNODE*)&_term[129]}, {"term",0,0,0, BnfParseProduction, 0,0,0,0, 0, &_var[76], &_var[77], (BNFoNODE*)&_term[131]}, {"factor",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[23]}, {"regexp",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[78], (BNFoNODE*)&_term[141]}, {"reStr",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[142]}, {"literal",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, &_var[81], (BNFoNODE*)&_term[145]}, {"litStr",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[146]}, {"command",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[149]}, {"eoi",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[150]}, {"occur",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_choi[27]}, {"nodeProg",0,0,0, BnfParseProduction, 0,0,0,0, 0, &_var[89], &_var[90], (BNFoNODE*)&_term[154]}, {"prodName",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[156]}, {"laProdName",0,0,0, BnfParseProduction, 0,0,0,0, 0, 0, 0, (BNFoNODE*)&_term[157]} }; BNFoPRODNAME _prodN[] = { {"arr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[1]}, {"ident",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[31]}, {"ln",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[2]}, {"ln",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[2]}, {"var",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[45]}, {"list",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[7], &_prod[24]}, {"stmnt",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[8]}, {"stmnt",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[8]}, {"stmnt",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[8]}, {"if",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[52]}, {"foreach",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[49]}, {"for",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[50]}, {"while",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[51]}, {"init",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[48]}, {"pre",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[47]}, {"file",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[46]}, {"stassoc",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[9]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"key",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[13], &_prod[26]}, {"ident",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[14], &_prod[31]}, {"term1",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[11]}, {"logop",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[17]}, {"term1",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[11]}, {"makeop",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[15]}, {"term2",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[12]}, {"compop",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[19]}, {"assop",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[18]}, {"term2",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[15], &_prod[12]}, {"term3",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[13]}, {"op1",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[20]}, {"term3",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[17], &_prod[13]}, {"term4",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[14]}, {"op2",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[21]}, {"term4",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[14]}, {"makeop",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[15]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"unopleft",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[22]}, {"value",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[27]}, {"unopright",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[23]}, {"assoc",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[25]}, {"value",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[27]}, {"key",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[30], &_prod[26]}, {"value",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[27]}, {"production",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[54]}, {"int",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[31], &_prod[28]}, {"name",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[32], &_prod[29]}, {"string",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[39]}, {"ident",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[31]}, {"list",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[24]}, {"reference",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[38]}, {"name",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[33], &_prod[29]}, {"name",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[34], &_prod[29]}, {"ident",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[31]}, {"string",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[36], &_prod[39]}, {"ident",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[37], &_prod[31]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"args",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[39], &_prod[32]}, {"path",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[30]}, {"named",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[34]}, {"unnamed",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[33]}, {"named",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[34]}, {"unnamed",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[33]}, {"argvalue",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[41], &_prod[35]}, {"argvalue",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[43], &_prod[35]}, {"int",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[44], &_prod[28]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"reference",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[38]}, {"name",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[48], &_prod[29]}, {"sqString",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[40]}, {"bqString",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[41]}, {"dqString",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[53], &_prod[43]}, {"bqLine",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[57], &_prod[42]}, {"var",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[45]}, {"var2",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[44]}, {"var",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[45]}, {"var2",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[44]}, {"path",1,0,0, BnfParseProdName, 0,0,0,0, 0, &_var[59], &_var[60], &_prod[30]}, {"string",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[63], &_prod[39]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[64], &_prod[7]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[65], &_prod[7]}, {"ident",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[31]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[66], &_prod[7]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"nullopnd",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[16]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"nullopnd",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[16]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"nullopnd",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[16]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[67], &_prod[7]}, {"cond",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[53]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[68], &_prod[7]}, {"cond",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[53]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[7]}, {"cond",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[53]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[7]}, {"body",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[7]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"expr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[10]}, {"nodeProg",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[65]}, {"bnfExpr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[73], &_prod[55]}, {"term",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[56]}, {"term",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[56]}, {"factor",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[57]}, {"factor",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[57]}, {"regexp",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[58]}, {"literal",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[60]}, {"command",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[62]}, {"eoi",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[63]}, {"prodName",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[66]}, {"laProdName",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[67]}, {"occur",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[64]}, {"nodeProg",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[65]}, {"bnfExpr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[55]}, {"occur",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[64]}, {"reStr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[80], &_prod[59]}, {"litStr",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, &_var[83], &_prod[61]}, {"stmnt",1,0,0, BnfParseProdName, 0,0,0,0, 0, 0, 0, &_prod[8]} }; BNFoREPORT _report[] = { { 1, (BNFoNODE *)&_choi[0] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[0] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[1] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[2] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[0] }, { 0, (BNFoNODE *)&_prodN[3] }, { 1, (BNFoNODE *)&_term[5] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[1] }, { 0, (BNFoNODE *)&_reg[2] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[3] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[4] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[5] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[4] }, { 0, (BNFoNODE *)&_lit[0] }, { 0, (BNFoNODE *)&_prodN[5] }, { 0, NULL }, { 3, (BNFoNODE *)&_prodN[6] }, { 0, (BNFoNODE *)&_comm[0] }, { 0, NULL }, { 0, (BNFoNODE *)&_comm[1] }, { 0, (BNFoNODE *)&_choi[1] }, { 0, (BNFoNODE *)&_comm[2] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[1] }, { 1, (BNFoNODE *)&_prodN[7] }, { 0, (BNFoNODE *)&_lit[2] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[8] }, { 0, NULL }, { 0, (BNFoNODE *)&_choi[2] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[9] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[10] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[11] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[12] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[13] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[14] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[15] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[16] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[17] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[18] }, { 0, (BNFoNODE *)&_prodN[19] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[20] }, { 1, (BNFoNODE *)&_term[26] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[21] }, { 0, (BNFoNODE *)&_prodN[22] }, { 0, (BNFoNODE *)&_prodN[23] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[24] }, { 1, (BNFoNODE *)&_term[28] }, { 0, NULL }, { 0, (BNFoNODE *)&_choi[3] }, { 0, (BNFoNODE *)&_prodN[27] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[25] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[26] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[28] }, { 2, (BNFoNODE *)&_choi[4] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[6] }, { 0, NULL }, { 1, (BNFoNODE *)&_term[34] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[29] }, { 0, (BNFoNODE *)&_prodN[30] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[31] }, { 1, (BNFoNODE *)&_term[36] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[32] }, { 0, (BNFoNODE *)&_prodN[33] }, { 0, (BNFoNODE *)&_prodN[34] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[3] }, { 0, (BNFoNODE *)&_prodN[35] }, { 0, (BNFoNODE *)&_lit[4] }, { 0, NULL }, { 2, (BNFoNODE *)&_prodN[36] }, { 0, (BNFoNODE *)&_prodN[37] }, { 2, (BNFoNODE *)&_prodN[38] }, { 0, NULL }, { 0, (BNFoNODE *)&_comm[3] }, { 0, NULL }, { 0, (BNFoNODE *)&_comm[4] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[7] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[8] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[9] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[10] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[11] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[12] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[13] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[5] }, { 1, (BNFoNODE *)&_choi[6] }, { 0, (BNFoNODE *)&_lit[6] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[39] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[40] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[41] }, { 0, (BNFoNODE *)&_choi[7] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[42] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[7] }, { 0, (BNFoNODE *)&_prodN[43] }, { 0, (BNFoNODE *)&_lit[8] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[14] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[15] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[44] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[45] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[46] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[47] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[48] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[49] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[16] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[17] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[50] }, { 1, (BNFoNODE *)&_choi[10] }, { 2, (BNFoNODE *)&_term[71] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[9] }, { 0, (BNFoNODE *)&_choi[11] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[51] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[10] }, { 0, (BNFoNODE *)&_prodN[52] }, { 0, (BNFoNODE *)&_lit[11] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[53] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[54] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[12] }, { 0, (BNFoNODE *)&_prodN[55] }, { 0, (BNFoNODE *)&_lit[13] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[56] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[14] }, { 0, (BNFoNODE *)&_prodN[57] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[15] }, { 0, (BNFoNODE *)&_choi[12] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[16] }, { 2, (BNFoNODE *)&_choi[13] }, { 1, (BNFoNODE *)&_prodN[60] }, { 0, (BNFoNODE *)&_lit[17] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[58] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[59] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[61] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[62] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[18] }, { 0, (BNFoNODE *)&_prodN[63] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[64] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[65] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[66] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[19] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[20] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[18] }, { 0, (BNFoNODE *)&_choi[15] }, { 0, (BNFoNODE *)&_prodN[67] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[19] }, { 0, NULL }, { 0, (BNFoNODE *)&_comm[5] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[21] }, { 0, (BNFoNODE *)&_choi[16] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[68] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[69] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[20] }, { 0, (BNFoNODE *)&_prodN[70] }, { 0, (BNFoNODE *)&_lit[21] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[22] }, { 0, (BNFoNODE *)&_reg[23] }, { 0, (BNFoNODE *)&_reg[24] }, { 0, NULL }, { 3, (BNFoNODE *)&_term[94] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[22] }, { 0, (BNFoNODE *)&_prodN[71] }, { 0, NULL }, { 1, (BNFoNODE *)&_choi[17] }, { 0, (BNFoNODE *)&_lit[23] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[25] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[26] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[72] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[73] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[27] }, { 0, NULL }, { 1, (BNFoNODE *)&_choi[18] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[28] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[29] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[74] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[75] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[24] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[25] }, { 0, (BNFoNODE *)&_prodN[76] }, { 0, (BNFoNODE *)&_lit[26] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[30] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[27] }, { 0, (BNFoNODE *)&_lit[28] }, { 0, (BNFoNODE *)&_prodN[77] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[29] }, { 0, (BNFoNODE *)&_prodN[78] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[30] }, { 0, (BNFoNODE *)&_prodN[79] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[31] }, { 0, (BNFoNODE *)&_lit[32] }, { 0, (BNFoNODE *)&_lit[33] }, { 0, (BNFoNODE *)&_prodN[80] }, { 0, (BNFoNODE *)&_lit[34] }, { 0, (BNFoNODE *)&_lit[35] }, { 0, (BNFoNODE *)&_prodN[81] }, { 0, (BNFoNODE *)&_lit[36] }, { 0, (BNFoNODE *)&_prodN[82] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[37] }, { 0, (BNFoNODE *)&_lit[38] }, { 0, (BNFoNODE *)&_lit[39] }, { 0, (BNFoNODE *)&_choi[19] }, { 0, (BNFoNODE *)&_choi[20] }, { 0, (BNFoNODE *)&_choi[21] }, { 0, (BNFoNODE *)&_lit[40] }, { 0, (BNFoNODE *)&_prodN[89] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[83] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[84] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[85] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[86] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[87] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[88] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[41] }, { 0, (BNFoNODE *)&_lit[42] }, { 0, (BNFoNODE *)&_prodN[90] }, { 0, (BNFoNODE *)&_prodN[91] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[43] }, { 0, (BNFoNODE *)&_lit[44] }, { 0, (BNFoNODE *)&_prodN[92] }, { 0, (BNFoNODE *)&_prodN[93] }, { 1, (BNFoNODE *)&_term[122] }, { 2, (BNFoNODE *)&_term[123] }, { 0, (BNFoNODE *)&_comm[6] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[45] }, { 0, (BNFoNODE *)&_lit[46] }, { 0, (BNFoNODE *)&_prodN[94] }, { 0, (BNFoNODE *)&_prodN[95] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[47] }, { 0, (BNFoNODE *)&_prodN[96] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[48] }, { 0, (BNFoNODE *)&_prodN[97] }, { 0, (BNFoNODE *)&_lit[49] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[50] }, { 0, (BNFoNODE *)&_prodN[98] }, { 0, (BNFoNODE *)&_lit[51] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[52] }, { 0, (BNFoNODE *)&_prodN[99] }, { 0, (BNFoNODE *)&_lit[53] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[100] }, { 0, NULL }, { 2, (BNFoNODE *)&_prodN[101] }, { 0, (BNFoNODE *)&_prodN[102] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[103] }, { 1, (BNFoNODE *)&_term[130] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[54] }, { 0, (BNFoNODE *)&_prodN[104] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[105] }, { 1, (BNFoNODE *)&_term[132] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[106] }, { 0, NULL }, { 0, (BNFoNODE *)&_choi[24] }, { 2, (BNFoNODE *)&_prodN[113] }, { 0, (BNFoNODE *)&_prodN[114] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[107] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[108] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[109] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[110] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[111] }, { 0, NULL }, { 0, (BNFoNODE *)&_prodN[112] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[55] }, { 0, (BNFoNODE *)&_prodN[115] }, { 0, (BNFoNODE *)&_lit[56] }, { 2, (BNFoNODE *)&_prodN[116] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[57] }, { 0, (BNFoNODE *)&_prodN[117] }, { 0, (BNFoNODE *)&_lit[58] }, { 0, NULL }, { 3, (BNFoNODE *)&_choi[25] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[31] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[32] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[33] }, { 0, (BNFoNODE *)&_prodN[118] }, { 0, (BNFoNODE *)&_reg[34] }, { 0, NULL }, { 3, (BNFoNODE *)&_choi[26] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[35] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[36] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[37] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[59] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[60] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[61] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[62] }, { 0, NULL }, { 2, (BNFoNODE *)&_term[155] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[63] }, { 3, (BNFoNODE *)&_prodN[119] }, { 0, (BNFoNODE *)&_lit[64] }, { 0, NULL }, { 0, (BNFoNODE *)&_reg[38] }, { 0, NULL }, { 0, (BNFoNODE *)&_lit[65] }, { 0, (BNFoNODE *)&_reg[39] }, { 0, NULL } }; BNFoNODE *_choiceSet[] = { (BNFoNODE *)&_term[1], (BNFoNODE *)&_term[2], (BNFoNODE *)&_term[3], NULL, (BNFoNODE *)&_term[12], (BNFoNODE *)&_term[13], NULL, (BNFoNODE *)&_term[15], (BNFoNODE *)&_term[16], (BNFoNODE *)&_term[17], (BNFoNODE *)&_term[18], (BNFoNODE *)&_term[19], (BNFoNODE *)&_term[20], (BNFoNODE *)&_term[21], (BNFoNODE *)&_term[22], (BNFoNODE *)&_term[23], NULL, (BNFoNODE *)&_term[29], (BNFoNODE *)&_term[30], NULL, (BNFoNODE *)&_term[32], (BNFoNODE *)&_term[33], NULL, (BNFoNODE *)&_term[37], (BNFoNODE *)&_term[38], NULL, (BNFoNODE *)&_term[49], (BNFoNODE *)&_term[50], NULL, (BNFoNODE *)&_term[52], (BNFoNODE *)&_term[53], NULL, (BNFoNODE *)&_term[54], (BNFoNODE *)&_term[55], NULL, (BNFoNODE *)&_term[56], (BNFoNODE *)&_term[57], (BNFoNODE *)&_term[58], (BNFoNODE *)&_term[59], (BNFoNODE *)&_term[60], (BNFoNODE *)&_term[61], NULL, (BNFoNODE *)&_term[65], (BNFoNODE *)&_term[70], NULL, (BNFoNODE *)&_term[66], (BNFoNODE *)&_term[67], (BNFoNODE *)&_term[68], (BNFoNODE *)&_term[69], NULL, (BNFoNODE *)&_term[74], (BNFoNODE *)&_term[77], NULL, (BNFoNODE *)&_term[75], (BNFoNODE *)&_term[76], NULL, (BNFoNODE *)&_term[80], (BNFoNODE *)&_term[81], (BNFoNODE *)&_term[82], NULL, (BNFoNODE *)&_term[86], (BNFoNODE *)&_term[87], NULL, (BNFoNODE *)&_term[89], (BNFoNODE *)&_term[90], (BNFoNODE *)&_term[91], NULL, (BNFoNODE *)&_term[96], (BNFoNODE *)&_term[97], (BNFoNODE *)&_term[98], (BNFoNODE *)&_term[99], (BNFoNODE *)&_term[100], NULL, (BNFoNODE *)&_term[102], (BNFoNODE *)&_term[103], (BNFoNODE *)&_term[104], (BNFoNODE *)&_term[105], (BNFoNODE *)&_term[106], NULL, (BNFoNODE *)&_term[114], (BNFoNODE *)&_term[115], NULL, (BNFoNODE *)&_term[116], (BNFoNODE *)&_term[117], NULL, (BNFoNODE *)&_term[118], (BNFoNODE *)&_term[119], NULL, (BNFoNODE *)&_term[124], (BNFoNODE *)&_term[125], (BNFoNODE *)&_term[126], (BNFoNODE *)&_term[127], NULL, (BNFoNODE *)&_term[133], (BNFoNODE *)&_term[140], NULL, (BNFoNODE *)&_term[134], (BNFoNODE *)&_term[135], (BNFoNODE *)&_term[136], (BNFoNODE *)&_term[137], (BNFoNODE *)&_term[138], (BNFoNODE *)&_term[139], NULL, (BNFoNODE *)&_term[143], (BNFoNODE *)&_term[144], NULL, (BNFoNODE *)&_term[147], (BNFoNODE *)&_term[148], NULL, (BNFoNODE *)&_term[151], (BNFoNODE *)&_term[152], (BNFoNODE *)&_term[153], NULL }; ICAoSYNTAX *IcaInitSyntax(ICAoSYNTAX *syntax) { static ICAoSYNTAX syntaxStatic; static ICAoJOB job; VARo *prodList; INT4 i, j; if (!syntax) syntax = &syntaxStatic; Job = &job; Job->isBuildTime = 1; j = 0; for(i=0; icurrNode = (BNFoNODE *) &_prod[i]; _BnfExecInit (&_prod[i]); } for(i=0; icurrNode = (BNFoNODE *) &_prodN[i]; _BnfExecInit (&_prodN[i]); } #ifdef LITLNUM for(i=0; icurrNode = (BNFoNODE *) &_lit[i]; _BnfExecInit (&_lit[i]); } #endif #ifdef REGNUM for(i=0; icurrNode = (BNFoNODE *) &_reg[i]; _BnfExecInit (&_reg[i]); } #endif #ifdef COMMNUM for(i=0; icurrNode = (BNFoNODE *) &_comm[i]; _BnfExecInit (&_comm[i]); } #endif #ifdef STRTNUM for(i=0; icurrNode = (BNFoNODE *) &_strt[i]; _BnfExecInit (&_strt[i]); } #endif #ifdef EOINNUM for(i=0; icurrNode = (BNFoNODE *) &_eoin[i]; _BnfExecInit (&_eoin[i]); } #endif VarGet (&job.scope, ""); syntax->prod = prodList; syntax->ign = DEFIGNORE; if (syntax == &syntaxStatic) { syntax->cmnt = DEFCOMMENT; syntax->ignAlt = ""; } if ((syntax->cmntRe = RegComp (syntax->cmnt)) == NULL) _ErrExit2 (e__regerror, syntax->cmntRe); Syntax = syntax; for(i=0; i #include #include #include "message.h" #include "regexp.h" #include "lst.h" #include "sm.h" #include "futil.h" #include "strv.h" #include "variable.h" #include "toklist.h" #include "icarus.h" #include "icaprog.h" #define _SRS #include SRSINCLUDE #define PRECEDBASE 10 extern ICAoJOB *Job; extern VARoSCOPE *globalScope; typedef struct PROGoSTATEMENT { INT4 precedence; struct VARoSTACK *stack; struct PROGoSTATEMENT *next; } PROGoSTATEMENT; static char *ProgArgName (char *name) { static INT4 classId; static struct PROGoARGNAME { char *list; /* for usage of module "list" only! */ INT4 class_id; /* for "list" module */ char *name; } *argName=NULL; if (!classId) LstManageClassFlex (&classId, sizeof (struct PROGoARGNAME), NULL, NULL, NULL); if (!LstHashSearch ((void **) &argName, name)) LstNewNamed ((void **) &argName, classId, name); return argName->name; } /**api* ProgMakePostfix ****************************************************** ** ** A linear list of symbols containing operators and operands is ** converted into a postfix stack: ** ** All tokens are processed from first to last: ** o operands are directly copied onto the postfix stack; ** o operators are temporarily placed in a temporary stack; ** however, before pushing, all operators with a execution ** priority higher or equal are popped from the temp. stack and pushed ** on the postscript stack. ** o opening and closing parentheses are pseudo operators with the ** lowest priority and need special treatment: ** * opening parent is put onto the temp. stack as a normal operator ** WITHOUT popping operators with higher or equal priority ** * closing parent pushes ALL operators from the temp stack until ** the opening parent is found, but then the opening parent is ** popped WITHOUT pushing onto the postscript stack, and the ** closing parent is never put onto the temp stack - both will be ** absent in the postscript stack. ** ** ** INPUT: address of token list [R] ** address of stack [R] ** IMPLICIT: ** ** RETURNS: 1 on success ** e__allocfail, if initialization of evaluation stack failed */ static void ProgMakePostfix(TOKoLIST *tokList, VARoSTACK *postfixStack) { static VARoSTACK *operatorStack = NULL; TOKoTOKEN *token; VARo *val, symbol, *tmp; INT4 tokCode, c; char *string; if(!operatorStack) operatorStack = VarStackNew(0); for(c=0; (token = TokNext(tokList, &c));) { tokCode = TokGetCode(token); string = TokGetStringCopy(tokList, token); if (tokCode > PROGxMINOPERAND) { /* token is an operand */ val = VarPushNew (postfixStack); switch(tokCode) { case PROGxNUM: VarSetType(val, VARxINT); VarSetStr(val, string); break; case PROGxREAL: VarSetType(val, VARxREAL); VarSetStr(val, string); break; case PROGxSTRING: VarSetStr(val, string); break; case PROGxVARIABLE: VarSetAlias (val, VarGet (&Job->scope, string), Job->scope); break; case PROGxCURLBRACEOPEN: VarSetType(val, VARxINT); VarSetCode(val, PROGxCURLBRACEOPEN); break; case PROGxCURLBRACECLOSE: VarSetType(val, VARxINT); VarSetCode(val, PROGxCURLBRACECLOSE); break; case PROGxARGNAME: VarSetStr (val, string); VarSetCode (val, PROGxARGNAME); break; case PROGxARGLISTEND: VarSetType(val, VARxINT); VarSetCode(val, PROGxARGLISTEND); break; case PROGxUSERARGLISTEND: VarSetType(val, VARxINT); VarSetCode(val, PROGxUSERARGLISTEND); break; default: break; } } /* ** if token is a separator between statements push remaining operators in ** the operator stack on the postfix stack */ else if(tokCode == PROGxSEPARATOR) { while((tmp = VarPop(operatorStack))) VarPushCopy(postfixStack, tmp); VarSetType(&symbol, VARxOPERATOR); VarSetPriority(&symbol, tokCode); VarPushCopy (postfixStack, &symbol); } /* token MUST be operator */ else { VarSetType(&symbol, VARxOPERATOR); VarSetPriority(&symbol, tokCode); if(SmEqs(string, "(")) { /* opening parent */ VarPushCopy(operatorStack, &symbol); } else if (SmEqs(string, ")")) { /* closing parent */ while((tmp = VarPop(operatorStack)) && VarGetPriority(tmp) != 1) VarPushCopy(postfixStack, tmp); } else { VarSetFunction(&symbol, IcaGetFunction(string)); /* ** pop from the operator stack until empty or until operator with ** lesser priority than the one represented by the current token */ while((tmp = VarPop(operatorStack)) && VarGetPriority(tmp) >= tokCode) VarPushCopy(postfixStack, tmp); if(tmp) /* priority lesser ...push back! */ VarPushCopy(operatorStack, tmp); VarPushCopy(operatorStack, &symbol); } } } /* Move remaining operators on the operator stack to the postfix stack */ while( (tmp = VarPop(operatorStack)) ) VarPushCopy(postfixStack, tmp); if(Job->isTraceTree) { printf("_____________________Row_Stack_______________________\n"); VarStackPrint(postfixStack); /* VarStackPrint(operatorStack); */ } return; } /**api* ProgPostfixEval ******************************************************* ** ** INPUT: address of stack ** IMPLICIT: ** RETURNS: 1 on success, otherwise _ErrRet(...) */ static INT4 ProgPostfixEval(VARoSTACK *stack) { static VARoSTACK *tmpStack = NULL; VARo *symbol; INT4 rv, c; if(!tmpStack) tmpStack = VarStackNew(0); VarStackReset(tmpStack); for (c=0; (symbol=VarInStackNext(stack, &c));) { if (VarType (symbol) == VARxOPERATOR) /* it is an operator */ rv = (*VarGetFunction(symbol))(tmpStack); else { VarPushCopy(tmpStack, symbol); } } return rv; } /****** ProgNew *************************************************************** ** ** Creates a new program object. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: program object ** */ PROGo *ProgNew() { PROGo *prog; if((prog =(PROGo *) calloc(sizeof(PROGo), 1)) == NULL) _ErrExit2(e__allocfail, "program object"); prog->statement = NULL; return prog; } /****** ProgCreate ************************************************************ ** ** ** INPUT: token list [R] ** IMPLICIT: ** ** RETURNS: program object ** */ PROGo *ProgCreate(TOKoLIST *tokList) { static VARoSTACK *postfixStack=NULL; PROGo *prog; PROGoSTATEMENT *newstatement, *statement=NULL; VARo *symbol; VARoSTACK *tmpStack, *stack; INT4 precedence=0, c1, c2; /* convert token list into a postfix stack */ if (!postfixStack) postfixStack = VarStackNew(0); ProgMakePostfix(tokList, postfixStack); symbol = VarPushNew (postfixStack); VarSetType(symbol, VARxOPERATOR); /* eliminate end-effect */ VarSetPriority (symbol, 0); /* create prog object and initialize */ prog = ProgNew(); globalScope = Job->scope; tmpStack = VarStackNew(0); for (c1=0; (symbol=VarInStackNext(postfixStack, &c1));) { /* separator ';' ...create new statement in program */ if (VarType(symbol) == VARxOPERATOR && VarGetPriority(symbol) == 0 && !VarStackIsEmpty(tmpStack)) { stack = VarStackNew(VarStackSize(tmpStack)); for (c2=0; (symbol=VarInStackNext(tmpStack, &c2));) VarPushCopy(stack, symbol); newstatement =(PROGoSTATEMENT *)calloc(sizeof(PROGoSTATEMENT), 1); newstatement->next = NULL; newstatement->precedence = precedence; newstatement->stack = stack; if(prog->statement == NULL) prog->statement = newstatement; else statement->next = newstatement; statement = newstatement; VarStackReset(tmpStack); } /* function call */ else if(VarType(symbol) == VARxOPERATOR && VarGetPriority(symbol) != 0) { precedence = VarGetPriority(symbol)/PRECEDBASE; VarPushCopy(tmpStack, symbol); } /* default action: push onto the statement's stack */ else VarPushCopy(tmpStack, symbol); } VarStackClose(tmpStack); VarStackReset (postfixStack); if(Job->isTraceTree) ProgPrintProg(prog); return prog; } /****** ProgExec ************************************************************* ** ** Executes a all statements in the program matching the current time. ** ** INPUT: program object [R] ** current execution time [R] ** IMPLICIT: ** ** RETURNS: ** */ INT4 ProgExec(PROGo *prog, INT4 time) { PROGoSTATEMENT *statement; if (!prog) return (FALSE); if (Job->isOptional && time & PROGxPOSTPARSE) return (TRUE); statement = prog->statement; while (statement != NULL) { if (statement->precedence & time) { if (Job->isTrace & 2) { printf("\n___time %d___", statement->precedence); printf("__________statement____________________(execute)\n"); VarStackPrint(statement->stack); } ProgPostfixEval(statement->stack); } statement = statement->next; } return(TRUE); } void ProgPrintProg(PROGo *prog) { VARoSTACK *stack; PROGoSTATEMENT *statement; statement = prog->statement; while(statement != NULL) { stack = statement->stack; printf("\n___time %d___", statement->precedence); printf("__________statement_______________________(print)\n"); VarStackPrint(stack); statement = statement->next; } } ** ** $RCSfile: icaprog.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:41 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #define PROGxBUILDTIME 1 #define PROGxPREPARSE 2 #define PROGxPOSTPARSE 4 #define PROGxSEPARATOR 0 enum PROGeOP { PROGxMINOPERAND=100, PROGxNUM, PROGxREAL, PROGxSTRING, PROGxVARIABLE, PROGxOBJECT, PROGxUNKNOWN, PROGxLBRACKET, PROGxRBRACKET, PROGxPARENTHESIS, PROGxARGNAME, PROGxARGLISTEND, PROGxCURLBRACEOPEN, PROGxCURLBRACECLOSE, PROGxUSERARGLISTEND }; typedef struct PROGo { struct PROGoSTATEMENT *statement; } PROGo; PROGo *ProgCreate (TOKoLIST *); INT4 ProgExec (PROGo *, INT4); void ProgPrintProg(PROGo *); PROGo *ProgNew (); char icarus_ID[] = "$Id: icarus.c,v 1.13 1996/08/11 23:24:13 etzold Exp $"; /* ** ** $RCSfile: icarus.c,v $ ** $Revision: 1.13 $ ** $Date: 1996/08/11 23:24:13 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** ** ** ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "regexp.h" #include "futil.h" #include "lst.h" #include "sm.h" #include "library.h" #include "strv.h" #include "variable.h" #include "toklist.h" #include "cursor.h" #include "icatask.h" #include "icarus.h" #include "icabnf.h" #define _SRS #include SRSINCLUDE INT4 NameListId = 0; ICAoJOB *Job; VARoSCOPE *globalScope; ICAoSYNTAX *newSyntax; SMoBUFF *IcaFunSetToken(); SMoBUFF *IcaFunSetMatch(); INT4 IcaFunGetFip(); static void IcaJobActivate (ICAoJOB *job); void LocalSetFunctions (); static void NameDump(FILE *f, void *o) { ICAoNAMELIST *t = (ICAoNAMELIST *)o; printf("Namelist: %s\n", t->name); } static void NameKill(void *o){} /**API* IcaCreateJob ********************************************************* ** ** This function creates and initializes a new job object which is ** needed for iterating through, eg, a flat file databank. A job object ** is generally needed when the parser should step through a file and ** halt at some position, eg, the entry end. **

    ** To associate the 'job' to the input (file or string) use IcaNewJob. ** ** INPUT: the syntax object [W] ** IMPLICIT: ** Job (ICAoJOB *) ** ** RETURNS: address of new job object */ ICAoJOB *IcaCreateJob(ICAoSYNTAX *syntax) { ICAoJOB *job; if ((job = (ICAoJOB *) calloc (sizeof(ICAoJOB), 1)) == NULL) _ErrExit2 (e__allocfail, "job object"); if (!NameListId) LstManageClass(&NameListId, sizeof(ICAoNAMELIST), NULL, NameKill,NameDump); job->syntax = syntax; job->parseError = 0; job->syntax->taskList = NULL; /* define icarus commands */ LocalSetFunctions (); BnfSetOpFunctions (); IcaOpLibrary(); /* initialize syntax */ if (!syntax->prod) { job->isBuildTime = TRUE; BnfBuild (syntax); job->scope = (VARoSCOPE *) VarCopyScope (syntax->scope); IcaContext ("push", &job); BnfInitRules (syntax, 0); /* run "init" programs */ IcaContext ("pop", NULL); job->isBuildTime = FALSE; } else job->scope = (VARoSCOPE *) VarCopyScope (syntax->scope); return job; } /**API* IcaJobDestroy ********************************************************* ** ** Deletes a job object. ** ** INPUT: address of the pointer to the job object [W] ** */ void IcaJobDestroy (ICAoJOB **job) { ICAoJOB *tmp; if (job && *job) { tmp = *job; if (tmp->inputCursor) CursorDelete (&tmp->inputCursor); if (tmp->tokList) TokDeleteAllLists (tmp->tokList); if (tmp->scope) VarScopeDestroy (&tmp->scope); free (tmp); *job = NULL; } } /**API* IcaDoJob ************************************************************* ** ** Activates the parser with the specified start production. Function ** requires a job object created with JobCreateJob which is already ** associated with the input (file, string) using IcaJobSetFile or ** IcaJobSetString. ** ** INPUT: the job object [W] ** the name of the start production (start symbol) [R] ** IMPLICIT: ** Job (ICAoJOB *) ** ** RETURNS: TRUE if parsing was successful ** FALSE otherwise */ INT4 IcaDoJob (ICAoJOB *job, char *startName) { BNFoPRODUCTION *start; Int4 rv; if (!(start = BnfGetProduction (job->syntax, startName, 0))) _ErrRet3 (e__objectunknown, "start production", startName); IcaContext ("push", &job); rv = BnfParseProduction (start); IcaContext ("pop", NULL); return rv; } void IcaExecProg (ICAoJOB *job) { if (job->prog) { IcaContext ("push", &job); VarExec (job->prog); IcaContext ("pop", NULL); } } void IcaContext (char *option, ICAoJOB **job) { static INT4 count=-1; static struct { ICAoJOB *job; CURSORo *cursor; VARoSCOPE *globalScope; } context[100]; switch (option[1]) { case 'u': /* push */ if (count >= 100 - 1) _ErrExit3 (f__limitexceeded, "Parsing contexts", 100); count++; context[count].job = Job; context[count].globalScope = globalScope; Job = *job; if (Job->scope) globalScope = Job->scope; break; case 'o': /* pop */ if (count) { Job = context[count].job; globalScope = context[count].globalScope; count--; if (job) *job = Job; } break; default: _ErrExit2 (e__unknownoption, option); } } static void IcaJobActivate (ICAoJOB *job) { job->parseError = 0; job->doAdvance = 1; job->isActive = 1; job->cursor = job->inputCursor; } /**API* IcaNewJob ************************************************************ ** ** Takes a job object created by IcaCreateJob and associates it ** with the input to be parsed. The input can ** be either a file or a string. The parsing itself can be initiated ** by IcaDoJob (forced parsing) or by IcaGetTokenList (lazy parsing). ** Both functions may parse through only part of the input. To continue ** call first IcaEndJob and then IcaNewJob again. **

    ** The parsing can process can be influenzed for both lazy and forced ** parsing by activating a 'task' with IcaSetTask. ** ** INPUT: o job object [W] ** o file object (file must be opened for read access) ** [R] or NULL ** o string to be parsed [R] or NULL ** IMPLICIT: ** Job (ICAoJOB *) ** ** RETURNS: TRUE - new job prepared ** FALSE - if the input (file) is exhausted */ INT4 IcaNewJob(ICAoJOB *job, FILEo *file, char *string) { job->file = file; TokGetList(INTOKLIST, &job->tokList); if (!TokIsListActive (job->tokList) || file || string) { if (TokIsListActive (job->tokList)) TokResetList (job->tokList); if (string && strlen(string) ) { TokSetStyle (job->tokList, "copy"); TokAdd (job->tokList, string, strlen (string), ICAxUNDEFCODE); } else if (file) { if (FileIsEof (file)) return(FALSE); TokSetFile(job->tokList, file); } else return(FALSE); job->inputCursor = CursorNew (); CursorInstall(job->inputCursor, TokGetFirst (job->tokList), job->tokList); } IcaJobActivate (job); return(TRUE); } /**API* IcaJobNext ************************************************************ ** ** Takes a job object created by IcaCreateJob. ** ** INPUT: job object ** IMPLICIT: ** Job (ICAoJOB *) ** ** RETURNS: TRUE - new job prepared ** FALSE - if the input (file) is exhausted */ void IcaJobNext(ICAoJOB *job) { TOKoLIST *tokList; if (IcaIsActive (job)) IcaEndJob (job); job->tokList = tokList = TokGetList (INTOKLIST, &job->tokList); if (!TokIsListActive(tokList)) { job->inputCursor = CursorNew (); CursorInstall(job->inputCursor, TokGetFirst (tokList), tokList); } IcaJobActivate (job); } /**API* IcaJobSetString ******************************************************* ** ** Sets a new input string with which to continue next job. ** ** INPUT: job object [W] ** string [R] */ void IcaJobSetString (ICAoJOB *job, char *str) { TOKoLIST *tokList; tokList = TokGetList (INTOKLIST, &job->tokList); if (TokIsListActive (tokList)) TokResetList (tokList); TokSetStyle (tokList, "copy"); TokAdd (tokList, str, strlen (str), ICAxUNDEFCODE); job->inputCursor = CursorNew (); CursorInstall (job->inputCursor, TokGetFirst (tokList), tokList); IcaJobActivate (job); } /**API* IcaJobSetFile ******************************************************** ** ** Sets a new input file with which to continue next job. ** ** INPUT: job object [W] ** string [R] */ void IcaJobSetFile (ICAoJOB *job, FILEo *file) { TOKoLIST *tokList; tokList = TokGetList (INTOKLIST, &job->tokList); if (TokIsListActive (tokList)) TokResetList (tokList); job->file = file; TokSetFile (tokList, file); job->inputCursor = CursorNew (); CursorInstall (job->inputCursor, TokGetFirst (tokList), tokList); IcaJobActivate (job); } /**api* IcaIsActive *********************************************************** ** ** Returns TRUE if the job object is active ie initiated by IcaNewJob, ** IcaNextJob. The job can be terminated by IcaEndJob. ** See also IcaNextJob. ** ** INPUT: job object [W] ** ** RETURNS: 1: active ** 0: not active */ Int4 IcaIsActive (ICAoJOB *job) { return job->isActive; } /**api* IcaIsActive *********************************************************** ** ** Returns TRUE if the input for the next job is exhausted. Applicable *** for both input from a file or from a string. ** ** INPUT: job object [R] ** ** RETURNS: 1: no more input ** 0: input still left */ Int4 IcaIsJobEnd (ICAoJOB *job) { return job->file ? FileIsEof (job->file) : CursorIsEnd (job->inputCursor); } Int4 IcaIsInputEnd (ICAoJOB *job) { return job->isInputEnd; } Int4 IcaSetInputEnd (ICAoJOB *job) { job->isInputEnd = 1; } /**API* IcaEndJob ************************************************************* ** ** Resets a job object and prepares it for the next call to IcaNewJob. ** It does NOT delete the job object. ** Use of this function should be replaced by the combination of ** IcaJobNext and IcaJobSetString. ** ** INPUT: job object [W] ** IMPLICIT: ** Job (ICAoJOB *) ** */ void IcaEndJob(ICAoJOB *job) { TOKoLIST *tokList = job->tokList; if (job->isActive) { if (tokList) { LstFirst((void **) &tokList); do { if (!SmEqs (tokList->name, INTOKLIST)) TokResetList(tokList); }while(LstNext((void **) &tokList)); } TaskDisableAll(Job->syntax->taskList); job->isActive = 0; job->isInputEnd = 0; } } /**API* IcaGetInputString ***************************************************** ** ** Returns the input string of the specified job. This is used when ** the parsing job modifies the string which must be reallocated to ** (most probably) a new address if the string grows in size. ** Must be called before IcaEndJob. ** ** INPUT: job object [W] ** ** RETURNS: the input string ** */ char *IcaGetInputString (ICAoJOB *job) { return TokGetString (job->tokList, TokGetFirst (job->tokList)); } void IcaPrintMessage (MSGo *msg) { char *fileName, fileLoc[200]=""; INT4 lnN; switch(msg->msg_code) { case e__parsererror3: /* report position in current input file */ if ((fileName = IcaGetCurrFileName ("input"))) { lnN = IcaGetCurrLineN ("input"); sprintf (fileLoc, "%s:%d: ", fileName, lnN); } break; default: /* report position in program */ if ((fileName = IcaGetCurrFileName ("prog"))) { lnN = IcaGetCurrLineN ("prog"); sprintf (fileLoc, "%s:%d: ", fileName, lnN); } break; } if (msg->msg_t == MSGxINFO) fprintf (stderr, "%s\n", msg->secmsg); else { if (*fileLoc) fprintf (stderr, fileLoc); fprintf (stderr, "error: %s, %s\n", msg->primsg, msg->secmsg); } } /**API* IcaGetTokenList ******************************************************* ** ** Retrieves a token list from the current job. If the token table ** does not yet exist it will result in the initiation of the parsing ** process. This behaviour is called "lazy parsing". The function ** requires an active 'job' which is provided by IcaNewJob. ** ** INPUT: the job object [W] ** name of the desired output token list [W] ** ** RETURNS: address of the token list ** NULL: parsing failed to produce the token list */ TOKoLIST *IcaGetTokenList (ICAoJOB *job, char *name) { TOKoLIST *tokList, *tokListRead; BNFoPRODUCTION *production; INT4 rv; IcaContext("push", &job); tokList = TokGetList(name, &job->tokList); /* if tokList is empty, activate producer production */ if( !TokIsListActive(tokList) ) { production = IcaGetSupplyNode(name); /* "parent" tokList found, it is possible to read it and to parse */ if(production->rdTokList) { tokListRead = IcaGetTokenList (job, production->rdTokList->name); if(TokIsListActive (tokListRead)) { job->cursor = CursorNew(); rv = BnfParseProdLoop (production); } } else { /* chose job input token list */ tokListRead = TokFindList(INTOKLIST, &job->tokList); job->cursor = job->inputCursor; rv = BnfParseProduction(production); } if (job->cursor != job->inputCursor) { CursorDelete(&job->cursor); job->cursor = NULL; } } IcaContext("pop", NULL); return(tokList); } /**API* IcaSetInputStreamer *************************************************** ** ** Sets a function to be called by the $In command. ** ** INPUT: o job object [W} ** o function that returns a file object and takes the ** symbolic stream name (see LibGetFileType), and ** the streamer data (see IcaSetInputStreamerData). */ void IcaSetInputStreamer (ICAoJOB *job, FILEo *(*func)(char*, void*)) { job->inputStreamer = func; } /**API* IcaSetInputStreamerData *********************************************** ** ** Sets optionally ** the data for the input streamer defined by IcaSetInputStreamer. ** ** INPUT: job object [W} ** pointer to the data object [R] */ void IcaSetInputStreamerData (ICAoJOB *job, void* data) { job->inputStreamerData = data; } /**API* IcaSetInputFile ******************************************************* ** ** Sets an input file for a job activated with IcaJobNext. ** ** INPUT: job object [W} ** pointer to the data object [R] */ void IcaSetInputFile (ICAoJOB *job, FILEo *file) { TokSetFile (job->tokList, file); if (job->file != file) { /* setting a new file */ if (job->cursor) CursorReset (job->cursor); } else if (file) CursorSetFile (job->cursor, file); job->file = file; } /**API* IcaSetTask ************************************************************ ** ** Enable or disable a 'task' for the current 'job' set by ** IcaNewJob. This function must be called BEFORE initiating the ** parsing process. ** ** INPUT: the job object [W] ** task name [R] ** flag: TRUE activates, FALSE deactivates ** IMPLICIT: ** ** RETURNS: */ void IcaSetTask (ICAoJOB *job, char *taskName, INT4 flag) { if (flag) TaskEnable (job->syntax->taskList, taskName); else TaskDisable (job->syntax->taskList, taskName); } /***** IcaCreateVariables **************************************************** ** ** ICARUS defines a few default variables: default input/output ** token list names, code of current (last) written/read token, ** $1, $2 ... sub-Matches in regular expression, ** current token string, etc. All the names of variables are ** MACRO-defined in icadef.h ** ** INPUT: ** IMPLICIT: ** ** RETURNS: */ void IcaCreateVariables() { INT4 i; char num[2]; VarSetInt(VarGet(&Job->scope, VARCODEIN), 0); VarSetInt(VarGet(&Job->scope, VARCODEOUT), 0); VarSetReadInt(VarGet(&Job->scope, "fip"), IcaFunGetFip); VarSetReadStr(VarGet(&Job->scope, VARCURRTOKEN), IcaFunSetToken); for(i=0; i < MAXKEYWORDS; i++) { sprintf(num, "%d", i); VarSetReadStr(VarGet(&Job->scope, num), IcaFunSetMatch); } } static struct ICAoNAMELIST *funcList=NULL; /* list of function pointers */ /**API* IcaSetFunction ******************************************************* ** ** Put the function pointer in the special named list ** ** INPUT: name of a function ** pointer to the function ** IMPLICIT: ** list reference Job->funcList ** ** RETURNS: */ void IcaSetFunction(char *functionName, FUNC function) { if( !LstHashSearch((void **) &funcList, functionName) ) { LstNew((void **) &funcList, NameListId); strcpy(funcList->name, functionName); funcList->pointer = (void *)function; } } /**API* IcaGetFunction ******************************************************* ** ** Get the pointer to function by it name in the list of ** function pointers. ** ** INPUT: name of a function ** IMPLICIT: ** list reference Job->funcList ** ** RETURNS: ** pointer to the function */ FUNC IcaGetFunction(char *functionName) { if (LstFirstNamed ((void **) &funcList, functionName)) return (FUNC)funcList->pointer; else return NULL; } /**API* IcaFunctionName ****************************************************** ** ** Find function name by it pointer in the function list. ** ** INPUT: function pointer ** IMPLICIT: ** list reference Job->funcList ** ** RETURNS: ** function name */ char *IcaFunctionName(FUNC function) { if( LstFirst((void **) &funcList) ) do { if(function == funcList->pointer) return(funcList->name); }while( LstNext((void **) &funcList) ); return(NULL); } /**API* IcaGetSupplyNode ***************************************************** ** ** Find a node that can supply input token list for given toklist ** ** INPUT: token list name ** IMPLICIT: ** list of production names: Job->prodList ** ** RETURNS: ** node pointer ** exit otherwise */ BNFoPRODUCTION *IcaGetSupplyNode(char *tokListName) { VARo *var; TOKoLIST *tokList; BNFoPRODUCTION *prod; INT4 c; if (Job->syntax->prod) { for (c=0; (var = VarNextInList (Job->syntax->prod, &c)); ) { prod = VarGetObject (NULL, var); if( (tokList = prod->wrtTokList) != NULL) if( !strcmp(tokListName, tokList->name) ) return(prod); } } _ErrExit3 (e__objectunknown, "Output token list", tokListName); } /**API* IcaErrPrint ********************************************************** ** ** Pretty-print function to print parsing error ** ** INPUT: production name ** fail pattern ** beginning of input token ** point where pattern fail ** IMPLICIT: ** ** RETURNS: */ void IcaErrPrint(char *nodeName, char *pattern, char *begin, char *point) { static char line[MAXPRINTSIZE+1], dots[MAXPRINTSIZE+1]; char *ptr; INT4 len, isEOL; memset(line, 0, MAXPRINTSIZE); memset(dots, 0, MAXPRINTSIZE); isEOL = FALSE; ptr = point; len = 0; if(*ptr == '\n') { ptr--; len++; isEOL = TRUE; } while(ptr > begin && len < MAXPRINTSIZE/2 && *ptr != '\n') { len++; ptr--; } if(*ptr == '\n' && len) { ptr++; len--; } if(len) { strncpy(line, ptr, len); memset(dots, '.', len); if(isEOL) line[len] = ' '; } strcat(dots, "^"); ptr = point; len = 1; while(ptrfile) return NULL; switch (option[0]) { case 'i': /* input */ return Job->file ? FileGetName (Job->file, "file") : NULL; case 'p': return Job->fileName ? Job->fileName : Job->syntax->fileName; default: _ErrExit2 (e__unknownoption, option); } } /**API* IcaGetCurrLineN ************************************************************ ** ** Returns the name of the file that is currently being parsed. ** ** INPUT: option "input" or "prog" [R] ** IMPLICIT: ** Job (ICAoJOB *job) [R] ** ** RETURNS: a file name */ INT4 IcaGetCurrLineN (char *option) { switch (option[0]) { case 'i': /* input */ return Job->file ? FileGetLineN (Job->file) : 0; case 'p': return Job->lineN; default: _ErrExit2 (e__unknownoption, option); } } INT4 IcaEval (char *prog) { static ICAoJOB *job=NULL; ICAoSYNTAX *syntax; if (!job) { syntax = (ICAoSYNTAX*)LibObjByName ("syntax", "icarus"); job = IcaCreateJob (syntax); } else IcaJobNext (job); IcaJobSetString (job, prog); IcaGetTokenList (job, "prog"); IcaExecProg (job); } INT4 IcaEvalInJob (char *prog, ICAoJOB *job) { static ICAoJOB *iJob=NULL, tmpJob; ICAoSYNTAX *syntax; if (!iJob) { syntax = (ICAoSYNTAX*)LibObjByName ("syntax", "icarus"); iJob = IcaCreateJob (syntax); iJob->scope = job->scope; } else IcaJobNext (iJob); IcaJobSetString (iJob, prog); IcaGetTokenList (iJob, "prog"); memcpy (&tmpJob, job, sizeof (ICAoJOB)); tmpJob.prog = iJob->prog; IcaExecProg (&tmpJob); } /* ** ** $RCSfile: icarus.h,v $ ** $Revision: 1.8 $ ** $Date: 1996/08/11 22:47:09 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #define ICAxMAXNAMESIZE 32 #define MAXKEYWORDS 8 #define MAXARGSNUM 32 #define MAXNAMESIZE 32 #define MAXPRINTSIZE 72 #define MAXBRANCHES 128 #define MAXLINESIZE 512 #define NODE "NODE" #define COPYSTYLE "copy" #define ECHOSTYLE "echo" #define ENDOFINPUT "\001\003\005\007\009\013" #define TMPIN "@TmpStackIn" #define TMPOUT "@TmpStackOut" #define INTOKLIST "@DefStackIn" #define OUTTOKLIST "@DefStackOut" #define VARTOKLISTIN "tli" #define VARTOKLISTOUT "tlo" #define VARCODEIN "ci" #define VARCODEOUT "co" #define VARCURRTOKEN "ct" #define ICAxUNDEFCODE -1 #define ICAxNEWPARSEERROR 1 #define ICAxPARSEERROR 2 typedef struct ICAoJOB { char *string; /* !obsolete! */ struct FILEo *file; /* file to parse */ struct ICAoNAMELIST *funcList; /* list of function pointers */ struct TOKoLIST *tokList; /* list of tokLists */ struct ICAoSYNTAX *syntax; /* ICARUS syntax */ struct SMoBUFF *codeBuff; /* token code names buffer */ struct TOKoLIST *outTokList; /* current output tokList */ struct TOKoTOKEN *inToken; /* current input token */ struct regexp *regExp; /* current regExp */ struct BNFoNODE *currNode; /* current node */ struct VARoSCOPE *scope; /* the scope containing variables */ struct CURSORo *cursor; struct CURSORo *inputCursor; /* describes input of all jobs */ char *failPattern; /* pattern that fail to parse */ INT4 parseError; /* error code */ INT4 isNew; /* flag */ INT4 isOptional; /* flag */ INT4 isBuildTime; /* flag */ INT4 isTrace; /* flag */ INT4 isTraceTree; /* flag */ INT4 isDebug; INT4 isActive; INT4 isInputEnd; INT4 doAdvance; INT4 lineN; /* curr line no of curr program */ char *fileName; /* name of current program file */ struct VARo *prog; /* Icarus program compiled by "job" */ struct FILEo *(*inputStreamer)(char*,void*); void *inputStreamerData; } ICAoJOB; typedef struct ICAoSYNTAX { char *name; /* Name of the syntax. */ char *fileName; /* Name of the file with ICA rules */ char *rules; /* Pointer to rules */ struct SMoBUFF *buff; /* Buffer with ICA productions */ struct ICAoSYNTAX *commandSyntax; /* The syntax of for the commands. */ struct ICAoNAMELIST *prodList; struct ICAoCOMMAND *userCommand; struct TASKo *taskList; /* pool of task links */ char *ign; /* Chars to be ignored */ char *cmnt; /* reg exp for comments */ INT4 initflag; struct VARo *prod; /* list of productions as var objects*/ struct VARoSCOPE *scope; struct regexp *cmntRe; char *ignAlt; /* alternative set of skip chars */ } ICAoSYNTAX; #define _ICAoSYNTAX typedef struct ICAoNAMELIST { char *list; int listId; char name[ICAxMAXNAMESIZE]; void *pointer; INT4 isInit; } ICAoNAMELIST; /* module prototypes ***************************************/ typedef struct FILEo *dummytointroducestructtagFILEo; typedef struct ICAoJOB *ICAvJOB; struct BNFoPRODUCTION *IcaGetSupplyNode(char *tokListName); FUNC IcaGetFunction(char *); char *IcaFunctionName(FUNC); char *IcaGetCodeName(INT4); void IcaCreateVariables(); void IcaErrPrint(char *nodeName, char *pattern, char *begin, char *point); void IcaSetFunction(char *, FUNC); char *IcaGetCurrFileName (); INT4 IcaInterprete (char *prog); void IcaPrintMessage (MSGo *msg); /* working with parsing jobs */ void IcaContext (char *option, ICAoJOB **job); ICAvJOB IcaCreateJob (struct ICAoSYNTAX *); void IcaEndJob (ICAvJOB); Int4 IcaNewJob (ICAvJOB, struct FILEo *, char *); void IcaJobNext(ICAoJOB *job); void IcaJobSetString (ICAoJOB *job, char *str); void IcaJobDestroy (ICAoJOB **job); void IcaSetTask (ICAvJOB, char *taskName, INT4 flag); void IcaSetInputStreamer (ICAvJOB, struct FILEo *(*func)(char*, void*)); void IcaSetInputStreamerData (ICAvJOB, void* data); void IcaSetInputFile (ICAvJOB, struct FILEo *file); struct TOKoLIST* IcaGetTokenList (ICAvJOB, char *); char* IcaGetInputString (ICAvJOB); Int4 IcaIsActive (ICAvJOB); #include #include #include #include "srs.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _FUNCTION #include "oddclass.h" ICAoSYNTAX *IcaInitSyntax (ICAoSYNTAX *); static INT4 PrintMessage (MSGo *msg); void ReadBuiltin (ICAoSYNTAX *syntax) { FILEo *file; ICAoJOB *job; SDLo *odd; Int4 opt; /* never write C-conversion */ opt = ParGetBool("ica2C"); ParDefBool("ica2C", 0); ParDefBool ("doSection", 1); /* pointers instead of numbers */ job = IcaCreateJob (syntax); /* process class information */ odd = OddInit (def, 1); file = FileNew ("SRSSDL:builtin.ic"); if (!FileOpen (file)) _ErrExit2 (e__filnotok, "SRSSDL:builtin.ic"); IcaJobSetFile (job, file); IcaGetTokenList (job, "prog"); IcaExecProg (job); /* process objects */ odd = OddInit (odd, 2); file = FileNew ("SRSSDL:builtin.i"); if (!FileOpen (file)) _ErrExit2 (e__filnotok, "SRSSDL:builtin.i"); IcaJobSetFile (job, file, NULL); IcaGetTokenList (job, "prog"); FileClose (job->file); job->file = NULL; IcaExecProg (job); ParDefBool ("ica2C", opt); } main(int argc, char **argv) { SDLo *odd; ARGoLIST *arglist; FILEo *file; ICAoJOB *job; ICAoSYNTAX *syntax; char line[MAXLINESIZE], *tokStr, *name; INT4 printAll, tokCode, c, rv; SrsEnv (); LibOpen ("srs5"); MsgSetFnct ((FUNC)IcaPrintMessage); arglist = LibObjByName ("arglist", "try"); argc = ArgGet (arglist, argc, argv); if (!ParGetBool ("useIni")) syntax = IcaInitSyntax ((ICAoSYNTAX*)LibObjByName ("syntax", "icarus")); else syntax = (ICAoSYNTAX*)LibObjByName ("syntax", "icarus"); odd = OddInit (def, 1); if (ParGetBool ("doCommandInfo")) { IargPrintInfo (); exit (0); } if (argc != 2) { ArgUsage (arglist); _ErrorExit (); } job = IcaCreateJob (syntax); file = FileNew(argv[1]); if (!FileOpen (file)) _ErrExit2 (e__filnotok, argv[1]); IcaJobSetFile (job, file); IcaGetTokenList (job, "prog"); FileClose (job->file); job->file = NULL; if (job->prog) { if (ParGetBool ("readBuiltin")) ReadBuiltin (syntax); IcaExecProg (job); } if (ParGetBool ("doClassInfo")) { odd = OddInit (odd, 2); OddWriteClassInfo (odd); } } char icatask_srs_ID[] = "$Id: icatask.c,v 1.1 1996/05/06 15:16:43 srs Exp $"; /* ** $RCSfile: icatask.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:43 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Authors: Thure Etzold ** Anatoly Ulyanov ** ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "message.h" #include "lst.h" #include "icatask.h" #define _SRS #include SRSINCLUDE /****** TaskLinkNew *********************************************************** ** ** Returns a new link object in the list of links. ** ** INPUT: link object list [W] ** IMPLICIT: ** ** RETURNS: new link object */ static TASKoLINK *TaskLinkNew (TASKoLINKS *links) { if (!links->linkAllocN) { if ((links->link = (void *) malloc (sizeof (TASKoLINK))) == NULL) _ErrExit2 (e__allocfail, "task link list"); links->linkN = 0; links->linkAllocN = 1; } else if (links->linkN >= links->linkAllocN) { links->linkAllocN *= 2; if ((links->link = (void *) realloc (links->link, links->linkAllocN * sizeof (TASKoLINK))) == NULL) _ErrExit2 (e__allocfail, "task link list"); } return &links->link[links->linkN++]; } /****** TaskIsRegister ******************************************************** ** ** Checks if the task is not already registered. ** ** INPUT: the name of the task [R] ** the syntax with which to register [W] ** IMPLICIT: ** ** RETURNS: TRUE if task registered ** FALSE otherwise ** */ INT4 TaskIsRegister (TASKo *task, char *name) { return(LstHashSearch((void **) &task, name)); } /****** TaskRegister ********************************************************** ** ** Registers a new task for the specified syntax and disables it. ** Checks first if the task is not already registered. ** ** INPUT: the name of the task [R] ** the syntax with which to register [W] ** IMPLICIT: ** ** RETURNS: the address of the flag whether the task is enabled or not ** */ static INT4 *TaskRegister (TASKo **task, char *name) { static int classId=0; if(!classId) LstManageClass (&classId, sizeof (TASKo), NULL, NULL, NULL); if (!LstHashSearch ((void **) task, name)) { LstNewNamed ((void **) task, classId, name); (*task)->isEnabled = 0; } return &((*task)->isEnabled); } /****** TaskEnable ************************************************************ ** ** Disables or deactivates a task for specified syntax. ** ** INPUT: task name [R] ** task object (list) [W] ** IMPLICIT: ** ** RETURNS: ** */ void TaskEnable (TASKo *task, char *name) { if (LstHashSearch ((void **) &task, name)) task->isEnabled = 1; } /****** TaskDisable *********************************************************** ** ** Disable or inactivates a task for specified syntax. ** ** INPUT: task name [R] ** task object (list) [W] ** IMPLICIT: ** ** RETURNS: ** */ void TaskDisable (TASKo *task, char *name) { if (LstHashSearch ((void **) &task, name)) task->isEnabled = 0; } /****** TaskDisablAll *********************************************************** ** Disable or inactivates all tasks. ** ** INPUT: task name [R] ** task object (list) [W] ** IMPLICIT: ** ** RETURNS: ** */ void TaskDisableAll(TASKo *task) { if( LstFirst((void **) &task) ) do { task->isEnabled = 0; } while( LstNext((void **) &task) ); } /**api* TaskAllocLinks ******************************************************** ** ** This function must be called during parser build time whenever ** a new link object requered for a node ** ** INPUT: ** RETURNS: */ static TASKoLINKS *TaskAllocLinks() { TASKoLINKS *links; if( (links = (TASKoLINKS *)malloc(sizeof(TASKoLINKS))) == NULL) _ErrExit2 (e__allocfail, "task links "); memset(links, NULL, sizeof(TASKoLINKS)); return(links); } /**api* TaskRequestLink ******************************************************* ** ** This function must be called during parser build time whenever ** a node (production) getting input from another production ** is associated with a task. ** This function will also register the task. ** ** INPUT: o task object (list) [W] ** o name of the task [R] ** o name of the input token list [R] ** o the token code if only tokens with that code should ** trigger the task [R] ** RETURNS: */ TASKoLINKS *TaskRequestLink (TASKo **task, char *taskName, struct BNFoPRODUCTION *currNode, TASKoLINKS *taskLinks) { TASKoLINK *link; if( !taskLinks ) taskLinks = TaskAllocLinks(); link = TaskLinkNew(taskLinks); link->node = currNode; link->isEnabledPtr = TaskRegister (task, taskName); return(taskLinks); } /**api* TaskNextActiveNode **************************************************** ** ** Returns the next (if any) active node associated with a currently ** active task and matching token code. ** ** INPUT: link object list [W] ** token code [R] ** pointer to iteration context - set to 0 to begin iter. [W] ** IMPLICIT: ** ** RETURNS: new link object */ struct BNFoPRODUCTION *TaskNextActiveNode (TASKoLINKS *linkList, INT4 *context) { TASKoLINK *link; while (1) { if (*context >= linkList->linkN) { *context = 0; return NULL; } link = &linkList->link[(*context)++]; if (*link->isEnabledPtr) break; } return link->node; } ** ** $RCSfile: icatask.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:44 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** */ typedef struct TASKo { char *list; /* for usage of module "list" only! */ INT4 class_id; /* for "list" module */ char name[30]; INT4 isEnabled; } TASKo; typedef struct TASKoLINK { struct BNFoPRODUCTION *node; INT4 *isEnabledPtr; } TASKoLINK; typedef struct TASKoLINKS { TASKoLINK *link; INT4 linkAllocN; INT4 linkN; } TASKoLINKS; /* module prototypes ***************************************/ void TaskEnable (TASKo *task, char *name); void TaskDisable (TASKo *task, char *name); void TaskDisableAll (TASKo *task); INT4 TaskIsRegister (TASKo *task, char *name); struct BNFoPRODUCTION *TaskNextActiveNode (TASKoLINKS *, INT4 *); TASKoLINKS *TaskRequestLink (TASKo **, char *, struct BNFoPRODUCTION *, TASKoLINKS *); char id_ID[] = "$Id: id.c,v 1.2 1996/08/11 22:47:10 etzold Exp $"; /* ** ** $RCSfile: id.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/08/11 22:47:10 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** functions for manupulating IDs ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "message.h" #include "sm.h" #include "futil.h" #include "binpack.h" #include "id.h" #include "library.h" /**api* IdSplit *************************************************************** ** ** splits an ID into its components; ** populates all fields of the id object; ** ** INPUT: id object [W] ** IMPLICIT: ** ** RETURNS: */ void IdSplit (IDoENTRY *id) { IDPTR tmp; tmp = id->id + id->id_d->fddbeg; _BinUnpack3Byte (tmp, id->fip); id->siz = id->id_d->siz; id->lib_x = (unsigned char) id->id[id->id_d->lbxbeg]; /* library index */ tmp = id->id + id->id_d->lxbeg; if (id->id_d->lxlen > 0) _BinUnpack2Byte (tmp, id->subentry_n); /* subentry number */ else id->subentry_n = 0; } /**api* IdBuild ** ************************************************************ ** ** builds an ID from fadd and library-index; function assumes fixed l ** lengths for all parts of the ID ...which is because of the byte anding ** and shifting - macros should be done for packing and unpacking ** numbers with a flexible byte length (as argument...switch..) ** ** INPUT: address of ID [W] ** library ID [R] ** file pointer to record in ID index [R] ** list index [R] or 0 ** ** IMPLICIT: ** ** RETURNS: 1 */ INT4 IdBuild (IDoENTRY *id, INT4 libId, UINT4 fip, INT4 list_x) { IDoTYPE *id_d=id->id_d; IDPTR tmp; id->lib_x = libId; id->fip = fip; tmp = id->id + id_d->fddbeg; /* fip */ _BinPack3Byte (tmp, fip); id->siz = id->id_d->siz; id->id[id_d->lbxbeg] = libId; /* library ID */ if (id_d->lxlen == 2) { /* subentry ID */ tmp = id->id + id_d->lxbeg; _BinPack2Byte (tmp, list_x); } return 1; } /**API* IdCopy *************************************************************** ** ** Copies an ID. ** ** INPUT: address of output ID [W] ** address of input ID [R] ** IMPLICIT: ** ** RETURNS: */ void IdCopy (IDoENTRY *a, IDoENTRY *b) { memcpy (a->id, b->id, b->siz); a->siz = b->siz; a->lib_x = b->lib_x; a->id_d = b->id_d; a->fip = b->fip; a->subentry_n = b->subentry_n; } /**API* IdToStr *************************************************************** ** ** Converts an ID into a string with a hexadecimal number. ** An ID of four byte is converted to a string 8 byte long. ** ** INPUT: address of ID-object [R] ** address of output hex number string [W] ** IMPLICIT: ** ** RETURNS: */ INT4 IdToStr (IDoENTRY *id, char *numstr) { char *tmp; INT4 k; /* ** go through each byte of ID (from first to last) convert it into ** two digit hex num - one digit numbers gets a '0' in front and copy ** it into a growing number string; */ for (k=0; k < id->id_d->siz; k++) { tmp = &numstr[k*2]; sprintf (tmp, "%2x", id->id[k]); if (*tmp == ' ') *tmp = '0'; /** prefix a "0" if it is a one digit hexnum */ } return 1; } /**API* IdFromStr ************************************************************ ** ** Converts a string with a hexadecimal number into an ID object. ** ** INPUT: address of ID object [W] ** string with hex number [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** e__novalentryidlen + */ INT4 IdFromStr (IDoENTRY *id, char *numstr) { INT4 len, k, num; char *tmp; len = strlen (numstr); id->siz = len / 2; /* ** find an appropriate id type description...this is only preliminary ** to give IdSplit the ID description with correct offsets...should ** be replaced later by correct ID type */ if (!(id->id_d = LibGetIdType (NULL, 0, id->siz))) _ErrRet3 (e__novalentryidlen, id->siz, numstr); /* ** exactly reverse SrsIDToStr ...go through number string from the ** end to the beginning in steps of two characters; */ for (k= id->siz - 1; k >= 0; k--) { tmp = &numstr[k*2]; sscanf (tmp, "%x", &num); id->id[k] = num; *tmp = '\0'; } IdSplit (id); /* ** now we can access the library-ID and assign the correct ** idType */ id->id_d = LibGetIdType (NULL, id->lib_x, id->siz); return 1; } /**api* IdIsSub ************************************************************ ** ** returns TRUE if the ID is pointing to a subentry; ** ** INPUT: address of number string [W] ** IMPLICIT: ** ** RETURNS: ID-object */ INT4 IdIsSub (IDoENTRY *id) { if (id->id_d && id->id_d->siz < 6) return 0; if (id->siz < 6) return 0; return 1; } /**api* IdGetSubN ************************************************************* ** ** Returns the subentry number; ** ** INPUT: ID object [R] ** IMPLICIT: ** ** RETURNS: subentry number */ INT4 IdGetSubN (IDoENTRY *id) { return id->subentry_n; } /**api* IdSize *************************************************************** ** ** Returns the size of the ID in bytes ** INPUT: address of ID-type object [R] ** ** RETURNS: size of ID in bytes */ Int4 IdSize (IDoTYPE *idType) { return idType->siz; } /**api* IdPatch *************************************************************** ** ** ** INPUT: address of ID-object [R] ** IMPLICIT: ** ** RETURNS: hexnumber string */ INT4 IdPatch (IDoENTRY *id, char *patchList) { return 1; } /**api* IdBuildSub ************************************************************ ** ** combines an entry-ID and a subentry number to a subentry-ID ** ** INPUT: address of ID-object [R] ** IMPLICIT: ** ** RETURNS: 0 if subEntryN is not valid ** 1 */ INT4 IdBuildSub (IDoENTRY *idSub, IDoENTRY *id, INT4 subEntryN) { static IDoTYPE *idType=NULL; IDPTR tmp; if (!idType) idType = (IDoTYPE*) LibObjByName ("idType", "SubEntry-ID"); if (subEntryN < 0 || subEntryN > 65536) return 0; memcpy ((idSub->id + idType->fddbeg), id->id, id->siz); tmp = idSub->id + idType->lxbeg; _BinPack2Byte (tmp, subEntryN); idSub->id_d = idType; idSub->siz = idType->siz; return 1; } *********************************************** ** ** $RCSfile: id.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/08/11 22:47:11 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define IDxXID 12 /* same as SRSxXID, max size of ID */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** definition of an ID type - this object class is also defined in ODD */ #ifndef _IDoTYPE #define _IDoTYPE typedef struct IDoTYPE { char *nam; INT4 siz; INT4 fddbeg; INT4 fddlen; INT4 lbxbeg; INT4 lbxlen; INT4 lxbeg; INT4 lxlen; INT4 (*cpy) (); } IDoTYPE; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Descriptor of an entry- or subentry-ID. This ID can be obtained ** from a "set" and used to open the corresponding "entry". */ typedef struct IDoENTRY { INT4 siz; /* length of the ID */ INT4 lib_x; /* (API) part of entry-ID that identifies the library where the entry resides */ UINT4 fip; /* part of entry-ID: pointer to node in ID-inx */ INT4 subentry_n; /* (API) part of subentry-ID: number of subentry within entry*/ unsigned char id[IDxXID]; /* entry-ID itself */ struct IDoTYPE *id_d; /* descriptor of entry-ID type */ } IDoENTRY; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ... */ #define _IdPatch(id, idPatch, idType) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** function prototypes */ INT4 IdBuild (IDoENTRY *id, INT4 libId, UINT4 fip, INT4 list_x); INT4 IdToStr (IDoENTRY *id, char *numstr); INT4 IdFromStr (IDoENTRY *id, char *numstr); INT4 IdIsSub (IDoENTRY *id); INT4 IdBuildSub (IDoENTRY *idSub, IDoENTRY *id, INT4 subEntryN); INT4 IdPatch (IDoENTRY *id, char *patchList); void IdSplit (IDoENTRY *id); void IdCopy (IDoENTRY *a, IDoENTRY *b); Int4 IdSize (struct IDoTYPE *idType); char ids_ID[] = "$Id: ids.c,v 1.3 1996/08/11 22:47:12 etzold Exp $"; /* ** ** $RCSfile: ids.c,v $ ** $Revision: 1.3 $ ** $Date: 1996/08/11 22:47:12 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "sm.h" #include "binpack.h" #include "futil.h" #include "tm.h" #include "id.h" #include "ids.h" #include "set.h" #include "library.h" #include "map.h" #define IDSxCURRENT_VERSION 1000000 #define IDSxMAXINFOBUFF 300 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static void IdsInfoWrite (IDSoFILE *idsFile); static INT4 IdsInfoRead (IDSoFILE *idsFile); /**api* IdsOpen *************************************************************** ** ** opens an IDS file (ID or entry pointer list); ** ** INPUT: o address of file name [R] ** o string specifying access type: ** "read", "write", "compress" [R] ** o size of cache used for writing the IDS, or NULL [R] ** o name of id-type [R] or NULL ** o address of error code [W] or NULL ** e__iscompressed ** e__indexisbusy ** e__notcompressed ** e__filopenerr ** ** IMPLICIT: ** ** RETURNS: new btree object ** NULL if there is a problem */ IDSoFILE *IdsOpen (char *name, char *option, INT4 cacheSize, char *idTypeName, INT4 *errCode) { IDSoFILE *idsFile; char fileName[FILxXNAM+1]; INT4 rv; /* main object */ if ((idsFile = (IDSoFILE *) calloc (1, sizeof (IDSoFILE))) == NULL) _ErrExit2 (e__allocfail, "idsFile-object"); sprintf (fileName, "%s.ids", name); strcpy (idsFile->fileName, _FilTempLN (fileName)); if (idTypeName) { if (!(idsFile->idType = (IDoTYPE *) LibObjByName ("idtype", idTypeName))) _ErrExit3 (e__objectunknown, "idType", idTypeName); strcpy (idsFile->idTypeName, idTypeName); } switch (tolower (option[0])) { /* ** open for read access using normal file i/o */ case 'r': if (!(idsFile->file = fopen (idsFile->fileName, "rb"))) { _ErrSet (errCode, e__filopenerr); return NULL; } rv = IdsInfoRead (idsFile); _ErrIf (rv) return NULL; if (!(idsFile->idType = (IDoTYPE *) LibObjByName ("idtype", idsFile->idTypeName))) _ErrExit3 (e__objectunknown, "idType", idTypeName); if (idsFile->isBusy) _ErrSet (errCode, e__indexisbusy); else if (!idsFile->isCompressed) { _ErrSet (errCode, e__notcompressed); return idsFile; } else return idsFile; fclose (idsFile->file); free (idsFile); return NULL; /* ** open for compression - two files must be opened */ case 'c': /* virtual memory object */ if ((idsFile->vm = (MAPo *) calloc (1, sizeof (MAPo))) == NULL) _ErrExit2 (e__allocfail, "virtual memory object"); rv = MapMem ((MAPo *) idsFile->vm, idsFile->fileName, NULL, 0); _ErrIf (rv) { free (idsFile); return NULL; } IdsInfoRead (idsFile); rv = IdsInfoRead (idsFile); _ErrIf (rv) { free (idsFile); return NULL; } idsFile->idType = (IDoTYPE *) LibObjByName ("idtype", idsFile->idTypeName); if (idsFile->isBusy) { _ErrSet (errCode, e__indexisbusy); return NULL; } else if (idsFile->isCompressed) { _ErrSet (errCode, e__iscompressed); return NULL; } #ifndef VMS /* ** delete the IDS previously opened for read access - only one ** version of the file can exist at a time (the output file) the ** input file has been just read into memory */ remove (idsFile->fileName); #endif /* cache */ if ((idsFile->cache = (MAPoCCH *) calloc (1, sizeof (MAPoCCH))) == NULL) _ErrExit2 (e__allocfail, "ids-cache-object"); idsFile->cache->nbloc = cacheSize; MapInitCache (idsFile->cache, idsFile->fileName, &idsFile->fileSize, 1); idsFile->isBusy = 1; idsFile->isCompressed = 1; idsFile->idsInsertedN = 0; IdsInfoWrite (idsFile); break; /* ** open for writing using cache */ case 'w': if (!idsFile->idType) _ErrExit2 (e__parnotdefined, "Id-type"); /* cache */ if ((idsFile->cache = (MAPoCCH *) calloc (1, sizeof (MAPoCCH))) == NULL) _ErrExit2 (e__allocfail, "ids-cache-object"); idsFile->cache->nbloc = cacheSize; rv = MapInitCache (idsFile->cache, idsFile->fileName, &idsFile->fileSize, 1); _ErrIf (rv) { free (idsFile); return NULL; } idsFile->isBusy = 1; idsFile->isCompressed = 0; IdsInfoWrite (idsFile); idsFile->idsInsertedN = 0; break; default: _ErrExit2 (e__unknownoption, option); } return idsFile; } /**api* IdsClose ************************************************************** ** ** closes an ids file; ** ** INPUT: address of IDS-file object [W] ** IMPLICIT: ** ** RETURNS: */ void IdsClose (IDSoFILE *idsFile) { idsFile->isBusy = 0; if (idsFile->cache) { _ErrMsg4 (i__wroteidfile, idsFile->fileName, (idsFile->fileSize+999)/1000, idsFile->idsInsertedN); MapCloseCache (idsFile->cache); idsFile->cache = NULL; idsFile->file = fopen (idsFile->fileName, "r+"); idsFile->timeCreated = TimeGet (); IdsInfoWrite (idsFile); } if (idsFile->set) SetDelete (idsFile->set->nam); if (idsFile->file) fclose (idsFile->file); if (idsFile->vm) idsFile->isCompressed = 1; free (idsFile); } /****** IdsInfoWrite ********************************************************** ** ** writes information about the file to the begin of file; ** writes an integer with the size of the info buffer in the front; ** ** INPUT: address of IDS-file object [R] ** IMPLICIT: ** ** RETURNS: */ static void IdsInfoWrite (IDSoFILE *idsFile) { INT4 infoBuffSize=0; char *buff, *buffOff; if ((idsFile->infoBuff = (char *) malloc (IDSxMAXINFOBUFF)) == NULL) _ErrExit2 (e__allocfail, "info-buffer"); buff = idsFile->infoBuff; _BinPackNum (buff, infoBuffSize); /* size of following buffer */ buffOff = buff; /* real start of info buffer */ _BinPackNum (buff, IDSxCURRENT_VERSION); /* version number */ _BinPackNum (buff, idsFile->fileSize); _BinPackNum (buff, idsFile->isBusy); _BinPackNum (buff, idsFile->isCompressed); _BinPackNum (buff, idsFile->idsInsertedN); _BinPackNum (buff, idsFile->timeCreated); _BinPackFixStr (buff, idsFile->idTypeName, 20); infoBuffSize = buff - buffOff; buff = idsFile->infoBuff; _BinPackNum (buff, infoBuffSize); /* size of following buffer */ if (idsFile->cache) MapCWrite (idsFile->cache, idsFile->infoBuff, infoBuffSize + 4); else if (idsFile->file) { fseek (idsFile->file, 0, 0); fwrite (idsFile->infoBuff, infoBuffSize + 4, 1, idsFile->file); } } /****** IdsInfoRead *********************************************************** ** ** compresses a linked list of IDs into a block ** ** INPUT: o address of IDS-file object [R] ** o address of ID object [R] ** o file address of previous ID in list ** or 0 if first in list [R] ** IMPLICIT: ** ** RETURNS: address of inserted ID */ static INT4 IdsInfoRead (IDSoFILE *idsFile) { INT4 infoBuffSize; char *buff; if (idsFile->vm) { /* file is already in memory */ buff = idsFile->vm->data; _BinUnpackNum (buff, infoBuffSize); } else { _BinFileUnpackNum (idsFile->file, infoBuffSize); if ((idsFile->infoBuff = (char *) malloc (infoBuffSize)) == NULL) _ErrExit2 (e__allocfail, "info-buffer"); fread (idsFile->infoBuff, infoBuffSize, 1, idsFile->file); buff = idsFile->infoBuff; } _BinUnpackNum (buff, idsFile->versionN); /* check version number */ if (idsFile->versionN != IDSxCURRENT_VERSION) _ErrRet4 (e__indexwrongversion, idsFile->fileName, idsFile->versionN, IDSxCURRENT_VERSION); _BinUnpackNum (buff, idsFile->fileSize); _BinUnpackNum (buff, idsFile->isBusy); _BinUnpackNum (buff, idsFile->isCompressed); _BinUnpackNum (buff, idsFile->idsInsertedN); _BinUnpackNum (buff, idsFile->timeCreated); _BinUnpackFixStr (buff, idsFile->idTypeName, 20); return 1; } /**api* IdsInsert ************************************************************* ** ** inserts an ID into the IDS-file ** ** INPUT: o address of IDS-file object [R] ** o address of ID object [R] ** o file address of previous ID in list ** or 0 if first in list [R] ** IMPLICIT: ** ** RETURNS: address of inserted ID */ FIP IdsInsert (IDSoFILE *idsFile, IDoENTRY *id, FIP idPrevFip) { static char nullFipBuff[4] = {0,0,0,0}; MAPoCCH *idsCache = idsFile->cache; char idFipBuff[4]; char *idPrev, *idFipBuffPtr = idFipBuff; FIP idFip; /* ** get file address of write offset, write then the address to the next ** ID (initially 0) and then the ID which is already in packed format */ MapCNew (idsCache, &idFip); MapCWrite (idsCache, nullFipBuff, 4); MapCWrite (idsCache, (char *) id->id, id->siz); /* ** if this is not the first ID in the list then the "pointer-to-next" of ** previous ID in list must be updated -> the previous ID is either still ** in cache or has been already written to the file */ if (idPrevFip) { if (!MapInCache (idsCache, idPrevFip, (void **) &idPrev)) { _BinPackFip (idFipBuffPtr, idFip); MapCUpdate (idsCache, idPrevFip, idFipBuff); MapDuplicateOverlap (idsCache, idPrevFip, idFipBuff, 4); } else _BinPackFip (idPrev, idFip); } idsFile->idsInsertedN++; return idFip; } #define IDSxTMPSETSIZE 200000 /**api* IdsCompress *********************************************************** ** ** compresses a linked list of IDs into a block ** ** INPUT: address of IDS-file object [R] ** file pointer to first ID in the list [W] ** IMPLICIT: ** ** RETURNS: number of IDs found in linked list */ INT4 IdsCompress (IDSoFILE *idsFile, FIP *idsFirstFip) { SETo *set = idsFile->set; MAPoCCH *idsCache=idsFile->cache; IDoTYPE *idType=idsFile->idType; FIP idNextFip, idFipSave; INT4 idN=0, k; char *tmpPtr, *idPtrSave; if (!set) { idsFile->set = SetNew (NULL, "temp"); set = idsFile->set; SetAlloc (set, IDSxTMPSETSIZE, idType); } else set->n = 0; /* ** get pointer to the begin of the ID list, save it... for the calculation ** of the next ID's address and unpack the address of the next ID in list */ tmpPtr = idsFile->vm->data + *idsFirstFip; /* ptr to begin of IID */ idFipSave = *idsFirstFip; idPtrSave = tmpPtr; _BinUnpackFip (tmpPtr, idNextFip); /* get fip to next ID ... pointer now at begin of ID */ do { if (!idN++) MapCNew (idsCache, idsFirstFip); /* address of first ID */ else { tmpPtr = idPtrSave + (idNextFip - idFipSave); /* address of next ID */ _BinUnpackFip (tmpPtr, idNextFip); } if (set->n >= set->allocN) SetRealloc (set, set->n + IDSxTMPSETSIZE, idType); /*_ErrExit3 (f__limitexceeded, "IDSxTMPSETSIZE", IDSxTMPSETSIZE);*/ memcpy (set->id_p + set->n++ * idType->siz, tmpPtr, idType->siz); } while (idNextFip); for (k=0; k < set->n; k++) { MapCWrite (idsCache, (char *) (set->id_p + k*idType->siz), idType->siz); idsFile->idsInsertedN++; } return idN; } /**api* IdsGet **************************************************************** ** ** compresses a linked list of IDs into a block ** ** INPUT: address of IDS-file object [R] ** file pointer to first ID in the list [W] ** IMPLICIT: ** ** RETURNS: number of IDs */ INT4 IdsGet (IDSoFILE *idsFile, IDPTR idBuff, FIP idsFip, INT4 idN) { fseek (idsFile->file, idsFip, 0); fread (idBuff, idsFile->idType->siz, idN, idsFile->file); return idN; /* or correct number, if less ? */ } /**api* IdsGetRange *********************************************************** ** ** compresses a linked list of IDs into a block ** ** INPUT: address of IDS-file object [R] ** id-buffer or NULL (no read!) [R] ** file pointer to first group of ID's [R] ** number of ID's in first group of ID's [R] ** file pointer to last group of ID's [R] ** number of ID's in last group of ID's [R] ** IMPLICIT: ** ** RETURNS: number of IDs found in linked list */ INT4 IdsGetRange (IDSoFILE *idsFile, IDPTR idBuff, FIP idsFip1, FIP idsFip2, INT4 idN1, INT4 idN2) { INT4 idBlockSize; FIP tmpFip; if (idsFip1 > idsFip2) /* obsolete */ tmpFip = idsFip1, idsFip1 = idsFip2, idsFip2 = tmpFip, idN2 = idN1; idBlockSize = idsFip2 - idsFip1 + idN2 * idsFile->idType->siz; if (idBuff) { /* read id's */ fseek (idsFile->file, idsFip1, 0); fread (idBuff, idBlockSize, 1, idsFile->file); } return idBlockSize / idsFile->idType->siz; } /**api* IdsGetFileSize ******************************************************** ** ** gets the file size in bytes; ** ** INPUT: address of IDS-file object [R] ** IMPLICIT: ** ** RETURNS: file size in bytes */ INT4 IdsGetFileSize (IDSoFILE *idsFile) { return idsFile->fileSize; } /**api* IdsGetTimeCreated ***************************************************** ** ** gets creation time; ** ** INPUT: address of IDS-file object [R] ** IMPLICIT: ** ** RETURNS: creation time */ INT4 IdsGetTimeCreated (IDSoFILE *idsFile) { return idsFile->timeCreated; } /**api* IdsGetIdN ************************************************************* ** ** gets the number of IDs; ** ** INPUT: address of IDS-file object [R] ** IMPLICIT: ** ** RETURNS: number of IDs */ INT4 IdsGetIdN (IDSoFILE *idsFile) { return idsFile->idsInsertedN; } /**api* IdsIsCompressed ******************************************************* ** ** returns TRUE if the ids file is compressed ** ** INPUT: address of ids file object [R] ** IMPLICIT: ** ** RETURNS: 1 or 0 */ INT4 IdsIsCompressed (IDSoFILE *idsFile) { return idsFile->isCompressed; } /**api* IdsIsCompressed ******************************************************* ** ** Returns the object describing the IDs stored in the file. ** ** INPUT: Ids file object [R] ** IMPLICIT: ** ** RETURNS: ID type object */ IDoTYPE *IdsGetIdType (IDSoFILE *idsFile) { return idsFile->idType; } ** ** $RCSfile: ids.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/08/11 22:47:12 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ids-file object */ typedef struct IDSoFILE { FILE *file; /* file handle to IDS file */ char *infoBuff; char idTypeName[20]; struct IDoTYPE *idType; struct MAPo *vm; struct MAPoCCH *cache; char fileName[FILxXNAM+1]; /* file name of index file */ INT4 idsInsertedN; INT4 isBusy; INT4 isCompressed; FIP fileSize; /* write offset which defines also the size of the file -> pointer after last byte */ UINT4 timeCreated; INT4 versionN; struct SETo *set; /* needed for compression */ } IDSoFILE; #ifndef _IDoENTRY typedef struct IDoENTRY *IDSdummytointroducestructtagIDoENTRY; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ IDSoFILE *IdsOpen (char *name, char *option, INT4 cacheSize, char *idTypeName, INT4 *errCode); void IdsClose (IDSoFILE *idsFile); FIP IdsInsert (IDSoFILE *idsFile, struct IDoENTRY *id, FIP previous); INT4 IdsCompress (IDSoFILE *idsFile, FIP *idsFirstFip); INT4 IdsGet (IDSoFILE *idsFile, IDPTR idBuff, FIP idsFip, INT4 idN); INT4 IdsGetRange (IDSoFILE *idsFile, IDPTR idBuff, FIP idsFip1, FIP idsFip2, INT4 idN1, INT4 idN2); /* info about ids-file */ INT4 IdsGetFileSize (IDSoFILE *idsFile); INT4 IdsGetTimeCreated (IDSoFILE *idsFile); INT4 IdsGetIdN (IDSoFILE *idsFile); INT4 IdsIsCompressed (IDSoFILE *idsFile); struct IDoTYPE *IdsGetIdType (IDSoFILE *idsFile); char idx_ID[] = "$Id: idx.c,v 1.1 1996/05/06 15:16:47 srs Exp $"; /* ** ** $RCSfile: idx.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:47 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "sm.h" #include "tm.h" #include "futil.h" #include "binpack.h" #define IDXxMAXRELNAMELEN 50 #define IDXxWRITEBUFFSIZ 500 #define IDXxREADBUFFSIZ 1 #define IDXxCURRENT_VERSION 1002 #define _IDXo typedef struct IDXo { FILE *file; /* file handle to ID file */ char fileName[FILxXNAM+1]; /* file name of ID file */ SMoBUFF *infoBuff; /* buffer for info block */ SMoBUFF *flatFileNames; /* buffer for info block */ FIP firstRecordFip; /* fip of first record in file */ INT4 isWriteOpen; /* file open for write access */ INT4 isUpdateOpen; /* file open for update access */ INT4 isBusy; INT4 maxStrLen; INT4 recordSize; /* total (fixed) record size */ INT4 recordN; /* number of ID-records in the file */ INT4 fileSize; /* file size in Bytes */ UINT4 timeCreated; INT4 versionN; char *buff; /* temporary buffer for reading/writing */ char *buffPtr; /* current offset in buffer */ INT4 buffSize; /* allocated size (n * recordSize); */ INT4 flatFileNameN; /* number of those file names */ char relName[IDXxMAXRELNAMELEN+1]; /* release name (eg, "23.0") */ } IDXo; #include "idx.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static INT4 IdxInfoRead (IDXo *idx); static void IdxInfoWrite (IDXo *idx); static void IdxWriteBlock (IDXo *idx); /**api* IdxOpen *************************************************************** ** ** opens an ID-index file; ** ** INPUT: o address of file name (without extension) [R] ** o string specifying access type: ** "read", "write", "update" [R] ** o maximum string length (reserved space) for the ID-names [R] ** or 0 ** o address of error code [W] ** IMPLICIT: ** ** RETURNS: new ID-index object ** NULL if there is a problem */ IDXo *IdxOpen (char *name, char *option, int maxStrLen, INT4 *errCode) { IDXo *idx; if ((idx = (IDXo *) calloc (1, sizeof (IDXo))) == NULL) _ErrExit2 (e__allocfail, "id-index-object"); sprintf (idx->fileName, "%s.idx", name); idx->infoBuff = BuffNew (50); idx->flatFileNames = BuffNew (20); switch (tolower (option[0])) { case 'r': /* read */ if (!(idx->file = fopen (_FilTempLN (idx->fileName), "rb"))) { _ErrSet (errCode, e__filopenerr); return NULL; } if (idx->isBusy) { _ErrSet (errCode, e__indexisbusy); return NULL; } IdxInfoRead (idx); idx->isWriteOpen = 0; idx->isUpdateOpen = 0; idx->buffSize = idx->recordSize * IDXxREADBUFFSIZ; if (!(idx->buff = (char *) malloc (idx->buffSize))) _ErrExit2 (e__allocfail, "id-index-object"); break; case 'u': if (!(idx->file = fopen (_FilTempLN (idx->fileName), "r+b"))) _ErrSet (errCode, e__filopenerr); if (idx->isBusy) { _ErrSet (errCode, e__indexisbusy); break; } IdxInfoRead (idx); idx->buffSize = idx->recordSize * IDXxREADBUFFSIZ; if (!(idx->buff = (char *) malloc (idx->buffSize))) _ErrExit2 (e__allocfail, "id-index-object"); idx->isBusy = 1; idx->isWriteOpen = 0; idx->isUpdateOpen = 1; break; case 'w': /* write */ if (!(idx->file = fopen (_FilTempLN (idx->fileName), "wb"))) { _ErrSet (errCode, e__filopenerr); return NULL; } idx->maxStrLen = maxStrLen; if (maxStrLen) { idx->recordSize = maxStrLen + 1 + 12; idx->buffSize = idx->recordSize * IDXxWRITEBUFFSIZ; if (!(idx->buff = (char *) malloc (idx->buffSize))) _ErrExit2 (e__allocfail, "id-index-object"); idx->buffPtr = idx->buff; } idx->recordN = 0; idx->isBusy = 1; idx->isWriteOpen = 1; idx->isUpdateOpen = 0; idx->flatFileNameN = 0; idx->relName[0] = '\0'; IdxInfoWrite (idx); break; default: _ErrExit2 (e__unknownoption, option); } return idx; } /**api* IdxClose ************************************************************** ** ** closes an ID-index opened for read or write access; ** ** INPUT: patch file object [W] ** IMPLICIT: ** ** RETURNS: */ void IdxClose (IDXo *idx) { if (idx->isWriteOpen || idx->isUpdateOpen) { if (idx->isWriteOpen) IdxWriteBlock (idx); /* flush buffer */ idx->isBusy = 0; idx->timeCreated = TimeGet (); IdxInfoWrite (idx); if (idx->isWriteOpen) _ErrMsg4 (i__wroteidfile, idx->fileName, (idx->fileSize+999)/1000, idx->recordN); } fclose (idx->file); free (idx); } /****** IdxInfoWrite ********************************************************** ** ** writes information about the file to the begin of file; ** writes an integer with the size of the info buffer in the front; ** ** INPUT: address of IDS-file object [R] ** IMPLICIT: ** ** RETURNS: */ static void IdxInfoWrite (IDXo *idx) { SMoBUFF *buff; INT4 size; buff = idx->infoBuff; BuffReset (buff); BuffPack (buff, "i7a50i", 0, IDXxCURRENT_VERSION, idx->fileSize, idx->isBusy, idx->recordN, idx->timeCreated, idx->recordSize, idx->relName, idx->flatFileNameN); BuffResetRead (idx->flatFileNames); BuffCat (buff, idx->flatFileNames); size = BuffLength (buff); idx->firstRecordFip = size; BuffReset (buff); BuffPack (buff, "i", size); fseek (idx->file, 0, 0); fwrite (BuffGetPtr (idx->infoBuff), size, 1, idx->file); } /****** IdsInfoRead *********************************************************** ** ** compresses a linked list of IDs into a block ** ** INPUT: o address of IDS-file object [R] ** o address of ID object [R] ** o file address of previous ID in list ** or 0 if first in list [R] ** IMPLICIT: ** ** RETURNS: address of inserted ID */ static INT4 IdxInfoRead (IDXo *idx) { INT4 size, k; SMoBUFF *buff=idx->infoBuff; fseek (idx->file, 0, 0); BuffReset (buff); BuffReadFile (buff, idx->file, 20); BuffUnpack (buff, "i2", &size, &idx->versionN); if (idx->versionN != IDXxCURRENT_VERSION && idx->versionN != 1001) _ErrRet4 (e__indexwrongversion, idx->fileName, idx->versionN, IDXxCURRENT_VERSION); BuffReadFile (buff, idx->file, size - 20); BuffUnpack (buff, "i5a50i", &idx->fileSize, &idx->isBusy, &idx->recordN, &idx->timeCreated, &idx->recordSize, idx->relName, &idx->flatFileNameN); BuffCat (idx->flatFileNames, buff); idx->firstRecordFip = BuffLength (buff); /* compatibility with old version */ if (idx->versionN == 1001) idx->firstRecordFip += 4; fseek (idx->file, idx->firstRecordFip, 0); return 1; } /**api* IdxWriteBlock ********************************************************* ** ** writes a block with ID-records to file ** ** INPUT: address of IDX-file object [R] ** IMPLICIT: ** ** RETURNS: */ static void IdxWriteBlock (IDXo *idx) { int size; size = (unsigned long) idx->buffPtr - (unsigned long) idx->buff; fwrite (idx->buff, size, 1, idx->file); idx->buffPtr = idx->buff; idx->fileSize += size; } /**API* IdxPutBuff ************************************************************ ** ** Puts the contents of a "buff" object into the index file as a ** record. ** ** INPUT: address of IDX-file object [R] ** address of "buff" object [R] ** IMPLICIT: ** ** RETURNS: file pointer to inserted record */ FIP IdxPutBuff (IDXo *idx, SMoBUFF *buff) { static INT4 isInit=0; INT4 size = BuffLength (buff); if (!isInit) { idx->recordSize = size; idx->buffSize = idx->recordSize * IDXxWRITEBUFFSIZ; if (!(idx->buff = (char *) malloc (idx->buffSize))) _ErrExit2 (e__allocfail, "id-index-object"); idx->buffPtr = idx->buff; isInit = 1; } else if (idx->recordSize != size) { _ErrExit4 (e__novalvar3, "IDX record size", size, idx->recordSize); } if ((unsigned long) idx->buffPtr - (unsigned long)idx->buff >= idx->buffSize) IdxWriteBlock (idx); memcpy (idx->buffPtr, BuffGetPtr (buff), size); idx->buffPtr += size; return ++(idx->recordN); } /**API* IdxGetBuff ************************************************************ ** ** Retrieves a record from the index. ** ** INPUT: address of IDX-file object [R] ** IMPLICIT: ** ** RETURNS: file pointer to inserted record */ void IdxGetBuff (IDXo *idx, FIP fip, SMoBUFF *buff) { fip = idx->firstRecordFip + (fip-1) * idx->recordSize; fseek (idx->file, fip, 0); BuffReadFile (buff, idx->file, idx->recordSize); } /**api* IdxPut *********************************************************** ** ** Puts an entry name, two file pointers and a file index ** into the index file as a record; ** ** INPUT: address of IDX-file object [R] ** address of "buff" object [R] ** IMPLICIT: ** ** RETURNS: file pointer to inserted record */ FIP IdxPut (IDXo *idx, char *name, FIP textFip, FIP dataFip, int fileX) { if (strlen (name) > idx->maxStrLen) _ErrExit (e__error); if ((unsigned long) idx->buffPtr - (unsigned long)idx->buff >= idx->buffSize) IdxWriteBlock (idx); _BinPackFip (idx->buffPtr, textFip); _BinPackFip (idx->buffPtr, dataFip); _BinPackNum (idx->buffPtr, fileX); _BinPackFixStr (idx->buffPtr, name, idx->maxStrLen); return ++(idx->recordN); } /**api* IdxGet *********************************************************** ** ** puts a new ids record at the end of file ** ** INPUT: address of IDX-file object [R] ** IMPLICIT: ** ** RETURNS: file pointer to inserted record */ void IdxGet (IDXo *idx, FIP fip, char *name, FIP *textFip, FIP *dataFip, int *fileX) { FIP tFip, dFip; int fX; fip = idx->firstRecordFip + (fip-1) * idx->recordSize; fseek (idx->file, fip, 0); fread (idx->buff, 1, idx->recordSize, idx->file); idx->buffPtr = idx->buff; if (textFip) _BinUnpackFip (idx->buffPtr, *textFip); else _BinUnpackFip (idx->buffPtr, tFip); if (dataFip) _BinUnpackFip (idx->buffPtr, *dataFip); else _BinUnpackFip (idx->buffPtr, dFip); if (fileX) _BinUnpackNum (idx->buffPtr, *fileX); else _BinUnpackNum (idx->buffPtr, fX); if (name) _BinUnpackFixStr (idx->buffPtr, name, idx->maxStrLen); return; } /**API* IdxGetRecordN ********************************************************* ** ** Returns number of records in the IDX-file. ** ** INPUT: address of IDX object [R] ** IMPLICIT: ** ** RETURNS: number of records */ INT4 IdxGetRecordN (IDXo *idx) { return idx->recordN; } /**API* IdxGetTimeCreated ***************************************************** ** ** Returns creation time of IDX file. ** ** INPUT: address of IDX object [R] ** IMPLICIT: ** ** RETURNS: number of records */ UINT4 IdxGetTimeCreated (IDXo *idx) { return idx->timeCreated; } /**api* IdxTouch ************************************************************** ** ** sets the internal index time to current time; ** ** INPUT: address of Idx object [W] ** IMPLICIT: ** ** RETURNS: */ void IdxTouch (char *fileName) { IDXo *idx; INT4 errCode; if (!(idx = IdxOpen (fileName, "update", 0, &errCode))) _ErrExit2 (errCode, fileName); idx->timeCreated = TimeGet (); IdxClose (idx); } /**api* IdxSetReleaseName ***************************************************** ** ** sets a release name (typically a number, eg, "23.0"; ** ** INPUT: address of idx object [R] ** IMPLICIT: ** ** RETURNS: */ void IdxSetReleaseName (IDXo *idx, char *relName) { if (strlen (relName) > IDXxMAXRELNAMELEN) _ErrExit3 (e__strtoolong, relName, IDXxMAXRELNAMELEN); strcpy (idx->relName, relName); } /**API* IdxGetReleaseName ***************************************************** ** ** Return release name (release number) of IDX file. ** ** INPUT: address of IDX object [R] ** IMPLICIT: ** ** RETURNS: release name */ char *IdxGetReleaseName (IDXo *idx) { return idx->relName; } /**api* IdxGetFlatFileNameN *************************************************** ** ** gets release name; ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: release name */ INT4 IdxGetFlatFileNameN (IDXo *idx) { return idx->flatFileNameN; } /**api* IdxGetFlatFileName **************************************************** ** ** get the next file name. ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: file name ** or NULL if no more names */ char *IdxGetFlatFileName (IDXo *idx, INT4 *c) { char *s=NULL; INT4 k; if (idx->flatFileNameN) { if (*c == 0) { BuffResetRead (idx->flatFileNames); *c = 1; } if (!BuffUnpack (idx->flatFileNames, "z", &s)) { *c = 0; s = NULL; } } return s; } /**api* IdxSetFlatFileName **************************************************** ** ** gets release name; ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: index that new file name receives in the list (first=0) */ INT4 IdxSetFlatFileName (IDXo *idx, char *flatFileName) { BuffPack (idx->flatFileNames, "a", flatFileName); return ++idx->flatFileNameN; } /**api* IdxWriteFlatFileNames ************************************************* ** ** Commits accumulated file names to index file; ** ** INPUT: address of Btree object [R] ** IMPLICIT: ** ** RETURNS: index that new file name receives in the list (first=0) */ INT4 IdxWriteFlatFileNames (IDXo *idx) { IdxInfoWrite (idx); return idx->flatFileNameN; } ** ** $RCSfile: idx.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:48 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ struct IDXo *IdxOpen (char *name, char *option, int maxStrLen, INT4 *errCode); void IdxClose (struct IDXo *idx); void IdxTouch (char *fileName); FIP IdxPutBuff (struct IDXo *idx, struct SMoBUFF *buff); void IdxGetBuff (struct IDXo *idx, FIP fip, struct SMoBUFF *buff); FIP IdxPut (struct IDXo *idx, char *name, FIP textFip, FIP dataFip, int fileX); void IdxGet (struct IDXo *idx, FIP fip, char *name, FIP *textFip, FIP *dataFip, int *fileX); /* get and set of some individual attributes */ char *IdxGetReleaseName (struct IDXo *idx); void IdxSetReleaseName (struct IDXo *idx, char *relName); UINT4 IdxGetTimeCreated (struct IDXo *idx); INT4 IdxGetRecordN (struct IDXo *idx); INT4 IdxSetFlatFileName (struct IDXo *idx, char *fileName); char *IdxGetFlatFileName (struct IDXo *idx, INT4 *context); INT4 IdxWriteFlatFileNames (struct IDXo *idx); INT4 IdxGetFlatFileNameN (struct IDXo *idx); char index_srs_ID[] = "$Id: index.c,v 1.5 1996/08/12 19:03:45 etzold Exp $"; /* ** ** $RCSfile: index.c,v $ ** $Revision: 1.5 $ ** $Date: 1996/08/12 19:03:45 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message, parser, map ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** module for building index-files ** ** index of type KEY or TREE consists of two files: ** seqlibname_indexname.inx and *.ids ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "sm.h" #include "futil.h" #include "binpack.h" #include "btree.h" #include "id.h" #include "ids.h" #include "hash.h" #include "index.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** declaration of global or module wide variables */ static INXo *indexCurr; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static INT4 InxHashSearch (void *value, void *record, HSHo *table); static void InxIdListUpdate (BTRoVALUE *idList, void *record); static void InxBtreeInsert (HSHo *table); /************************************************************ ** definitions and functions for use of hash table */ typedef struct { BTRoVALUE idList; INT4 value; } HASHNUMOBJ; typedef struct { BTRoVALUE idList; double value; } HASHREALOBJ; typedef struct { BTRoVALUE idList; char value[1]; } HASHSTROBJ; typedef struct { BTRoVALUE idList; } HASHANYOBJ; INT4 myhash_func (HSHo *table, void *obj) { register unsigned long h=0, g, i; register char *p; INT4 len; switch (indexCurr->valueType) { case BTRxSTR: case BTRxIDENTRY: p = ((HASHSTROBJ*) obj)->value; len = strlen(p); break; case BTRxNUM: p = (char*) &((HASHNUMOBJ*) obj)->value; len = sizeof(((HASHNUMOBJ*) obj)->value); break; case BTRxREAL: p = (char*) &((HASHREALOBJ*) obj)->value; len = sizeof(((HASHREALOBJ*) obj)->value); break; } for (i=0; i> 24)) ^ g; } return (INT4) h % table->max_hash_elem; } INT4 mycompare_func(void *obj1, void *obj2) { switch (indexCurr->valueType) { case BTRxSTR: case BTRxIDENTRY: return strcmp( ((HASHSTROBJ*)obj1)->value, ((HASHSTROBJ*)obj2)->value ); case BTRxNUM: return ((HASHNUMOBJ*)obj1)->value - ((HASHNUMOBJ*)obj2)->value; case BTRxREAL: if ( ((HASHREALOBJ*)obj1)->value < ((HASHREALOBJ*)obj2)->value ) return -1; if ( ((HASHREALOBJ*)obj1)->value > ((HASHREALOBJ*)obj2)->value ) return 1; return 0; } return -9999; /* no legal valueType */ } INT4 myprint_func(void *obj) { if (!obj) { printf("no object\n"); return 0; } else switch (indexCurr->valueType) { case BTRxSTR: case BTRxIDENTRY: printf("%s\n", ((HASHSTROBJ*) obj)->value); break; case BTRxNUM: printf("%20d\n", ((HASHNUMOBJ*) obj)->value); break; case BTRxREAL: printf("%20.2f\n", ((HASHREALOBJ*) obj)->value); break; } return 1; } INT4 mydelete_func(void *obj) { return 1; } /****** InxHashSearch ************************************************** ** ** searches an element in hash table and inserts the element, ** if not found. The hash table must be initialized before ** in InxOpen. ** ** INPUT: address of keyword [R] ** address of pointer to hash table [R] ** IMPLICIT: ** ** OUTPUT: ** returns: 1 if keyword was found ** 0 if new element was added */ static INT4 InxHashSearch (void *value, void *record, HSHo *table) { HASHANYOBJ *insertObj, *foundObj=NULL; BTRoVALUE *idList; INT4 errCode, size; FIP fip; /* ** construct object to search for depending on index value type. ** search for the object in the existing hash table */ switch (indexCurr->valueType) { case BTRxSTR: case BTRxIDENTRY: size = sizeof (HASHSTROBJ) + strlen((char*)value); insertObj = (HASHANYOBJ*) malloc (size); strcpy (((HASHSTROBJ*) insertObj)->value, (char*)value); break; case BTRxNUM: insertObj = (HASHANYOBJ*) malloc (sizeof(HASHNUMOBJ)); ((HASHNUMOBJ*) insertObj)->value = atol((char*)value); break; case BTRxREAL: insertObj = (HASHANYOBJ*) malloc (sizeof(HASHREALOBJ)); ((HASHREALOBJ*) insertObj)->value = atof((char*)value); break; } if ((foundObj = HshSearchObject(table, (void*)insertObj))) { free((void*)insertObj); InxIdListUpdate(&((HASHANYOBJ*)foundObj)->idList, record); } else { if (!indexCurr->idsFile) indexCurr->idsFile = IdsOpen (indexCurr->fileName, "write", indexCurr->idsCacheSize, ((IDoENTRY *) record)->id_d->nam, &errCode); HshInsertObject(table, (void*)insertObj); idList = &insertObj->idList; fip = IdsInsert (indexCurr->idsFile, (IDoENTRY *) record, 0); idList->firstIdFip = idList->lastIdFip = fip; idList->idN = 1; } /* ERROR HANDLING ????????????? */ return foundObj ? 1 : 0; } /**api* InxInsertStr ********************************************************** ** ** searches a key in an index and inserts a new node if not found; ** ** INPUT: address of index object (INXo) [W] ** address of value string [R] ** address of ID object [R] ** IMPLICIT: ** indexCurr (INXo *) current index object [W] ** ** RETURNS: 1 if value was found in tree ** 0 if it was newly inserted */ INT4 InxInsertStr (INXo *inx, char *value, IDoENTRY *id) { INT4 rv, errCode; /* ** ...check index */ if (!inx->isWriteOpen) _ErrExit2 (e__notwriteopen, inx->fileName); if (!inx->type) _ErrExit2 (e__parnotdefined, "index type"); indexCurr = inx; /** make index object wide */ if (!indexCurr->idsFile) indexCurr->idsFile = IdsOpen (indexCurr->fileName, "write", indexCurr->idsCacheSize, id->id_d->nam, &errCode); if ((rv = InxHashSearch (value, id, inx->table))) inx->valueFoundN++; else inx->valueInsertedN++; return rv; } /****** InxIdListUpdate ****************************************************** ** ** updates idList ** ** INPUT: pointer to BTRoVALUE ** address of new id-record ** IMPLICIT: ** indexCurr (INXo *) [W] ** ** RETURNS: */ static void InxIdListUpdate(BTRoVALUE *idList, void *record) { FIP fip; if (indexCurr->valueType == BTRxIDENTRY) return; fip = IdsInsert(indexCurr->idsFile, (IDoENTRY*) record, idList->lastIdFip); idList->lastIdFip = fip; idList->idN++; } /****** InxBtreeInsert ****************************************************** ** ** ** INPUT: pointer to hash table [R] ** IMPLICIT: ** indexCurr (INXo *) [R] ** ** RETURNS: */ static void InxBtreeInsert (HSHo *table) { HASHANYOBJ *obj; BTRoREC record; char valStr[80]; INT4 i; for (i=0; i < table->cur_hash_elem; i++) { obj = (HASHANYOBJ*) table->hash_list[i]; switch (indexCurr->valueType) { case BTRxNUM: sprintf (valStr, "%d", ((HASHNUMOBJ*) obj)->value); record.str = valStr; break; case BTRxREAL: sprintf (valStr, "%f", ((HASHREALOBJ*) obj)->value); record.str = valStr; break; case BTRxIDENTRY: case BTRxSTR: record.str = ((HASHSTROBJ*) obj)->value; break; } record.type = BTRxVALUE; memcpy (&record.r.value, &obj->idList, sizeof (BTRoVALUE)); BtrInsertRecord (&record); } } /**api* InxSetType ************************************************************ ** ** searches a key in an index and inserts a new node if not found; ** ** INPUT: address of index object (INXo) ** index type: "id", "string", "number", "real" [R] ** IMPLICIT: ** ** RETURN: */ void InxSetType (INXo *inx, char *option) { if (inx->type) _ErrExit2 (e__parisdefined, "index type"); switch (tolower (option[0])) { case 'i': case 's': inx->type = BTRxVALUE; inx->valueType = BTRxSTR; break; case 'n': inx->type = BTRxVALUE; inx->valueType = BTRxNUM; break; case 'r': inx->type = BTRxVALUE; inx->valueType = BTRxREAL; break; default: _ErrExit2 (e__unknownoption, option); } } /**api* InxSetCache *********************************************************** ** ** sets the cache with specified size for the ID-list ** ** INPUT: address of index object (INXo) ** cache size in ? [R] ** IMPLICIT: ** ** RETURN: */ void InxSetCache (INXo *inx, INT4 cacheSize) { inx->idsCacheSize = cacheSize; } /**api* InxClose ************************************************************** ** ** close index and ids-file (if not INXxID); ** ** INPUT: address of index description (INXo) [W] ** IMPLICIT: ** indexCurr (INXo *inx) [W] ** ** RETURNS: 1 if success */ INT4 InxClose (INXo *inx) { BTRo *btree; INT4 errCode; if (!inx || /*!inx->valueInsertedN ||*/ !inx->table) return 0; btree = BtrOpen (inx->fileName, "write", &errCode); _ErrExit2 (errCode, FileGetName (btree->file, "path")); switch (inx->valueType) { case BTRxIDENTRY: case BTRxSTR: BtrSetType (btree, "str"); break; case BTRxNUM: BtrSetType (btree, "num"); break; case BTRxREAL: BtrSetType (btree, "real"); break; } indexCurr = inx; HshSort(inx->table); /* TEST TEST */ #ifdef xxx printf("********* after sort ***********\n"); HshLength(inx->table); HshPrintAll(inx->table); #endif /* TEST TEST */ BtrBuildStartPhase1 (btree, inx->valueInsertedN); InxBtreeInsert (inx->table); BtrBuildStartPhase2 (); InxBtreeInsert (inx->table); BtrClose (btree); if (!inx->idsFile) inx->idsFile = IdsOpen (inx->fileName, "write", inx->idsCacheSize, "Entry-ID", &errCode); IdsClose (inx->idsFile); return 1; } /**api* InxOpen *************************************************************** ** ** opens an index and return an index object ** ** INPUT: name of index file name [R] ** option: "new" [R] ** IMPLICIT: ** ** RETURNS: 1 */ INXo *InxOpen (char *nam, char *option) { INXo *inx; switch (tolower (option[0])) { /* ** write new index */ case 'n': if ((inx = (INXo *) calloc (1, sizeof (INXo))) == NULL) _ErrExit2 (e__allocfail, "index-object"); inx->valueType = 0; inx->type = 0; inx->isWriteOpen = 1; strcpy (inx->fileName, nam); inx->table = HshNewTable(5013, 70, myhash_func, mycompare_func, myprint_func, mydelete_func); break; default: _ErrExit2 (e__unknownoption, option); } return inx; } ** ** $RCSfile: index.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:49 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** Implementing HashTable instead of AVL Tree: Gerald Schaefer ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define INXxXKEY 80 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** describes an index of all types */ typedef struct INXo { struct HSHo *table; /* hash table */ char fileName[133]; /* name of index output file */ char patchName[133]; INT4 type; /* index type */ INT4 valueType; /* value type */ INT4 valueInsertedN; /* no of inserted values */ INT4 valueFoundN; /* no of times value was found in index */ INT4 isWriteOpen; /* flag if index is open for "write" */ struct IDSoFILE *idsFile; struct IDPoFILE *idpFile; FIP idFip; /* INT4 avlOff; obsolete */ /* INT4 nodeCnt; obsolete */ INT4 idsCacheSize; } INXo; #ifndef IDoENTRY typedef struct IDoENTRY *dummytointroducestructtagIDoENTRY; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ /* manipulating indices */ INXo *InxOpen (char *nam, char *option); INT4 InxClose (INXo *inx); void InxSetType (INXo *inx, char *option); void InxSetCache (INXo *inx, INT4 cacheSize); void InxSetPatch (INXo *inx, char *patchName); /* inserting */ INT4 InxInsertStr (INXo *inx, char *value, struct IDoENTRY *id); FIP InxInsertId (INXo *inx, char *str, struct BTRoID *idRec); /* searching */ struct BTRoID *InxSearchId (INXo *inx, char *str, FIP *idFip); char library_ID[] = "$Id: library.c,v 1.12 1996/08/11 22:47:14 etzold Exp $"; /* ** ** $RCSfile: library.c,v $ ** $Revision: 1.12 $ ** $Date: 1996/08/11 22:47:14 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port by Lukas Rosenthaler and Reinhard ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: message, file, sm ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** functions open flat files and indices for read access only - compare ** time stamps and retrieve entry information from ID-indices ** ** Global Parameters: ** "printf" ** "parSetFields" - fields are turned on/off by parameters ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "strv.h" #include "lst.h" #include "tm.h" #include "btree.h" #include "sdlget.h" #include "ids.h" #include "idx.h" #include "par.h" #include "dict.h" #include "library.h" #define _SRS #define _SLB #include SRSINCLUDE #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #ifdef sun extern INT4 printf (); #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** constants and enums */ #define LIBxMAXINXOPEN 10 /* max no of indices opened */ #define LIBxMAXFILESOPEN 20 /* max no of indices opened */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** description of a library flat file opened for read access */ typedef struct { FILEo *file; /* file object...opened with FilURead */ struct SLBo *lib; /* address of library object */ INT4 fileX; /* index to file within library */ struct SRSoFILTYP *fileType; /* address of file type object */ } LIBoFLATFILE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external, global and module wide variables */ #ifdef O_WIN struct WINo *winBase; #endif SRSoDB *srsdb; INT4 SdlGetObjects (long int **obj_n, void ***obj_p, char *sec_nm); static INT4 LibGetTokenCode (char *tokName); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** for the 'group' dictionarya */ static void* GroupToKey (DictElem* e) { return (*(SRSoGROUP **)e)->com; } static CLASSoDICT groupDictClass = { (ValComparer)strequal, (ValHasher)strhash, (KeyAccessor)GroupToKey, NULL, 0 }; static DICTv groupDict=NULL; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** default function for printing lines */ static INT4 LibPrint (char *s) { Int4 len; len = strlen (s); if (len) { if (s[len-1] != '\n') puts (s); else fwrite (s, len, 1, stdout); } return 1; } static INT4 LibPrintf (char *formatStr, ...) { va_list ap; va_start (ap, formatStr); vprintf (formatStr, ap); va_end (ap); if (formatStr[strlen (formatStr) -1] != '\n') putc ('\n', stdout); return 1; } /**api* LibIndexOpen ********************************************************** ** ** opens the btree and the ids file (if not ID field) but first checks ** if these are in a list of up to MAXINXOPEN open files; ** ** INPUT: library object [R] ** field object [R] or NULL to open auxilliary index ** flag if opening for info only [R] ** IMPLICIT: ** ** RETURNS: lib index object ** or NULL */ LIBoINDEX *LibIndexOpen ( SLBo *lib, SLBoFIELD *field, INT4 isForInfo) { static LIBoINDEX libInx[LIBxMAXINXOPEN], *libInxPtr; static INT4 libInxCnt = 0; BTRo *btree=NULL; IDSoFILE *idsFile = NULL; struct IDXo *idx = NULL; char indexName[132]; INT4 errCode, k, isIdIndex; /* ** check if requested index is among those that are already open...index ** is defined by library and field objects */ for (k=0; k < LIBxMAXINXOPEN && k < libInxCnt; k++) if (lib == libInx[k].lib && field == libInx[k].field) return &libInx[k]; /* ** open both btree and ids file (if ID field also the IDX file */ /* open auxilliary index if field not specified */ if (!field) { LibGetIndexName (lib, NULL, indexName, "read"); if (!(idx = IdxOpen (indexName, "read", 0, &errCode))) { if (!isForInfo) _ErrMsg2 (errCode, indexName); return NULL; } } else { LibGetIndexName (lib, field, indexName, "read"); btree = BtrOpen (indexName, "read", &errCode); if (_ErrIs (errCode)) { if (!isForInfo) _ErrMsg2 (errCode, FileGetName (btree->file, "path")); return NULL; } isIdIndex = 0; if (!(idsFile = IdsOpen (indexName, "read", 0, NULL, &errCode))) { if (!isForInfo) _ErrMsg2 (errCode, indexName); return NULL; } if (_ErrIs (errCode) && !isForInfo) { /* index is not compressed */ _ErrMsg2 (errCode, indexName); return NULL; } if (LibIsField (field, "id")) { isIdIndex = 1; if (!(idx = IdxOpen (indexName, "read", lib->maxNameLen, &errCode))) { if (!isForInfo) _ErrMsg2 (errCode, indexName); return NULL; } if (LibHasNoFiles (lib)) LibSetLibFlatFiles (lib, idx); } } /* ** get new lib index object ...if all are in use then close btree and ** ids file (if opened) */ libInxPtr = &libInx[libInxCnt % LIBxMAXINXOPEN]; if (libInxCnt++ >= LIBxMAXINXOPEN) { if (libInxPtr->btree) BtrClose (libInxPtr->btree); if (libInxPtr->idsFile) { IdsClose (libInxPtr->idsFile); libInxPtr->idsFile = NULL; } if (libInxPtr->idx) { IdxClose (libInxPtr->idx); libInxPtr->idx = NULL; } } libInxPtr->isIdIndex = isIdIndex; libInxPtr->idsFile = idsFile; libInxPtr->idx = idx; libInxPtr->btree = btree; libInxPtr->lib = lib; libInxPtr->field = field; return libInxPtr; } /**API* LibName *************************************************************** ** ** Returns the library name. ** ** INPUT: library object [R] ** IMPLICIT: ** ** RETURNS: library name if found ** NULL if the library name is unknown */ char *LibName (SLBo *lib) { return lib->nam; } /**API* LibGetLinkFromName **************************************************** ** ** Returns the "from" name of a link. This name is usually a databank ** name but can also be a symbolic one, such as "parent" or "tax_parent". ** ** INPUT: link object [R] ** ** RETURNS: the name or empty string if there is none */ char *LibGetLinkFromName (LINKo *link) { return (link->nam1 ? link->nam1 : ""); } /**API* LibGetLinkToName ***************************************************** ** ** Returns the "to" name of a link. See also LibGetLinkFromName. ** ** INPUT: link object [R] ** ** RETURNS: the name or empty string if there is none */ char *LibGetLinkToName (LINKo *link) { return (link->nam2 ? link->nam2 : ""); } /**API* LibGetName ************************************************************ ** ** Returns the library name in various formats. ** ** INPUT: address of library object [R] ** option: "full", "short", "logical" [R] ** IMPLICIT: ** ** RETURNS: library name if found ** NULL if the library name is unknown */ char *LibGetName (SLBo *lib, char *option) { switch (tolower (option[0])) { case 'f': /* full */ return lib->nam; case 's': /* short */ return NULL; case 'l': /* logical */ return NULL; default: _ErrExit2 (e__unknownoption, option); return NULL; } } /**API* LibGetIcarusFileName ************************************************** ** ** Returns the name of the icarus file which has the specified ** information for a library. The function uses information in ** the section if specified otherwise it makes an 'educated guess' so ** the file with the returned name is not guaranteed to exist. ** ** INPUT: address of library object [R] ** option: "info", "syntax", "structure" [R] ** IMPLICIT: ** ** RETURNS: the full file name (path) */ char *LibGetIcarusFileName (SLBo *lib, char *option) { static STRv name=NULL; if (!name) name = StrNew (); else StrClear (&name); StrSetS (&name, "SRSDB:"); StrAppS (&name, SmEdit (LibName (lib), SMxLOWCASE)); switch (tolower (option[1])) { case 'n': /* info */ StrAppS (&name, ".it"); break; case 'y': /* syntax */ StrAppS (&name, ".is"); break; case 't': /* structure */ StrAppS (&name, ".i"); break; default: _ErrExit2 (e__unknownoption, option); return NULL; } return _Str(name); } /**API* LibGetGroupName ******************************************************* ** ** Returns the library group name in various formats. ** ** INPUT: address of library object [R] ** option: "full", "short" [R] ** IMPLICIT: ** ** RETURNS: library name if found ** NULL if the library name is unknown */ char *LibGetGroupName (SRSoGROUP *group, char *option) { switch (tolower (option[0])) { case 'f': /* full */ return group->com; case 's': /* short */ return group->short_nm; default: _ErrExit2 (e__unknownoption, option); return NULL; } } /**API* LibGetFieldName ******************************************************* ** ** Returns the name of a data-field. Returns "unknown" if the field ** name could not be found. See also LibGetFieldTypeName. ** ** INPUT: address of field object [R] ** IMPLICIT: ** ** RETURNS: field name */ char *LibGetFieldName (SLBoFIELD *field) { static char unknown[30] = "unknown field"; if (field && field->type && field != (SLBoFIELD *) 1L) { if (field->type->ityp == SRSxHEADER) return (field->name); else return field->type->nam; } else return unknown; } /**API* LibGetFieldTypeName *************************************************** ** ** Returns the name of a data-field type. ** ** INPUT: address of field type object [R] ** IMPLICIT: ** ** RETURNS: field name */ char *LibGetFieldTypeName (SRSoFLD *type) { return type->nam; } /**API* LibGetFieldShortName ************************************************** ** ** Returns the short name of a data-field. ** ** INPUT: address of field object [R] ** IMPLICIT: ** ** RETURNS: short field name */ char *LibGetFieldShortName (SLBoFIELD *field) { if (field->type->ityp == SRSxHEADER) return (field->name); else return field->type->shortn; } /**API* LibGetFieldIType ****************************************************** ** ** Returns the index type of a field as string. ** ** INPUT: address of field object [R] ** IMPLICIT: ** ** RETURNS: field name ** NULL */ char *LibGetFieldIType (SLBoFIELD *field) { static char *fieldIType[10]={"", "id", "index", "link", "show", "tree", "num", "real", "group"}; return fieldIType[field->index]; } /**api* LibOpenFlatFile ******************************************************* ** ** Opens a flat file. ** More than one file may be open at a time - ** so if limit is exceeded some files ** have to be closed again; ** selects global "library" ** If a file could not be opened it will be marked bad - so no attempt ** will be done to open it again. ** ** INPUT: address of library object [W] ** file index [R] ** file type object [R] ** pointer to address of file object [W] ** IMPLICIT: ** ** RETURNS: 1 if file was opened ** 2 if already open ** file could not be opened: e__filnotok + ** file is known to be 'unopenable': e__badfile */ FILEo *LibOpenFlatFile (SLBo *lib, INT4 fileX, SRSoFILTYP *ft, INT4 *errCode) { static LIBoFLATFILE openFiles[LIBxMAXFILESOPEN]; static INT4 count = 0; FILEo *file; LIBoFLATFILE *openFile; char fileName[FILxXNAM+1], *dirName; INT4 k, c; /* ** check first if the file is already opened ...find out by comparing ** the library and the file index; */ for (k=0; k < LIBxMAXFILESOPEN; k++) { if (lib == openFiles[k].lib && fileX == openFiles[k].fileX && ft == openFiles[k].fileType) return openFiles[k].file; } /* ** return error if there were previous unsuccessful attempts to open */ if (lib->fil[fileX].isBad) { if (errCode) *errCode = e__badfile; return NULL; } /* ** get the next 'openfile' object in the ring */ openFile = &(openFiles[count++ % LIBxMAXFILESOPEN]); if (!openFile->file) openFile->file = FileNew(NULL); file = openFile->file; /* iterate over directory names - first can be empty! */ for (c=0, k=0; (dirName = LibGetNextFlatFileDirName (lib, &c)) || !k; k++) { if (!dirName) dirName =""; FileSetName (file, "dir", dirName); FileSetName (file, "name", lib->fil[fileX].nam); FileSetName (file, "ext", ft->typ_nm); FileSetMaxLine (file, ft->ln_z); if (!FileOpen (file)) { lib->fil[fileX].isBad = 1; /* don't try again to open it */ _ErrMsg2 (e__filnotok, fileName); return NULL; } else break; } openFile->lib = lib; openFile->fileX = fileX; openFile->fileType = ft; return file; } /**api* LibGetFileType ******************************************************** ** ** Returns the file type object with the specified name or the first ** in the list if no name was specified. ** ** INPUT: the library object [R] ** symbolic name of the file stream (or NULL) [R] ** pointer to the index of the file type object (or NULL) [W] ** ** RETURNS: the file type object ** NULL: not found */ SRSoFILTYP *LibGetFileType (SLBo *lib, char *name, Int4 *index) { if (index) *index = 0; return lib->form->fil_t[0]; } /**api* LibOpenNextFlatFile *************************************************** ** ** Opens the next flat file. ** ** INPUT: the library object [R] ** address of file object (set to NULL the first time) [W] ** the file type object [R] ** ** RETURNS: 1: next entry is in current file ** 2: new flat file was opened ** 0: end of the input stream (no more flat files) ** -1: failure during open */ Int4 LibOpenNextFlatFile (SLBo *lib, FILEo **file, SRSoFILTYP *ft, Int4 *fileX) { Int4 rv; if (!*file || FileIsEof (*file)) { if (++(*fileX) >= lib->nfil) return 0; if ((*file = LibOpenFlatFile (lib, *fileX, ft, &rv))) return 2; else return -1; } return 1; } /**api* LibOpenNextEntryFile ************************************************** ** ** Opens the next file that matches a search expression specified ** by the library object. To begin start with file set to NULL. ** The file object holds the iteration context itself. ** ** INPUT: the library object [R] ** address of file object (set to NULL the first time) [W] ** the file type object [R] ** ** RETURNS: number of files in the iteration */ Int4 LibOpenNextEntryFile (SLBo *lib, FILEo **file, SRSoFILTYP *ft) { Int4 c; if (!*file) { *file = FileNew (NULL); FileSetMaxLine (*file, ft->ln_z); if (*ft->pipe) FileSetPipe (*file, ft->pipe); c = 0; FileSetName (*file, "dir", LibGetNextFlatFileDirName (lib, &c)); FileSetName (*file, "name", *ft->searchName ? ft->searchName : "*"); FileSetName (*file, "ext", ft->typ_nm); } /* construct file name */ return FileNext (*file); } /**api* LibOpenEntryFile ****************************************************** ** ** Opens the file that matches a search expression specified ** by the library object. To begin start with file set to NULL. ** The file object holds the iteration context itself. ** ** INPUT: the library object [R] ** address of file object (set to NULL the first time) [W] ** the file type object [R] ** ** RETURNS: number of files in the iteration */ Int4 LibOpenEntryFile (SLBo *lib, FILEo **file, SRSoFILTYP *ft, char *name) { Int4 c; char tmp[100]=""; SmEdit (name, SMxLOWCASE); if (!*file) { *file = FileNew (NULL); FileSetMaxLine (*file, ft->ln_z); if (*ft->pipe) FileSetPipe (*file, ft->pipe); c = 0; FileSetName (*file, "dir", LibGetNextFlatFileDirName (lib, &c)); /* if (*ft->printName) sprintf (tmp, ft->printName, name); */ FileSetName (*file, "name", *tmp? tmp : name); FileSetName (*file, "ext", ft->typ_nm); return FileNext (*file); } return 1; } /**api* LibEntryInfo ********************************************************** ** ** accesses ID-index and retrieve information to access entry; ** NULL can be specified if certain info is not desired; ** ** INPUT: file pointer in to node in ID-index [R] ** library object [R] ** address of text file pointer [W] or NULL ** address of data file pointer [W] or NULL ** address of file index [W] or NULL ** address of index creation time [W] or NULL ** address of entry name [W] or NULL ** IMPLICIT: ** ** RETURNS: 1 */ INT4 LibEntryInfo (UINT4 fip, SLBo *lib, FIP *textFip, FIP *dataFip, INT4 *fileX, UINT4 *indexTime, char *entryName) { LIBoINDEX *libInx; if (!(libInx = LibIndexOpen (lib, LibGetIdField (lib), 0))) _ErrRet (e__error); IdxGet (libInx->idx, fip, entryName, textFip, dataFip, fileX); if (indexTime) *indexTime = IdxGetTimeCreated (libInx->idx); return 1; } /**api* LibGetEntryAuxInfo **************************************************** ** ** Retrieves a record with auxilliary information. ** ** INPUT: file pointer in to node in ID-index [R] ** library object [R] ** initialized buffer object [W] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 LibGetEntryAuxInfo (UINT4 fip, SLBo *lib, SMoBUFF *buff) { LIBoINDEX *libInx; if (!(libInx = LibIndexOpen (lib, NULL, 0))) _ErrRet (e__error); IdxGetBuff (libInx->idx, fip, buff); return 1; } /**api* LibSetField *********************************************************** ** ** selects a field-type for processing; field type can be specified ** directly or through a library - field type is only switched on if a ** library (if specified) points to it; ** ** INPUT: o name of library [R] ** o name of field type [R] or NULL ** o option: "init" - all fields are turned off
    ** "set" - field is turned on [R]
    ** "unset" - specified field is turned off
    ** "xinit" - same as "init" but ID-field is ** turned on...init for indexing
    ** "readlink" - turns on ID field + link fields
    ** "allindex" - all index fields are turned on
    ** "compress" - all compressable index fields are ** turned on
    ** "entry" - all fields of entry are turned on ** IMPLICIT: ** ** RETURNS: 1 if field was set (ie, was not set before); ** 0 if not */ INT4 LibSetField (char *libName, char *fieldName, char *option) { SLBo *lib; SLBoFORM *form; SLBoFIELD *field; SRSoFLD *fieldTypeCurr, *fieldType=NULL; INT4 k, setF = 0; /* ** get objects for library [and fieldtype] */ if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); if (fieldName) { if ((field = LibHasFieldNamed (lib, fieldName))) fieldType = field->type; else _ErrExit3 (e__objectunknown, "data-field", fieldName); } /* ** loop over all data-fields of selected library ** and set or unset the "do" flag */ form = lib->form; for (k=0; k < form->nf; k++) { field = &(form->f[k]); fieldTypeCurr = field->type; switch (tolower (option[0])) { case 'u': /* unset */ if (fieldType != fieldTypeCurr) /* otherwise fall through case */ break; case 'i': /* init */ field->do_f = 0; break; case 's': /* set */ if (fieldType == fieldTypeCurr && !field->do_f) { field->do_f = 1; setF = 1; } break; case 'r': /* readlink */ field->do_f = (field->index==SRSxID || field->index == SRSxLINK) ? 1 : 0; break; case 'x': /* xinit */ field->do_f = (field->index == SRSxID) ? 1 : 0; break; case 'a': /* allindex */ case 'c': /*compress */ if (field->index == SRSxID || field->index == SRSxKEY || field->index == SRSxNUM || field->index == SRSxREAL) { field->do_f = 1; setF = 1; } break; case 'e': /* entry */ field->do_f = 1; setF = 1; break; default: _ErrExit2 (e__unknownoption, option); } } return setF; } /****** LibSetActiveFields **************************************************** ** ** sets fields to be listed within entry list by what is specified in ** the global parameter list; ** ** INPUT: address of library descr. [R] ** IMPLICIT: ** ** RETURNS: 1 */ void LibSetActiveFields (SLBo *lib) { SLBoFORM *form; SLBoFIELD *df; INT4 k; if (!(ParGetBool ("parSetFields"))) return; form = lib->form; form->access_f = FALSE; for (k=0; k < form->nf; k++) { df = &form->f[k]; df->do_f = ParGetBool (df->type->nam) ? TRUE : FALSE; if (df->do_f) form->access_f = TRUE; } } /****** LibFieldIsActive ****************************************************** ** ** checks if certain field is to be processed; ** ** INPUT: library object [R] ** field index [R] ** pointer to flag if field is first in entry [W] ** IMPLICIT: ** ** RETURNS: FALSE if not ** TRUE if yes */ INT4 LibFieldIsActive (SLBo *lib, INT4 fieldInx, INT4 *isFirst) { SLBoFIELD *field; field = &(lib->form->f)[fieldInx]; if (lib->form->first != NULL) { /* either explicitly first field */ if (lib->form->first == field) { *isFirst = TRUE; return 1; } } else if (LibIsField (field, "id")) { /* or the ID field is first field */ *isFirst = TRUE; return 1; } *isFirst = FALSE; if (field->do_f) return 1; return 0; } /**api* LibHasField *********************************************************** ** ** Checks if library has field with specified type and returns it. ** See also LibHasFieldNamed to get a field by name and LibGetFieldType. ** ** INPUT: library object [R] ** field type object [R] ** IMPLICIT: ** ** RETURNS: the field object ** NULL: not found */ SLBoFIELD *LibHasField (SLBo *lib, SRSoFLD *fieldType) { SLBoFIELD *field; Int4 k; for (k=0; k < lib->form->nf; k++) { field = &lib->form->f[k]; if (field->type == fieldType) return field; } return NULL; } /**api* LibHasFieldNamed ****************************************************** ** ** Checks if library has field with specified name returns it. ** Function assumes that the library has only ONE field with that ** name. ** See also LibHasField, LibGetFieldType, LibGetIdField, LibSetField, ** LibNextFieldInGroup, LibNextField, LibNextGroupField, ** LibGetFieldWithCode. ** ** INPUT: library object [R] ** long or short field name [R] ** IMPLICIT: ** ** RETURNS: the field object ** NULL: not found */ SLBoFIELD *LibHasFieldNamed (SLBo *lib, char *name) { SLBoFIELD *field; SRSoFLD *fieldType; Int4 c; for (c=0; (fieldType = LibNextFieldType (name, &c));) { if ((field = LibHasField (lib, fieldType))) return field; } return NULL; } /**api* LibGetFieldType ******************************************************* ** ** checks if data-field for specified library or library group exists ** and return pointer to ** the data-field type object; field name can be the short name or the ** full name. See also LibFieldType. ** ** INPUT: library name [R] ** field name [R] ** ** RETURNS: field type object ** NULL: not found */ SRSoFLD *LibGetFieldType (char *lib_nm, char *field_nm) { SRSoFLD *df_t; SRSoGROUP *libgroup; SLBo *lib; INT4 k; if (!LibGetLibGroup (lib_nm, &libgroup, &lib)) return NULL; /* ** name of a library was specified */ if (lib != NULL) for (k=0; k < lib->form->nf; k++) { df_t = lib->form->f[k].type; if (SmEqs (field_nm, df_t->shortn) || SmEqs (field_nm, df_t->nam)) return df_t; } /* ** else fields of the library group must be checked */ else exit (0); return NULL; } /**api* LibFieldType ********************************************************** ** ** Returns for a field object the object describing its type. See also ** LibGetFieldType. ** ** INPUT: field object [R] ** ** RETURNS: field type object */ SRSoFLD *LibFieldType (SLBoFIELD *field) { return field->type; } /**api* LibGetIdField ********************************************************* ** ** returns the ID field object of specified library; ** ** INPUT: library object [R] ** IMPLICIT: ** ** RETURNS: data-field object ** NULL */ SLBoFIELD *LibGetIdField (SLBo *lib) { INT4 context; SLBoFIELD *field; for (context=0; (field = LibNextField (lib, &context)); ) if (LibIsField (field, "id")) return field; return NULL; } /**api* LibGetFirstField ****************************************************** ** ** returns the first field to be found in entry; ** ** INPUT: library object [R] ** IMPLICIT: ** ** RETURNS: data-field object ** NULL */ SLBoFIELD *LibGetFirstField (SLBo *lib) { if (lib->form->first) return lib->form->first; else return LibGetIdField (lib); } /****** LibAlias ************************************************************** ** ** checks if an alias name (library name or logical name for either the ** library itself or for a single of its flatfiles) corresponds to a ** libary; ** ** INPUT: alias name [R] ** IMPLICIT: ** ** RETURNS: pointer to the library ** NULL if not found */ SLBo *LibAlias (char *lib_nm) { SRSoGROUP *group; SLBo *lib; INT4 l, c1, c2; for (c1=0; (group = LibNextLibGroup (&c1)); ) for (c2=0; (lib = LibNextLib (group, &c2)); ) { if (!lib->isActive) continue; /* library is not active */ if (SmEqs (lib->nam, lib_nm)) return lib; for (l=0; l < lib->nfil; l++) if (SmEqs (lib->fil[l].lnam, lib_nm)) return lib; for (l=0; *(lib->lnam[l]) != '\0'; l++) /* search all lib names */ if (SmEqs (lib->lnam[l], lib_nm)) return lib; } return NULL; } /**api* LibNextFieldInGroup *************************************************** ** ** Iterates for specified library over all fields that belong to ** specified field group. ** ** INPUT: library object [R] ** group field object [R] ** address of iterator [W} must be set to 0 to start ** ** RETURNS: address of field object ** NULL: the list has been exhausted */ SLBoFIELD *LibNextFieldInGroup (SLBo *lib, SLBoFIELD *fieldGroup, Int4 *c) { SLBoFIELD *field; while ((field = LibNextField (lib, c))) if (fieldGroup->type == field->type->group) return field; *c = 0; return NULL; } /**api* LibGetLibGroup ******************************************************** ** ** takes either library group name and library name and returns address ** of library and libgroup (library name) or only libgroup; ** comparison is case insensitive; sets "library" to NULL if name of ** library group.

    ** function is also useful for testing if library or group names are ** valid! ** ** INPUT: address of name [R] ** address of pointer to libgroup descr. [W] or NULL ** address of pointer to library descr. [W] or NULL ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: 1 if name found ** 0 if not */ INT4 LibGetLibGroup (char *nam, SRSoGROUP **libgroup, SLBo **library) { SRSoGROUP *group; SLBo *lib; INT4 c1, c2; /* ** if name is from a library group set "library" to NULL and return */ for (c1=0; (group = LibNextLibGroup (&c1)); ) if (SmEqs (nam, group->short_nm) || SmEqs (nam, group->com)) { if (libgroup) *libgroup = group; if (library) *library = NULL; return 1; } for (c1=0; (group = LibNextLibGroup (&c1)); ) for (c2=0; (lib = LibNextLib (group, &c2)); ) { if (!lib->isActive) continue; /* library is not active */ if (SmEqs (nam, lib->nam)) { if (!library) return 1; *library = lib; break; } } if (!library || *library == NULL) return 0; /* name not known */ /* ** find library's group */ for (c1=0; (group = LibNextLibGroup (&c1)); ) { *libgroup = group; for (c2=0; (lib = LibNextLib (group, &c2)); ) { if (lib == *library) return 1; } } return 1; } /**api* LibRegisterObj ******************************************************** ** ** Registers an object so that it can be retrieved again by "LibObjByName" ** ** INPUT: o name of class: "library", "fieldtype", "group" ** "parser", "idtype", "arglist", "expression", ** "environment", "syntax" [R] ** o pointer to object [R] or NULL to initialize dictionary ** IMPLICIT: ** ** RETURNS: pointer to object ** NULL if not found */ void LibRegisterObj (char *className, void *obj) { INT4 c; SRSoGROUP *group; switch (tolower (className[2])) { case 'o': /* group */ if (!groupDict) { groupDict = DictCreate (&groupDictClass); for (c=0; (group = LibNextLibGroup (&c)); ) DictSet (&groupDict, group->com, SRSoGROUP*) = group; } if (obj) DictSet (&groupDict, ((SRSoGROUP*) obj)->com, SRSoGROUP*) = (SRSoGROUP*) obj; break; default: _ErrExit2 (e__unknownnam, className); } } /**api* LibObjByName ********************************************************** ** ** returns pointer to object with specified name from specified ** object class; case insensitive! ** ** INPUT: o name of class: "library", "fieldtype", "group" ** "parser", "idtype", "arglist", "expression", ** "environment", "syntax" [R] ** o name of object [R] ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: pointer to object ** NULL if not found */ void *LibObjByName (char *class_nm, char *objName) { Iter i; INT4 k; switch (tolower (class_nm[2])) { case 'o': /* group */ if (!groupDict) LibRegisterObj ("group", NULL); i = DictWith (groupDict, objName); return i ? DictIn (i, SRSoGROUP*) : NULL; break; case 'b': /* library */ for (k=0; k < srsdb->nslb; k++) { if (!srsdb->slb[k].isActive) continue; /* library is not active */ if (SmEqs (objName, srsdb->slb[k].nam)) return (void *) &srsdb->slb[k]; } break; case 'e': /* fieldtype */ for (k=0; k < srsdb->nfld; k++) /* long name */ if (SmEqs (objName, srsdb->fld[k].nam)) return (void *) &srsdb->fld[k]; for (k=0; k < srsdb->nfld; k++) /* short name */ if (SmEqs (objName, srsdb->fld[k].shortn)) return (void *) &srsdb->fld[k]; break; case 't': /* idtype */ for (k=0; k < srsdb->niddsc; k++) if (SmEqs (objName, srsdb->iddsc[k].nam)) return (void *) &srsdb->iddsc[k]; break; case 'g': /* arglist */ for (k=0; k < srsdb->commandN; k++) if (!strcmp (objName, srsdb->command[k].name)) return (void *) &srsdb->command[k]; break; case 'v': /* environment */ for (k=0; k < srsdb->environmentN; k++) if (SmEqs (objName, srsdb->environment[k].name)) return (void *) &srsdb->environment[k]; case 'n': /* syntax */ for (k=0; k < srsdb->syntaxN; k++) if (SmEqs (objName, srsdb->syntax[k].name)) return (void *) &srsdb->syntax[k]; default: _ErrExit2 (e__unknownnam, class_nm); } return NULL; } /**api* LibNextFieldType ****************************************************** ** ** Returns the next field type with the specified long or short name. ** ** INPUT: o name of class: "library", "link" "fetch" [R] ** o object-ID [R] ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: pointer to object ** NULL if not found */ SRSoFLD *LibNextFieldType (char *name, Int4 *c) { for (; *c < srsdb->nfld; (*c)++) if (SmEqs (name, srsdb->fld[*c].nam) || SmEqs (name, srsdb->fld[*c].shortn)) return &srsdb->fld[(*c)++]; /* not found */ *c = 0; return NULL; } /**api* LibObjById ********************************************************** ** ** returns pointer of object with specified object-ID from specified ** object class; case insensitive! ** ** INPUT: o name of class: "library", "link" "fetch" [R] ** o object-ID [R] ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: pointer to object ** NULL if not found */ void *LibObjById (char *class_nm, INT4 objId) { switch (tolower (class_nm[2])) { case 'b': /* library */ if (objId < 256 && objId > 0) return (void *) srsdb->libTable[objId]; break; case 'n': /* link */ if (objId < srsdb->nlnk) return (void *) &(srsdb->lnk)[objId]; break; default: _ErrExit2 (e__unknownnam, class_nm); } return NULL; } static INT4 LibGetTokenCode (char *tokName) { /* separate 'tokentable|code' into two fields */ for (; *tokName && *tokName != '|'; tokName++) ; if (*tokName == '|') { *tokName = '\0'; return TokStrToCode (tokName+1); } return -1; } /**api* LibActiveLinks ******************************************************** ** ** marks links between active libraries; sets link names to library names; ** ** INPUT: ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: 1 */ INT4 LibActiveLinks () { SRSoGROUP *group; SLBo *lib; LINKo *link; IDoTYPE *idType = (IDoTYPE*) LibObjByName ("idtype", "Entry-ID"); INT4 c1, c2, k; for (k=0; k < srsdb->nslb; srsdb->slb[k++].upd_f=FALSE) ; for (c1=0; (group = LibNextLibGroup (&c1)); ) for (c2=0; (lib = LibNextLib (group, &c2)); ) lib->upd_f = 1; for (k=0; k < srsdb->nlnk; k++) { /* can't use the function LibNextLink! */ link = &srsdb->lnk[k]; if (LinkIsMapsToParent (link)) link->isActive = TRUE; else if (!link->lib2) link->isActive = FALSE; else if (!link->lib1) /* parent links */ link->isActive = TRUE; else { if (!link->lib1->upd_f || !link->lib2->upd_f) link->isActive = FALSE; else { if (!link->id1_d) link->id1_d = idType; if (!link->id2_d) link->id2_d = idType; if (!*link->nam1) link->nam1 = link->lib1->nam; if (!*link->nam2) link->nam2 = link->lib2->nam; link->isActive = TRUE; link->tokCode = LibGetTokenCode (link->token); } } } return 1; } /**api* LibIsIdField ********************************************************** ** ** returns TRUE if the specified field is an ID field; ** ** INPUT: library name [R] ** data-field type name [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 LibIsIdField (char *libName, char *fieldName) { SLBo *lib; SLBoFIELD *field; INT4 c; if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "data bank", fieldName); for (c=0; field = LibNextField (lib, &c);) if(SmEqs(field->type->nam,fieldName)||SmEqs(field->type->shortn,fieldName)) return (field->index == SRSxID) ? 1 : 0; return 0; } /**api* LibIsFieldType ******************************************************** ** ** returns TRUE if the specified field is of specified type; ** ** INPUT: field object [R] ** type: "index", "ID", "link", "show", "num", "real" ** "group", "active" [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 LibIsFieldType (SRSoFLD *fType, char *option) { switch (tolower (option[1])) { case 'n': /* index */ return (fType->ityp == SRSxID || fType->ityp == SRSxKEY || fType->ityp == SRSxNUM || fType->ityp == SRSxREAL) ? 1 : 0; case 'd': /* ID */ return (fType->ityp == SRSxID) ? 1 : 0; case 'i': /* link */ return (fType->ityp == SRSxLINK) ? 1 : 0; case 'h': /* show */ return (fType->ityp != SRSxGROUP) ? 1 : 0; case 'o': /* doquery */ return (fType->ityp == SRSxID || fType->ityp == SRSxKEY || fType->ityp == SRSxNUM || fType->ityp == SRSxREAL || fType->ityp == SRSxGROUP) ? 1 : 0; case 'u': /* num */ return (fType->ityp == SRSxNUM) ? 1 : 0; case 'e': /* real */ return (fType->ityp == SRSxREAL) ? 1 : 0; case 'r': /* group */ return (fType->ityp == SRSxGROUP) ? 1 : 0; case 'c': /* active */ return (ParGetBool (fType->nam)); default: _ErrExit2 (e__unknownoption, option); } return 0; } #define _Index(x,y) ( ((x)-'a'+1) << 5) +((y)-'a'+1) /**API* LibIsField ************************************************************ ** ** Returns 1 if the specified characteristic is true for the specified ** data-field. ** ** INPUT: o address of field object [R] ** o type: "index", "ID", "link", "show", "num", "real" ** "doquery", "group", "active", "system" "subentry" ** "formatted", "header" [R] ** ** RETURNS: 1: specified characteristic is true ** 0: not */ INT4 LibIsField (SLBoFIELD *field, char *option) { if (!field) return 0; switch (_Index (tolower(option[0]), tolower (option[1]))) { case _Index('i','n'): /* index */ return (field->index == SRSxID || field->index == SRSxKEY || field->index == SRSxNUM || field->index == SRSxREAL) ? 1 : 0; case _Index('i','d'): /* ID */ return (field->index == SRSxID) ? 1 : 0; case _Index('l','i'): /* link */ return (field->index == SRSxLINK) ? 1 : 0; case _Index('h','e'): /* header */ return (field->type->ityp == SRSxHEADER) ? 1 : 0; case _Index('s','h'): /* show */ return (field->type->isGroup ? 0 : 1); case _Index('d','o'): /* doquery */ return (field->index == SRSxID || field->index == SRSxKEY || field->index == SRSxNUM || field->index == SRSxREAL || field->type->isGroup) ? 1 : 0; case _Index('n', 'u'): /* num */ return (field->index == SRSxNUM) ? 1 : 0; case _Index('r','e'): /* real */ return (field->index == SRSxREAL) ? 1 : 0; case _Index('g','r'): /* group */ return (field->type->isGroup) ? 1 : 0; case _Index('a','c'): /* active */ return (ParGetBool (field->type->nam) || field->do_f); case _Index('s','y'): /* system */ return field->isSystem; case _Index('s','u'): /* subentry */ return !field->indexId ? 0 : ((field->indexId->siz == 6) ? 1 : 0); case _Index('f','o'): /* formatted */ return field->type->formatN ? 1 : 0; default: _ErrExit2 (e__unknownoption, option); } return 0; } /**API* LibFieldHeaderHasWith ************************************************* ** ** Returns the number of field with the specified characteristic that ** is associated with the specified header field. Associated here means ** simply the fields following the header field in the $libformat ** definition until the next header field. ** ** INPUT: o address of library object [R] ** o header field object [R] ** o one of options suitable for LibIsField [R] or NULL ** ** RETURNS: number of fields in the group defined by the header field */ INT4 LibFieldHeaderHasWith (SLBo *lib, SLBoFIELD *header, char *option) { SLBoFIELD *field; Int4 c, k; for (c=0, k=0; (field = LibNextField (lib, &c));) { if (field == header) k++; else if (k) { if (LibIsField (field, "header")) break; else if (!option || LibIsField (field, option)) k++; } } return k ? k-1 : 0; } /**API* LibGetFieldFormat ***************************************************** ** ** Returns the format for printing the field inside a table. ** ** INPUT: field object [R] ** ** RETURNS: table print format */ INT4 LibGetFieldFormat (SLBo *lib, SLBoFIELD *field) { Int4 format; if ((format = field->tableFormat)) return format; else if ((format = lib->form->tableFormat)) return format; else return LIBxLISTING; } /**API* LibIsSubField ********************************************************* ** ** Returns TRUE if the specified characteristic is true for the specified ** data-field of a subentry. ** ** INPUT: o field object [R] ** o subentry object [R] ** o option: "inSubEntry", "first", "fromParent" [R] ** ** RETURNS: TRUE or FALSE */ INT4 LibIsSubField (SLBoFIELD *field, LIBoSUBENTRY *subEntry, char *option) { Int4 i; if (!field) return 0; switch (tolower (option[1])) { case 'n': /* insubEntry */ for (i=0; i < subEntry->fieldsN; i++) if (subEntry->fields[i].type == field->type) return 1; return 0; case 'i': /* first */ return (subEntry->first == field->type) ? 1 : 0; case 'r': /* fromParent */ return field->indexId == subEntry->idType ? 0 : 1; default: _ErrExit2 (e__unknownoption, option); } return 0; } /**api* LibGetFieldWithCode ************************************************** ** ** Returns for the field object with specified "fields" token code. ** ** INPUT: library object [R] ** (numeric) token code [R] ** ** RETURNS: the field object ** NULL: if not found */ SLBoFIELD *LibGetFieldWithCode (SLBo *lib, Int4 code) { SLBoFIELD *field; Int4 i; for (i=0; (field=LibNextField (lib, &i));) { if (field->fieldTokCode == 0) field->fieldTokCode = TokStrToCode (field->code); if (field->fieldTokCode == code) return field; } return NULL; } /**api* LibGetIndexTokenType ************************************************** ** ** Returns for specified data-field the name of the token table containing ** the words to be indexed and their token code if specified. ** ** INPUT: address of field object [R] ** address of code [W] ** IMPLICIT: ** ** RETURNS: the name of the token table */ char *LibGetIndexTokenType (SLBoFIELD *field, INT4 *code) { return field->indexToken[0]; } /**api* LibIsGenericId ******************************************************** ** ** returns TRUE if the ID name for each entry is to be generated during ** indexing, ie, no suitable data-field with unique identifiers exist; ** ** INPUT: address of library object [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 LibIsGenericId (SLBo *lib) { #ifdef xxx return lib->form->f[0].gnrc_f; /* field with index 0 is ID-field */ #endif return 1; } /**api* LibIsFilePerEntry ***************************************************** ** ** returns TRUE if the library is organized as a directory of files, each ** containing a single entry; ** ** INPUT: address of library object [R] ** ** RETURNS: 1 ** 0 */ INT4 LibIsFilePerEntry (SLBo *lib) { return lib->form->fil_t[0]->sngl_f; } int (*funct)(char *, int); /**API* LibOpen *************************************************************** ** ** Opens specified depot file with all the run-time-data defined in the ** ODD files. ** ** INPUT: name of depot file [R] ** IMPLICIT: ** ** RETURNS: ** */ void LibOpen () { LIBoID *libId; SRSoGROUP *group; char **object_p; long *object_n; INT4 idNum, k; SdlGetObjects (&object_n, (void ***) &object_p, "srs5"); srsdb = (SRSoDB *) object_p[O_SRSDB]; ParSetTable ("global", NULL, "PRIVATE"); ParInit (srsdb->parTable); if ((srsdb->libTable = (SLBo **) calloc (256, sizeof (SLBo *))) == NULL) _ErrExit2 (e__allocfail, "library-ID list"); /* ** go through defined library-Ids, check and create a table of ** library objects where the Id serves as index */ for (k=0; k < srsdb->libIdN; k++) { libId = &srsdb->libId[k]; if (!libId->library) /* pointer is still a forward */ continue; idNum = libId->n; if (idNum <= 0 || idNum > 255) /* check range */ _ErrExit3 (e__novallibid, idNum, libId->library->nam); if (srsdb->libTable[idNum]) /* is ID already in use? */ _ErrExit4 (e__dupllibid, idNum, libId->library->nam, srsdb->libTable[idNum]->nam); srsdb->libTable[idNum] = libId->library; if (libId->library->idNum) /* has library an ID already? */ _ErrExit4 (e__libidexst, idNum, libId->library->nam, libId->library->idNum); libId->library->idNum = idNum; if ((group = libId->library->group)) /* assign library to a group */ group->library[group->libraryN++] = libId->library; } /* initialize 'HREF' parameters */ for (k=0; k < srsdb->hrefN; k++) { ParDefStr (srsdb->href[k].name, srsdb->href[k].link); ParSetVolatile (srsdb->href[k].name); } /* ** set an initial default environment ...can be changed later */ #ifdef VMS LibSetEnvironment ("vms"); #else LibSetEnvironment ("unix"); #endif } /**API* LibSetEnvironment ***************************************************** ** ** Sets library environment with specified name. ** ** INPUT: name of environment object [R] ** IMPLICIT: ** ** RETURNS: ** */ INT4 LibSetEnvironment (char *envName) { IDoTYPE *idType = (IDoTYPE *) LibObjByName ("idtype", "Entry-ID"); SLBoFIELD *field; SLBo *lib; LIBoENV *env; LIBoLIBENV *libenv; INT4 k, l, c, i; ParDefStr ("env", envName); if (!(env = (LIBoENV *) LibObjByName ("environment", envName))) _ErrExit3 (e__objectunknown, "environment", envName); for (k=0; k < srsdb->nslb; k++) /* turn all libs OFF */ srsdb->slb[k].isActive = 0; /* iterate over databanks in "site" and init libraries */ for (k=0; k < env->libenvN; k++) { libenv = &env->libenv[k]; for (l=0; *(libenv->lib->dirName[l] = libenv->dirName[l]) && l < 3; l++) ; lib = libenv->lib; lib->indexDirName = libenv->indexDirName; lib->isActive = 1; if (!lib->isInit) { lib->isInit = 1; for (c=0; (field = LibNextField (lib, &c));) { for (i=0; i<5; i++) if (*field->indexToken[i]) field->indexTokCode[i] = LibGetTokenCode (field->indexToken[i]); if (*field->tableToken) field->tableTokCode = LibGetTokenCode (field->tableToken); if (!field->indexId) field->indexId = idType; } } } /* ** initialize links...links between existing libs are activated */ LibActiveLinks (); ParDefFunction ("printf", (INT4 (*)()) LibPrintf); ParDefFunction ("print", (INT4 (*)()) LibPrint); return 1; } /**API* LibNextLink *********************************************************** ** ** Returns next link object if available. The context must be initially ** set to 0. The function returns only 'active' links, ie, links between ** existing databanks. See also LinkNext. ** ** INPUT: address of context [W] ** IMPLICIT: ** ** RETURNS: address of link object ** NULL if the list is exhausted (next call will start at begin) */ LINKo *LibNextLink (INT4 *context) { LINKo *link; if (*context >= srsdb->nlnk) { *context = 0; return NULL; } while (*context < srsdb->nlnk) { link = &srsdb->lnk[(*context)++]; if (link->isActive) return link; } *context = 0; return NULL; } /**API* LibNextLibGroup ******************************************************* ** ** Returns next library group object if available. The context must be ** initially set to 0. ** ** INPUT: address of context [W] ** IMPLICIT: ** ** RETURNS: address of library group object ** NULL if the list is exhausted (next call will start at begin) */ SRSoGROUP *LibNextLibGroup (INT4 *context) { if (*context >= srsdb->ngroup) { *context = 0; return NULL; } return &srsdb->group[(*context)++]; } /**API* LibNextLib ************************************************************ ** ** Returns next library object of specified library group if available. ** The context must be initially set to 0. ** ** INPUT: o address of library group object [W] ** o address of context [W] ** IMPLICIT: ** ** RETURNS: address of library object ** NULL if the list is exhausted (next call will start at begin) */ SLBo *LibNextLib (SRSoGROUP *group, INT4 *context) { SLBo *lib; while ((lib = group->library[(*context)++]) && !lib->isActive) ; if (!lib) *context = 0; return lib; } /**API* LibNextField ********************************************************** ** ** Returns next field object of specified library if available; ** The context must be initially set to 0. ** ** INPUT: o address of library object [R] ** o address of context [W] ** IMPLICIT: ** ** RETURNS: address of field object ** NULL if the list is exhausted (next call will start at begin) */ SLBoFIELD *LibNextField (SLBo *lib, INT4 *context) { static SLBo *libCurr; if (*context == 0) libCurr = lib; if (*context >= libCurr->form->nf) { *context = 0; return NULL; } return &libCurr->form->f[(*context)++]; } /**API* LibNextFieldFormat **************************************************** ** ** Returns next field object of specified library if available; ** The context must be initially set to 0. ** ** INPUT: o address of library object [R] ** o address of context [W] ** IMPLICIT: ** ** RETURNS: address of field object ** NULL if the list is exhausted (next call will start at begin) */ LIBoFieldFormat *LibNextFieldFormat (SRSoFLD *fieldType, INT4 *context) { static SLBo *libCurr; if (fieldType->formatN <= *context) { *context = 0; return NULL; } else return &fieldType->format[(*context)++]; } /**api* LibFieldFormat ************************************************************** ** ** Returns the field format object if there is the field has a format with ** the specified name. if an empty name is specified then the first ** format in the list is returned (default format). ** ** INPUT: address of field object [R] ** format name (or NULL or empty string) [R] ** ** RETURNS: data-field format object */ LIBoFieldFormat *LibFieldFormat (SLBoFIELD *field, char *name) { LIBoFieldFormat *format; Int4 c; for (c=0; (format = LibNextFieldFormat (field->type, &c));) if (!name || !*name || SmEqs (format->name, name)) return format; return NULL; } void LibSelectFieldFormat (SRSoFLD *fieldType, char *name) { LIBoFieldFormat *format; Int4 c; if (name && *name) for (c=0; (format=LibNextFieldFormat (fieldType, &c));) { if (SmEqs (format->name, name)) format->isSelected = 1; else format->isSelected =0; } } char *LibGetFieldFormatEval (SLBoFIELD *field) { SRSoFLD *fieldType = field->type; Int4 k; if (!fieldType->formatN) return NULL; for (k=0; kformatN; k++) if (fieldType->format[k].isSelected) return fieldType->format[k].eval; return field->type->format[0].eval; /* first in list is default */ } /**api* LibGroupNew *********************************************************** ** ** Creates a new (empty) databank group with specified name (if any). ** ** INPUT: name of the group [R] or NULL ** ** RETURNS: the group object */ SRSoGROUP *LibGroupNew (char *name) { SRSoGROUP *group; if (!(group = (SRSoGROUP *) calloc (sizeof (SRSoGROUP), 1))) _ErrExit2 (e__allocfail, "db group"); if (name) { group->com = malloc (strlen (name) + 1); strcpy (group->com, name); LibRegisterObj ("group", group); } return group; } /**api* LibGroupAddDb ********************************************************* ** ** Adds one more data bank to the group. ** ** INPUT: group object [W] ** databank object [R] ** */ void LibGroupAddDb (SRSoGROUP *group, SLBo *lib) { group->library[group->libraryN++] = lib; } #define LIBxMaxFieldsInGroup 800 /**api* LibNextGroupField ***************************************************** ** ** Iterates over all field objects in an entire databank group. ** See also LibGroupNew and LibGroupAddDb for creating and extending ** library groups. ** ** INPUT: o group object [W] ** o flag if to show all fields or only those that all ** databanks in the group have in common [R] ** o iterator [W] ** */ SLBoFIELD *LibNextGroupField (SRSoGROUP *group, INT4 isOnlyCommon, INT4 *c) { SLBo *lib; SLBoFIELD *field; INT4 c1, c2, k; /* init first */ if (!group->fieldN) { group->fieldCount = (char *) calloc (LIBxMaxFieldsInGroup, sizeof(char)); for (c1=0; (lib = LibNextLib (group, &c1));) for (c2=0; (field = LibNextField (lib, &c2));) { for (k=0; k < group->fieldN; k++) if (group->field[k]->type == field->type && !LibIsField (field, "header")) { group->fieldCount[k]++; break; } if (k == group->fieldN) { if (k == LIBxMaxFieldsInGroup) _ErrExit3 (f__limitexceeded, "fields in group", LIBxMaxFieldsInGroup); else { group->fieldCount[group->fieldN] = 1; group->field[group->fieldN++] = field; } } } } /* return next field */ if (!*c) *c = 0; else if (*c == group->fieldN) { *c = 0; return NULL; } if (isOnlyCommon) { for (; *c < group->fieldN; (*c)++) if (group->fieldCount[*c] == group->libraryN) return (group->field[(*c)++]); } else return group->field[(*c)++]; return NULL; } /**api* LibToId *************************************************************** ** ** finds a library-ID for a library object; ** ** INPUT: address of library object [R] ** IMPLICIT: ** ** RETURNS: library ID or -1 if not found */ INT4 LibToId (SLBo *lib) { return lib->isActive ? lib->idNum : -1; } /**api* LibLinkToId *********************************************************** ** ** finds a link-ID for a link object; ** ** INPUT: address of link object [R] ** IMPLICIT: ** ** RETURNS: link ID or -1 if not found */ INT4 LibLinkToId (LINKo *link) { INT4 k; for (k=0; k < srsdb->nlnk; k++) if (link == &srsdb->lnk[k]) return k; return -1; } /**API* LibGetNextFlatFileDirName ********************************************* ** ** Returns the next flat file directory name in the list. To get the ** first the context must be set to 0. ** ** INPUT: address of library object [R] ** context (must be set to 0 for first in list) [W] ** IMPLICIT: ** ** RETURNS: o pointer to directory name ** o NULL if the list is exhausted (next call will start ** at begin) */ char *LibGetNextFlatFileDirName (SLBo *lib, INT4 *context) { char *dirName, parName[80]; if (!lib->dirName[*context] || !*lib->dirName[*context] || *context > 3) { *context = 0; return NULL; } if (LibIs (lib, "user")) { sprintf (parName, "%sDirName", lib->nam); if (!(dirName = ParGetStr (parName)) || !*dirName) dirName = lib->dirName[(*context)++]; } else dirName = lib->dirName[(*context)++]; return dirName; } /**API* LibGetNextFlatFileName ********************************************** ** ** Returns the next flat file directory name in the list. To get the ** first the context must be set to 0. ** ** INPUT: address of library object [R] ** context (must be set to 0 for first in list) [W] ** IMPLICIT: ** ** RETURNS: o pointer to directory name ** o NULL if the list is exhausted (next call will start ** at begin) */ char *LibGetNextFlatFileName (SLBo *lib, UINT4 *context) { static char *dirName; static char fileName[300]; static INT4 c; SRSoFILTYP *fileType=lib->form->fil_t[0]; if (!*context) { c = 0; dirName = LibGetNextFlatFileDirName (lib, &c); } do { if (*fileType->searchName) sprintf (fileName, "%s%s", dirName, fileType->searchName); else sprintf (fileName, "%s*.%s", dirName, fileType->typ_nm); if (FilSearch (fileName, fileName, context)) return fileName; *context = 0; } while ((dirName = LibGetNextFlatFileDirName (lib, &c))); /* no more file names */ return NULL; } /**api* LibGetIndexName ******************************************************* ** ** finds a library-ID for a library object; composes a name that contains ** the directory + lib name and short field name...the extensions ** have to be added by the index modules; ** ** If the field object is omitted (NULL instead) then the name for ** the auxilliary index is returned. ** ** INPUT: address of library object [R] ** field object [R] or NULL ** address of output string [W] ** mode: "read" or "write" [R] ** IMPLICIT: ** global parameter "indexDirName" [R] ** ** RETURNS: 1 if ok */ INT4 LibGetIndexName (SLBo *lib, SLBoFIELD *field, char *indexName, char *mode) { char *indexDirName=NULL, tmp1[80], tmp2[80], *libName; libName = *lib->shortName ? lib->shortName : lib->nam; if (LibIs (lib, "user")) { sprintf (tmp1, "%sDirName", libName); if (!(indexDirName = ParGetStr (tmp1)) || !*indexDirName) indexDirName = lib->indexDirName; } else { switch (tolower (mode[0])) { case 'r': if (!(indexDirName = ParGetStr ("indexDirName")) || !*indexDirName) indexDirName = lib->indexDirName; break; case 'w': /* ** check if either output dir or (with lesser priority) index dir ** are defined (command line) */ if (!(indexDirName = ParGetStr ("outDirName")) || !*indexDirName) if (!(indexDirName = ParGetStr ("indexDirName")) || !*indexDirName) indexDirName = lib->indexDirName; break; default: _ErrExit2 (e__unknownoption, mode); } } if (field) sprintf (indexName, "%s%s_%s", indexDirName, SmEdit (strcpy (tmp1, libName), SMxLOWCASE), SmEdit (strcpy (tmp2, field->type->shortn), SMxLOWCASE)); else sprintf (indexName, "%s%s", indexDirName, SmEdit (strcpy (tmp1, libName), SMxLOWCASE)); return 1; } /**API* LibGetLink ************************************************************ ** ** Returns link between the libraries specified. ** ** INPUT: first library's name [R] ** second library's name [R] ** IMPLICIT: ** ** RETURNS: o address of link object ** o NULL if the library names could not be resolved or if ** there is no link specified between the two. */ LINKo *LibGetLink (char *lib1Name, char *lib2Name) { LINKo *link; SLBo *lib1,*lib2; INT4 context; if (!(lib1 = (SLBo *) LibObjByName ("library", lib1Name))) { _ErrMsg3 (e__objectunknown, "library", lib1Name); return NULL; } if (!(lib2 = (SLBo *) LibObjByName ("library", lib2Name))) { _ErrMsg3 (e__objectunknown, "library", lib2Name); return NULL; } for (context=0; (link = LibNextLink (&context)); ) if ( (link->lib1 == lib1 && link->lib2 == lib2) || (link->lib1 == lib2 && link->lib2 == lib1)) return link; return NULL; } /**api* LibGetLinkName ******************************************************* ** ** composes the file name for a link file ** ** INPUT: address of link object [R] ** flag if file with link in reverse dir [R] ** address of output string [W] ** mode: "read" or "write" [R] ** IMPLICIT: ** global parameter "indexDirName" [R] ** ** RETURNS: 1 if ok */ void LibGetLinkName (LINKo *link, INT4 isReverse, char *fileName, char *mode) { char *indexDirName=NULL, tmp1[80], tmp2[80]; if (LibIs (link->lib1, "user") || LibIs (link->lib2, "user")) { sprintf (tmp1, "%sDirName", link->lib1->nam); if (!(indexDirName = ParGetStr (tmp1)) || !*indexDirName) indexDirName = link->lib1->indexDirName; } else { switch (tolower (mode[0])) { case 'r': if (!(indexDirName = ParGetStr ("indexDirName")) || !*indexDirName) indexDirName = link->lib1->indexDirName; break; case 'w': /* ** check if either output dir or (with lesser priority) index dir ** are defined (command line) */ if (!(indexDirName = ParGetStr ("outDirName")) || !*indexDirName) if (!(indexDirName = ParGetStr ("indexDirName")) || !*indexDirName) indexDirName = link->lib1->indexDirName; break; default: _ErrExit2 (e__unknownoption, mode); } } if (!isReverse) sprintf (fileName, "%s%s_%s.link", indexDirName, SmEdit (strcpy (tmp1, link->nam1), SMxLOWCASE), SmEdit (strcpy (tmp2, link->nam2), SMxLOWCASE)); else sprintf (fileName, "%s%s_%s.link", indexDirName, SmEdit (strcpy (tmp1, link->nam2), SMxLOWCASE), SmEdit (strcpy (tmp2, link->nam1), SMxLOWCASE)); } /**API* LibPrintLibs ********************************************************** ** ** Lists all active libraries + some information ** ** INPUT: ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: */ void LibPrintLibs () { SRSoGROUP *group; SLBo *lib; LIBoINDEX *libInx; INT4 context1, context2, (*print)(char *,...); if (!(print = (INT4 (*)(char *, ...)) ParGetFunction ("printf"))) print = (INT4 (*)(char *, ...)) printf; print (" Library Group Entries Index Date\n"); print ("-------------------------------------------------------------------\n"); for (context1=0; (group = LibNextLibGroup (&context1)); ) for (context2=0; (lib = LibNextLib (group, &context2)); ) if ((libInx = LibIndexOpen (lib, LibGetIdField (lib), 1))) { print ("%24s %-18s %7d %12s\n", lib->nam, group->com, BtrGetRecordN (libInx->btree), TimeToString (BtrGetTimeCreated (libInx->btree), "short")); } } /****** LibPrintInfo ********************************************************** ** ** displays info about library ** ** INPUT: address of library name [R] ** IMPLICIT: ** ** RETURNS: 1 */ void LibPrintInfo (char *libName) { static char ln[132], *fieldType[10]={"", "id", "index", "link", "show", "tree", "num", "real", "group"}, *linkType[3]={"", " read-link", "index-link"}; SRSoGROUP *group; SLBo *lib; LINKo *link; SRSoFILTYP *fileType; SLBoFIELD *field; LIBoINDEX *libInx; char *dirName, relName[100], *tmp; INT4 c, k, l, isIdField, (*print)(char *, ...); if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); if (!(print = (INT4 (*)(char *, ...))ParGetFunction ("printf"))) print = (INT4 (*)(char *, ...)) printf; LibGetLibGroup (libName, &group, &lib); field = LibGetIdField (lib); /* ** find the release name if available */ relName[0] = '\0'; if ((libInx = LibIndexOpen (lib, field, 1))) if ((tmp = IdxGetReleaseName (libInx->idx)) && *tmp) sprintf (relName, ", release: %s, ", tmp); print ("\nLibrary: \"%s\"%s from group: \"%s\"\n\n", lib->nam, relName, group->com); /* ** list all indices */ print ("Data Fields (B=busy, C=compressed):\n\n"); print ("Name Short Type Inx Ids No No Creation B C\n"); print (" Name (kb) (kb) Words IDs Date \n"); print ("-------------------------------------------------------------------------------\n"); for (c=0, *ln='\0'; (field = LibNextField (lib, &c)); ) { sprintf (ln, "%-20s", LibGetFieldName (field)); sprintf (ln, "%s %-5s", ln, field->type->shortn); sprintf (ln, "%s %-5s", ln, fieldType[field->index]); if (LibIsField (field, "index") && (libInx = LibIndexOpen (lib, field, 1))) { isIdField = LibIsField (field, "id"); sprintf (ln, "%s %6d", ln, BtrGetFileSize (libInx->btree) / 1000); sprintf (ln, "%s %6d", ln, !isIdField ? IdsGetFileSize (libInx->idsFile) /1000 : 0); sprintf (ln, "%s %7d", ln, BtrGetRecordN (libInx->btree)); sprintf (ln, "%s %8d", ln, !isIdField ? IdsGetIdN (libInx->idsFile) : 0); sprintf (ln, "%s %9s", ln, TimeToString (BtrGetTimeCreated (libInx->btree), "short")); sprintf (ln, "%s %d", ln, BtrIsBusy (libInx->btree)); sprintf (ln, "%s %d", ln, IdsIsCompressed (libInx->idsFile)); } print ("%s\n", ln); } /* ** print link info */ print ("\n\nLinks:\n\n"); for (c=0; (link = LibNextLink (&c)); ) if (lib == link->lib1) print ("%s \"%s\" to \"%s\"\n", linkType[link->typ], lib->nam, link->lib2->nam); print (" \n"); for (c=0; (link = LibNextLink (&c)); ) if (lib == link->lib2) print ("%s \"%s\" to \"%s\"\n", linkType[link->typ], link->lib1->nam, lib->nam); print (" \n"); /* ** list names of flatfiles */ print ("Directory: "); for (c=0; (dirName = LibGetNextFlatFileDirName (lib, &c));) print (" \"%s\" ", dirName); print ("\n\n"); print ("Filename(s):\n"); if (LibIsFilePerEntry (lib)) print (" \"*\"\n"); else for (k=0; k < lib->nfil; k++) { *ln = '\0'; for (l=0; (fileType = lib->form->fil_t[l]); l++) sprintf (ln, "%s %15s.%s", ln, lib->fil[k].nam, fileType->typ_nm); print ("%s\n", ln); } print (" \n"); } /**api* LibParSetLibs ******************************************************** ** ** sets a list of libraries by taking a string with lib names separated ** by space; the "libList" "reset" will turn all libraries OFF; ** ** INPUT: string with a list of field names [R] ** ** IMPLICIT: ** ** RETURNS: 1 ** 0 if something is wrong */ INT4 LibParSetLibs (char *libList) { SRSoGROUP *group; SLBo *lib; char *tok, *tokList, tmp[132]; int context1, context2; strcpy (tmp, libList); tokList = tmp; if (SmEqs (libList, "reset")) { for (context1=0; (group = LibNextLibGroup (&context1));) for (context2=0; (lib = LibNextLib (group, &context2));) ParDefNum (lib->nam, 0); return 1; } while ((tok = strtok (tokList, " "))) { tokList = NULL; if ((lib = LibAlias (tok))) ParDefNum (lib->nam, 1); else { _ErrMsg3 (e__objectunknown, "library", tok); return 0; } } return 1; } /**api* LibParSetLinkLibs ***************************************************** ** ** sets a list of libraries by taking a string with lib names separated ** by space; the "libList" "reset" will turn all libraries OFF; ** ** INPUT: string with a list of field names [R] ** ** IMPLICIT: ** ** RETURNS: 1 ** 0 if something is wrong */ INT4 LibParSetLinkLibs (char *libList) { SRSoGROUP *group; SLBo *lib; char *tok, *tokList, tmp[132], parName[80]; int context1, context2; if (SmEqs (libList, "reset")) { for (context1=0; (group = LibNextLibGroup (&context1));) for (context2=0; (lib = LibNextLib (group, &context2));) { sprintf (parName, "%sLink", lib->nam); ParDefNum (parName, 0); } return 1; } strcpy (tmp, libList); tokList = tmp; while ((tok = strtok (tokList, " "))) { tokList = NULL; if ((lib = LibAlias (tok))) { sprintf (parName, "%sLink", lib->nam); ParDefNum (parName, 1); ParDefNum ("linkToLibs", 1); } else { _ErrMsg3 (e__objectunknown, "library", tok); return 0; } } return 1; } /**api* LibParSetFields ******************************************************* ** ** sets a list of fields by taking a string with fields separated by ** space; the "fieldList" "reset" will turn all fields OFF ** ** INPUT: string with a list of field names [R] ** ** IMPLICIT: ** srsdb (SRSoDB *) [R] ** ** RETURNS: 1 ** 0 if something is wrong */ INT4 LibParSetFields (char *fieldList) { SRSoFLD *fieldType; char *tok, *tokList, tmp[132]; int k, c, isFound; if (SmEqs (fieldList, "reset")) { for (k=0; k < srsdb->nfld; k++) ParDefNum (srsdb->fld[k].nam, 0); return 1; } strcpy (tmp, fieldList); tokList = tmp; ParDefNum ("parSetFields", 1); while ((tok = strtok (tokList, " "))) { tokList = NULL; for (isFound=0, c=0; (fieldType=LibNextFieldType (tok, &c));) { ParDefNum (fieldType->nam, 1); isFound=1; } if (!isFound) { _ErrMsg3 (e__objectunknown, "data-field", tok); return 0; } } return 1; } /**api* LibIs ***************************************************************** ** ** returns some boolean information about the library; ** ** INPUT: library object [R] ** option: "marked", "user", "selected", "linkTarget" [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 LibIs (SLBo *lib, char *option) { char parName[80]; switch (tolower (option[0])) { case 's': /* selected */ return (ParGetBool (lib->nam)); case 'm': /* marked */ return lib->upd_f; case 'u': /* user */ return lib->isFromUser; case 'l': /* linkTarget */ sprintf (parName, "%sLink", lib->nam); return (ParGetBool (parName)); default: _ErrExit2 (e__unknownoption, option); } return 0; } /**api* LibMarkLinkedLibs ***************************************************** ** ** marks all libraries that are either directly or indirectly linked - all ** others are unmarked; the mark can be questioned by the function ** "LibIs"; marking includes library specified as argument; ** ** INPUT: library name [R] ** IMPLICIT: ** ** RETURNS: 1 if library is linked to at least one other ** 0 otherwise */ INT4 LibMarkLinkedLibs (char *libName) { SRSoGROUP *group; SLBo *lib; LINKo *link; INT4 isLinked=0, context1, context2, k, l; /* unmark all libraries */ for (context1=0; (group = LibNextLibGroup (&context1)); ) for (context2=0; (lib = LibNextLib (group, &context2)); ) lib->upd_f = 0; /* test if library is linked at all */ for (k=0, context1=0; (link = LibNextLink (&context1)); k++) if (link->typ != 3 && (SmEqs (libName, link->lib1->nam) || SmEqs (libName, link->lib2->nam))) { link->lib1->upd_f = link->lib2->upd_f = 1; isLinked = 1; } /* propagate all links by marking all libs that have a marked partner in a link - repeat number of link times */ for (l=0; l < k; l++) for (context1=0; (link = LibNextLink (&context1));) if (link->typ != 3 && (link->lib1->upd_f || link->lib2->upd_f)) link->lib1->upd_f = link->lib2->upd_f = 1; return isLinked; } /**api* LibIsAnyFieldActive *************************************************** ** ** tests is any field of library has been activated; ** ** INPUT: library name [R] ** IMPLICIT: ** ** RETURNS: 1 if at least one field is active ** 0 otherwise */ INT4 LibIsAnyFieldActive (char *libName) { SLBo *lib; SLBoFIELD *field; INT4 context; if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); for (context=0; (field = LibNextField (lib, &context)); ) if (LibIsField (field, "active")) return 1; return 0; } /**api* LibIsFieldInGroup ***************************************************** ** ** returns 1 if field type belongs logically to the field type group; ** ** INPUT: field type object [R] ** field type (group) object [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 LibIsFieldInGroup (struct SRSoFLD *fieldType, struct SRSoFLD *fieldTypeGroup) { return fieldType->group == fieldTypeGroup ? 1 : 0; } /**API* LibIsDataType ********************************************************* ** ** Returns 1 if databank contains protein sequences. ** ** INPUT: library object [R] ** one of: "protein", "dna" ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 LibIsDataType (struct SLBo *lib, char *option) { switch (tolower (option[0])) { case 'p': /* protein */ return lib->dataType == 1 ? 1 : 0; case 'd': /* dna */ return lib->dataType == 2 ? 1 : 0; default: _ErrExit2 (e__unknownoption, option); } } /**API* LibSetStatus ********************************************************** ** ** Activates/Deactivates the specified library. ** ** INPUT: library name [R] ** 1=activate, 0=deactivate [R] ** IMPLICIT: ** ** RETURNS: ** library object ** NULL if library name not valid */ SLBo *LibSetStatus (char *libName, int doActivate) { SLBo *lib; INT4 k, isActive; /* iterate over all libraries - not just the active ones */ for (k=0; k < srsdb->nslb; k++) { lib = &srsdb->slb[k]; if (SmEqs (libName, lib->nam)) { isActive = lib->isActive; lib->isActive = doActivate; if (isActive != doActivate) LibActiveLinks (); return lib; } } return NULL; } /**API* LibSetIndexDir ***************************************************** ** ** Sets a new index directory for the specified library. ** ** INPUT: library object [W] ** directory name [R] ** IMPLICIT: ** ** RETURNS: */ void LibSetIndexDir (SLBo *lib, char *dirName) { char *tmp; if (!(tmp = (char *) malloc (strlen (dirName)+1))) _ErrExit2 (e__allocfail, "directory name"); strcpy (tmp, dirName); if (!OddIsInDepot (lib->indexDirName)) free (lib->indexDirName); lib->indexDirName = tmp; } /**API* LibSetFlatFileName ***************************************************** ** ** Sets a new flat file name without the extension (!) that is specified ** by the file type object. ** ** INPUT: library object [W] ** file name [R] ** ** RETURNS: */ void LibSetFlatFileName (SLBo *lib, char *fileName) { SLBoFIL *file; char *tmp; if (!(file = (SLBoFIL *) malloc (sizeof (SLBoFIL)))) _ErrExit2 (e__allocfail, "file object"); /* file name */ if (!(tmp = (char *) malloc (strlen (fileName)+1))) _ErrExit2 (e__allocfail, "file name"); strcpy (tmp, fileName); file->nam = tmp; /* (empty) logical file name */ if (!(tmp = (char *) malloc (4))) _ErrExit2 (e__allocfail, "logical file name"); *tmp = '\0'; file->lnam = tmp; lib->fil = file; lib->nfil = 1; } /**API* LibSetFlatFileDir ***************************************************** ** ** Sets a new flat file directory for specified library. ** ** INPUT: library object [W] ** directory name [R] ** ** RETURNS: */ void LibSetFlatFileDir (SLBo *lib, char *dirName) { char *tmp; if (!(tmp = (char *) malloc (strlen (dirName)+1))) _ErrExit2 (e__allocfail, "directory name"); strcpy (tmp, dirName); lib->dirName[0] = tmp; } /**API* LibGetIdType ********************************************************* ** ** Returns an IDtype object. ** If either library name or library ID are specified the ID type ** specific for that library is returned otherwise a default ID type that ** corresponds with the specified ID size. ** ** INPUT: library name [R] or NULL ** library-ID [R] or 0 ** length of ID [R] ** ** RETURNS: ** address of ID-type object */ IDoTYPE *LibGetIdType (char *libName, INT4 libId, INT4 idSize) { SLBo *lib=NULL; if (idSize == 4) { if (libName) { if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrMsg3 (e__objectunknown, "library", libName); } else if (libId) { if (!(lib = (SLBo *) LibObjById ("library", libId))) _ErrMsg2 (e__libidnotknown, libId); } else { return (IDoTYPE *) LibObjByName ("idtype", "entry-id"); } if (lib) return (LibGetIdField (lib))->indexId; } else if (idSize == 6) { /* there is no other at the moment */ return (IDoTYPE *) LibObjByName ("idtype", "seq-ft-id"); } else { _ErrMsg4 (e__novalvar, "IDlength", idSize, "4 or 6"); } return NULL; } /**API* LibHasNoFiles **************************************************** ** ** Returns TRUE if no flat file name records are associated with ** library object, ie, no source flat files were specified in ** the ODD specificiation. ** Returns TRUE only if entries of library are not in separate files - ** here flat file names are never directly specified. ** ** INPUT: library object [W] ** ** RETURNS: ** 1 ** 0 */ INT4 LibHasNoFiles (SLBo *lib) { if (lib->nfil || LibIsFilePerEntry (lib)) return 0; else return 1; } /**API* LibSetLibFlatFiles **************************************************** ** ** Searches directory for files that match the search string or the ** name '*.externsion' and puts these names into the array of flat file ** source names. These names are also stored in the IDX file. ** ** INPUT: library object [W] ** IDX file object [R] ** ** RETURNS: ** number of files found ** 0 files */ INT4 LibSetLibFlatFiles (SLBo *lib, struct IDXo *idx) { static char emptyLNam[1]=""; SLBoFIL *libFile; char *fileName, name[80]; INT4 c1=0, k; UINT4 c2; if (!IdxGetFlatFileNameN (idx)) { for (c2=0; (fileName = LibGetNextFlatFileName (lib, &c2));) { FilParse(fileName, name, FILxNAME); IdxSetFlatFileName (idx, name); } IdxWriteFlatFileNames (idx); /* flush file names into IDX file */ } k = IdxGetFlatFileNameN (idx); if (!(libFile = (SLBoFIL *) calloc (k, sizeof (SLBoFIL)))) _ErrExit2 (e__allocfail, "library file objects"); for (c1=0, k=0; (fileName = IdxGetFlatFileName (idx, &c1)); k++) { libFile[k].nam = fileName; libFile[k].lnam = emptyLNam; } lib->fil = libFile; lib->nfil = k; return k; } /**API* LibPrintStartupInfo *************************************************** ** ** Prints selected information about the library groups, databanks, fields ** and links that are needed by interfaces talking to some remote ** server.Prints to stdout. ** ** INPUT: ** ** RETURNS: */ void LibPrintStartupInfo () { static classId = 0; static struct LibCoords { char *intern; INT4 type_id; char name[100]; INT4 x, y; } *coords=NULL; FILo file; SRSoGROUP *group; SLBo *lib; LINKo *link; SLBoFIELD *field; LIBoINDEX *libInx; INT4 c1, c2, c3, x, y; char *tmp; /* ** init list for storing the libraries coordinates in the network ** picture ** Try to read the file (if exists) and save the coordinates */ if (!classId) LstManageClass (&classId, sizeof (struct LibCoords), NULL, NULL, NULL); if (!_ErrIs (FilUOpen (&file, "SRSWWW:srsnet.dat", 100, 0))) { while (!FilEof (&file)) { LstNew ((void **) &coords, classId); if (sscanf (file.ln, "coord: %s %d %d", coords->name, &coords->x, &coords->y) == 3) FilURead (&file); } } for (c1=0; (group = LibNextLibGroup (&c1)); ) { printf ("group: %s, searchall: %d\n", group->com, !group->single_f); } for (c1=0; (group = LibNextLibGroup (&c1)); ) for (c2=0; (lib = LibNextLib (group, &c2)); ) if ((libInx = LibIndexOpen (lib, LibGetIdField (lib), 1))) { if (LstHashSearch ((void **) &coords, lib->nam)) x = coords->x, y = coords->y; else x = y = 0; /* print library */ printf ("lib: %s, rel: %s, entries: %d, date: %s, group: %s, x: %d, y: %d\n", lib->nam, (tmp = IdxGetReleaseName (libInx->idx)) ? tmp : "", BtrGetRecordN (libInx->btree), TimeToString (BtrGetTimeCreated (libInx->btree), "date"), group->com, x, y); /* print fields */ for (c3=0; (field = LibNextField (lib, &c3)); ) if (!LibIsField (field, "system")) printf ("field: %s, type: %s\n", LibGetFieldName (field), LibGetFieldIType (field)); } /* print links */ for (c1=0; (link = LibNextLink (&c1)); ) if (link->lib1 && link->lib2) printf ("link: %s %s\n", link->lib1->nam, link->lib2->nam); } /**api* LibGetMaxNameSize ***************************************************** ** ** Returns the maximum size for a library name or field name. ** The max field length can include the max format name length ** ("formattedField"). The function can return the max length ** within the specified library, group, or if neither are specified ** in all groups. ** ** INPUT: group object (or NULL) [R] ** library object (or NULL) [R] ** option: "library", "field", "formattedField" ** IMPLICIT: ** ** RETURNS: the maximum string length */ Int4 LibGetMaxNameSize (SRSoGROUP *group, SLBo *lib, char *option) { LIBoFieldFormat *format; SLBoFIELD *field; INT4 c1, c2, c3, c4, len, fLen=0, isSingleGroup=0, isSingleLib=0, maxLen=0, maxFLen=0; if (group) isSingleGroup = 1; if (lib) { isSingleGroup = 1; isSingleLib = 1; } if (option[2] == 'b') { /* library */ for (c1=0; isSingleGroup || (group = LibNextLibGroup (&c1)); ) { for (c2=0; isSingleLib || (lib = LibNextLib (group, &c2)); ) if ((len = strlen (LibName (lib)))) maxLen = len; if (isSingleGroup) break; } } else { /* field or formattedField */ for (c1=0; isSingleGroup || (group = LibNextLibGroup (&c1)); ) { for (c2=0; isSingleLib || (lib = LibNextLib (group, &c2)); ) { for (c3=0; (field = LibNextField(lib, &c3));) { if (!LibIsField (field, "header")) { len = strlen (LibGetFieldName (field)); if (option[2] == 'r') /* formattedField */ { for (c4=0; (format=LibNextFieldFormat (field->type, &c4));) if ((fLen = strlen (format->name))) maxFLen = fLen; len += fLen; } if (len > maxLen) maxLen = len; } } if (isSingleLib) break; } if (isSingleGroup) break; } } return maxLen; } /**api* LibParViewSetLibsRoot ************************************************* ** ** sets a list of libraries by taking a string with lib names separated ** by space; the "viewLibListRoot" "reset" will turn all libraries OFF; ** ** INPUT: string with a list of field names [R] ** ** IMPLICIT: ** ** RETURNS: 1 ** 0 if something is wrong */ INT4 LibParSetLibsViewRoot (char *libList) { SRSoGROUP *group; SLBo *lib; char *tok, *tokList, tmp[132]; int context1, context2; char parName[80]; char libName[80]; int viewNumber; strcpy (tmp, libList); tokList = tmp; if (SmEqs (libList, "reset")) { for (context1=0; (group = LibNextLibGroup (&context1));) for (context2=0; (lib = LibNextLib (group, &context2));) { sprintf(parName,"v%d_R_%s",ParGetNum("viewNumber"),libName); ParDefNum (parName, 0); } return 1; } while ((tok = strtok (tokList, " "))) { tokList = NULL; if(SmEqs(tok,"~~~~~~~~~~~~~~")) continue; sscanf(tok,"v%d_R_%s",&viewNumber,libName); if ((lib = LibAlias (libName))) { sprintf(parName,"v%d_R_%s",viewNumber,libName); ParDefNum (parName, 1); } else { _ErrMsg3 (e__objectunknown, "library", tok); return 0; } } return 1; } /**api* LibParViewSetLibsLeaf ************************************************* ** ** sets a list of libraries by taking a string with lib names separated ** by space; the "viewLibListLeaf" "reset" will turn all libraries OFF; ** ** INPUT: string with a list of field names [R] ** ** IMPLICIT: ** ** RETURNS: 1 ** 0 if something is wrong */ INT4 LibParSetLibsViewLeaf (char *libList) { SRSoGROUP *group; SLBo *lib; char *tok, *tokList, tmp[132]; int context1, context2; char parName[80]; char libName[80]; int viewNumber; strcpy (tmp, libList); tokList = tmp; if (SmEqs (libList, "reset")) { for (context1=0; (group = LibNextLibGroup (&context1));) for (context2=0; (lib = LibNextLib (group, &context2));) { sprintf(parName,"v%d_L_%s",ParGetNum("viewNumber"),libName); ParDefNum (parName, 0); } return 1; } while ((tok = strtok (tokList, " "))) { tokList = NULL; if(SmEqs(tok,"~~~~~~~~~~~~~~")) continue; sscanf(tok,"v%d_L_%s",&viewNumber,libName); if ((lib = LibAlias (libName))) { sprintf(parName,"v%d_L_%s",viewNumber,libName); ParDefNum (parName, 1); } else { _ErrMsg3 (e__objectunknown, "library", tok); return 0; } } return 1; } ** ** $RCSfile: library.h,v $ ** $Revision: 1.8 $ ** $Date: 1996/08/11 22:47:15 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define LIBxNULL 255 /* formerly SLBxNULL */ /* definition of data field types */ enum srs_dft {SRSxID=1, SRSxKEY, SRSxLINK, SRSxSHOW, SRSxHEADER, SRSxNUM, SRSxREAL, SRSxGROUP}; enum LIBeFORMAT {LIBxLISTING=1, LIBxLEFT, LIBxRIGHT, LIBxCENTER, LIBxPREFORMAT, LIBxTOPICLIST, LIBxNUMBERLIST, LIBxBULLETLIST, LIBxTABLE}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** contains neccessary info for accessing indexes to search a key and for ** retrieval of IDs */ typedef struct LIBoINDEX { struct SLBo *lib; /* library descriptor */ struct SLBoFIELD *field; /* data-field descriptor */ struct BTRo *btree; /* b-tree object */ struct IDSoFILE *idsFile; /* file with ID-lists */ struct IDXo *idx; /* id-index */ INT4 isIdIndex; } LIBoINDEX; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** list of functions exported by module "seqlib" */ #ifndef _SRSoGROUP typedef struct SRSoGROUP *dummytointroducestructtagSRSoGROUP; #endif #ifndef _SRSoFLD typedef struct SRSoFLD *dummytointroducestructtagSRSoFLD; #endif #ifndef _LINKo typedef struct LINKo *dummytointroducestructtagLINKo; #endif /* get info */ char *LibName (struct SLBo *lib); char *LibGetName (struct SLBo *lib, char *option); char *LibGetGroupName (struct SRSoGROUP *group, char *option); char *LibGetIcarusFileName (struct SLBo *lib, char *option); void LibPrintInfo (char *libName); void LibPrintStartupInfo (); void LibPrintLibs (); INT4 LibEntryInfo (UINT4 fip, struct SLBo *lib, UINT4 *text_fip, UINT4 *data_fip, INT4 *file_x, UINT4 *indexTime, char *entry_nm); INT4 LibGetEntryAuxInfo (UINT4 fip, struct SLBo *lib, struct SMoBUFF *buff); INT4 LibGetLibGroup (char *nam, struct SRSoGROUP **libgroup, struct SLBo **library); Int4 libGetMaxNameSize (struct SRSoGROUP *group, struct SLBo *lib, char *option); struct LIBoFieldFormat *LibFieldFormat (struct SLBoFIELD *field, char *name); struct SLBo *LibAlias (char *lib_nm); void *LibObjByName (char *class_nm, char *obj_nm); void *LibObjById (char *class_nm, INT4 ObjId); struct SRSoFLD *LibGetFieldType (char *lib_nm, char *field_nm); struct SRSoFLD *LibFieldType (struct SLBoFIELD *field); INT4 LibToId (struct SLBo *lib); INT4 LibLinkToId (struct LINKo *link); INT4 LibMarkLinkedLibs (char *libName); struct LINKo *LibGetLink (char *lib1Name, char *lib2Name); struct IDoTYPE *LibGetIdType (char *libName, INT4 libId, INT4 idSize); Int4 LibGetFieldFormat (struct SLBo *lib, struct SLBoFIELD *field); struct SLBoFIELD *LibGetFieldWithCode (struct SLBo *lib, Int4 code); /* functions returning booleans */ INT4 LibIs (struct SLBo *lib, char *option); INT4 LibFieldIsActive (struct SLBo *lib, INT4 fd_x, INT4 *first_f); INT4 LibIsIdField (char *libName, char *fieldName); INT4 LibIsFilePerEntry (struct SLBo *lib); INT4 LibIsGenericId (struct SLBo *lib); INT4 LibIsField (struct SLBoFIELD *field, char *type); INT4 LibIsFieldType (struct SRSoFLD *fieldType, char *option); struct SLBoFIELD *LibHasFieldNamed (struct SLBo *lib, char *name); struct SLBoFIELD *LibHasField (struct SLBo *lib, struct SRSoFLD *fieldType); INT4 LibIsAnyFieldActive (char *libName); INT4 LibIsFieldInGroup (struct SRSoFLD *fieldType, struct SRSoFLD *fieldTypeGroup); INT4 LibIsDataType (struct SLBo *lib, char *option); INT4 LibHasNoFiles (struct SLBo *lib); /* working on databank groups */ struct SLBoFIELD *LibNextGroupField (struct SRSoGROUP *group, INT4 isOnlyCommon, INT4 *c); void LibGroupAddDb (struct SRSoGROUP *group, struct SLBo *lib); struct SRSoGROUP *LibGroupNew (char *name); /* for iteration */ struct SRSoFLD *LibNextFieldType (char *name, Int4 *c); struct SLBoFIELD *LibNextFieldInGroup (struct SLBo *lib, struct SLBoFIELD *fieldGroup, Int4 *c); struct SRSoGROUP *LibNextLibGroup (INT4 *context); struct SLBo *LibNextLib (struct SRSoGROUP *group, INT4 *context); struct SLBoFIELD *LibNextField (struct SLBo *lib, INT4 *context); struct LINKo *LibNextLink (INT4 *context); struct LIBoFieldFormat *LibNextFieldFormat (struct SRSoFLD *field, INT4 *context); /* others */ struct SRSoFILTYP *LibGetFileType (struct SLBo *lib, char *name, Int4 *index); char *LibGetFieldFormatEval (struct SLBoFIELD *field); INT4 LibSetField (char *lib_nm, char *field_nm, char *optiona); void LibSetActiveFields (struct SLBo *lib); INT4 LibGetIndexName (struct SLBo *lib, struct SLBoFIELD *field, char *indexName, char *mode); void LibGetLinkName (struct LINKo *link, INT4 isReverse, char *fileName, char *mode); struct SLBoFIELD *LibGetIdField (struct SLBo *lib); struct SLBoFIELD *LibGetFirstField (struct SLBo *lib); INT4 LibActiveLinks (); void LibSetIndexDir (struct SLBo *lib, char *dirName); struct SLBo *LibSetStatus (char *libName, int doActivate); void LibSetFlatFileDir (struct SLBo *lib, char *dirName); void LibSetFlatFileName (struct SLBo *lib, char *fileName); INT4 LibSetLibFlatFiles (struct SLBo *lib, struct IDXo *idx); char *LibGetNextFlatFileDirName (struct SLBo *lib, INT4 *context); char *LibGetFieldName (struct SLBoFIELD *field); char *LibGetFieldTypeName (struct SRSoFLD *type); char *LibGetFieldShortName (struct SLBoFIELD *field); char *LibGetFieldIType (struct SLBoFIELD *field); INT4 LibSetEnvironment (char *envName); char *LibGetLinkToName (struct LINKo *link); char *LibGetLinkFromName (struct LINKo *link); /* for checking parameters */ INT4 LibParSetLib (char *libName); /* open files */ void LibOpen (); LIBoINDEX *LibIndexOpen (struct SLBo*, struct SLBoFIELD*, INT4); struct FILEo *LibOpenFlatFile (struct SLBo*, INT4, struct SRSoFILTYP*, INT4*); Int4 LibOpenNextEntryFile (struct SLBo*, struct FILEo**, struct SRSoFILTYP *); Int4 LibOpenEntryFile(struct SLBo*, struct FILEo**, struct SRSoFILTYP*, char*); Int4 LibOpenNextFlatFile (struct SLBo*, struct FILEo**, struct SRSoFILTYP*, Int4*); char link_srs_ID[] = "$Id: link.c,v 1.11 1996/08/14 16:19:28 etzold Exp $"; /* ** ** $RCSfile: link.c,v $ ** $Revision: 1.11 $ ** $Date: 1996/08/14 16:19:28 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: query, sm, setop, srs, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** module has functions for linkage of sets of different ** types and/or origin (library). ** ** Global Parameters: ** "isPrintNoPath" - if "1" print error message if a path between to ** libs was not found ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "id.h" #include "lst.h" #include "set.h" #include "par.h" #include "link.h" #include "map.h" #include "btree.h" #include "ids.h" #include "library.h" #include "binpack.h" #include "query.h" #define _CONSTANTS #define _SRS #define _SLB #include SRSINCLUDE #define LINKxMAXIDN 300000 #define LINKxMAXCOST 1000000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** points to other link-node and to the link descrition; */ typedef struct LINKoEDGE { char *list; /* for usage of module "list" only! */ INT4 class_id; /* for "list" module */ struct LINKoNODE *fromNode; struct LINKoNODE *toNode; struct LINKo *link; INT4 cost; INT4 isReverse; /* TRUE if link specified in node is reverse to link in link-descripton */ } LINKoEDGE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** describes a node in linkage map; */ typedef struct LINKoNODE { char *list; /* for usage of module "list" only! */ INT4 class_id; /* for "list" module */ char name[100]; struct LINKoEDGE *fromEdge; struct LINKoEDGE *edge; INT4 minCost; } LINKoNODE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** extern, global or modulewide variables */ static char linkbuff[LNKxBUFFSIZ]; static LINKoNODE *node=NULL; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static void LinkConnectNodes (LINKo *link, INT4 isReverse); static void LinkExplore (LINKoEDGE *fromEdge, LINKoNODE *startNode, INT4 minCost); static INT4 LinkAnalNames (char *a_nm, char *b_nm, char **liba_nm, char **libb_nm, INT4 *a_n, INT4 *b_n); static INT4 LinkGoPath (char *fromName, char *toName, INT4 fromLibN, INT4 toLibN, LINKoNODE *node, SETo *outSet); static INT4 LinkCheckIdTyp (LINKo *Link, IDoTYPE *id1_d, IDoTYPE *id2_d); static INT4 LinkMapSingle (LINKo *lnk, char *a_nm, INT4 a_n, SETo *c, INT4 rev_f); static INT4 LinkGetLSet (LINKo *lnk, unsigned char **id_p, INT4 *n, INT4 rev_f); static INT4 LinkGetSet (SETo *s, unsigned char **id_p, INT4 *n, INT4 lib_x); static void LinkAddLink (LINKo *link, IDoENTRY *fromId, IDoENTRY *toId); /**api* LinkInit ************************************************************** ** ** selects links to active libraries; ** Copies library-names to link-descriptors where neccessary, initializes ** linkage map; ** ** INPUT: address of array of link-descriptors [R] ** number of link-descriptors [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 LinkInit () { static INT4 isInit=0; LINKo *link; INT4 c; if (isInit) return 0; LibActiveLinks (); for (c=0; (link = LibNextLink (&c)); ) { if (!link->isActive || !link->lib1 || !link->lib2) continue; LinkConnectNodes (link, 1); LinkConnectNodes (link, 0); } isInit=1; return 1; } static void LinkNewNode (LINKoNODE *node) { node->edge = NULL; } Int4 LinkIsMapsToParent (LINKo *link) { return link->typ == LINKxToParent ? 1 : 0; } /****** LinkConnectNode ******************************************************* ** ** Connects to nodes. Creates both nodes if they don't exist and ** creates an edge object for first node. ** The connection is unidirectional and must be repeated in reverse order ** to achieve bidirectionality of the link. ** ** INPUT: o link object [R] ** o TRUE if direction is reverse to direction ** specified in ODD [R] ** IMPLICIT: ** node (LINKoNODE *) [W] ** ** RETURNS: */ static void LinkConnectNodes (LINKo *link, INT4 isReverse) { static INT4 nodeClassId=0, edgeClassId=0; LINKoEDGE *edge; char fromName[100], toName[100]; if (!nodeClassId) { LstManageClass (&nodeClassId, sizeof (LINKoNODE), (void *) LinkNewNode, NULL, NULL); LstManageClass (&edgeClassId, sizeof (LINKoEDGE), NULL, NULL, NULL); node = NULL; } if (isReverse) { strcpy (fromName, LibGetLinkToName (link)); strcpy (toName, LibGetLinkFromName (link)); } else { strcpy (fromName, LibGetLinkFromName (link)); strcpy (toName, LibGetLinkToName (link)); } if (!LstHashSearch ((void **) &node, SmEdit (fromName, SMxLOWCASE))) LstNewNamed ((void **) &node, nodeClassId, fromName); LstNew ((void **) &node->edge, edgeClassId); edge = node->edge; edge->fromNode = node; edge->cost = link->val; /* ** has to be reverse the other way round since ** the path is searched always in reverse direction ** ...to 'go' the path one has then to backtrack */ edge->isReverse = !isReverse; edge->link = link; if (!LstHashSearch ((void **) &node, SmEdit (toName, SMxLOWCASE))) LstNewNamed ((void **) &node, nodeClassId, toName); edge->toNode = node; } /**API* LinkSearchPath ******************************************************** ** ** Searches shortest path from one (library) node to another. ** Searches way from target to start - optimal way to target is recorded ** and placed in list of "LINKoSTEP" which can be "walked" in reverse ** direction. ** ** INPUT: first node's name [R] ** second node's name [R] ** IMPLICIT: ** node (LINKoNODE *) ** ** RETURNS: address of first node in path ** NULL if no path found */ LINKoNODE *LinkSearchPath (char *from, char *to) { SLBo *lib; char fromName[100], toName[100]; LinkInit (); strcpy (fromName, from); strcpy (toName, to); /* init all nodes */ LstFirst ((void **) &node); do node->minCost = LINKxMAXCOST; while (LstNext ((void **) &node)); if (!LstHashSearch ((void **) &node, SmEdit (fromName, SMxLOWCASE))) return NULL; LinkExplore (NULL, node, 0); if (LstHashSearch ((void **) &node, SmEdit (toName, SMxLOWCASE))) return (node->minCost == LINKxMAXCOST || node->minCost == 0) ? NULL : node; else return NULL; } /****** LinkExplore *********************************************************** ** ** ** INPUT: node (current) location at function call [R] or NULL ** node where exploration should be commenced [W] ** minCost so far [R] ** IMPLICIT: ** node (LINKoNODE *) ** ** RETURNS: address of first node in path ** NULL if no path found */ static void LinkExplore (LINKoEDGE *fromEdge, LINKoNODE *startNode, INT4 minCost) { LINKoEDGE *edge=startNode->edge; INT4 newMinCost; startNode->minCost = minCost; startNode->fromEdge = fromEdge; LstFirst ((void **) &edge); do { newMinCost = minCost + edge->cost; if (edge->toNode->minCost > newMinCost) LinkExplore (edge, edge->toNode, newMinCost); } while (LstNext ((void **) &edge)); } /**API* LinkBackTrack ******************************************************** ** ** ** INPUT: node from which to backtrack [R] ** pointer to address of link object [W] or NULL ** pointer to flag whether link is reverse or not [W] or NULL ** IMPLICIT: ** ** RETURNS: NULL if already at end of path ** node one step back in path */ LINKoNODE *LinkBackTrack (LINKoNODE *toNode, LINKo **link, INT4 *isReverse) { LINKoEDGE *edge=toNode->fromEdge; if (!edge) return NULL; if (link) *link = edge->link; if (isReverse) *isReverse = edge->isReverse; return edge->fromNode; } /**API* LinkGetPathLength ***************************************************** ** ** Returns the number of steps in a path ** ** INPUT: address of target node [R] ** IMPLICIT: ** ** RETURNS: nr. of steps in path */ INT4 LinkGetPathLength (LINKoNODE *toNode) { INT4 k; for (k=0; (toNode = LinkBackTrack (toNode, NULL, NULL)); k++) ; return k; } /**API* LinkGetNextInPath ***************************************************** ** ** Walks back one step and returns node object. ** ** INPUT: address of target node [R] ** address of flag for link direction [W] or NULL ** ** RETURNS: node object one step back in the path ** NULL if at end of path */ LINKoNODE *LinkGetNextInPath (LINKoNODE *toNode, INT4 *isReverse) { return LinkBackTrack (toNode, NULL, isReverse); } /****** LinkMap *************************************************************** ** ** top level function of this module; ** processes all possible linkages, set "b" will be mapped unto set "a" ** resulting in set c that is a subset of set "a"; ** set with second identifier will be mapped (i.e. has type of) onto ** set with first identifier; ** ** INPUT: address of first identifier [R] ** address of second identifier [R] ** address of resultant set [R] ** IMPLICIT: ** ** RETURNS: 1 ** e__unknownnam + ** e__ambigouslink + ** e__unknownnam + ** e__filopenerr + */ INT4 LinkMap (char *toName, char *fromName, SETo *c) { LINKoNODE *node; char *toLibName, *fromLibName; INT4 fromLibN, toLibN, rv; LinkInit (); if ((rv = LinkToParent (toName, fromName, c)) != 0) { _ErrIf (rv) { SetDelete (c->nam); return rv; } else return 1; } for (fromLibN=toLibN=0; (rv = LinkAnalNames (toName, fromName, &toLibName, &fromLibName, &toLibN, &fromLibN)) != 0;) { _ErrRet (rv); /* search path in reverse direction ...then backtrack */ if (!(node = LinkSearchPath (toLibName, fromLibName))) { if (ParGetNum ("isPrintNoPath")) _ErrMsg3 (e__nopath, fromLibName, toLibName); continue; } rv = LinkGoPath (fromName, toName, fromLibN, toLibN, node, c); _ErrRet (rv); } return 1; } /**api* LinkToParent ********************************************************** ** ** processes two kinds of linkages which involve both a conversion ** from CHILD-type to PARENT-type IDs; ** 1) conversion of set of CHILD-type IDs directly to PARENT-type ID's ** here second identifier must be name of conversion-link descriptor; ** 2) mapping of set of CHILD-type IDs to set of PARENT-type ids; ** ** INPUT: name of first set or "parent" [R] ** name of second set [R] ** address of resul set [W] ** IMPLICIT: ** ** RETURNS: 1: success ** 0: no path known to connect sets ** e__unknownnam: one of the two names is known ** e__novallink: link is known but not valid */ INT4 LinkToParent (char *a_nm, char *b_nm, SETo *c) { SETo *a, *b; LINKo *lnka=NULL, *lnkb, *lnk; INT4 a_t, b_t; if ((a_t = LinkIdentify (a_nm, &a, &lnka)) == 0) _ErrRet2 (e__unknownnam, a_nm); if ((b_t = LinkIdentify (b_nm, &b, &lnkb)) == 0) _ErrRet2 (e__unknownnam, b_nm); LinkIdentify ("PARENT", NULL, &lnk); if (a_t == LNKxSET && b_t == LNKxSET) { if (LinkCheckIdTyp (lnk, a->id_d, b->id_d)) { c->id_p = SetMapIds (a->id_p, b->id_p, a->n, b->n, &c->n, a->id_d->siz, b->id_d->siz, a->id_d->fddbeg, b->id_d->fddbeg, a->id_d->fddlen + a->id_d->lbxlen); SetMakeOwn (c, a->id_d); return 1; } } else if (b_t == LNKxSET && (lnka && lnka->typ == LNKxMAPRNT)) { if (lnka->id2_d == b->id_d) { c->id_p = SetMapToParent (b->id_p, b->n, &c->n, b->id_d->siz, b->id_d->fddbeg, b->id_d->fddlen + b->id_d->lbxlen); SetMakeOwn (c, lnk->id1_d); return 1; } else _ErrRet3 (e__novallink, a_nm, b_nm); } return 0; } /****** LinkCheckIdTyp ******************************************************** ** ** checks if both ID-types are listed in link-descriptor; ** ** INPUT: address of link-descr. [R] ** address of first id-descr. [R] ** address of second id-descr. [R] ** IMPLICIT: ** ** RETURNS: 1 if ok ** 0 if not */ static INT4 LinkCheckIdTyp (LINKo *lnk, IDoTYPE *id1_d, IDoTYPE *id2_d) { if (id1_d == lnk->id1_d) { if (id2_d == lnk->id2_d) return 1; } else if (id1_d == lnk->id2_d) { if (id2_d == lnk->id1_d) return 1; } return 0; } /****** LinkAnalNames ********************************************************* ** ** input names may be set or library names; function gets for a ** set-name the associated library name with specified number (there may ** be many libraries associated with a set!). ** numbers must be 0 initially and will be incremented by one if there is ** a library name left. ** ** INPUT: address of first identifier [R] ** address of second identifier [R] ** output address of first library name [W] ** output address of second library name [W] ** output address of library number of first set [W] ** output address of library number of second set [W] ** IMPLICIT: ** ** ** RETURNS: 0 if no library name left ** 1 if success ** e__unknownnam + ** e__ambigouslink + */ static INT4 LinkAnalNames (char *a_nm, char *b_nm, char **liba_nm, char **libb_nm, INT4 *a_n, INT4 *b_n) { LINKo *lnka, *lnkb; SETo *a, *b; INT4 a_t, b_t, libb_f = FALSE, liba_f = FALSE; if ((a_t = LinkIdentify (a_nm, &a, &lnka)) == 0) _ErrRet2 (e__unknownnam, a_nm); if ((b_t = LinkIdentify (b_nm, &b, &lnkb)) == 0) _ErrRet2 (e__unknownnam, b_nm); if (a_t == LNKxSET) { if (a->n == 0) return 0; if (!a->anal_f) SetLibStat (a); } if (b_t == LNKxSET) { if (b->n == 0) return 0; if (!b->anal_f) SetLibStat (b); } if (a_t == LNKxSET && b_t == LNKxSET) { if (a->lib_n > 1 && b->lib_n > 1) _ErrRet3 (e__ambigouslink, a_nm, b_nm); } if (a_t == LNKxSET && *a_n < a->lib_n) { *liba_nm = a->lib_nm[(*a_n)++]; liba_f = TRUE; } else if (*a_n < 1) { *liba_nm = a_nm; liba_f = TRUE; } if (b_t == LNKxSET && *b_n < b->lib_n) { *libb_nm = b->lib_nm[(*b_n)++]; libb_f = TRUE; } else if (*b_n < 1) { *libb_nm = b_nm; libb_f = TRUE; } if (a_t == LNKxLINK && b_t == LNKxLINK) { (*b_n)++; (*a_n)++; } return liba_f && libb_f ? 1 : 0; } /****** LinkGoPath ************************************************************ ** ** processes each step of a path in sequential order; and adds set of ** found entries to resultant set; ** ** INPUT: address of first identifier [R] ** address of second identifier [R] ** number of library in first set [R] ** number of library in second set [R] ** address of path's first step [R] ** address of resultant set [W] ** IMPLICIT: ** ** RETURNS: 1 ** e__unknownnam + ** e__filopenerr + */ static INT4 LinkGoPath (char *fromName, char *toName, INT4 fromLibN, INT4 toLibN, LINKoNODE *node, SETo *outSet) { SETo *tmp, *toSet; LINKo *link; INT4 rv, nStep, isReverse; char tmp1Name[SETxXNAM+1], tmp2Name[SETxXNAM+1]; char *nextFromName; tmp1Name[0] = tmp2Name[0] = '\0'; for (nStep=0; (node = LinkBackTrack (node, &link, &isReverse)); nStep++){ if (!nStep) /* first step */ nextFromName = fromName; else { strcpy (tmp2Name, tmp1Name); nextFromName = tmp2Name; } /* ** perform next link and put result into newly created temporary set ** delete input temporary sets */ tmp = SetNew (tmp1Name, "temp"); /* output set */ rv = LinkMapSingle (link, nextFromName, nStep ? 1 : fromLibN, tmp, isReverse); _ErrRet (rv); SetMakeOwn (tmp, isReverse ? link->id1_d : link->id2_d); if (*tmp2Name) SetDelete (tmp2Name); } if (LinkIdentify (toName, &toSet, NULL) == LNKxSET) SetOp (tmp, toSet, NULL, SETxAND); SetOp (outSet, tmp, NULL, SETxOR); SetDelete (tmp1Name); return 1; } /**api* LinkIdentify ********************************************************** ** ** takes and identifier and finds out if its either a set name or a ** library name or nothing ** ** INPUT: address of name string [R] ** address of pointer to link-dscr. [W] or NULL ** address of pointer to set-dscr [W] or NULL ** IMPLICIT: ** ** RETURNS: 0 if unknown identifier ** LNKxLINK if a link ** LNKxSET if a set */ INT4 LinkIdentify (char *name, SETo **setPtr, LINKo **linkPtr) { SETo* set; LINKo* link; INT4 c; LinkInit (); if (SmEqs ("parent", name)) for (c=0; (link = LibNextLink (&c)); ) if (SmEqs (name, link->nam1) || SmEqs(name, link->nam2)) { if (linkPtr) *linkPtr = link; return LNKxLINK; } if ((set = (SETo *) SetGet (name)) != NULL) { if (setPtr != NULL) *setPtr = set; if (SetIsDB (set)) return LNKxLINK; else return LNKxSET; } else return 0; } /****** LinkDoLink ************************************************************ ** ** performs a single step in an linkage path; set's identifier ** must be either a setname or a library name; map is performed to the ** other library specified in the link-dsc. ** ** INPUT: address of linkage descriptor [R] ** set identifier [R] ** number of subset [R] ** address of resultant set's descr. [W] ** reverse flag [R] ** IMPLICIT: ** ** RETURNS: 1 ** e__unknownnam + ** e__filopenerr + */ static INT4 LinkMapSingle (LINKo *lnk, char *a_nm, INT4 a_n, SETo *c, INT4 rev_f) { LINKo *lnka; SETo *a; unsigned char *aid_p, *bid_p; INT4 a_t, a_z, b_z, rv; if ((a_t = LinkIdentify (a_nm, &a, &lnka)) == 0) _ErrRet2 (e__unknownnam, a_nm); rv = LinkGetLSet (lnk, &bid_p, &b_z, a_t == LNKxSET ? rev_f : !rev_f); _ErrRet (rv); if (a_t == LNKxSET) { LinkGetSet (a, &aid_p, &a_z, a_n); c->id_p = SetLink (aid_p, a_z, bid_p, b_z, &c->n, rev_f); } else c->id_p = SetCutLink (bid_p, b_z, &c->n, rev_f); SetRemoveDouble (c->id_p, c->n, 4, &c->n); if (ParGetNum ("doQueryReport")) Message (5, i__mappedset, 0, rev_f ? lnk->nam1 : lnk->nam2, c->n); return 1; } /****** LinkGetSet ************************************************************ ** ** returns pointer to ids and number of ids - the returned set is a subset ** of the input set containing ids of only one library - specified by ** number; ** if s->anal_f = FALSE it is assumed that the set contains ID's of ** only one primary library; ** ** INPUT: address of set-descr. [R] ** address of pointer to id's [W] ** address of set size [W] ** library index within set [R] ** IMPLICIT: ** ** RETURNS: 1 */ static INT4 LinkGetSet (SETo *s, unsigned char **id_p, INT4 *n, INT4 lib_x) { INT4 k, fst_x; if (!s->anal_f) { *id_p = s->id_p; *n = s->n; } else { for (k=0, fst_x=0; k < lib_x-1; fst_x += (INT4) s->lib_z[k++]) /*$$$$*/ ; *n = s->lib_z[k]; *id_p = s->id_p + s->id_d->siz * fst_x; } return 1; } /****** LinkGetLSet *********************************************************** ** ** gets a set of link Id's: set is either already in memory or has ** to be read; set must be sorted depending on linkage (reverse or not) ** after first of second id. ** ** INPUT: address of link descr. [W] ** address of pointer to ID-block [W] ** address of set size [R] ** flag if link is in reverse direction [R] ** IMPLICIT: ** linkbuff (char []) [W] ** ** RETURNS: 1 ** e__filopenerr + */ static INT4 LinkGetLSet (LINKo *link, unsigned char **id_p, INT4 *n, INT4 rev_f) { static MAPo map; static char nam_s[FILxXNAM+1]; INT4 rv; char nam[FILxXNAM+1], *tmp; if (link->use) link = link->use; LibGetLinkName (link, rev_f, nam, "read"); if (strcmp (nam, nam_s) != 0) { if (nam_s[0] != '\0') MapFree (&map); #ifdef VMS rv = MapMem (&map, nam, linkbuff, LNKxBUFFSIZ); #else rv = MapMem (&map, nam, linkbuff, LNKxBUFFSIZ - 512); #endif _ErrRet (rv); strcpy (nam_s, nam); } /* ** first INT4 in mapsection contains the number of IDs - copy that ** number ...the set of link IDs start right after that number */ tmp = map.data; _BinUnpackNum (tmp, link->linkIdN); if (rev_f) _BinUnpackNum (tmp, link->lib2EntryN); else _BinUnpackNum (tmp, link->lib1EntryN); if (LNKxBUFFSIZ/8 < link->linkIdN) _ErrExit3 (f__limitexceeded, "links in buffer", LNKxBUFFSIZ/8); *n = link->linkIdN; *id_p = (unsigned char *) tmp; return 1; } /****** LinkReadLSet ********************************************************** ** ** reads a set of link ID's from file; ** ** INPUT: set name [R] ** address of set pointer [W] ** address of link-desc. [R] ** reverse flag [R] ** IMPLICIT: ** ** RETURNS: 1 ** e__filnotok + */ INT4 LinkReadLSet (char *nam, SETo **set_p, LINKo *lnk, INT4 rev_f) { SETo *set; FILE *fil; char fil_nm[FILxXNAM+1]; int errCode; sprintf (fil_nm, "%s%s.lnk", lnk->lib1->indexDirName, nam); fil = (FILE *) FilOpenR (fil_nm, &errCode); _ErrRet2 (errCode, fil_nm); set = SetNew (nam, "temp"); fread ((void *) &set->n, sizeof (INT4), 1, fil); fread (set->id_p, 8, set->n, fil); fclose (fil); SetMakeOwn (set, (IDoTYPE *) LibObjByName ("idtype", "link-id")); *set_p = set; return 1; } /**api* LinkOpen ************************************************************** ** ** ** INPUT: link object obtained by, eg, LibGetLink [W] ** option: "read", "writeread" or "writeindex" [R] ** IMPLICIT: ** ** RETURNS: the link object ** NULL: if the index does not exist ("read") */ LINKo *LinkOpen (LINKo *link, char *opt) { FILEo *file; SLBoFIELD *field; char fileName[FILxXNAM+1]; INT4 buffSize, errCode; /* ** read access */ if (SmEqs ("read", opt)) { LibGetLinkName (link, 0, fileName, "read"); file = FileNew (fileName); link->toFile = file; if (!(file = FileOpen (file))) return NULL; _BinFileUnpackNum (FileGetFile (file), link->linkIdN); _BinFileUnpackNum (FileGetFile (file), link->lib1EntryN); link->toFile = file; LibGetLinkName (link, 1, fileName, "read"); file = FileNew (fileName); link->fromFile = file; if (!(file = FileOpen (file))) return NULL; _BinFileUnpackNum (FileGetFile (file), link->linkIdN); _BinFileUnpackNum (FileGetFile (file), link->lib2EntryN); return link; } /* ** write access */ else { buffSize = LINKxMAXIDN * (link->id1_d->siz + link->id2_d->siz); if ((link->id_p = (unsigned char *) malloc (buffSize)) == NULL) { _ErrMsg2 (e__allocfail, "link ID buffer"); return NULL; } link->idWrtOff = (char *) link->id_p; link->goodRefN = link->badRefN = link->linkIdN = 0; /* ** open associated indices */ if (SmEqs ("writeindex", opt)) { /* if this is an index link */ if ((field = LibHasField (link->lib1, link->fromField))) { LibGetIndexName (link->lib1, field, fileName, "read"); link->btree1 = BtrOpen (fileName, "read", &errCode); _ErrMsg2 (errCode, FileGetName (link->btree1->file, "path")); link->ids1 = IdsOpen (fileName, "read", 0, NULL, &errCode); _ErrMsg2 (errCode, fileName); } else _ErrExit3 (e__dbhasnotfield, LibName(link->lib1),link->fromField->nam); } if ((field = LibHasField (link->lib2, link->toField))) { LibGetIndexName (link->lib2, field, fileName, "read"); link->btree2 = BtrOpen (fileName, "read", &errCode); _ErrMsg2 (errCode, FileGetName (link->btree2->file, "path")); link->ids2 = IdsOpen (fileName, "read", 0, NULL, &errCode); _ErrMsg2 (errCode, fileName); link->isOpen = 1; } else _ErrExit3 (e__dbhasnotfield, LibName (link->lib2), link->toField->nam); return link; } } /**api* LinkGetCreTime ***************************************************** ** ** Returns the creation time of the link indices. Link must be ** already opened for read access with LinkOpen. ** ** INPUT: link object (must be opened for read access) [R] ** ** RETURNS: creation time */ Int4 LinkGetCreTime (LINKo *link) { return FileGetTime (link->toFile, "create"); } /**api* LinkGetLinkN ********************************************************** ** ** returns the number of links found in link index ** ** INPUT: link object (must be opened for read access) [R] ** IMPLICIT: ** ** RETURNS: number of links */ INT4 LinkGetLinkN (LINKo *link) { return link->linkIdN; } /**api* LinkGetEntryN ********************************************************* ** ** returns the number of entries of library used as sorting criterion ** found in the link (always the first library name in the link name); ** ** INPUT: link object (must be opened for read access) [R] ** IMPLICIT: ** ** RETURNS: number of entries */ INT4 LinkGetEntryN (LINKo *link, INT4 isReverse) { return isReverse ? link->lib2EntryN : link->lib1EntryN; } /**api* LinkSets ************************************************************** ** ** ** INPUT: link object [W] ** first set [R] ** second set [R] ** IMPLICIT: ** ** RETURNS: 1 */ void LinkSets (LINKo *link, SETo *fromSet, SETo *toSet) { IDoENTRY fromId, toId; INT4 i, j; for (i=0; SetNextId (fromSet, &fromId, &i);) for (j=0; SetNextId (toSet, &toId, &j);) LinkAddLink (link, &fromId, &toId); } /**api* LinkClose ************************************************************* ** ** writes two files with link ID's - first with with link-IDs sorted ** afters first entry-ID, second with link-IDs sorted after second ** entry ID; ** ** INPUT: link object [R] ** IMPLICIT: ** ** RETURNS: 1 */ void LinkClose (LINKo *link) { FILE *file; char fileName[FILxXNAM+1]; int errCode; /* ** close indices */ if (link->btree1) BtrClose (link->btree1); if (link->btree2) BtrClose (link->btree2); if (link->ids1) IdsClose (link->ids1); if (link->ids2) IdsClose (link->ids2); /* ** sort after first entry and write to file */ LibGetLinkName (link, 0, fileName, "write"); file = FilOpenW (fileName, &errCode); _ErrExit2 (errCode, fileName); SetHeapSort (link->id_p, link->linkIdN, 8, 0, 4); SetRemoveDouble (link->id_p, link->linkIdN, 8, &link->linkIdN); link->lib1EntryN = SetCountKey (link->id_p, link->linkIdN, 8, 0, 4); /* ** convert number of IDs to platform independent format */ _BinFilePackNum (file, link->linkIdN); _BinFilePackNum (file, link->lib1EntryN); fwrite (link->id_p, 8, link->linkIdN, file); fclose (file); /* ** sort after second entry and write out */ LibGetLinkName (link, 1, fileName, "write"); file = FilOpenW (fileName, &errCode); _ErrExit2 (errCode, fileName); SetHeapSort (link->id_p, link->linkIdN, 8, 4, 4); link->lib2EntryN = SetCountKey (link->id_p, link->linkIdN, 8, 4, 4); _BinFilePackNum (file, link->linkIdN); _BinFilePackNum (file, link->lib2EntryN); fwrite (link->id_p, 8, link->linkIdN, file); fclose (file); _ErrMsg6 (i__builtlink, link->lib1->nam, link->lib2->nam, link->goodRefN, link->badRefN, link->linkIdN); link->isOpen = 0; } /**api* LinkNext ************************************************************ ** ** Returns the next link where the specified library participates and ** which has the specified characteristic. ** See also LibNextLink. ** ** INPUT: the library object [R] ** address of iterator which must be set to 0 to start [R] ** option: "read" [R] ** ** RETURNS: the link object ** NULL: list is exhausted */ LINKo *LinkNext (SLBo *lib, char *option, Int4 *i) { LINKo *link; switch (option[0]) { case 'r': /* read */ while (link = LibNextLink (i)) { if (link->lib1 == lib && *link->token) return link; } break; default: _ErrExit2 (e__unknownoption, option); } *i = 0; return NULL; } /**api* LinkIs *************************************************************** ** ** Returns whether or not the specified characteristic is true for ** the link. ** ** INPUT: the link object [R] ** option: "read", "index", "user", "libs" [R] ** ** RETURNS: TRUE or FALSE */ Int4 LinkIs (LINKo *link, char *option) { switch (tolower (option[0])) { case 'r': /* read */ return *link->token ? 1 : 0; case 'i': /* index */ return *link->token ? 0 : 1; case 'u': /* user */ return (LibIs (link->lib1, "user") || LibIs (link->lib2, "user")) ? 1: 0; case 'l': /* libs */ return link->lib1 && link->lib2 ? 1 : 0; default: _ErrExit2 (e__unknownoption, option); return NULL; } } /**api* LinkNextToken ********************************************************* ** ** Iterates over the tokens used for building 'read' links. ** The token is characterized by token table name and token code. ** Returns the name of the token table. The token code is written ** into specified address. ** ** INPUT: the link object [R] ** address of token code [W] ** address of iterator. Must be set to 0 to start [W] ** ** RETURNS: name of token table ** NULL: list is exhausted */ char *LinkNextToken (LINKo *link, Int4 *code, Int4 *i) { if (!*i) { (*i)++; *code = link->tokCode; return link->token; } else { *i = 0; return NULL; } } /**api* LinkIdWithString ************************************************************ ** ** Links an entry-ID with a all entries that 'have' the string in ** the index specified by the link. ** ** INPUT: link object [W] ** ID object [R] ** string [R] ** ** RETURNS: TRUE if entries to be linked where identified by string */ Int4 LinkIdWithString (LINKo *link, IDoENTRY *fromId, char *s) { static SETo set; IDoENTRY toId; BTRoREC *record; FIP idFip; Int4 i; if ((record = BtrSearch (link->btree2, s, &idFip, 0))) { LinkCollectSet (&set, record, link->ids2); for (i=0; SetNextId (&set, &toId, &i);) LinkAddLink (link, fromId, &toId); link->goodRefN++; return 1; } else { link->badRefN++; return 0; } } /**api* LinkAddLink ************************************************************ ** ** Adds a new link to the link-ID buffer. ** ** INPUT: link object [W] ** from-ID object [R] ** to-ID object [R] */ static void LinkAddLink (LINKo *link, IDoENTRY *fromId, IDoENTRY *toId) { if (link->linkIdN + 1 > LINKxMAXIDN) _ErrExit3 (e__settoosmall, link->linkIdN + 1, LINKxMAXIDN); memcpy (link->idWrtOff, fromId->id, fromId->siz); link->idWrtOff += fromId->siz; memcpy (link->idWrtOff, toId->id, toId->siz); link->idWrtOff += toId->siz; link->linkIdN++; } /**api* LinkCollectSet ********************************************************* ** ** Collects all the Ids linked to btree records into specified set. ** ** INPUT: set object [W] ** record from btree object [R] ** Ids file object [R] */ void LinkCollectSet (SETo *set, BTRoREC *record, IDSoFILE *idsFile) { IDoTYPE *idType; IDPTR tmp; idType = IdsGetIdType (idsFile); tmp = SetGetIdBuff (set, record->r.value.idN * IdSize (idType)); IdsGet (idsFile, tmp, record->r.value.firstIdFip, record->r.value.idN); SetSetEntryN (set, record->r.value.idN); SetSetIdType (set, idType); } ** ** $RCSfile: link.h,v $ ** $Revision: 1.3 $ ** $Date: 1996/08/11 22:47:16 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define LNKxSET 1 #define LNKxLINK 2 #define LNKxBUFFSIZ 8*300000 #define LNKxREAD 1 #define LNKxINDEX 2 #define LNKxMAPRNT 3 #define LINKxToParent 3 typedef struct LINKo *LINKv; typedef struct LINKoNODE *LINKvNode; #ifndef _SLBo typedef struct SLBo *dummytointroducestructtagSLBo; #endif typedef struct BTRoREC *dummytointroducestructtagBTRoREC; typedef struct IDSoFILE *dummytointroducestructtagIDSoFILE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ INT4 LinkInit (); INT4 LinkMap (char *a_nm, char *b_nm, SETo *c); INT4 LinkIdentify (char *nam, SETo **s_p, LINKv *linkPtr); LINKv LinkOpen (LINKv link, char *opt); void LinkSets (LINKv link, struct SETo *set1, struct SETo *set2); void LinkIds (LINKv link, struct IDoENTRY *id1, IDoENTRY *id2); void LinkClose (LINKv link); Int4 LinkGetCreTimeLinkN (LINKv link); INT4 LinkGetLinkN (LINKv link); INT4 LinkGetEntryN (LINKv link, INT4 isReverse); INT4 LinkToParent (char *a_nm, char *b_nm, SETo *c); Int4 LinkIsMapsToParent (LINKv link); LINKv LinkNext (struct SLBo *lib, char *option, Int4 *i); char *LinkNextToken (LINKv link, Int4 *code, Int4 *i); void LinkCollectSet (struct SETo *set, struct BTRoREC *record, struct IDSoFILE *idsFile); /* for playing with paths */ struct LINKoNODE *LinkSearchPath (char *fromName, char *toName); INT4 LinkGetPathLength (struct LINKoNODE *toNode); struct LINKoNODE *LinkBackTrack (struct LINKoNODE *fromNode, LINKv *link, INT4 *isReverse); struct LINKoNODE *LinkGetNextInPath (struct LINKoNODE *toNode, INT4 *isReverse); #include #include "def.h" #include "slist.h" /******************************************************************** ** SIMPLE LIST: ** only for elements that can be created, destroyed, copied and moved ** without the need of calling management functions. ********************************************************************/ int listPos; int listAddPos; LISTo* ListAllocImpl(int sz) { LISTo* l=(LISTo*)malloc(sizeof(LISTo)+sz); ASSERT(l,CouldNotAllocList); l->usage=1; l->end=sz; return l; } void* ListNewImpl(int sz) { LISTo* l=(LISTo*)malloc(sizeof(LISTo)+sz); ASSERT(l,CouldNotAllocList); l->usage=1; l->end=sz; l->len=0; return l+1; } void ListChangeImpl(void** list, int beg, int end) { LISTo* l=cast(*list, LISTo*)-1; int len=l->len; int dlen=end-beg; if (l->endusage>1) { LISTo* old=l+1; l=ListAllocImpl(len+dlen); l->len=len+dlen;l++; memcpy(offset(l, end, void*), offset(old,beg,void*), len-beg); if (dlen>0) memcpy(l, old, beg); else memcpy(l, old, end); ListDel(old); } else { l->len+=dlen; l++; memmove(offset(l,end, void*), offset(l,beg,void*), len-beg); } *list=l; } void ListDel(void* list) { LISTo* l=cast(list, LISTo*)-1; if (!--l->usage) free(l); } void ListDebug(void* list, int sz) { LISTo* l=(LISTo*)list-1; printf("LISTo:%p len:%d",list,l->len/sz); if (l->end!=l->len) printf(" grow:%d",(l->end-l->len)/sz); if (l->usage>1) printf(" shared:%d",l->usage-1); printf("\n"); } void ListIntDebug(int* list) { int i; ListDebug(list,sizeof(int)); printf("{ "); for (i=0; i<_ListLen(list); i++) { printf("%d ",list[i]); } printf("}\n"); } void ListPtrDebug(void** list) { int i; ListDebug(list,sizeof(void*)); printf("{ "); for (i=0; i<_ListLen(list); i++) { printf("%p ",list[i]); } printf("}\n"); } /************************************************************************** ** ALLOCATION POOL **************************************************************************/ /*#define POOL_DEBUG*/ #define POOL_MAX_ELEM_SIZE 256 #define POOL_CHUNK_SIZE 4096 #define ALIGN_SIZE_LOG 3 /* const WORD SMALL_OBJ_MASK=(POOL_MAX_ELEM_SIZE-1); const WORD TOO_BIG_MASK=~(POOL_CHUNK_SIZE-1); const WORD NOT_FITTING_OBJ_MASK=~((POOL_CHUNK_SIZE-1)&~SMALL_OBJ_MASK); */ void** pools[POOL_MAX_ELEM_SIZE>>ALIGN_SIZE_LOG]; long poolAllocated[POOL_MAX_ELEM_SIZE>>ALIGN_SIZE_LOG]; long poolAvailable[POOL_MAX_ELEM_SIZE>>ALIGN_SIZE_LOG]; void* palloc(int size) { if (size<=POOL_MAX_ELEM_SIZE) { void** pool; size=(size-1)>>ALIGN_SIZE_LOG; pool=pools[size]; if (pool) { /* return the first free element, and remove from list */ pools[size]=(void**)*pool; } else { /* create a new pool */ void **curr,**prev; int elemSize=(size+1)<pool) { *curr=prev; prev=curr; curr=offset(curr,-elemSize, void**); } pools[size]=prev; /* first free elem */ #ifdef POOL_DEBUG poolAvailable[size]+=poolNum; #endif } #ifdef POOL_DEBUG poolAllocated[size]++; poolAvailable[size]--; #endif return pool; } else return malloc(size); } void pfree(void* obj, int size) { ASSERT(obj, FreeingNull); if (size<=POOL_MAX_ELEM_SIZE) { void** elem=(void**)obj; /* add elem to free list */ size=(size-1)>>ALIGN_SIZE_LOG; *elem=pools[size]; pools[size]=elem; #ifdef POOL_DEBUG poolAllocated[size]--; poolAvailable[size]++; #endif } else free(obj); } void PoolDebug(int size) { #ifdef POOL_DEBUG int sz=(size-1)>>ALIGN_SIZE_LOG; printf("POOL size:%d allocated:%ld available:%ld\n", size, poolAllocated[sz], poolAvailable[sz]); #endif } void PoolDebugAll() { #ifdef POOL_DEBUG int sz; for (sz=0; sz>ALIGN_SIZE_LOG; sz++) { if (pools[sz]) PoolDebug((sz+1)<usage++,list) #define _ListSet(plist,list) (ListDel(*(plist)),*(plist)=_ListCpy(list)) /* element operations */ #define _ListIns(plist) *(ListChangeImpl((void**)(plist),0,sizeof(**(plist))),*(plist)) #define _ListAdd(plist,pos) *(_ListAddImpl(plist,pos)) #define _ListApp(plist) *(listPos=_ListLen(*(plist)),_ListAddImpl(plist,listPos)) #define _ListCut(plist,pos) (listPos=pos*sizeof(**(plist)),ListChangeImpl((void**)(plist),listPos+sizeof(**(plist)),listPos)) #define _ListPush(plist) _ListApp(plist) #define _ListPop(plist) (listPos=_ListLen(*(plist))-1,_ListCut(plist, listPos)) /* multiple elem operations */ #define _ListCutMany(plist,pos,num) (listPos=pos*sizeof(**(plist)),ListChangeImpl((void**)(plist),listPos+sizeof(**(plist))*num,listPos)) #define _ListInsMany(plist,num) (ListChangeImpl((void**)plist,0,sizeof(**plist)*num),(*plist)[pos]) #define _ListAddMany(plist,pos,num) (listAddPos=pos*sizeof(**(plist)),\ ListChangeImpl((void**)(plist),listAddPos,listAddPos+sizeof(**(plist))*num),*(plist)+pos) #define _ListAppMany(plist,num) (listPos=_ListLen(*(plist)),_ListAddMany(plist,listPos,num)) #define _ListAddArr(plist,pos,arr,num) memcpy(_ListAddMany(plist,pos,num),arr,sizeof(*plist)*num) #define _ListInsArr(plist,arr,num) memcpy(_ListInsMany(plist,num),arr,sizeof(*plist)*num) #define _ListAppArr(plist,arr,num) memcpy(_ListAppMany(plist,num),arr,sizeof(*plist)*num) #define _ListAddList(plist,pos,list) _ListAddArr(plist,pos,list,_ListLen(list)) #define _ListInsList(plist,list) _ListInsArr(plist,list,_ListLen(list)) #define _ListAppList(plist,list) _ListAppArr(plist,list,_ListLen(list)) /* access */ #define _ListAt(list,pos) (ASSERT(pos<_ListLen(list), OutOfBounds),list[pos]) #define _ListLen(list) (((LISTo*)(list)-1)->len/sizeof(*(list))) /************************************************************************** ** ALLOCATION POOL **************************************************************************/ void* palloc(int size); void pfree(void* obj, int size); #define _palloc(type) ((type*)palloc(sizeof(type))) #define _pfree(ptr) (pfree(ptr, sizeof(*(ptr)))) void PoolDebug(int size); void PoolDebugAll(); #endif #include #include #include #include #define DECLARE_ONLY #include "srs.h" INT4 IopCalc () { INT4 l, r, result; char op[10]; IargGetArgs ("op|r|l", op, &r, &l); switch (*op) { case '+': result = l + r; break; case '-': result = l - r; break; case '/': result = l / r; break; case '*': result = l * r; break; } IcaReturn ("int", result); } void LocalSetFunctions () { IcaSetFunction("IopCalc", (FUNC)IopCalc); } **********************************************************/ char logicals_ID[] = "$Id: logicals.c,v 1.1 1996/05/06 15:16:53 srs Exp $"; /* ** ** $RCSfile: logicals.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:53 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** Author of this module: Lukas Rosenthaler and Reinhard Doelz ** Heavy Modifications by Thure Etzold and John Smith ** Copyright granted to Thure Etzold for distribution withing the SRS package ** ****************************************************************************** ** * *********************************************************** * * * * * BIOFTP.UNIBAS.CH SOFTWARE DISTRIBUTION * * * * * *---------------------------------------------------------* * * Copyright notice * * * * * * This program package has been written starting from '92 * * * at the Biocomputing Laboratory, University of Basel, by * * * Lukas Rosenthaler. Though it has been a major effort to * * * make it work, no responsibility can be taken for errors * * * occuring while running the programs or resulting from * * * processing the program's output. The writing of these * * * was supported by Basel University. * * * * * * This program is public domain and can by used, copied * * * and modified without restriction as long as this * * * copyright notice is included. * * * * * * This program version can be obtained from the bioftp * * * anonymous ftp server, together with the README file. * * * Software may be used without charge following the rules * * * stated therein. Users should acknowledge the program * * * properly if results to be published are obtained. * * *********************************************************** * * * +----------------------------+--------------------------------------+ * | Dr. Lukas Rosenthaler | RF * rosenth@urz.unibas.ch | * | Biocomputing | DECNET 20579::48130::rosenth | * |Biozentrum der Universitaet | | * | Klingelbergstrasse 70 | FAX +41 61 261- 6760 or 267- 2078 | * | CH-4056 Basel | TEL +41 61 267- 2076 or 2247 | * +----------- bioftp.unibas.ch is the SWISS EMBnet node -------------+ * ----------------------------------------- * ****************************************************************************** */ /****************************************************************************** * * Description, Purpose * ^^^^^^^^^^^^^^^^^^^^ * * This modules implements a consistent handling of VMS logicals and * Unix environment variables (furtheron the term "logicals" is applied * both to VMS logical names and Unix environment variables). * The logicals may be nested, as long as the first component of a pathname * is a logical. A logical itself may reference another logical up to a * nesting depth of 32. * * Examples: * VMS: * $ define GCGDIR D$DISK:[SOFTWARE.GCG.] * $ define DATADIR GCGDIR:[PROTDATA.] * $ define WORKDB DATADIR:[WORK]WORKING_DATABASE.DAT * * WORKDB will translate to: * "D$DISK:[SOFTWARE.GCG][.PROTDATA.][WORK]WORKING_DATABASE.DAT" * * Unix: (assuming /bin/csh) * % setenv GCGDIR /usr/software/gcg * % setenv DATADIR GCGDIR/protdata * % setenv WORKDB DATADIR/work/working_database.dat * * WORKDB will translate to: * "/usr/software/gcg/protdata/work/working_database.dat" * ****************************************************************************** * * include files: * */ #include #ifdef VMS # include unixio # include stdio # include stdlib #else # include # include #endif #if defined dos # define SLASH '\\' # else # define SLASH '/' #endif #define PATH_BUF_LEN 132 /* maximal length of pathname */ /***api* LogNameTranslate ***************************************************** ** ** Translation of (possibly recursive) definition of VMS logical names of ** Unix environment variables. The routine uses the "getenv()" call which, ** in Unix, just returns the value of an environment variable. On VMS, ** "getenv()" first tries to use it's argument as a logical name that is to ** be translated, then searches the symbol name space. ** ** translate_logical() can resolve recursive definition of logiacls/environ- ** ment variables as long as the logical is always the first component of ** the path. The nesting depth may *NOT* be greater than 32 in order to ** prevent infinite loops which may occur (logical ONE points to TWO, which ** itself is a logical pointing to ONE...) ** ** If there is no translation, the routine returns the original path. ** The routine does *NOT* allocate memory for the translated path, so the ** caller has to provide the buffer and indicate it's length! ** * Parameters : * char *name : path to translate * char *trans_name : translated path * int len : length of string supplied as trans_name * ** RETURNS: success or failure */ int LogNameTranslate (char *name, char *trans_name, int len) { char strbuf1[PATH_BUF_LEN], strbuf2[PATH_BUF_LEN], log[PATH_BUF_LEN]; char *strptr; int depth, i, l; int no_more_trans; no_more_trans = 0; depth = 0; (void) strncpy (strbuf1, name, PATH_BUF_LEN); do { /* * search first delimiter in string. */ # ifdef VMS strptr = strchr (strbuf1, ':'); # else if ((strptr = strchr (strbuf1, ':')) == NULL) { strptr = strchr (strbuf1, SLASH); } else { strptr[0] = SLASH; } # endif if (strptr != NULL) { /* we do have a delimiter, we try to translate only up to the delimiter */ l = strptr - strbuf1; for (i = 0; i < l; i++) log[i] = strbuf1[i]; log[i] = '\0'; } else { /* no delimiter, we try to translate the whole string */ l = 0; (void) strcpy (log, strbuf1); } # ifdef VMS for (i = 0; i _LT_ strlen (log); i++) log[i] = (char) toupper ((int) log[i]); # endif if ((strptr = getenv (log)) != NULL) { /* * ok, we found translation */ (void) strcpy (strbuf2, strptr); if (l > 0) { #ifdef VMS /* * delimiter ":" included */ (void) strcat (strbuf2, &(strbuf1[l + 1])); #else /* * delimiter "/" or "\" for dos, *NOT* included */ (void) strcat (strbuf2, &(strbuf1[l])); #endif } (void) strcpy (strbuf1, strbuf2); } else { /* sorry, no translation */ no_more_trans = 1; } depth++; } while ((! no_more_trans) && (depth < 32)); /* * check, if logicals are too deeply nested, as e.g. * * VMS: define TEST MIST: * define MIST TEST: * unix: setenv TEST MIST * setenv MIST TEST * * These declarations will produce infinte loops * in resolving the "logicals". * Therefore we allow only a depth of 32 ! */ if (depth == 32) { /* infinite loop ? */ return (999); } /* * result string supplied was too short */ if (strlen (strbuf1) > len) { return (999); } else { #if defined dos { char * ds; if((ds=strstr(strbuf1,"\\\\"))==NULL); /* no double bslashes found */ else{ /* conv \\ to :\ */ *ds=':'; } } #endif (void) strcpy (trans_name, strbuf1); } return (0); } ** ** $RCSfile: logicals.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:54 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** Author of this module: Lukas Rosenthaler and Reinhard Doelz ** Copyright granted to Thure Etzold for distribution withing the SRS package ** ** ** ******************************************************************** ** * * ** * BIOFTP.UNIBAS.CH SOFTWARE DISTRIBUTION * ** * * ** * Copyright Notice * ** * ================ * ** * * ** * This include file contains the declarations for "logcials.c" * ** * Biocomputing Laboratory, University of Basel, by Lukas Rosen- * ** * thaler. For a detailed copyright notice see the README file or * ** * or the C source files! * ** ******************************************************************** ** ******************************************************************************* */ #ifdef _NO_PROTO extern INT4 translate_logical (); #else extern INT4 translate_logical (char *name, char *trans_name, INT4 len); #endif char lst_ID[] = "$Id: lst.c,v 1.2 1996/07/09 20:38:20 etzold Exp $"; /* ** ** $RCSfile: lst.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/07/09 20:38:20 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Author: Gerald Schaefer ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387372 ** Email: schaefer@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** management of a list of generic objects ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include typedef int INT4; /*#include "message.h"*/ #include "lst.h" #include "sdlget.h" #if !defined(TRUE) #define TRUE 1 #define FALSE 0 #endif #define LSTxOBJNAMELEN 20 #define LSTxDEFLISTSIZE 2 #define LSTxDEFHASHSIZE 2 /* ** LSTxHFREE means that this hash table element was never used before ** LSTxHDEL means that the element was used before but deleted now */ #define LSTxHFREE (void*)1L #define LSTxHDEL (void*)0L /* ** structure definition of the manager object, each list ** has one manager */ typedef struct { void **first_list_elem; /* address of an array of void pointers */ /* pointing to the objects. The array is */ /* automatically doubled, if overflow */ INT4 max_list_elem; /* max. number of objects to be handled by the list */ INT4 last; /* index of last inserted element in the list */ INT4 current; /* index of currently active object */ INT4 flex; /* flexible names */ INT4 not_hashed; /* counter for not-hashed objects (see delete) */ void **first_hash_elem; /* address of an array of void pointers */ /* pointing to the objects. The array is */ /* automatically doubled, if overflow */ INT4 max_hash_elem; /* max. number of objects in the hash table */ INT4 cur_hash_elem; /* current number of objects in the hash table */ } LSTo; /* ** type definition of the smallest object that can be stored ** in any list. All user defined objects must have these three ** attributes before its problem specific attributes. ** The first two attributes are initialized and maintained by ** the list module. The third attribute must be initialized ** by the application modules. If the application module never ** uses a search by name this attribute may be skipped. */ typedef struct { LSTo *manager; /* the first three attributes are necessary */ INT4 type_id; /* for all objects to be managed by the list */ char name[LSTxOBJNAMELEN]; } LSToOBJ; typedef struct { LSTo *manager; /* the first three attributes are necessary */ INT4 type_id; /* for all objects to be managed by the list */ char *name; /* flexible name length */ } LSToOBJFLEXNAME; /* ** by means of the following object type, any object may be fully ** described, that should be handled by the list module. The list ** module needs for each type of object the size (for allocation) ** and the functions to initialize, delete, or dump the objects. */ typedef struct { LSTo *manager; /* manager of list of manager_objects */ INT4 type_id; /* manager_object has type_id = 0 */ char name[LSTxOBJNAMELEN]; /* unused here */ INT4 obj_id; /* object_id (i.e. type_id of object to be managed) */ /* not really necessary at the moment == manager->last */ INT4 size; /* size of object */ INT4 flex; /* flexible names (pointer instead of array) */ void (*init_f)(void *); /* pointer to initialization function */ void (*delete_f)(void *); /* pointer to destructor function */ void (*print_f)(FILE *, void *); /* pointer to dump function */ } LSToMANAGER; /* ** static function prototypes of list module */ static LSTo *LstNewList(INT4 type_id); static INT4 LstIsList(LSTo *man); static LSTo *LstGetManager(void *obj); static unsigned LstHashFunc (LSTo *man, char *s); static INT4 LstHashObject(LSTo *man, void *obj); static INT4 LstHashUpdate(LSTo *man); static INT4 LstInsert(LSTo *man, void *obj); static INT4 LstGetObjSize(INT4 type_id); static void LstDeleteOne(void *obj); static INT4 LstRemoveFromList(void **obj); /* ** info_list is the internal list of the list module, by which the ** types of that objects are managed that will be able to be inserted ** into any other list. The pointer value NULL means that the list ** has not been initialized yet. */ static LSToMANAGER *info_list = NULL; /* ** normally there are object type dependent functions used to initialize ** new objects, to delete an object or to print the attribute values of ** an object. But there could be situations were you do not need one of ** these functions (e.g., you do not need a delete function if there are ** no pointers to subobjects, which should be deleted recursively). ** To supply the application programmer with a comfortable solution when ** he does not want to provide a special function, it has been implemented ** that the application programmer may supply NULL, if he does not need ** to program a special function. To prevent a segmentation fault the ** following dummy function is used in that case. ** For better testing there are now three different dummy functions ** init_dummy, delete_dummy, print_dummy ** calling the functions supplying a NULL-Pointer as parameter should print ** the function name (for use in LstInfo) */ static void init_dummy(void *x) { if (!x) printf(" *init_dummy* "); /* see LstInfo */ #if defined(TRACE) printf("*** function init_dummy called ***\n"); #endif /* ** may be called, if nothing to initialize */ } static void delete_dummy(void *x) { if (!x) printf(" *delete_dummy* "); /* see LstInfo */ #if defined(TRACE) printf("*** function delete_dummy called ***\n"); #endif /* ** may be called, if nothing to delete */ } static void print_dummy(FILE *file, void *x) { if (!x) printf(" *print_dummy* "); /* see LstInfo */ #if defined(TRACE) printf("*** function print_dummy called ***\n"); #endif /* ** may be called, if nothing to print */ } /**api* LstInfo *********************************************************** ** ** gets the manager object of the info_list and checks it. ** Prints the information on all classes that can be managed. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstInfo() { LSTo *man; INT4 i; man = LstGetManager(info_list); if (!man) { return 0; } printf("******* List Info ***************\n"); printf("* List Module can manage %d different classes:\n", man->last + 1); /* ** print the attribute values of all objects in the ordered object list */ for (i=0; i <= man->last; i++) { printf("...Class%d: ", i); printf(" ..ObjID: %d ", ((LSToMANAGER*)man->first_list_elem[i])->obj_id); printf(" ..Size: %d ", ((LSToMANAGER*)man->first_list_elem[i])->size); ((LSToMANAGER*)man->first_list_elem[i])->init_f(NULL); ((LSToMANAGER*)man->first_list_elem[i])->delete_f(NULL); ((LSToMANAGER*)man->first_list_elem[i])->print_f(NULL, NULL); } return 1; } /**api* LstManageClass ******************************************************** ** ** registers a new class to be managed by the list module. The type_id is ** passed back to the calling function. The class description (object ** size, functions to be used to initialize, delete or print an object ** of that class) is put into the info_list as a special manager object. ** If the info list does not already exist, it will be created ** automatically. ** If size is negative, flexible names (char*) are used ! ** ** INPUT: type id of a new class to be managed by the list module [W] ** size of an object of the new class [R] ** address of a function to be called to init an object [R] ** address of a function to be called to delete an object [R] ** address of a function to be called to dump an object [R] ** IMPLICIT: ** info_list (LSToMANAGER *) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstManageClass(INT4 *newtype_id, INT4 size, void (*init_func)(void *), void (*delete_func)(void *), void (*print_func)(FILE *,void *)) { /* ** only register classes that are not already registered ** it is convenient to pass 0 as newtype_id */ if (*newtype_id > 0) return 0; /* maybe already registered */ /* ** if info list does not already exist, create info list automatically */ if (!info_list) { if (!LstNew((void**)&info_list, 0)) return 0; /* the next initializations would not be necessary */ /* the values can not be asked for during runtime, as */ /* there would result some strange side effects !! */ info_list->type_id = 0; info_list->obj_id = 0; info_list->flex = FALSE; /* default */ info_list->size = sizeof(LSToMANAGER); info_list->init_f = init_dummy; info_list->delete_f = delete_dummy; info_list->print_f = print_dummy; } /* ** create a special manager object for the new class and ** put it into info list */ if (!LstNew((void**)&info_list, 0)) return 0; info_list->type_id = 0; info_list->obj_id = info_list->manager->last; if (size>0) { info_list->size = size; info_list->flex = FALSE; } else { info_list->size = -size; info_list->flex = TRUE; } info_list->init_f = init_func ? init_func : init_dummy; info_list->delete_f = delete_func ? delete_func : delete_dummy; info_list->print_f = print_func ? print_func : print_dummy; *newtype_id = info_list->manager->last; return 1; } /**api* LstManageClassFlex ************************************************ ** ** registers a new class to be managed by the list module. The type_id is ** passed back to the calling function. ** The object names will have dynamic (flexible) names. ** More details: see LstManageClass() ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstManageClassFlex(INT4 *newtype_id, INT4 size, void (*init_func)(void *), void (*delete_func)(void *), void (*print_func)(FILE *, void *)) { return LstManageClass(newtype_id, -size, init_func, delete_func, print_func); } /****** LstNewList ************************************************************ ** ** creates and initializes a manager object for a new list and ** allocates memory for an array, later used to store addresses ** of objects. ** To increase the speed when searching for named but unordered ** objects a hash table has been implemented, too. ** ** INPUT: type_id of object to create the list for [R] ** IMPLICIT: ** ** RETURNS: address of the manager object on success, NULL otherwise */ static LSTo *LstNewList(INT4 type_id) { INT4 i; LSTo *list = (LSTo*) malloc(sizeof(LSTo)); if (!list) return NULL; /* error handling ... */ /* ** initialize list */ list->max_list_elem = LSTxDEFLISTSIZE; list->first_list_elem = (void**)malloc(list->max_list_elem*sizeof(void*)); if (!list->first_list_elem) { free(list); return NULL; /* error handling ... */ } list->last = -1; list->current = -1; list->flex = FALSE; /* default */ if (type_id > 0) list->flex = ((LSToMANAGER*)info_list->manager-> first_list_elem[type_id]) -> flex; list->not_hashed = 0; /* ** initialize hash table */ list->max_hash_elem = LSTxDEFHASHSIZE; list->first_hash_elem = (void**)malloc(list->max_hash_elem*sizeof(void*)); if (!list->first_hash_elem) { free(list->first_list_elem); /* the above allocated array */ free(list); return NULL; /* error handling ... */ } list->cur_hash_elem = 0; for (i=0; i < list->max_hash_elem; i++) list->first_hash_elem[i] = LSTxHFREE; return list; } /****** LstIsList ************************************************************* ** ** checks if the manager object exists an has convenient attribute values. ** ** INPUT: address of an existing manager object [R] ** IMPLICIT: ** ** RETURNS: 1 if manager object seems ok, 0 otherwise */ static INT4 LstIsList(LSTo *man) { /* how to look for correct initialized lists ... ??? */ if (!man) return 0; if (man->max_list_elem < LSTxDEFLISTSIZE) return 0; if (man->last < 0) return 0; if (man->current < 0) return 0; /* how to look for correct initialized hash table ... ??? */ return 1; } /****** LstGetManager ********************************************************* ** ** checks, if the object exists and if the manager attribute of the object ** points to a correct manager object. ** ** INPUT: address of an existing object [R] ** IMPLICIT: ** ** RETURNS: address of manager object on success, 0 otherwise */ static LSTo *LstGetManager(void *obj) { LSTo *man; if (!obj) return 0; man = ((LSToOBJ*)obj)->manager; if (!LstIsList(man)) return 0; return man; } /****** LstHashFunc *********************************************************** ** ** computes a hash index for a given string. Needs the manager object ** to get the current size of the hash table. ** ** INPUT: address of an existing manager object [R] ** address of an object name to hash [R] ** IMPLICIT: ** ** RETURNS: the computed hash index */ static unsigned LstHashFunc (LSTo *man, char *s) { register unsigned long h=0, g; register char *p = s; while (*p) { h= (h << 4) + *p++; if ((g= (h & 0xf0000000))) h= (h ^ (g >> 24)) ^ g; } #ifdef xxxx while (*s) h = (h<<5) + *s++; /* horner's function ...segdewick */ /* h = (h << 1) ^ *s++; */ #endif return h % man->max_hash_elem; } /****** LstHashObject ********************************************************* ** ** puts an existing object into the hash table of the specified manager, ** but only if the object has a name (i.e. name length > 0). ** If there exists a collision with the hash index the next free ** position will be occupied (round robin). ** ** INPUT: address of an existing manager object [R] ** address of an existing object [R] ** IMPLICIT: ** modifies hash table and manager ** ** RETURNS: 1 */ static INT4 LstHashObject(LSTo *man, void *obj) { INT4 i; char *key; INT4 hash_index; /* ** insert object in hash table if name is longer than 0 */ if (man->flex) key = ((LSToOBJFLEXNAME*)obj)->name; else key = ((LSToOBJ*)obj)->name; if (key && strlen(key)>0) { /* hash object */ hash_index = (INT4) LstHashFunc(man, key); #if defined(TRACE) printf("hash_index for key *%s* is %d\n", key, hash_index); #endif /* search for next free place */ for (i=hash_index; imax_hash_elem; i++) if (man->first_hash_elem[i] <= LSTxHFREE) { man->first_hash_elem[i] = obj; /* no entry yet */ man->cur_hash_elem++; return 1; } for (i=0; ifirst_hash_elem[i] <= LSTxHFREE) { man->first_hash_elem[i] = obj; /* no entry yet */ man->cur_hash_elem++; return 1; } } else return 1; return 1; } /****** LstHashUpdate ********************************************************* ** ** updates the hash table of the specified manager. All at the moment ** not-hashed objects will be hashed, if their name length is > 0. ** If the hash table is not big enough, it will be doubled before ** hashing objects. For the sake of simplicity the table will be also ** doubled, if there would be not-hashed unnamed objects. ** ** INPUT: address of an existing manager object [R] ** IMPLICIT: ** modifies hash table and manager ** ** RETURNS: 1 if all named objects have been successfully inserted, ** 0 otherwise */ static INT4 LstHashUpdate(LSTo *man) { INT4 i, rv=1; /* be sure that hash table is big enough */ if (man->cur_hash_elem + man->not_hashed > (man->max_hash_elem * 0.8)) { void **tmp; #if defined(TRACE) printf("*** INFO: Expanding hash table from %d to ", man->max_hash_elem); #endif /* extend hash table and rehash all elements in list */ while (man->cur_hash_elem + man->not_hashed > man->max_hash_elem) man->max_hash_elem = man->max_hash_elem * 2 + 7; #if defined(TRACE) printf("%d elements ***\n", man->max_hash_elem); #endif tmp = (void**) malloc(man->max_hash_elem * sizeof(void*)); if (!tmp) return 0; /* no errror message to keep list module independent from other modules */ free(man->first_hash_elem); /* free old array */ man->first_hash_elem = tmp; /* use new array */ /* mark all elements as not-hashed */ man->not_hashed = man->last +1; for (i=0; i < man->max_hash_elem; i++) man->first_hash_elem[i] = LSTxHFREE; } /* hash all elements not currently hashed */ for (i = man->last - man->not_hashed + 1; i<=man->last; i++) rv &= LstHashObject(man, man->first_list_elem[i]); man->not_hashed = 0; return rv; } /**api* LstHashSearch ********************************************************* ** ** gets the manager object of an existing object list and checks it. ** Then an object with name obj_name is searched for using the ** hash table. If there are not-hashed objects the hash table needs ** to be updated first. ** Passes the address of the found object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** address of an object name to search for [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstHashSearch(void **obj, char *obj_name) { LSTo *man; LSToOBJ *tmp1; LSToOBJFLEXNAME *tmp2; INT4 i, rv = 1; INT4 stop_search = 0; INT4 hash_index; if (!strlen(obj_name)) return 0; man = LstGetManager(*obj); if (!man) return 0; /* ** if there are not-hashed objects (objects that are only ** inserted in the ordered list) update the hash table first */ if (man->not_hashed > 0) rv = LstHashUpdate(man); if (rv == 0) return 0; /* if malloc failed */ /* get hash index for object name */ hash_index = (INT4) LstHashFunc(man, obj_name); #if defined(TRACE) printf("hash_index for obj_name *%s* is %d\n", obj_name, hash_index); #endif /* search for object in hash table beginning with hash index */ if (man->flex) { for (i=hash_index; imax_hash_elem; i++) { tmp2 = (LSToOBJFLEXNAME*)man->first_hash_elem[i]; if ((void*)tmp2 == LSTxHFREE) {stop_search = 1; break;} if ((void*)tmp2 == LSTxHDEL) continue; if (!strcmp(tmp2->name, obj_name)) { /* named object found */ *obj = (void*)tmp2; return 1; } } if (!stop_search) for (i=0; ifirst_hash_elem[i]; if ((void*)tmp2 == LSTxHFREE) {stop_search = 1; break;} if ((void*)tmp2 == LSTxHDEL) continue; if (!strcmp(tmp2->name, obj_name)) { /* named object found */ *obj = (void*)tmp2; return 1; } } } else { for (i=hash_index; imax_hash_elem; i++) { tmp1 = (LSToOBJ*)man->first_hash_elem[i]; if ((void*)tmp1 == LSTxHFREE) {stop_search = 1; break;} if ((void*)tmp1 == LSTxHDEL) continue; if (!strcmp(tmp1->name, obj_name)) { /* named object found */ *obj = (void*)tmp1; return 1; } } if (!stop_search) for (i=0; ifirst_hash_elem[i]; if ((void*)tmp1 == LSTxHFREE) {stop_search = 1; break;} if ((void*)tmp1 == LSTxHDEL) continue; if (!strcmp(tmp1->name, obj_name)) { /* named object found */ *obj = (void*)tmp1; return 1; } } } return 0; /* named object not found */ } /****** LstInsert ************************************************************* ** ** inserts the address of the object into the list managed ** by the manager object. ** If the list will overflow, the array is automatically doubled in size. ** If the name of the object is not an empty string, then the object ** will be inserted into a hash table, too (see LstHashUpdate). ** ** INPUT: address of an existing manager object [R] ** address of an existing object [R] ** IMPLICIT: ** man (LSTo*) [W] ** ** RETURNS: 1 on success, 0 otherwise */ static INT4 LstInsert(LSTo *man, void *obj) { /* ** if list overflows, double object list and restore addresses */ if (man->last >= man->max_list_elem - 1) { INT4 i; void **tmp = (void**) malloc(2 * man->max_list_elem * sizeof(void*)); if (!tmp) return 0; #if defined(TRACE) printf("*** INFO: Expanding object list from %d to ", man->max_list_elem); #endif /* ** copy addresses of existing objects */ for (i=0; i < man->max_list_elem; i++) tmp[i] = man->first_list_elem[i]; free(man->first_list_elem); /* free old array */ man->first_list_elem = tmp; /* use new array */ man->max_list_elem *= 2; #if defined(TRACE) printf("%d elements ***\n", man->max_list_elem); #endif } man->last++; man->first_list_elem[man->last] = obj; man->current = man->last; ((LSToOBJ*)obj)->manager = man; /* ** update the counter of not-hashed objects */ man->not_hashed++; return 1; } /****** LstGetObjSize ********************************************************* ** ** The size of the object with type type_id is read from the info_list ** and returned. ** ** INPUT: type id of object [R] ** IMPLICIT: ** info_list (LSToMANAGER *) [R] ** ** RETURNS: size of object with type type_id; 0 if type_id incorrect */ static INT4 LstGetObjSize(INT4 type_id) { /* ** in the initialization phase info_list does not already ** exist when the size of the manager object (type_id == 0) ** has to be queried. The order of the following if-statements ** is very important to prevent a segmentation fault ! */ if (type_id == 0) return sizeof(LSToMANAGER); if (type_id < 0) return 0; if (!info_list) return 0; if (type_id > info_list->manager->last) return 0; return ((LSToMANAGER*)info_list->manager->first_list_elem[type_id])->size; } /**api* LstInsertObject ******************************************************* ** ** inserts an already existing object into an object list. ** If the object list does not already exist, it will be created ** automatically. ** Remember that the user of this function has to set the name and ** the type_id of the object correctly before inserting: there will ** be no initialization here. ** If this function fails, 0 will be returned, but the object will ** not be destroyed. ** If the complete list will be destroyed later, the object inserted ** by this function will be destroyed, too. ** If the name of the object is not an empty string, the object will ** be inserted into a hash table, if LstHashSearch will be used. ** ** INPUT: address of an address of an existing object [W] ** address of an existing object [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstInsertObject(void **obj, void *new_obj) { LSTo *man; /* ** if the object list does already exist, get the manager, ** if not, create a new list automatically and get the manager. */ if (*obj) { man = ((LSToOBJ*)*obj)->manager; if (!LstIsList(man)) return 0; } else man = LstNewList(((LSToOBJ*)new_obj)->type_id); /* ** insert the new object into the object list. On success modify the first ** function parameter to point to the new object, and return 1 */ if (LstInsert(man, new_obj)) { *obj = new_obj; return 1; } else return 0; /* object will not be destroyed automatically */ } /**api* LstNewNamed *********************************************************** ** ** creates a new object of type type_id and inserts this object into ** a list. The size of the object (obj_size) is read from the info_list. ** If the object list does not already exist, it will be created ** automatically. ** If name is not NULL, the name will be set after initialization. ** If the name is not an empty string, the object will be inserted ** into a hash table, too. ** ** INPUT: address of an address of an existing object [W] ** type id of object to be created [R] ** address of name of object [R] ** IMPLICIT: ** info_list (LSToMANAGER *) [R] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstNewNamed(void **obj, INT4 type_id, char *name) { LSTo *man; void *tmp; INT4 obj_size; /* ** read object size from info_list and fail if zero */ obj_size = LstGetObjSize(type_id); if (obj_size == 0) return 0; /* ** if the object list does already exist, get the manager, ** if not, create a new list automatically and get the manager. */ if (*obj) { man = ((LSToOBJ*)*obj)->manager; if (!LstIsList(man)) return 0; } else man = LstNewList(type_id); /* ** allocate memory for the new object, fail if not enough memory available. */ tmp = (void*) malloc(obj_size); if (!tmp) return 0; /* ** save the type_id within the new object, which is important ** for initializing, deleting, and printing of the object ** (object type dependent functions) */ ((LSToOBJ*)tmp)->type_id = type_id; if (man->flex) /* name is pointer */ ((LSToOBJFLEXNAME*)tmp)->name = NULL; /* initializing of objects depends on object type !!! */ if (type_id > 0) ((LSToMANAGER*)info_list->manager-> first_list_elem[((LSToOBJ*)tmp)->type_id]) -> init_f(tmp); /* if name is not NULL, set name */ if (name) { if (man->flex) { ((LSToOBJFLEXNAME*)tmp)->name = (char*)malloc(strlen(name)+1); strcpy(((LSToOBJFLEXNAME*)tmp)->name, name); } else strcpy(((LSToOBJ*)tmp)->name, name); } else { if (man->flex) ((LSToOBJFLEXNAME*)tmp)->name = NULL; else strcpy(((LSToOBJ*)tmp)->name, ""); } /* ** insert the new object into the object list. On success modify the first ** function parameter to point to the new object, and return 1 */ if (LstInsert(man, tmp)) { *obj = tmp; return 1; } else { free(tmp); /* release memory of object that could not be inserted */ return 0; } } /**api* LstNew **************************************************************** ** ** creates a new object of type type_id and inserts this object into ** a list. The size of the object (obj_size) is read from the info_list. ** If the object list does not already exist, it will be created ** automatically. ** ** INPUT: address of an address of an existing object [W] ** type id of object to be created [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstNew(void **obj, INT4 type_id) { return LstNewNamed(obj, type_id, NULL); } /**api* LstNewNamedUnique ************************************************* ** ** creates a new object of type type_id and inserts this object into ** a list, if there exists no object with the specified name. ** The size of the object (obj_size) is read from the info_list. ** If the object list does not already exist, it will be created ** automatically. ** ** INPUT: address of an address of an existing object [W] ** type id of object to be created [R] ** address of the unique object name [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstNewNamedUnique(void **obj, INT4 type_id, char *name) { void **tmp = obj; /* don't modify the object handle if no object inserted */ if (LstHashSearch(tmp, name)) return 0; return LstNewNamed(obj, type_id, name); } /**api* LstFirst ************************************************************** ** ** gets the manager object of an existing object list and checks it. ** Sets the attribute 'current' of the manager to 0 (first object). ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstFirst(void **obj) { LSTo *man; man = LstGetManager(*obj); if (!man) return 0; man->current = 0; /* it's sure that last >= 0 */ /* ** modify the object list handle to point to the new current object */ *obj = man->first_list_elem[man->current]; return 1; } /**api* LstLast *************************************************************** ** ** gets the manager object of an existing object list and checks it. ** Sets the attribute 'current' of the manager to 'last' (last object). ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstLast(void **obj) { LSTo *man; man = LstGetManager(*obj); if (!man) return 0; man->current = man->last; /* it's sure that last >= 0 */ /* ** modify the object list handle to point to the new current object */ *obj = man->first_list_elem[man->current]; return 1; } INT4 LstIsLast(void *obj) { LSTo *man; man = LstGetManager(obj); if (!man) return 0; return (man->current == man->last) ? 1 : 0; } /**api* LstNext **************************************************************** ** ** gets the manager object of an existing object list and checks it. ** Increments the attribute 'current' of the manager (next object). ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstNext(void **obj) { LSTo *man; man = LstGetManager(*obj); if (!man) return 0; if (man->current == man->last) return 0; man->current++; /* ** modify the object list handle to point to the new current object */ *obj = man->first_list_elem[man->current]; return 1; } /**api* LstPrev **************************************************************** ** ** gets the manager object of an existing object list and checks it. ** Decrements the attribute 'current' of the manager (previous object). ** Sets the attribute 'current' of the manager to 0 (first object). ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstPrev(void **obj) { LSTo *man; man = LstGetManager(*obj); if (!man) return 0; if (man->current == 0) return 0; man->current--; /* ** modify the object list handle to point to the new current object */ *obj = man->first_list_elem[man->current]; return 1; } /**api* LstGetPosition ******************************************************** ** ** gets the manager object of an existing object and checks it. ** Gets the attribute 'current' of the manager and returns it via 'n'. ** ** INPUT: address of an existing object contained in a list [R] ** address of an integer to return the current index [W] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstGetPosition(void *obj, INT4 *n) { LSTo *man; man = LstGetManager(obj); if (!man) return 0; *n = man->current; return 1; } /**api* LstSetPosition ***************************************************** ** ** gets the manager object of an existing object list and checks it. ** Sets the attribute 'current' of the manager to 'n', if correct. ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** position of an existing object in manager array [R] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstSetPosition(void **obj, INT4 n) { LSTo *man; man = LstGetManager(*obj); if (!man) return 0; if (n < 0 || n > man->last) return 0; man->current = n; /* ** modify the object list handle to point to the new current object */ *obj = man->first_list_elem[man->current]; return 1; } /**api* LstSetObjCurrent *************************************************** ** ** gets the manager object of an existing object list and checks it. ** Then the object 'newcurr' is searched for in the object list. ** The search begins with the first object. ** Sets the attribute 'current' of the manager to the index of the ** object 'newcurr'. ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** address of an object to search for [R] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstSetObjCurrent(void **obj, void *newcurr) { LSTo *man; INT4 i; man = LstGetManager(*obj); if (!man) return 0; for (i=0; i <= man->last; i++) if (man->first_list_elem[i] == newcurr) { man->current = i; *obj = man->first_list_elem[man->current]; return 1; } return 0; } /**api* LstFirstNamed ********************************************************* ** ** gets the manager object of an existing object list and checks it. ** Then an object with name obj_name is searched for in the object list. ** The search begins with the first object. ** Sets the attribute 'current' of the manager to the index of the ** object found first. ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** address of an object name to search for [R] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstFirstNamed(void **obj, char *obj_name) { LSTo *man; INT4 i, startpos=0; char *name; man = LstGetManager(*obj); if (!man) return 0; for (i=startpos; i <= man->last; i++) { if (man->flex) name = ((LSToOBJFLEXNAME*)man->first_list_elem[i])->name; else name = ((LSToOBJ*)man->first_list_elem[i])->name; if (!strcmp(name, obj_name)) { man->current = i; *obj = man->first_list_elem[man->current]; return 1; } } return 0; } /**api* LstNextNamed ********************************************************** ** ** gets the manager object of an existing object list and checks it. ** Then an object with name obj_name is searched for in the object list. ** The search begins with the object after current. ** So you can't find the first object using this function ! ** Sets the attribute 'current' of the manager to the index of the ** object found first. ** Passes the address of the current object back to the calling function. ** ** INPUT: address of an address of an existing object [R,W] ** address of an object name to search for [R] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstNextNamed(void **obj, char *obj_name) { LSTo *man; INT4 i; char *name; man = LstGetManager(*obj); if (!man) return 0; for (i=man->current+1; i <= man->last; i++) { if (man->flex) name = ((LSToOBJFLEXNAME*)man->first_list_elem[i])->name; else name = ((LSToOBJ*)man->first_list_elem[i])->name; if (!strcmp(name, obj_name)) { man->current = i; *obj = man->first_list_elem[man->current]; return 1; } } return 0; } /****** LstDeleteOne ********************************************************** ** ** deletes the specified object using a special function depending on ** the object type. LstDeleteOne can be used only internally in the ** context of LstDeleteAll or LstDelete because there are no changes ** to the pointer array of the manager. ** ** INPUT: address of an existing object [R] ** IMPLICIT: ** info_list (LSToMANAGER *) [R] ** ** RETURNS: nothing */ static void LstDeleteOne(void *obj) { /* deletion of objects depends on object type !!! */ if (((LSToMANAGER*)info_list->manager-> first_list_elem[((LSToOBJ*)obj)->type_id]) -> flex) free( ((LSToOBJFLEXNAME*)obj)->name ); ((LSToMANAGER*)info_list->manager-> first_list_elem[((LSToOBJ*)obj)->type_id]) -> delete_f(obj); if (!OddIsInDepot ((char *) obj)) free(obj); } /****** LstRemoveFromList ***************************************************** ** ** gets the manager object of an existing object list and checks it. ** If the current object is not equal to the object passed as argument, ** the current index is modified first. ** The pointer array of the manager is rearranged. Also the current ** object changes. It will be the next object, that has been moved to ** the position of the deleted object. If there is a reference to the ** object in the hash table this reference is removed, too. ** IMPORTANT: if the last object is removed from the list, the ordered ** list, the hash table and the manager is removed also. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ static INT4 LstRemoveFromList(void **obj) { LSTo *man; INT4 i; INT4 rv = 1; man = LstGetManager(*obj); if (!man) return 0; /* ** deleting an object is only possible if the object ** equals the current object in the ordered list ! ** if this is not true compute the correct current index */ if (man->first_list_elem[man->current] != *obj) { for (i=0; i <= man->last; i++) { if (man->first_list_elem[i] == *obj) { man->current = i; break; } } if (i > man->last) return 0; /* object not in ordered list */ /* -> if it should be possible to delete a hash table object, that */ /* is not in the ordered list a boolean variable is needed here */ /* -> in the current implementation this case will never arise */ } /* ** if the last object is removed from the list, free the ** administration objects, too */ if (man->last == 0) { free(man->first_list_elem); free(man->first_hash_elem); free(man); /* ** modify the object list handle to signal that list deleted; ** remember to delete the object in the calling function !!!! */ *obj = NULL; return 1; } /* ** if a hash table exists already and there are not-hashed objects ** in the ordered list, the hash table needs to be updated before ** the pointer to the object is removed */ if (man->cur_hash_elem > 0 && man->not_hashed > 0) { rv = LstHashUpdate(man); if (rv == 0) return 0; /* hash table update failed */ } if (man->cur_hash_elem > 0) { /* hash table exists */ for (i=0; i < man->max_hash_elem; i++) if (man->first_hash_elem[i] == *obj) { man->first_hash_elem[i] = LSTxHDEL; break; } } else man->not_hashed--; /* up to now hash table does not exist */ /* ** rearrange the pointer array of the manager. Be sure to do this ** after!! updating hashtable */ for (i=man->current; i < man->last; i++) man->first_list_elem[i] = man->first_list_elem[i+1]; man->first_list_elem[man->last] = 0; man->last--; if (man->current>man->last) man->current = man->last; /* if last deleted */ /* ** modify the object list handle to point to the new current object */ *obj = man->first_list_elem[man->current]; return 1; } /**api* LstDelete ************************************************************* ** ** LstDelete may be called externally. The object is removed from the list ** i.e. the pointer array of the manager is rearranged. Also the current ** object changes. It will be the next object, that has been moved to ** the position of the deleted object. If there is a reference to the ** object in the hash table this reference is removed, too. This is all ** done by LstRemoveFromList. After all the object is deleted. ** Caution: the programmer is responsible that the object has the ** correct type_id set ! ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstDelete(void **obj) { void *tmp; /* ** remember the object to delete */ tmp = *obj; if (!tmp) return 0; /* ** removes all references to the object */ if (!LstRemoveFromList(obj)) { fprintf(stderr, "FATAL_ERROR in LstDelete\n"); return 0; } /* ** delete the data structure of the object ** be sure that the object has the correct type_id set ! */ LstDeleteOne(tmp); return 1; } /**api* LstDeleteNamed ******************************************************** ** ** searchs for the object with the given name and deletes it, if found. ** LstDeleteNamed may be called externally to delete one named object. ** ** INPUT: address of an address of an existing object [R,W] ** address of name of object [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstDeleteNamed(void **obj, char *name) { if (!LstFirstNamed(obj, name)) return 0; return LstDelete(obj); } /**api* LstDeleteToEndOfList ************************************************** ** ** LstDeleteToEndOfList may be called externally to delete all objects ** (including the current object) up to the end of the list. ** Warning: If the first object is the current object, the effect ** is identical to LstDeleteAll. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstDeleteToEndOfList(void **obj) { LSTo *man; INT4 save; INT4 rv=1; man = LstGetManager(*obj); if (!man) return 0; /* ** if current object equals first object, delete the complete list */ if (man->current == 0) return LstDeleteAll(obj); /* ** Remember index of object, that should be the last afterwards, ** and remove all objects behind */ save = man->current - 1; while (save < man->last) rv = LstDelete(obj); return rv; } /**api* LstDeleteAll ********************************************************** ** ** gets the manager object of an existing object list and checks it. ** Then deletes all data structures belonging to the list. ** LstDeleteAll may be called externally to delete all objects ** inclusive the manager. A NULL pointer is given back to the ** calling function, so that the next insertion of a new object ** will automatically generate a new list. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** info_list (LSToMANAGER *) [R] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstDeleteAll(void **obj) { LSTo *man; INT4 i; man = LstGetManager(*obj); if (!man) return 0; /* ** delete the data structures of all objects */ for (i=0; i <= man->last; i++) LstDeleteOne(man->first_list_elem[i]); /* ** delete the arrays of the manager and the manager itself */ free(man->first_list_elem); /* delete ordered list */ free(man->first_hash_elem); /* delete hash table */ free(man); /* ** modify the object list handle to signal that the list is empty */ *obj = NULL; return 1; } /**api* LstPrint ************************************************************** ** ** prints the attribute values of the specified object using a ** special function depending on the object type. ** ** INPUT: file descriptor [W] ** address of an existing object [R] ** IMPLICIT: ** info_list (LSToMANAGER *) [R] ** ** RETURNS: nothing */ void LstPrint(FILE *file, void *obj) { /* printing of objects depends on object type !!! */ ((LSToMANAGER*)info_list->manager-> first_list_elem[((LSToOBJ*)obj)->type_id]) -> print_f(file, obj); } /**api* LstPrintAll *********************************************************** ** ** gets the manager object of an existing object list and checks it. ** Prints the attribute values of all objects in the object list. ** ** INPUT: address of an existing object [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstPrintAll(void *obj) { LSTo *man; INT4 i; man = LstGetManager(obj); if (!man) { #if defined(TRACE) printf("*** ERROR: no object list found !!! \n"); #endif return 0; } #if defined(TRACE) printf("* List has %d entries:\n", man->last + 1); /* test: generate hash table */ LstHashUpdate(man); #endif /* ** print the attribute values of all objects in the ordered object list */ for (i=0; i <= man->last; i++) { #if defined(TRACE) printf("...Object%d: ", i); #endif LstPrint(NULL, man->first_list_elem[i]); } #if defined(TRACE) /* ** print the attribute values of all objects in the hash table */ if (man->first_hash_elem) /* hash table exists ? */ for (i=0; i < man->max_hash_elem; i++) { if (man->first_hash_elem[i] <= LSTxHFREE) continue; printf("...HashObject%d: ", i); LstPrint(NULL, man->first_hash_elem[i]); } #endif return 1; } /**api* LstPrintAllNames ***************************************************** ** ** gets the manager object of an existing object list and checks it. ** Prints the names of all objects in the ordered object list. ** ** INPUT: address of an existing object [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstPrintAllNames(void *obj) { LSTo *man; INT4 i; char *name; man = LstGetManager(obj); if (!man) return 0; printf("* List has %d entries:\n", man->last + 1); /* ** print the names of all objects in the ordered object list */ for (i=0; i <= man->last; i++) { if (man->flex) name = ((LSToOBJFLEXNAME*)man->first_list_elem[i])->name; else name = ((LSToOBJ*)man->first_list_elem[i])->name; printf("...Object%2d: *%s*\n", i, name); } return 1; } /**api* LstLength ************************************************************* ** ** gets the manager object of an existing object list and checks it. ** If there is a correct list, computes the number of objects in ** the list and returns it. ** ** INPUT: address of an existing object [R] ** IMPLICIT: ** ** RETURNS: length of list on success, 0 otherwise */ INT4 LstLength(void *obj) { LSTo *man; man = LstGetManager(obj); if (!man) { #if defined(TRACE) printf("*** ERROR: no object list found !!! \n"); #endif return 0; } #if defined(TRACE) printf("* List has %d entries:\n", man->last + 1); #endif return man->last + 1; } /**api* LstRelease ************************************************************ ** ** LstRelease may be called externally. The object is removed from list, ** i.e. the pointer array of the manager is rearranged. Also the current ** object changes. It will be the next object, that has been moved to ** the position of the deleted object. If there is a reference to the ** object in the hash table this reference is removed, too. This is all ** done by LstRemoveFromList. The data structures of the ** object will still survive and the address will be returned. ** ** INPUT: address of an address of an existing object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: address of released object on success, 0 otherwise */ void *LstRelease(void** obj) { void *tmp; /* ** remember the object to release */ tmp = *obj; if (!tmp) return 0; /* ** removes all references to the object */ if (!LstRemoveFromList(obj)) return 0; /* ** remove the pointer to the manager and return the address of ** the released object */ ((LSToOBJ*)tmp)->manager = NULL; return tmp; } /**api* LstMove *************************************************************** ** ** the current object of the source object list is released (see above). ** Then gets the manager object of the destination list and checks it. ** If the destination list does not already exist, it is created ** automatically. Last the released object is inserted into ** the destination object list. ** ** As a side effect the current objects of both lists change. ** In case of the destination list, it will be the inserted object. ** In case of the source list, it will be the next object that has ** been moved to the position of the released object. ** ** INPUT: address of an address of the destination object [R,W] ** address of an address of an existing source object [R,W] ** IMPLICIT: ** man->current (INT4) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstMove(void** dest, void **source) { LSTo *man; void *tmp; /* ** release the current object in the source list and save ** it in tmp. Fail, if there is no object to release. */ tmp = LstRelease(source); if (!tmp) { fprintf(stderr, "FATAL_ERROR in LstMove (1)\n"); return 0; } /* ** get the manager of the destination list; if the list does ** not already exist, create it automatically. */ if (*dest) { man = ((LSToOBJ*)*dest)->manager; if (!LstIsList(man)) { fprintf(stderr, "FATAL_ERROR in LstMove (2)\n"); return 0; } } else man = LstNewList(((LSToOBJ*)tmp)->type_id); /* ** insert released object (tmp) into destination list */ if (LstInsert(man, tmp)) { *dest = tmp; return 1; } else { LstDeleteOne(tmp); /* delete released object !!??? */ /* ** if failed to insert first object into destination list, ** delete the arrays of the manager and the manager itself */ if (man->last < 0) { /* empty list */ free(man->first_list_elem); /* delete ordered list */ free(man->first_hash_elem); /* delete hash table */ free(man); } fprintf(stderr, "FATAL_ERROR in LstMove (3)\n"); return 0; } } /**api* LstAssign ************************************************************* ** ** assigns an existing parameter list to a sublist of another object. ** If the destination sublist does already exist, the parameter ** list cannot be inserted. The case that the parameter list does ** not exist is not checked, because LstAssign changes no values ** in that case. After assignment the parameter list is reset and ** may therefore be used to initialize any other parameter list. ** ** INPUT: address of an empty destination sublist [W] ** address of an (existing) parameter list [R,W] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstAssign(void** sublist, void **paramlist) { /* ** you can only assign a complete list ** no insertion is possible */ if (*sublist) return 0; *sublist = *paramlist; /* ** reset paramlist, so that it can be used for a new list later */ *paramlist = NULL; return 1; } /**api* LstChangeObjectName ******************************************** ** ** gets the manager object of an existing object list and checks it. ** Then changes the name of the specified object. ** Works for character pointer and character array! ** ** INPUT: address of an existing object [R] ** address of the new object name [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 LstChangeObjectName(void *tmp, char *name) { LSTo *man; char *old_name=NULL; man = LstGetManager(tmp); if (!man) return 0; /* check, if there is an old name that must be freed */ if (man->flex) { old_name = ((LSToOBJFLEXNAME*)tmp)->name; if (old_name) free(old_name); } /* set name */ if (name) { if (man->flex) { ((LSToOBJFLEXNAME*)tmp)->name = (char*)malloc(strlen(name)+1); strcpy(((LSToOBJFLEXNAME*)tmp)->name, name); } else strcpy(((LSToOBJ*)tmp)->name, name); } else { if (man->flex) ((LSToOBJFLEXNAME*)tmp)->name = NULL; else strcpy(((LSToOBJ*)tmp)->name, ""); } return 1; } ** ** $RCSfile: lst.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:55 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Author: Gerald Schaefer ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387451 ** Email: schaefer@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** management of a list of generic objects ** contains prototypes of non-static functions of the list module ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ INT4 LstInfo(); INT4 LstManageClass(INT4 *newtype_id, INT4 size, void (*init_func)(void *), void (*delete_func)(void *), void (*print_func)(FILE *, void *)); INT4 LstManageClassFlex(INT4 *newtype_id, INT4 size, void (*init_func)(void *), void (*delete_func)(void *), void (*print_func)(FILE *,void *)); INT4 LstHashSearch(void **obj, char *obj_name); INT4 LstInsertObject(void **obj, void *new_obj); INT4 LstNewNamed(void **obj, INT4 obj_id, char *name); INT4 LstNewNamedUnique(void **obj, INT4 obj_id, char *name); INT4 LstNew(void **obj, INT4 obj_id); INT4 LstFirst(void **obj); INT4 LstLast(void **obj); INT4 LstNext(void **obj); INT4 LstPrev(void **obj); INT4 LstGetPosition(void *obj, INT4 *n); INT4 LstSetPosition(void **obj, INT4 n); INT4 LstSetObjCurrent(void **obj, void *newcurr); INT4 LstFirstNamed(void **obj, char *obj_name); INT4 LstNextNamed(void **obj, char *obj_name); INT4 LstDelete(void **obj); INT4 LstDeleteNamed(void **obj, char *name); INT4 LstDeleteToEndOfList(void **obj); INT4 LstDeleteAll(void **obj); void LstPrint(FILE *file, void *obj); INT4 LstPrintAll(void *obj); INT4 LstPrintAllNames(void *obj); INT4 LstLength(void *obj); void *LstRelease(void** obj); INT4 LstMove(void** dest, void **source); INT4 LstAssign(void** sublist, void **paramlist); INT4 LstChangeObjectName(void *obj, char *name); /* info */ INT4 LstIsLast(void *obj); /* following functions would be nice ..... INT4 LstChangeName(char *old_name, char *new_name); ************************************************************/ char map_srs_ID[] = "$Id: map.c,v 1.1 1996/05/06 15:16:56 srs Exp $"; /* ** ** $RCSfile: map.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:56 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: rtl, file, sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** maps a file to memory and provides functions for writing to ** the file, saving and delteing the mapped memory; Either a ** file can be created with specified nr. of blocks or existing ** file can be extended by nr. of blocks. ** before deleting the mapsection the memory is saved to the file ** and the unused space of it is deleted; the output file is a ** Two functions for writing are provided for assuring that ** the map section is written to in a sequential manner. ** ** map-section-file: ** 1) LF-stream file (C-stream-file) ** 2) first longword contains number of bytes written to file ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include /* services definitions */ #include #include /* RMS data structures system */ #include /* defines codes for sys$getsyiw */ #include "rtl.h" #include "message.h" #include "futil.h" #include "map.h" #ifdef __ALPHA /****** MapPageSize *********************************************************** ** ** determines system's page size at run time - for compatibility ** of vms and openvms! ** ** INPUT: address of MAPo [W] ** address of buffer [W] or NULL ** size of section in bytes [R] ** ** RETURNS: 1 ** e__allocfail + */ int MapPageSize (long *cpupage_z) { /* ** structure with item list returned from sys$getsyiw (returns ** the size of the page size at run time */ static struct itm { short int buflen; /* length of buffer in byte */ short int item_code; /* symbolic item code */ long bufadr; /* address of return value buffer */ long retlenadr; /* address of return value buffer length */ } itemlist[2]; long cpupage_zlen; int rv; itemlist[0].buflen = 4; itemlist[0].item_code = SYI$_PAGE_SIZE; itemlist[0].bufadr = cpupage_z; itemlist[0].retlenadr = &cpupage_zlen; itemlist[1].buflen = 0; itemlist[1].item_code = 0; rv = sys$getsyiw (0, 0, 0, &itemlist, 0, 0, 0); _StopIfEven(rv); return 1; } #endif /****** MapCreSec ************************************************************* ** ** creates a map section - alignes the begin of the buffer to next page ** boundary which means the buffer shrinks! make sure it is big enough! ** buffer size will be tailored so that the end of the ** buffer falls onto a page boundary as well... ** ** INPUT: address of MAPo [W] ** address of buffer [W] or NULL ** size of section in bytes [R] ** ** RETURNS: 1 ** e__allocfail + */ int MapCreSec (MAPo *m, char *buff, int buff_z) { unsigned int mapaddr[2], secmask, pagelet_n ; int rv; long pagesize; char *buff_s; /* ** get cpu specific page size first ...mapped memorymust be aligned ** on that; */ #ifdef __ALPHA MapPageSize (&pagesize); #else pagesize = 512; #endif /* ** calculate new begin of buffer -> to next block boundary ...since ** these may result in a decrease of the buffer size the amount of ** bytes shifted must be subtracted from the buffer size; */ if (buff) { buff_s = buff; buff = (char *) ((((unsigned long) buff - 1) / pagesize) * pagesize + pagesize); buff_z -= buff - buff_s; buff_z = (buff_z / pagesize) * pagesize; pagelet_n = buff_z / 512; } /* ** define start and end addresses of map section - if buff and buff_z != 0 */ mapaddr[0] = buff; mapaddr[1] = mapaddr[0] + buff_z - 1; /* MUST point to last byte in buff */ secmask = (buff ? 0 : SEC$M_EXPREG) | (m->wrt_f == TRUE ? SEC$M_WRT : 0); rv = sys$crmpsc ( &mapaddr, &(m->raddr), 0, secmask, 0, 0, 0, m->chan, pagelet_n, 0, 0, 0); _StopIfEven(rv); m->data = m->raddr[0]; m->xbyt = m->raddr[1] - (unsigned int) m->data; if (m->xbyt < buff_z -1 && buff_z != 0 && m->wrt_f) _ErrExit3 (e__crmpscfail, pagelet_n, (m->xbyt/512)); m->trnc_f = TRUE; return 1; } /**api* MapMem **************************************************************** ** ** opens file and maps it to memory for read access only; ** ** INPUT: address of map-descriptor [W] ** address of filename [R] ** address of buffer [W] or NULL ** size of buffer in bytes [R] or 0 ** IMPLICIT: ** ** RETURNS: 1 if success ** e__filopenerr + */ int MapMem (MAPo *m, char *fil_n, void *buff, int buff_z) { struct FAB fab; struct RAB rab; int k, n, rv, size = 0; fab = cc$rms_fab; /* init fab */ fab.fab$l_dna = fil_n; fab.fab$b_dns = strlen(fil_n); fab.fab$l_fop = FAB$M_UFO; /* user file open */ /* fab.fab$b_shr = FAB$M_NIL;*/ /* no sharing */ fab.fab$b_rfm = FAB$C_STMLF; /* C stream file */ rv = sys$open (&fab); /* open file + get channel */ if (!(rv % 2)) _ErrRet2 (e__filopenerr, fil_n); m->chan = fab.fab$l_stv; m->wrt_f = FALSE; rv = MapCreSec(m, buff, buff_z); m->foff = m->data; m->off = (unsigned int) m->data + *(m->foff); strcpy(m->filn, fil_n); return 1; } /**api* MapAlloc ************************************************************** ** ** allocates nr. of blocks, opens file of same size and creates map ** section; ** ** INPUT: address of MAPo ** address of file name ** nr. of blocks to be allocated ** ** OUTPUT: ** returns: 1 if success ** e__allocfail + ** e__filopenerr + */ int MapAlloc (MAPo *m, char *filn, int nbloc) { struct FAB fab; register rv; fab = cc$rms_fab; /* create file access */ fab.fab$l_dna = filn; /* block descr. of file */ /* name */ fab.fab$b_dns = strlen(filn); fab.fab$l_alq = nbloc; /* nr. of blocks to */ fab.fab$l_fop = FAB$M_UFO; /* allocate user file open */ fab.fab$b_rfm = FAB$C_STMLF; /* C stream file no */ fab.fab$b_shr = FAB$M_NIL; /* sharing */ rv = sys$create (&fab); /* open file + get channel */ if (rv % 2 == 0) _ErrRet2 (e__filopenerr, filn); m->chan = fab.fab$l_stv; m->wrt_f = TRUE; rv = MapCreSec(m, NULL, nbloc*512); strcpy(m->filn, filn); m->off = m->data + 4; /* room for offset */ m->foff = m->data; *(m->foff) = 4; return 1; } /**api* MapExtend ************************************************************* ** ** opens existing file and adds specified nr. of blocks to it - resultant ** file is mapped to memory; ** If nbloc ==0 file has to be opened in order to get the section's size; ** ** INPUT: address of MAPo ** address of filename ** nr. of blocks to add ** ** OUTPUT: ** returns: 1 ** e__filopenerr + */ int MapExtend (MAPo *m, char *filn, int nbloc) { struct FAB fab; struct RAB rab; char blocks[32767]; /* 64 blocks */ int k, n, rv, size; fab = cc$rms_fab; /* init fab */ fab.fab$l_dna = filn; fab.fab$b_dns = strlen(filn); fab.fab$b_fac = FAB$M_UPD | FAB$M_BIO | FAB$M_PUT; fab.fab$w_mrs = sizeof(blocks); /* max. record size */ rab = cc$rms_rab; /* init rab */ rab.rab$l_fab = &fab; rab.rab$l_rbf = &blocks; rab.rab$b_rac = RAB$C_RFA; /* acc. by record file */ rab.rab$l_rop = RAB$M_EOF; /* addr. pos. at EOF */ /* after open */ rab.rab$w_rsz = fab.fab$w_mrs; rv = sys$open (&fab); /* open file + get channel */ if (rv % 2 == 0) { _ErrMsg2 (e__filopenerr, filn); _StopIfEven(rv); } rv = sys$connect (&rab); if (rv % 2 == 0) _ErrRet2 (e__filopenerr, filn); rv = sys$write (&rab); /* get file siz after */ /* $write */ _StopIfEven(rv); size = 64 + (int) rab.rab$w_rfa[0] - 1; if ((nbloc = nbloc - 64) > 0) /* write more if necess. */ { n = MapMOD(nbloc, 64); for (k = 0; k < n; k++) { size += 64; rv = sys$write (&rab); _StopIfEven(rv); } } rv = sys$close (&fab); _StopIfEven(rv); fab.fab$l_fop = FAB$M_UFO; /* user file open no */ /* sharing C stream file */ if (!m->wrt_f) fab.fab$b_fac = FAB$M_GET; fab.fab$b_shr = m->wrt_f ? FAB$M_NIL : FAB$M_SHRGET; fab.fab$b_rfm = FAB$C_STMLF; /* open file + get channel */ rv = sys$open (&fab); _StopIfEven(rv); m->chan = fab.fab$l_stv; rv = MapCreSec(m, NULL, size*512); m->foff = m->data; m->off = m->data + *(m->foff); strcpy(m->filn, filn); return 1; } /**api* MapFree *************************************************************** ** ** frees map section + updates i.e. writes mapped file; ** writes two extra '\n' - the first is supposed to be the last record's ** end and the second is for rfa-access in MapTruncate - otherwise ** unpredictable positioning ** ** INPUT: address of MAPo ** ** OUTPUT: ** returns: 1 */ int MapFree(MAPo *m) { int rv; if (m->wrt_f) { *(m->off) = '\n'; /* for rfa access for rfa */ *(m->off+1) = '\n'; /* access */ } rv = sys$deltva ( /* del map sect + update */ /* fil */ &(m->raddr), 0, 0); _StopIfEven(rv); /* free(m->alloc);*/ rv = sys$dassgn (m->chan); /* close file */ _StopIfEven(rv); if (m->trnc_f && m->wrt_f) MapTruncate(m); /* cut off unused space */ return 1; } /****** MapTruncate *********************************************************** ** ** truncates a file to the size that is really used (MAPo->off); ** ** INPUT: address of MAPo ** ** OUTPUT: ** returns: 1 */ int MapTruncate (MAPo *m) { struct FAB fab; struct RAB rab; int rv, nbyte, blocn, off; fab = cc$rms_fab; /* init fab */ fab.fab$l_dna = m->filn; fab.fab$b_dns = strlen(m->filn); fab.fab$b_fac = FAB$M_TRN | FAB$M_UPD; /* truncate access trunc */ fab.fab$l_fop = FAB$M_TEF; /* alloc at EOF C stream */ fab.fab$b_rfm = FAB$C_STMLF; /* file no sharing */ fab.fab$b_shr = FAB$M_NIL; rab = cc$rms_rab; /* init rab */ rab.rab$l_fab = &fab; rab.rab$b_rac = RAB$C_RFA; /* acc. by record file */ /* addr. */ rv = sys$open (&fab); /* access file */ _StopIfEven(rv); rv = sys$connect (&rab); _StopIfEven(rv); /* goto end of file */ nbyte = (unsigned int) m->off - (unsigned int) m->data; blocn = nbyte / 512; off = nbyte - blocn * 512+1; blocn = off == 0 ? blocn: blocn + 1; rab.rab$w_rfa[0] = blocn; rab.rab$w_rfa[2] = off; rv = sys$find (&rab); _StopIfEven(rv); rv = sys$truncate (&rab); /* truncate */ _StopIfEven(rv); rv = sys$close (&fab); _StopIfEven(rv); return 1; } /****** MapNew **************************************************************** ** ** returns relative section file's address of begin of unused space; ** only MapPutS and MapWrite may be used for writing to the map-section; ** ** INPUT: address of MAPo ** address of address where to put file address ** ** OUTPUT: places file address into transm. address ** returns: 1 if success */ int MapNew (MAPo *m, unsigned int *fadd) { *fadd = *(m->foff); return 1; } /**api* MapCNew *************************************************************** ** ** returns relative file address of begin of unused space in cache; ** only MapCWrite may be used for writing to the cache; ** ** INPUT: address of MAPoCCH ** address of address where to put file address ** ** OUTPUT: places file address into transm. address ** returns: 1 if success */ int MapCNew (MAPoCCH *c, unsigned int *fadd) { *fadd = *(c->foff); return 1; } /****** MapPutS *************************************************************** ** ** puts a 0-terminated string at the end of used space in map-section ** map->off and map->foff are updated according to string length; ** ** INPUT: address of MAPo ** address of string ** ** OUTPUT: ** returns: 1 if success ** e__eom < file-name, max nr. of bytes> */ int MapPutS (MAPo *m, char *s) { int len; len = strlen(s); if (*m->foff + len + 1 > m->xbyt) return e__eom; strcpy(m->off, s); m->off = (unsigned int) m->off + len + 1; *(m->foff) = *(m->foff) + len + 1; return 1; } /****** MapWrite ************************************************************** ** ** appends specified nr. of bytes to end of used map-section; ** ** INPUT: address of MAPo ** address of source ** nr. of bytes to be transferred ** ** OUTPUT: ** returns: 1 if ok ** e__eom < file-name, max nr. of bytes> */ int MapWrite (MAPo *m, char *s, int n) { if (*m->foff + n > m->xbyt) return e__eom; memcpy(m->off, s, n); m->off = (unsigned int) m->off + n; *(m->foff) += n; return 1; } /****** MapMalloc ************************************************************* ** ** same as malloc but allocates in map-section; ** ** INPUT: address of MAPo ** nr. of bytes to be allocated ** ** OUTPUT: ** returns: address of allocated area if ok ** NULL if e__eom */ char *MapMalloc (MAPo *m, int n) { char *off_s; if (*m->foff + n > m->xbyt) return NULL; off_s = m->off; m->off = (unsigned int) m->off + n; *(m->foff) += n; return off_s; } /**api* MapCWrite ************************************************************* ** ** appends specified nr. of bytes to end of used cache; ** ** INPUT: address of MAPoCCH ** address of source ** nr. of bytes to be transferred ** ** OUTPUT: ** returns: 1 if ok ** e__eoc */ int MapCWrite (MAPoCCH *c, char *s, int n) { memcpy(c->off, s, n); c->off = (unsigned int) c->off + n; *(c->foff) = *(c->foff) + n; if (c->off > c->buff + (c->nbloc - 1) * 512) MapFlush(c); return 1; } /**api* MapInitCache ********************************************************** ** ** initializes a cache, i.e. allocates memory, opens files etc.; ** MAPoCCH->foff must be set before calling (0 = no existing file) ** ** INPUT: cache descriptor MAPoCCH [W] ** file name [R] ** address of cache's file offset [W] ** flag if new file should be opened [R] ** ** RETURNS: 1 if success ** e__allocfail + ** e__filopen + */ int MapInitCache (MAPoCCH *c, char *fil_nm, unsigned *foff, int new_f) { int nbloc; c->filn = fil_nm; c->foff = foff; if (new_f) *foff = 0; c->hbloc = MapMOD(c->nbloc, 2); c->nbloc = c->hbloc * 2; /* even number */ if ((c->buff = malloc(c->nbloc * 512)) == 0) _ErrRet2(e__allocfail, "cache buffer"); c->fab = 0; c->rab = 0; if (*(c->foff) == 0) { c->new_f = TRUE; c->off = c->buff; c->fstbloc = 1; c->coff = 0; } else { c->new_f = FALSE; nbloc = MapMOD(*(c->foff), 512); if ((c->fstbloc = nbloc - c->hbloc + 1) <= 1) { c->fstbloc = 1; c->coff = 0; } else { nbloc = c->hbloc; c->coff = (c->fstbloc-1) * 512; } c->off = c->buff + *c->foff - c->coff; MapReadBlk (c, nbloc, c->fstbloc); } return 1; } /****** MapFlush ************************************************************** ** ** closes file theat was opend for read/update access (for fseek) ** writes 1st half of cache to file, shifts 2nd half of cache to begin ** and opens file again for read/upd access (no sharing possible); ** ** INPUT: address of MAPoCCH ** ** OUTPUT: ** returns: 1 if OK */ int MapFlush (MAPoCCH *c) { int shift = c->hbloc * 512; MapWriteBlk(c, c->hbloc+1, c->fstbloc); memcpy(c->buff, c->buff + shift, shift); c->fstbloc += c->hbloc; c->off -= shift; c->coff = c->coff + shift; return 1; } /****** MapCloseCache ********************************************************* ** ** flushes cache to file and deletes memory; ** ** INPUT: address of MAPoCCH ** ** OUTPUT: ** returns: 1 if success */ int MapCloseCache (MAPoCCH *c) { int nbloc, rv; nbloc = MapMOD(*(c->foff) - c->coff, 512); MapWriteBlk(c, nbloc, c->fstbloc); rv = sys$close (c->fab); _StopIfEven(rv); return 1; } /****** MapWriteBlk *********************************************************** ** ** opens file for block-IO and writes specified number of blocks to ** block offset and closes file; ** writes in portions of 64 blocks which is the max size of block-IO; ** ** INPUT: address of MAPoCCH ** nr of blocks to write ** block offset in file ** ** OUTPUT: ** returns: 1 if OK */ int MapWriteBlk (MAPoCCH *c, int nbloc, int off) { struct FAB *fab; struct RAB *rab; char *data = c->buff; int n, rv; if (c->rab == 0) rv = MapFOpen(c, MAPxWRITE); fab = c->fab; rab = c->rab; fab->fab$w_deq = nbloc; /* extend quantity */ rab->rab$l_bkt = off; while (nbloc > 0) { n = nbloc - 64; n = n < 0 ? nbloc : 64; rab->rab$w_rsz = n * 512; rab->rab$l_rbf = data; data = (unsigned int) data + n * 512; nbloc -= n; rv = sys$write (rab); _StopIfEven(rv); rab->rab$l_bkt += n; } return 1; } /****** MapFOpen ************************************************************** ** ** opens file for block-IO, read and write access - creates a new file ** if c->fstblock = 1; ** ** INPUT: address of MAPoCCH ** access mode: MAPxWRITE, MAPxREAD ** ** OUTPUT: ** returns: 1 if success ** e__allocfail + */ int MapFOpen (MAPoCCH *c, int acc_o) { struct FAB *fab; struct RAB *rab; int rv; if ((fab = malloc(sizeof(struct FAB))) == 0) _ErrRet2(e__allocfail, "FAB"); if ((rab = malloc(sizeof(struct RAB))) == 0) _ErrRet2(e__allocfail, "RAB"); *fab = cc$rms_fab; fab->fab$l_dna = c->filn; fab->fab$b_dns = strlen(c->filn); fab->fab$b_fac = acc_o == MAPxWRITE ? FAB$M_BIO | FAB$M_GET | FAB$M_PUT : FAB$M_BIO | FAB$M_GET; fab->fab$b_rfm = FAB$C_STMLF; /* C stream file */ if (!c->new_f) fab->fab$l_fop = FAB$M_CIF; /* open existing file */ *rab = cc$rms_rab; rab->rab$l_fab = fab; rv = sys$create (fab); /* open file */ _StopIfEven(rv); rv = sys$connect (rab); _StopIfEven(rv); c->fab = fab; c->rab = rab; return 1; } /****** MapReadBlk ************************************************************ ** ** opens file for block-IO and reads specified number of blocks from ** block offset and closes file; ** reads in portions of 64 blocks which is the max size of block-IO; ** ** INPUT: address of MAPoCCH ** nr of blocks to read ** block offset in file (first block = 1) ** ** OUTPUT: ** returns: 1 if OK */ int MapReadBlk (MAPoCCH *c, int nbloc, int off) { struct FAB *fab; struct RAB *rab; char *data = c->buff; int n, rv; if (c->fab == 0) rv = MapFOpen(c, MAPxWRITE); fab = c->fab; rab = c->rab; rab->rab$l_bkt = off; while (nbloc > 0) { n = nbloc - 64; n = n < 0 ? nbloc : 64; rab->rab$w_usz = n * 512; rab->rab$l_ubf = data; data = (unsigned int) data + n * 512; nbloc -= n; rv = sys$read (rab); _StopIfEven(rv); } return 1; } /****** MapRdMem ************************************************************** ** ** reads sectin file into private memory; ** reads in portions of 64 blocks which is the max size of block-IO; ** ** INPUT: section file name ** pointer to memory block ** ** OUTPUT: ** returns: 1 if OK ** e__allocfail + */ int MapRdMem (char *fil_nm, void **p) { struct FAB *fab; struct RAB *rab; MAPoCCH *c; char *data; int n, rv, size; c = calloc (1, sizeof (MAPoCCH)); strcpy (c->filn, fil_nm); rv = MapFOpen(c, MAPxREAD); _ErrRet (rv); size = c->fab->fab$l_alq; c->rab->rab$l_bkt = 1; /* start reading with */ /* first block */ if ((data = malloc (size * 512)) == 0) _ErrExit2(e__allocfail, "memory by MapRdMem"); *p = data; while (size > 0) { n = size - 64; n = n < 0 ? size : 64; c->rab->rab$w_usz = n * 512; c->rab->rab$l_ubf = data; data = (unsigned int) data + n * 512; size -= n; rv = sys$read (c->rab); _StopIfEven(rv); } rv = sys$close (c->fab); _StopIfEven(rv); return 1; } /**api* MapCUpdate ************************************************************ ** ** overwrites an integer at desired file offset; this corresponds ** to fseek + putw, here however block-IO is used to get block, modify it ** and write it back; ** ** INPUT: address of MAPoCCH ** relative file position ** value ** ** OUTPUT: ** returns: 1 if success */ int MapCUpdate (MAPoCCH *c, unsigned int fadd, char *fip) { struct RAB *rab = c->rab; static char buffer[1024]; static char *buff = &(buffer[0]); char *updloc; int rv, blocn, nbyte, blocoff; blocn = MapMOD(fadd, 512); /* number of block */ blocoff = fadd - (fadd/512)*512; if (blocoff == 0) blocn++; nbyte = blocoff > 508 ? 1024 : 512; rab->rab$w_usz = nbyte; rab->rab$l_ubf = buff; rab->rab$w_rsz = nbyte; rab->rab$l_rbf = buff; rab->rab$l_bkt = blocn; rv = sys$read (rab); _StopIfEven(rv); updloc = buff + blocoff; memcpy (updloc, fip, 4); rab->rab$l_bkt = blocn; rv = sys$write (rab); _StopIfEven(rv); return 1; } /**api* MapInCache ************************************************************ ** ** translates relative byte offset in file into cache address if referring ** to location in cache; ** ** INPUT: address of MAPoCCH ** relative file address ** address that receives translation ** ** OUTPUT: places address into address ** returns: 1 if translation was done ** 0 if location is not in cache */ int MapInCache (MAPoCCH *c, unsigned int fadd, void **ptr) { if (fadd < c->coff) return 0; else *ptr = fadd - c->coff + (unsigned int) c->buff; return 1; } /****** MapMOD **************************************************************** ** ** ** INPUT: divident ** divisor ** ** OUTPUT: ** returns: divident MOD divisor */ int MapMOD (int a, int b) { int quot; quot = a/b; return a == quot*b ? quot : ++quot; } /**api* MapDuplicateOverlap *************************************************** ** ** Addresses that need updating may be exactly on the boundary between ** file and memory cache ...in that case both locations need updating. ** This function updates in the cache only those bytes that overlaps. ** ** INPUT: address of IDS-file object [R] ** file pointer to first ID in the list [W] ** IMPLICIT: ** ** RETURNS: length of overlap ** 0 if no overlap exists */ INT4 MapDuplicateOverlap (MAPoCCH *cache, UINT4 fip, void *buff, INT4 size) { INT4 overlapLen; overlapLen = size - (cache->coff - fip); if ((cache->coff > fip) && overlapLen > 0) { memcpy (cache->buff, (char *) buff + size - overlapLen, overlapLen); return overlapLen; } else return 0; } ** ** $RCSfile: map.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:16:57 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define MAPxWRITE 1 #define MAPxREAD 2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** virtual memory (map) section */ typedef struct MAPo { char filn[FILxXNAM+1]; /* file name */ unsigned short chan; /* channel number returned by sys$create */ UINT4 xbyt; /* size of section in bytes */ UINT4 *foff; /* pointer to relative file address in section file */ char *off; /* pointer to relative file address in section file */ char *alloc; /* start address of allocated memory */ char *data; /* buffers start address */ UINT4 raddr[2]; /* array of start and end address returned by sys$crmpsc used by sys$deltva */ unsigned char trnc_f; /* TRUE: resultant file is truncated to size actually used */ unsigned char wrt_f; /* TRUE: mapsection has write access - changes are saved on disk */ unsigned char isAllocBuff; /* buffer has been allocated for section */ } MAPo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** cache object */ typedef struct MAPoCCH { char *filn; /* file name */ #ifdef VMS struct FAB *fab; struct RAB *rab; #else INT4 fid; #endif char *buff; /* address of buffer */ INT4 nbloc; /* size of cache in blocks */ INT4 hbloc; /* half of ->nbloc */ INT4 fstbloc; /* first block of file to receive flushing */ char *off; /* current address (after last byte added) in cache */ UINT4 coff; /* rel. file address of first byte in cache */ UINT4 *foff; /* pointer to current address (after last byte added) rel. file address */ INT4 new_f; /* flag set if a new cache file is opened during program execution */ } MAPoCCH; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ INT4 MapMem (MAPo *m, char *fil_n, void *buff, INT4 buff_z); INT4 MapFree (MAPo *m); INT4 MapAlloc (MAPo *m, char *filn, INT4 nbloc); char *MapMalloc (MAPo *m, INT4 n); INT4 MapInitCache (MAPoCCH *c, char *fil_nm, unsigned *foff, INT4 new_f); INT4 MapCNew (MAPoCCH *c, UINT4 *fadd); INT4 MapCWrite (MAPoCCH *c, char *s, INT4 n); INT4 MapInCache (MAPoCCH *c, UINT4 fadd, void **ptr); INT4 MapCUpdate (MAPoCCH *c, UINT4 fadd, char *fip); INT4 MapCloseCache (MAPoCCH *c); INT4 MapDuplicateOverlap (MAPoCCH *cache, UINT4 fip, void *buff, INT4 size); char message_srs_ID[] = "$Id: message.c,v 1.2 1996/05/08 00:19:38 etzold Exp $"; /* ** ** $RCSfile: message.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/05/08 00:19:38 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** default opens "SYS$ERROR" as output file which ** receives the ** error or informational messages; output can be directed to a ** file with "MsgSetOut" at the begin of the program; ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #ifndef VMS # include #endif #include "msg.h" #include "futil.h" #include "sm.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** global or module wide variables */ static int (*PrintMessage)(MSGo *) = NULL; /* pointer to print function */ static MSGo msg; /* message object - input to user specified function */ static FILEo* msgFile=NULL; /***** MsgPrintMessage ******************************************************** ** ** default function for message printing; ** ** INPUT: message object [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 MsgPrintMessage (MSGo *msg) { if (msg->msg_t != MSGxINFO) fprintf (stderr, "%s, %s\n", msg->msg_nm, msg->primsg); if (*(msg->secmsg)) fprintf (stderr, "%s", msg->secmsg); return 1; } /****** MsgInit *************************************************************** ** ** opens the message file and the output file; ** ** INPUT: ** IMPLICIT: ** msgFile (FILEo *) [W] ** ** RETURNS: 1 if success */ INT4 MsgInit () { int rv; /* ** open message file */ msgFile = FileNew (MSGxFILE); FileSetMaxLine (msgFile, 200); /* FileSetUnixIo (msgFile);*/ if (!FileOpen (msgFile)) { fprintf (stderr, "\"%s\" could not be opened\n", FileGetName (msgFile, "path")); exit(-1); } if (PrintMessage == NULL) PrintMessage = MsgPrintMessage; return 1; } /**api* MsgAnalCode ********************************************************** ** ** analyzes a message code: calculates the file pointer and finds out ** the message type ** ** INPUT: message object [W] ** message code [R] ** address of file pointer [W] ** IMPLICIT: ** ** RETURNS: 1 if a real message code ** 0 if not */ INT4 MsgAnalCode (MSGo *msg, int msg_code, unsigned int *fip) { int msg_t; if (msg_code > MSGxMAX || msg_code < MSGxMIN || msg_code == e__error) return 0; /* ** msg_code = fip + msg_t * -MSGxMAX */ msg_t = msg_code / MSGxMAX; *fip = -msg_code + MSGxMAX * msg_t; msg->msg_code = msg_code; msg->msg_t = (enum msg_typ) msg_t; return 1; } /**api* Message *************************************************************** ** ** checks if the number is really error code; ** opens file with error messages, goes to address specified in error code ** forms message object and prints it; ** if more arguments are transmitted and the next line(s) in file begins ** with a non alpha character then the line + arguments are transmitted ** to "printf". ** aborts program if MSGxEXIT ** if MSGxMSG then the line containing the message name is not printed ** note that after that line several output lines may occur - they will ** simply be concatenated to one; ** ** INPUT: o number of arguments following ** o error code ** o MSGxEXIT or MSGxNOEX or MSGxMSG ** o (optional) ** o up to 10 arguments for "printf" ** IMPLICIT: ** msg (MSGo) [W] ** msgFile (FILEo *) [W] ** ** RETURNS: 1 if success ** 0 if number is not a message code */ INT4 Message (INT4 arg_n, INT4 msg_code, INT4 opt, ...) { static int first_f=TRUE; va_list ap; unsigned int fip; int rv; char secmsg[MSGxXLN * MSGxXNLN+1], *tmp; /* ** open message file + output file */ if (first_f) { MsgInit (); first_f = FALSE; } /* ** convert message number into a file pointer and set file pointer in message ** file to this address; */ if (!MsgAnalCode (&msg, msg_code, &fip)) return 0; FileSeek (msgFile, fip); /* ** first line contains message name and primary message - extract those; ** all following lines that do not start with either of "fewi" are copied ** into one string - the secondary message; */ sscanf (FileReadLn (msgFile), "%[^,] , %[^\n]", msg.msg_nm, msg.primsg); SmEdit (msg.primsg, SMxTRIM); /* cut of trailing white space */ if (arg_n > 3) { secmsg[0] = '\0'; while (tmp = FileReadLn (msgFile)) { if (strchr ("fewi", tmp[0]) != NULL) break; SmEdit (tmp, SMxTRIM2 | SMxDECODE); strcat (secmsg, tmp); } /* ** secondary message is a format specification for printf - make final ** message line - argument list is the one given to "Message" */ va_start (ap, opt); vsprintf (msg.secmsg, secmsg, ap); va_end (ap); } else msg.secmsg[0] = '\0'; /* ** print message and exit program if requested; */ (*PrintMessage) (&msg); if (opt == MSGxEXIT) exit (256); return 1; } /**API* MsgSetFnct ************************************************************ ** ** Replaces the default function for printing error and information ** messages. ** ** INPUT: address of function [R] ** IMPLICIT: ** fnct_f (int) ** outfnct (int) [W] ** ** RETURNS: */ void MsgSetFnct (INT4 (*fnct)()) { PrintMessage = fnct; } #define e__msgfail -3000114 #define e__allocfail -3000167 #define e__freefail -3000256 #define e__settoobig -3000334 #define e__readerr -3000377 #define e__novalop -3000417 #define e__novaltyp -3000474 #define e__nosetfree -3000571 #define e__userabort -3000603 #define e__filnotopen -3000640 #define e__filnotok -3000695 #define e__filopenerr -3000750 #define e__eof -3000807 #define e__ltoolong -3000839 #define e__invnodenum -3000891 #define e__missnode -3000956 #define e__toomansym -3001019 #define e__eot -3001084 #define e__parsefail -3001154 #define e__bldparsefail -3001221 #define e__strprsfail -3001324 #define e__lnotsaved -3001390 #define e__novalpnam -3001444 #define e__novalsnam -3001528 #define e__invalnum -3001612 #define e__procfail -3001702 #define e__symnotuniq -3001764 #define e__toomanstrct -3002222 #define e__startismiss -3002358 #define e__isnotss -3002413 #define e__novalid -3002530 #define e__missingchar -3002637 #define e__unknownnterm -3002725 #define e__charnotknown -3002797 #define e__symnotknown -3002905 #define e__novalsyminfo -3002992 #define e__novalarg -3003085 #define e__novalcommand -3003172 #define e__bnfbuildfail -3003254 #define e__wrongpartyp -3003346 #define e__novalptyp -3003439 #define e__novalopt -3003532 #define e__misscolon -3003597 #define e__nammismatch -3003655 #define e__namnotuniq -3003720 #define e__novalauthor -3003781 #define i__slbreportbeg -1003870 #define i__slbreportend -1004173 #define i__inxreport -1004299 #define i__processing -1004392 #define e__eom -3004448 #define i__inxcmprss -1004543 #define e__nofieldend -3004637 #define e__wrongfieldcnt -3004696 #define e__strtoolong -3004809 #define e__linenotexst -3004879 #define e__invalstr -3004941 #define e__invalnumber -3005013 #define e__invalifn -3005088 #define e__invalofn -3005170 #define e__activesubmenu -3005253 #define e__allwinused -3005347 #define e__exceedsize -3005387 #define e__eob -3005478 #define e__novalfield -3005512 #define e__novalnam -3005562 #define e__unexpectnum -3005689 #define e__noinit -3005767 #define e__strnotfou -3005814 #define e__strnotfound -3005877 #define e__novalstr -3005933 #define e__novalfadd -3005985 #define e__novalnum -3006051 #define e__libnotinx -3006133 #define i__wrotefile -1006212 #define i__wrotefiles -1006256 #define e__novalpos -3006315 #define e__novalseqlen -3006382 #define e__seqfrg -3006475 #define e__seekfail -3006533 #define e__crmpscfail -3006588 #define e__maxlinksexceed -3006675 #define e__unknownnam -3006759 #define e__novallink -3006812 #define e__toofew -3006875 #define e__namreserved -3006949 #define i__sdlreport -1007018 #define e__nopath -3007426 #define e__ambigouslink -3007488 #define e__badarglist -3007662 #define e__namnotdef -3007719 #define e__invaloutdir -3007781 #define i__wroteseq -1007849 #define i__wroteseqsfile -1007896 #define e__complement -3007966 #define e__novalreference -3008068 #define i__lnkreport -1008176 #define e__exceedquota -3008252 #define e__rtlfail -3008298 #define e__novalsettyp -3008364 #define e__collidsfail -3008449 #define e__inheritfail -3008537 #define e__objnotfound -3008614 #define e__objnotnhrt -3008705 #define e__missdefattr -3008825 #define e__symappendfail -3009013 #define e__exceedarr -3009096 #define e__novalterm -3009159 #define i__mappedset -1009242 #define i__loadlinkset -1009308 #define e__novalseqform -3009364 #define i__wroteseqlen -1009430 #define e__novalpar -3009584 #define e__toomanpar -3009674 #define i__procsubset -1009770 #define e__sicinvalgroups -3009854 #define e__unknowncommand -3009956 #define i__readingname -1010012 #define e__interrupt -3010075 #define i__wroteset -1010107 #define e__sftop -3010173 #define e__libnotlinked -3010252 #define e__filnotfound -3010309 #define e__filcloseerr -3010388 #define e__filwriteerr -3010442 #define i__noentriesfound -1010542 #define e__nonounix -3010578 #define i__listtolib -1010659 #define e__eostack -3010755 #define f__limitexceeded -4010780 #define e__nontermexpect -3010855 #define e__novalformat -3010902 #define e__parnottype -3010961 #define e__foundoneof -3011060 #define e__unknownoption -3011134 #define e__parisdefined -3011207 #define e__parnotdefined -3011277 #define e__notwriteopen -3011339 #define e__indexisbusy -3011417 #define e__doesnotexistfunction -3011489 #define e__overflowstack -3011562 #define f__failedtomovelist -4011636 #define e__couldnotgetsequence -3011703 #define e__nothingtoevaluate -3011790 #define e__failureinslbgetx -3011832 #define e__joinillegalpar -3011916 #define e__entryparsefail -3011981 #define e__illegalposition -3012042 #define e__illegalvalueonstack -3012126 #define e__illegalvaluesonstack -3012244 #define e__illegaldirectioninrange -3012373 #define e__operatorbeforenotallowed -3012457 #define e__operatorafternotallowed -3012514 #define e__postoohigh -3012569 #define i__entry -1012640 #define e__objectunknown -3012685 #define e__noseqinlist -3012755 #define e__noresult -3012797 #define e__illegalrangemod -3012836 #define e__illegalmodparam -3012900 #define e__illegalqueryparam -3012967 #define e__noparamlist -3013029 #define e__negativelength -3013077 #define e__incorrectlength -3013146 #define e__fnctnotdefined -3013217 #define e__btreenotprep -3013357 #define i__writeindex -1013451 #define e__invalidid -3013531 #define e__hasnotfixedrecord -3013614 #define e__fieldnotindex -3013697 #define e__iscompressed -3013763 #define e__notcompressed -3013826 #define i__processingentry -1013902 #define i__wrotebtree -1013945 #define i__wroteidfile -1014082 #define e__inxnotcompress -3014203 #define e__listnotfilled -3014267 #define e__buffexceeded -3014358 #define i__openedidpatch -1014430 #define e__dupllibid -3014523 #define e__novallibid -3014628 #define e__libidexst -3014729 #define e__libidnotknown -3014832 #define e__settoosmall -3014924 #define i__builtlink -1015034 #define i__checkinglib -1015224 #define e__novalentryidlen -3015279 #define e__indexnotuptodate -3015387 #define e__indexwrongversion -3015494 #define e__regerror -3015595 #define i__mustbuildinx -1015630 #define i__mustbuildlink -1015704 #define i__diffentrynum -1015783 #define e__labelnotfound -3015860 #define i__givinguplib -1015956 #define e__strnotinset -3016027 #define e__numnotinset -3016130 #define e__realnotinset -3016233 #define e__functionnotinset -3016333 #define e__charnotallowed -3016438 #define e__realnotinrange -3016542 #define e__checkerr -3016650 #define e__setopneedsidtype -3016708 #define e__nolinklibselected -3016808 #define i__querynegative -1016900 #define e__novalvar -3016959 #define e__novalvar2 -3017031 #define e__novalvar3 -3017104 #define e__formatnomatch -3017177 #define e__relbegandend -3017280 #define e__invalidshift -3017369 #define e__shiftseqisfrag -3017456 #define e__seqwithneglen -3017522 #define e__badfile -3017604 #define i__indexnotexist -1017653 #define i__indexnotcompleted -1017737 #define i__indexnotuptodate -1017832 #define i__indexnotcompressed -1017924 #define e__rangewithundefval -3018019 #define e__argwrongnum -3018106 #define e__argwrongtype -3018204 #define e__argsendnull -3018310 #define e__fatal -3018382 #define e__unknownarg -3018404 #define e__nocurrentcommand -3018477 #define e__onlyoneunnamed -3018563 #define e__varwrongclass -3018780 #define e__varisreadonly -3018901 #define e__seqillegallength -3019070 #define e__novalchar -3019168 #define e__missingarg -3019235 #define e__nosetorlib -3019319 #define e__functionnotexist -3019377 #define e__emptyquerystring -3019441 #define e__illegalbaseconv -3019481 #define e__dbnotlegal -3019589 #define e__noviewselect -3019711 #define e__querynotfound -3019796 #define e__dbhasnotfield -3019868 #define e__icastackempty -3019962 #define e__icaunknownattr -3020024 #define e__icavartype -3020111 #define e__icaenumval -3020205 #define e__icarequiredattr -3020274 #define e__icaattrval -3020360 #define e__templNoCurrTemplate -3020413 #define e__unknownformat -3020473 #define e__templEndOfHistory -3020559 #define i__invalidentry -1020644 #define e__setnotuniqname -3020713 #define e__icainvalidselect -3020782 #define e__icainvallistassign -3020906 #define e__icaopTask -3021051 #define e__icaopEdit -3021130 #define e__icaopAssign -3021227 #define e__icaopRestrictLen -3021323 #define e__icaopMove -3021417 #define e__icabnfGetProd -3021490 #define e__icabnfExpression -3021574 #define e__icabnfProgram -3021661 #define e__icabnfLinkBnfNet -3021732 #define e__icabnfParser -3021809 #define e__icarusFatal -3021879 #define e__toklistFind -3021932 #define e__toklistReplace -3021992 #define e__toklistIsUniq -3022056 #define e__parsererror1 -3022119 #define e__parsererror2 -3022197 #define e__parsererror3 -3022274 #define e__wwwnomatchingview -3022363 #define e__nolibslct -3022530 #define e__wwwNoQueryOrEntriesSelected -3022572 #define e__wwwNoQuerySpecified -3022656 #define e__toktablenotwritable -3022721 #define i__bldReadLink -1022796 #define e__bldNoReadLinks -3022867 #define f__noVarScope -4022934 int headTable[]={0,1,2,2,3,3,3,3}; int tailTable[]={0,0,1,0,3,2,1,0}; char* MIFromULong(ULONG x, int* len) { static char buf[16]; int l=1; char* pos=buf; ULONG r; /* get the first byte */ *pos++=x&0x3F; x>>=6; /* unsigned! */ while (x) { *pos++=(char)x; x>>=8; l++; } ASSERT(l<8,IntTooLong); /* get log2 lenght */ buf[0] |= headTable[l-1]<<6; r=tailTable[l-1]; /* add filling bytes */ while (r--) { *pos++=(char)x; l++; } *len=l; return buf; } ULONG MIToULong(char* buf) { ULONG n; int shift=6; /* get lenght */ int l=1<<((*buf>>6)&0x3); n=(*buf++)&0x3F; while (--l) { n|=(*buf++)<>6)&0x3); } char* MIFromLong(long x, int* len) { /* make an unsigned out of the signed, rotating right 1 */ ULONG encoded; if (x>=0) encoded=(ULONG)x<<1; else encoded=(((ULONG)-x)<<1)+1; return MIFromULong(encoded, len); } long MIToLong(char* buf) { ULONG encoded=MIToULong(buf); if (encoded&0x1) return -(encoded>>1); else return encoded>>1; } /************************************************************************** ** FLOATING-POINT CODEC */ #include typedef struct { int lMant; int lExp; } FloatFormat; FloatFormat floatFormats[]= { {1,0}, /* small int */ {1,1}, {2,1}, {3,1}, {3,2}, {7,2}, {15,2}, {7,3}, {15,3} }; #define WORD_BITS 32 void MIFromMantissa(double m, char** buf) { char* p=*buf; double mInt; WORD chunk; int bit=0; /* convert first, encoded with sign(msb:0=-,1=+) */ if (m>0) { m=modf(ldexp(m,WORD_BITS),&mInt); chunk=(WORD)mInt; } else { m=modf(ldexp(-m,WORD_BITS),&mInt); chunk=((WORD)mInt)^(1<=0; bit-=8) { *p++=(chunk>>bit)&0xFF; } while (m!=0) { m=modf(ldexp(m,WORD_BITS),&mInt); chunk=(WORD)mInt; /* convert chunk */ for (bit=WORD_BITS-8; bit>=0; bit-=8) { *p++=(chunk>>bit)&0xFF; } }; /* go back to last non-zero byte to find real lenght */ p--; while (!*p) p--; p++; *buf=p; } double MIToMantissa(char* p, int len) { double m=0; int exp; WORD chunk=0; int bit,sign; /* first chunk encodes sign */ for (bit=0; bit=-16 && mInt<16)) { /* small int, encode in 1 byte */ char c=((int)mInt)&0x1F; *p++=c; } else { char mant[20], *m=mant; int l; ULONG coded; d=frexp(d,&exp); /* code exponent */ if (exp>=0) coded=exp<<1; else coded=(-exp<<1)|0x1; *p++=coded&0x1F; coded>>=5; if (coded) {*p++=coded; coded>>=8;} if (coded) {*p++=coded; } ASSERT(!(coded>>8), ExpOutOfRange); /* code mantissa */ MIFromMantissa(d, &m); /* find and set format */ lMant=m-mant; lExp=p-buf; f=floatFormats+1; while (lMant>f->lMant || lExp>f->lExp) { f++; ASSERT(flExp-lExp; while (lExp--) *p++=0; /* copy mantissa */ m=mant; l=lMant; while (l--) *p++=*m++; /* adjust mant. lenght */ lMant=f->lMant-lMant; while (lMant--) *p++=0; } *len=(p-buf); return buf; } double MIToDouble(char* buf) { char* p=buf; int format; format=(*p>>5)&0x7; if (format==0) { /* small int */ int coded=*p&0x1F; /* extend sign */ if (coded&0x10) coded |= ~0x1F; return coded; } else { int exp; FloatFormat* f; ULONG coded; int lExp; double d; f=floatFormats+(*p>>5); /* get exponent */ coded=(*p++)&0x1F;lExp=f->lExp-1; if (lExp--) { coded|=(*p++)<<5; if (lExp--) coded|=(*p++)<<13; } if (coded&0x1) exp=-(coded>>1); else exp=coded>>1; /* get mantissa */ d=MIToMantissa(p, f->lMant); return ldexp(d, exp); } } int MIToDoubleSize(char head) { FloatFormat* format=floatFormats+((head>>5)&0x7); return format->lMant+format->lExp; } #define _MI_H /****************************************************** ** MACHINE-INDEPENDENT CODING/DECODING of numbers ******************************************************/ /* int codec */ char* MIFromULong(unsigned long x, int* len); char* MIFromLong(long x, int* len); unsigned long MIToULong(char* buf); long MIToLong(char* buf); int MIToLongSize(char head); /* floating-point codec */ char* MIFromDouble(double d, int* len); double MIToDouble(char* buf); int MIToDoubleSize(char head); #endif *************************************** ** ** $RCSfile: msg.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/05/08 00:19:39 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define MSGxFILE "SRSDAT:message.dat" #define MSGxHHDR "msg.h" #define MSGxHDR "message.h" #define MSGxSCM "MESSAGE BUFFER" #define MSGxXNLN 5 #define MSGxXLN 132 #define MSGxXARG 10 enum msg_typ {MSGxINFO=1, MSGxWARNING, MSGxERROR, MSGxFATAL}; #define MSGxMAX -1000000 * (INT4) MSGxINFO #define MSGxMIN -1000000 * (INT4) MSGxFATAL - 100000 #define MSGxMSG 0 #define MSGxEXIT 1 #define MSGxNOEX 2 #define e__error -3000001 #include "def.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description of a message. */ typedef struct MSGo { INT4 msg_code; /* message code number */ char msg_nm[30]; /* (API) message code name */ char primsg[MSGxXLN+1]; /* (API) primary message */ char secmsg[MSGxXLN*MSGxXNLN+1]; /* (API) secondary message - additional lines that may contain arguments */ enum msg_typ msg_t; /* (API) message type: one of MSGxINFO, MSGxWARNING, MSGxERROR, MSGxFATAL */ } MSGo; #ifdef LONG_ERROR_MSG # define __ERRMSG fprintf (stderr, "File: %s, Line: %d\n", __FILE__,__LINE__); #else # define __ERRMSG #endif #define _ErrorExit() exit(-1) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macro checks if number of arguments is correct */ #define _CheckArgN(arg_n, min, max, errmsg) \ if (((arg_n) > (max)) || ((arg_n) < (min))) return (errmsg) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** checks some return value if it is message code, prints message ** and aborts program brutally;...does it no longer! behaves like ** _ErrExit now; */ #define _ErrStop(rv)\ do {if ((((INT4) rv) < MSGxMAX) && (((INT4) rv > MSGxMIN))) { __ERRMSG \ Message (3, ((INT4) rv), MSGxEXIT); }} while (0) #define _ErrStop2(rv, p2)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (4, ((INT4) rv), MSGxEXIT, p2);}} while (0) #define _ErrStop3(rv, p2, p3)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (5, ((INT4) rv), MSGxEXIT, p2, p3);}} while (0) #define _ErrStop4(rv, p2, p3, p4)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (6, ((INT4) rv), MSGxEXIT, p2, p3, p4);}} while (0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** checks some return value if it is message code and only prints ** message */ #define _ErrMsg(rv)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (3, ((INT4) rv), MSGxNOEX);}} while (0) #define _ErrMsg2(rv, p2)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (4, ((INT4) rv), MSGxNOEX, p2);}} while (0) #define _ErrMsg3(rv, p2, p3)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (5, ((INT4) rv), MSGxNOEX, p2, p3);}} while (0) #define _ErrMsg4(rv, p2, p3, p4)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (6, ((INT4) rv), MSGxNOEX, p2, p3, p4);}} while (0) #define _ErrMsg5(rv, p2, p3, p4, p5)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (7, ((INT4) rv), MSGxNOEX, (p2), (p3), (p4), (p5));}} while (0) #define _ErrMsg6(rv, p2, p3, p4, p5, p6)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ Message (8, ((INT4) rv), MSGxNOEX, p2, p3, p4, p5, p6);}} while (0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** checks some return value if it is message code, prints message ** and returns message code to calling function */ #define _ErrRet(rv) \ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { \ return (INT4) rv;}} while (0) #define _ErrRet1(rv)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (3, ((INT4) rv), MSGxNOEX)) return (INT4) rv;}} while (0) #define _ErrRet2(rv, p2)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (4, ((INT4) rv), MSGxNOEX, p2)) return (INT4) rv;}} while (0) #define _ErrRet3(rv, p2, p3)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (5, ((INT4) rv), MSGxNOEX, p2, p3)) return (INT4) rv;}} while (0) #define _ErrRet4(rv, p2, p3, p4)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (6, ((INT4) rv), MSGxNOEX, p2, p3, p4)) return (INT4) rv;}} while (0) #define _ErrRet5(rv, p2, p3, p4, p5)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (6, ((INT4) rv), MSGxNOEX, p2, p3, p4, p5)) return (INT4) rv;}} while (0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** checks some return value if it is message code, prints message ** and exits program */ #define _ErrExit(rv)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (3, ((INT4) rv), MSGxNOEX)) exit(-1);}} while (0) #define _ErrExit2(rv, p2)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (4, ((INT4) rv), MSGxNOEX, p2)) exit(-1);}} while (0) #define _ErrExit3(rv, p2, p3)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ {if (Message (5, ((INT4) rv), MSGxNOEX, p2, p3)) exit(-1);}}} while (0) #define _ErrExit4(rv, p2, p3, p4)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (6, ((INT4) rv), MSGxNOEX, p2, p3, p4)) exit(-1);}} while (0) #define _ErrExit5(rv, p2, p3, p4, p5)\ do {if (((INT4) rv) < MSGxMAX && ((INT4) rv > MSGxMIN)) { __ERRMSG \ if (Message (7, ((INT4) rv), MSGxNOEX, p2, p3, p4, p5)) exit(-1);}} while (0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** checks some return value if it is message code */ #define _ErrIf(rv)\ if ( (INT4) rv < MSGxMAX && (INT4) rv > MSGxMIN) #define _ErrIs(rv)\ ( (INT4) rv < MSGxMAX && (INT4) rv > MSGxMIN) #define _ErrSet(errCodePtr, errCode)\ do { \ if (errCodePtr) \ *errCodePtr = (INT4) errCode; \ } while (0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ INT4 Message (INT4 arg_n, INT4 msg_code, INT4 opt, ...); void MsgSetFnct (INT4 (*fnct)()); char msgdef_srs_ID[] = "$Id: msgdef.c,v 1.2 1996/07/09 23:38:09 etzold Exp $"; /* ** ** $RCSfile: msgdef.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/07/09 23:38:09 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port by Lukas Rosenthaler and Reinhard ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: none ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** this program generates the file message.h which defines ** unique values for all error messages in message.dat; ** this value is calculated as the file address (by ftell) ** multipied by -1 minus 1 000 000; (i. e. the error ** value is always smaller than -1 000 000 = MAXERR); ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "msg.h" int main() { FILE *inf, *outf; int fip, errcode; int k; char line[MSGxXLN]; char errnam[MSGxXLN]; char dummy; inf = fopen ("../etc/message.dat", "r"); if (inf == NULL) { printf("\"%s\" could not be opened\n",MSGxFILE); exit(1); } outf = fopen("message.h", "w"); if (outf == NULL) { printf("\"%s\" could not be opened\n",MSGxHDR); exit(1); } fprintf(outf, "#include \"%s\"\n", MSGxHHDR); /* ** read file with messages until line starts with either of "iwef" ** (info, warning, error, fatal), get the fip (file pointer) multiply by ** -1 and add MSGxMAX * message type (enum msg_typ); */ while (1) { do { fip = ftell(inf); fgets(line, MSGxXLN, inf); } while (strchr ("iwef", line[0]) == NULL && !feof(inf)); if (feof(inf)) break; switch (line[0]) { case 'i': errcode = -1 * fip + (MSGxMAX * MSGxINFO); break; case 'w': errcode = -1 * fip + (MSGxMAX * MSGxWARNING); break; case 'e': errcode = -1 * fip + (MSGxMAX * MSGxERROR); break; case 'f': errcode = -1 * fip + (MSGxMAX * MSGxFATAL); break; case 'o': /* obsolete */ errcode = 0; break; default: printf ("messages starting with \"%d__\" have unknown type\n=> %s\n", line[0], line); exit(1); break; } dummy = fgetc(inf); /* for RMS to see that record end is */ ungetc(dummy, inf); /* reached otherwise ftell = bullshit */ for (k = 0; (line[k] != ',') && (k < 80) ; k++) errnam[k] = line[k]; errnam[k] = '\0'; if (k == 80) { printf("error message is in wrong format:\n %s\n", errnam); exit(1); } if (errcode != 0) fprintf(outf, "#define %s %d\n", errnam, errcode); } printf("message.h is created in the current folder\n"); exit (0); } char readsdl_srs_ID[] = "$Id: odd.c,v 1.1 1996/05/06 15:17:00 srs Exp $"; /* ** ** $RCSfile: odd.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:00 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "message.h" #include "futil.h" #include "sm.h" #include "parser.h" #include "arglist.h" #include "par.h" #include "sdl.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _ODD #define _FUNCTION #include "sdl_def.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object wide variables */ PRSoST *gblst_s; main(int argc, char **argv) { SDLo *odd; char infil[FILxXNAM+1], outfil[FILxXNAM+1]; int opt1, opt2; #ifndef BOOTSTRAP void **o_p; int *o_n; #endif /* ** process command line options */ ParSetTable ("global", NULL, "PRIVATE"); ParInit (ODD_parTable); argc = ArgGet (&argList[0], argc, argv); if (argc != 2) { /* process command line options */ ArgUsage (argList); exit (1); } if (ParGetBool ("doInitHeader")) opt1 = SDLxNOHDR, opt2 = SDLxHDR; else if (ParGetBool ("doMetaData")) opt1 = SDLxHDR; else if (ParGetBool ("doSection") && ParGetBool ("doHeader")) opt1 = SDLxPRESEC, opt2 = SDLxHDRSEC; else if (ParGetBool ("doSection")) opt1 = SDLxNOHDR, opt2 = SDLxSECTION; else if (ParGetBool ("doHeader")) opt1 = SDLxNOHDR, opt2 = SDLxHDR2; else if (ParGetBool ("doClassInfo")) opt1 = SDLxNOHDR, opt2 = SDLxHDR2; else exit (0); #ifndef BOOTSTRAP # ifdef VMS SdlGetObjects (&o_n, &o_p, "SDL"); # else SdlGetObjects (&o_n, &o_p, "sdl"); # endif odd = (SDLo *) o_p[O_SDL]; #else odd = (&def[0]); #endif sprintf(infil, "SRSSDL:%s_def.sdl", argv[1]); sprintf(outfil, "SRSSOU:%s_def.h", argv[1]); odd->ifnam = &infil[0]; odd->ofnam = &outfil[0]; SdlProc(odd, opt1); if (opt1 == SDLxHDR) exit(0); odd = (SDLo *) odd->oc[odd->oc_n-1].s; SdlProc(odd, opt2); exit (0); } #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "arglist.h" #include "toklist.h" #include "icarus.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _ODD #define _FUNCTION #include "oddclass.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object wide and global variables */ typedef INT4 (*SDLoFNCTx)(); SDLoFNCTx SDL_fnctx[] = {NULL}; static INT4 PrintMessage (MSGo *msg); struct ICAoSYNTAX *IcaInitSyntax(struct ICAoSYNTAX *syntax); main(int argc, char **argv) { SDLo *odd; ARGoLIST *arglist; FILEo *file; ICAoJOB *job; ICAoSYNTAX *syntax; ParSetTable ("global", NULL, "PRIVATE"); ParInit (ODD_parTable); MsgSetFnct ((FUNC)IcaPrintMessage); argc = ArgGet (&argList[0], argc, argv); if (argc != 3) { /* process command line options */ ArgUsage (argList); exit (1); } syntax = IcaInitSyntax (NULL); /* process class information */ job = IcaCreateJob (syntax); odd = OddInit (def, 1); file = FileNew (argv[1]); if (!FileOpen (file)) _ErrExit2 (e__filnotok, argv[2]); IcaJobSetFile (job, file); IcaGetTokenList (job, "prog"); IcaExecProg (job); /* process objects */ job = IcaCreateJob (syntax); odd = OddInit (odd, 2); file = FileNew (argv[2]); if (!FileOpen (file)) _ErrExit2 (e__filnotok, argv[2]); IcaJobSetFile (job, file); IcaGetTokenList (job, "prog"); job->file = FileDelete (job->file); IcaExecProg (job); OddOut (odd); } #include #include #include "srs.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _ODD #define _FUNCTION #include "oddclass.h" int main(int argc, char **argv) { SETo *set; ENTRYo *entry; IDoENTRY id; INT4 i; SrsEnv (); LibOpen ("srs5"); OddInit (def, 1); IcaInitSyntax (LibObjByName ("syntax", "icarus")); MsgSetFnct ((FUNC)IcaPrintMessage); argc = ArgGet (LibObjByName ("arglist", "getz"), argc, argv); if (ParGetNum ("printLibInfo") && argc == 2) { /* print only info ? */ LibPrintInfo (argv[1]); exit (0); } else if (ParGetNum ("printLibs")) { LibPrintLibs (); exit (0); } if ((set = Query (argv[1], "Q1"))) for (i=1; i <= set->n; i++) { SetGetID (set, i, &id); entry = EntryOpen (&id); if (ParGetBool ("printEntireEntry")) EntryPrint (entry); else EntryPrintFields (entry); EntryClose (&entry); } exit (0); } ** ** $RCSfile: odd.h,v $ ** $Revision: 1.3 $ ** $Date: 1996/07/30 10:48:29 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.x Copyright by Thure Etzold ** */ #define SDLxXSS 7 /* max nr of substrt a strct may have */ #define SDLxXNAM 15 /* maxlen of names in definition file */ #define SDLxXLN 512 /* max line len in definition file */ #define SDLxXHLN 79 /* max line len in header file */ #define SDLxXLOG 2000 /* max nr. of logicals */ #define SDLxXSYM 5000 /* max nr. of symbols per table */ #define SDLxXLSYM 132 /* max size of symbol */ #define SDLxXSYMTBL 100000 /* max size of symbol table */ #define SDLxXLOGTBL 30000 /* max size of table for logicals */ #define SDLxXASSGSTR 132 /* max length of string assignement */ #define SDLxXADDR 20000 /* max length of string assignement */ #define SDLxXOBJCLASS 255 #define SDLxXOBJ 2048 /* max nr. of objects per class */ #define SDLxXFNCT 200 /* max nr. of transm. functions */ #define SDLxNULLFNCT 10000 #define ODDxNULL 4294967295U enum ODDeAct {SDLxNOHDR, SDLxHDR, SDLxHDR2, SDLxSECTION,SDLxPRESEC,SDLxHDRSEC}; #define SDLxRD 1 /* ATTRIBUTE read */ #define SDLxNORD 2 /* ATTRIBUTE not yet read */ #define SDLxREQ 1 /* ATTRIBUTE is required */ #define SDLxNOREQ 0 /* ATTRIBUTE is not required */ #define SDLxDFLT 1 #define SDLxNODFLT 2 #define SDLxPNUM 9 #define SDLxFNCT 11 /* object type */ #define SDLxPFNCT 10 #define SDLxCLONE 20 #define SDLxOVERLAY 18 #define SDLxDEFER 16 #define SDLxBNF 21 #define SDLxVIRTUAL 1 #define SDLxGTYPDEFNAM "GenTypeDef" #define SDLxGTYPNAM "GenType" /* lm bit on: turns bit off + TRUE */ #define _SdlIsStr(x) (x != (x & SDLxLBOFF)) ? (x = x & SDLxLBOFF) : 0 #define _SdlMarkStr(x) x |= SDLxLBON /* turn leftmost bit on */ #define __SdlAddr(addr) { if (odd->section_f) SdlListAddr (addr); } #define _SdlMalloc(n) \ ((odd->section_f) ? SdlMalloc (n) : (void *) malloc (n)) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macros for alignment */ #if defined (VMS) || defined (dos) # define ALI4 1 # define ALI8 1 #else #if defined (osf) || defined (irix64) # define ALI4 4 # define ALI8 8 #else # define ALI4 4 # define ALI8 4 #endif #endif #define _SdlAlignFour(off) (off) = (((off) + (ALI4-1))/ALI4)*ALI4 #define _SdlAlignEight(off) (off) = (((off) + (ALI8-1))/ALI8)*ALI8 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** pointer into the data structure built by ODD */ typedef char *SDLoPTR; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** holds pointers to addresses of both function name and argument list */ typedef struct { char **nam; char **args; char **module; char isDone; } ODDoFNCT_P; typedef struct ODDoCDEFINE { char name[80]; INT4 n; } ODDoCDEFINE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ #ifndef _SDL typedef struct SDLo *dummytointroducestructtagSDLo; #endif #ifndef _ODDoHEAD typedef struct ODDoHEAD *dummytointroducestructtagODDoHEAD; #endif #ifndef _SDLoOBJ typedef struct SDLoOBJ *dummytointroducestructtagSDLoOBJ; #endif #ifndef _SDLoATTR typedef struct SDLoATTR *dummytointroducestructtagSDLoATTR; #endif void *SdlMalloc (int n); int SdlListAddr (SDLoPTR a); int SdlSaveAddr (struct SDLoOBJ *obj, SDLoPTR uobj); int SdlGenericNames (struct SDLoOBJ *obj, int typ, char *typ_nm); int SdlCheckPar (struct SDLoATTR *attr, char *s, int v); struct SDLo *OddInit (struct SDLo *oddBase, INT4 level); struct SDLoOBJ *OddGetClass (char *className); void *OddFinishObj (struct SDLoOBJ *class); void OddWriteClassInfo (struct SDLo *odd); char *OddGetClassName (struct SDLoOBJ *class); void OddSetObjListSize (struct SDLoOBJ *class, char *attrName, Int4 n); char *OddGetAttrDeclName (struct SDLoATTR *attr); char *OddGetClassDeclName (struct SDLoOBJ *class); struct SDLoATTR *OddGetAttribute (struct SDLoOBJ *class, char *name); ** ** $RCSfile: oddclass.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/07/30 10:48:30 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** from ODD file: "srsica:odd.i" ** date of ODD compilation: 29-JUL-1996 14:27 ** */ #define AT_CHILD 6 #define AT_PROTOFNCT 10 #define AT_FNCT 11 #define AT_CLONE 20 #if defined(_SDL) && !defined(_ODDoVAL) #define _ODDoVAL typedef struct ODDoVAL { char *nam; UINT4 val; } ODDoVAL; #endif #if defined(_SDL) && !defined(_ODDoATYP) #define _ODDoATYP typedef struct ODDoATYP { INT4 (*make) (); INT4 (*insert) (); INT4 (*size) (); INT4 (*write) (); INT4 (*declare) (); INT4 (*check) (); INT4 (*gentype) (); unsigned char save_f; char *tnam; } ODDoATYP; #endif #if defined(_SDL) && !defined(_SDLoATTR) #define _SDLoATTR typedef struct SDLoATTR { char *rem; struct SDLoOBJ *class; struct ODDoVAL *val; INT4 val_n; char *nam; char *tnam; char *sw_nm; char *alt_nm; char *dnam; INT4 unnamed; unsigned char typ; unsigned char ptyp[4]; INT4 arrsz; INT4 min; INT4 max; INT4 off; unsigned char req; unsigned char status[2]; unsigned char isrd; INT4 dfltv; char *dflts; float dfltvf; INT4 scnt; struct SDLoOBJ *obj; INT4 hasObjsN; } SDLoATTR; #endif #if defined(_SDL) && !defined(_SDLoOBJ) #define _SDLoOBJ typedef struct SDLoOBJ { char *nam; char *rem; char *tnam; char *pp_nm; char *dnam; unsigned char typ; unsigned char status[2]; INT4 siz; char *s; INT4 ns; char *uobj_coff; INT4 gbl_n; INT4 loc_n; unsigned char nss; unsigned char ss[7]; INT4 np; struct SDLoATTR *p; INT4 gtyp_n; char *gtypdef_nm[7]; char *gtyp_nm[7]; char *orgtyp_nm; } SDLoOBJ; #endif #if defined(_SDL) && !defined(_SDLo) #define _SDLo typedef struct SDLo { char *ifnam; char *ofnam; char *sec_nm; INT4 sec_z; INT4 oc_n; struct SDLoOBJ *oc; INT4 at_n; struct ODDoATYP *at; unsigned char error; unsigned char action; unsigned char pass_n; unsigned char keepst_f; unsigned char section_f; } SDLo; #endif #ifndef _PARo #define _PARo typedef struct PARo { char *intern; /* for internal use for the list manager */ INT4 classId; /* for internal use for the list manager */ char *name; /* name of associated global parameter */ char *str; /* Value of 'string' parameter. */ INT4 num; /* Value of 'number' parameter. */ float real; /* Value of 'real' parameter. */ INT4 (*function) (); /* Value of 'function' parameter. */ void *object; /* Value of 'object' parameter. */ unsigned char isVolatile; unsigned char type; /* Parameter type. */ char *comment; /* Short description of parameter. */ char *helpTopic; /* help topic associated to parameter */ char *key; /* keystroke associated to parameter or value */ struct PARoTYPE *parType; /* Object 'partype' for validating the parameter value. */ struct PARoTYPE *check; /* Object 'partype' for validating the parameter value. */ INT4 isLocked; /* internal use... */ char *set; /* Icarus command to set the current value. */ char *get; /* Icarus command to get the current value. */ } PARo; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Describes further a parameter type by specifying constraints or a function for checking the parameter value. */ #ifndef _PARoTYPE #define _PARoTYPE typedef struct PARoTYPE { char *intern; /* for internal use for the list manager */ INT4 classId; /* for internal use for the list manager */ char *name; /* Name of associated global parameter. */ INT4 (*check) (); /* Function that checks parameter value. */ INT4 max; /* Max value, or max length. */ INT4 min; /* Mmin value, or min length. */ float maxReal; /* Max real value. */ float minReal; /* Min real value. */ char *charSet; /* Permissible set of chars for parameter value string. */ } PARoTYPE; #endif #ifndef _PARoLIST #define _PARoLIST typedef struct PARoLIST { struct PARo *par; /* List of all predefined parameters. */ INT4 parN; /* Number of predefined parameters. */ struct PARoTYPE *parType; /* List of all predefined parameter types. */ INT4 parTypeN; /* Number of predefined parameter types. */ } PARoLIST; #endif #ifndef _arg_t #define _arg_t typedef struct arg_t { char *name; INT4 type; char *parameter; char *comment; INT4 (*check) (); INT4 defaultNum; char *defaultStr; float defaultReal; } arg_t; #endif #ifndef _ARGoLIST #define _ARGoLIST typedef struct ARGoLIST { char *name; char *usage; struct arg_t *arg; INT4 argN; } ARGoLIST; #endif #ifdef _FUNCTION #undef _FUNCTION INT4 OFInheritSize (SDLoOBJ *, SDLoATTR *); #define OFInheritSize_F (INT4(*)()) OFInheritSize INT4 OF4BArrSize (SDLoOBJ *, SDLoATTR *); #define OF4BArrSize_F (INT4(*)()) OF4BArrSize INT4 OF4BSize (SDLoOBJ *, SDLoATTR *); #define OF4BSize_F (INT4(*)()) OF4BSize INT4 OFPtrArrSize (SDLoOBJ *, SDLoATTR *); #define OFPtrArrSize_F (INT4(*)()) OFPtrArrSize INT4 OFPtrSize (SDLoOBJ *, SDLoATTR *); #define OFPtrSize_F (INT4(*)()) OFPtrSize INT4 OFBNFSize (SDLoOBJ *, SDLoATTR *); #define OFBNFSize_F (INT4(*)()) OFBNFSize INT4 OFBArrSize (SDLoOBJ *, SDLoATTR *); #define OFBArrSize_F (INT4(*)()) OFBArrSize INT4 OFMakeDefault (SDLoOBJ *, SDLoATTR *, unsigned int *); #define OFMakeDefault_F (INT4(*)()) OFMakeDefault INT4 OFMakeNoDefault (SDLoOBJ *, SDLoATTR *, unsigned int *); #define OFMakeNoDefault_F (INT4(*)()) OFMakeNoDefault INT4 OFMakeChild (SDLoOBJ *, SDLoATTR *, unsigned int *); #define OFMakeChild_F (INT4(*)()) OFMakeChild INT4 OFMakeChildN (SDLoOBJ *, SDLoATTR *, unsigned int *); #define OFMakeChildN_F (INT4(*)()) OFMakeChildN INT4 OFMakeAllObj (SDLoOBJ *, SDLoATTR *, unsigned int *); #define OFMakeAllObj_F (INT4(*)()) OFMakeAllObj INT4 OFMakeAllObjN (SDLoOBJ *, SDLoATTR *, unsigned int *); #define OFMakeAllObjN_F (INT4(*)()) OFMakeAllObjN INT4 OFDefSimple (FILE *, SDLoATTR *, char *, char *); #define OFDefSimple_F (INT4(*)()) OFDefSimple INT4 OFDefStr (FILE *, SDLoATTR *, char *, char *); #define OFDefStr_F (INT4(*)()) OFDefStr INT4 OFDefFnct (FILE *, SDLoATTR *, char *, char *); #define OFDefFnct_F (INT4(*)()) OFDefFnct INT4 OFDefHeader (FILE *, SDLoATTR *, char *, char *); #define OFDefHeader_F (INT4(*)()) OFDefHeader INT4 OFDefStructPtr (FILE *, SDLoATTR *, char *, char *); #define OFDefStructPtr_F (INT4(*)()) OFDefStructPtr INT4 OFDefGenericTyp (FILE *, SDLoATTR *, char *, char *); #define OFDefGenericTyp_F (INT4(*)()) OFDefGenericTyp INT4 OFDefUser (FILE *, SDLoATTR *, char *, char *); #define OFDefUser_F (INT4(*)()) OFDefUser INT4 OFDefEbnf (FILE *, SDLoATTR *, char *, char *); #define OFDefEbnf_F (INT4(*)()) OFDefEbnf INT4 OFInsertFloat (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertFloat_F (INT4(*)()) OFInsertFloat INT4 OFInsertInt (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertInt_F (INT4(*)()) OFInsertInt INT4 OFInsertUInt (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertUInt_F (INT4(*)()) OFInsertUInt INT4 OFInsertUChar (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertUChar_F (INT4(*)()) OFInsertUChar INT4 OFInsertUser (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertUser_F (INT4(*)()) OFInsertUser INT4 OFInsertStr (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertStr_F (INT4(*)()) OFInsertStr INT4 OFInsertFunction (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertFunction_F (INT4(*)()) OFInsertFunction INT4 OFInsertObject (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertObject_F (INT4(*)()) OFInsertObject INT4 OFInsertHeader (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInsertHeader_F (INT4(*)()) OFInsertHeader INT4 OFInherit (void *, void *, void *, void ***, char *, unsigned int, int); #define OFInherit_F (INT4(*)()) OFInherit INT4 OFGeneric (void *, void *, void *, void ***, char *, unsigned int, int); #define OFGeneric_F (INT4(*)()) OFGeneric INT4 OFWrtInt (SDLoATTR *, char *, void **); #define OFWrtInt_F (INT4(*)()) OFWrtInt INT4 OFWrtUChar (SDLoATTR *, char *, void **); #define OFWrtUChar_F (INT4(*)()) OFWrtUChar INT4 OFWrtUInt (SDLoATTR *, char *, void **); #define OFWrtUInt_F (INT4(*)()) OFWrtUInt INT4 OFWrtFloat (SDLoATTR *, char *, void **); #define OFWrtFloat_F (INT4(*)()) OFWrtFloat INT4 OFWrtStr (SDLoATTR *, char *, void **); #define OFWrtStr_F (INT4(*)()) OFWrtStr INT4 OFWrtName (SDLoATTR *, char *, void **); #define OFWrtName_F (INT4(*)()) OFWrtName INT4 OFWrtNULL (SDLoATTR *, char *, void **); #define OFWrtNULL_F (INT4(*)()) OFWrtNULL INT4 OFWrtAddr (SDLoATTR *, char *, void **); #define OFWrtAddr_F (INT4(*)()) OFWrtAddr INT4 OFWrtEBNF (SDLoATTR *, char *, void **); #define OFWrtEBNF_F (INT4(*)()) OFWrtEBNF INT4 OFCheckNum (SDLoATTR *, int, char *); #define OFCheckNum_F (INT4(*)()) OFCheckNum INT4 OFCheckStr (SDLoATTR *, int, char *); #define OFCheckStr_F (INT4(*)()) OFCheckStr INT4 OFGenSimple (SDLoOBJ *, SDLoATTR *); #define OFGenSimple_F (INT4(*)()) OFGenSimple INT4 OFGenObject (SDLoOBJ *, SDLoATTR *); #define OFGenObject_F (INT4(*)()) OFGenObject typedef INT4 (*SDLoFNCT)(); SDLoFNCT SDL_fnct[] = { OFInheritSize_F, OF4BArrSize_F, OF4BSize_F, OFPtrArrSize_F, OFPtrSize_F, OFBNFSize_F, OFBArrSize_F, OFMakeDefault_F, OFMakeNoDefault_F, OFMakeChild_F, OFMakeChildN_F, OFMakeAllObj_F, OFMakeAllObjN_F, OFDefSimple_F, OFDefStr_F, OFDefFnct_F, OFDefHeader_F, OFDefStructPtr_F, OFDefGenericTyp_F, OFDefUser_F, OFDefEbnf_F, OFInsertFloat_F, OFInsertInt_F, OFInsertUInt_F, OFInsertUChar_F, OFInsertUser_F, OFInsertStr_F, OFInsertFunction_F, OFInsertObject_F, OFInsertHeader_F, OFInherit_F, OFGeneric_F, OFWrtInt_F, OFWrtUChar_F, OFWrtUInt_F, OFWrtFloat_F, OFWrtStr_F, OFWrtName_F, OFWrtNULL_F, OFWrtAddr_F, OFWrtEBNF_F, OFCheckNum_F, OFCheckStr_F, OFGenSimple_F, OFGenObject_F }; #endif #ifdef _INITOBJS ODDoVAL defval[] = { {"y", 1}, {"n", 0}, {"y", 1}, {"n", 0}, {"int", 1}, {"string", 2}, {"strv", 9}, {"object", 3}, {"real", 4}, {"var", 6}, {"list", 16}, {"n", 0}, {"y", 1}, {"int", 1}, {"string", 2}, {"strv", 9}, {"object", 3}, {"real", 4}, {"var", 6}, {"list", 16}, {"init", 2}, {"pre", 4}, {"initpre", 6}, {"post", 8}, {"prepost", 12}, {"direct", 1}, {"interface", 0}, {"yes", 1}, {"no", 0}, {"y", 1}, {"n", 0}, {"int", 2}, {"uint", 3}, {"uchar", 1}, {"string", 4}, {"protofunction", 10}, {"function", 11}, {"child", 6}, {"nr_of_childs", 7}, {"object", 9}, {"clone", 20}, {"defer", 16}, {"inherit", 17}, {"user", 12}, {"float", 0}, {"allobjects", 5}, {"nr_of_objects", 8}, {"generic", 15}, {"generic_typ", 13}, {"generic_obj", 14}, {"overload", 18}, {"store", 19}, {"bnf", 21}, {"num", 9}, {"name", 10}, {"text", 11}, {"constant", 12}, {"y", 1}, {"n", 0}, {"obsolete", 1}, {"system", 2}, {"api", 3}, {"obsolete", 1}, {"system", 2}, {"api", 3} }; ODDoATYP defatyp[] = { {OFMakeDefault, OFInsertFloat, OF4BArrSize, OFWrtFloat, OFDefSimple, OFCheckNum, OFGenSimple, 0, "float"}, {OFMakeDefault, OFInsertUChar, OFBArrSize, OFWrtUChar, OFDefSimple, OFCheckNum, NULL, 0, "unsigned char"}, {OFMakeDefault, OFInsertInt, OF4BArrSize, OFWrtInt, OFDefSimple, OFCheckNum, OFGenSimple, 0, "INT4"}, {OFMakeDefault, OFInsertUInt, OF4BArrSize, OFWrtUInt, OFDefSimple, OFCheckNum, NULL, 0, "UINT4"}, {OFMakeDefault, OFInsertStr, OFPtrArrSize, OFWrtStr, OFDefStr, OFCheckStr, OFGenSimple, 1, "char"}, {OFMakeAllObj, NULL, OFPtrSize, OFWrtAddr, OFDefStructPtr, NULL, NULL, 1, ""}, {OFMakeChild, NULL, OFPtrSize, OFWrtAddr, OFDefStructPtr, NULL, NULL, 1, ""}, {OFMakeChildN, NULL, OF4BSize, OFWrtInt, OFDefSimple, NULL, NULL, 0, "INT4"}, {OFMakeAllObjN, NULL, OF4BSize, OFWrtInt, OFDefSimple, NULL, NULL, 0, "INT4"}, {OFMakeDefault, OFInsertObject, OFPtrArrSize, OFWrtAddr, OFDefStructPtr, NULL, OFGenObject, 1, ""}, {OFMakeNoDefault, OFInsertStr, OFPtrSize, OFWrtName, NULL, OFCheckStr, NULL, 0, ""}, {OFMakeDefault, OFInsertFunction, OFPtrSize, OFWrtName, OFDefFnct, NULL, NULL, 1, ""}, {OFMakeDefault, OFInsertUser, OFPtrArrSize, OFWrtNULL, OFDefUser, NULL, NULL, 1, ""}, {NULL, OFGeneric, NULL, NULL, NULL, NULL, NULL, 0, ""}, {NULL, OFGeneric, NULL, NULL, NULL, NULL, NULL, 0, ""}, {NULL, NULL, OFPtrArrSize, NULL, OFDefGenericTyp, NULL, NULL, 1, ""}, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, ""}, {OFMakeNoDefault, OFInherit, OFInheritSize, NULL, NULL, NULL, NULL, 0, ""}, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, ""}, {OFMakeDefault, OFInsertHeader, OFPtrArrSize, OFWrtNULL, OFDefHeader, NULL, NULL, 1, ""}, {OFMakeDefault, OFInsertObject, OFPtrArrSize, NULL, OFDefStructPtr, NULL, NULL, 1, ""}, {NULL, NULL, OFBNFSize, OFWrtEBNF, OFDefEbnf, NULL, NULL, 0, ""} }; SDLoATTR defpar[] = { {"", NULL, &defval[0], 0, "name", "", "", "", "fnctnam", 0, 10, 11, 11, 11, 11, 1, -1000000000, 30, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[0], 0, "args", "", "", "", "args", 0, 4, 11, 11, 11, 11, 1, -1000000000, 132, 0, 1, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[0], 0, "module", "", "", "", "module", 0, 4, 11, 10, 10, 10, 1, -1000000000, 30, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Name of value.", NULL, &defval[0], 0, "name", "", "", "", "name", 1, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 1, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Number value.", NULL, &defval[0], 0, "n", "", "", "", "n", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 1, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Comment field.", NULL, &defval[0], 0, "rem", "", "", "", "rem", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Name of the argument in an Icarus program.", NULL, &defval[0], 0, "name", "", "", "", "name", 1, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Comment field.", NULL, &defval[0], 0, "rem", "", "", "", "rem", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Defines if parameter may be unnamed.", NULL, &defval[0], 2, "unnamed", "", "", "", "isUnnamed", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Defines if parameter is required.", NULL, &defval[2], 2, "required", "", "", "", "isRequired", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Type of the argument", NULL, &defval[4], 7, "t", "", "", "", "type", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 2, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[11], 0, "class", "", "", "", "className", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Default value of type 'int' arguments.", NULL, &defval[11], 0, "defInt", "", "", "", "defInt", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Default value of type 'string' arguments.", NULL, &defval[11], 0, "defStr", "", "", "", "defaultStr", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[11], 0, "enum", "", "", "", "vals", 0, 6, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 1, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[11], 0, "", "", "", "", "valsN", 0, 7, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 1, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[11], 0, "", "", "", "", "isSet", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[11], 0, "", "struct VARo", "", "", "*val", 0, 12, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, 0}, {"Name of command in Icarus programs.", NULL, &defval[11], 0, "name", "", "", "", "name", 1, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 1, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"C function that implements the command.", NULL, &defval[11], 0, "f", "", "", "", "functionName", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Determines whether the command should appear in the \nIcarus functions reference list.\n", NULL, &defval[11], 2, "show", "", "", "", "isShow", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Comment field.", NULL, &defval[13], 0, "rem", "", "", "", "rem", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Type of value to be returned (if any).", NULL, &defval[13], 7, "return", "", "", "", "returnType", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 2, "", 0.000000, 0, NULL, -1}, {"Execution time of command.", NULL, &defval[20], 5, "time", "", "", "", "time", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 8, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[25], 0, "returnClass", "", "", "", "returnClass", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Call function directly or via C-interface.", NULL, &defval[25], 2, "call", "", "", "", "isDirectCall", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"normal function.", NULL, &defval[27], 0, "methodOf", "", "", "", "methodOf", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "args", "", "", "", "args", 0, 6, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 2, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "", "", "", "", "argsN", 0, 7, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 2, "", 0.000000, 0, NULL, -1}, {"Function to be executed for command.", NULL, &defval[27], 0, "", "INT4", "", "", "(*function)()", 0, 12, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Number of arguments ordered from C function (via 'IargGetArgs').", NULL, &defval[27], 0, "", "", "", "", "orderN", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Number of orders currently allocated.", NULL, &defval[27], 0, "", "", "", "", "orderAllocN", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"Array with a list of argument orders.", NULL, &defval[27], 0, "", "struct IARGoVALUE", "", "", "**order", 0, 12, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "name", "", "", "", "nam", 1, 4, 10, 10, 10, 10, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "val", "", "", "", "val", 0, 3, 9, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "make", "", "", "", "make", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(struct SDLoOBJ *, struct SDLoATTR *, unsigned int *)", 0.000000, 0, NULL, 0}, {"", NULL, &defval[27], 0, "insert", "", "", "", "insert", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(void *, void *, void *, void ***, char *, unsigned int,int)", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "calcsize", "", "", "", "size", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(struct SDLoOBJ *, struct SDLoATTR *)", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "write", "", "", "", "write", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(void)", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "declare", "", "", "", "declare", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(FILE *, struct SDLoATTR *, char *, char *)", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "check", "", "", "", "check", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(struct SDLoATTR *, int, char *)", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 0, "gentype", "", "", "", "gentype", 0, 11, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "(struct SDLoOBJ *, struct SDLoATTR *)", 0.000000, 0, NULL, -1}, {"", NULL, &defval[27], 2, "save_address", "", "", "", "save_f", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "typname", "", "", "", "tnam", 0, 4, 0, 0, 0, 0, 1, -1000000000, 20, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "rem", "", "", "", "rem", 0, 4, 10, 11, 11, 11, 1, 0, 512, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "", "", "", "", "class", 0, 9, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 7, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "enum", "", "", "", "val", 0, 6, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 4, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "", "", "", "", "val_n", 0, 7, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 4, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "name", "", "", "", "nam", 1, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "typname", "", "", "", "tnam", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "switchname", "", "", "", "sw_nm", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "alttypname", "", "", "", "alt_nm", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 0, "declname", "", "", "", "dnam", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[29], 2, "unnamed", "", "", "", "unnamed", 0, 2, 0, 0, 0, 0, 1, 0, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[31], 22, "type", "", "", "", "typ", 0, 1, 10, 10, 10, 10, 1, -1000000000, 1000000000, 0, 1, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[53], 4, "valtype", "", "", "", "ptyp", 0, 1, 10, 10, 10, 10, 4, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[57], 0, "repeat", "", "", "", "arrsz", 0, 2, 9, 12, 12, 12, 1, 1, 10000, 0, 0, 0, 0, 0, 1, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[57], 0, "min", "", "", "", "min", 0, 2, 9, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, -1000000000, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[57], 0, "max", "", "", "", "max", 0, 2, 9, 12, 12, 12, 1, 0, 1000000000, 0, 0, 0, 0, 0, 1000000000, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[57], 0, "", "", "", "", "off", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[57], 2, "required", "", "", "", "req", 0, 1, 10, 10, 10, 10, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[59], 3, "status", "", "", "", "status", 0, 1, 10, 10, 10, 10, 2, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "", "", "", "", "isrd", 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "defaultval", "", "", "", "dfltv", 0, 2, 9, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "defaultstr", "", "", "", "dflts", 0, 4, 10, 12, 11, 11, 1, 0, 132, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "defaultvalf", "", "", "", "dfltvf", 0, 0, 9, 9, 9, 9, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, 0}, {"", NULL, &defval[62], 0, "", "", "", "", "scnt", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "objectclass", "", "", "", "obj", 0, 9, 12, 12, 12, 12, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 7, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "", "", "", "", "hasObjsN", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, -1, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "name", "", "", "", "nam", 1, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "rem", "", "", "", "rem", 0, 4, 10, 11, 11, 11, 1, 0, 512, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "typname", "", "", "", "tnam", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "ppname", "", "", "", "pp_nm", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "declname", "", "", "", "dnam", 0, 4, 10, 11, 11, 11, 1, 0, 25, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 0, "type", "", "", "", "typ", 0, 1, 9, 12, 12, 12, 1, 0, 12, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[62], 3, "status", "", "", "", "status", 0, 1, 10, 10, 10, 10, 2, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "siz", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "s", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "ns", 0, 2, 0, 0, 0, 0, 1, 0, 10000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "uobj_coff", 0, 4, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "gbl_n", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "loc_n", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "nchilds", "", "", "", "nss", 0, 1, 9, 9, 9, 9, 1, -1000000000, 7, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "child", "", "", "", "ss", 0, 1, 12, 12, 12, 12, 7, 0, 255, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "np", 0, 7, 0, 0, 0, 0, 1, 1, 256, 0, 0, 0, 0, 0, 6, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "attrs", "SDLoATTR", "", "", "p", 0, 6, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 6, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "gtyp_n", 0, 2, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "gtypdef_nm", 0, 4, 0, 0, 0, 0, 7, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "gtyp_nm", 0, 4, 0, 0, 0, 0, 7, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "orgtypname", "", "", "", "orgtyp_nm", 0, 4, 11, 10, 10, 10, 1, -1000000000, 40, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "infile", "", "", "", "ifnam", 0, 4, 12, 11, 11, 11, 1, 1, 132, 0, 1, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "outfile", "", "", "", "ofnam", 0, 4, 12, 11, 11, 11, 1, 1, 132, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "section_name", "", "", "", "sec_nm", 0, 4, 10, 11, 11, 11, 1, 0, 50, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "section_size", "", "", "", "sec_z", 0, 2, 9, 9, 9, 9, 1, 1, 100000, 0, 0, 0, 0, 0, 1000, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "oc_n", 0, 8, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 7, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "oc", 0, 5, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 7, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "at_n", 0, 8, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 5, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "at", 0, 5, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 5, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "error", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "action", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "pass_n", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "keepst_f", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1}, {"", NULL, &defval[65], 0, "", "", "", "", "section_f", 0, 1, 0, 0, 0, 0, 1, -1000000000, 1000000000, 0, 0, 0, 0, 0, 0, "", 0.000000, 0, NULL, -1} }; SDLoOBJ defstrct[] = { {"function", "", "", "", "X", 11, 2, 2, 0, "", 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, &defpar[0], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"val", "Value in an enumeration", "ODDoVALUE", "", "ODDValue", 0, 0, 0, 0, "", 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, &defpar[3], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"var", "Argument of Icarus command.", "IARGoVALUE", "", "IARGVALUE", 0, 0, 0, 0, "", 0, "", 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 12, &defpar[6], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"com", "", "IARGoCOM", "", "IARGCOM", 0, 0, 0, 0, "", 0, "", 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 15, &defpar[18], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"value", "", "ODDoVAL", "SDL", "defval", 0, 0, 0, 0, "", 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, &defpar[33], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"attrtype", "", "ODDoATYP", "SDL", "defatyp", 0, 0, 0, 0, "", 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, &defpar[35], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"attribute", "", "SDLoATTR", "SDL", "defpar", 0, 0, 0, 0, "", 0, "", 0, 0, 2, 4, 6, 0, 0, 0, 0, 0, 25, &defpar[44], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"object", "", "SDLoOBJ", "SDL", "defstrct", 0, 0, 0, 0, "", 0, "", 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 21, &defpar[69], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {"def", "", "SDLo", "SDL", "def", 0, 0, 0, 0, "", 0, "", 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 13, &defpar[90], 0, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""} }; SDLo def[] = { {"SRSICA:sdl.sdl", "SRSSOU:odd5.h", "sdl", 50, 9, &defstrct[0], 22, &defatyp[0], 0, 0, 0, 0, 0} }; PARo ODD_par[] = { {NULL, 0, "doInitHeader", "", 0, 0.000000, NULL, NULL, 0, 16, "h-file with struct declaration and initialization", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "doHeader", "", 0, 0.000000, NULL, NULL, 0, 16, "h-file with struct declaration", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "doSection", "", 0, 0.000000, NULL, NULL, 0, 16, "binary section file (can be combined with '-h')", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "doMetaData", "", 0, 0.000000, NULL, NULL, 0, 16, "h-file with meta data initialization", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "doClassInfo", "", 0, 0.000000, NULL, NULL, 0, 16, "file with class information", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "printProgress", "", 0, 0.000000, NULL, NULL, 0, 16, "print a line for each ODD-file read", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "printProgress", "", 0, 0.000000, NULL, NULL, 0, 16, "print a line for each ODD-file read", "", "", NULL, NULL, 0, "", ""}, {NULL, 0, "printDots", "", 0, 0.000000, NULL, NULL, 0, 16, "print a dot for each ODD-file read", "", "", NULL, NULL, 0, "", ""} }; PARoTYPE Odd_parType[] = { {NULL, 0, "boolean", NULL, 3, 0, 0.000000, 0.000000, "yYnN01oOfFjJ"} }; PARoLIST ODD_parTable[] = { {&ODD_par[0], 8, &Odd_parType[0], 1} }; arg_t args[] = { {"-help", 1, "", "this message", NULL, 0, "", 0.000000}, {"-i", 0, "doInitHeader", "", NULL, 0, "", 0.000000}, {"-h", 0, "doHeader", "", NULL, 0, "", 0.000000}, {"-s", 0, "doSection", "", NULL, 0, "", 0.000000}, {"-m", 0, "doMetaData", "", NULL, 0, "", 0.000000}, {"-c", 0, "doClassInfo", "", NULL, 0, "", 0.000000}, {"-r", 0, "printProgress", "", NULL, 0, "", 0.000000}, {"-d", 0, "printDots", "", NULL, 0, "", 0.000000} }; ARGoLIST argList[] = { {"odd", "sectionName", &args[0], 8} }; #endif char oddfncts_srs_ID[] = "$Id: oddfncts.c,v 1.2 1996/06/16 17:59:40 etzold Exp $"; /* ** ** $RCSfile: oddfncts.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/06/16 17:59:40 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "message.h" #include "sm.h" #include "futil.h" #include "sdl.h" #include "strv.h" #define _CONSTANTS #define _SDL #define _ODD #include "sdl_def.h" typedef int (*SDLoFNCT)(); INT4 OddIsAttr (SDLoATTR *attr, char *option); INT4 OddIsClass (SDLoOBJ *class, char *option); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object wide variables */ extern SDLo *odd; extern SDLoFNCT SDL_fnct[]; extern ODDoFNCT_P function[SDLxXFNCT]; extern FILo *f; /****************************************************************************** ****** Group of functions calculating object size ***************************** ******************************************************************************* ** ** INPUT: address of parent object [R] ** address of attribute [R] ** address of offset within structure [W] ** IMPLICIT: ** odd (SDLo *) */ int OFInheritSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { #ifdef nhrt (obj->nhrt)[obj->nhrt_n] = &((odd->oc)[attr->dfltv]); (obj->nhrt_offp)[obj->nhrt_n] = &(attr->off); obj->nhrt_n++; #endif return 0; } int OF4BArrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignFour (*off); return 4 * attr->arrsz; } int OF4BSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignFour (*off); return 4; } int OFPtrArrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignEight (*off); return (sizeof (char *) * attr->arrsz); } int OFPtrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignEight (*off); return sizeof (char *); } int OFBNFSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignEight (*off); return (sizeof (char *) + sizeof (int)); } int OFBArrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { return 1 * attr->arrsz; } /****************************************************************************** ****** group of functions for posprocesssing attributes *********************** ******************************************************************************* ** ** ** INPUT: address of parent object [R] ** address of attribute [R] ** address of header [W] ** address of current offset in target structure [W] ** IMPLICIT: ** odd (SDLo *) [R] ** ** RETURNS: e__parismiss + ** 1 */ int OFMakeDefault (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { int (*insert)(); int l, rv; if (!(attr->isrd)) { if (attr->req) _ErrRet (e__parismiss); else if ((insert = odd->at[attr->typ].insert) != NULL) for (l = 0; l < attr->arrsz; l++) { rv = (*insert) (obj, attr, attr, off, 0, ODDxNULL, TRUE); _ErrRet (rv); } } return 1; } int OFMakeNoDefault (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { if (!(attr->isrd)) _ErrRet (e__parismiss); return 1; } int OFMakeChildN (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { memcpy (*off, &((odd->oc)[attr->dfltv].loc_n), sizeof (int)); return 1; } int OFMakeAllObjN (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { memcpy (*(int **) off, &((odd->oc)[attr->dfltv].gbl_n), sizeof (int)); return 1; } int OFMakeChild (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { SDLoOBJ *referredClass; SDLoPTR tmp; int rv, fst_x, l, i; referredClass = &(odd->oc[attr->dfltv]); fst_x = referredClass->gbl_n - referredClass->loc_n; /* inx of first obj */ attr->dflts = &(referredClass->dnam[0]); attr->tnam = &(referredClass->tnam[0]); if (odd->action != SDLxNOHDR) memcpy (*(int **) off, &fst_x, sizeof (int)); else { SDLoPTR tmp; tmp = referredClass->s + (referredClass->siz * fst_x); memcpy (*off, &tmp, sizeof (SDLoPTR)); } return 1; } int OFMakeAllObj (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { SDLoOBJ *referredClass; referredClass = & (odd->oc[attr->dfltv]); if (odd->action != SDLxNOHDR) memset (*off, 0, sizeof (SDLoPTR)); else memcpy (*off, &(referredClass->s), sizeof (SDLoPTR)); attr->dflts = &(referredClass->dnam[0]); attr->tnam = &(referredClass->tnam[0]); return 1; } /****** OfArraySiz ***********************************************************/ /** ** returns string with array size for declaration of arrays ** if not array string is empty; ** ** INPUT: attribute object [R] ** IMPLICIT: ** ** RETURNS: address of string **/ char *OFArraySiz (SDLoATTR *attr) { static char as[10]; if (attr->arrsz > 1) sprintf(as, "[%d]", attr->arrsz); else as[0] = '\0'; return &as[0]; } /****************************************************************************** ***** group of functions for writing attribute definition to header file ****** ******************************************************************************* ** ** ** INPUT: attribute object [R] ** generic type [R] ** generic object type [R] ** IMPLICIT: ** odd (SDLo *) [R] ** ** RETURNS: ** */ char *OddRemark (SDLoATTR *attr) { static char remark[550]; if (!*attr->rem) remark[0] = '\0'; else sprintf (remark, " /*%s %s */", OddIsAttr (attr, "api") ? "API" : "", attr->rem); return remark; } char *OddAddRemark (char *ln, SDLoATTR *attr) { static char newLn[600]; char remark[550]; char *lastBlankPtr; int l, k, lSave; if (!*attr->rem) return ln; else { sprintf (newLn, "%-40s ", ln); sprintf (remark, "/*%s %s */", OddIsAttr (attr, "api") ? "API" : "", attr->rem); l = 0; while (1) { for (k=strlen (newLn); (k % 80) && remark[l]; k++, l++) { newLn[k] = remark[l]; if (newLn[k] == ' ') { lastBlankPtr = &newLn[k]; lSave = l; } } if (remark[l]) { /* comment string is not yet finished */ *lastBlankPtr = '\0'; sprintf (newLn, "%s\n%43s", newLn, " "); l = lSave; } else { newLn[k] = '\0'; break; } } } return newLn; } int OFDefSimple (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; sprintf(l, " %-24s%s%s;", odd->at[attr->typ].tnam, attr->dnam, OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefStr (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; sprintf (l, " %-24s*%s%s;", "char", attr->dnam, OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefFnct (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; char tnam[80], args[80], tmp[80]; strcpy (args, attr->dflts); if (gtyp_nm != NULL) { /* generic argument type */ if (typdef_nm != NULL) { sprintf (tmp, "struct %s", typdef_nm); SmSwapS (args, SDLxGTYPDEFNAM, tmp); } SmSwapS (args, SDLxGTYPNAM, gtyp_nm); } else SmSwapS (args, SDLxGTYPDEFNAM, "void"); /* generic return val type */ if (strcmp (SDLxGTYPNAM, attr->tnam) == 0 && gtyp_nm != NULL) sprintf (tnam, "%-24s*", gtyp_nm); else strcpy (tnam, "INT4"); sprintf (l, " %-24s(*%s)%s;", tnam, attr->dnam, " ()" /*args*/ ); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefHeader (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; sprintf (l, " %-24s*%s;", attr->tnam, attr->dnam); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefStructPtr (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; char tnam[80]; sprintf (tnam, "struct %s", attr->tnam); sprintf (l, " %-24s*%s%s;", tnam, attr->dnam, OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefGenericTyp (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; if (gtyp_nm == NULL) sprintf (l, " %-24s*%s;", "void", attr->dnam); else sprintf(l, " %-24s*%s;", gtyp_nm, attr->dnam); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefUser (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; int pp_f; pp_f = *(attr->sw_nm) != '\0' ? TRUE : FALSE; if (pp_f) /* if preprocessor switch */ fprintf(fil, "#ifdef %s\n", attr->sw_nm); sprintf (l, " %-24s%s%s;", attr->tnam, attr->dnam, OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); if (pp_f) { fprintf(fil, "#else\n"); fprintf(fil, " %-24s%s%s;%s\n", (*attr->alt_nm == '\0') ? "unsigned int" : attr->alt_nm, attr->dnam, OFArraySiz (attr), OddRemark (attr)); fprintf(fil, "#endif\n"); } return 1; } int OFDefEbnf (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { fprintf(fil, " %-24s%s;\n", "char", "**ebnfln"); fprintf(fil, " %-24s%s;\n", "INT4", "nebnfln"); return 1; } /****************************************************************************** ****** group of functions for inserting attribute values ********************** ******************************************************************************* ** ** ** INPUT: address of parent object [R] ** address of attribute [R] ** address of header [W] ** address of current offset in target structure [W] ** IMPLICIT: ** odd (SDLo *) [R] ** f (FILo *) [R] ** ** RETURNS: e__parismiss + ** e__parnotok + ** e__allocfail + ** e__objnotfound + ** 1 */ int OFInsertFloat (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, float **dest, char *tokstr, unsigned int tokval, int dflt_f) { float value; if (dflt_f) value = dfltattr->dfltvf; else sscanf (tokstr, "%f", &value); _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (float)); *dest += 1; return 1; } int OFInsertInt (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, int **dest, char *tokstr, unsigned int tokval, int dflt_f) { int value; if (tokval == ODDxNULL) value = dflt_f ? dfltattr->dfltv : atoi(tokstr); else value = tokval; _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (int)); *dest += 1; return 1; } int OFInsertUInt (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { unsigned int value; if (tokval == ODDxNULL) value = dflt_f ? dfltattr->dfltv : atoi(tokstr); else value = tokval; _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (unsigned int)); *dest += 1; return 1; } int OFInsertUChar (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned char **dest, char *tokstr, unsigned int tokval, int dflt_f) { unsigned char value; if (tokval == ODDxNULL) value = dflt_f ? dfltattr->dfltv : atoi(tokstr); else value = tokval; _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (char)); *dest += 1; return 1; } int OFInsertUser (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, void ***dest, char *tokstr, unsigned int tokval, int dflt_f) { memset (*dest, 0, sizeof (char *)); *dest += 1; return 1; } int OFInsertStr (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, char ***dest, char *tokstr, unsigned int tokval, int dflt_f) { char *newvalue, *value = NULL; int rv; /* if (tokval == ODDxNULL) ...does this ever happen? */ value = dflt_f ? &((dfltattr->dflts)[0]) : tokstr; /* else value += _SdlIsStr (tokval); */ rv = SdlCheckPar (attr, value, 0); _ErrRet (rv); /* insert into user-object */ if ((newvalue = (char *) _SdlMalloc (strlen (value) + 1)) == 0) _ErrRet2(e__allocfail, "symbol string"); memcpy (*dest, &newvalue, sizeof (char *)); if (attr->typ == AT_PROTOFNCT) /* copy function to array */ OddAddFunction (*dest); *dest = *dest + 1; strcpy (newvalue, value); if (odd->action == SDLxNOHDR) SmEdit (newvalue, SMxDECODE); return 1; } int OFInsertFunction (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { unsigned int value; SDLoPTR tmp=NULL; value = dflt_f ? SDLxNULLFNCT : tokval; if (odd->action == SDLxNOHDR) { if (odd->section_f) { /* function index */ tmp += dflt_f ? SDLxXFNCT : value; memcpy (*dest, &tmp, sizeof (SDLoPTR)); } else { /* function address */ tmp = dflt_f ? NULL : (SDLoPTR) SDL_fnct[value]; memcpy (*dest, &tmp, sizeof (SDLoPTR)); } } else { /* function name */ tmp = dflt_f ? "NULL" : *(function[value].nam); memcpy (*(char ***) dest, &tmp, sizeof (SDLoPTR));} if (!dflt_f) attr->dflts = *(function[value].args); *dest += 1; return 1; } int OFInsertObject (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, void ***dest, char *tokstr, unsigned int tokval, int dflt_f) { SDLoOBJ *refClass; SDLoPTR obj_p; int rv; refClass = &(odd->oc[attr->dfltv]); /*tokval = atoi (tokstr);*/ if (!dflt_f) { if (attr->typ == AT_CLONE) { if ((obj_p = (SDLoPTR) _SdlMalloc (refClass->siz)) == 0) _ErrRet2(e__allocfail, "object clone"); memcpy (obj_p, (void *) (refClass->s + refClass->siz * tokval), refClass->siz); } else obj_p = (void *) (refClass->s + refClass->siz * tokval); } else obj_p = NULL; /* ** copy object address into output object */ if (odd->action == SDLxNOHDR) memcpy (*dest, &obj_p, sizeof (SDLoPTR)); else memcpy (*dest, &tokval, sizeof (SDLoPTR)); (*dest)++; attr->dflts = &(refClass->dnam[0]); /* declaration name */ /* ** give attribute a type definition name */ if (refClass->gtyp_n == 0 || tokval == SDLxXOBJ) attr->tnam = refClass->tnam; else if (tokval != ODDxNULL) attr->tnam = (refClass->gtypdef_nm)[tokval]; return 1; } int OFInsertHeader (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { #ifdef org ODDoHEAD *head; if (!dflt_f) { if ((head = (ODDoHEAD *) _SdlMalloc (sizeof (ODDoHEAD))) == 0) _ErrRet2(e__allocfail, "object clone"); memcpy (head, &ODD_headers[tokval], sizeof (ODDoHEAD)); } else head = NULL; memcpy (*dest, &head, sizeof (int *)); *dest += 1; #endif return 1; } int OFInherit (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { SDLoOBJ *inherit_obj; void *obj_p; inherit_obj = &(odd->oc[attr->dfltv]); if (tokval >= inherit_obj->gbl_n) _ErrRet4 (e__objnotfound, f->n, f->nam, tokstr); obj_p = (void *) (inherit_obj->s + tokval * inherit_obj->siz); memcpy (*dest, obj_p, inherit_obj->siz); if (odd->section_f) SdlSaveAddr (inherit_obj, (SDLoPTR) *dest); return 1; } int OFGeneric (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, void ***dest, char *tokstr, unsigned int tokval, int dflt_f) { _ErrRet (SdlGenericNames (&(odd->oc[O_HEAD]), attr->typ, tokstr)); return 1; } /****************************************************************************** ******** group of functions for writing attribute value to header file ******** ******************************************************************************* ** ** ** INPUT: attribute object [R] ** destination string [W] ** address of source [W] ** IMPLICIT: ** ** RETURNS: ** */ int OFWrtInt (SDLoATTR *attr, char *s, int **source) { sprintf (s, "%d", **source); (*source)++; return 1; } int OFWrtUChar (SDLoATTR *attr, char *s, unsigned char **source) { sprintf (s, "%d", **source); (*source)++; return 1; } int OFWrtUInt (SDLoATTR *attr, char *s, unsigned int **source) { sprintf (s, "%u", **source); (*source)++; return 1; } int OFWrtFloat (SDLoATTR *attr, char *s, float **source) { sprintf (s, "%f", **source); (*source)++; return 1; } int OFWrtStr (SDLoATTR *attr, char *s, char ***source) { static STRv str; if (!str) str = StrNew (); StrSetS (str, **source); StrEncode (str); sprintf (s, "\"%s\"", _Str (str)); (*source)++; return 1; } int OFWrtName (SDLoATTR *attr, char *s, char ***source) { sprintf (s, "%s", **source); (*source)++; return 1; } int OFWrtNULL (SDLoATTR *attr, char *s, void ***source) { sprintf (s, "NULL"); (*source)++; return 1; } int OFWrtAddr (SDLoATTR *attr, char *s, unsigned int **source) { if (**source == ODDxNULL) sprintf(s, "NULL"); else sprintf(s, "&%s[%d]", attr->dflts, **source); (*source)++; return 1; } int OFWrtEBNF (SDLoATTR *attr, char *s, char ***source) { sprintf(s, "&%s[0], %d", **source, ** (int **) (source+sizeof (char *))); (*source) += 8; return 1; } /****************************************************************************** ******* group of functions for checking attribute values ********************** ******************************************************************************* ** ** ** INPUT: ** address of attribute [R] ** address of value ** IMPLICIT: ** f (FILo *) [R] ** ** RETURNS: ** e__parnotok + ** 1 */ int OFCheckNum (SDLoATTR *attr, int v, char *s) { char errmsg[MSGxXLN]; if (v > attr->max) sprintf(errmsg, "Attribute: %s, value: %d, max: %d", attr->nam, v, attr->max); else if (v < attr->min) sprintf(errmsg, "Attribute: %s, value: %d, min: %d", attr->nam, v, attr->min); else return 1; _ErrRet4 (e__parnotok, f->n, f->nam, errmsg); return 1; } int OFCheckStr (SDLoATTR *attr, int v, char *s) { char errmsg[MSGxXLN]; int len; len = strlen (s); if (len > attr->max) sprintf (errmsg, "Attribute: %s, string: %s, maxlen: %d", attr->nam, s, attr->max); else if (len < attr->min) sprintf (errmsg, "Attribute: %s, string: %s, minlen: %d", attr->nam, s, attr->min); else return 1; _ErrRet4 (e__parnotok, f->n, f->nam, errmsg); return 1; } /****************************************************************************** ******* group of functions for generating generic types ******************** ******************************************************************************* ** ** ** INPUT: ** address of attribute [R] ** address of value ** IMPLICIT: ** odd (SDLo *) [R] ** ** RETURNS: ** e__parnotok + ** 1 */ int OFGenSimple (SDLoOBJ * headobj, SDLoATTR *attr) { SdlGenericNames (headobj, AT_GENERIC_TYP, odd->at[attr->typ].tnam); return 1; } int OFGenObject (SDLoOBJ * headobj, SDLoATTR *attr) { SDLoOBJ *ref_obj; char gtyp_nm[SDLxXLSYM+1]; ref_obj = &(odd->oc[attr->dfltv]); sprintf (gtyp_nm, "struct %s *", ref_obj->tnam); SdlGenericNames (headobj, AT_GENERIC_TYP, gtyp_nm); return 1; } char oddfncts_ID[] = "$Id: oddfnctsnew.c,v 1.3 1996/07/30 10:48:30 etzold Exp $"; /* ** ** $RCSfile: oddfnctsnew.c,v $ ** $Revision: 1.3 $ ** $Date: 1996/07/30 10:48:30 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "message.h" #include "sm.h" #include "futil.h" #include "strv.h" #include "odd.h" #define _SDL #define _ODD #include "oddclass.h" typedef int (*SDLoFNCT)(); INT4 OddIsAttr (SDLoATTR *attr, char *option); INT4 OddIsClass (SDLoOBJ *class, char *option); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object wide variables */ extern SDLo *odd; extern SDLoFNCT SDL_fnct[]; extern ODDoFNCT_P function[SDLxXFNCT]; extern FILo *f; /****************************************************************************** ****** Group of functions calculating object size ***************************** ******************************************************************************* ** ** INPUT: address of parent object [R] ** address of attribute [R] ** address of offset within structure [W] ** IMPLICIT: ** odd (SDLo *) */ int OFInheritSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { return 0; } int OF4BArrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignFour (*off); return 4 * attr->arrsz; } int OF4BSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignFour (*off); return 4; } int OFPtrArrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignEight (*off); return (sizeof (char *) * attr->arrsz); } int OFPtrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignEight (*off); return sizeof (char *); } int OFBNFSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { _SdlAlignEight (*off); return (sizeof (char *) + sizeof (int)); } int OFBArrSize (SDLoOBJ *obj, SDLoATTR *attr, int *off) { return 1 * attr->arrsz; } /****************************************************************************** ****** group of functions for posprocesssing attributes *********************** ******************************************************************************* ** ** INPUT: address of parent object [R] ** address of attribute [R] ** address of header [W] ** address of current offset in target structure [W] ** IMPLICIT: ** odd (SDLo *) [R] ** ** RETURNS: e__icarequiredattr + ** 1 */ int OFMakeDefault (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { int (*insert)(); int l, rv; if (!(attr->isrd)) { if (attr->req) _ErrRet (e__icarequiredattr); else if ((insert = odd->at[attr->typ].insert) != NULL) for (l = 0; l < attr->arrsz; l++) { rv = (*insert) (obj, attr, attr, off, 0, ODDxNULL, TRUE); _ErrRet (rv); } } return 1; } int OFMakeNoDefault (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { if (!(attr->isrd)) _ErrRet (e__icarequiredattr); return 1; } int OFMakeChildN (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { Int4 n; n = (attr->hasObjsN!=-1) ? attr->hasObjsN : odd->oc[attr->dfltv].loc_n; memcpy (*off, &n, sizeof (int)); return 1; } int OFMakeAllObjN (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { memcpy (*(int **) off, &((odd->oc)[attr->dfltv].gbl_n), sizeof (int)); return 1; } int OFMakeChild (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { SDLoOBJ *refClass; SDLoPTR tmp; int rv, firstX, l, i; refClass = &(odd->oc[attr->dfltv]); firstX = refClass->gbl_n - refClass->loc_n; if (attr->hasObjsN != -1) refClass->loc_n -= attr->hasObjsN; attr->dflts = OddGetClassDeclName (refClass); attr->tnam = &(refClass->tnam[0]); if (odd->action != SDLxNOHDR && !odd->section_f) memcpy (*(int **) off, &firstX, sizeof (int)); else { SDLoPTR tmp; tmp = refClass->s + (refClass->siz * firstX); memcpy (*off, &tmp, sizeof (SDLoPTR)); } return 1; } int OFMakeAllObj (SDLoOBJ *obj, SDLoATTR *attr, SDLoPTR *off) { SDLoOBJ *referredClass; referredClass = & (odd->oc[attr->dfltv]); if ((odd->action != SDLxNOHDR) && !odd->section_f) memset (*off, 0, sizeof (SDLoPTR)); else memcpy (*off, &(referredClass->s), sizeof (SDLoPTR)); attr->dflts = OddGetClassDeclName (referredClass); attr->tnam = &(referredClass->tnam[0]); return 1; } /****** OfArraySiz ***********************************************************/ /** ** returns string with array size for declaration of arrays ** if not array string is empty; ** ** INPUT: attribute object [R] ** IMPLICIT: ** ** RETURNS: address of string **/ char *OFArraySiz (SDLoATTR *attr) { static char as[10]; if (attr->arrsz > 1) sprintf(as, "[%d]", attr->arrsz); else as[0] = '\0'; return &as[0]; } /****************************************************************************** ***** group of functions for writing attribute definition to header file ****** ******************************************************************************* ** ** ** INPUT: attribute object [R] ** generic type [R] ** generic object type [R] ** IMPLICIT: ** odd (SDLo *) [R] ** ** RETURNS: */ char *OddRemark (SDLoATTR *attr) { static char remark[550]; if (!*attr->rem) remark[0] = '\0'; else sprintf (remark, " /*%s %s */", OddIsAttr (attr, "api") ? "API" : "", attr->rem); return remark; } char *OddAddRemark (char *ln, SDLoATTR *attr) { static char newLn[600]; char remark[550]; char *lastBlankPtr; int l, k, lSave; if (!*attr->rem) return ln; else { sprintf (newLn, "%-40s ", ln); sprintf (remark, "/*%s %s */", OddIsAttr (attr, "api") ? "API" : "", attr->rem); l = 0; while (1) { for (k=strlen (newLn); (k % 80) && remark[l]; k++, l++) { newLn[k] = remark[l]; if (newLn[k] == ' ') { lastBlankPtr = &newLn[k]; lSave = l; } } if (remark[l]) { /* comment string is not yet finished */ *lastBlankPtr = '\0'; sprintf (newLn, "%s\n%43s", newLn, " "); l = lSave; } else { newLn[k] = '\0'; break; } } } return newLn; } int OFDefSimple (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; sprintf(l, " %-24s%s%s;", odd->at[attr->typ].tnam, OddGetAttrDeclName (attr), OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefStr (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; sprintf (l, " %-24s*%s%s;", "char", OddGetAttrDeclName (attr), OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefFnct (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; char tnam[80], args[80], tmp[80]; strcpy (args, attr->dflts); if (gtyp_nm != NULL) { /* generic argument type */ if (typdef_nm != NULL) { sprintf (tmp, "struct %s", typdef_nm); SmSwapS (args, SDLxGTYPDEFNAM, tmp); } SmSwapS (args, SDLxGTYPNAM, gtyp_nm); } else SmSwapS (args, SDLxGTYPDEFNAM, "void"); /* generic return val type */ if (strcmp (SDLxGTYPNAM, attr->tnam) == 0 && gtyp_nm != NULL) sprintf (tnam, "%-24s*", gtyp_nm); else strcpy (tnam, "INT4"); sprintf (l, " %-24s(*%s)%s;", tnam, attr->dnam, " ()" /*args*/ ); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefHeader (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; sprintf (l, " %-24s*%s;", attr->tnam, attr->dnam); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefStructPtr (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; char tnam[80]; sprintf (tnam, "struct %s", odd->oc[attr->dfltv].tnam); sprintf (l, " %-24s*%s%s;", tnam, OddGetAttrDeclName (attr), OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefGenericTyp (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; if (gtyp_nm == NULL) sprintf (l, " %-24s*%s;", "void", attr->dnam); else sprintf(l, " %-24s*%s;", gtyp_nm, attr->dnam); fprintf (fil, "%s\n", OddAddRemark (l, attr)); return 1; } int OFDefUser (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { char l[133]; int pp_f; pp_f = *(attr->sw_nm) != '\0' ? TRUE : FALSE; if (pp_f) /* if preprocessor switch */ fprintf(fil, "#ifdef %s\n", attr->sw_nm); sprintf (l, " %-24s%s%s;", attr->tnam, attr->dnam, OFArraySiz (attr)); fprintf (fil, "%s\n", OddAddRemark (l, attr)); if (pp_f) { fprintf(fil, "#else\n"); fprintf(fil, " %-24s%s%s;%s\n", (*attr->alt_nm == '\0') ? "unsigned int" : attr->alt_nm, attr->dnam, OFArraySiz (attr), OddRemark (attr)); fprintf(fil, "#endif\n"); } return 1; } int OFDefEbnf (FILE *fil, SDLoATTR *attr, char *gtyp_nm, char *typdef_nm) { fprintf(fil, " %-24s%s;\n", "char", "**ebnfln"); fprintf(fil, " %-24s%s;\n", "INT4", "nebnfln"); return 1; } /****************************************************************************** ****** group of functions for inserting attribute values ********************** ******************************************************************************* ** ** ** INPUT: address of parent object [R] ** address of attribute [R] ** address of header [W] ** address of current offset in target structure [W] ** IMPLICIT: ** odd (SDLo *) [R] ** f (FILo *) [R] ** ** RETURNS: e__icarequiredattr + ** e__icaattrval + ** e__allocfail + ** e__objnotfound + ** 1 */ int OFInsertFloat (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, float **dest, char *tokstr, unsigned int tokval, int dflt_f) { float value; if (dflt_f) value = dfltattr->dfltvf; else sscanf (tokstr, "%f", &value); _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (float)); *dest += 1; return 1; } int OFInsertInt (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, int **dest, char *tokstr, unsigned int tokval, int dflt_f) { int value; if (tokval == ODDxNULL) value = dflt_f ? dfltattr->dfltv : atoi(tokstr); else value = tokval; _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (int)); *dest += 1; return 1; } int OFInsertUInt (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { unsigned int value; if (tokval == ODDxNULL) value = dflt_f ? dfltattr->dfltv : atoi(tokstr); else value = tokval; _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (unsigned int)); *dest += 1; return 1; } int OFInsertUChar (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned char **dest, char *tokstr, unsigned int tokval, int dflt_f) { unsigned char value; if (tokval == ODDxNULL) value = dflt_f ? dfltattr->dfltv : atoi(tokstr); else value = tokval; _ErrRet (SdlCheckPar (attr, 0, value)); memcpy (*dest, &value, sizeof (char)); *dest += 1; return 1; } int OFInsertUser (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, void ***dest, char *tokstr, unsigned int tokval, int dflt_f) { memset (*dest, 0, sizeof (char *)); *dest += 1; return 1; } int OFInsertStr (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, char ***dest, char *tokstr, unsigned int tokval, int dflt_f) { char *newvalue, *value = NULL; int rv; /* if (tokval == ODDxNULL) ...does this ever happen? */ value = dflt_f ? &((dfltattr->dflts)[0]) : tokstr; /* else value += _SdlIsStr (tokval); */ rv = SdlCheckPar (attr, value, 0); _ErrRet (rv); /* insert into user-object */ if ((newvalue = (char *) _SdlMalloc (strlen (value) + 1)) == 0) _ErrRet2(e__allocfail, "symbol string"); memcpy (*dest, &newvalue, sizeof (char *)); if (attr->typ == AT_PROTOFNCT) /* copy function to array */ OddAddFunction (*dest); *dest = *dest + 1; strcpy (newvalue, value); if (odd->action == SDLxNOHDR || odd->section_f) SmEdit (newvalue, SMxDECODE); return 1; } int OFInsertFunction (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { unsigned int value; SDLoPTR tmp=NULL; value = dflt_f ? SDLxNULLFNCT : atoi (tokstr); if (odd->action == SDLxNOHDR || odd->section_f) { if (odd->section_f) { /* function index */ tmp += dflt_f ? SDLxXFNCT : value; memcpy (*dest, &tmp, sizeof (SDLoPTR)); } else { /* function address */ tmp = dflt_f ? NULL : (SDLoPTR) SDL_fnct[value]; memcpy (*dest, &tmp, sizeof (SDLoPTR)); } } else { /* function name */ tmp = dflt_f ? "NULL" : *(function[value].nam); memcpy (*(char ***) dest, &tmp, sizeof (SDLoPTR));} if (!dflt_f) attr->dflts = *(function[value].args); *dest += 1; return 1; } int OFInsertObject (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, void ***dest, char *tokstr, unsigned int tokval, int dflt_f) { SDLoOBJ *refClass; SDLoPTR obj_p; int rv, objX; refClass = &(odd->oc[attr->dfltv]); if (tokstr) objX = atoi (tokstr); else if (tokval == ODDxNULL) objX = -1; else objX = tokval; /* possibly never occurs */ if (!dflt_f && objX != -1) { obj_p = (void *) (refClass->s + refClass->siz * objX); } else obj_p = NULL; /* copy object address into output object */ if (odd->action == SDLxNOHDR || odd->section_f) memcpy (*dest, &obj_p, sizeof (SDLoPTR)); else memcpy (*dest, &objX, sizeof (SDLoPTR)); (*dest)++; attr->dflts = OddGetClassDeclName (refClass); /* declaration name */ /* give attribute a type definition name */ attr->tnam = refClass->tnam; return 1; } int OFInsertHeader (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { return 1; } int OFInherit (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, unsigned int **dest, char *tokstr, unsigned int tokval, int dflt_f) { return 1; } int OFGeneric (SDLoOBJ *obj, SDLoATTR *attr, SDLoATTR *dfltattr, void ***dest, char *tokstr, unsigned int tokval, int dflt_f) { return 1; } /****************************************************************************** ******** group of functions for writing attribute value to header file ******** ******************************************************************************* ** ** ** INPUT: attribute object [R] ** destination string [W] ** address of source [W] ** IMPLICIT: ** ** RETURNS: ** */ int OFWrtInt (SDLoATTR *attr, char *s, int **source) { sprintf (s, "%d", **source); (*source)++; return 1; } int OFWrtUChar (SDLoATTR *attr, char *s, unsigned char **source) { sprintf (s, "%d", **source); (*source)++; return 1; } int OFWrtUInt (SDLoATTR *attr, char *s, unsigned int **source) { sprintf (s, "%u", **source); (*source)++; return 1; } int OFWrtFloat (SDLoATTR *attr, char *s, float **source) { sprintf (s, "%f", **source); (*source)++; return 1; } int OFWrtStr (SDLoATTR *attr, char *s, char ***source) { static STRv str; if (!str) str = StrNew (); StrSetS (&str, **source); StrEncode (&str); sprintf (s, "\"%s\"", _Str (str)); (*source)++; return 1; } int OFWrtName (SDLoATTR *attr, char *s, char ***source) { sprintf (s, "%s", **source); (*source)++; return 1; } int OFWrtNULL (SDLoATTR *attr, char *s, void ***source) { sprintf (s, "NULL"); (*source)++; return 1; } int OFWrtAddr (SDLoATTR *attr, char *s, unsigned int **source) { if (**source == ODDxNULL) sprintf(s, "NULL"); else sprintf(s, "&%s[%d]", attr->dflts, **source); (*source)++; return 1; } int OFWrtEBNF (SDLoATTR *attr, char *s, char ***source) { return 1; } /****************************************************************************** ******* group of functions for checking attribute values ********************** ******************************************************************************* ** ** INPUT: address of attribute [R] ** address of value ** IMPLICIT: ** f (FILo *) [R] ** ** RETURNS: e__icaattrval + ** 1 */ int OFCheckNum (SDLoATTR *attr, int v, char *s) { char errmsg[MSGxXLN]; if (v > attr->max) sprintf(errmsg, "Attribute: %s, value: %d, max: %d", attr->nam, v, attr->max); else if (v < attr->min) sprintf(errmsg, "Attribute: %s, value: %d, min: %d", attr->nam, v, attr->min); else return 1; _ErrRet2 (e__icaattrval, errmsg); return 1; } int OFCheckStr (SDLoATTR *attr, int v, char *s) { char errmsg[MSGxXLN]; int len; len = strlen (s); if (len > attr->max) sprintf (errmsg, "Attribute: %s, string: %s, maxlen: %d", attr->nam, s, attr->max); else if (len < attr->min) sprintf (errmsg, "Attribute: %s, string: %s, minlen: %d", attr->nam, s, attr->min); else return 1; _ErrRet2 (e__icaattrval, errmsg); return 1; } int OFGenSimple (SDLoOBJ * headobj, SDLoATTR *attr) { return 1; } int OFGenObject (SDLoOBJ * headobj, SDLoATTR *attr) { return 1; } char oddtools_srs_ID[] = "$Id: oddtools.c,v 1.1 1996/05/06 15:17:04 srs Exp $"; /* ** ** $RCSfile: oddtools.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:04 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "message.h" #include "oddtools.h" #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif typedef struct ODDooQ_P { struct ODDooQ_P *dn ,*up; int data; } ODDoQ_P; typedef struct ODDooL_P { struct ODDooL_P *dn; int data; } ODDoL_P; typedef struct ODDooT_P { struct ODDooT_P *left, *right; char bal; int data; } ODDoT_P; typedef struct ODDoHEAD_ { void *dn; void *up; void *null; int cx; unsigned char init_f; int n; void *current; void *new; unsigned char off; int (*getnew)(struct ODDoHEAD *, int); int (*add)(struct ODDoHEAD *); int (*search)(struct ODDoHEAD *, void *, char *); int (*delete)(struct ODDoHEAD *); void *(*position)(struct ODDoHEAD *,int); int (*clear)(struct ODDoHEAD *); } ODDoHEAD; /***********************************/ /****** OBJECT WIDE VARIABLES ******/ /***********************************/ extern char *section; extern int section_z; /****** OddQInit ************************************************************** ** ** inititalizes data-structure queue; ** ** INPUT: queue-header [W] ** IMPLICIT: ** ** RETURNS: 1 */ int OddQInit (ODDoHEAD *hd) { hd->null = (void *) &(hd->dn); hd->up = (void *) hd->null; hd->dn = (void *) hd->null; hd->n = 0; hd->init_f = TRUE; return 1; } /**api* OddLAdd *************************************************************** ** ** adds new item to linked list; ** ** INPUT: queue-dscr. [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if head->new is NULL */ int OddLAdd (ODDoHEAD *hd) { ODDoL_P *new, *lst; if (!hd->init_f) OddQInit (hd); /* use same function as for queue */ if (hd->new == NULL) return 0; new = (ODDoL_P *) ((char *) hd->new - hd->off); new->dn = (ODDoL_P *) hd->null; lst = (ODDoL_P *) hd->up; lst->dn = new; hd->up = new; hd->n++; if (hd->n == 1) { /* first element */ hd->cx = 0; hd->current = &(new->data); } hd->new = NULL; return 1; } /**api* OddNew **************************************************************** ** ** allocates memory for new element and places address to i ** into header->new; ** ** INPUT: address of header [W] ** size of item ** IMPLICIT: ** ** RETURNS: 1 ** e__allocfail + */ int OddNew (ODDoHEAD *hd, int size) { if ((hd->new = (void *) malloc (size + hd->off)) == NULL) _ErrRet2(e__allocfail, "item by OddNew"); hd->new = (char *) hd->new + hd->off; /* shift offset */ return 1; } /**api* OddQAdd ************************************************************** ** ** places item that header->new points to at end of queue; ** initializes queue if necessary; ** ** INPUT: queue-header [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if header->new not defined ** */ int OddQAdd (ODDoHEAD *hd) { ODDoQ_P *new; if (!hd->init_f) OddQInit (hd); if (hd->new == NULL) return 0; new = (ODDoQ_P *) ((char *) hd->new - hd->off); new->up = (ODDoQ_P *) hd->up; new->dn = (ODDoQ_P *) hd->null; new->up->dn = new; new->dn->up = new; hd->n++; if (hd->n == 1) { hd->cx = 0; hd->current = &(new->data); } hd->new = NULL; return 1; } /**api* OddQPosition ********************************************************** ** ** positions cursor to element with specified number ** ** INPUT: list-dscr. [W] ** index of item [R] first element has index 1 !!! ** or ODDxNEXT, ODDxPREV, ODDxFIRST, ODDxLAST ** IMPLICIT: ** ** RETURNS: pointer to object ** NULL if index larger than actual count or queue empty */ void *OddQPosition (ODDoHEAD *hd, int x) { ODDoQ_P *nxt; int k; if (x > 0) x--; if (x == ODDxNEXT) x = hd->cx+1; if (x == ODDxPREV) x = hd->cx-1; if (x >= hd->n || x == -1 || hd->n == 0) return NULL; if (x == hd->cx) return hd->current; if (x != ODDxFIRST && x != ODDxLAST) { nxt = (ODDoQ_P *) ((char *) hd->current - hd->off); if (x > hd->cx) for (k=hd->cx; k < x; nxt = nxt->dn, k++) ; else for (k=hd->cx; k > x; nxt = nxt->up, k--) ; } else if (x == ODDxFIRST) nxt = hd->dn, x = 0; else if (x == ODDxLAST) nxt = hd->up, x = hd->n -1; hd->current = &(nxt->data); hd->cx = x; return hd->current; } /**api* OddLPosition ************************************************************** ** ** positions cursor to element with specified number in linked list; ** ** INPUT: list-dscr. [W] ** index of item [R] first element has index 1 !!! ** or ODDxNEXT, ODDxPREV, ODDxFIRST, ODDxLAST ** IMPLICIT: ** ** RETURNS: pointer to object ** NULL if index larger than actual count or queue empty */ void *OddLPosition (ODDoHEAD *hd, int x) { ODDoL_P *nxt; int k; if (x > 0) x--; if (x == ODDxNEXT) x = hd->cx+1; if (x == ODDxPREV) x = hd->cx-1; if (x >= hd->n || x == -1 || hd->n == 0) return NULL; if (x == hd->cx) return hd->current; if (x != ODDxFIRST && x != ODDxLAST) { if (x > hd->cx) k = hd->cx, nxt = (ODDoL_P *) ((char *) hd->current - hd->off); else k = 0, nxt = hd->dn; for (; k < x; nxt = nxt->dn, k++) ; } else if (x == ODDxFIRST) nxt = hd->dn, x = 0; else nxt = hd->up, x = hd->n - 1; hd->current = &(nxt->data); hd->cx = x; return hd->current; } /**api* OddLInsert **************************************************************** ** ** inserts element in linked list either left or right of current; ** new element becomes then current element; ** ** INPUT: address of list header [W] ** ODDxLEFT or ODDxRIGHT [R] ** IMPLICIT: ** ** RETURNS: 1 */ int OddLInsert (ODDoHEAD *hd, int pos) { ODDoL_P *tmp, *new; if (!hd->init_f || !hd->n) { OddLAdd (hd); return 1; } else { new = (ODDoL_P *) ((char *) hd->new - hd->off); if (pos == ODDxRIGHT) { tmp = (ODDoL_P *) ((char *) hd->current - hd->off); hd->cx++; } else if (pos == ODDxLEFT) { if (hd->cx > 0) { OddLPosition (hd, hd->cx); hd->cx++; tmp = (ODDoL_P *) ((char *) hd->current - hd->off); } else { hd->cx = 0; tmp = (ODDoL_P *) hd; } } new->dn = tmp->dn; tmp->dn = new; } hd->n++; hd->current = &(new->data); return 1; } /**api* OddLDelete **************************************************************** ** ** Deletes an entry from a list - current entry will be the one after ** the deleted one; ** ** INPUT: address of header-dsc. [W] ** IMPLICIT: ** ** RETURNS: 1 ** 0 if list empty */ int OddLDelete (ODDoHEAD *hd) { ODDoL_P *prev, *tmp; int *rv, fst_f = FALSE; if (hd->n == 0) return 0; tmp = (ODDoL_P *) ((char *) hd->current - hd->off); if (hd->cx > 0) { OddLPosition (hd, hd->cx); prev = (ODDoL_P *) ((char *) hd->current - hd->off); } else prev = (ODDoL_P *) hd, fst_f = TRUE; prev->dn = tmp->dn; OddFree (tmp); if (hd->n == 1) OddQInit (hd); else { hd->n--; if (hd->cx == hd->n) hd->current = &(prev->data); else { hd->current = &(prev->dn->data); if (!fst_f) hd->cx++; } } return 1; } /****** OddFree ******************************************************************* ** ** frees memory - does it only if memory is not within the ODD-section; ** ** INPUT: pointer to memory to be freed [W] ** IMPLICIT: ** section (void *) [R] ** section_z (int) [R] ** ** RETURNS: 1 if freed ** 0 if not */ int OddFree (char *p) { if (p >= section && p <= section + section_z) return 0; else free (p); p = NULL; return 1; } ******************* ** ** $RCSfile: oddtools.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:05 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** */ #define ODDxNEXT -2 #define ODDxPREV -3 #define ODDxFIRST -4 #define ODDxLAST -5 #define ODDxRIGHT 0 #define ODDxLEFT 1 #define ODDxFORWARD 2 #define ODDxREVERSE 4 #define ODDxCURRENT 8 ** C list management *****************************************************************************/ #include #include #include "def.h" #include "oldlistbuf.h" /* creation/deletion */ void ListBufCreate(LISTBUFv* list, LISTBUFoINFO* i, int dim) { int memSize=sizeof(LISTBUFo)+(i->elemSize)*dim; *list=malloc(memSize); (*list)->info=i; (*list)->num=0; (*list)->size=memSize; } void ListBufDelete(LISTBUFv* list) { free(*list); /* I know the size of it! */ *list=NULL; } /* insertion/removal */ void ListBufAppend(LISTBUFv* list, void* val) { Iter i=NULL; ListBufAdd(list, &i, val); } void ListBufInsert(LISTBUFv* list, void* val) { Iter i=ListBufFirst(list); ListBufAdd(list,&i,val); } void ListBufAdd (LISTBUFv* list, Iter* i, void* val) { int num=((*list)->num++); int elemSize=(*list)->info->elemSize; int last=sizeof(LISTBUFo)+num*elemSize; int offset; num++; /* append if i invalid */ if (!*i) *i=cast(*list,BYTE*)+last; offset=cast(*i,BYTE*)-cast(*list,BYTE*); if (last>=(*list)->size) { /* grow the list, copy elements inserting new */ LISTBUFo* oldListBuf=*list; BYTE* oldIter=cast(*i,BYTE*); int newSize=sizeof(LISTBUFo)+2*num*elemSize; *list=malloc(newSize); *i=cast(*list,BYTE*)+offset; memcpy(cast(*list,BYTE*),cast(oldListBuf,BYTE*),offset); memcpy(cast(*i,BYTE*)+elemSize,oldIter,last-offset); memcpy(cast(*i,BYTE*),val,elemSize); (*list)->size=newSize; free(oldListBuf); } else { /* move the elements after (including) insertion point */ memmove(cast(*i,BYTE*)+elemSize,cast(*i,BYTE*),last-offset); memcpy(*i,val,elemSize); } } void ListBufRemove(LISTBUFv* list, Iter* i) { int num=(--(*list)->num); int elemSize= (*list)->info->elemSize; int last=sizeof(LISTBUFo)+num*elemSize; int offset; /* append if i invalid */ ASSERT(*i,RemoveInvalid); offset=cast(*i,BYTE*)-cast(*list,BYTE*); if ((*list)->size>last+2*num*elemSize) { /* shrink the list, copy elements removing */ LISTBUFv oldListBuf=*list; BYTE* oldIter=cast(*i,BYTE*); int newSize=sizeof(LISTBUFo)+num*elemSize; *list=malloc(newSize); *i=cast(*list,BYTE*)+offset; memcpy(cast(*list,BYTE*),cast(oldListBuf,BYTE*),offset); memcpy(cast(*i,BYTE*),oldIter+elemSize,last-offset); cast(*list,LISTBUFo*)->size=newSize; free(oldListBuf); if (cast(*i, BYTE*)>=cast(*list, BYTE*)+newSize) *i=NULL; } else { /* move the elements after removal point */ memmove(cast(*i,BYTE*),cast(*i,BYTE*)+elemSize,last-offset); } } void ListBufClear (LISTBUFv* list) { (*list)->num=0; } /* access */ void* ListBufAtPos (LISTBUFv* list, int pos) { return ListBufAt(list,ListBufInPos(list,pos)); } void* ListBufAt (LISTBUFv* list, Iter i) { ASSERT(i,InvalidIter); return i; } /* iterator support */ Iter ListBufInPos(LISTBUFv* list, int pos) { if (pos<(*list)->num) return cast(*list,BYTE*)+sizeof(LISTBUFo)+ pos*(*list)->info->elemSize; else return NULL; } int ListBufPosAt(LISTBUFv* list, Iter i) { ASSERT(i,InvalidIter); return (cast(i,BYTE*)-(cast(*list,BYTE*)+sizeof(LISTBUFo)))/ (*list)->info->elemSize; } Iter ListBufFirst(LISTBUFv* list) { return ListBufInPos(list,0); } void* ListBufNext (LISTBUFv* list, Iter* i) { if (!*i) *i=ListBufFirst(list); else { int elemSize=(*list)->info->elemSize; *i=cast(*i,BYTE*)+elemSize; if (cast(*i,BYTE*)>=cast(*list,BYTE*)+sizeof(LISTBUFo)+(*list)->num*elemSize) { *i=NULL; return NULL; } } return *i; } Iter ListBufLast (LISTBUFv* list) { int num=(*list)->num; if (num) return cast(*list,BYTE*)+(*list)->info->elemSize*(num-1); else return NULL; } void* ListBufPrev (LISTBUFv* list, Iter* i) { if (!*i) i=ListBufLast(list); else { int elemSize=(*list)->info->elemSize; *i=cast(*i,BYTE*)-elemSize; if (cast(*i,BYTE*)num; } BOOL ListBufEmpty(LISTBUFv* list) { return (*list)->num==0; } #define _LISTBUF_H /******************************************************************************* ** C generic ListBuf management **/ /* will be class of value */ typedef struct LISTBUFoINFO { int elemSize; } LISTBUFoINFO; typedef struct LISTBUFo { LISTBUFoINFO* info; int size; int num; } LISTBUFo; /* a list of values */ typedef LISTBUFo* LISTBUFv; /************************************ ** ITERATOR ** ** USE ONLY ONE iterator with add,remove: ** other iterators become invalid ** NULL iterator is position without value: ** access: invalid ** add: identifies position AFTER last element (append) ** next: starts from first again ** prev: starts from last again */ /************************************ ** LISTBUF API */ /* creation/deletion */ void ListBufCreate(LISTBUFv* list, LISTBUFoINFO* i, int dim); void ListBufDelete(LISTBUFv* list); /* insertion/removal */ void ListBufAppend(LISTBUFv* list, void* val); void ListBufInsert(LISTBUFv* list, void* val); void ListBufClear (LISTBUFv* list); /* iterator mantains position after operation */ void ListBufAdd (LISTBUFv* list, Iter* i, void* val); void ListBufRemove(LISTBUFv* list, Iter* i); /* access */ void* ListBufAtPos (LISTBUFv* list, int pos); void* ListBufAt (LISTBUFv* list, Iter i); /* iterator support */ Iter ListBufInPos (LISTBUFv* list, int pos); int ListBufPosAt (LISTBUFv* list, Iter i); Iter ListBufFirst(LISTBUFv* list); void* ListBufNext (LISTBUFv* list, Iter* i); Iter ListBufLast (LISTBUFv* list); void* ListBufPrev (LISTBUFv* list, Iter* i); /* information */ int ListBufCard (LISTBUFv* list); BOOL ListBufEmpty(LISTBUFv* list); /************************************************************************ ** specialized list declarations (good for debugging) */ typedef struct LISTBUFoChar { LISTBUFo head; char arr[100]; } LISTBUFoChar; typedef LISTBUFoChar STRINGo; typedef struct LISTBUFoInt { LISTBUFo head; int arr[10]; } LISTBUFoInt; typedef struct LISTBUFoPtr { LISTBUFo head; BYTE* arr[10]; } LISTBUFoPtr; #endif **/ char parameter_srs_ID[] = "$Id: par.c,v 1.3 1996/07/14 16:21:23 etzold Exp $"; /* ** $RCSfile: par.c,v $ ** $Revision: 1.3 $ ** $Date: 1996/07/14 16:21:23 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message, rtl, sdl, sdlget, oddfncts ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description ** =========== ** ** management of user defined variables ** if the variable is a number or real then the value is 0 if undefined - ** which means that every parameter has a default value of 0! ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "sm.h" #include "futil.h" #include "sdlget.h" #include "lst.h" #include "regexp.h" #include "par.h" #include SRSINCLUDE #define PARxXNAM 80 #define PARxXSTR 5000 /* ** name of the ODD file with the user definitions */ #define SRSDEFAULTS "SRSDAT:srsparam.dat" #ifdef VMS # define USERDEFAULTS "SYS$LOGIN:srsparam.dat" #else # define USERDEFAULTS "HOME/.srsparam" #endif enum tableType {PARxPRIVATE=1,PARxLAYERED}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** parameter list object (parameter table) */ typedef struct PARoTABLE { char *list; /* for usage of module "list" only! */ INT4 classId; /* for "list" module */ char name[132]; /* name of the parameter table */ struct PARo *par; /* list of all predefined parameters */ INT4 parN; /* number of predefined parameters */ struct PARoTYPE *parType; /* list of all predefined parameter types */ INT4 parTypeN; /* number of predefined parameter types */ INT4 parClassId; /* for the /lst/ module */ INT4 parTypeClassId; /* for the /lst/ module */ char isModified; /* has one of the parameters in the table been modified? */ struct PARoTABLE *up; /* Upper or outer parameter list */ enum tableType type; /* type of the table */ } PARoTABLE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** global and module wide variables */ static PARoTABLE *parTable=NULL; INT4 changepar_f; /* tells if any parameter in the list was changed */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** internal functions */ int ParOCheckFunction (PARo *par, INT4 (*function) ()); int ParOCheckReal (PARo *par, float real); int ParOCheckNum (PARo *par, int num); int ParOCheckStr (PARo *par, char *str); static INT4 ParODefBool (PARo *par, char *str); static void ParTableNew (void *obj); static void ParTableKill (void *obj); static void ParNew (void *obj); static void ParDump (FILE *file, void *obj); /***** ParTableNew ************************************************************ ** ** Initializes a new parameter table object. ** ** INPUT: pointer to memory location [W] ** IMPLICIT: ** ** RETURNS: */ static void ParTableNew (void *obj) { static INT4 parClassId=0, parTypeClassId=0; PARoTABLE *table = (PARoTABLE *) obj; if (!parClassId) { LstManageClassFlex (&parClassId, sizeof (PARo), ParNew, NULL, ParDump); LstManageClassFlex (&parTypeClassId, sizeof (PARoTYPE), NULL, NULL, NULL); } table->parClassId = parClassId; table->parTypeClassId = parTypeClassId; table->parN = 0; table->parTypeN = 0; table->par = NULL; table->parType = NULL; } /***** ParTableKill *********************************************************** ** ** Deletes a parameter table object. ** ** INPUT: pointer to memory location [W] ** IMPLICIT: ** ** RETURNS: */ static void ParTableKill (void *obj) { PARoTABLE *table = (PARoTABLE *) obj; if (table->par) LstDeleteAll ((void **)&table->par); if (table->parType) LstDeleteAll ((void **)&table->parType); } /**api* ParGetTable *********************************************************** ** ** Returns table object for specified name. ** ** INPUT: table name [R] ** IMPLICIT: ** parTable [W] ** ** RETURNS: ** address of parameter table object */ PARoTABLE *ParGetTable (char *name) { PARoTABLE *tmp = parTable; if (!LstHashSearch ((void **) &tmp, name)) _ErrExit3 (e__objectunknown, "parameter table", name); return tmp; } /***** ParSetTable ************************************************************ ** ** ** INPUT: o table name [R] ** o table name of table that the new table is added to [R] ** if omitted then the currently active table is used ** o option: "private", "layered" [R] ** IMPLICIT: ** parTable [W] ** ** RETURNS: ** address of parameter table object */ PARoTABLE *ParSetTable (char *name, char *upName, char *option) { static INT4 classId=0; static PARoTABLE *table=NULL; PARoTABLE *upTable = parTable; if (!classId) LstManageClass (&classId, sizeof (PARoTABLE), ParTableNew, ParTableKill, NULL); if (upName) if (!LstHashSearch ((void **) &upTable, upName)) _ErrExit3 (e__objectunknown, "parameter table", upName); if (!LstHashSearch ((void **) &table, name)) { LstNewNamed ((void **) &table, classId, name); table->up = upTable; table->type = SmEqs (option, "private") ? PARxPRIVATE : PARxLAYERED; } parTable = table; return table; } /***** ParUnsetTable ************************************************************ ** Sets table that has been set prior to the current one. ** ** INPUT: ** IMPLICIT: ** parTable [W] ** ** RETURNS: ** address of parameter table object */ PARoTABLE *ParUnsetTable () { if (parTable->up) parTable = parTable->up; return parTable; } void ParDeleteTable (char *name) { PARoTABLE *table=parTable; if (!LstHashSearch ((void **) &table, name)) _ErrExit3 (e__objectunknown, "table", name); if (parTable == table) parTable = table->up; LstDelete ((void **) &table); } /***** ParNew ***************************************************************** ** ** initializes parameter list; this is only necessary if predefined ** parameter's + parameter types exists ... ** ** INPUT: parameter name [R] ** IMPLICIT: ** parClassId (int) [W] ** parTypeClassId (int) [W] ** ** RETURNS: address of parameter object */ static void ParNew (void *obj) { PARo *par=(PARo *) obj; par->type = PARxNEW; par->parType = NULL; par->str = NULL; par->isLocked = 0; par->isVolatile = 0; par->set = NULL; } /***** ParDump **************************************************************** ** ** initializes parameter list; this is only necessary if predefined ** parameter's + parameter types exists ... ** ** INPUT: file pointer [W] or NULL ** parameter name [R] ** IMPLICIT: ** parClassId (int) [W] ** parTypeClassId (int) [W] ** ** RETURNS: address of parameter object */ static void ParDump (FILE *file, void *obj) { PARo *par=(PARo *) obj; if (!file) file = stderr; switch (par->type) { case PARxNUM: case PARxBOOL: fprintf (file, "#par /name=%s /num=%d\n", par->name, par->num); break; case PARxREAL: fprintf (file, "#par /name=%s /real=%f\n", par->name, par->real); break; case PARxSTR: fprintf (file, "#par /name=%s /str=%s\n", par->name, par->str); break; default: break; } } void ParDumpAll () { LstPrintAll ((void *) parTable->par); } /**api* ParInit *************************************************************** ** ** Initializes parameter table with a predifined parameter table. ** ** INPUT: address of parameter list object [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: */ void ParInit (PARoLIST *parList) { PARo *par=NULL; PARoTYPE *parType=NULL; char tmp[256]; int k, len; /* ** Copy parameters from the Parameter list (ODD) to the parameter table. */ LstNewNamed ((void **) &par, parTable->parClassId, "__dummy__"); for (k=0; k < parList->parN; k++) { parList->par[k].classId = parTable->parClassId; LstInsertObject ((void **) &par, &parList->par[k]); } parTable->par = par; /* ** Do the same for the list of parameter types. */ LstNewNamed ((void **) &parType, parTable->parTypeClassId, "__dummy__"); for (k=0; k < parList->parTypeN; k++) { parList->parType[k].classId = parTable->parTypeClassId; LstInsertObject ((void **) &parType, &parList->parType[k]); if (*parType->charSet) { /* expand permissive character set */ strcpy (tmp, parType->charSet); SmCharSet (tmp); parType->charSet = (char *) malloc (strlen (tmp) + 1); strcpy (parType->charSet, tmp); } } parTable->parType = parType; } /***** ParFind **************************************************************** ** ** searches a parameter by name; if not found a new parameter is inserted ** in the list with parameter type PARxNEW and returned; ** ** INPUT: parameter name [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: address of parameter object */ PARo *ParFind (char *parName) { if (!parTable) ParInit (NULL); if (!LstHashSearch ((void **) &parTable->par, parName)) LstNewNamed ((void **) &parTable->par, parTable->parClassId, parName); return parTable->par; } /**api* ParGetRead ************************************************************ ** ** Searches a parameter for read access. ** If the table is not specified then the one currently active is used. ** ** INPUT: parameter name [R] ** parameter table [R] or NULL ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: address of parameter object ** NULL if not found */ PARo *ParGetRead (char *parName, PARoTABLE *table) { PARo *getPar=NULL; if (!table) table = parTable; for (; table; table=table->up) if (LstHashSearch ((void **) &table->par, parName)) { getPar = table->par; break; } return getPar; } /**api* ParGetWrite *********************************************************** ** ** Retrieves a parameter for write access. ** If the table is not specified then the one currently active is used. ** ** INPUT: parameter name [R] ** parameter table [W] or NULL ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: address of parameter object ** NULL if not found */ PARo *ParGetWrite (char *parName, PARoTABLE *table) { PARoTABLE *tmp; PARo *getPar=NULL; char *intern; if (!table) table = parTable; for (tmp=parTable; tmp; tmp=tmp->up) { if (LstHashSearch ((void **) &tmp->par, parName)) { /* if found in upper table than copy it to current table */ if (tmp != table) { LstNewNamed ((void **) &table->par, table->parClassId, parName); getPar = table->par; intern = getPar->intern; /* save the pointer to the list */ memcpy (getPar, tmp->par, sizeof (PARo)); getPar->intern = intern; if (tmp->par->str) { getPar->str = (char *) malloc (strlen (tmp->par->str) + 1); strcpy (getPar->str, tmp->par->str); } } else getPar = tmp->par; break; } } /* create new parameter in current table if not found */ if (!getPar) { LstNewNamed ((void **) &table->par, table->parClassId, parName); getPar = table->par; } return getPar; } /**API* ParDelete ************************************************************* ** ** Deletes parameter with specified name. ** ** INPUT: parameter name [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: 1 if parameter was found and deleted ** 0 if parameter was not found */ INT4 ParDelete (char *parName) { PARo *par; if (!(par = ParGetRead (parName, parTable))) return 0; parTable->par = par; LstDelete ((void**) &parTable->par); return 1; } /**API* ParDeleteMatch ******************************************************** ** ** Searches all parameters for regular expression and delete all that ** match. ** ** INPUT: regular expression [R] ** IMPLICIT: ** ** RETURNS: number of parameters deleted */ INT4 ParDeleteMatch (char *reStr) { regexp *re; INT4 k=0; re = RegComp (reStr); LstFirst ((void **) &parTable->par); do { if (RegExec (re, parTable->par->name)) { LstDelete ((void**) &parTable->par); k++; } else LstNext ((void **) &parTable->par); } while (!LstIsLast ((void *) parTable->par)); if (RegExec (re, parTable->par->name)) { LstDelete ((void**) &parTable->par); k++; } free (re); return k; } INT4 ParDeleteAssign (char *s) { if (*s) ParDeleteMatch (s); } /**API* ParDefNum ************************************************************* ** ** Inserts or modifies a "number" parameter. ** ** INPUT: parameter name [R] ** parameter value [R] ** IMPLICIT: ** ** RETURNS: 1 if parameter was found ** 0 if it has been inserted ** invalid value: e__parnottype + */ INT4 ParDefNum (char *parName, INT4 num) { PARo *par; par = ParGetWrite (parName, parTable); return ParODefNum (par, num); } /**API* ParDefBool ************************************************************** ** Inserts or modifies a "boolean" parameter. ** ** INPUT: parameter name [R] ** parameter value [R] ** IMPLICIT: ** ** RETURNS: 1 if parameter was found ** 0 if it has been inserted ** invalid value: e__parnottype + */ INT4 ParDefBool (char *parName, INT4 num) { PARo *par; par = ParGetWrite (parName, parTable); return ParODefNum (par, num); } /**API* ParDefReal ************************************************************ ** ** Inserts or modifies a "real" parameter. ** ** INPUT: parameter name [R] ** parameter value [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: 1 if parameter was found ** 0 if it has been inserted ** invalid value: e__parnottype + */ INT4 ParDefReal (char *parName, float real) { PARo *par; par = ParGetWrite (parName, parTable); return ParODefReal (par, real); } /**API* ParDefStr ************************************************************* ** ** Inserts or modifies a "string" parameter. ** ** INPUT: parameter name [R] ** parameter value [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: 1 if parameter was found ** 0 if it has been inserted ** invalid value: e__parnottype + */ INT4 ParDefStr (char *parName, char *str) { PARo *par; par = ParGetWrite (parName, parTable); return ParODefStr (par, str); } /**API* ParDefFunction ******************************************************** ** ** Inserts or modifies a "function" parameter. ** ** INPUT: parameter name [R] ** parameter value [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: 1 if parameter was found ** 0 if it has been inserted ** invalid value: e__parnottype + */ INT4 ParDefFunction (char *parName, INT4 (*function) ()) { PARo *par; par = ParGetWrite (parName, parTable); return ParODefFunction (par, function); } /**api* ParGetNumF ************************************************************ ** ** Calls ParGetNum with variable length argument lists ** ** ** INPUT: pointer to string ** ** ** RETURNS: modified string ** **/ INT4 ParIsDefinedF(char *strfmt, ...) { char parName[200]; va_list args; va_start(args,strfmt); vsprintf(parName,strfmt,args); va_end(args); return ParIsDefined (parName); } /**api* ParGetNumF ************************************************************ ** ** Calls ParGetNum with variable length argument lists ** ** ** INPUT: pointer to string ** ** ** RETURNS: modified string ** **/ INT4 ParGetNumF(char *strfmt, ...) { char parName[200]; va_list args; va_start(args,strfmt); vsprintf(parName,strfmt,args); va_end(args); return ParGetNum (parName); } /** RParGetStr *************************************************** ** ** Does a ParGetStr with variable length argument lists ** ** INPUT: pointer to string ** ** ** RETURNS: modified string ** ** */ char *ParGetStrF (char *strfmt, ...) { char parName[200]; va_list args; va_start(args,strfmt); vsprintf(parName,strfmt,args); va_end(args); return ParGetStr(parName); } /** RParGetBool ********************************************************************** ** ** Does a ParGetBool with variable length argument lists ** ** INPUT: pointer to string ** ** ** RETURNS: modified string ** ** ** ** */ INT4 ParGetBoolF(char *strfmt, ...) { char parName[200]; va_list args; va_start(args,strfmt); vsprintf(parName,strfmt,args); va_end(args); return ParGetBool(parName); } /** RParDefStr *********************************************************************** ** ** Does a variable format ParDefStr ** ** INPUT: pointer to string ** ** ** RETURNS: modified string ** ** */ INT4 ParDefStrF (char *parName, char *strfmt, ...) { char parValue[200]; va_list args; va_start(args,strfmt); vsprintf(parValue,strfmt,args); va_end(args); return ParDefStr(parName,parValue); } /** RParDelete *********************************************************** ** ** Variable format ParDelete ** ** INPUT: pointer to string ** ** RETURNS: modified string ** ** */ INT4 ParDeleteF (char *strfmt, ...) { char parName[200]; va_list args; va_start(args,strfmt); vsprintf(parName,strfmt,args); va_end(args); return ParDelete(parName); } /**API* ParDefObject ********************************************************** ** ** Inserts or modifies an "object" parameter. ** ** INPUT: parameter name [R] ** parameter value [R] ** IMPLICIT: ** parTable (PARoTABLE *) [W] ** ** RETURNS: 1 if parameter was found ** 0 if it has been inserted ** invalid value: e__parnottype + */ INT4 ParDefObject (char *parName, void *object) { PARo *par; par = ParGetWrite (parName, parTable); return ParODefObject (par, object); } /**API* ParGetNum ************************************************************* ** ** Retrieves the value of a "number" parameter. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: value if parameter found ** 0 if not (default value) */ INT4 ParGetNum (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) return ParOGetNum (par); else return 0; } /**API* ParGetBool ************************************************************ ** ** Retrieves the value of a "boolean" parameter. ** parameter may be a number or string ("1", "yes", "ja", "on"). ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: value if parameter found ** 0 if not */ INT4 ParGetBool (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) return ParOGetBool (par); else return 0; } /**API* ParGetReal ************************************************************ ** ** Retrieves the value of a "real" parameter. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: value if parameter found ** 0 if not (default value) */ float ParGetReal (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) return ParOGetReal (par); else return 0; } /**API* ParGetStr ************************************************************* ** ** Retrieves the value of a "string" parameter. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: value if parameter found ** address to empty string if not */ char *ParGetStr (char *parName) { static char nullString[1]=""; PARo *par; if ((par = ParGetRead (parName, parTable))) return ParOGetStr (par); else return nullString; } /**API* ParGetFunction ******************************************************** ** ** Retrieves the value of a "function" parameter. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: value if parameter found ** NULL if not */ INT4 (*ParGetFunction (char *parName))() { PARo *par; if ((par = ParGetRead (parName, parTable))) return ParOGetFunction (par); else return NULL; } /**API* ParGetObject ********************************************************** ** ** Retrieves the value of an "object" parameter. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: value if parameter found ** NULL if not */ void *ParGetObject (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) return ParOGetObject (par); else return NULL; } /**api* ParIsModified ********************************************************* ** ** returns TRUE if any of the parameters was changed since reading into ** memory ** ** INPUT: ** IMPLICIT: ** table (PARoTABLE *) [R] ** ** RETURNS: TRUE if at least one parameter is changed ** FALSE if not */ INT4 ParIsModified () { return parTable->isModified; } /**api* ParIsDefined ********************************************************** ** ** returns TRUE if the parameter exists already ** ** INPUT: ** IMPLICIT: ** parTable (PARoTABLE *) [R] ** ** RETURNS: TRUE if exists ** FALSE if not */ INT4 ParIsDefined (char *parName) { return ParGetRead (parName, parTable) ? 1 : 0; } /**api************************************************************************* ** ** functions that get single descriptive values in the parameter object ** ** INPUT: address of parameter object [W] ** ... ** IMPLICIT: ** ** RETURNS: */ char *ParOGetHelpTopic (PARo *par) { return par->helpTopic; } char *ParOGetComment (PARo *par) { return par->comment; } char *ParOGetKey (PARo *par) { return par->key; } char *ParOCharSet (PARo *par) { return par->parType ? par->parType->charSet : NULL; } INT4 ParOGetNum (PARo *par) { /* convert string to integer */ if (par->type & PARxSTR && !(par->type & PARxNUM)) { par->num = atoi (par->str); par->type = par->type | PARxNUM; } if (!(par->type & PARxNUM || par->type & PARxBOOL)) _ErrExit3 (e__parnottype, par->name, "number"); return par->num; } INT4 ParOGetBool (PARo *par) { /* a boolean may be stored as a string parameter: "yes", "ja", "on" */ if (par->type == PARxSTR) { if (strchr ("yj", tolower (par->str[0])) || strchr ("n", tolower (par->str[1]))) { par->num = 1; par->type = par->type | PARxBOOL; } else if (!(par->type & PARxNUM || par->type & PARxBOOL)) _ErrExit3 (e__parnottype, par->name, "number/boolean/string"); } return par->num; } float ParOGetReal (PARo *par) { if (!(par->type & PARxREAL)) _ErrExit3 (e__parnottype, par->name, "real"); return par->real; } char *ParOGetStr (PARo *par) { char s[20]; if (!(par->type & PARxSTR) && par->type & PARxNUM) { sprintf (s, "%d", par->num); par->type = par->type | PARxSTR; ParODefStr (par, s); } else if (!(par->type & PARxSTR)) _ErrExit3 (e__parnottype, par->name, "string"); return par->str; } INT4 (*ParOGetFunction (PARo *par))() { if (par->type != PARxFUNCTION) _ErrExit3 (e__parnottype, par->name, "function"); return par->function; } void *ParOGetObject (PARo *par) { if (par->type != PARxOBJECT) _ErrExit3 (e__parnottype, par->name, "object"); return par->object; } INT4 ParOGetType (PARo *par) { return par->type; } /**api************************************************************************* ** ** functions that set single descriptive values in the parameter object ** ** INPUT: address of parameter object [W] ** ... ** IMPLICIT: ** ** RETURNS: */ void ParODefHelpTopic (PARo *par, char *helpTopic) { par->helpTopic = helpTopic; } void ParODefComment (PARo *par, char *comment) { par->comment = comment; } void ParODefKey (PARo *par, char *key) { par->key = key; } void ParODefCharSet (PARo *par, char *charSet) { if (par->parType) par->parType->charSet = charSet; } void ParODefType (PARo *par, char *parTypeName) { LstFirstNamed ((void **) &parTable->parType, parTypeName); par->parType = parTable->parType; } INT4 ParODefNum (PARo *par, INT4 num) { /* _ErrRet (ParOCheckNum (par, num)); */ if (par->isLocked) return 0; if (par->type & PARxSTR) par->type = PARxNUM; /* forces implicit conversion next time accessed as str */ else par->type |= PARxNUM; if (!par->num != num) parTable->isModified = 1; /* record change */ par->num = num; return 1; } INT4 ParODefStr (PARo *par, char *str) { int rv; if (par->isLocked) return 0; if (!str) return 0; if (par->type == PARxNUM){ /* string should be tested if contains digits */ return ParODefNum (par, atoi (str)); } if (par->type == PARxBOOL) return ParODefBool (par, str); if (par->type & PARxNUM) par->type = PARxSTR; /* forces implicit conversion next time accessed as num */ else par->type |= PARxSTR; if (par->set && *par->set) { char com[200]; sprintf (com, par->set, str); IcaEval (com); } rv = ParOCheckStr (par, str); _ErrRet (rv); if (!par->str || strcmp (par->str, str)) { /** record change */ parTable->isModified = 1; if (par->str && !OddIsInDepot (par->str)) free (par->str); /* delete ...new string could be larger */ par->str = (char *) malloc (strlen (str) + 1); strcpy (par->str, str); } return 1; } INT4 ParODefReal (PARo *par, float real) { if (par->isLocked) return 0; par->type |= PARxREAL; par->real = real; return 1; } INT4 ParODefFunction (PARo *par, INT4 (*function)()) { if (par->isLocked) return 0; par->type |= PARxFUNCTION; par->function = function; return 1; } INT4 ParODefObject (PARo *par, void *object) { if (par->isLocked) return 0; par->type = PARxOBJECT; par->object = object; return 1; } static INT4 ParODefBool (PARo *par, char *str) { INT4 val; if (par->isLocked) return 0; if (strchr ("yj", tolower (str[0]))) /* yes, ja */ val = 1; else if (strchr ("n", tolower (str[1]))) /* on */ val = 1; else val = 0; par->type |= PARxBOOL; if (!par->num != val) parTable->isModified = 1; /* record change */ ParODefNum (par, val); return 1; } /**API* ParSetVolatile ******************************************************** ** ** Sets the parameter so that it does not get saved by ParSave. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: */ void ParSetVolatile (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) par->isVolatile = 1; } /**API* ParLock *************************************************************** ** ** Locks a parameter to prevent modification until unlocked again. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: */ void ParLock (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) par->isLocked = 1; } /**API* ParUnlock ************************************************************* ** ** Unlocks a parameter. ** ** INPUT: parameter name [R] ** IMPLICIT: ** ** RETURNS: */ void ParUnlock (char *parName) { PARo *par; if ((par = ParGetRead (parName, parTable))) par->isLocked = 0; } /**api************************************************************************* ** ** checks a 'string' value ** ** INPUT: parameter object [R] ** string [R] ** IMPLICIT: ** ** RETURNS: ** 1 if value OK ** e__parnottype + ** e__checkfunctionerr <> ** e__strnotinset + ** e__charnotallowed + */ int ParOCheckStr (PARo *par, char *str) { PARoTYPE *parType; int isFound=0, len, k; if (!(par->type & PARxSTR || par->type & PARxBOOL)) /* parameter type */ _ErrRet3 (e__parnottype, par->name, "string"); if ((parType = par->parType)) { /* now use parType object... */ len = strlen (str); if (parType->charSet) /* test character set */ for (k=0; k < len; k++) if (!strchr (parType->charSet, str[k])) _ErrRet3 (e__charnotallowed, str[k], par->name); if (parType->max) { if (len > parType->max || len < parType->min) /* string length */ _ErrRet3 (e__invalstr, parType->min, parType->max); } if (parType->check) /* user check function */ if (!(*parType->check) (str)) return e__checkerr; } return 1; } /**api************************************************************************* ** ** checks a 'num' value ** ** INPUT: parameter object [R] ** number [R] ** IMPLICIT: ** ** RETURNS: ** 1 if value OK ** e__parnottype + ** e__checkfunctionerr <> ** e__numnotinset + */ int ParOCheckNum (PARo *par, int num) { PARoTYPE *parType; int isFound=0; if (par->type != PARxNUM && par->type != PARxBOOL) /* parameter type */ _ErrRet3 (e__parnottype, par->name, "number"); if ((parType = par->parType)) { if (num > parType->max || num < parType->min) /* number range */ _ErrRet3 (e__invalnumber, parType->min, parType->max); if (parType->check) /* user check function */ if (!(*parType->check) (num)) return e__checkerr; } return 1; } /**api************************************************************************* ** ** checks a 'real' value ** ** INPUT: parameter object [R] ** real [R] ** IMPLICIT: ** ** RETURNS: ** 1 if value OK ** e__parnottype + ** e__checkfunctionerr <> ** e__realnotinset + */ int ParOCheckReal (PARo *par, float real) { PARoTYPE *parType; int isFound=0; if (par->type != PARxREAL) /* parameter type */ _ErrRet3 (e__parnottype, par->name, "real"); if ((parType = par->parType)) { if (real > parType->maxReal || real < parType->minReal) /* range */ _ErrRet5 (e__realnotinrange, real, parType->minReal, parType->maxReal, par->name); if (!parType->check) /* user check function */ if (!(*parType->check) (real)) return e__checkerr; } return 1; } /**api************************************************************************* ** ** checks a 'function' value ** ** INPUT: parameter object [R] ** function pionter [R] ** IMPLICIT: ** ** RETURNS: ** 1 if value OK ** e__parnottype + ** e__checkfunctionerr <> ** e__functionnotinset + */ int ParOCheckFunction (PARo *par, INT4 (*function) ()) { PARoTYPE *parType; int isFound=0; if (par->type != PARxFUNCTION) /* parameter type */ _ErrRet3 (e__parnottype, par->name, "function"); if ((parType = par->parType)) { if (!parType->check) /* user check function */ if (!(*parType->check) (function)) return e__checkerr; } return 1; } /**api* ParSave *************************************************************** ** ** saves parameters in ODD-file; ** ** INPUT: file name of output file [R] ** IMPLICIT: ** ** RETURNS: */ void ParSave (char *fileName) { FILE *file; INT4 errCode, context; file = (FILE *) FilOpenW (fileName, &errCode); _ErrExit2 (errCode, fileName); for (context=0; ParPrintNext (file, &context, "odd");) ; fclose (file); } /**api* ParIsVolatileName ***************************************************** ** ** Analyses if the name has the 'volatile' mark at the end, removes it ** and sets the parameter volatile. ** ** INPUT: parameter name [W] ** IMPLICIT: ** ** RETURNS: 1 or 0 */ Int4 ParIsVolatileName (char *name) { Int4 len=strlen(name); if (name[len-1] == '~') { name[len-1] = '\0'; ParSetVolatile (name); } } /**api* ParRead *************************************************************** ** ** reads user defined parameters from SRSPARAM in either the user's home ** directory, or if it does not exist there in SRSDAT ** ** INPUT: file of input file [R] ** IMPLICIT: ** ** RETURNS: 1 if successful ** e__filnotok */ INT4 ParRead (char *fileName) { FILo file; INT4 num, rv; float real; char str[PARxXSTR+1], parName[PARxXNAM+1]; rv = FilUOpen (&file, fileName, PARxXSTR+20, 0); _ErrRet (rv); while (!FilEof (&file)) { if (sscanf (file.ln, "#par /name=%[^ /] /num=%d", parName, &num) == 2) { ParIsVolatileName (parName); ParDefNum (parName, num); } else if (sscanf (file.ln, "#par /name=%[^ /] /bool=%d", parName, &num)==2){ ParIsVolatileName (parName); ParDefBool (parName, num); } else if (sscanf (file.ln, "#par /name=%[^ /] /real=%f", parName,&real)==2){ ParIsVolatileName (parName); ParDefReal (parName, real); } else if ((rv = (sscanf(file.ln, "#par /name=%[^ /] /str=%[^\n]", parName, str))) >= 1) { ParIsVolatileName (parName); if (rv == 2) ParDefStr (parName, str); else ParDefStr (parName, ""); } else _ErrMsg2 (e__novalformat, file.ln); FilURead (&file); } FilUClose (&file); return 1; } /**api* ParPrintNext ********************************************************** ** ** prints the next (or first if context=0) parameter in various formats; ** ** INPUT: output file [W] ** address of context [W] ** IMPLICIT: ** ** RETURNS: 1 if successful ** 0 if last parameter was reached */ INT4 ParPrintNext (FILE *file, INT4 *context, char *option) { static PARo *par=NULL; if (!*context || !par) { par = parTable->par; LstFirst ((void **) &par); *context = 1; } else if (!LstNext ((void **) &par)) { *context = 0; /* list is exhausted */ par = NULL; return 0; } while (1) { if (par->isVolatile) return 1; else if (par->type & PARxBOOL ) { fprintf (file, "#par /name=%s /bool=%d\n", par->name, par->num); break; } else if (par->type & PARxSTR ) { fprintf (file, "#par /name=%s /str=%s\n", par->name, par->str); break; } else if (par->type & PARxNUM ) { fprintf (file, "#par /name=%s /num=%d\n", par->name, par->num); break; } else if (par->type & PARxREAL ) { fprintf (file, "#par /name=%s /real=%f\n", par->name, par->real); break; } else { if (!LstNext ((void **) &par)) { *context = NULL; par = NULL; return 0; } } } return 1; } ************************************************************** ** ** $RCSfile: par.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/07/14 16:21:24 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** */ enum par_type {PARxNEW=0, PARxSTR=1, PARxNUM=2, PARxREAL=4, PARxFUNCTION=8, PARxBOOL=16, PARxOBJECT=32}; #define PARxPARNOTDEF 100000 #define PARxPARNULL 99999 #define PARxON 1 #define PARxOFF 0 #ifndef _PARoTABLE typedef struct PARoLIST *dummytointroducestructtagPARoLIST; #endif #ifndef PARoTABLE typedef struct PARoTABLE *dummytointroducestructtagPARoTABLE; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ /* acting on the parameter table */ void ParInit (struct PARoLIST *parList); INT4 ParIsModified (); void ParDumpAll (); INT4 ParRead (char *fileName); void ParSave (char *fileName); INT4 ParPrintNext (FILE *file, INT4 *context, char *option); INT4 ParDelete (char *parName); INT4 ParDeleteMatch (char *reStr); struct PARoTABLE *ParSetTable (char *name, char *upName, char *option); void ParDeleteTable (char *name); struct PARoTABLE *ParUnsetTable (); struct PARoTABLE *ParGetTable (char *name); /* define parameters */ INT4 ParDefNum (char *par_nm, INT4 num); INT4 ParDefBool (char *par_nm, INT4 num); INT4 ParDefReal (char *par_nm, float real); INT4 ParDefStr (char *par_nm, char *str); INT4 ParDefFunction (char *par_nm, INT4 (*function) ()); INT4 ParDefObject (char *par_nm, void *object); /* retrieve parameter values */ INT4 ParGetNum (char *par_nm); INT4 ParGetBool (char *parName); float ParGetReal (char *par_nm); char *ParGetStr (char *par_nm); INT4 (*ParGetFunction (char *par_nm))(); void *ParGetObject (char *par_nm); INT4 ParIsDefinedF(char *strfmt, ...); INT4 ParGetNumF(char *strfmt, ...); INT4 ParGetBoolF(char *strfmt, ...); char *ParGetStrF(char *strfmt, ...); INT4 ParDeleteF (char *strfmt, ...); INT4 ParDefStrF (char *parName, char *strfmt, ...); /* get a pointer to parameter of various types */ struct PARo *ParGetRead (char *parName, struct PARoTABLE *table); struct PARo *ParGetWrite (char *parName, struct PARoTABLE *table); struct PARo *ParFind (char *parName); struct PARo *ParGetDefault (char *parName); struct PARo *ParNextValue (struct PARo *par, INT4 *context); struct PARo *ParGetNeighbour (char *parName); /* info from parameter using parameter pointer */ INT4 ParOGetState (struct PARo *par); char *ParOGetHelpTopic (struct PARo *par); char *ParOGetComment (struct PARo *par); char *ParOGetKey (struct PARo *par); char *ParOGetCharSet (struct PARo *par); INT4 ParOGetType (struct PARo *par); INT4 ParOGetNum (struct PARo *par); char *ParOGetStr (struct PARo *par); float ParOGetReal (struct PARo *par); INT4 (*ParOGetFunction (struct PARo *par))(); void *ParOGetObject (struct PARo *par); /* manipulate parameter using parameter pointer */ void ParODefState (struct PARo *par, INT4 state); void ParODefHelpTopic (struct PARo *par, char *helpTopic); void ParODefComment (struct PARo *par, char *comment); void ParODefKey (struct PARo *par, char *key); void ParODefCharSet (struct PARo *par, char *charSet); void ParODefType (struct PARo *par, char *parTypeName); INT4 ParODefNeighbour (struct PARo *par, char *parName); void ParODefValue (struct PARo *par, struct PARo *valPar); INT4 ParODefNum (struct PARo *par, INT4 num); INT4 ParODefStr (struct PARo *par, char *str); INT4 ParODefReal (struct PARo *par, float real); INT4 ParODefFunction (struct PARo *par, INT4 (*function) ()); INT4 ParODefObject (struct PARo *par, void *object); /* others */ INT4 ParIsDefined (char *par_nm); void ParUnlock (char *parName); void ParLock (char *parName); void ParSetVolatile (char *parName); #include #include #include "def.h" #include "print.h" #include "oldlistbuf.h" #include "string.h" /***************************************************************** ** IMPLEMENTATION utilities */ PRINTv Active[20]; PRINTv* LastActive=Active; PRINTv Printer=NULL; void NoFormat(PRINTv out, char command, ...) { /* command does nothing */ } void PushPrinter() { *(LastActive++)=Printer; } void PopPrinter() { Printer=*(--LastActive); } PRINTv CopyPrinter(PRINTv p) { p->usage++; return p; } /***************************************************************** ** API functions - no context */ void xPrintBuf(PRINTv out, BYTE* buf, int n) { do { int want=n; BYTE* s=call(out->book)(out, &want); n-=want; while (want--) *s++=*buf++; } while (n); } void xPrintClose(PRINTv* out) { PRINTv p=*out; if (!--p->usage) {call (p->close) (p, NULL, 0); } *out=NULL; } void xPrintBufClose(PRINTv* out, BYTE* s, int n) { PRINTv p=*out; if (!--p->usage) call (p->close) (p, s, n); *out=NULL; } void xPrintFormat(PRINTv out, char comm, ...) { va_list l; va_start(l, comm); call (out->format)(out, comm, l); va_end(l); } void xPrintInt(PRINTv out, int i) { char buf[20]; char* p=buf; xPrintFormat(out, '['); sprintf(buf, "%d", i); while (*p) xPrint(out, *p++); xPrintFormat(out, ']'); } void xPrintS(PRINTv out, char* s) { xPrintFormat(out, '['); xPrintBuf(out, s, strlen(s)); xPrintFormat(out, ']'); } void xPrintStr(PRINTv out, STRv s) { xPrintS(out, Str(s)); } /***************************************************************** ** API functions - contextual */ PRINTv PrintGet() { Printer->usage++; return Printer; } void PrintClose() { xPrintClose(&Printer); PopPrinter(); } void PrintBufClose(BYTE* s, int n) { xPrintBufClose(&Printer, s, n); PopPrinter(); } void PrintBuf(BYTE* buf, int n) { xPrintBuf(Printer, buf, n); } void PrintInt(int i) { xPrintInt(Printer, i); } void PrintS(char* s) { xPrintS(Printer, s); } void PrintStr(STRv s) { xPrintStr(Printer, s); } void PrintFormat(char comm, ...) { va_list l; va_start(l, comm); call (Printer->format)(Printer, comm, l); va_end(l); } /************************************************************ ** output to STRING */ /* string writer */ #define PRINT_BUF_DIM 256 typedef struct PRINToBUF { BYTE buf[PRINT_BUF_DIM]; struct PRINToBUF* next; } PRINToBUF; /* buffered string writer */ typedef struct PRINToSTR { PRINTo head; STRv* dest; BYTE* pos; BYTE* stop; PRINToBUF* beg; PRINToBUF* buf; int len; } PRINToSTR; /************************************************************ ** BUFFERED output to string */ void PrintBufOverflow(PRINToSTR* out) { /* allocate new buffer */ BYTE* s; PRINToBUF* buf=typeAlloc(PRINToBUF); buf->next=NULL; out->buf->next=buf; out->buf=buf; s=buf->buf; out->pos=s; out->stop=s+PRINT_BUF_DIM; out->len+=PRINT_BUF_DIM; } void StrPrintBufPut(PRINToSTR* out, BYTE c) { if (out->pos!=out->stop) *(out->pos++)=c; else { PrintBufOverflow(out); *(out->pos++)=c; } } BYTE* StrPrintBufBook(struct PRINToSTR* out, int* n) { BYTE* s=out->pos; if (s+*nstop) { out->pos+=*n; return s; } else if (s!=out->stop) { /* ask to fill buffer */ *n=out->stop-s; out->pos=out->stop; return s; } else { PrintBufOverflow(out); return StrPrintBufBook(out, n); } } void StrPrintBufClose(struct PRINToSTR* out, BYTE* src, int n) { int lastLen=out->pos - out->buf->buf; int dlen=out->len+lastLen; STRv val=*out->dest; BYTE* s; PRINToBUF *buf, *next; /* reallocate the string */ if (val) { int len=val->len; StrBufChange(&val,len,len+dlen); s=val->arr+len; } else { val=StrBufNew(dlen); val->len=dlen; s=val->arr; *(s+dlen)='\0'; } *out->dest=val; /* now copy the BYTEs from the buffers */ buf=out->beg; while ((next=buf->next)) { memcpy(s, buf->buf, PRINT_BUF_DIM); free(buf); buf=next; s+=PRINT_BUF_DIM; } /* copy last (not full) buffer */ memcpy(s, buf->buf, lastLen); free(buf); /* kill myself */ free(out); } /*************************************************************** ** UNBUFFERED output to string */ void PrintStrOverflow(PRINToSTR* out) { /* string space exceeded: go to buffered management */ BYTE* s; PRINToBUF* buf; STRv val=*out->dest; if (val) val->len=(char *)out->pos-val->arr; out->head.put=(Putter)StrPrintBufPut; out->head.book=(Booker)StrPrintBufBook; out->head.close=(Closer)StrPrintBufClose; buf=typeAlloc(PRINToBUF); buf->next=NULL; out->beg=out->buf=buf; s=buf->buf; out->pos=s; out->stop=s+PRINT_BUF_DIM; out->len=0; } void PrintStrPut(PRINToSTR* out, BYTE c) { if (out->pos!=out->stop) *(out->pos++)=c; else { PrintStrOverflow(out); *(out->pos++)=c; } } BYTE* PrintStrBook(struct PRINToSTR* out, int* n) { BYTE* s=out->pos; if (s+*nstop) { out->pos+=*n; return s; } else if (s!=out->stop && *out->dest) { /* ask to fill string */ *n=out->stop-s; out->pos=out->stop; return s; } else { PrintStrOverflow(out); return StrPrintBufBook(out, n); } } void PrintStrClose(struct PRINToSTR* out, BYTE* src, int n) { BYTE* s=out->pos; STRv val=*out->dest; if (val) { int len; *s='\0'; len=val->len=(char *)s-val->arr; StrBufChange(&val, len, len+n); memcpy(val->arr+len, src, n); } else { val=StrBufNew(n); val->len=n; memcpy(val->arr, src, n); } *out->dest=val; free(out); } void PrintOpenStr(STRv* out) { PRINToSTR* s=typeAlloc(PRINToSTR); STRv val=*out; PushPrinter(); Printer=(PRINTv)s; s->head.usage=1; s->dest=out; s->head.put=(Putter)PrintStrPut; s->head.book=(Booker)PrintStrBook; s->head.close=(Closer)PrintStrClose; s->head.format=(Formatter)NoFormat; if (val->usage==1 && val->lendim) { s->pos=val->arr; s->stop=val->arr+val->dim; } else { StrDel(val); *out=NULL; s->pos=s->stop=NULL; } } /************************************************************ ** output to FILE */ /* file writer */ #define PRINT_FILE_DIM 256 typedef struct PRINToFILE { PRINTo head; FILE* dest; BYTE buf[PRINT_FILE_DIM]; int num; } PRINToFILE; void PrintFilePut(struct PRINToFILE* out, BYTE c) { if (out->num) { fwrite(out->buf, 1, out->num, out->dest); out->num=0; } putc(c, out->dest); } BYTE* PrintFileBook(struct PRINToFILE* out, int* n) { if (out->num) fwrite(out->buf, 1, out->num, out->dest); if ((out->num=*n)>PRINT_FILE_DIM) out->num=*n=PRINT_FILE_DIM; return out->buf; } void PrintFileClose(struct PRINToFILE* out, BYTE* src, int n) { if (out->num) fwrite(out->buf, 1, out->num, out->dest); fwrite(src, 1, n, out->dest); fclose(out->dest); free(out); } void PrintOpenFileImpl(FILE* file) { PRINToFILE* s=typeAlloc(PRINToFILE); PushPrinter(); Printer=(PRINTv)s; s->head.usage=1; s->dest=file; s->head.put=(Putter)PrintFilePut; s->head.book=(Booker)PrintFileBook; s->head.close=(Closer)PrintFileClose; s->head.format=(Formatter)NoFormat; s->num=0; } void PrintOpenFile(char* fileName) { PrintOpenFileImpl(fopen(fileName, "wb")); } void PrintStdoutClose(struct PRINToFILE* out, BYTE* src, int n) { if (out->num) fwrite(out->buf, 1, out->num, out->dest); fwrite(src, 1, n, out->dest); free(out); } void PrintOpen() { PrintOpenFileImpl(stdout); Printer->close=(Closer)PrintStdoutClose; } /*************************************************************** ** PRETTY PRINTING filter */ /* parses the result, pretty-printing it ** breakAt suggests where to cut lines (no indentation) ** indent, unindent are matching pairs */ #define PRETTY_MASK 0xFF #define PRETTY_BUF_SIZE (PRETTY_MASK+1) #define PRETTY_NOEND 0x7FFF typedef struct PRETTYoBLOCK { LISTBUFv comm; struct PRETTYoBLOCK* up; int end; BOOL broken; } PRETTYoBLOCK; typedef struct PRETTYoCOMMAND { char command; int start; struct PRETTYoBLOCK* block; } PRINToCOMMAND; LISTBUFoINFO PrettyCommandListInfo = { sizeof(PRINToCOMMAND) }; /*CLASSoLISTBUF PrettyCommandListInfo= { sizeof(PRINToCOMMAND), sizeof(LISTBUFo), DefElemCopier, DefElemDeleter, 0, NoHeadCopier, NoHeadDeleter, 0 };*/ typedef struct PRINToPRETTY { /* global state */ PRINTo head; PRINTv out; char line[256]; int width; int minWidth; int step; /* state of delayed output */ int last; int lastIndent; int lastBreak; struct PRETTYoBLOCK* lastBlock; /* state of current output */ int pos; struct PRETTYoBLOCK* currBlock; } PRINToPRETTY; PRINToPRETTY* PrettyCx; /********************************************************************** ** the real printing.. */ void PrettyIndent() { int num=PrettyCx->lastIndent; PRINTv out=PrettyCx->out; PrettyCx->lastBreak=PrettyCx->last+PrettyWidth()-PrettyCx->lastIndent; call (out->put)(out, '\n'); do { int want=num; BYTE* s=call(out->book)(out, &want); num-=want; while (want--) *s++=' '; } while (num); } void PrettyOut(PRINTv out, char c) { if (c=='\n') PrettyIndent(); else call(out->put)(out, c); } /********************************************************************** ** INDENTATION MANAGEMENT */ int PrettyWidth() { if (PrettyCx->width-PrettyCx->lastIndentminWidth) return PrettyCx->lastIndent+PrettyCx->minWidth; else return PrettyCx->width; } BOOL PrettyInNextLine() { int nextWidth=PrettyWidth()-PrettyCx->lastIndent; if (PrettyCx->lastBlock->end-PrettyCx->last<=nextWidth) { PrettyIndent(); return TRUE; } return FALSE; } void PrettyCommand(char command) { switch(command) { case 'N': { PrettyIndent(); } break; case 'I': { PrettyCx->lastIndent += PrettyCx->step; } break; case 'U': { PrettyCx->lastIndent -= PrettyCx->step; } break; } } /*********************************************************************** ** BLOCK PRINTING MANAGEMENT */ void PrettySkip(PRETTYoBLOCK* bl) { Iter comm=bl->comm; PRINToCOMMAND* curr; while (curr=ListBufNext(&bl->comm, &comm)) { if (curr->command=='[') { PrettySkip(curr->block); free(curr->block); } } } BOOL PrettyBlock() { PRETTYoBLOCK* bl=PrettyCx->lastBlock; PRINTv out=PrettyCx->out; BOOL doBreak=TRUE; if (!bl->broken) { if (bl->end==PRETTY_NOEND) { if (PrettyCx->poslastBreak) return FALSE; } else if (bl->endlastBreak || PrettyInNextLine()) doBreak=FALSE; } if (doBreak) { PRINToCOMMAND* curr; Iter comm=NULL; bl->broken=TRUE; comm=ListBufFirst(&bl->comm); while (comm) { curr=(PRINToCOMMAND*)ListBufAt(&bl->comm,comm); while (PrettyCx->last!=curr->start) { if (PrettyCx->last==PrettyCx->pos) return FALSE; if (PrettyCx->last==PrettyCx->lastBreak) PrettyIndent(); PrettyOut(out,PrettyCx->line[PrettyCx->last++&PRETTY_MASK]); } if (curr->command=='[') { PrettyCx->lastBlock=curr->block; ListBufRemove(&bl->comm, &comm); if (!PrettyBlock()) return FALSE; } else { PrettyCommand(curr->command); ListBufRemove(&bl->comm, &comm); } } /* finish block */ while (PrettyCx->last!=bl->end) { if (PrettyCx->last==PrettyCx->pos) return FALSE; if (PrettyCx->last==PrettyCx->lastBreak) PrettyIndent(); PrettyOut(out, PrettyCx->line[PrettyCx->last++&PRETTY_MASK]); } } else { /* if new block fits in PrettyCx->line, print it all */ while (PrettyCx->lastend) PrettyOut(out, PrettyCx->line[PrettyCx->last++&PRETTY_MASK]); PrettySkip(bl); } PrettyCx->lastBlock=bl->up; ListBufDelete(&bl->comm); free(bl); return TRUE; } /**************************************************************** ** PRINTING API */ void PrintPrettyPut(struct PRINToPRETTY* out, BYTE c) { if (out->pos>out->last+out->width) { /* print line, formatting it */ PrettyCx=out; while (PrettyBlock()); } out->line[out->pos++&PRETTY_MASK]=c; } BYTE* PrintPrettyBook(struct PRINToPRETTY* out, int* n) { int avail, pos, toBufEnd; if (out->pos>out->last+out->width) { /* print line, formatting it */ PrettyCx=out; while (PrettyBlock()); } avail=(out->last-out->pos)&PRETTY_MASK; if (!avail) avail=PRETTY_BUF_SIZE; toBufEnd=PRETTY_BUF_SIZE-(out->pos&PRETTY_MASK); if (avail>toBufEnd) avail=toBufEnd; if (*n<=avail) { pos=out->pos; out->pos+=*n; return out->line+(pos&PRETTY_MASK); } else { *n=avail; pos=out->pos; out->pos+=avail; return out->line+(pos&PRETTY_MASK); } } void PrintPrettyFlush(struct PRINToPRETTY* out); void PrintPrettyFormat(struct PRINToPRETTY* out, char command, ...) { PRINToCOMMAND c; switch (command) { case ']': { out->currBlock->end=out->pos; out->currBlock=out->currBlock->up; } break; case '[': { PRETTYoBLOCK* bl=typeAlloc(PRETTYoBLOCK); bl->up=out->currBlock; ListBufCreate(&bl->comm,&PrettyCommandListInfo,5); bl->end=PRETTY_NOEND; bl->broken=FALSE; c.command=command; c.start=out->pos; c.block=bl; if (out->currBlock) ListBufAppend(&out->currBlock->comm, &c); out->currBlock=c.block; } break; case 'I': case 'U': case 'N': { c.command=command; c.start=out->pos; if (out->currBlock) ListBufAppend(&out->currBlock->comm, &c); } break; case 'F': { PrintPrettyFlush(out); PrintPrettyFormat(out, '['); out->lastBlock=out->currBlock; } break; default: { va_list l; va_start(l, command); call(out->out->format)(out->out,command, l); va_end(l); } } } void PrintPrettyFlush(struct PRINToPRETTY* out) { PrettyCx=out; while (out->currBlock) PrintPrettyFormat(out,']'); while (out->lastBlock) PrettyBlock(); } void PrintPrettyClose(struct PRINToPRETTY* out, BYTE* src, int n) { while (n) { int want=n; BYTE* s=PrintPrettyBook(out, &want); n-=want; } /* flush now */ xPrintBuf((PRINTv)out, src, n); PrintPrettyFlush(out); xPrintClose(&out->out); free(out); } PRINToPRETTY* PrintPrettyImpl(int width, int minWidth, int step) { PRINToPRETTY* p=PrettyCx=typeAlloc(PRINToPRETTY); p->head.usage=1; p->head.put=(Putter)PrintPrettyPut; p->head.book=(Booker)PrintPrettyBook; p->head.close=(Closer)PrintPrettyClose; p->head.format=(Formatter)PrintPrettyFormat; p->width=width; p->minWidth=minWidth; p->step=step; p->pos=0; p->currBlock=NULL; PrintPrettyFormat(p,'['); p->last=0; p->lastIndent=0; p->lastBreak=p->width; p->lastBlock=p->currBlock; return p; } void PrintPretty(int width, int minWidth, int step) { PRINToPRETTY* p=PrintPrettyImpl(width, minWidth, step); p->out=Printer; Printer=(PRINTv)p; } void xPrintPretty(PRINTv* out, int width, int minWidth, int step) { PRINToPRETTY* p=PrintPrettyImpl(width, minWidth, step); p->out=*out; *out=(PRINTv)p; } /************************************************************************/ #define _MYSTREAM_H #include "strv.h" typedef struct PRINTo* PRINTv; typedef void (*Putter)(PRINTv out, BYTE c); typedef BYTE* (*Booker)(PRINTv out, int* n); typedef void (*Closer)(PRINTv out, BYTE* src, int n); typedef void (*Formatter)(PRINTv out, char command, ...); typedef struct PRINTo { int usage; Putter put; Booker book; Closer close; Formatter format; } PRINTo; extern PRINTv Printer; /* PUBLIC OPERATIONS */ /* stream management operations */ void PrintOpen(); void PrintOpenStr(STRv* out); void PrintOpenFile(char* fileName); /* gets an external copy of the current stream */ PRINTv PrintGet(); /* contextual operations */ void PrintPretty(int width, int minWidth, int step); void PrintClose(); void PrintBufClose(BYTE* s, int n); void PrintFormat(char command, ...); #define Print(char) call(Printer->put)(Printer,char) void PrintBuf(BYTE* buf, int n); void PrintS(char* s); void PrintStr(STRv s); void PrintInt(int i); /* not contextual operations */ void xPrintPretty(PRINTv* out, int width, int minWidth, int step); void xPrintClose(PRINTv* out); void xPrintBufClose(PRINTv* out, BYTE* s, int n); void xPrintFormat(PRINTv out, char comm, ...); #define xPrint(out, char) call(out->put)(out, char) void xPrintBuf(PRINTv out, BYTE* buf, int n); void xPrintInt(PRINTv out, int i); void xPrintS(PRINTv out, char* s); void xPrintStr(PRINTv out, STRv s); #endif char query_srs_ID[] = "$Id: query.c,v 1.8 1996/08/12 19:03:46 etzold Exp $"; /* ** ** $RCSfile: query.c,v $ ** $Revision: 1.8 $ ** $Date: 1996/08/12 19:03:46 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port by Lukas Rosenthaler and Reinhard ** ** Author: Gerald Schaefer ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387372 ** Email: schaefer@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "lst.h" #include "strv.h" #include "par.h" #include "regexp.h" #include "ids.h" #include "btree.h" #include "tm.h" #include "library.h" #include "id.h" #include "entry.h" #include "set.h" #include "link.h" #include "seqlib.h" #include "query.h" #include "icarus.h" #include "icaarg.h" #define _CONSTANTS #define _SRS #define _SLB #define _INDEX #include SRSINCLUDE #ifdef sun extern INT4 printf (); #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** constants and enums */ #define QRYxXFIL 10 /* max no of indices opened */ #define QRYxXSNLN 255 #define QRYxXSYM 300 /* max no of tokens in token list */ #define QRYxXST 3000 /* max no of characters allocated for token list */ enum qry_tok {QRYxKEY=1, QRYxNAME, QRYxINDEX, QRYxLPAR, QRYxRPAR, QRYxLBRK, QRYxRBRK, QRYxOP}; /* all token types in the query */ #define QRYxSETOP 32 /* log op have 6th + 4th bit set */ #define QRYxLINK 16 /* link op have 5th + 4th bit set */ #define QRYxLLINK 24 #define QRYxRLINK 25 #define QRYxOR 40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Describes the external parameter context which determines the ** 'behaviour' of this module. */ typedef struct QUERYoInfo { char doReport; char doListValues; char doRetrieve; char isErrWrongField; char isWWW; Int4 valN; Int4 maxValN; Int4 minValN; Int4 printValN; Int4 printFirstValN; } QUERYoInfo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ INT4 QueryRangeSearchIndex (SLBo *lib, SLBoFIELD *field, INT4 low, INT4 high, double lowReal, double highReal, INT4 isReal, INT4 isLE, INT4 isRE, INT4 isFirst, INT4 isLast, SETo *set); static INT4 QueryGet ( LIBoINDEX *openinx, SETo *set_p, char *key); static INT4 QueryGetWild (LIBoINDEX *libIndex, SETo *set, char *str, char *wildStr, INT4 cmpLen); static INT4 QryCollectIds (SETo *set, LIBoINDEX *libInx, BTRoREC *record, FIP idFip); static INT4 QryGoGcgDots (FILo *file); static INT4 QrySetSearch (char *s); static INT4 QryKey (char *set_nm); static INT4 QryRetrieveRange (LIBoINDEX *libIndex, SETo *set); static INT4 QryIndexRetrieve (SLBo *lib, SRSoFLD *fieldType, SETo *set); static SETo* QueryDo (char *s, char *name, INT4 isRecursive); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external, global and module wide variables */ static SETo* resultSet = NULL; static QUERYoInfo queryInfoBuff; static QUERYoInfo* queryInfo=&queryInfoBuff; static INT4 (*print)(char *, ...); void (*QueryPrintValue)()=NULL; /* prints information if result_name is a set */ /* returns: 1 if set, 0 if none */ int dump_info(char *result_name) { SETo *set; set = (SETo*) SetGet(result_name); if (set) { printf("*** Set \"%s\": total of %d entries ***\n", result_name ,set->n); return 1; } return 0; } #define NAMELEN 40 typedef char FILENAME[FILxXNAM+1]; #define MAXNAMES 20 void QuerySetPrintValue (void (*func)()) { if (func) QueryPrintValue = func; } static INT4 qryprintferr (char *ln,...) { va_list ap; va_start (ap, ln); vfprintf (stderr, ln, ap); va_end (ap); return 1; } INT4 QryCheck () { } INT4 QryMakeWild () { } INT4 QryInit () { } INT4 QryRetrieve () { } INT4 QryParse () { } INT4 QryTransformQuery() { } INT4 QryDo (char *query, char *set_nm) { return 1; } /****** QueryGet ************************************************************** ** ** searches a key in index and retrieves block of pointers; ** ** INPUT: index object [W] ** set object [W] ** search value [R] ** IMPLICIT: ** ** RETURNS: 1 if key found ** 0 if not */ static INT4 QueryGet ( LIBoINDEX *libInx, SETo *set, char *value) { BTRoREC *record; FIP idFip; if ((record = BtrSearch (libInx->btree, value, &idFip, 0))) { QryCollectIds (set, libInx, record, idFip); return 1; } else return 0; } /****** QueryGetWild ************************************************************ ** ** same as QryGet but takes keys with wildcard at end; ** ** INPUT: address of index-descriptor [W] ** address of set-descriptor [W] ** address of search key [R] ** length of string before wildcard [R] ** IMPLICIT: ** ** RETURNS: 1 if key found ** 0 if not */ static INT4 QueryGetWild (LIBoINDEX *libInx, SETo *set, char *str, char *regexpStr, INT4 cmpLen) { regexp *regExp; BTRoREC *record; FIP idFip; SETo *setTmp; char tmpStr[133]; char setName[SETxXNAM+1]; INT4 rv, maxValN, valCount=0; /* ** compile the regular expression and get the first record to start ** the search */ regExp = RegComp (regexpStr); if (regExp == NULL) _ErrRet2 (e__regerror, "regcomp failure"); if ((--cmpLen)) { /* is 1 if wildcard is at begin ...set to 0 */ if (!(record = BtrSearch (libInx->btree, str, &idFip, cmpLen))) return 0; } else if (!(record = BtrRecordGet (libInx->btree, BTRxFIRST))) return 0; /* ** now iterate over this and following records and try to match ** regular expression */ while (1) { strcpy (tmpStr, record->str); SmEdit (tmpStr, SMxLOWCASE); if ((cmpLen) && memcmp (tmpStr, str, cmpLen) != 0) break; /* string begin not found any more */ if (queryInfo->valN > queryInfo->printValN) break; if (RegExec (regExp, tmpStr)) { if (queryInfo->doRetrieve) setTmp = SetNew (setName, "temp"); QryCollectIds (setTmp, libInx, record, idFip); if (queryInfo->doRetrieve) { rv = SetOp (set, setTmp, NULL, QRYxOR); SetDelete (setName); _ErrRet(rv); } } idFip++; /* next entries idFip...if ID index */ if (!(record = BtrRecordGet (libInx->btree, BTRxNEXT))) break; /* no more records */ } free (regExp); return 1; } /****** QryCollectIds ********************************************************* ** ** retrieves id-descriptor in index-file, accesses the ids-file ** and retrieves all ids; ** ** INPUT: library index object [R] ** value record [R] ** set object [W] ** IMPLICIT: ** ** RETURNS: 1 if success */ static INT4 QryCollectIds (SETo *set, LIBoINDEX *libInx, BTRoREC *record, FIP idFip) { BTRoVALUE *valRec; INT4 n; if (queryInfo->doListValues) { n = record->r.value.idN; if (queryInfo->minValN <= n) { if (++queryInfo->valN >= queryInfo->printFirstValN) { if (QueryPrintValue) QueryPrintValue (LibName (libInx->lib), LibGetFieldName (libInx->field), record->str, queryInfo->valN - queryInfo->printFirstValN+1, n); else TemplPrint ("value", record->str, n); } } if (!queryInfo->doRetrieve) return; } set->id_d = libInx->field->indexId; valRec = &record->r.value; _ErrStop (SetAlloc (set, valRec->idN, set->id_d)); IdsGet (libInx->idsFile, set->id_p, valRec->firstIdFip, valRec->idN); set->n = valRec->idN; return 1; } /****** QryCheckNam *********************************************************** ** ** checks a name within an expression ** ** INPUT: address of name [R] ** IMPLICIT: ** ** RETURNS: 1 if ok ** 0 if not */ INT4 QryCheckNam (char *nam) { return SetTestName (nam); } INT4 QryReadName (SETo *set, char *ln) { return 1; } INT4 QryReadNames (char *fil_nm, char *set_nm) { return 1; } /**API* QrySetToList ********************************************************** ** ** Prints a set as a list of entry names which can be read again ** by "QryReadNames". The format is compatible with the ** GCG file of names. If the global boolean parameter "fosnWithPos" ** is set to 1 and the set contains subentry-IDs (sequence features) ** then the begin and end positions within the parent entry's sequence ** are added. ** function prints to STDOUT unless a print function is defined using ** the global parameter "printf". ** ** INPUT: set name [R] ** IMPLICIT: ** ** RETURNS: no of entries printed ** e__novalnam + */ INT4 QrySetToList (char *set_nm) { SETo *set; ENTRYo *entry; IDoENTRY id; char hexnumstr[20], source_nm[40], ln[133]; INT4 k,(*print)(char*, ...)=(INT4(*)(char*,...))ParGetFunction("printf"); if ((set = SetGet (set_nm)) == NULL) _ErrRet2 (e__novalnam, set_nm); /* ** get for every ID in the set the logical name of the flat file (GCG) or the ** library ..or if not available just the library name, the entry name ** and the hexnum string of the entry ID and write them out; */ for (k=1; k <= set->n; k++) { SetGetID (set, k, &id); entry = EntryOpen (&id); IdToStr (&id, hexnumstr); EntrySourceName (entry, source_nm); if (IdIsSub (entry->id) && ParGetBool ("fosnWithPos")) ;/*SlbGetFeature (entry, NULL, NULL);*/ else { sprintf (ln, "%s:%s ! ID: %s\n", source_nm, entry->entry_nm, hexnumstr); if (!(*print) (ln)) break; } EntryClose (&entry); } return k-1; } /**API* QryLinkOne ************************************************************ ** ** Links a single one entry-ID to a library. ** ** INPUT: o address of ID object [R] ** o library name [R] ** o name of result set [W] if NULL string then a name is ** created and written into char array ** IMPLICIT: ** ** RETURNS: ** 1 ** output set name exists: e__namnotunique + */ INT4 QryLinkOne (IDoENTRY *id, char *lib_nm, char *out_nm) { SETo *tmp, *outset; char tmp_nm[QRYxXNAM+1]; INT4 rv; /* ** new set that contains the one ID to be linked */ tmp = SetNew (tmp_nm, "temp"); tmp->id_p = id->id; tmp->n = 1; rv = SetMakeOwn (tmp, id->id_d); _ErrRet(rv); /* ** create output set - name can be optionally supplied but must be unique */ if (*out_nm == '\0') outset = SetNew (out_nm, "temp"); else if (!(outset = SetNew (out_nm, NULL))) return 0; /* ** do the link, delete temporary set and output set if link was not ** successful */ LinkMap (lib_nm, tmp_nm, outset); SetDelete (tmp_nm); if (outset->n) return 1; else { SetDelete (out_nm); return 0; } } #ifdef xxx /**API* QryFindID ************************************************************* ** ** Retrieves a single entry from specified library by searching a word ** in the specified index. ** Returns first ID of the set. This function should be only applied ** where no more than one entry can be found (eg, searching entry names, ** primary accession numbers). ** ** INPUT: name of library [R] ** name of data-field [R] ** search word [R] ** IMPLICIT: ** ** RETURNS: address of ID object ** NULL if no success */ IDoENTRY *QryFindID (char *libName, char *fieldName, char *word) { static IDoENTRY id, *idPtr=NULL; char query[1024], *setName = "__fromQueryFindId__"; if (!LibGetLibGroup (libName, NULL, NULL)) { _ErrMsg3 (e__unknownnam, "Library", libName ); return NULL; } if (LibGetFieldType (libName, fieldName) == NULL) { _ErrMsg3 (e__namnotdef, "Index", fieldName); return NULL; } sprintf (query, "[%s-%s:%s]", libName, fieldName, word); if (QryDo (query, setName)) { SetGetID (SetGet (setName), 1, &id); idPtr = &id; } SetDelete (setName); return idPtr; } #endif /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /***** QuerySetBehave ********************************************************* ** ** Populates the "queryInfo" object with flags determining the behaviour ** of some of the functions in this module which is determined by ** the global parameters (module "par"). ** ** INPUT: ** IMPLICIT: ** queryInfo (QUERYoInfo *) [W] ** */ static void QuerySetBehave () { queryInfo->isWWW = ParGetBool ("isHTMLFormat") ? 1 : 0; if (ParGetBool ("queryDoReport")) queryInfo->doReport = 1; if (ParGetBool ("queryListValues")) { queryInfo->doListValues = 1; queryInfo->doRetrieve = 0; } else queryInfo->doRetrieve = 1; queryInfo->printFirstValN = ParGetNum ("printIndexFirstValN") ? ParGetNum ("printIndexFirstValN") : 1; queryInfo->valN = 0; queryInfo->maxValN = ParGetNum ("maxIndexValN"); queryInfo->minValN = ParGetNum ("minIndexValN"); if (!ParGetNum ("printIndexValN")) queryInfo->printValN = 2000000000; /* max number will never be reached */ else queryInfo->printValN = ParGetNum ("printIndexValN") + queryInfo->printFirstValN; } /**API* QueryMakeWild ********************************************************* ** ** Adds wildcards ('*') to the search strings of the query if the ** parameter "makeWild" is ON. ** ** INPUT: STRv with query string [W] ** ** RETURNS: query string with wildcards added */ char *QueryMakeWild (STRv *s) { static ICAoSYNTAX *syntax=NULL; static ICAoJOB *job=NULL; if (!syntax) { syntax = (ICAoSYNTAX *) LibObjByName ("syntax", "makeWild"); job = IcaCreateJob (syntax); } IcaJobSetString (job, _Str(*s)); IcaDoJob (job, "query"); StrSetS (s, IcaGetInputString (job)); IcaEndJob (job); return _Str (*s); } /**api* Query ***************************************************************** ** ** Performs the specified query. If no query name is specified a ** unique temporary name will be used. ** ** INPUT: the SRS query string [R] ** the query name (or NULL) [R] ** ** RETURNS: */ SETo *Query (char *s, char *name) { SETo *set; QuerySetBehave (); set = QueryDo (s, name, 0); return (set && set->n) ? set : NULL; } SETo *QueryRecursive (char *s, char *name) { return QueryDo (s, name, 1); } static SETo *QueryDo (char *s, char *name, INT4 isRecursive) { static ICAoSYNTAX *syntax=NULL; static ICAoJOB *jobStatic=NULL; static INT4 uniqueSetN=0; SETo *resultSetSave, *tmp; ICAoJOB *job; char uniqueName[100]; if (!syntax) { syntax = (ICAoSYNTAX *) LibObjByName ("syntax", "srsquery"); jobStatic = IcaCreateJob (syntax); } if (isRecursive) { resultSetSave = resultSet; job = IcaCreateJob (syntax); } else job = jobStatic; if (!name) { sprintf (uniqueName, "Q_%d", ++uniqueSetN); name = uniqueName; } resultSet = SetNew (name, NULL); IcaJobSetString (job, s); if (queryInfo->doListValues) TemplPrint ("head"); IcaDoJob (job, "query"); IcaEndJob (job); tmp = resultSet; if (queryInfo->doListValues) TemplPrint ("tail", SetGetQueryStr (name)); if (isRecursive) resultSet = resultSetSave; return tmp; } void QuerySetGet () { LINKo *link; SLBo *lib; SETo *set; Int4 isLink, c; char name[132]; IargGetArgs ("name", name); if (!(set = SetGet (name))) { if (!(lib = (SLBo *) LibObjByName ("library", name)) && !SmEqs (name, "parent")) { for (c=0, isLink=0; (link=LibNextLink (&c));) if (SmEqs (name, LibGetLinkFromName (link)) || SmEqs (name, LibGetLinkToName (link))) { isLink=1; break; } if (!isLink) _ErrExit2 (e__nosetorlib, name); } set = SetNew (name, NULL); SetSetIsDB (set); } IcaReturn ("set", set); } void QueryDBGroup () { SRSoGROUP *group, *tmp; SLBo *lib; char libName[132], groupName[132]; IargGetArgs ("init|db|group", groupName, libName, &group); if (*groupName) { /* initialize new or already existing group */ if (!(group = (SRSoGROUP *) LibObjByName ("group", groupName))) group = LibGroupNew (groupName); group->libraryN = 0; } /* databank name could be a group name! */ else if ((tmp = (SRSoGROUP*) LibObjByName ("group", libName))) group = tmp; else { /* add a new databank to the group */ if (!(lib = (SLBo *) LibObjByName ("library", libName))) { _ErrMsg3 (e__objectunknown, "data bank", libName); return; } else LibGroupAddDb (group, lib); } IcaReturn ("group", (void*) group); } void QuerySaveResult (Int4 runTime, SETo *set, STRv q) { if (runTime) IargGetArgs ("set|q", &set, &q); SetOp (resultSet, set, NULL, QRYxOR); resultSet->queryStr = q; } void QueryStrSearch () { SRSoGROUP *group; SRSoFLD *fieldType; SLBoFIELD *field, *f; SLBo *lib; SETo *tmp, *tmpSub, *set; char indexName[40], s[255]; INT4 c, k; IargGetArgs ("group|index|s", &group, indexName, s); set = SetNew (NULL, "temp"); for (c=0; lib = LibNextLib (group, &c);) { if (queryInfo->doListValues) TemplPrint ("library", LibName (lib)); if ((field = LibHasFieldNamed (lib, indexName))) { if (LibIsField (field, "group")) /* field is field group (eg, "all") */ for (k=0; (f = LibNextFieldInGroup (lib, field, &k));) { tmp = SetNew (NULL, "temp"); if (QueryStrSearchIndex (s, lib, f, tmp)) { if (SetIsSubEntry (SetGetName (tmp))) { /* set of subentries */ tmpSub = tmp; tmp = SetNew (NULL, "temp"); LinkToParent ("PARENT", SetGetName (tmpSub), tmp); SetDel (tmpSub); } SetOp (set, tmp, NULL, QRYxOR); } SetDel (tmp); } else { tmp = SetNew (NULL, "temp"); if (QueryStrSearchIndex (s, lib, field, tmp)) SetOp (set, tmp, NULL, QRYxOR); SetDel (tmp); } } } IcaReturn ("set", set); } void QueryRangeSearch () { SRSoGROUP *group; SRSoFLD *fieldType; SLBoFIELD *field; SLBo *lib; SETo *tmp, *set; char indexName[40], l[40], h[40]; INT4 c, le, re, rv, isFirst, isLast; IargGetArgs ("group|index|l|h|le|re", &group, indexName, l, h, &le, &re); set = SetNew (NULL, "temp"); isFirst = SmEqs (l, "min") ? 1 : 0; isLast = SmEqs (h, "max") ? 1 : 0; for (c=0; lib = LibNextLib (group, &c);) { if ((field = LibHasFieldNamed (lib, indexName))) { tmp = SetNew (NULL, "temp"); if (LibIsField (field, "real")) rv = QueryRangeSearchIndex (lib, field, 0, 0, isFirst ? 0 : strtod (l, NULL), isLast ? 0 : strtod (h, NULL), 1, re, le, isFirst, isLast, tmp); else if (LibIsField (field, "num")) rv = QueryRangeSearchIndex (lib, field, isFirst ? 0 : atoi(l), isLast ? 0 : atoi(h), 0, 0, 0, le, re, isFirst, isLast, tmp); else continue; if (rv) SetOp (set, tmp, NULL, QRYxOR); SetDel (tmp); } } IcaReturn ("set", set); } SETo *QuerySetAssign (Int4 runTime, STRv name, SETo *set) { SETo *tmp; if (runTime) IargGetArgs ("name|s", &name, &set); if ((tmp = SetNew (_Str (name), NULL))) SetOp (tmp, set, NULL, SETxOR); if (runTime) IcaReturn ("set", tmp); else return set; } void QueryLinkOp () { SETo *set, *s1, *s2; char op[10], s1Name[100], s2Name[100]; IargGetArgs ("op|s1|s2", op, &s1, &s2); set = SetNew (NULL, "temp"); switch (*op) { case '>': LinkMap (SetGetName (s1), SetGetName (s2), set); break; case '<': LinkMap (SetGetName (s2), SetGetName (s1), set); break; default: _ErrExit2 (e__unknownoption, "op in QuerySetOp"); } IcaReturn ("set", set); } void QueryLogOp () { SETo *set, *s1, *s2; char op[10], s1Name[100], s2Name[100]; IargGetArgs ("op|s1|s2", op, &s1, &s2); if (SetIsDB (s1)) _ErrExit2 (e__dbnotlegal, SetGetName (s1)); else if (SetIsDB (s2)) _ErrExit2 (e__dbnotlegal, SetGetName (s2)); set = SetNew (NULL, "temp"); switch (*op) { case '&': SetOp (s1, s2, set, SETxAND); break; case '|': SetOp (s1, s2, set, SETxOR); break; case '!': SetOp (s2, s1, set, SETxNOT); break; default: _ErrExit2 (e__unknownoption, "op in QuerySetOp"); } IcaReturn ("set", set); } INT4 QueryStrSearchIndex (char *s, SLBo *lib, SLBoFIELD *field, SETo *set) { LIBoINDEX *libIndex; char sWild[255]; INT4 len; if (!(libIndex = LibIndexOpen (lib, field, 0))) return 0; SmEdit (s, SMxTRIM|SMxLOWCASE); if ((len = RegWildToRegexp (s, sWild, 1))) { if (queryInfo->doReport) print (" ...searching \"%s\"\n", s); QueryGetWild (libIndex, set, s, sWild, len); } else QueryGet (libIndex, set, s); return SetGetSize (set); } STRv QueryOpMakeWild (INT4 runTime, STRv s) { if (runTime) IargGetArgs ("s", &s); if (!strchr ("*", _Str(s)[StrLen(s)-1]) && StrLen (s) > 1) StrAppS (&s, "*"); if (runTime) IcaReturn ("strv", s); return s; } INT4 QueryRangeSearchIndex (SLBo *lib, SLBoFIELD *field, INT4 low, INT4 high, double lowReal, double highReal, INT4 isReal, INT4 isLE, INT4 isRE, INT4 isFirst, INT4 isLast, SETo *set) { BTRoVALUE begin, end, *val; LIBoINDEX *libIndex; BTRo *btree; INT4 idN; if (!(libIndex = LibIndexOpen (lib, field, 0))) return 0; btree = libIndex->btree; /* ** get record for low value in range */ if (isFirst) begin = (BtrRecordGet(btree, BTRxFIRST))->r.value; else { val = isReal ? BtrSearchReal(btree, lowReal) : BtrSearchNum(btree, low); if (BtrIsSearchGreaterMaxVal (btree)) return 0; if (val && isLE) begin = (BtrRecordGet (btree, BTRxNEXT))->r.value; else begin = (BtrRecordGet (btree, BTRxCURR))->r.value; } /* ** get record for high value in range */ if (isLast) end = (BtrRecordGet(btree, BTRxLAST))->r.value; else { val = isReal ? BtrSearchReal(btree, highReal) : BtrSearchNum(btree, high); if (BtrIsSearchLessMinVal (btree)) return 0; else if (BtrIsSearchGreaterMaxVal (btree)) end = (BtrRecordGet(btree, BTRxLAST))->r.value; if (val && isRE) end = (BtrRecordGet (btree, BTRxPREV))->r.value; else end = (BtrRecordGet (btree, BTRxCURR))->r.value; } if (begin.firstIdFip > end.firstIdFip) return 0; /* nothing found */ /* ** get the set of IDs */ idN = IdsGetRange (libIndex->idsFile, (IDPTR) NULL, begin.firstIdFip, end.firstIdFip, begin.idN, end.idN); _ErrStop (SetAlloc (set, idN, libIndex->field->indexId)); /* alloc id-buff */ /* read id's */ set->n = IdsGet (libIndex->idsFile, set->id_p, begin.firstIdFip, idN); SetSort (set); /* sorting is necessary for set operations */ } void QuerySetFunctions () { IcaSetFunction ("QuerySetGet", (FUNC)QuerySetGet); IcaSetFunction ("QueryDBGroup", (FUNC)QueryDBGroup); IcaSetFunction ("QueryStrSearch", (FUNC)QueryStrSearch); IcaSetFunction ("QueryRangeSearch", (FUNC)QueryRangeSearch); IcaSetFunction ("QueryLogOp", (FUNC)QueryLogOp); IcaSetFunction ("QueryLinkOp", (FUNC)QueryLinkOp); IcaSetFunction ("QueryOpMakeWild", (FUNC)QueryOpMakeWild); IcaSetFunction ("QuerySaveResult", (FUNC)QuerySaveResult); IcaSetFunction ("QuerySetAssign", (FUNC)QuerySetAssign); IcaSetFunction ("QueryMakeWild", (FUNC)QueryMakeWild); } ************************* ** ** $RCSfile: query.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:10 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define QRYxXNAM 30 /* max length of names for ? */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ #ifndef _PRSoST typedef struct PRSoST *dummytointroducestructtagPRSoST; #endif #ifndef _SETo typedef struct SETo *dummytointroducestructtagSETo; #endif /* functions for retrieval */ struct SETo *Query (char *s, char *name); struct SETo *QueryRecursive (char *s, char *name); INT4 QryReadNames (char *fil_nm, char *set_nm); INT4 QryListToSet (struct PRSoST *tokstack, FILo *file); INT4 QryLinkOne (IDoENTRY *id, char *lib_nm, char *set_nm); /* IDoENTRY *QryFindID (char *lib_nm, char *field_nm, char *value);*/ /* check or transform query */ /* others */ INT4 QrySetToList (char *set_nm); char queryass_ID[] = "$Id: queryass.c,v 1.5 1996/07/14 16:21:25 etzold Exp $"; /* ** ** $Source: /home/srs/cvsroot/srs/src/queryass.c,v $ ** $Revision: 1.5 $ ** $Date: 1996/07/14 16:21:25 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "strv.h" #include "library.h" #include "queryass.h" #define _CONSTANTS #define _SRS #define _SLB #include "srs5.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** static functions */ static char *QasGetLinkString (QASoQUERY *qas); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** describes a retrieve command from any index ** + two functions for creating and deleting instances */ typedef struct QASoRETRIEVE { char *list; /* for usage of module "list" only! */ INT4 classId; /* for "list" module */ char fieldName[80]; SMoBUFF *search; SMoBUFF *query; char rangeBegin[20]; char rangeEnd[20]; INT4 isRangeBeginExcl; INT4 isRangeEndExcl; INT4 isSubEntry; INT4 doSubEntry; INT4 isRange; } QASoRETRIEVE; static int QasInitRetrieve (QASoRETRIEVE *r) { r->rangeBegin[0] = r->rangeEnd[0] = '\0'; r->isRangeBeginExcl = r->isRangeEndExcl = 0; r->isSubEntry = r->doSubEntry = 0; r->search = BuffNew (20); r->query = BuffNew (20); r->isRange = 0; } static int QasDeleteRetrieve (QASoRETRIEVE *r) { if (r->search) BuffDelete (&r->search); if (r->query) BuffDelete (&r->query); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** describes a node in linkage map; */ typedef struct QASoLIB { char *list; /* for usage of module "list" only! */ INT4 classId; /* for "list" module */ char name[80]; } QASoLIB; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ static QASoRETRIEVE *QasSetRetrieve (QASoQUERY *query, char *fieldName); static SMoBUFF *QasGetLibsAndDoLink (QASoQUERY *query, INT4 *doLink); static Int4 QasMakeRetrievals (QASoQUERY *query, SMoBUFF *libNames, INT4 doLink); /**API* QasNew **************************************************************** ** ** Get a new query object. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: new query object */ QASoQUERY *QasNew () { QASoQUERY *query; query = (QASoQUERY *) calloc (sizeof (QASoQUERY), 1); query->op = QASxAND; strcpy (query->opName, "&"); return query; } /**API* QasNew **************************************************************** ** ** Deletes a query object. ** ** INPUT: query object [W] ** IMPLICIT: ** ** RETURNS: NULL */ QASoQUERY *QasDelete (QASoQUERY *query) { if (query) { LstDeleteAll ((void *) &query->lib); LstDeleteAll ((void *) &query->retrieve); free (query); } return NULL; } /**API* QasInitLink *********************************************************** ** ** Sets the query to be a link from an arbitrary query expression ** to one or more ** databanks. The query must be further defined with QasSetQueryToLink, ** QasSetLinkLib, QasSetLinkType before obtaining the query string ** from QasGetQueryString. ** The input query object can be obtained from QasNew. ** ** INPUT: query object [W] ** */ void QasInitLink (QASoQUERY *query) { query->isLink = 1; query->linkWithN = 0; } /**API* QasSetTmpSetNum ******************************************************* ** ** Sets the start number for the query assistant to use as part of ** names generated for temporary sets. ** ** INPUT: query object [W] ** the number [R] ** */ void QasSetTmpSetNum (QASoQUERY *qas, Int4 n) { qas->tmpSetNum = n; } /**API* QasSetQueryToLink ***************************************************** ** ** Sets the query expression to be linked with one or more libraries. ** Query must be initialized with QasInitLink. ** ** INPUT: link object [W] ** library name [R] ** */ void QasSetQueryToLink (QASoQUERY *query, char *s) { query->queryToLink = StrCpyS (s); } /**API* QasSetLinkWith ******************************************************** ** ** Sets the library or expression to be linked with the linkQuery. Several ** 'with' expressions can be set. ** Query must be initialized with QasInitLink. ** ** INPUT: link object [W] ** library name [R] ** */ void QasSetLinkWith (QASoQUERY *query, char *with) { query->linkWith[query->linkWithN++] = StrCpyS (with); } /**API* QasSetLinkType ******************************************************** ** ** Sets the type of the link query. Query must be initialized with ** QasInitLink. ** ** INPUT: link object [W] ** option: "toSet", "toLibs", "notToSet" [R] ** */ void QasSetLinkType (QASoQUERY *qas, char *option) { switch (option[2]) { case 'S': qas->linkType = QASxToSet; break; case 'L': qas->linkType = QASxToLibs; break; case 't': qas->linkType = QASxToSetNot; break; default: _ErrExit2 (e__unknownoption, option); } } /**API* QasSetRetrieveStr ***************************************************** ** ** Resets a query object to initial state. ** ** INPUT: query object [W] ** IMPLICIT: ** ** RETURNS: */ void QasReset (QASoQUERY *query) { LstDeleteAll ((void *) &query->lib); LstDeleteAll ((void *) &query->retrieve); query->op = QASxAND; strcpy (query->opName, "&"); query->isMakeWild = 0; query->subEntryFieldType = NULL; } /**API* QasSetRetrieveStr ***************************************************** ** ** Sets a databank to be searched. More than one can be set. ** ** INPUT: query object [W] ** databank (library) name [R] ** IMPLICIT: ** ** RETURNS: 1 if success ** databank name unknown: e__objectunknown <> + */ INT4 QasSetLibrary (QASoQUERY *query, char *libName) { static int classId=0; SRSoGROUP *group; SLBo *lib; if ((lib = (SLBo *) LibObjByName ("library", libName))) libName = LibGetName (lib, "full"); else if ((group = (SRSoGROUP *) LibObjByName ("group", libName))) libName = LibGetGroupName (group, "full"); else _ErrRet3 (e__objectunknown, "databank (group)", libName); if (!classId) LstManageClass (&classId, sizeof (QASoLIB), NULL, NULL, NULL); if (!LstHashSearch ((void **) &query->lib, libName)) LstNewNamed ((void **) &query->lib, classId, libName); return 1; } /****** QasSetRetrieve ******************************************************** ** ** Returns a "retrieve" object or creates a new one. ** ** INPUT: query object [W] ** field name [R] ** low boundary string (maybe int or real) [R] ** IMPLICIT: ** ** RETURNS: retrieve object if success ** NULL if field name unknown */ static QASoRETRIEVE *QasSetRetrieve (QASoQUERY *query, char *fieldName) { static int classId=0; SRSoFLD *fieldType; QASoRETRIEVE *retrieve; if (!classId) LstManageClass (&classId, sizeof (QASoRETRIEVE), QasInitRetrieve, QasDeleteRetrieve, NULL); if (!(fieldType = (SRSoFLD *) LibObjByName ("fieldtype", fieldName))) { _ErrMsg3 (e__objectunknown, "data-field", fieldName); return NULL; } fieldName = fieldType->nam; if (!LstHashSearch ((void **) &query->retrieve, fieldName)) LstNewNamed ((void **) &query->retrieve, classId, fieldName); return query->retrieve; } /**API* QasSetRetrieveStr ***************************************************** ** ** Sets a search string for specified index. ** ** INPUT: query object [W] ** field name [R] ** search string [R] ** IMPLICIT: ** ** RETURNS: */ void QasSetRetrieveStr (QASoQUERY *query, char *fieldName, char *str) { QASoRETRIEVE *retrieve; if (str && *str) { if ((retrieve = QasSetRetrieve (query, fieldName))) BuffCopyString (retrieve->search, str); } } /**API* QasSetRangeBegin ****************************************************** ** ** Sets the lower boundary of a range retrieval. ** ** INPUT: query object [W] ** field name [R] ** low boundary string (maybe int or real) [R] ** IMPLICIT: ** ** RETURNS: number of query in history if success ** 0 if not */ void QasSetRangeBegin (QASoQUERY *query, char *fieldName, char *begin) { QASoRETRIEVE *retrieve; if ((retrieve = QasSetRetrieve (query, fieldName))) { strcpy (retrieve->rangeBegin, begin); retrieve->isRange = 1; } } /**API* QasSetRangeEnd ******************************************************** ** ** Sets the upper boundary of a range retrieval. ** ** INPUT: query object [W] ** field name [R] ** low boundary string (maybe int or real) [R] ** IMPLICIT: ** ** RETURNS: number of query in history if success ** 0 if not */ void QasSetRangeEnd (QASoQUERY *query, char *fieldName, char *end) { QASoRETRIEVE *retrieve; if ((retrieve = QasSetRetrieve (query, fieldName))) { strcpy (retrieve->rangeEnd, end); retrieve->isRange = 1; } } /**API* QasSetRangeBeginExcl ************************************************** ** ** Sets the lower boundary not to be included in range. ** ** INPUT: query object [W] ** field name [R] ** low boundary string (maybe int or real) [R] ** IMPLICIT: ** ** RETURNS: number of query in history if success ** 0 if not */ void QasSetRangeBeginExcl (QASoQUERY *query, char *fieldName) { QASoRETRIEVE *retrieve; if ((retrieve = QasSetRetrieve (query, fieldName))) { retrieve->isRangeBeginExcl = 1; retrieve->isRange = 1; } } /**API* QasSetRangeEndExcl **************************************************** ** ** Sets the upper boundary not to be included in range. ** ** INPUT: query object [W] ** field name [R] ** low boundary string (maybe int or real) [R] ** IMPLICIT: ** ** RETURNS: number of query in history if success ** 0 if not */ void QasSetRangeEndExcl (QASoQUERY *query, char *fieldName) { QASoRETRIEVE *retrieve; if ((retrieve = QasSetRetrieve (query, fieldName))) { retrieve->isRangeEndExcl = 1; retrieve->isRange = 1; } } /**API* QasSetMakeWild ******************************************************* ** ** Sets the flag to add to all search words a terminal wildcard "*". ** ** INPUT: query object [W] ** IMPLICIT: ** ** RETURNS: */ void QasSetMakeWild (QASoQUERY *query) { query->isMakeWild = 1; } /**API* QasSetSubEntries ****************************************************** ** ** Sets the query to return subentries found by specified field. This ** works only if othe fields of different entry types are combined ** with logical AND. ** ** INPUT: query object [W] ** field name [R] ** IMPLICIT: ** ** RETURNS: */ void QasSetSubEntries (QASoQUERY *query, char *fieldName) { if (!(query->subEntryFieldType = (SRSoFLD *) LibObjByName ("fieldtype", fieldName))) { _ErrMsg3 (e__objectunknown, "fieldType", fieldName); } } /**API* QasSetOp ************************************************************** ** ** Sets the operator that combines the separate retrieval commands. ** ** INPUT: query object [W] ** operator name: "or", "and" [R] ** IMPLICIT: ** ** RETURNS: */ void QasSetOp (QASoQUERY *query, char *opName) { switch (tolower (opName[0])) { case '|': case 'o': /* or */ query->op = QASxOR; strcpy (query->opName, "|"); break; case '&': case 'a': /* and */ query->op = QASxAND; strcpy (query->opName, "&"); break; default: _ErrExit2 (e__unknownoption, opName); } } /**API* QasGetQueryString ***************************************************** ** ** Build a query string from all the information accumulated so far. ** This function can be called at any point during query building. ** The function might generate names of intermediate sets for later ** reference in the query, eg, "(L1=[a-b:c]) ! L1retrieve; Int4 rv, k, doLink=0, makeWildSave; if (query->isLink) return QasGetLinkString (query); else { libNames = QasGetLibsAndDoLink (query, &doLink); if (!QasMakeRetrievals (query, libNames, doLink)) return NULL; /* ** Now combine all retrievals to one big query string */ if (!str) str = StrNew (); else StrClear (&str); if (doLink) StrAppS (&str, "("); for (k=0,(rv=LstFirst ((void **)&retrieve)); rv; (rv=LstNext ((void **)&retrieve)),k++) if (!(retrieve->doSubEntry && doLink)) { if (k) StrPrintf(&str, "%s %s ",query->opName,BuffGetPtr (retrieve->query)); else StrAppS (&str, BuffGetPtr (retrieve->query)); } /* if retrieval of subentries requires link */ if (doLink) { StrAppS (&str, ") > "); LstFirst ((void **) &retrieve); do { if (retrieve->doSubEntry) StrAppS (&str, BuffGetPtr (retrieve->query)); } while (LstNext ((void **) &retrieve)); } if (query->isMakeWild) { Int4 save = ParGetNum ("makeWild"); ParDefNum ("makeWild", 1); QueryMakeWild (&str); ParDefNum ("makeWild", save); } return _Str (str); } } static char *QasGetLinkString (QASoQUERY *qas) { static Int4 count; STRv query1, query2, str; Int4 k; count = qas->tmpSetNum; str = StrNew (); query1 = StrNew (); query2 = StrNew (); if (qas->linkWithN > 1 || qas->linkType == QASxToSetNot) { StrPrintf (&query1, "(L%d=%s)", ++count, _Str(qas->queryToLink)); StrPrintf (&query2, "L%d", count); } else { StrSet (&query1, qas->queryToLink); StrSet (&query2, qas->queryToLink); } if (qas->linkType == QASxToSet) { for (k=0; k < qas->linkWithN; k++) { if (!k) StrPrintf (&str, "(%s < %s)", _Str(query1), _Str(qas->linkWith[k])); else StrPrintf (&str, " & (%s < %s)", _Str(query2), _Str(qas->linkWith[k])); } } else if (qas->linkType == QASxToLibs) { for (k=0; k < qas->linkWithN; k++) { if (!k) StrPrintf (&str, "(%s > %s)", _Str(query1), _Str(qas->linkWith[k])); else StrPrintf (&str, " | (%s > %s)", _Str(query2), _Str(qas->linkWith[k])); } } else if (qas->linkType == QASxToSetNot) { for (k=0; k < qas->linkWithN; k++) { if (!k) StrPrintf (&str, "%s ! (%s < %s)", _Str(query1), _Str(query2), _Str(qas->linkWith[k])); else StrPrintf (&str, " ! (%s < %s)", _Str(query2), _Str(qas->linkWith[k])); } } StrDel (query1); StrDel (query2); return _Str (str); } /****** QasGetLibsAndDoLink *************************************************** ** ** Writes the list of selected libraries and groups into a buffer ** marks retrieval commands that lead to subentries and determines if ** the desired ouput is a list of subentries and if a link to subentries ** must be performed. ** ** INPUT: query object [W] ** address of link flag [W] ** IMPLICIT: ** ** RETURNS: buffer object with the library (group) list */ static SMoBUFF *QasGetLibsAndDoLink (QASoQUERY *query, INT4 *doLink) { static SMoBUFF *libNames=NULL; QASoRETRIEVE *retrieve=query->retrieve; SRSoGROUP *group; SLBo *lib; SLBoFIELD *field; INT4 c, c2; libNames = BuffInit (libNames, 50); LstFirst ((void **) &query->lib); do { if ((lib = (SLBo *) LibObjByName ("library", query->lib->name))) { BuffPrintF (libNames,"%s ", LibGetName (lib, "full")); for (c=0; (field = LibNextField (lib, &c)); ) if (LibIsField (field, "subentry")) { if (LstHashSearch ((void **) &retrieve, LibGetFieldName (field))) { retrieve->isSubEntry = 1; if (field->type == query->subEntryFieldType) retrieve->doSubEntry = 1; } } } else if ((group = (SRSoGROUP *) LibObjByName ("group", query->lib->name))){ BuffPrintF (libNames,"%s,", LibGetGroupName (group, "full")); for (c2=0; (lib = LibNextLib (group, &c2)); ) { for (c=0; (field = LibNextField (lib, &c)); ) if (LibIsField (field, "subentry")) { if (LstHashSearch ((void **) &retrieve, LibGetFieldName (field))) { retrieve->isSubEntry = 1; if (field->type == query->subEntryFieldType) retrieve->doSubEntry = 1; } } } } } while (LstNext ((void **) &query->lib)); BuffShiftCurrPtr (libNames, -1); BuffCopyChar (libNames, '\0'); BuffToLower (libNames); if (LstLength ((void *) retrieve) > 1 && query->subEntryFieldType && query->op == QASxAND) *doLink = 1; else *doLink = 0; return libNames; } /****** QasGetLibsAndDoLink *************************************************** ** ** Writes the list of selected libraries and groups into a buffer ** marks retrieval commands that lead to subentries and determines if ** the desired ouput is a list of subentries and if a link to subentries ** must be performed. ** ** INPUT: query object [W] ** address of link flag [W] ** IMPLICIT: ** ** RETURNS: 1: successful ** 0: no retrieval was set */ static Int4 QasMakeRetrievals (QASoQUERY *query, SMoBUFF *libNames, INT4 doLink) { SRSoFLD *fieldType; QASoRETRIEVE *retrieve=query->retrieve; INT4 n; /* ** Iterate over all "retrieve" objects, form for each a query string ** and remember the subentry type requested ...if any */ if (!retrieve) /* nothing was set */ return 0; LstFirst ((void **) &retrieve); n = 0; do { BuffReset (retrieve->query); /* convert subentries to PARENT */ if (retrieve->isSubEntry && !retrieve->doSubEntry) BuffCopyString (retrieve->query, "("); /* databank names */ if (LstLength (query->lib) == 1) BuffPrintF (retrieve->query, "[%s-", BuffGetPtr (libNames)); else if (!n && !(doLink && retrieve->doSubEntry)) { BuffPrintF (retrieve->query, "[libs={%s}-", BuffGetPtr (libNames)); n++; } else BuffPrintF (retrieve->query, "[libs-", BuffGetPtr (libNames)); if (!(fieldType = (SRSoFLD *) LibObjByName ("fieldtype", retrieve->fieldName))) _ErrExit3 (e__objectunknown, "data-field", retrieve->fieldName); /* string search */ if (!retrieve->isRange) BuffPrintF (retrieve->query, "%s: %s]", retrieve->fieldName, BuffGetPtr (retrieve->search)); /* range retrieval */ else BuffPrintF (retrieve->query, "%s# %s%s:%s%s]", retrieve->fieldName, retrieve->isRangeBeginExcl ? "!" : "", retrieve->rangeBegin, retrieve->isRangeEndExcl ? "!" : "", retrieve->rangeEnd); /* convert subentries to PARENT */ if (retrieve->isSubEntry && !retrieve->doSubEntry) BuffCopyString (retrieve->query, " > parent)"); } while (LstNext ((void **) &retrieve)); return 1; } *************************** ** ** $Source: /home/srs/cvsroot/srs/src/queryass.h,v $ ** $Revision: 1.2 $ ** $Date: 1996/06/24 13:46:51 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** The query 'object'. Use only functions to access and modify. */ typedef enum QASeOP {QASxOR=1, QASxAND} QASeOP; typedef enum QASeLinkType {QASxToSet=1, QASxToLibs, QASxToSetNot} QASeLinkType; typedef struct QASoQUERY { char name[80]; Int4 isMakeWild; Int4 isLink; Int4 tmpSetNum; /* used to create set names */ struct STRo *linkWith[100]; struct STRo *queryToLink; Int4 linkWithN; QASeLinkType linkType; char subEntryType[80]; enum QASeOP op; char opName[10]; struct QASoRETRIEVE *retrieve; struct QASoLIB *lib; struct SRSoFLD *subEntryFieldType; } QASoQUERY; typedef struct QASoQUERY *QASv; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ /* construct and destruct */ struct QASoQUERY *QasNew (); struct QASoQUERY *QasDelete (struct QASoQUERY *query); /* set attributes */ INT4 QasSetLibrary (struct QASoQUERY *query, char *libName); void QasSetRetrieveStr (struct QASoQUERY *query, char *fieldName, char *str); void QasSetRangeBegin (struct QASoQUERY *query, char *fieldName, char *begin); void QasSetRangeEnd (struct QASoQUERY *query, char *fieldName, char *end); void QasSetRangeBeginExcl (struct QASoQUERY *query, char *fieldName); void QasSetRangeEndExcl (struct QASoQUERY *query, char *fieldName); void QasSetOp (struct QASoQUERY *query, char *opName); void QasSetMakeWild (struct QASoQUERY *query); void QasSetSubEntries (struct QASoQUERY *query, char *fieldName); void QasSetTmpSetNum (struct QASoQUERY *qas, Int4 n); /* get attributes */ char *QasGetQueryString (struct QASoQUERY *query); * regcomp and regexec -- regsub and regerror are elsewhere * @(#)regexp.c 1.3 of 18 April 87 * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * Beware that some of this code is subtly aware of the way operator * precedence is structured in regular expressions. Serious changes in * regular-expression syntax might require a total rethink. */ #include #include #include "regexp.h" #include "regmagic.h" #include "message.h" /* added */ /* * The "internal use only" fields in regexp.h are present to pass info from * compile to execute that permits the execute phase to run lots faster on * simple cases. They are: * * regstart char that must begin a match; '\0' if none obvious * reganch is the match anchored (at beginning-of-line only)? * regmust string (pointer into program) that match must include, or NULL * regmlen length of regmust string * * Regstart and reganch permit very fast decisions on suitable starting points * for a match, cutting down the work a lot. Regmust permits fast rejection * of lines that cannot possibly match. The regmust tests are costly enough * that regcomp() supplies a regmust only if the r.e. contains something * potentially expensive (at present, the only such thing detected is * or + * at the start of the r.e., which can involve a lot of backup). Regmlen is * supplied because the test in regexec() needs it and regcomp() is computing * it anyway. */ /* * Structure for regexp "program". This is essentially a linear encoding * of a nondeterministic finite-state machine (aka syntax charts or * "railroad normal form" in parsing technology). Each node is an opcode * plus a "next" pointer, possibly plus an operand. "Next" pointers of * all nodes except BRANCH implement concatenation; a "next" pointer with * a BRANCH on both ends of it is connecting two alternatives. (Here we * have one of the subtle syntax dependencies: an individual BRANCH (as * opposed to a collection of them) is never concatenated with anything * because of operator precedence.) The operand of some types of node is * a literal string; for others, it is a node leading into a sub-FSM. In * particular, the operand of a BRANCH node is the first node of the branch. * (NB this is *not* a tree structure: the tail of the branch connects * to the thing following the set of BRANCHes.) The opcodes are: */ /* definition number opnd? meaning */ #define END 0 /* no End of program. */ #define BOL 1 /* no Match "" at beginning of line. */ #define EOL 2 /* no Match "" at end of line. */ #define ANY 3 /* no Match any one character. */ #define ANYOF 4 /* str Match any character in this string. */ #define ANYBUT 5 /* str Match any character not in this string. */ #define BRANCH 6 /* node Match this alternative, or the next... */ #define BACK 7 /* no Match "", "next" ptr points backward. */ #define EXACTLY 8 /* str Match this string. */ #define NOTHING 9 /* no Match empty string. */ #define STAR 10 /* node Match this (simple) thing 0 or more times. */ #define PLUS 11 /* node Match this (simple) thing 1 or more times. */ #define OPEN 20 /* no Mark this point in input as start of #n. */ /* OPEN+1 is number 1, etc. */ #define CLOSE 30 /* no Analogous to OPEN. */ /* * Opcode notes: * * BRANCH The set of branches constituting a single choice are hooked * together with their "next" pointers, since precedence prevents * anything being concatenated to any individual branch. The * "next" pointer of the last BRANCH in a choice points to the * thing following the whole choice. This is also where the * final "next" pointer of each individual branch points; each * branch starts with the operand node of a BRANCH node. * * BACK Normal "next" pointers all implicitly point forward; BACK * exists to make loop structures possible. * * STAR,PLUS '?', and complex '*' and '+', are implemented as circular * BRANCH structures using BACK. Simple cases (one character * per match) are implemented with STAR and PLUS for speed * and to minimize recursive plunges. * * OPEN,CLOSE ...are numbered at compile time. */ /* * A node is one char of opcode followed by two chars of "next" pointer. * "Next" pointers are stored as two 8-bit pieces, high order first. The * value is a positive offset from the opcode of the node containing it. * An operand, if any, simply follows the node. (Note that much of the * code generation knows about this implicit relationship.) * * Using two bytes for the "next" pointer is vast overkill for most things, * but allows patterns to get big without disasters. */ #define OP(p) (*(p)) #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) #define OPERAND(p) ((p) + 3) /* * See regmagic.h for one further detail of program structure. */ /* * Utility definitions. */ #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif #define FAIL(m) { regerror(m); return(NULL); } #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') #define META "^$.[()|?+*\\" /* * Flags to be passed up and down. */ #define HASWIDTH 01 /* Known never to match null string. */ #define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ #define SPSTART 04 /* Starts with * or +. */ #define WORST 0 /* Worst case. */ /* * Global work variables for regcomp(). */ static char *regparse; /* Input-scan pointer. */ static int regnpar; /* () count. */ static char regdummy; static char *regcode; /* Code-emit pointer; ®dummy = don't. */ static long regsize; /* Code size. */ /* * Forward declarations for regcomp()'s friends. */ #ifndef STATIC #define STATIC static #endif STATIC char *reg(); STATIC char *regbranch(); STATIC char *regpiece(); STATIC char *regatom(); STATIC char *regnode(); STATIC char *regnext(); STATIC void regc(); STATIC void reginsert(); STATIC void regtail(); STATIC void regoptail(); #ifdef STRCSPN STATIC int strcspn(); #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** the error reporting functions are located elsewhere in the original ** distribution.. the macro _ErrMsg replaces the original function "regerror" ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int errreport = 0; /* Report errors via errseen? */ char *errseen = NULL; /* Error message. */ /* void error (char *s1, char *s2) { fprintf(stderr, "regexp: "); fprintf(stderr, s1, s2); fprintf(stderr, "\n"); exit(1); }*/ void regerror (char *s) { if (errreport) errseen = s; else _ErrMsg2 (e__regerror, s); } /* - regcomp - compile a regular expression into internal code * * We can't allocate space until we know how big the compiled form will be, * but we can't compile it (and thus know how big it is) until we've got a * place to put the code. So we cheat: we compile it twice, once with code * generation turned off and size counting turned on, and once "for real". * This also means that we don't allocate space until we are sure that the * thing really will compile successfully, and we never have to move the * code and thus invalidate pointers into it. (Note that it has to be in * one piece because free() must be able to free it all.) * * Beware that the optimization-preparation code in here knows about some * of the structure of the compiled regexp. */ regexp * RegComp(exp) /* formerly "regcomp" */ char *exp; { register regexp *r; register char *scan; register char *longest; register int len; int flags; extern char *malloc(); if (exp == NULL) FAIL("NULL argument"); /* First pass: determine size, legality. */ regparse = exp; regnpar = 1; regsize = 0L; regcode = ®dummy; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Small enough for pointer-storage convention? */ if (regsize >= 32767L) /* Probably could be 65535L. */ FAIL("regexp too big"); /* Allocate space. */ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); if (r == NULL) FAIL("out of space"); /* Second pass: emit code. */ regparse = exp; regnpar = 1; regcode = r->program; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Dig out information for optimizations. */ r->regstart = '\0'; /* Worst-case defaults. */ r->reganch = 0; r->regmust = NULL; r->regmlen = 0; scan = r->program+1; /* First BRANCH. */ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ scan = OPERAND(scan); /* Starting-point info. */ if (OP(scan) == EXACTLY) r->regstart = *OPERAND(scan); else if (OP(scan) == BOL) r->reganch++; /* * If there's something expensive in the r.e., find the * longest literal string that must appear and make it the * regmust. Resolve ties in favor of later strings, since * the regstart check works with the beginning of the r.e. * and avoiding duplication strengthens checking. Not a * strong reason, but sufficient in the absence of others. */ if (flags&SPSTART) { longest = NULL; len = 0; for (; scan != NULL; scan = regnext(scan)) if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { longest = OPERAND(scan); len = strlen(OPERAND(scan)); } r->regmust = longest; r->regmlen = len; } } return(r); } /* - reg - regular expression, i.e. main body or parenthesized thing * * Caller must absorb opening parenthesis. * * Combining parenthesis handling with the base level of regular expression * is a trifle forced, but the need to tie the tails of the branches to what * follows makes it hard to avoid. */ static char * reg(paren, flagp) int paren; /* Parenthesized? */ int *flagp; { register char *ret; register char *br; register char *ender; register int parno; int flags; *flagp = HASWIDTH; /* Tentatively. */ /* Make an OPEN node, if parenthesized. */ if (paren) { if (regnpar >= NSUBEXP) FAIL("too many ()"); parno = regnpar; regnpar++; ret = regnode(OPEN+parno); } else ret = NULL; /* Pick up the branches, linking them together. */ br = regbranch(&flags); if (br == NULL) return(NULL); if (ret != NULL) regtail(ret, br); /* OPEN -> first. */ else ret = br; if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; while (*regparse == '|') { regparse++; br = regbranch(&flags); if (br == NULL) return(NULL); regtail(ret, br); /* BRANCH -> BRANCH. */ if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; } /* Make a closing node, and hook it on the end. */ ender = regnode((paren) ? CLOSE+parno : END); regtail(ret, ender); /* Hook the tails of the branches to the closing node. */ for (br = ret; br != NULL; br = regnext(br)) regoptail(br, ender); /* Check for proper termination. */ if (paren && *regparse++ != ')') { FAIL("unmatched ()"); } else if (!paren && *regparse != '\0') { if (*regparse == ')') { FAIL("unmatched ()"); } else FAIL("junk on end"); /* "Can't happen". */ /* NOTREACHED */ } return(ret); } /* - regbranch - one alternative of an | operator * * Implements the concatenation operator. */ static char * regbranch(flagp) int *flagp; { register char *ret; register char *chain; register char *latest; int flags; *flagp = WORST; /* Tentatively. */ ret = regnode(BRANCH); chain = NULL; while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { latest = regpiece(&flags); if (latest == NULL) return(NULL); *flagp |= flags&HASWIDTH; if (chain == NULL) /* First piece. */ *flagp |= flags&SPSTART; else regtail(chain, latest); chain = latest; } if (chain == NULL) /* Loop ran zero times. */ (void) regnode(NOTHING); return(ret); } /* - regpiece - something followed by possible [*+?] * * Note that the branching code sequences used for ? and the general cases * of * and + are somewhat optimized: they use the same NOTHING node as * both the endmarker for their branch list and the body of the last branch. * It might seem that this node could be dispensed with entirely, but the * endmarker role is not redundant. */ static char * regpiece(flagp) int *flagp; { register char *ret; register char op; register char *next; int flags; ret = regatom(&flags); if (ret == NULL) return(NULL); op = *regparse; if (!ISMULT(op)) { *flagp = flags; return(ret); } if (!(flags&HASWIDTH) && op != '?') FAIL("*+ operand could be empty"); *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); if (op == '*' && (flags&SIMPLE)) reginsert(STAR, ret); else if (op == '*') { /* Emit x* as (x&|), where & means "self". */ reginsert(BRANCH, ret); /* Either x */ regoptail(ret, regnode(BACK)); /* and loop */ regoptail(ret, ret); /* back */ regtail(ret, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '+' && (flags&SIMPLE)) reginsert(PLUS, ret); else if (op == '+') { /* Emit x+ as x(&|), where & means "self". */ next = regnode(BRANCH); /* Either */ regtail(ret, next); regtail(regnode(BACK), ret); /* loop back */ regtail(next, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '?') { /* Emit x? as (x|) */ reginsert(BRANCH, ret); /* Either x */ regtail(ret, regnode(BRANCH)); /* or */ next = regnode(NOTHING); /* null. */ regtail(ret, next); regoptail(ret, next); } regparse++; if (ISMULT(*regparse)) FAIL("nested *?+"); return(ret); } /* - regatom - the lowest level * * Optimization: gobbles an entire sequence of ordinary characters so that * it can turn them into a single node, which is smaller to store and * faster to run. Backslashed characters are exceptions, each becoming a * separate node; the code is simpler that way and it's not worth fixing. */ static char * regatom(flagp) int *flagp; { register char *ret; int flags; *flagp = WORST; /* Tentatively. */ switch (*regparse++) { case '^': ret = regnode(BOL); break; case '$': ret = regnode(EOL); break; case '.': ret = regnode(ANY); *flagp |= HASWIDTH|SIMPLE; break; case '[': { register int class; register int classend; if (*regparse == '^') { /* Complement of range. */ ret = regnode(ANYBUT); regparse++; } else ret = regnode(ANYOF); if (*regparse == ']' || *regparse == '-') regc(*regparse++); while (*regparse != '\0' && *regparse != ']') { if (*regparse == '-') { regparse++; if (*regparse == ']' || *regparse == '\0') regc('-'); else { class = UCHARAT(regparse-2)+1; classend = UCHARAT(regparse); if (class > classend+1) FAIL("invalid [] range"); for (; class <= classend; class++) regc(class); regparse++; } } else regc(*regparse++); } regc('\0'); if (*regparse != ']') FAIL("unmatched []"); regparse++; *flagp |= HASWIDTH|SIMPLE; } break; case '(': ret = reg(1, &flags); if (ret == NULL) return(NULL); *flagp |= flags&(HASWIDTH|SPSTART); break; case '\0': case '|': case ')': FAIL("internal urp"); /* Supposed to be caught earlier. */ case '?': case '+': case '*': FAIL("?+* follows nothing"); case '\\': if (*regparse == '\0') FAIL("trailing \\"); ret = regnode(EXACTLY); regc(*regparse++); regc('\0'); *flagp |= HASWIDTH|SIMPLE; break; default: { register int len; register char ender; regparse--; len = strcspn(regparse, META); if (len <= 0) FAIL("internal disaster"); ender = *(regparse+len); if (len > 1 && ISMULT(ender)) len--; /* Back off clear of ?+* operand. */ *flagp |= HASWIDTH; if (len == 1) *flagp |= SIMPLE; ret = regnode(EXACTLY); while (len > 0) { regc(*regparse++); len--; } regc('\0'); } break; } return(ret); } /* - regnode - emit a node */ static char * /* Location. */ regnode(op) char op; { register char *ret; register char *ptr; ret = regcode; if (ret == ®dummy) { regsize += 3; return(ret); } ptr = ret; *ptr++ = op; *ptr++ = '\0'; /* Null "next" pointer. */ *ptr++ = '\0'; regcode = ptr; return(ret); } /* - regc - emit (if appropriate) a byte of code */ static void regc(b) char b; { if (regcode != ®dummy) *regcode++ = b; else regsize++; } /* - reginsert - insert an operator in front of already-emitted operand * * Means relocating the operand. */ static void reginsert(op, opnd) char op; char *opnd; { register char *src; register char *dst; register char *place; if (regcode == ®dummy) { regsize += 3; return; } src = regcode; regcode += 3; dst = regcode; while (src > opnd) *--dst = *--src; place = opnd; /* Op node, where operand used to be. */ *place++ = op; *place++ = '\0'; *place++ = '\0'; } /* - regtail - set the next-pointer at the end of a node chain */ static void regtail(p, val) char *p; char *val; { register char *scan; register char *temp; register int offset; if (p == ®dummy) return; /* Find last node. */ scan = p; for (;;) { temp = regnext(scan); if (temp == NULL) break; scan = temp; } if (OP(scan) == BACK) offset = scan - val; else offset = val - scan; *(scan+1) = (offset>>8)&0377; *(scan+2) = offset&0377; } /* - regoptail - regtail on operand of first argument; nop if operandless */ static void regoptail(p, val) char *p; char *val; { /* "Operandless" and "op != BRANCH" are synonymous in practice. */ if (p == NULL || p == ®dummy || OP(p) != BRANCH) return; regtail(OPERAND(p), val); } /* * regexec and friends */ /* * Global work variables for regexec(). */ static char *reginput; /* String-input pointer. */ static char *regbol; /* Beginning of input, for ^ check. */ static char **regstartp; /* Pointer to startp array. */ static char **regendp; /* Ditto for endp. */ /* * Forwards. */ STATIC int regtry(); STATIC int regmatch(); STATIC int regrepeat(); #ifdef DEBUG int regnarrate = 0; void regdump(); STATIC char *regprop(); #endif /* - regexec - match a regexp against a string */ int RegExec(prog, string) /* formerly "regexec" */ register regexp *prog; register char *string; { register char *s; /* Be paranoid... */ if (prog == NULL || string == NULL) { regerror("NULL parameter"); return(0); } /* Check validity of program. */ if (UCHARAT(prog->program) != MAGIC) { regerror("corrupted program"); return(0); } /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { s = string; while ((s = strchr(s, prog->regmust[0])) != NULL) { if (strncmp(s, prog->regmust, prog->regmlen) == 0) break; /* Found it. */ s++; } if (s == NULL) /* Not present. */ return(0); } /* Mark beginning of line for ^ . */ regbol = string; /* Simplest case: anchored match need be tried only once. */ if (prog->reganch) return(regtry(prog, string)); /* Messy cases: unanchored match. */ s = string; if (prog->regstart != '\0') /* We know what char it must start with. */ while ((s = strchr(s, prog->regstart)) != NULL) { if (regtry(prog, s)) return(1); s++; } else /* We don't -- general case. */ do { if (regtry(prog, s)) return(1); } while (*s++ != '\0'); /* Failure. */ return(0); } /* - regtry - try match at specific point */ static int /* 0 failure, 1 success */ regtry(prog, string) regexp *prog; char *string; { register int i; register char **sp; register char **ep; reginput = string; regstartp = prog->startp; regendp = prog->endp; sp = prog->startp; ep = prog->endp; for (i = NSUBEXP; i > 0; i--) { *sp++ = NULL; *ep++ = NULL; } if (regmatch(prog->program + 1)) { prog->startp[0] = string; prog->endp[0] = reginput; return(1); } else return(0); } /* - regmatch - main matching routine * * Conceptually the strategy is simple: check to see whether the current * node matches, call self recursively to see whether the rest matches, * and then act accordingly. In practice we make some effort to avoid * recursion, in particular by going through "ordinary" nodes (that don't * need to know whether the rest of the match failed) by a loop instead of * by recursion. */ static int /* 0 failure, 1 success */ regmatch(prog) char *prog; { register char *scan; /* Current node. */ char *next; /* Next node. */ scan = prog; #ifdef DEBUG if (scan != NULL && regnarrate) fprintf(stderr, "%s(\n", regprop(scan)); #endif while (scan != NULL) { #ifdef DEBUG if (regnarrate) fprintf(stderr, "%s...\n", regprop(scan)); #endif next = regnext(scan); switch (OP(scan)) { case BOL: if (reginput != regbol) return(0); break; case EOL: if (*reginput != '\0') return(0); break; case ANY: if (*reginput == '\0') return(0); reginput++; break; case EXACTLY: { register int len; register char *opnd; opnd = OPERAND(scan); /* Inline the first character, for speed. */ if (*opnd != *reginput) return(0); len = strlen(opnd); if (len > 1 && strncmp(opnd, reginput, len) != 0) return(0); reginput += len; } break; case ANYOF: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) return(0); reginput++; break; case ANYBUT: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) return(0); reginput++; break; case NOTHING: break; case BACK: break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: { register int no; register char *save; no = OP(scan) - OPEN; save = reginput; if (regmatch(next)) { /* * Don't set startp if some later * invocation of the same parentheses * already has. */ if (regstartp[no] == NULL) regstartp[no] = save; return(1); } else return(0); } case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: { register int no; register char *save; no = OP(scan) - CLOSE; save = reginput; if (regmatch(next)) { /* * Don't set endp if some later * invocation of the same parentheses * already has. */ if (regendp[no] == NULL) regendp[no] = save; return(1); } else return(0); } case BRANCH: { register char *save; if (OP(next) != BRANCH) /* No choice. */ next = OPERAND(scan); /* Avoid recursion. */ else { do { save = reginput; if (regmatch(OPERAND(scan))) return(1); reginput = save; scan = regnext(scan); } while (scan != NULL && OP(scan) == BRANCH); return(0); /* NOTREACHED */ } } break; case STAR: case PLUS: { register char nextch; register int no; register char *save; register int min; /* * Lookahead to avoid useless match attempts * when we know what character comes next. */ nextch = '\0'; if (OP(next) == EXACTLY) nextch = *OPERAND(next); min = (OP(scan) == STAR) ? 0 : 1; save = reginput; no = regrepeat(OPERAND(scan)); while (no >= min) { /* If it could work, try it. */ if (nextch == '\0' || *reginput == nextch) if (regmatch(next)) return(1); /* Couldn't or didn't -- back up. */ no--; reginput = save + no; } return(0); } case END: return(1); /* Success! */ default: regerror("memory corruption"); return(0); } scan = next; } /* * We get here only if there's trouble -- normally "case END" is * the terminating point. */ regerror("corrupted pointers"); return(0); } /* - regrepeat - repeatedly match something simple, report how many */ static int regrepeat(p) char *p; { register int count = 0; register char *scan; register char *opnd; scan = reginput; opnd = OPERAND(p); switch (OP(p)) { case ANY: count = strlen(scan); scan += count; break; case EXACTLY: while (*opnd == *scan) { count++; scan++; } break; case ANYOF: while (*scan != '\0' && strchr(opnd, *scan) != NULL) { count++; scan++; } break; case ANYBUT: while (*scan != '\0' && strchr(opnd, *scan) == NULL) { count++; scan++; } break; default: /* Oh dear. Called inappropriately. */ regerror("internal foulup"); count = 0; /* Best compromise. */ break; } reginput = scan; return(count); } /* - regnext - dig the "next" pointer out of a node */ static char * regnext(p) register char *p; { register int offset; if (p == ®dummy) return(NULL); offset = NEXT(p); if (offset == 0) return(NULL); if (OP(p) == BACK) return(p-offset); else return(p+offset); } #ifdef DEBUG STATIC char *regprop(); /* - regdump - dump a regexp onto stdout in vaguely comprehensible form */ void regdump(r) regexp *r; { register char *s; register char op = EXACTLY; /* Arbitrary non-END op. */ register char *next; extern char *strchr(); s = r->program + 1; while (op != END) { /* While that wasn't END last time... */ op = OP(s); printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ next = regnext(s); if (next == NULL) /* Next ptr. */ printf("(0)"); else printf("(%d)", (s-r->program)+(next-s)); s += 3; if (op == ANYOF || op == ANYBUT || op == EXACTLY) { /* Literal string, where present. */ while (*s != '\0') { putchar(*s); s++; } s++; } putchar('\n'); } /* Header fields of interest. */ if (r->regstart != '\0') printf("start `%c' ", r->regstart); if (r->reganch) printf("anchored "); if (r->regmust != NULL) printf("must have \"%s\"", r->regmust); printf("\n"); } /* - regprop - printable representation of opcode */ static char * regprop(op) char *op; { register char *p; static char buf[50]; (void) strcpy(buf, ":"); switch (OP(op)) { case BOL: p = "BOL"; break; case EOL: p = "EOL"; break; case ANY: p = "ANY"; break; case ANYOF: p = "ANYOF"; break; case ANYBUT: p = "ANYBUT"; break; case BRANCH: p = "BRANCH"; break; case EXACTLY: p = "EXACTLY"; break; case NOTHING: p = "NOTHING"; break; case BACK: p = "BACK"; break; case END: p = "END"; break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); p = NULL; break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); p = NULL; break; case STAR: p = "STAR"; break; case PLUS: p = "PLUS"; break; default: regerror("corrupted opcode"); break; } if (p != NULL) (void) strcat(buf, p); return(buf); } #endif /* * The following is provided for those people who do not have strcspn() in * their C libraries. They should get off their butts and do something * about it; at least one public-domain implementation of those (highly * useful) string routines has been published on Usenet. */ #ifdef STRCSPN /* * strcspn - find length of initial segment of s1 consisting entirely * of characters not from s2 */ static int strcspn(s1, s2) char *s1; char *s2; { register char *scan1; register char *scan2; register int count; count = 0; for (scan1 = s1; *scan1 != '\0'; scan1++) { for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ if (*scan1 == *scan2++) return(count); count++; } return(count); } #endif /****** RegWildToRegexp ******************************************************* ** ** converts a string containing wildcards into a regular expression; ** the world can contain ** the wildcards '*' (any number of chars) and '?' (any single character); ** the function returns the position of the first wildcard within the ** word (first position is 1!); ** "." is converted to "\." ** expression will begin with '^' and end with '$'; ** ** INPUT: o string containing wildcards [R] ** o pointer to output regular expression [R] ** o flag if wildcards (see above) are to be recognized as ** such and be replaced within a regular expression ** IMPLICIT: ** ** RETURNS: 0 if word contains no wildcards ** position of first wildcard in string (1=string begin) */ int RegWildToRegexp (char *s, char *reStr, INT4 isWild) { int firstWildLoc=0, k; char c, tmp[512]; char *reStrPtr=tmp; /* tmp str so that output can be written to input str */ /* ** a full regular expression is given between two '/' s */ if (*s == '/' && *(s + strlen (s) - 1) == '/') { strcpy (tmp, s+1); /* remove left '/'*/ tmp[ strlen (tmp) - 1 ] = '\0'; /* ...and right '/' */ strcpy (reStr, tmp); return 1; } if (isWild) { *reStrPtr++ = '^'; /* begin of line */ for (k=0; (c = s[k]); k++) { if (c == '*' || c == '?') { /* it is a wildcard */ if (!firstWildLoc) firstWildLoc = k+1; *reStrPtr++ = '.'; if (c == '*') { *reStrPtr++ = '*'; } } else if (s[k] == '.') { /* dots must be escaped */ *reStrPtr++ = '\\'; *reStrPtr++ = '.'; } else *reStrPtr++ = s[k]; } *reStrPtr++ = '$'; /* end of line */ *reStrPtr = '\0'; if (reStr) strcpy (reStr, tmp); } return firstWildLoc; } * Definitions etc. for regexp(3) routines. * * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], * not the System V one. */ #define NSUBEXP 10 typedef struct regexp { char *startp[NSUBEXP]; char *endp[NSUBEXP]; char regstart; /* Internal use only. */ char reganch; /* Internal use only. */ char *regmust; /* Internal use only. */ int regmlen; /* Internal use only. */ char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; extern regexp *RegComp(); extern int RegExec(); extern void regsub(); extern void regerror(); extern int RegWildToRegexp (char *str, char *reStr, int isWild); * The first byte of the regexp internal "program" is actually this magic * number; the start node begins in the second byte. */ #define MAGIC 0234 * regsub * @(#)regsub.c 1.3 of 2 April 86 * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. */ #include #include #include "regmagic.h" #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif /* - regsub - perform substitutions after a regexp match */ void regsub(prog, source, dest) regexp *prog; char *source; char *dest; { register char *src; register char *dst; register char c; register int no; register int len; extern char *strncpy(); if (prog == NULL || source == NULL || dest == NULL) { regerror("NULL parm to regsub"); return; } if (UCHARAT(prog->program) != MAGIC) { regerror("damaged regexp fed to regsub"); return; } src = source; dst = dest; while ((c = *src++) != '\0') { if (c == '&') no = 0; else if (c == '\\' && '0' <= *src && *src <= '9') no = *src++ - '0'; else no = -1; if (no < 0) { /* Ordinary character. */ if (c == '\\' && (*src == '\\' || *src == '&')) c = *src++; *dst++ = c; } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { len = prog->endp[no] - prog->startp[no]; (void) strncpy(dst, prog->startp[no], len); dst += len; if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ regerror("damaged match string"); return; } } } *dst++ = '\0'; } char sdlget_ID[] = "\n$Id: sdlget.c,v 1.1 1996/05/06 15:17:15 srs Exp $"; /* ** ** $RCSfile: sdlget.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:15 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "message.h" #include "futil.h" #include "odd.h" #define _SDL #define _ODD #include "oddclass.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object wide variables */ #ifndef BOOTSTRAP typedef int (*SDLoFNCT)(); extern SDLoFNCT SDL_fnctx[]; #endif SDLoPTR section; INT4 section_z; /**api* SdlGetObjects ********************************************************* ** ** expands name to "SRSSEC:name.SEC" and "... .PTR" reads these files ** using block-IO into newly allocated memory; addresses in ref-list ** are corrected for the difference of location of section-block; ** ** INPUT: address of array of array of objects [W] ** address of array of sizes of above array [W] ** address of section name [R] ** IMPLICIT: ** SDL_fnct (SDLoFNCT[]) [R] ** section (void *) [W] ** section_z (int) [W] ** ** RETURNS: 1 */ INT4 SdlGetObjects (long int **obj_n, void ***obj_p, char *sec_nm) { FILE *sec_fd, *ptr_fd; char fil_nm[FILxXNAM+1]; SDLoPTR *ptr, *ptrlist, data, *addr, sec, *o_p, *ptr_p; long int addr_n, *o_n; int diff, k, objc_n, rv, sec_z, ptr_z; /* ** open file with the data (*.sec) and the file with a list of pointers ** int the data file to be updated (*.ptr) */ sprintf (fil_nm, "SRSSEC:%s.sec", sec_nm); sec_fd = FilOpenR (fil_nm, &rv); _ErrExit2 (rv, fil_nm); sprintf (fil_nm, "SRSSEC:%s.ptr", sec_nm); ptr_fd = FilOpenR (fil_nm, &rv); _ErrExit2 (rv, fil_nm); /* ** get the sizes of both files, allocate memory accordingly and read the ** files in one go */ rv = fread (&sec_z, sizeof(int), 1, sec_fd); if (sizeof (char *) != sizeof (int)) fseek (sec_fd, sizeof (char *) - sizeof (int), 1); /** 1 == SEEK_CUR */ rv = fread (&ptr_z, sizeof(int), 1, ptr_fd); if ((sec = (SDLoPTR) malloc (sec_z)) == NULL) _ErrExit2(e__allocfail, "section by SdlGetObjects"); section = sec; /** global variables */ section_z = sec_z; if ((ptrlist = (SDLoPTR *) malloc (ptr_z)) == 0) _ErrExit2(e__allocfail, "pointer array by SdlGetObjects"); fread (sec, 1, sec_z, sec_fd); fread (ptrlist, 1, ptr_z, ptr_fd); ptr = ptrlist; /* ** get the following info from begin of .ptr file: ** o address of section begin (at the time section was built) ** o number of object classes represented in the section ** o for each class the number of instances + offset of its array in ** the section */ data = (char *) *ptr++; /** addr of section begin */ objc_n = (long) *ptr++; /** number of objects */ o_n = (long *) malloc (objc_n * sizeof (int *)); o_p = (SDLoPTR *) malloc (objc_n * sizeof (unsigned int *)); diff = (int) (sec - data); for (k=0; k < objc_n; k++) { o_p[k] = (SDLoPTR) (*ptr++) + diff; /** address of obj-array */ o_n[k] = (long) *ptr++; /** size of obj-array */ } /* ** then read the number of references */ addr_n = (long) *ptr++; /** number of references */ addr = ptr; /** ref list */ for (k=0; k < addr_n; k++) { ptr_p = (SDLoPTR *) (addr[k] + diff); if ((long) *ptr_p <= SDLxXFNCT) { #ifndef BOOTSTRAP if ((long) *ptr_p < 0) *ptr_p = 0; else *ptr_p = (long) *ptr_p == SDLxXFNCT ? NULL : (SDLoPTR) SDL_fnctx[(long)*ptr_p]; #else ; #endif } else *ptr_p = *ptr_p + diff; } /* ** delete list of pointers to be relocated and return info to caller */ free (ptrlist); *obj_p = (void **) o_p; *obj_n = o_n; return objc_n; } /**api* SdlGetObj ************************************************************* ** ** gets pointer to objects of a type and the number; ** ** INPUT: address of SDL descr. [R] ** object-class ID [R] ** address of object pointer [W] ** address of object count [W] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 SdlGetObj (SDLo *sdl, int class_x, void **obj_p, int *obj_n) { *obj_p = (void *) (sdl->oc[class_x].s); *obj_n = sdl->oc[class_x].ns; return 1; } /**api* OddIsInDepot ********************************************************** ** ** returns 1 if pointer points within a depot with defined ODD objects ** ...means that that ** cannot be freed because the whole depot is allocated as one big block ** ** INPUT: address [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 OddIsInDepot (char *p) { return (p >= section && p < section + section_z) ? 1 : 0; } ** ** $RCSfile: sdlget.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:15 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** list of functions exported by module "seqlib" */ INT4 OddIsInDepot (char *p); char sdl_ID[] = "$Id: sdlnew.c,v 1.8 1996/08/11 22:47:18 etzold Exp $"; /* ** ** $RCSfile: sdlnew.c,v $ ** $Revision: 1.8 $ ** $Date: 1996/08/11 22:47:18 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "strv.h" #include "tm.h" #include "map.h" #include "par.h" #include "templ.h" #include "dict.h" #include "variable.h" #define _SDL #define _ODD #include "oddclass.h" #include "odd.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macros and enums */ enum status {ODDxOBSOLETE=1, ODDxSYSTEM, ODDxAPI}; enum linebreak {SDLxFIRST=1, SDLxLAST=2, SDLxBREAK=4, SDLxBOUND=8}; typedef INT4 (*SDLoFNCT)(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object wide variables */ static int addr_n = 0; static SDLoPTR *addr; static FILo file; static int fnct_x; SDLo *odd=NULL; ODDoFNCT_P function[SDLxXFNCT]; FILo *f = &file; static MAPo map; ODDoCDEFINE cDefine[100]; INT4 cDefineN=0; #ifndef BOOTSTRAP extern SDLoFNCT SDL_fnct[]; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static void OddSetFlags (int opt); static int OddObjSizes (void); static int SdlAlloc (void); int SdlWrtHdr (SDLo *d, int opt); static int SdlCloseSec (); static int SdlObjInx (char *nam); int OddRegisterObj (SDLoOBJ *obj); static int SdlIsChild (int p_x, int ch_x); void *OddFinishObj (SDLoOBJ *obj); static int OddResetObj (SDLoOBJ *obj); static int OddGetValue (SDLoATTR *attr, char **tokstr, unsigned *tokval, VARo *value); static int SdlCopySec (char **s); static int SdlWrtTtl (FILE *f, char *in, char *out); static int SdlWrtTypDef (FILE *fil, SDLoOBJ *s, int ns); static int SdlWrtInit (FILE *fil, SDLoOBJ *s, int ns); static int SdlWrtAttr (FILE *fil, SDLoOBJ *obj, char *typdef_nm, char *gtyp_nm); static int SdlWrtFnct (FILE *f, SDLoOBJ *s); void OddWriteClassInfo (SDLo *odd); INT4 OddIsAttr (SDLoATTR *attr, char *option); INT4 OddIsClass (SDLoOBJ *class, char *option); /**api* OddInit *************************************************************** ** ** ** INPUT: ODD data base object [W] ** ** IMPLICIT: ** odd (SDLo *) [W] ** ** RETURNS: 1 */ SDLo *OddInit (SDLo *oddBase, INT4 level) { ODDoATYP *at; INT4 atN; if (level == 1) { odd = oddBase; } else if (level == 2) { at = oddBase->at; atN = oddBase->at_n; odd = (SDLo *) oddBase->oc[odd->oc_n-1].s; odd->at = at; odd->at_n = atN; odd->action |= SDLxHDR; } odd->pass_n = 1; OddSetFlags (level); OddObjSizes (); return odd; } Int4 OddIsActive () { return odd ? 1 : 0; } /**api* OddInit *************************************************************** ** ** ** INPUT: ODD data base object [W] ** ** IMPLICIT: ** odd (SDLo *) [W] ** ** RETURNS: 1 */ void OddInitDepot () { if (odd->pass_n == 1) { odd->pass_n = 2; SdlAlloc (); } } /****** SdlMalloc ************************************************************* ** ** same as malloc but creates a mapsection initially ** ** INPUT: nr. of bytes to allocate [R] ** IMPLICIT: ** addr (unsigned int) ** odd (SDLo *) ** map (MAPo) ** ** RETURNS: address of allocated area ** NULL if none available */ void *SdlMalloc (int siz) { static int init_f = FALSE; char fil_nm[FILxXNAM+1]; int shiftalign, rv; if (!init_f) /* init_f is FALSE on first call, else TRUE */ { /* ** this part of the code is only execute the first time this ** function is called. It then allocates a map section of ** size given by odd->sec_z */ sprintf (fil_nm, "SRSSEC:%s.sec", odd->sec_nm); rv = MapAlloc (&map, fil_nm, odd->sec_z); _ErrExit (rv); /* ** first int in section has the file offset after the last byte written ** to same section...this int + some bytes (for alignment) must be skipped ** before starting to write to the section */ shiftalign = (sizeof (char *) - sizeof (unsigned int)); map.off += shiftalign; *(map.foff) += shiftalign; if ((addr = (SDLoPTR *) malloc (sizeof (SDLoPTR) * SDLxXADDR)) == NULL) _ErrExit2(e__allocfail, "array addr"); init_f = TRUE; } return (void *) MapMalloc (&map, siz); } /****** OddSetFlags *********************************************************** ** ** sets global flags; ** ** INPUT: compilation level (1 or 2) [R] ** IMPLICIT: ** odd (SDLo *) [W] ** ** RETURNS: 1 */ static void OddSetFlags (INT4 level) { odd->error = FALSE; if (level == 1) { if (ParGetBool ("doMetaData")) odd->action = SDLxHDR; else odd->action = SDLxNOHDR; } else if (level == 2) { if (ParGetBool ("doInitHeader")) odd->action = SDLxHDR; else if (ParGetBool ("doSection") && ParGetBool ("doHeader")) odd->action = SDLxHDRSEC; else if (ParGetBool ("doSection")) odd->action = SDLxSECTION; else if (ParGetBool ("doHeader")) odd->action = SDLxHDR2; else if (ParGetBool ("doClassInfo")) odd->action = SDLxHDR2; } odd->section_f = (odd->action == SDLxSECTION || odd->action == SDLxHDRSEC); } /**new* OddGetClass *********************************************************** ** ** Returns the class object which has the specified name. ** ** INPUT: name of the class [W] ** IMPLICIT: ** odd (SDLo *) ** ** ** RETURNS: ** class object ** NULL if specified class does not exist */ SDLoOBJ *OddGetClass (char *className) { SDLoOBJ *class; INT4 classIndex; classIndex = SdlObjInx (className); _ErrIf (classIndex) return NULL; else return &(odd->oc[classIndex]); } void *OddGetCurrObj (SDLoOBJ *class) { return class->uobj_coff; } char *OddGetClassName (SDLoOBJ *class) { return class->nam; } void OddSetObjListSize (SDLoOBJ *class, char *attrName, Int4 n) { SDLoATTR *attr; char tmp[100]; sprintf (tmp, "%sN", attrName); if ((attr = OddGetAttribute (class, tmp))) { attr->hasObjsN = n; if (!(attr = OddGetAttribute (class, attrName))) _ErrExit3 (e__icaunknownattr, OddGetClassName (class), attrName); attr->hasObjsN = n; } } /****** OddFinishObj *********************************************************** ** ** does post processing of object i.e. checks whether all required ** attributes have been read, fills non read attributes with defaults; ** ** INPUT: object ID [W] ** IMPLICIT: ** odd (SDLo *) [W] ** f (FILo *) [R] ** ** RETURNS: 1 if success ** e__icarequiredattr + ** e__parnotok + ** e__noss + */ void *OddFinishObj (SDLoOBJ *class) { SDLoATTR *attr; SDLoPTR off; int rv, k; int (*make) (SDLoOBJ *, SDLoATTR *, SDLoPTR *); for (k = 0; k < class->np; k++) { attr = &(class->p[k]); off = class->uobj_coff + attr->off; /* off to place prmtr */ if ((make = odd->at[attr->typ].make) != NULL) { rv = (*make) (class, attr, &off); } _ErrIf (rv) { if (rv == e__icarequiredattr) _ErrMsg3(e__icarequiredattr, attr->nam, OddGetClassName (class)); odd->error = TRUE; continue; } } if (odd->section_f && class->typ != SDLxVIRTUAL) SdlSaveAddr (class, class->uobj_coff); /* save pointers */ OddResetObj (class); return class->uobj_coff; } /****** OddResetObj ********************************************************** ** ** after a object has been read along with all child-objects ** some attributes of SDLoOBJ and SDLoATTR have to be reset before ** working on the next object on the same level; this is ** what is done here; ** ** INPUT: object ID [W] ** IMPLICIT: ** odd (SDLo *) [W] ** ** RETURNS: 1 */ static int OddResetObj (SDLoOBJ *obj) { SDLoOBJ *tmp; SDLoATTR *attr; int k; for (k = 0; k < obj->np; k++) { attr = &obj->p[k]; attr->isrd = FALSE; attr->hasObjsN = -1; } for (k = 0; k < obj->nss; k++) { /* child-objects */ tmp = &odd->oc[ (obj->ss)[k] ]; if (tmp != obj) tmp->loc_n = 0; } return 1; } /****** OddRegisterObj ******************************************************** ** ** increments counter for a specific object and calculates offset ** of new target object; ** counters gbl_n and loc_n must be initialized with 0 ** ** INPUT: address of object-descriptor (SDLoOBJ) [W] ** IMPLICIT: ** odd (SDLo *) ** ** RETURNS: 1 if success ** e__toomanstrct */ int OddRegisterObj (SDLoOBJ *obj) { (obj->gbl_n)++; (obj->loc_n)++; if (obj->gbl_n > obj->ns && odd->pass_n == 2) return e__toomanstrct; if (obj->gbl_n != 1) obj->uobj_coff += obj->siz; else obj->uobj_coff = obj->s; return 1; } /******************* odd ids ************************************************/ typedef struct ODDoID { char name[80]; SDLoOBJ *class; INT4 objX; } ODDoID; static void* OddIdToKey (DictElem* e) { return (*(ODDoID **)e)->name; } static CLASSoDICT idDictClass = { (ValComparer)strequal, (ValHasher)strhash, (KeyAccessor)OddIdToKey, NULL, 0 }; static DICTv idDict=NULL; void OddIdInit () { if (idDict) DictDestroy (idDict); idDict = DictCreate (&idDictClass); } int OddIdRetrieve (char *idName, INT4 isOptional) { Iter i; ODDoID *id; if (i = DictWith (idDict, idName)) { id = DictIn (i, ODDoID*); return id->objX; } else { if (!isOptional) _ErrMsg3 (e__objectunknown, "object-ID", idName); return -1; } } void OddIdRegister (SDLoOBJ *class, char *idName) { ODDoID *id; if ((id = (ODDoID *) malloc (sizeof (ODDoID))) == NULL) _ErrExit2 (e__allocfail, "object-Id"); strcpy (id->name, idName); id->class = class; id->objX = class->gbl_n-1; if (!idDict) OddIdInit (); DictSet (&idDict, idName, ODDoID*) = id; } /****** OddObjSizes *********************************************************** ** ** calculates offsets of attributes in all objects described ** in array of object definitions and calculates ** the objects sizes; objects that inherit others get size of inherited ** object added - inherited objects are appended; ** ** INPUT: ** IMPLICIT: ** odd (SDLo *) [W] ** gblerr (int) [W] ** ** RETURNS: 1 if success ** e__novalptyp + */ static int OddObjSizes (void) { SDLoOBJ *obj, *iobj; SDLoATTR *attr; int n, k, attr_n, off, member_z, maxmember_z; int (*calcsize) (); for (n = 0; n < odd->oc_n; n++) { obj = &((odd->oc)[n]); attr_n = obj->np; off = 0; for (k=0, maxmember_z=0; k < attr_n; k++) { attr = &(obj->p)[k]; /* ** calculate the size of the data member that will correspond ** to the attribute....assuming that the data structure itself is ** optimally aligned some invidual members have to be aligned within the ** structure ...this is also done by the function "calcsize" which ** sets the offset to the begin of the data member */ if ((calcsize = odd->at[attr->typ].size) != NULL) { member_z = (*calcsize) (obj, attr, &off); if (member_z > maxmember_z) maxmember_z = member_z; attr->off = off; off += member_z; } } /* ** calc. size of structure until begin of next ...this depends on the ** alignment which is to the size of the largest member; eg, on osf, a ** structure that has a pointer (size 8byte) is always aligned to an 8 byte ** boundary */ if (maxmember_z >= 8) _SdlAlignEight (off); else if (maxmember_z >= 4) _SdlAlignFour (off); obj->siz = off; } return 1; } /****** SdlAlloc ************************************************************** ** ** allocates storage for all counted objects and sets counters back to 0; ** if object is to be organized in a data structure (such as a list) ** then the size has to be increased by the size of the pointers needed. ** - the needed space is given by org->off. ** This additional space is always at the beginning of a user block! ** So by shifting the whole array of user-objects by org->off ** obj->s points to the begin of the user-block as seen from the user ** and so it can be treated as any other user-object. ** ** INPUT: ** IMPLICIT: ** odd (SDLo *) [W] ** ** RETURNS: 1 if successfull */ static int SdlAlloc (void) { SDLoOBJ *obj; int allsiz, k; for (k=0; k < odd->oc_n; k++) { obj = &(odd->oc[k]); if (obj->gbl_n == 0) continue; obj->ns = obj->gbl_n; allsiz = obj->siz * obj->ns; obj->s = _SdlMalloc (allsiz); if (!obj->s) _ErrExit2 (e__allocfail, "array of objects by SdlAlloc"); obj->gbl_n = obj->loc_n = 0; /* reset counter */ } return 1; } /****** SdlIsChild ************************************************************ ** ** finds out if object with second index is a child of object ** with first index; ** ** INPUT: ID of parent object [R] ** ID of child object [R] ** IMPLICIT: ** odd (SDLo *) ** ** RETURNS: 1 if child ** 0 if not */ static int SdlIsChild (int p_x, int ch_x) { SDLoOBJ *obj = &(odd->oc[p_x]); int k; for (k = 0; k < obj->nss; k++) if (ch_x == obj->ss[k]) return 1; return 0; } /****** SdlObjInx ************************************************************* ** ** takes a "DEFINE" name, checks whether this name corresponds to a ** object to be processed and returns the offset of the object ** description in global array of SDLoOBJ; ** ** INPUT: address of object name [R] ** IMPLICIT: ** odd (SDLo *) ** ** RETURNS: object ID (offset in array of object-descriptors) ** e__novalsnam */ static int SdlObjInx (char *nam) { SDLoOBJ *obj; int k, inx; for (k = 0, inx = -1; k < odd->oc_n; k++) { obj = &(odd->oc)[k]; if (SmEqs (obj->nam, nam)) inx = k; } if (inx == -1) return e__novalsnam; return inx; } /****** OddGetAttribute ******************************************************* ** ** Returns the attribute description with specified name for specified ** class; ** ** INPUT: class object [R] ** attribute name [R] ** ** RETURNS: ** attribute type object ** NULL if attribute with specified name was not found */ SDLoATTR *OddGetAttribute (SDLoOBJ *class, char *name) { SDLoATTR *attr; INT4 k; for (k = 0; k < class->np; k++) { attr = &class->p[k]; /* unnamed attributes start with ':' */ if (SmEqs (attr->nam, name) || (*name == ':' && attr->unnamed)) return attr; } return NULL; } INT4 OddIsPartOfList (SDLoOBJ *class, char *attrName) { SDLoATTR *attr; if (!(attr = OddGetAttribute (class, attrName))) _ErrRet3 (e__icaunknownattr, OddGetClassName (class), attrName); return attr->typ == AT_CHILD ? 1 : 0; } void OddInstallClasses () { odd = (SDLo *)odd->oc[odd->oc_n-1].s; } /****** OddObjAttribute ****************************************************** ** ** Replaces SdlAttribute; ** ** INPUT: class object [W] ** attribute name [R] ** IMPLICIT: ** odd (SDLo *) ** ** RETURNS: e__icaunknownattr + ** e__parnotok + ** e__symnotuniq + ** e__novalid + ** e__bnfbuildfail + ** e__allocfail + ** e__objnotfound + ** e__objnotnhrt + ** 1 if successful */ INT4 OddObjAttribute (SDLoOBJ *class, char *attrName, VARo *value) { VARo *varList=NULL; char *tokstr; SDLoATTR *attr, *defaultAttr; SDLoPTR off; unsigned tokval; int (*insert) (); int c=0, k, rv, isDefault=0; if (!(attr = OddGetAttribute (class, attrName))) _ErrRet3 (e__icaunknownattr, OddGetClassName (class), attrName); defaultAttr = attr; off = ((SDLoPTR) class->uobj_coff + attr->off); if (VarType (value) == VARxLIST) { /* first in list - if list */ varList = value; value = VarNextInList (varList, &c); } for (k=0; k < attr->arrsz; k++) { if (!isDefault) { rv = (k && !varList) ? 0 : OddGetValue (attr, &tokstr, &tokval, value); if (!rv) isDefault = 1; /* now enter default value */ _ErrIf (rv) odd->error = TRUE; } if ((insert = odd->at[attr->typ].insert) != NULL) { rv =(*insert)(class, attr, defaultAttr, &off, tokstr, tokval, isDefault); _ErrIf (rv) odd->error = TRUE; } if (varList && !isDefault) /* next in list - if list */ if (!(value = VarNextInList (varList, &c))) isDefault = 1; } attr->isrd = TRUE; return 1; } /****** SdlParTyp ************************************************************* ** ** checks whether ATTRIBUTE value type is one of declared types: ** SDLxPNUM, SDLxPNAM, SDLxPTXT, SDLxPCNST; ** ** INPUT: address of ATTRIBUTE name ** address of array of alowed types ** actual type ** IMPLICIT: ** f (FILo *) ** ** OUTPUT: ** returns: 1 if ok ** e__wrongpartyp (line nr., msg-line) + */ int SdlParTyp (char *nam, unsigned char *ptyp, unsigned int typ) { static char *typn[4] = {", number", ", name", ", text", ", constant"}; char errs[MSGxXLN], errln[MSGxXLN]; int k, err_f = FALSE; (void) strcpy (errs, ""); for (k = 0; k < 4 && ptyp[k] != 0; k++) if (ptyp[k] == typ) { err_f = FALSE; break; } else { err_f = TRUE; strcat(errs, typn[ptyp[k] - SDLxPNUM]); } if (!err_f) return 1; errs[0] = ' '; /* remove ',' */ sprintf(errln, "ATTRIBUTE: %s, expected type: %s", nam, errs); _ErrRet4(e__wrongpartyp, f->n, f->nam, errln); return 1; } /****** OddIsOfVal ************************************************************ ** ** checks list of values if specified string is OK; ** ** INPUT: address of attribute-dsc. [R] ** string read [R] ** address of value [W] ** IMPLICIT: ** ** RETURNS: 1 if found ** 0 else */ int OddIsOfVal (SDLoATTR *attr, char *tokstr, unsigned int *val) { int k; SmEdit (tokstr, SMxLOWCASE); for (k=0; k < attr->val_n && strcmp (tokstr, attr->val[k].nam) != 0; k++) ; if (k==attr->val_n) return 0; else *val = attr->val[k].val; return 1; } /****** OddGetValue *********************************************************** ** ** gets next value from the symbol table, tests it and gets symbol value ** if it is a constant, or number if enumerated type; ** ** INPUT: ** attribute descriptor [R] ** address of token string [W] ** address of token value [W] ** IMPLICIT: ** ** RETURNS: 1 if value could be read ** 0 there was no token in token table ** e__icaenumval + ** e__symnotknown + ** e__symnotuniq + */ static int OddGetValue (SDLoATTR *attr, char **tokstr, unsigned *tokval, VARo *value) { int rv; *tokval = ODDxNULL; *tokstr = VarGetStr (value); /* rv = SdlParTyp (attr->nam, &attr->ptyp[0], *tokval); _ErrRet (rv);*/ *tokval = ODDxNULL; if (attr->val_n) /* check if value is one of the list */ if (!OddIsOfVal (attr, *tokstr, tokval)) _ErrRet3(e__icaenumval, *tokstr, attr->nam); return 1; } /****** SdlSaveAddr *********************************************************** ** ** Processes each attribute in a user-object and in case it is an ** address saves it in global array ** ** INPUT: object-descriptor [R] ** start address of user-object [W] ** IMPLICIT: ** addr_n (int) [W] ** addr (unsigned int *) [W] ** odd (SDLo *) [R] ** ** RETURNS: 1 */ int SdlSaveAddr (SDLoOBJ *obj, SDLoPTR uobj) { SDLoATTR *attr; SDLoPTR **off; int k, l; for (k=0; k < obj->np;) { attr = &((obj->p)[k++]); off = (SDLoPTR **) (uobj + attr->off); if (odd->at[attr->typ].save_f) for (l=0; l < attr->arrsz; l++, off++) if (*off != 0 || attr->typ == AT_FNCT) __SdlAddr ((SDLoPTR) off); } return 1; } /****** SdlCheckPar *********************************************************** ** ** tests an attribute value; ** ** INPUT: address of ATTRIBUTE description (SDLoATTR) ** address of string 0 if an int or char ** int or char ** IMPLICIT: ** ** OUTPUT: ** returns: 1 if parameter ok ** e__parnotok + */ int SdlCheckPar (SDLoATTR *attr, char *s, int v) { int (*check) (SDLoATTR *, int, char *); if ((check = odd->at[attr->typ].check) != NULL) { return (*check) (attr, v, s); } return 1; } /****** OddWriteCDefines ****************************************************** ** ** writes constant definitions into header ** ** INPUT: address of file descriptor [W] ** ** RETURNS: */ static void OddWriteCDefines (FILE *file) { ODDoCDEFINE *tmp; INT4 k; for (k=0, tmp=cDefine; k < cDefineN; k++, tmp++) fprintf(file, "#define %-16s %d\n", tmp->name, tmp->n); } /****** SdlWrtHdr ************************************************************* ** ** writes a header file that contains constant definitions, type ** declarations, and declaration + init of OBJECT s; ** ** INPUT: address of SDLo ** option: SDLxHDR, SDLxHDR2 ** ** OUTPUT: ** returns: 1 if success ** e__filopenerr, */ int SdlWrtHdr (SDLo *d, int opt) { FILE *fil; int errCode; fil = FilOpenW (d->ofnam, &errCode); _ErrExit2 (errCode, d->ofnam); SdlWrtTtl(fil, d->ifnam, d->ofnam); OddWriteCDefines (fil); SdlWrtTypDef(fil, &(d->oc[0]), d->oc_n); if (opt == SDLxHDR) SdlWrtInit(fil, &(d->oc[0]), d->oc_n); fclose(fil); return 1; } /****** OddGetAttrDeclName **************************************************** ** ** Returns the name to be used for declaring a member of a C struct for ** specified attribute object. ** ** INPUT: attribute object [R] ** ** RETURNS declaration name [R] */ char *OddGetAttrDeclName (SDLoATTR *attr) { return (*attr->dnam ? attr->dnam : attr->nam); } /****** OddGetClassDeclName *************************************************** ** ** Returns the name to be used for declaring a C struct. ** ** INPUT: class object [R] ** ** RETURNS declaration name [R] */ char *OddGetClassDeclName (SDLoOBJ *class) { return (*class->dnam ? class->dnam : class->nam); } /****** SdlWrtTtl ************************************************************* ** ** writes a title to a header file; ** ** INPUT: address of file descr. ** name of DDL- language input file ** name of output file ** ** OUTPUT: ** returns: 1 */ static int SdlWrtTtl (FILE *f, char *in, char *out) { char *time; SmEdit(in, SMxLOWCASE); SmEdit(out, SMxLOWCASE); time = SmTime (0); fprintf(f, "/******************************************************************************\n"); fprintf(f, "**\n\ ** $RCSfile: sdlnew.c,v $\n\ ** $Revision: 1.8 $\n\ ** $Date: 1996/08/11 22:47:18 $\n\ ** $Author: etzold $\n\ **\n\ ** $Locker: $\n\ ** $State: Exp $\n\ **\n"); fprintf(f,"** from ODD file: \"%s\"\n", in); fprintf(f,"** date of ODD compilation: %s\n", time); fprintf(f,"**\n"); fprintf(f,"*/\n\n\n"); return 1; } /****** SdlWrtTypDef ********************************************************** ** ** writes type definitions of all objects in header file; ** puts typdefs with #ifndef-#endif clause this allows the OBJECT ** to be defined else where; the identifier is the same as in the ** typdef but in uppercase; ** writes typdef only if at least one object of class has been ** defined; ** ** INPUT: address of file descr. [W] ** base address of array of strct defs. (SDLoOBJ) [R] ** number of strct defs. [R] ** ** RETURNS: 1 */ static int SdlWrtTypDef (FILE *fil, SDLoOBJ *s, int ns) { SDLoOBJ *obj; char *typdef_nm, *gtyp_nm = NULL; int k, l, i, gentype_f; for (k = 1; k < ns; k++) { /** for every object-class */ obj = &(s[k]); if (obj->typ == SDLxVIRTUAL) continue; else { gentype_f = obj->gtyp_n == 0 ? FALSE : TRUE; /* ** for every distinct generic type ...if any */ for (l=gentype_f ? obj->gtyp_n-1 : 0; l >= 0; l--) { if (!gentype_f) typdef_nm = obj->tnam; else { gtyp_nm = (obj->gtyp_nm)[l]; typdef_nm = (obj->gtypdef_nm)[l]; for (i=0; i < obj->gtyp_n; i++) { if (strcmp ((obj->gtyp_nm)[i], gtyp_nm) == 0) break; } if (i < l) continue; /* typedef was already written */ } /* ** write title: comment (if available) ... */ if (*obj->rem) { fprintf (fil, "\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"); fprintf (fil, "** %s\n*/\n", obj->rem); } if (*(obj->pp_nm) != '\0') /* preprocessor switch */ fprintf (fil, "\n#if defined(_%s) && !defined(_%s)\n", obj->pp_nm, typdef_nm); else fprintf (fil, "\n#ifndef _%s\n", typdef_nm); fprintf(fil, "#define _%s\n", typdef_nm); /* ...to prevent redefinit */ fprintf(fil, "typedef struct %s {\n", typdef_nm); SdlWrtAttr (fil, obj, typdef_nm, gtyp_nm); /* ** process attribues of inherited objects */ fprintf(fil, "} %s;\n#endif\n", typdef_nm); } } } /* ** print all funtion info at the end of all typdefs...function class - if ** present is the first of all classes (index=0) -> C compilers like ** that better... */ obj = &(s[0]); if (obj->typ == SDLxFNCT) SdlWrtFnct (fil, obj); return 1; } /****** SdlWrtAttr ************************************************************ ** ** Writes declaration for all attributes within a struct typedef; ** ** INPUT: address of file-dsc [W] ** address of object-dsc [R] ** address of typedef name [R] ** address of generic type [R] or NULL ** IMPLICIT: ** ** RETURNS: 1 */ static int SdlWrtAttr (FILE *fil, SDLoOBJ *obj, char *typdef_nm, char *gtyp_nm) { SDLoATTR *attr; int (*declare) (FILE *, SDLoATTR *, char *, char *); int l; for (l = 0; l < obj->np; l++) { attr = &((obj->p)[l]); if ((declare = odd->at[attr->typ].declare) != NULL) { (*declare) (fil, attr, gtyp_nm, typdef_nm); } } return 1; } /****** OddAddFunction ******************************************************** ** ** adds a new function to the list; ** ** INPUT: address of location of object function [R] ** IMPLICIT: ** function (struct []) [W] ** ** RETURNS: */ void OddAddFunction (char **loc) { function[fnct_x].nam = loc; function[fnct_x].args = loc + 1; function[fnct_x].module = loc + 2; function[fnct_x++].isDone = 0; } /****** OddOutput ************************************************************* ** ** Performs selected output operations. ** ** INPUT: odd base object [W] ** IMPLICIT: ** ** RETURNS: */ void OddOut (SDLo *odd) { if (odd->error) _ErrExit (e__procfail); if (ParGetBool ("doClassInfo")) { OddWriteClassInfo ((SDLo *) odd->oc[odd->oc_n-1].s ); } else if (odd->action != SDLxNOHDR && odd->action != SDLxSECTION && odd->action != SDLxPRESEC) { SdlWrtHdr (odd, odd->action); } if (odd->section_f) SdlCloseSec (); } /****** SdlWrtVal ************************************************************* ** ** writes a single value in header file for init. arrays of OBJECTs; ** ** INPUT: address of file descr. ** address of attribute object (SDLoATTR) ** address of current offset in target object ** address of flag saying SDLxFIRST, SDLxLAST, SDLxNORMAL ** OUTPUT: ** returns: 1 */ int SdlWrtVal (FILE *fil, SDLoATTR *attr, SDLoPTR *off, int *item_f) { static char ln[SDLxXLN], str[SDLxXLN]; int (*writeval) (); if (*item_f & SDLxLAST) { fprintf(fil, "%s%s", ln, *item_f & SDLxBOUND ? "}" : ""); *item_f = 0; return 1; } if ((writeval = odd->at[attr->typ].write) != NULL) { (*writeval) (attr, str, off); } if (*item_f & SDLxFIRST) { /* print first item */ sprintf(ln, " %s%s", *item_f & SDLxBOUND ? "{" : "", str); *item_f = 0; } else { if (*item_f & SDLxBREAK) { fprintf(fil, "%s%s,\n", ln, *item_f & SDLxBOUND ? "}" : ""); sprintf(ln, " %s%s", *item_f & SDLxBOUND ? "{" : "", str); *item_f = 0; } else if (strlen(ln) + strlen(str) + 2 >= SDLxXHLN) { fprintf(fil, "%s,\n", ln); sprintf(ln, " %s", str); } else sprintf(ln, "%s, %s", ln, str); } return 1; } /****** SdlWrtFnct ************************************************************ ** ** writes typedef for function pointer, prototypes of functions ** and array of function pointers; ** ** INPUT: output-file [W] ** Object-descriptor [R] ** IMPLICIT: ** function (struct *) [R] ** ** RETURNS: 1 ** 0 if no functions defined */ static int SdlWrtFnct (FILE *f, SDLoOBJ *s) { char args[132], *moduleName, *fnctName, tmp[80]; char *tmpPtr = tmp, **tmpPPtr, *tmpFnctName[100]; int item_f, k, i, l, n; if (s->gbl_n == 0) return 0; /* nothing to initialize */ fprintf(f, "\n#ifdef _FUNCTION\n#undef _FUNCTION\n"); /* ** define a constant with the function name - if module name is defined ** otherwise assign dummy function - defines are grouped by module name */ if (1/*odd->action != SDLxHDR*/) { for (i=0; i < s->gbl_n; i++) { for (k=i, moduleName=NULL, l=0; k < s->gbl_n; k++) { if (!function[k].isDone) { if (!moduleName) { /* new module name */ moduleName = *function[k].module; if (*moduleName) fprintf (f, "\n#ifdef %s_M\n", moduleName); else fprintf (f, "\n"); } if (!(strcmp (moduleName, *function[k].module))) { /* ** write function prototype */ fnctName = *function[k].nam; strcpy (args, *(function[k].args)); SmSwapS (args, SDLxGTYPDEFNAM, "void"); SmSwapS (args, SDLxGTYPNAM, "void"); fprintf (f, "INT4 %s ", fnctName); fprintf (f, "%s;\n", args); tmpFnctName[l++] = fnctName; /* save for "#else" */ fprintf (f, "#%sdefine %s_F (INT4(*)()) %s\n", *moduleName ? " " : "", fnctName, fnctName); function[k].isDone = 1; } } } if (moduleName && *moduleName) { fprintf (f, "#else\n"); fprintf (f,"void Dummy%s () {_ErrExit2 (e__fnctnotdefined, \"%s\");}\n", moduleName, moduleName); for (n=0; n < l; n++) fprintf (f, "# define %s_F (INT4(*)()) Dummy%s\n", tmpFnctName[n], moduleName); fprintf (f, "#endif\n"); } } } /* ** write array of function pointers - or rather with the macros ** defined just above */ if (1/*odd->action != SDLxHDR*/) { fprintf (f, "typedef INT4 (*SDLoFNCT)();\n\n"); fprintf (f, "\nSDLoFNCT SDL_fnct[] = {\n"); item_f = SDLxFIRST; for (k=0; k < s->gbl_n; k++) { tmpPPtr = &tmpPtr; sprintf (*tmpPPtr, "%s_F", *function[k].nam); SdlWrtVal (f, &(s->p[0]), (SDLoPTR *) &tmpPPtr, &item_f); } item_f = SDLxLAST; SdlWrtVal (f, &(s->p[0]), NULL, &item_f); fprintf (f, "\n};\n"); } fprintf (f, "#endif\n"); return 1; } /****** SdlWrtInit ************************************************************ ** ** initializes arrays of objects with values; ** ** INPUT: address of file descr. ** base address of array of strct defs. (SDLoOBJ) ** number of strct defs. ** ** RETURNS: 1 */ static int SdlWrtInit (FILE *fil, SDLoOBJ *s, int ns) { SDLoOBJ *obj; SDLoATTR *pptr; SDLoPTR off, trgts; int k, l, m, n, item_f; fprintf (fil, "\n#ifdef _INITOBJS\n"); for (k = 0; k < ns; k++) { /* all strct types */ obj = &s[k]; if (obj->gbl_n == 0) /* nothing to initialize */ continue; if (obj->typ == SDLxFNCT) continue; fprintf(fil, "\n%s %s[] = {\n", obj->tnam, OddGetClassDeclName (obj)); item_f = SDLxFIRST | SDLxBOUND; for (n = 0; n < obj->gbl_n; n++) { /* all alloc. strct */ trgts = obj->s + (n * obj->siz); item_f |= SDLxBREAK | SDLxBOUND; for (l = 0; l < obj->np; l++) { /* all attributes */ pptr = &(obj->p[l]); off = trgts + pptr->off; for (m = 0; m < pptr->arrsz; m++) /* all vals. in par */ /* array */ SdlWrtVal(fil, pptr, &off, &item_f); } } item_f |= SDLxLAST | SDLxBOUND; SdlWrtVal(fil, pptr, &off, &item_f); fprintf(fil, "\n};\n"); } fprintf (fil, "\n#endif\n"); return 1; } /****** SdlListAddr *********************************************************** ** ** ** INPUT: address to be put on list [R] ** IMPLICIT: ** addr_n (int) ** addr (unsigned int) ** ** RETURNS: 1 */ int SdlListAddr (SDLoPTR a) { addr[addr_n++] = a; if (addr_n > SDLxXADDR) _ErrExit3 (e__exceedsize, "array addr", SDLxXADDR); return 1; } /****** SdlCopySec ************************************************************ ** ** copies string into map-section and outputs new address ** ** INPUT: address of pointer to string [W] ** IMPLICIT: ** ** RETURNS: 1 */ static int SdlCopySec (char **s) { char *p; p = (char *) SdlMalloc (strlen (*s) + 1); strcpy (p, *s); *s = p; return 1; } /****** SdlCloseSec *********************************************************** ** ** closes a map-section and writes out file of addresses; ** ** INPUT: ** IMPLICIT: ** odd (SDLo *) ** map (MAPo) ** addr_n (int) ** addr (unsigned int) ** ** RETURNS: 1 */ static int SdlCloseSec () { FILE *fil; char ptr_nm[FILxXNAM+1], sec_nm[FILxXNAM+1]; long tmp; int rv, k, obj_n, size; sprintf (ptr_nm, "SRSSEC:%s.ptr", odd->sec_nm); sprintf (sec_nm, "SRSSEC:%s.sec", odd->sec_nm); fil = FilOpenW (ptr_nm, &rv); _ErrExit2 (rv, ptr_nm); size = (addr_n + (odd->oc_n*2) + 3) * sizeof (SDLoPTR) + sizeof (int); fwrite (&size, sizeof (int), 1, fil); /* size of ptr file */ tmp = (long) map.data + sizeof (char *); fwrite (&tmp, sizeof (SDLoPTR), 1, fil); /* addr of section begin */ tmp = odd->oc_n; fwrite (&tmp, sizeof (long), 1, fil); /* number of objects */ /* ** for each class represented in the section, write the pointer to its ** array of instances within the section and the number of instances */ for (k=0; k < odd->oc_n; k++) { fwrite (&((odd->oc)[k].s), sizeof (SDLoPTR), 1, fil); tmp = odd->oc[k].ns; fwrite (&tmp, sizeof (long), 1, fil); } tmp = addr_n; fwrite (&tmp, sizeof (long), 1, fil); /* number of references */ fwrite (addr, sizeof (SDLoPTR), addr_n, fil); /* ref. list */ fclose (fil); size = *(map.foff); rv = MapFree (&map); _ErrExit (rv); for (k=0, obj_n=0; k < odd->oc_n; obj_n += (odd->oc)[k++].ns) ; Message (9, i__sdlreport, 0, sec_nm, size / 512, ptr_nm, addr_n / 512*4, odd->ifnam, obj_n, odd->oc_n); return 1; } /****** OddWriteClassInfo ***************************************************** ** ** writes a text file with meta info about all defined classes; ** ** INPUT: address of odd base [W] ** IMPLICIT: ** ** RETURNS: */ void OddWriteClassInfo (SDLo *odd) { TEMPLv templ; SDLoOBJ *class; SDLoATTR *attr; char *typeName[30]={"real", "number", "number", "", "string", "", "list of", "", "", "pointer to", "", "function", "", "", "", "", "", "", "", "", "", "BNF-productions", "", "", "", "", "", "", "" }; int i, k, l, isPointer; /* ** open script and print first a directory of all classes */ templ = TemplOpen ("SRSICA:srswww.i", NULL); TemplWith (templ, "$classInfo"); /* TemplPrint ("dir.head", TimeToString (0, "date")); for (k=0; k < odd->oc_n; k++) { class = &(odd->oc[k]); if (OddIsClass (class, "system") || OddIsClass (class, "obsolete")) continue; SmEdit (class->nam, SMxLOWCASE); class->nam[0] = toupper (class->nam[0]); TemplPrint ("dir.class", k, class->nam); } TemplPrint ("dir.tail"); */ /* ** then the classes + attributes */ TemplPrint ("head", TimeToString (0, "date")); for (k=0; k < odd->oc_n; k++) { class = &(odd->oc[k]); if (OddIsClass (class, "system") || OddIsClass (class, "obsolete")) continue; TemplPrint ("class.head", k, class->nam); TemplPrint ("class.remark", class->rem); /* ** attribute information */ TemplWith (templ, "class.attrib"); for (l=0; l < class->np; l++) { attr = &(class->p[l]); if (*attr->nam && !OddIsAttr (attr, "obsolete") && ! OddIsAttr (attr, "system")) { SmEdit (attr->nam, SMxLOWCASE); TemplPrint ("head", attr->nam); /* print comment */ TemplPrint (*attr->rem ? "remark" : "empty", attr->rem); /* unnamed */ TemplPrint (attr->unnamed ? "unnamed" : "empty"); /* required */ TemplPrint (attr->req ? "required" : "empty"); /* attribute type */ isPointer = 0; TemplPrint ("typeHead"); if (attr->val_n) { /* list of string values */ TemplPrint ("optionList.head"); for (i=0; i < attr->val_n; i++) TemplPrint ("optionList.option", attr->val[i].nam); TemplPrint ("optionList.tail"); } else if (*typeName[attr->typ] == 'p') { /* pointer */ TemplPrint ("ptrType",typeName[attr->typ], odd->oc[attr->dfltv].nam); isPointer = 1; } else if (*typeName[attr->typ] == 'l') { TemplPrint ("listType", odd->oc[attr->dfltv].nam); isPointer = 1; } else if (*typeName[attr->typ] == 'p') { TemplPrint ("ptrType",typeName[attr->typ], odd->oc[attr->dfltv].nam); isPointer = 1; } else if (*typeName[attr->typ]) TemplPrint ("type", typeName[attr->typ]); /* min + max */ if (attr->min != -1000000000 && attr->max != 1000000000) { if (attr->typ == 4) TemplPrint ("minmaxStr", attr->min, attr->max); else TemplPrint ("minmaxNum", attr->min, attr->max); } /* array of max number of elements */ if (attr->arrsz > 1) TemplPrint ("arrSize", attr->arrsz); TemplPrint ("typeTail"); /* default value */ if (attr->val_n) { for (i=0; i < attr->val_n; i++) if (attr->val[i].val == attr->dfltv) { TemplPrint ("default.option", attr->val[i].nam); break; } if (i >= attr->val_n) TemplPrint ("empty"); } else if (*attr->dflts) TemplPrint ("default.string", attr->dflts); else if (attr->dfltv != 0 && !isPointer) TemplPrint ("default.num", attr->dfltv); else if (attr->dfltvf != 0) TemplPrint ("default.num", attr->dfltvf); else TemplPrint ("empty", attr->dfltvf); TemplPrint ("tail"); TemplPrint ("infoEnd"); } } TemplEndWith (); TemplPrint ("class.tail"); } TemplEndWith (); } /**api* OddIsAttr ************************************************************* ** ** returns some boolean information about the attribute; ** ** INPUT: attribute object [R] ** option: "obsolete", "system", "api" [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 OddIsAttr (SDLoATTR *attr, char *option) { int k; switch (tolower (option[0])) { case 'a': /* api */ for (k=0; k < 2; k++) if (attr->status[k] == (unsigned char) ODDxAPI) return 1; break; case 'o': /* obsolete */ for (k=0; k < 2; k++) if (attr->status[k] == (unsigned char) ODDxOBSOLETE) return 1; break; case 's': /* system */ for (k=0; k < 2; k++) if (attr->status[k] == (unsigned char)ODDxSYSTEM) return 1; break; default: _ErrExit2 (e__unknownoption, option); } return 0; } /**api* OddIsClass ************************************************************ ** ** returns some boolean information about the class; ** ** INPUT: class object [R] ** option: "obsolete", "system", "api" [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 */ INT4 OddIsClass (SDLoOBJ *class, char *option) { int k; switch (tolower (option[0])) { case 'a': /* api */ for (k=0; k < 2; k++) if (class->status[k] == (unsigned char) ODDxAPI) return 1; break; case 'o': /* obsolete */ for (k=0; k < 2; k++) if (class->status[k] == (unsigned char) ODDxOBSOLETE) return 1; break; case 's': /* system */ for (k=0; k < 2; k++) if (class->status[k] == (unsigned char)ODDxSYSTEM) return 1; break; default: _ErrExit2 (e__unknownoption, option); } return 0; } /*****************************************************************************/ char seq_srs_ID[] = "$Id: seq.c,v 1.6 1996/07/30 10:48:32 etzold Exp $"; /* ** ** $RCSfile: seq.c,v $ ** $Revision: 1.6 $ ** $Date: 1996/07/30 10:48:32 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message, list ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "sm.h" #include "strv.h" #include "futil.h" #include "lst.h" #include "par.h" #include "icarus.h" #include "icaarg.h" #define _INITOBJS #include "seq.h" #ifdef sun extern INT4 printf (); #endif typedef char TABLE[4][4][4]; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ static char SeqTranslCodon (char *triplett, SEQoTranslTable *transTable, INT4 isStartCodon); static void SeqTranslTableEdit (SEQoTranslTable *tTable, SEQoTranslCodon *tCodon); static void SeqTranslTableRevert (SEQoTranslTable *tTable); static INT4 *SeqGetTranslNtOrder (); static void SeqDump (FILE *file, void *obj); static void SeqInit (void *obj); static void SeqKill (void *obj); static INT4 SeqBinToAscii (char *seq, INT4 len); static INT4 SeqTest (FILo *file); static INT4 SeqCopy (SEQo *seq, char *s, INT4 read_o); static INT4 SeqReadPirSeq (SEQo **seq, FILo *file); static INT4 SeqReadEMBLSeq (SEQo **seq, FILo *file); static INT4 SeqReadGCGSeq (SEQo **seq, FILo *file); static INT4 SeqReadMSFSeq (SEQo **seq, FILo *file); static INT4 SeqMSFNam (char *name, char *file_nm, char *seq_nm); static INT4 SeqGCGCheck(char *seq, INT4 len); static INT4 SeqWrite (char *seq, INT4 len, INT4 line_n, INT4 block_n, INT4 format_o, INT4 (*print)(char*,...)); static void SeqAlloc (SEQo *seq, INT4 len); static void SeqMakeOwn (SEQo *seq); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** global variables */ INT4 global_before_f; INT4 global_after_f; static INT4 recordSeparatorLength=0; /**api* SeqNew *************************************************************** ** ** gets a new initialized sequence object; ** ** INPUT: pointer to address of sequence object [W] ** IMPLICIT: ** ** RETURNS: */ INT4 SeqNew (SEQo **seq) { static INT4 seqtype_id=0; if (!seqtype_id) LstManageClass (&seqtype_id, sizeof (SEQo), SeqInit, SeqKill, SeqDump); return LstNew ((void **) seq, seqtype_id); } /****** SeqDump ************************************************************** ** ** dumps all information belonging to the specified object. ** This is the print function set through LstManageClass ** for seq_type objects (see SeqNew). ** ** INPUT: address of an object [R] ** file pointer [W] or NULL ** IMPLICIT: ** ** RETURNS: nothing */ static void SeqDump (FILE *file, void *obj) { SEQo *tmp = (SEQo*)obj; if (!file) file = stderr; fprintf (file, "*%s*\n", tmp->name); fprintf (file, "......accno: %10s bpos %d epos %d compl_f %d\n", tmp->accno, tmp->bpos, tmp->epos, (INT4)tmp->compl_f); if (tmp->seq) printf ("......*%s*......\n", tmp->seq); /* print sublist, i.e. parameter list of function */ if (tmp->sublist) { fprintf (file, "SUBLIST "); LstPrintAll ((void*) tmp->sublist); } } /****** SeqInit ************************************************************** ** ** initializes the specified object. ** This is the init function set through LstManageClass ** for seq_type objects (see SeqNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void SeqInit (void *obj) { SEQo *tmp = (SEQo*) obj; strcpy(tmp->name, ""); /* dummy values */ tmp->cmnt = NULL; tmp->seq = NULL; tmp->replace = NULL; tmp->len = 0; tmp->check = 0; tmp->bpos = 0; tmp->epos = 0; tmp->part_len = 0; strcpy(tmp->accno, ""); /* dummy values */ tmp->keep_f = 0; tmp->compl_f = 0; tmp->cut_f = 0; tmp->before_f = 0; tmp->after_f = 0; tmp->sublist = NULL; } /****** SeqKill ************************************************************** ** ** deletes the specified object. ** This is the delete function set through LstManageClass ** for seq_type objects (see SeqNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void SeqKill (void *obj) { SEQo *tmp = (SEQo*) obj; if (tmp->seq) free(tmp->seq); if (tmp->cmnt) free(tmp->cmnt); if (tmp->replace) free(tmp->replace); /* delete sublist ? */ if (tmp->sublist) LstDeleteAll((void**)&tmp->sublist); } /****** SeqBinToAscii ********************************************************* ** ** Converts sequence of 2-bit GATC to ASCII; corresponds to ** GCG procedures BinToSeq, BinToFilter and BinToGATC; ** ** INPUT: address of compressed sequence [W] (must be able to hold ** it when decompressed) ** sequence length [R] ** IMPLICIT: ** ** RETURNS: 1 */ static INT4 SeqBinToAscii (char *seq, INT4 len) { static char nuc[] = "CTAG", fstcall_f = TRUE; static UINT4 tbl[256]; UINT4 *seqPtr = (UINT4 *) seq; unsigned char *binseq, *buff; INT4 i, k, l, m, n, x; if (fstcall_f) { /* ** make a table of translations from a byte with encoded sequence ** to an array of 4 ascii characters */ fstcall_f = FALSE; for (k=0, x=0; k < 4; k++) for (l=0; l < 4; l++) for (m=0; m < 4; m++) for (n=0; n < 4; n++) tbl[x++] = nuc[k] + 256 * nuc[l] + 65536 * nuc[m] + 16777216 * nuc[n]; } /* ** convert unsigned characters with 4 ecoded nucleotide names into ** unsigned ints (in reality an array of 4 ascii characters); start ** from the end of the sequence...then we can do the replacement ** "within" the string; ** the base address of array seq_p (=seq) must be aligned on 4 byte ** boundary!!! ** ** slightly more complicated since we have the little-big endian problem ** again...the 4 byte value in "tbl" (which is a four letter sequence) is ** LITTLE endian...it needs to be converted to platform dependent format ** which is done by the shifting; */ i = ((len+3)/4)-1; binseq = (unsigned char *) seq; for (; i >= 0; i--) { buff = (unsigned char *) &tbl[binseq[i]]; seqPtr[i] = ((UINT4) ((unsigned char) buff[0])) + ((UINT4) ((unsigned char) buff[1]) << 8) + ((UINT4) ((unsigned char) buff[2]) << 16) + ((UINT4) ((unsigned char) buff[3]) << 24); } seq[len] = '\0'; return 0; } /****** SeqRemoveStop ********************************************************* ** ** Removes trailing stop codon from sequence. ** ** INPUT: sequence object [W] ** IMPLICIT: ** ** RETURNS: */ void SeqRemoveStop (SEQo *seq) { if (seq->seq[seq->len-1] == '*') seq->seq[ --(seq->len) ] = '\0'; } /****** SeqTranslate ********************************************************* ** ** Translates a DNA sequence into protein; ** The translation is controlled by the translation table, the list ** of translation exceptions and the list of codon changes to be ** applied to the translation table. ** ** INPUT: o address dna sequence object [R] ** o start position (begin=1) [R] ** o translation table [R] ** o array of translation exception descriptions [R] or NULL ** o array of codon changes to be applied to the ** translation table [R] or NULL ** IMPLICIT: ** ** RETURNS: translated protein sequence ** NULL if there was a problem */ SEQo *SeqTranslate (SEQo *dna, INT4 start, SEQoTranslTable *tTable, SEQoTranslExcept *tExcept, SEQoTranslCodon *tCodon) { SEQoTranslExcept *tExceptNext; SEQo *prot=NULL; INT4 k, l, isFirst=1; char aa; if (dna->len - start + 1 < 3) { _ErrMsg3 (e__seqillegallength, start, dna->len); return NULL; } if (tCodon) SeqTranslTableEdit (tTable, tCodon); SeqNew (&prot); SeqAlloc (prot, (dna->len - start)/3 + 100); for (k=start-1, l=0, tExceptNext=tExcept; k < dna->len-1;) { /* deal with possible translation exception */ if (tExceptNext && k == tExceptNext->begin-1) { isFirst=0; prot->seq[l++] = tExceptNext->aa; k += tExcept->length; tExceptNext->isDone = 1; tExceptNext = (++tExceptNext)->aa ? tExceptNext : NULL; } else if (isFirst) { /* first codon */ isFirst = 0; if ((aa = SeqTranslCodon (&dna->seq[k], tTable, 1)) == 'M') { prot->seq[l++] = aa; k += 3; } else global_before_f-- ; } else { prot->seq[l++] = SeqTranslCodon (&dna->seq[k], tTable, 0); k += 3; } } prot->seq[l] = '\0'; prot->len = l; if (tCodon) /* remove edited translation table again */ SeqTranslTableRevert (tTable); SeqRemoveStop (prot); sprintf (prot->name, "%s_aa", dna->name); return prot; } /****** SeqTranslCodon ******************************************************** ** ** Translates a nucleotide triplett into an amino acid. ** The triplett may contain ambiguity codes. ** If the last nucleotide is missing an 'x' is assumed. ** ** INPUT: nucleotide triplett [R] ** the translation table [R] ** a flag if to translate the start codon [R] ** IMPLICIT: ** ** RETURNS: the translated amino acid. */ char SeqTranslCodon (char *triplett, SEQoTranslTable *transTable, INT4 isStartCodon) { static char *ntAmbigList[26]={ "A","CGT","C","AGT","","","G","ACT","", "","GT","","AC","GATC","","","","AG", "CG","T","U","ACG","AT","ACGT","CT",""}; INT4 k, l, m, *order; char b1, b2, b3, aa, aaPrev=0, *ntList[3], *aaTrans; order = SeqGetTranslNtOrder (); aaTrans = isStartCodon ? transTable->saa : transTable->aa; /* The triplett might contain ambiguity codes: assign to each base in the triplett the list of possible nucleotides Make the last nucleotide an 'x' if it is missing */ for (k=0; k<3; k++) { b1 = tolower(triplett[k]); ntList[k] = ntAmbigList[(b1 ? b1 : 'x') - 'a']; } /* get all indices into the aa transl list for all combinations */ aa = 'X'; for (k=0; (b1=ntList[0][k]); k++) for (l=0; (b2=ntList[1][l]); l++) for (m=0; (b3=ntList[2][m]); m++) { aa = aaTrans[order[b1]*16 + order[b2]*4 + order[b3]]; if (aaPrev && aa != aaPrev) { aa = 'X'; break; aaPrev = aa; } } return aa; } /****** SeqTranslTableEdit **************************************************** ** ** Translates a nucleotide triplett into an amino acid. ** The triplett may contain ambiguity codes. ** ** INPUT: nucleotide triplett [R] ** the translation table [R] ** a flag if to translate the start codon [R] ** IMPLICIT: ** ** RETURNS: the translated amino acid. */ static void SeqTranslTableEdit (SEQoTranslTable *tTable, SEQoTranslCodon *tCodon) { SEQoTranslCodon *tmp; INT4 *order; char *swap, *nt; order = SeqGetTranslNtOrder (); if (!tTable->aaAlt) tTable->aaAlt = (char *) malloc (strlen (tTable->aa) + 1); strcpy (tTable->aaAlt, tTable->aa); swap = tTable->aa; tTable->aa = tTable->aaAlt; tTable->aaAlt = swap; for (tmp = tCodon; tmp->aa; tmp++) { nt = tmp->codon; tTable->aa[ order[*nt++]*16 + order[*nt++]*4 + order[*nt] ] = tmp->aa; } } /****** SeqTranslTableRevert ************************************************** ** ** Reverts edited table to original version. ** ** INPUT: translation table [W] ** IMPLICIT: ** ** RETURNS: */ static void SeqTranslTableRevert (SEQoTranslTable *tTable) { char *swap; swap = tTable->aa; tTable->aa = tTable->aaAlt; tTable->aaAlt = swap; } /****** SeqTaxaToTranslTable ************************************************** ** ** Searches various taxa (case insensitive) to find the appropriate ** translation table; ** ** INPUT: address of buffer with organism source information ** IMPLICIT: ** ** RETURNS: the translation table */ SEQoTranslTable *SeqTaxaToTranslTable (SMoBUFF *org) { INT4 id; if (BuffSearch(org,"Protozoa") && BuffSearch(org,"Cili") && !BuffSearch(org,"Mitoch")) id = 6; else if (BuffSearch(org,"Mitochond") && BuffSearch(org,"Yeast")) id = 3; else if (BuffSearch(org,"Mitochond") && (BuffSearch(org,"Podospora") || BuffSearch(org,"Protozoa")) || BuffSearch (org, "Mycoplasma")) id = 4; else if (BuffSearch(org,"Mitochond") && (BuffSearch(org,"Vertebrata") || BuffSearch(org,"Mammalia"))) id = 2; else if (BuffSearch(org,"Mitochond") && BuffSearch(org,"Echinoderm")) id = 9; else if (BuffSearch(org,"Mitochond")) id = 5; else if (BuffSearch(org,"Bacteri") || BuffSearch(org,"Chloroplast") ) id = 11; else if (BuffSearch(org,"Platyhelminthes")) id = 14; else id = 1; /* standard */ return (SeqIdToTranslTable (id)); } /****** SeqIdToTranslTable ************************************************** ** ** Returns the translation table with specified (numeric) ID. ** ** INPUT: the id (1 to ?) [R] ** IMPLICIT: ** ** RETURNS: the translation table ** NULL if not found */ SEQoTranslTable *SeqIdToTranslTable (INT4 id) { SEQoTranslTable *tmp=translTable; for (tmp=translTable; *tmp->name; tmp++) if (tmp->id == id) return tmp; return NULL; } /****** SeqGetTranslNtOrder ************************************************** ** ** Gets the order for the nucleotides to be used to correspond a codon ** to an amino acid in the translation table ** ** INPUT: ** IMPLICIT: ** ** RETURNS: an array where the nt character addresses the order */ static INT4 *SeqGetTranslNtOrder () { static INT4 isInit=0, order[300]; if (!isInit) { order['T'] = 0; order['C'] = 1; order['A'] = 2; order['G'] = 3; isInit = 1; } return order; } /****** SeqComplement ********************************************************* ** ** reverse complements a dna sequence; ** processes also GCG ambiguity codes; ** ** INPUT: address of dna sequence object [W] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ INT4 SeqComplement (SEQo *seq) { INT4 i,j; char c, *s=seq->seq; if (!s) return 0; /* swap flags */ i = global_before_f; global_before_f = global_after_f; global_after_f = i; for (i=0, j=seq->len-1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } for (i=0; i < seq->len; i++) switch (s[i]) { case 'A': s[i] = 'T'; break; case 'C': s[i] = 'G'; break; case 'G': s[i] = 'C'; break; case 'T': s[i] = 'A'; break; case 'U': s[i] = 'A'; break; case 'M': s[i] = 'K'; break; case 'R': s[i] = 'Y'; break; case 'W': s[i] = 'W'; break; case 'S': s[i] = 'S'; break; case 'Y': s[i] = 'R'; break; case 'K': s[i] = 'M'; break; case 'V': s[i] = 'B'; break; case 'H': s[i] = 'D'; break; case 'D': s[i] = 'H'; break; case 'B': s[i] = 'V'; break; case 'X': s[i] = 'X'; break; case 'N': s[i] = 'N'; break; case 'a': s[i] = 't'; break; case 'c': s[i] = 'g'; break; case 'g': s[i] = 'c'; break; case 't': s[i] = 'a'; break; case 'u': s[i] = 'a'; break; case 'm': s[i] = 'k'; break; case 'r': s[i] = 'y'; break; case 'w': s[i] = 'w'; break; case 's': s[i] = 's'; break; case 'y': s[i] = 'r'; break; case 'k': s[i] = 'm'; break; case 'v': s[i] = 'b'; break; case 'h': s[i] = 'd'; break; case 'd': s[i] = 'h'; break; case 'b': s[i] = 'v'; break; case 'x': s[i] = 'x'; break; case 'n': s[i] = 'n'; break; } return 1; } /**api** SeqClr *************************************************************** ** ** deletes all sequence-descriptors ** in the list; ** ** INPUT: pointer to address of sequence object [W] ** ** IMPLICIT: ** ** RETURNS: 1 */ void SeqClr (SEQo **seq) { LstDeleteAll ((void **) seq); *seq = NULL; } /**api* SeqClean ************************************************************** ** ** removes sequences with seq->keep_f == FALSE; sets seq->keep_f ** of kept sequences to FALSE; sets list pointer to the first element ** in the set; ** ** INPUT: ** IMPLICIT: ** ** RETURNS: 1 */ void SeqClean (SEQo **seq) { LstFirst ((void **) seq); do { if (!(*seq)->keep_f) LstDelete ((void **) seq); else (*seq)->keep_f = FALSE; } while (LstNext ((void **) seq)); LstFirst ((void **) seq); } /****** SeqTest *************************************************************** ** ** reads a file, tests line for any of the tokens described for ** TestSeqFormat, and returns if something is found; ** ** INPUT: address of file-dsc. [W] ** IMPLICIT: ** ** RETURNS: token-value */ static INT4 SeqTest (FILo *file) { INT4 x, lineNoSave=0; while (!file->eof) { if (file->l[0] == '>') { file->l++; return SEQxRANGLE; } if (file->l[2] == ';') { file->l++; return SEQxSEMICOLON; } if ((x = SmLoc (file->l, "Check:")) != -1) { file->l += x + 1; return SEQxCHECK; } if ((x = SmLoc (file->l, "..")) != -1) { file->l += x + 1; return SEQxDOTDOT; } /* ** recognize EMBL format by "SQ Sequence" line followed by ** line starting with " ". */ if (SmMixLoc (file->l, "SQ Sequence", 1, 1) != -1) lineNoSave = file->n; if (SmMixLoc (file->l, " ", 1, 1) != -1) if (file->n == lineNoSave + 1) return SEQxEMBL; FilURead (file); } return e__eof; } /**api* SeqGoGcgDots ********************************************************** ** ** searches for ".." and sets file pointer to following line - if not ** found file pointer is set at begin of file ** ** INPUT: address of file-dsc. [W] ** IMPLICIT: ** ** RETURNS: 1 if dots were found ** 0 if not */ INT4 SeqGoGcgDots (FILo *file) { FILoL_S savepos; FilUSave (file, &savepos); while (!file->eof) { if (SmLoc (file->l, "..") != -1) { FilURead (file); return 1; } FilURead (file); } FilUBack (file, &savepos); file->eof = 0; return 0; } /****** SeqTestFormat ********************************************************* ** ** takes an opened file, analyzes file for sequence format: ** o GCG, if there is a line with a "Check:" followed by "..", either ** on same or following line; ** o GCG-MSF, if "Check:", ".." is followed by "//" in first column; ** o PIR, if a line with '>' in first column followed by ';' with ** a distance of 3 columns ** o PEARSON or FASTA if only the '>' is found; ** if a format could be dtermined then file pointer is set at beginning ** of sequence that is: GCG or GCG-MSF: line with ".." ** PIR, PEARSON: line with ">" ** ** INPUT: address of file-dsc [W] ** IMPLICIT: ** ** RETURNS: if format found: SEQxGCG, SEQxMSF, SEQxPIR, SEQxPEARSON ** else: 0 */ static INT4 SeqTestFormat (FILo *file) { INT4 rv, format=0, gcg_f=0, check_f=0; do { rv = SeqTest (file); if (rv == SEQxEMBL) { format = SEQxEMBL; break; } if (rv == SEQxRANGLE) format = SEQxPIR; if (rv == SEQxPIRTOKENS) format = SEQxPIR; if (rv == SEQxCHECK) { if (gcg_f) { format = SEQxMSF; FilUBack2 (file); } else check_f = TRUE; } if (rv == SEQxDOTDOT && check_f) { FilUSave2 (file); gcg_f = TRUE; check_f = FALSE; } } while (rv != e__eof && !format); if (gcg_f && !format) { format = SEQxGCG; FilUBack2 (file); } return format; } /****** SeqCopy *************************************************************** ** ** adds sequence to existing sequence ** with or without filtering (i.e. copies only alphanums and ".', \"-") ** ** INPUT: address of sequence descriptor [W] ** address of sequence string [R] ** copy option: SEQxFILTER, or 0 [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 if sequence terminator was found ('*') */ static INT4 SeqCopy (SEQo *seq, char *stream, INT4 option) { static SMoBUFF *buff=NULL; INT4 rv=1; if (!buff) buff = BuffNew (1000); if (seq->seq == NULL) /* begin of new sequence? */ BuffReset (buff); /* ** process single characters...filter nonsequence characters out */ if (option == SEQxFILTER) { for (; *stream != '\0'; stream++) { if (isalpha (*stream) || *stream == '-' || *stream == '.') BuffCopyChar (buff, *stream); else if (*stream == '*') { /* terminator */ rv = 0; break; } } BuffCopyChar (buff, '\0'); BuffShiftCurrPtr (buff, -1); /* 0 char will be overwritten by next call */ } else { /* sequence is trustworthy...copy without looking at the content */ BuffCopyString (buff, stream); } seq->len = BuffGetCurrOffset (buff); seq->seq = BuffGetPtr (buff); return rv; } /****** SeqReadPirSeq ********************************************************* ** ** assumes that file->ln contains title line >...; ** reads a sequence in PIR format from file; ** ** INPUT: pointer to address of sequence object [R] ** file object (opened for reading) [W] ** ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if either wrong format or EOF */ static INT4 SeqReadPirSeq (SEQo **seq, FILo *file) { SeqNew (seq); sscanf (&file->ln[4], "%s", (*seq)->name); FilURead (file); strcpy ((*seq)->cmnt, file->ln); while (FilURead (file) != e__eof) if (!SeqCopy (*seq, file->ln, SEQxFILTER)) break; SeqMakeOwn (*seq); return 1; } /****** SeqReadEMBLSeq ******************************************************** ** ** Assumes that file pointer is at begin of sequence. ** Reads a sequence in EMBL format from file; ** ** INPUT: pointer to address of sequence object [R] ** file object (opened for reading) [W] ** ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if either wrong format or EOF */ static INT4 SeqReadEMBLSeq (SEQo **seq, FILo *file) { SeqNew (seq); do { if (!SeqCopy (*seq, file->ln, SEQxFILTER)) break; } while (FilURead (file) != e__eof); SeqMakeOwn (*seq); return 1; } /****** SeqReaddGCGSeq ******************************************************** ** ** reads GCG -sequence from file; assumes that file->ln contains line ** with >..<; ** ** INPUT: pointer to address of sequence object [R] ** file object (opened for reading) [W] ** IMPLICIT: ** ** RETURNS: 1 */ static INT4 SeqReadGCGSeq (SEQo **seq, FILo *file) { SeqNew (seq); FilParse (file->nam, (*seq)->name, FILxNAME); while (FilURead (file) != e__eof) { if (!SeqCopy (*seq, file->ln, SEQxFILTER)) break; } SeqMakeOwn (*seq); return 1; } /****** SeqReadMSFSeq ********************************************************* ** ** assumes that file->ln contains line with /../; ** reads all sequences from MSF-file; ** ** INPUT: pointer to address of sequence object [R] ** file object (opened for reading) [W] ** IMPLICIT: ** ** RETURNS: number of sequences read */ static INT4 SeqReadMSFSeq (SEQo **seq, FILo *file) { char seq_nm[SEQxXNAM+1]; INT4 seq_n, max_nmz, nam_z, seq_f, seq_z; for (seq_n=0, max_nmz=0, seq_f=FALSE; FilURead (file) != e__eof;) { /* ** after the two dots all sequences occuring in the msf file are listed ** one name per row, each row starts with "Name:" */ if (!seq_f) { if (sscanf (file->ln, " Name: %s Len: %d", seq_nm, &seq_z) == 2) { SeqNew (seq); strcpy ((*seq)->name, seq_nm); SeqAlloc ((*seq), seq_n); /** allocate sequence buffer */ seq_n++; if ((nam_z = strlen (seq_nm)) > max_nmz) max_nmz = nam_z; /** size of longest name -> identation length */ } else if (SmLoc (file->ln, "//") != -1) seq_f = TRUE; /** sequences start after that */ } /* ** block with sequences is being processed */ else { /* ** read sequence name -> length is determined by longest name... ** if the string is not empty (line might be a number line ...) ** then the sequence must be copied -> get the sequence object ** by the name just read; */ strncpy (seq_nm, file->ln, max_nmz); SmEdit (seq_nm, SMxTRIM); if (seq_nm[0] != ' ') { LstFirstNamed ((void **) seq, seq_nm); /** assumes names are unique */ SeqCopy (*seq, &file->ln[max_nmz], SEQxFILTER); } } } return seq_n; } /**API* SeqReadAll ************************************************************ ** ** Opens file, tests format and reads sequence(s) if format could ** be determined. ** The following formats are understood: PIR, FASTA, EMBL, GCG, MSF. ** ** INPUT: address of pointer to sequence object [W] ** file name [R] ** IMPLICIT: ** ** RETURNS: number of sequences read; ** e__novalseqform + ** e__filnotok + */ INT4 SeqReadAll (SEQo **seq, char *fil_nm) { FILo *file; INT4 seq_n=0, rv; rv = FilUOpen2 (&file, fil_nm, SEQxXLN, FILxVAR); _ErrIf (rv) { _ErrMsg2 (rv, fil_nm); return 0; } rv = SeqTestFormat (file); switch (rv) { case SEQxGCG: seq_n = SeqReadGCGSeq (seq, file); break; case SEQxMSF: seq_n = SeqReadMSFSeq (seq, file); break; case SEQxPIR: do { SeqReadPirSeq (seq, file); seq_n++; } while (SeqTestFormat (file) == SEQxPIR); break; case SEQxPEARSON: break; case SEQxEMBL: seq_n = SeqReadEMBLSeq (seq, file); break; default: _ErrMsg3 (e__novalseqform, fil_nm, "GCG, GCG-MSF, PIR, FASTA, EMBL"); } FilUClose2 (file); return seq_n; } /**api* SeqReadPIR ************************************************************ ** ** reads a sequence in PIR format; ** ** INPUT: pointer to address of sequence object [W] ** file name [R] ** IMPLICIT: ** ** RETURNS: number of sequences read ** e__novalseqform + ** e__filnotok + */ INT4 SeqReadPIR (SEQo **seq, char *fil_nm) { FILo *file; INT4 k, rv; rv = FilUOpen2 (&file, fil_nm, SEQxXLN, FILxVAR); _ErrRet2(rv, fil_nm); for (k=0; SeqTestFormat (file) == SEQxPIR; k++) SeqReadPirSeq (seq, file); FilUClose2 (file); if (k==0) _ErrRet3 (e__novalseqform, fil_nm, "PIR"); return k; } /**api* SeqReadGCG ************************************************************ ** ** reads either single GCG files or GCG-MSF-file or file-of-names; ** ** INPUT: pointer to address of sequence object [W] ** name (GCG-file name) [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 SeqReadGCG (SEQo **seq, char *name) { #ifndef dos char file_nm[FILxXNAM]; UINT4 context = 0; if (strchr (name, '{') != NULL) SeqReadMSF (seq, name); else while (FilSearch (name, file_nm, &context) != 0) SeqReadGCGFile (seq, file_nm); #endif return 1; } /**api* SeqReadGCGFile ******************************************************** ** ** opens a sequence in GCG-format and reads sequence into global seqbuff; ** sequence-info goes into sequence-descriptor; ** file-NAME is copied to sequence-name ** ** INPUT: pointer to address of sequence object [W] ** name (GCG-file name) [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** e__allocfail + ** e__novalseqform + */ INT4 SeqReadGCGFile (SEQo **seq, char *fil_nm) { FILo *file; INT4 rv; rv = FilUOpen2 (&file, fil_nm, SEQxXLN, FILxVAR); _ErrRet2 (rv, fil_nm); if (SeqTestFormat (file) != SEQxGCG) _ErrRet3 (e__novalseqform, fil_nm, "GCG"); rv = SeqReadGCGSeq (seq, file); FilUClose2 (file); return 1; } /****** SeqMSFNam ************************************************************* ** ** analyzes a name that specifies a set of sequences in MSF file ** file name must have "{*}" at the end; ** ** INPUT: o address of input string [R] ** o address that receives filename part [W] ** o address that receives seqname part [W] ** wildcard will be removed ** IMPLICIT: ** ** RETURNS: 0 if no wildcard ** 1 if yes */ static INT4 SeqMSFNam (char *name, char *file_nm, char *seq_nm) { char *off; INT4 l; for (l=0; *name != '{' && *name; name++, l++) file_nm[l] = *name; file_nm[l] = '\0'; for (l=0; *(++name) != '}' && *name; l++) seq_nm[l] = *name; seq_nm[l] = '\0'; if ((off = (char *) strchr (seq_nm, '*')) == NULL) return 0; else *off = '\0'; return 1; } /**api* SeqReadMSF ************************************************************ ** ** reads all sequences in an MSF file; ** file name must have "{*}" at the end; ** ** INPUT: pointer to address of sequence object [W] ** name of MSF file [R] ** IMPLICIT: ** ** RETURNS: number of sequences read ** e__novalseqform + ** e__filnotok + */ INT4 SeqReadMSF (SEQo **seq, char *msf_nm) { FILo *file; char fil_nm[SEQxXNAM+1], seq_nm[SEQxXNAM+1]; INT4 rv, seq_n; SeqMSFNam (msf_nm, fil_nm, seq_nm); seq_n = 0; rv = FilUOpen2 (&file, fil_nm, SEQxXLN, FILxVAR); _ErrRet2 (rv, fil_nm); if (SeqTestFormat (file) != SEQxMSF) _ErrRet3 (e__novalseqform, fil_nm, "GCG-MSF"); seq_n = SeqReadMSFSeq (seq, file); FilUClose2 (file); return seq_n; } /**api* SeqSetRecordSeparator ************************************************* ** ** GCG 7.x format on VMS has a single char separating records. ** SeqFromLib must ignore that. ** ** INPUT: length of separator [R] ** IMPLICIT: ** recordSeparatorLength (INT4) [W] ** ** RETURNS: */ void SeqSetRecordSeparator (INT4 i) { #ifdef VMS recordSeparatorLength = i; #else recordSeparatorLength = 0; #endif } /**api* SeqFromLib ************************************************************ ** ** reads sequence file from current position - assumes that the ** title line is just read in and reads comment plus sequence; ** ** INPUT: o address of sequence object [W] ** o address of file-descriptor [W] ** o optional scanf format string to extract the name [R] or ** NULL ** o string that marks the end of the sequence [R] ** o flag determines if first line after title is a comment line ** else the title line is read into comment [R] ** IMPLICIT: ** ** RETURNS: 1 ** e__eof */ INT4 SeqFromLib (SEQo **seq, FILo *file, char *findId, char *exitstr, INT4 options) { INT4 k, l, off, len, seq_z, readchar_n, rv=1, gcgascii_f = FALSE, gcgbin_f = FALSE; SeqNew (seq); /* ** edit first entry line and get entry name */ SmEdit (file->ln, SMxUPCASE); SmXLoc (file->ln, exitstr, 1, 1); if (findId) sscanf (file->ln, findId, (*seq)->name); else sscanf (file->ln, "%s", (*seq)->name); /* ** if this is a gcg sequences then it has a length field and either 2BIT ** or ASCII */ if ((off = SmLoc (file->ln, "LEN:")) != -1) { sscanf (&((file->ln)[off]), "LEN: %d", &seq_z); if (SmLoc (file->ln, "2BIT") != -1) gcgbin_f = TRUE; if (SmLoc (file->ln, "ASCII") != -1) gcgascii_f = TRUE; } /* ** read and copy second line of entry with comment to the sequence */ if (options & 1) { if (FilURead (file) == e__eof) return e__eof; } /* strcpy (seq->cmnt, file->ln); */ /* ** read the binary encoded sequence (length = sequence len * 4 ... some ** extra info is read if the last byte is not completely used; then ** convert the sequence to ascii format; seq->seq must be aligned to 4 byte ** boundary for SeqBinToAsci - SeqMalloc does this */ if (gcgbin_f || gcgascii_f) { readchar_n = gcgbin_f ? (seq_z+3)/4 : seq_z; SeqAlloc (*seq, seq_z+4+1); for (k=0, l=readchar_n; k < readchar_n; k += file->len, l -= file->len) fread ((*seq)->seq+k, 1, l > file->len ? file->len + recordSeparatorLength : l, file->fil); if (gcgbin_f) SeqBinToAscii ((*seq)->seq, seq_z); (*seq)->len = seq_z; file->l = file->ln; file->ln[0] = '\0'; /** wipe out file->ln...fread! */ } /* ** if not gcg format read the sequence until exitstr is encountered */ else { while (1) { if (FilURead (file) == e__eof) { rv = e__eof; break; } if (memcmp (file->ln, exitstr, strlen (exitstr)) == 0) break; len = strlen (file->ln); if (file->ln[len-1] == '\n') file->ln[--len] = '\0'; SeqCopy (*seq, file->ln, SEQxFILTER); } if (options & 2) (*seq)->seq = NULL; /* prevents strange behaviour of srsbuild on osf1 ... sequence is not needed anyway ..just the length */ else SeqMakeOwn (*seq); } return rv; } /****** SeqGCGCheck *********************************************************** ** ** is the equiv. to the GCG CheckSeq; calculates a check sum for the ** input sequence; ** ** INPUT: address of array holding sequence ** length of seuqence ** ** RETURNS: check sum if successful ** */ static INT4 SeqGCGCheck(char *seq, INT4 len) { static INT4 fstcall_f = 1; static char table[256]; INT4 k, check = 0, i = 0; if (fstcall_f) { for (k = 0; k <= 255; k++) table[k] = toupper(k); fstcall_f = 0; } for( i=0, check=0; i < len; i++, seq++) check += ((i % 57)+1) * table[ (INT4) *seq]; return check % 10000; } /****** SeqWrite ************************************************************** ** ** writes a sequence to file with specified characters per line and ** characters by block; ** ** INPUT: o address of file block [W] ** o address of sequence [R] ** o length of sequence [R] ** o char per line [R] ** o char per block [R] ** o format option bitmask [R] ** using SEQxNUMBER, SEQxSTAR, SMxLOWCASE, SMxUPCASE or 0 ** SEQxLMARGIN ** IMPLICIT: ** ** RETURNS: nr. of lines written */ static INT4 SeqWrite (char *seq, INT4 len, INT4 colN, INT4 blockColN, INT4 option, INT4 (*print)(char*,...)) { char line[SEQxXLN+1], *tmp; INT4 lineN = 0, k; if (!len) return 0; for (k=0; k < len && *seq != '\0'; k++) { if (k % colN == 0) { /* is end of line? */ if (k != 0) { *tmp = '\0'; if (option & SEQxEMBLNUMBER) sprintf (line, "%-70s%10d", line, k); print ("%s\n", line); } if (option & SEQxNUMBER) sprintf (line, "%8d ", k+1); else if (option & SEQxLMARGIN) sprintf (line, " "); else strcpy (line, ""); tmp = &(line[strlen (line)]); } else if (k % blockColN == 0) /* is end of block ? */ *(tmp++) = ' '; *(tmp++) = seq[k]; } if (option & SEQxSTAR) /* put star at the end of the sequence */ *tmp++ = '*'; *tmp = '\0'; /* print last line feed */ if (option & SEQxEMBLNUMBER) sprintf (line, "%-70s%10d", line, k); print ("%s\n", line); return ++lineN; } /**API* SeqWriteGCG *********************************************************** ** ** Prints a sequence in GCG format. ** ** INPUT: o address of sequence object [R] ** o sequence name [R] or NULL ** o function to be used for printing lines [R] prints to STDOUT ** if NULL ** ** RETURNS: no of lines printed */ INT4 SeqWriteGCG (SEQo *seq, char *nam, INT4 (*print)(char*,...)) { INT4 cksum; if (!print) print = (INT4 (*)(char*,...)) printf; cksum = SeqGCGCheck (seq->seq, seq->len); print ("%s Length: %d Check: %d ..\n\n", nam == NULL ? seq->name : nam, seq->len, cksum); return SeqWrite (seq->seq, seq->len, 60, 10, SEQxNUMBER, print) + 2; } /**API* SeqWriteApplet ************************************************************** ** ** Prints a sequence in GCG format. ** ** INPUT: o address of sequence object [R] ** o sequence name [R] or NULL ** o function to be used for printing lines [R] prints to STDOUT ** if NULL ** ** RETURNS: no of lines printed */ INT4 SeqWriteApplet (SEQo *seq, char *nam) { printf ("\n"); printf ("\n", seq->seq); printf (""); printf ("\n"); } /**API* SeqWritePIR *********************************************************** ** ** Prints a sequence in PIR format. ** ** INPUT: o address of sequence object [R] ** o sequence name [R] title line is omitted if NULL ** o title line [R] or NULL ** o function to be used for printing lines [R] prints to STDOUT ** if NULL ** ** RETURNS: no of lines printed */ INT4 SeqWritePIR (SEQo *seq, char *nam, char *cmnt, INT4 (*print)(char*,...)) { INT4 lncnt = 0; if (!print) print = (INT4 (*)(char*,...)) printf; if (!seq) return 0; print (">P1;%s\n", nam == NULL ? seq->name : nam); if (cmnt == NULL) print (" Length: %d\n", seq->len); else print ("%s\n", cmnt); lncnt = SeqWrite (seq->seq, seq->len, 60, 10, SEQxSTAR, print); print ("\n"); return lncnt+2; } /**API* SeqWriteEmbl ********************************************************** ** ** Prints a sequence in EMBL format. ** ** INPUT: o address of sequence object [R] ** o sequence name [R] title line is omitted if NULL ** o function to be used for printing lines [R] prints to STDOUT ** if NULL ** ** RETURNS: no of lines printed ** */ INT4 SeqWriteEMBL (SEQo *seq, char *nam, INT4 (*print)(char*,...)) { INT4 lncnt = 0; if (!print) print = (INT4 (*)(char*,...)) printf; if (!seq) return 0; if (nam) print ("SQ Sequence%6d BP;\n", seq->len); lncnt = SeqWrite (seq->seq, seq->len, 60, 10, SEQxLMARGIN | SEQxEMBLNUMBER, print); print ("//\n"); return lncnt+2; } /**Api* SeqWriteSwiss ********************************************************* ** ** writes sequence in Swissprot format to file ** ** INPUT: sequence object [R] ** sequence name ...if NULL then the title line is omitted [R] ** print line function [R] ** ** OUTPUT: ** returns: nr. of lines written to file */ INT4 SeqWriteSwiss (SEQo *seq, char *nam, INT4 (*print)(char*,...)) { INT4 lncnt = 0; if (!print) print = (INT4 (*)(char*,...)) printf; if (!seq) return 0; if (nam) if (! ParGetNum ("printText")) /* JC */ print ("SQ Sequence%6d AA;\n", seq->len); lncnt = SeqWrite (seq->seq, seq->len, 60, 10, SEQxLMARGIN, print); print ("//\n"); return lncnt+2; } /**api* SeqWriteGDE *********************************************************** ** ** writes sequence in GDE format ** ** INPUT: address of sequence object [R] ** file pointer of output file [W] ** name to appear in the title line [R] or NULL ** ** RETURNS: nr. of lines written to file */ INT4 SeqWriteGDE (SEQo *seq, char *nam, INT4 (*print)(char*,...)) { INT4 ln_n=0; if (!print) print = (INT4 (*)(char*,...)) printf; if (!seq) return 0; print ("%c%s\n", '%', nam == NULL ? seq->name : nam); ln_n = SeqWrite (seq->seq, seq->len, 60, 10, 0, print); print ("\n"); return ln_n+1; } /**api* SeqWriteFasta ********************************************************* ** ** modified 3-may-95 by Peter Rice to cut out spaces ** ** writes sequence in PIR format to file ** ** INPUT: address of sequence object [R] ** file pointer of output file [W] ** name to appear in the title line [R] or NULL ** ** RETURNS: nr. of lines written to file ** */ INT4 SeqWriteFasta (SEQo *seq, char *nam, INT4 (*print)(char*,...)) { INT4 lncnt = 0; if (!print) print = (INT4 (*)(char*,...)) printf; if (!seq) return 0; print (">%s\n", nam == NULL ? seq->name : nam); lncnt = SeqWrite (seq->seq, seq->len, 60, 60, 0, print); /* block 10 to 60 */ /* print ("\n"); commented out */ return lncnt+1; /* was lncnt+2 */ } /**API* SeqWrtMSF ************************************************************* ** ** Prints a list of sequences in MSF (GCG) format. ** ** INPUT: o address of sequence object [R] ** o function to be used for printing lines [R] prints to STDOUT ** if NULL ** ** RETURNS: */ INT4 SeqWrtMSF (SEQo *seq, INT4 (*print)(char*,...)) { INT4 savepos, k, allcksum, ali_z, line_n = 60; if (!print) print = (INT4 (*)(char*,...)) printf; if (!seq) return 0; LstGetPosition (seq, &savepos); /* ** go through all sequences and find out the max length which will ** become the length of the alignment...and calculate the total check sum ** of the alignment; */ do { if (seq->len > ali_z) ali_z = seq->len; allcksum += SeqGCGCheck (seq->seq, seq->len); } while (LstNext ((void **) &seq)); allcksum = allcksum % 10000; /* ** print title of alignment and the names of the sequences occurring ** in the MSF file; */ print ("MSF: %d Type: P Check: %d ..\n\n", ali_z, allcksum); LstSetPosition ((void **) &seq, savepos); do { print (" Name: %-12s Len: %6d Check: %4d Weight: 1\n", seq->name, seq->len, SeqGCGCheck (seq->seq, seq->len)); } while (LstNext ((void **) &seq)); print ("\n//\n"); /* ** print the sequence alignment */ for (k=0; k < ali_z; k += line_n) { LstSetPosition ((void **) &seq, savepos); do { print ("%-12s ", seq->name); SeqWrite (&seq->seq[k], line_n, line_n, 10, 0, print); } while (LstNext ((void **) &seq)); print ("\n"); } return 1; } /**api** SeqAlloc ************************************************************ ** ** allocates memory for a sequence string with know length; ** ** INPUT: address of sequence object [W] ** IMPLICIT: ** ** RETURNS: 1 if OK ** 0 else */ static void SeqAlloc (SEQo *seq, INT4 len) { if (seq->seq) fprintf(stderr, "*** MEMORY LEAK in SeqAlloc ***\n"); if ((seq->seq = (char *) malloc (len + 1)) == NULL) _ErrExit2 (e__allocfail, "sequence"); } /**api** SeqMakeOwn *********************************************************** ** ** copies the sequence string from temporary to extra allocated memory; ** ** INPUT: address of sequence object [W] ** IMPLICIT: ** ** RETURNS: */ static void SeqMakeOwn (SEQo *seq) { char *tmp; if (seq->len) { if ((tmp = (char *) malloc (seq->len + 1)) == NULL) _ErrExit2 (e__allocfail, "sequence"); memcpy (tmp, seq->seq, seq->len); tmp[seq->len] = '\0'; seq->seq = tmp; } else seq->seq = NULL; } /**api** SeqSubSeq ************************************************************ ** ** makes a subsequence from sequence as specified ** ** INPUT: address of sequence object [W] ** begin of subsequence (first aa = 1) [R] ** length of subsequence [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** 0 else */ INT4 SeqSubSeq (SEQo *seq, INT4 beg, INT4 len) { if (beg <= 0 || len <= 0) return 0; if (beg > seq->len) /* begin */ return 0; if (beg + len-1 > seq->len) /* length */ len = seq->len - beg + 1; memcpy (seq->seq, &seq->seq[beg-1], len); seq->len = len; seq->seq[len] = '\0'; return 1; } /**api** SeqHead ************************************************************ ** ** makes a subsequence from start of sequence with length len ** ** INPUT: address of sequence object [W] ** length of subsequence [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** 0 else */ INT4 SeqHead(SEQo *seq, INT4 len) { /* ** SeqSubSeq does no free allocated memory, so maybe ** another implementation will be used later */ return SeqSubSeq(seq, 1, len); } /**api** SeqTail ************************************************************ ** ** makes a subsequence from end of sequence with length len ** ** INPUT: address of sequence object [W] ** length of subsequence [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** 0 else */ INT4 SeqTail(SEQo *seq, INT4 len) { /* ** SeqSubSeq does no free allocated memory, so maybe ** another implementation will be used later */ return SeqSubSeq(seq, seq->len - len + 1, len); } /**api** SeqCat ************************************************************ ** ** concatenates a subsequence (range) to another sequence (*seq) ** ** INPUT: address of address of sequence object [R] ** address of sequence (range) object [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** 0 else */ INT4 SeqCat (SEQo **seq, SEQo *range) { SEQo *result = *seq; char *oldseq; /* look, if there was already a sequence before */ oldseq = result->seq; /* make sure correct length is set */ if (!oldseq) { result->len = 0; oldseq = ""; } else result->len = strlen(result->seq); result->len += strlen(range->seq); result->seq = (char*) malloc(result->len + 1); strcpy(result->seq, oldseq); strcat(result->seq, range->seq); if (*oldseq) free(oldseq); return 1; } /**api** SeqJoin ********************************************************* ** ** computes the join operation. First a new sequence object is created ** and then all subsequences in the ramge list are appended ** to that sequence object. ** ** INPUT: address of address of sequence object [W] ** address of sequence (range) object in a list [R] ** IMPLICIT: ** ** RETURNS: 1 if OK ** 0 or error code else */ INT4 SeqJoin(SEQo **seq, SEQo *range) { INT4 rv; if (SeqNew(seq)) { LstFirst((void**)&range); do { rv = SeqCat(seq, range); _ErrRet (rv); } while (LstNext((void**)&range)); } else return 0; return 1; } /**api* SeqSwap *************************************************************** ** ** swaps a character in all sequences; ** ** INPUT: address of sequence object [W] ** old character [R] ** new character [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 SeqSwap (SEQo *seq, char a, char b) { INT4 savepos; LstGetPosition (seq, &savepos); LstFirst ((void **) &seq); do { SmSwap (seq->seq, a, b); } while (LstNext ((void **) &seq)); LstSetPosition ((void **) &seq, savepos); return 1; } /**api* SeqRemoveGaps ********************************************************* ** ** removes gaps (either '-' or '.') from sequence ** ** INPUT: address of sequence-dsc. [W] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 SeqRemoveGaps (SEQo *seq) { SmSwapS (seq->seq, ".", ""); SmSwapS (seq->seq, "-", ""); seq->len = strlen (seq->seq); return 1; } /**api* SeqGet *************************************************************** ** ** Gets sequence in sequence buffer by name; ** ** INPUT: pointer to address of sequence object [W] ** name [R] ** IMPLICIT: ** ** RETURNS: number in list if found ** 0 if not */ INT4 SeqGet (SEQo **seq, char *seq_nm) { INT4 pos; if (!LstFirstNamed ((void **) seq, seq_nm)) return 0; LstGetPosition ((void *) *seq, &pos); return pos; } /* icarus functions */ static SEQo *seqCurr=NULL; SeqIopNew () { SEQo *seq; STRv name; IargGetArgs ("name|list", &name, &seq); if (!seq && seqCurr) SeqClean (&seqCurr); SeqNew (&seq); seqCurr = seq; if (name) { strcpy (seq->name, _Str(name)); StrDel (name); } IcaReturn ("sequence", seq); } SeqIopApp () { SEQo *seq; STRv s; IargGetArgs ("seq|s", &seq, &s); SeqCopy (seq, _Str(s), SEQxFILTER); StrDel (s); IcaReturn ("sequence", seq); } SeqIopMake () { SEQo *seq; IargGetArgs ("seq", &seq); SeqMakeOwn (seq); } SeqIopPrint () { SEQo *seq; INT4 format; IargGetArgs ("format|seq", &format, &seq); if (!seq) seq = seqCurr; switch (format) { case SEQxGCG: SeqWriteGCG (seq, NULL, NULL); break; case SEQxPIR: SeqWritePIR (seq, seq->name, "", NULL); break; case SEQxFASTA: SeqWriteFasta (seq, seq->name, NULL); break; case SEQxEMBL: SeqWriteEMBL (seq, seq->name, NULL); break; case SEQxSWISS: SeqWriteSwiss (seq, seq->name, NULL); break; case SEQxMSF: SeqWriteApplet (seq, seq->name); break; default: _ErrExit2 (e__unknownoption, "format in SeqIopPrint"); } } ** ** $RCSfile: seq.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:17 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #include "transl.h" #define SEQxXNAM 50 /* max size of sequence name */ #define SEQxXWIN 31 #define SEQxXCMNT 512 /* max size of sequence comment */ #define SEQxXLN 255 #define SEQxSEQBUFF 1000000 /* size of sequence buffer */ enum seqformat {SEQxGCG=1, SEQxMSF, SEQxPIR, SEQxPEARSON, SEQxFASTA, SEQxEMBL, SEQxSWISS, SEQxCLUSTAL}; enum formattoken {SEQxRANGLE=1, SEQxPIRTOKENS, SEQxCHECK, SEQxDOTDOT, SEQxSEMICOLON}; enum formatoption {SEQxFILTER=1, SEQxNUMBER=8, SEQxSTAR=16, SEQxLMARGIN=32, SEQxEMBLNUMBER=64}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** description of a sequence */ typedef struct SEQo { char *intern; /* the first three attributes are necessary */ INT4 type_id; /* for all objects to be managed by the list */ char name[20]; char *cmnt; /* sequence description */ char *seq; /* pointer to sequence string */ char *replace; /* string to be replaced or inserted into sequence */ INT4 len; /* length of sequence */ INT4 check; /* GCG check sum */ INT4 bpos; /* begin position of range */ INT4 epos; /* end position of range */ INT4 part_len; /* 0: complete <0: head >0: tail */ char accno[10]; char keep_f; /* flag if sequence should be kept */ char compl_f; /* flag if sequence is to be reverse complemented */ char cut_f; /* flag that replace sequence is to be inserted in range */ char before_f; /* flag that shows whether the operator BEFORE exists */ char after_f; /* flag that shows whether the operator AFTER exists */ struct SEQo *sublist; } SEQo; typedef struct SEQoTranslExcept { char aa; INT4 begin; INT4 length; INT4 isDone; } SEQoTranslExcept; typedef struct SEQoTranslCodon { char aa; char codon[4]; } SEQoTranslCodon; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ INT4 SeqNew (SEQo **seq); void SeqClr (SEQo **seq); void SeqClean (SEQo **seq); /* input from file in various formats */ INT4 SeqReadAll (SEQo **seq, char *fil_nm); INT4 SeqReadPIR (SEQo **seq, char *fil_nm); INT4 SeqReadGCG (SEQo **seq, char *nam); INT4 SeqReadGCGFile (SEQo **seq, char *fil_nm); INT4 SeqReadMSF (SEQo **seq, char *msf_nm); INT4 SeqReadLib (SEQo **seq, FILo *file, char *exitstr); INT4 SeqFromLib (SEQo **seq, FILo *file, char *scanId, char *exitstr, INT4 comment_f); /* output to file in various formats */ INT4 SeqWriteGCG (SEQo *seq, char *nam, INT4 (*print)(char*,...)); INT4 SeqWritePIR (SEQo *seq, char *nam, char *cmnt, INT4 (*print)(char*,...)); INT4 SeqWriteFasta (SEQo *seq, char *nam, INT4 (*print)(char*,...)); INT4 SeqWriteEMBL (SEQo *seq, char *nam, INT4 (*print)(char*,...)); INT4 SeqWriteSwiss (SEQo *seq, char *nam, INT4 (*print)(char*,...)); INT4 SeqWriteMSF (SEQo *seq, INT4 (*print)(char*,...)); /* sequence manipulation */ INT4 SeqSwap (SEQo *seq, char a, char b); INT4 SeqSubSeq (SEQo *seq, INT4 beg, INT4 len); INT4 SeqRemoveGaps (SEQo *seq); INT4 SeqComplement (SEQo *seq); INT4 SeqJoin (SEQo **seq, SEQo *range); INT4 SeqHead (SEQo *seq, INT4 len); INT4 SeqTail (SEQo *seq, INT4 len); INT4 SeqCat (SEQo **seq1, SEQo *seq2); /* for translating DNA to protein */ SEQoTranslTable *SeqTaxaToTranslTable (SMoBUFF *org); SEQoTranslTable *SeqIdToTranslTable (INT4 id); struct SEQo *SeqTranslate (SEQo *dna, INT4 start, SEQoTranslTable *tTable, SEQoTranslExcept *tExcept, SEQoTranslCodon *tCodon); /* others */ INT4 SeqGoGcgDots (FILo *file); INT4 SeqGet (SEQo **seq, char *seq_nm); void SeqSetRecordSeparator (INT4 i); char seqlib_srs_ID[] = "$Id: seqlib.c,v 1.2 1996/05/06 19:20:52 etzold Exp $"; /* ** ** $RCSfile: seqlib.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/05/06 19:20:52 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.x Copyright by Thure Etzold ** ** Author: Gerald Schaefer ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387372 ** Email: schaefer@embl-heidelberg.de ** ** ** Requires: list,expr,stack ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description sequence computation using generic list ** =========== ** ** Global Parameters: ** "printf" ** "writeFOSN" ** "shiftbeginpos" ** "shiftendpos" ** "isshiftbeginrelend" ** "isshiftendrelbegin" ** "takeuncompletefeature" ** "takeuncompleteshiftfeature" ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* #define TRACE #define DUMMY #define TRACE1 */ #include #include #include #include #include #include "message.h" #include "sm.h" #include "lst.h" #include "futil.h" #include "par.h" #include "id.h" #include "library.h" #include "entry.h" #include "seq.h" #include "query.h" #include "seqlib.h" #define _SRS #define _SLB #define _CONSTANTS #include SRSINCLUDE #define vabs(x) ((x)<0 ? -(x) : (x)) #define NAMELEN 40 enum slbfile_type {SLBxNORMAL=0, SLBxGCG7, SLBxGCG8, SLBxGCG8_1}; typedef struct STKo { void *a; }STKo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external, global and module wide variables */ extern FILE *protokoll; ENTRYo *global_entry; SEQo *seqCurr = NULL; /* remembers, if entry sequence was already read */ SEQo *featureSeq = NULL; SEQo *seqRangeList = NULL; static SLBoFEATURE feature = { 0, 0, 1, NULL, NULL, NULL, 0, NULL, NULL, NULL}; static FILE *file=NULL; static SMoBUFF *featureBuff=NULL; INT4 global_before_f = 0; INT4 global_after_f = 0; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ static INT4 join(STKo *parameter_stack, STKo *eval_stack); static INT4 complement(STKo *parameter_stack, STKo *eval_stack); static INT4 replace(STKo *parameter_stack, STKo *eval_stack); static INT4 one_of(STKo *parameter_stack, STKo *eval_stack); static void SlbInitFeature (SLBoFEATURE *feature); static void SlbJoinList(); static void SlbComplementList(); static void SlbReplaceList(char *replace); static INT4 SlbInsert (INT4 bpos, INT4 epos); static INT4 SlbSetAccno(char *acc); static INT4 SlbShiftAndCheck(); static INT4 SlbEvaluate(); static void SlbWriteFosn (SEQo *seq); static SEQo *SlbRetrieveAccNo (char *accno); static char *SlbCurrEntryName (); typedef struct FUNC_DESC_ { char func_name[20]; INT4 (*func) (); } FUNC_DESC; #define MAXFUNC 4 FUNC_DESC func_table[MAXFUNC] = { { "join", join }, { "complement", complement }, { "replace", replace }, { "one-of", one_of } }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** default function for printing lines */ static INT4 SlbPrintF (char *formatStr, ...) { va_list ap; va_start (ap, formatStr); vfprintf (file, formatStr, ap); va_end (ap); if (formatStr[strlen (formatStr) -1] != '\n') fprintf (file, "\n"); return 1; } /****** SlbGetCurrEntryName *************************************************** ** ** Prints name entry that is currently processed. ** ** INPUT: ** IMPLICIT: ** global_entry (ENTRYo *) [R] ** ** RETURNS: */ static char *SlbGetCurrEntryName () { return EntryGetFullName (global_entry); } /****** SlbEntryPrint ********************************************************* ** ** prints a single sequence entry using various options; function needs ** to know how many entries have to be printed and are currently printed ** in order to decide if the output file (if any) has to be opened or ** closed. ** ** INPUT: entry object [R] ** set Name (for constructing output file name) [R] ** number of entries to print in whole list [R] ** number of current entry [R] ** IMPLICIT: ** ** RETURNS: */ void SlbEntryPrint (ENTRYo *entry, char *setName, int entryN, int entryCurrN) { SLBoFEATURE *feature; SEQo *seq = NULL; char *fileExt; INT4 errCode, seqFormat, (*print)(char*,...); switch (tolower (ParGetStr ("seqFormat")[0])) { case 'p': seqFormat = SEQxPIR; fileExt = ".pir"; break; case 'e': seqFormat = SEQxEMBL; fileExt = ".dat"; break; case 's': seqFormat = SEQxSWISS; fileExt = ".dat"; break; case 'g': seqFormat = SEQxGCG; fileExt = ".gcg"; break; case 'f': seqFormat = SEQxFASTA; fileExt = ".fas"; break; } /* ** the next deals with the file name... part of which may be specified by ** user and open the file ...if not already open */ if (ParGetNum ("printToFile")) { char *tmp, *outFileName, outDirName[FILxXNAM+1], fileName[FILxXNAM+1]; ParDefFunction ("printf", (INT4 (*)()) SlbPrintF); outFileName = ParGetStr ("outFileName"); if ((tmp = ParGetStr ("outDirName"))) sprintf (outDirName, "%s/", tmp); else *outDirName = '\0'; if (!entryCurrN && seqFormat != SEQxGCG) { if (outFileName && *outFileName) sprintf (fileName, "%s%s", outDirName, outFileName); else sprintf (fileName, "%s%s%s", outDirName, setName, fileExt); } else if (seqFormat == SEQxGCG) { if (entryN == 1 && outFileName && *outFileName) sprintf (fileName, "%s%s", outDirName, outFileName); else sprintf (fileName, "%s%s%s", outDirName, entry->entry_nm, fileExt); } if (*fileName) { file = FilOpenW (fileName, &errCode); _ErrMsg2 (errCode, fileName); } } /* ** print text (annotation) */ print = (INT4 (*)(char*,...)) ParGetFunction ("printf"); if (ParGetNum ("printText")) EntryPrint (entry); else if (ParGetNum ("parSetFields")) { print ("entry: %s \n", entry->full_nm); EntryPrintFields (entry); } else if (seqFormat != SEQxFASTA) print ("entry: %s \n", entry->full_nm); /* ** print data (sequence) */ if (ParGetNum ("printData")) { if (IdIsSub (entry->id)) errCode = SlbGetFeature (entry, &seq, &feature); else errCode = SlbGetSequence (entry, &seq); _ErrIf (errCode) _ErrMsg2 (e__failureinslbgetx, entry->full_nm); else { switch (seqFormat) { case SEQxPIR: SeqWritePIR (seq, entry->entry_nm, 0, print); break; case SEQxEMBL: SeqWriteEMBL (seq, ParGetNum ("printText") ? NULL : EntryGetName (entry), print); break; case SEQxSWISS: SeqWriteSwiss (seq, entry->entry_nm, print); break; case SEQxGCG: SeqWriteGCG (seq, entry->entry_nm, print); break; case SEQxFASTA: SeqWriteFasta (seq, entry->entry_nm, print); break; } } } /* ** close file */ if (file && (entryCurrN == entryN - 1 || seqFormat == SEQxGCG)) { fclose (file); file = NULL; /* set back to default value /stdout/ */ } } /****** SlbGetNamedFunction *************************************************** ** ** looks for the named function in the local function table ** ** INPUT: address of function name [R] ** IMPLICIT: ** ** RETURNS: address of function descriptor, if function exists, ** otherwise NULL */ static FUNC_DESC* SlbGetNamedFunction(char* name) { INT4 i; for (i=0; i */ static INT4 one_of(STKo *parameter_stack, STKo *eval_stack) { #ifdef xxx STKoSYM op; STKoSYM first; INT4 param_count = 0; INT4 rv=1; if (ParGetNum("discardoneof")) { _ErrRet(e__foundoneof); } /* ** auf dem Stack koennen Zahlen (pos) liegen oder es kann eine ** Parameterliste mit Ranges existieren !! */ while (StkPop(parameter_stack, &op) != e__eostack) { param_count++; /* printf("Parameter: %d\n", param_count); */ if (param_count==1) first = op; } if (param_count > 0) { rv = StkPush(eval_stack, first); _ErrRet2(rv, "when evaluating one-of"); } else { /* seqRangeList with ranges */ LstFirst ((void**)&seqRangeList); if (LstNext ((void**)&seqRangeList)) LstDeleteToEndOfList((void**)&seqRangeList); } #endif return 1; } /****** SlbExe **************************************************************** ** ** this function implements the operator EXE. ** Symbols are popped from the evaluation stack until the next ** function name is popped. If there are values on the stack, ** the values are pushed into a private parameter stack. If the ** function name is popped, the corresponding function is called ** and supplied with the parameter stack. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** reads the content of the evaluation stack ** writes the content of the parameter stack ** ** RETURNS: 1 on success ** e__doesnotexistfunction */ INT4 SlbExe (STKo *eval_stack) { /* pop symbols from eval_stack, if operator: execute them (not possible here!) if value: put it into private parameter_stack if variable: put it's value into private parameter_stack if functionname: execute function giving it a pointer to the private parameter_stack if OP_SEQ: nothing to do */ #ifdef xxx STKo private_stack; STKoSYM sym; FUNC_DESC *func_desc_ptr; float float_val; INT4 int_flag=1, rv=1; if (!StkIniSym(&private_stack, 20)) { _ErrRet2(e__allocfail, "in initialization of private parameter stack"); } while (1) { rv = StkPop(eval_stack, &sym); if (sym.any.code == STKxFNAME) { /* get function_description pointer ... */ func_desc_ptr = SlbGetNamedFunction(sym.var_name.name); /* ??? Should there be a number that decides what parameter list to use ? */ if (func_desc_ptr) rv = (func_desc_ptr->func) (&private_stack, eval_stack); else rv = e__doesnotexistfunction; _ErrIf(rv) { StkDelSym(&private_stack); _ErrRet2(rv, sym.var_name.name); } break; } switch (sym.any.code) { case 0: break; case STKxNAME: rv = StkPush(&private_stack, sym); _ErrIf(rv) { StkDelSym(&private_stack); _ErrMsg(rv); /* because _ErrRet does not print message */ _ErrRet(rv); } break; case STKxNUMBER: /* put value into private parameter stack */ case STKxFLOAT: case STKxINUM: case STKxFNUM: int_flag = 1; ExpGetVal(&sym,&float_val,&int_flag); ExpGetSym(&sym,float_val,int_flag); rv = StkPush(&private_stack, sym); _ErrIf(rv) { StkDelSym(&private_stack); _ErrMsg(rv); /* because _ErrRet does not print message */ _ErrRet(rv); } break; } } StkDelSym(&private_stack); #endif return 1; } /****** SlbOpAfter ************************************************************ ** ** this function implements the operator AFTER ( > ). ** An integer value is popped from the evaluation stack. ** Negative positions are rejected. ** Legal positions are made negative afterwards to mark the ** existence of the 'after' operator. ** The value is pushed onto the evaluation stack again. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** ** RETURNS: 1 */ INT4 SlbOpAfter (STKo *eval_stack) { #ifdef xxx float val, ergval; INT4 int_flag=1; INT4 rv; if (!ParGetNum("takeuncompletefeature")) _ErrRet(e__operatorafternotallowed); else global_after_f = 1; rv = ExpPopVal(eval_stack, &val, &int_flag); if (!int_flag) _ErrRet2(e__illegalvalueonstack, val); /* negative positions must not exist, parser should signal error before */ if (val<0) _ErrRet(e__illegalposition); ergval = val>0 ? val : 1; /* default */ /* ** make ergval negative to use it later as a sign ** for the existence of after_f in range */ ergval = -ergval; ExpPushVal(eval_stack, ergval, int_flag); return rv; #endif } /****** SlbOpBefore *********************************************************** ** ** this function implements the operator BEFORE ( < ). ** An integer value is popped from the evaluation stack. ** Negative positions are rejected. ** Legal positions are made negative afterwards to mark the ** existence of the 'before' operator. ** The value is pushed onto the evaluation stack again. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** ** RETURNS: 1 */ INT4 SlbOpBefore (STKo *eval_stack) { #ifdef xxx float op1val, ergval; INT4 int_flag=1; INT4 rv; if (!ParGetNum("takeuncompletefeature")) _ErrRet(e__operatorbeforenotallowed); else global_before_f = 1; rv = ExpPopVal(eval_stack, &op1val, &int_flag); if (!int_flag) _ErrRet2(e__illegalvalueonstack, op1val); /* negative positions must not exist, parser should signal error before */ if (op1val<0) _ErrRet(e__illegalposition); ergval = op1val>1 ? op1val : 1; /* default */ /* ** make ergval negative to use it later as a sign ** for the existence of before_f in range */ ergval = -ergval; ExpPushVal(eval_stack, ergval, int_flag); return rv; #endif } /****** SlbOpRange ************************************************************ ** ** this function implements the operator RANGE ( .. ). ** Two integer values are popped from the evaluation stack. ** A new sequence object is inserted into the seqRangeList, using ** the popped value as begin and end position. The accession number ** of the new sequence object is initially an empty string. ** If a position is negative it means that an operator (before, after) ** existed. Therefore a flag (before_f, after_f) is set TRUE in SlbInsert. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** inserts a new sequence object into seqRangeList ** ** RETURNS: 1 on success, 0 otherwise */ INT4 SlbOpRange (STKo *eval_stack) { #ifdef xxx float val1, val2; INT4 int_flag=1; INT4 rv; rv = ExpPopVals(eval_stack, &val1, &val2, &int_flag); if (!int_flag) _ErrRet3(e__illegalvaluesonstack, val1, val2); if (!val1 || !val2) _ErrRet (e__rangewithundefval); if (vabs (val1) > vabs(val2)) _ErrRet(e__illegaldirectioninrange); /* Generate new range and insert it into list */ rv = SlbInsert((INT4) val1, (INT4) val2); return rv; #endif } /****** SlbOpMakeRange ******************************************************** ** ** this function implements the operator MAKERANGE ( .. ). ** One integer value gets popped from the evaluation stack. ** A new sequence object is inserted into the seqRangeList, using ** the popped value as begin and end position. The accession number ** of the new sequence object is initially an empty string. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** inserts a new sequence object into seqRangeList ** ** RETURNS: 1 on success, 0 otherwise */ INT4 SlbOpMakeRange (STKo *eval_stack) { float op1val; INT4 int_flag=1; INT4 rv; #ifdef xxx #ifdef TRACE1 printf("Function *SlbOpMakeRange* called\n"); #endif rv = ExpPopVal(eval_stack, &op1val, &int_flag); if (!int_flag) _ErrRet2(e__illegalvalueonstack, op1val); if (op1val<=0) _ErrRet(e__illegalposition); #ifdef TRACE printf("computing range %d .. %d \n", (INT4)op1val, (INT4)op1val); #endif /* Generate new range and insert it into list */ rv = SlbInsert((INT4)op1val, (INT4)op1val); return rv; #endif } /****** SlbOpSelect *********************************************************** ** ** this function implements the operator SELECT ( . ). ** Two integer values are popped from the evaluation stack. ** The user is asked to specify a position between that positions. ** The user-specified or default position is pushed onto stack again. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** ** RETURNS: 1 */ INT4 SlbOpSelect (STKo *eval_stack) { #ifdef xxx char answer[20]; float op1val, op2val, ergval, userval; INT4 int_flag=1; INT4 rv; rv = ExpPopVals(eval_stack, &op1val, &op2val, &int_flag); if (!int_flag) _ErrRet3(e__illegalvaluesonstack, op1val, op2val); ergval = op1val; /* default */ if (ParGetNum("interactiveselect")) { printf("what position do you want BETWEEN %d and %d [%d]: ", (INT4)op1val, (INT4)op2val, (INT4)ergval); gets(answer); if (strlen(answer) > 0) { if (sscanf(answer, "%f", &userval) == 1) { if (userval < op1val || userval > op2val) printf("** position too low or too high: default used !!\n"); else ergval = userval; } else printf("** illegal input: default used !!\n"); } } ExpPushVal(eval_stack, ergval, int_flag); return rv; #endif } /****** SlbOpCut ************************************************************** ** ** this function implements the operator CUT ( ^ ). ** Two integer values are popped from the evaluation stack. ** A new sequence object is inserted into the seqRangeList, using ** the popped values as begin and end position. Because there should ** be only a site specified, begin and end position must be adjacent. ** At the moment the end position is set according to begin position. ** The accession number of the new sequence object is initially an ** empty string. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** inserts a new sequence object into seqRangeList ** ** RETURNS: 1 on success, 0 otherwise */ INT4 SlbOpCut (STKo *eval_stack) { #ifdef xxx char answer[20]; float val1, val2, ergval, userval; INT4 int_flag=1; INT4 rv; rv = ExpPopVals (eval_stack, &val1, &val2, &int_flag); if (!int_flag) _ErrRet3(e__illegalvaluesonstack, val1, val2); ergval = val1; /* default */ if (val2-val1 > 1 && ParGetNum("interactivecut")) { printf("after what position do you want to CUT %d..%d [%d]: ", (INT4)val1, (INT4)val2, (INT4)ergval); gets(answer); if (strlen(answer) > 0) { if (sscanf(answer, "%f", &userval) == 1) { if (userval < val1 || userval > val2-1) printf("** position too low or too high: default used !!\n"); else ergval = userval; } else printf("** illegal input: default used !!\n"); } } val1 = ergval; val2 = val1 + 1; /* the two positions must be adjacent */ /* Generate new sequence object and insert it into list */ rv = SlbInsert ((INT4)val1, (INT4)val2); if (rv) seqRangeList->cut_f = 1; /* set flag (site_flag) */ return rv; #endif } /****** SlbOpSetAccno ********************************************************* ** ** this function implements the operator SET_ACCNO ( : ). ** The accession number is popped from the evaluation stack. ** Modifies (sets) the accession number of the sequence object, ** that was last inserted into the seqRangeList. ** ** INPUT: address of evaluation stack [R] ** IMPLICIT: ** modifies the content of the evaluation stack ** modifies last inserted sequence object in seqRangeList ** ** RETURNS: 1 on success, 0 otherwise */ INT4 SlbOpSetAccno (STKo *eval_stack) { #ifdef xxx char accno[NAMELEN]; INT4 rv; rv = ExpPopVarname(eval_stack, accno); rv = SlbSetAccno (accno); return rv; #endif } /****** SlbPrintFeature ******************************************************* ** ** this function is used to concatenate all lines belonging to ** the same feature description in a database. After concatenating ** all lines into one string, the resulting string will be parsed ** and evaluated. ** ** INPUT: address of line in feature table [R] ** IMPLICIT: ** modifies the global featureline ** ** RETURNS: */ static void SlbPrintFeature(char *ln) { INT4 len; #if defined(TRACE) printf ("%s", ln); #endif memcpy (ln, " ", 2); /* blank FT */ len = strlen (ln); if (ln[ len-1 ] == '\n') ln[len-1] = '\0'; BuffCopyString (featureBuff, ln); } /**api* SlbMakeFeature ***************************************************** ** ** accesses the feature table of an entry from the sequence library ** and returns the evaluated sequence object; also returns a pointer ** to the global feature object, wherein translation exceptions and ** special codons may be stored. ** ** INPUT: buffer with the feature description [R] ** address of entry object [R] ** pointer to address of sequence object [W] ** pointer to address of feature description object [W] ** IMPLICIT: ** featureBuff (SMoBUFF *) [W] ** ** RETURNS: 1 on success, 0 otherwise */ INT4 SlbMakeFeature (SMoBUFF *featureBuff, ENTRYo *entry, SEQo *seq, SEQo **res_seq, SLBoFEATURE **featurePtr) { #ifdef xxx static SMoBUFF *buff=NULL; #ifdef xxx EXPo *expression; INT4 rv; char *tmp; if (!buff) buff = BuffNew (100); else BuffReset (buff); #ifdef xxx if (BuffSearch (featureBuff, "join(")) return 0; #endif global_entry = entry; /* needed in SlbSeqFromAccNo to get library name */ seqCurr = seq; /* entry sequence already read */ SlbInitFeature (&feature); if (featurePtr) *featurePtr = &feature; expression = (EXPo*) LibObjByName("expression", "embl_feature"); if (!expression) _ErrRet4(e__objnotfound, 5, "seqlib.c", "embl_feature"); ExpInit(expression); SlbListReset(); /* maybe at another place ??? */ /* ** ExpEval builds only a list structure (seqRangeList), that has ** to be evaluated later. The sequence of the entry was passed ** to SlbMakeFeature via the attribute "seq". ** After ExpEval parsing is already completely done and ** feature.transl_except points to one of maybe many translation ** exception objects in a list, if there exists one. */ BuffCopyString (buff, BuffGetPtr (featureBuff)+5); /* remove line code */ while ((tmp = BuffSearch (buff,"\nFT"))) strncpy(tmp," ",3); rv = ExpEval (BuffGetPtr (buff), "location", EXPxEVALUATE); if (rv == e__parsefail) rv = e__entryparsefail; _ErrRet2(rv, entry->entry_nm); rv = SlbShiftAndCheck(); _ErrMsg2(rv, entry->entry_nm); _ErrRet(rv); rv = SlbEvaluate(); _ErrRet2(rv, entry->entry_nm); /* ** the last inserted one is the RESULT ** move it to the result sequence list */ seqCurr = NULL; /* reset to initial state */ if (featureSeq) { LstMove ((void**) res_seq, (void**)&featureSeq); return 1; } else #endif return 0; #endif } /**API* SlbGetFeature ********************************************************* ** ** Retrives for the specified subentry, or sequence feature, the sequence ** and the address of an object that contains parts of the feature ** annotation. Function accesses the feature table of the ** original flat file and evaluates the feature location expression. ** ** INPUT: address of entry object [R] ** address of pointer to sequence object [W] ** address of pointer to feature description object [W] ** IMPLICIT: ** ** RETURNS: 1 if successful ** e__entryparsefail + ** 0 otherwise */ INT4 SlbGetFeature (ENTRYo *entry, SEQo **res_seq, SLBoFEATURE **featurePtr) { #ifdef xxx EXPo *expression; INT4 rv, (*printSave)(); SlbInitFeature (&feature); if (featurePtr) *featurePtr = &feature; expression = entry->lib->form->featureExpression; ExpInit(expression); SlbListReset(); global_entry = entry; /* ** goto begin of feature in entry */ rv=EntryOpenText(entry); EntryBeginSub(entry); while ( (rv = EntryNextSub (entry)) < entry->id->subentry_n) if (_ErrIs (rv) || rv == 0) _ErrRet2 (e__entryparsefail, entry->entry_nm); /* ** print feature to the feature buffer */ if (!featureBuff) featureBuff = BuffNew (1000); else BuffReset (featureBuff); printSave = ParGetFunction ("printf"); ParDefFunction ("printf", (INT4(*)()) SlbPrintFeature); EntryPrintSub (entry); /* copy feature to featureBuff */ ParDefFunction ("printf", printSave); /* reset print function */ /* ** ExpEval builds only a list structure (seqRangeList), that has ** to be evaluated later. The sequence of the entry has not ** been read yet. After ExpEval parsing is already completely ** done and feature.transl_except points to one of maybe many ** translation exception objects in a list, if there exists one. */ rv = ExpEval(BuffGetPtr (featureBuff), "location", EXPxEVALUATE); if (rv == e__parsefail) rv = e__entryparsefail; _ErrRet2(rv, entry->entry_nm); rv = SlbShiftAndCheck(); _ErrRet(rv); if (ParGetNum ("listFOSN") && !ParGetNum ("printData")) { SlbWriteFosn (seqRangeList); } else { rv = SlbEvaluate(); _ErrRet(rv); /* ** the last inserted one is the RESULT ** move it to the result sequence list */ if (featureSeq) { LstMove ((void**) res_seq, (void**)&featureSeq); return 1; } } #endif return 0; } /**api* SlbWriteFosn ********************************************************** ** ** writes list of features as extended FOSN file with begin and end ** positions within parent sequence, complement...join ** ** INPUT: address of sequence object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void SlbWriteFosn (SEQo *seq) { SEQo *joinSeq; char hexNumStr[20], l[133]; INT4 (*print)(); IdToStr (global_entry->id, hexNumStr); print = ParGetFunction ("printf"); /* ** check first if there is a sublist (-> join) and process that */ if (seq->sublist && ParGetNum ("fosnWithPos")) { joinSeq = seq->sublist; /* ** start with the last sequence if the WHOLE join must be complemented ** in that case all individual joined sequences must be complemented */ if (seq->compl_f) LstLast ((void **) &joinSeq); else LstFirst ((void **) &joinSeq); do { if (seq->compl_f) joinSeq->compl_f = !joinSeq->compl_f; if (!*joinSeq->name) sprintf (l, "%s:%s", global_entry->lib->nam, global_entry->entry_nm); else { sprintf (l, "%s", joinSeq->name); } sprintf (l, "%s Begin: %d End: %d", l, joinSeq->bpos, joinSeq->epos); if (LibIsDataType (global_entry->lib, "dna")) sprintf (l, "%s Strand: %c", l, joinSeq->compl_f ? '-' : '+'); sprintf (l, "%s Join: %s_%d", l, global_entry->entry_nm, global_entry->id->subentry_n); sprintf (l, "%s !Id: %s\n", l, hexNumStr); print (l); } while (seq->compl_f ? LstPrev ((void **) &joinSeq) : LstNext ((void **) &joinSeq)); } /* ** normal sequence */ else { sprintf (l, "%s", EntryGetGCGName (global_entry)); if (ParGetNum ("fosnWithPos")) { if (seq->part_len > 0) seq->bpos = seq->epos - seq->part_len + 1; else if (seq->part_len < 0) seq->epos = seq->bpos + -seq->part_len - 1; sprintf (l, "%s Begin: %d End: %d", l, seq->bpos, seq->epos); if (LibIsDataType (global_entry->lib, "dna")) sprintf (l, "%s Strand: %c", l, seq->compl_f ? '-' : '+'); sprintf (l, "%s Join: %s_%d", l, EntryGetName (global_entry), global_entry->id->subentry_n); } sprintf (l, "%s !Id: %s\n", l, hexNumStr); print (l); } } /**API* SlbNextSequence ******************************************************* ** ** 'Walks' to the next sequence in the file. Use "EntryOpenStream" to open ** the flat file. ** ** INPUT: address of entry object [W] ** IMPLICIT: ** ** RETURNS: 1 on success ** 0 if at the end of the file */ INT4 SlbNextSequence (ENTRYo *entry) { #ifdef xxx SRSoFILTYP *fileType=entry->lib->form->fil_t[1]; FILo *file=entry->file[1]; INT4 k; while (1) { if (SmXLoc (file->l, fileType->fsts, fileType->fstl, fileType->fstr) != -1) break; if (FilURead (file) == e__eof) return 0; } /* ** advance lines */ for (k=1; k < fileType->adv; k++) FilURead (file); entry->isDataBegin = 1; entry->fip[1] = file->crfdd; #endif return 1; } /**API* SlbGetSequence ******************************************************** ** ** Retrieves the sequence for specified entry. ** ** INPUT: address of entry object [R] ** address of pointer to sequence object [W] ** IMPLICIT: ** ** RETURNS: 1 on success ** 0 otherwise */ INT4 SlbGetSequence (ENTRYo *entry, SEQo **seqPtr) { #ifdef xxx SEQo *seq=NULL; SRSoFILTYP *fileType; FIP fipSave; INT4 isGetSeqLenOnly = ParGetNum ("getSeqLenOnly"), splitN; char name[50], dummy[10]; #if defined(TRACE) printf("SlbGetSequence: %d\n", sequence_count++); #endif if (entry->isDataBegin) entry->isDataBegin = 0; /* stream access - file pointer is positioned */ else if (!EntryOpenData (entry)) return 0; /* ** get the file type object and assume that the first line after the ** sequence title is a comment line only if a production "find" for ** the entry name is specified */ fileType = entry->lib->form->fil_t[ENTxDATA]; SeqSetRecordSeparator (fileType->type == SLBxGCG7 ? 1 : 0); /* gcg format for vms */ SeqFromLib (seqPtr, entry->file[ENTxDATA], (*fileType->find) ? fileType->find : NULL, /* scanf gets name */ fileType->exit, (*fileType->find ? 1 : 0) | /* no title line -> no comment ... */ (isGetSeqLenOnly ? 2 : 0)); /* ** GCG 8.1 if a sequence exceeds some size it is split into overlapping ** fragments, each 110000bp long with an overlap of 10000 ** sequence which is the continuation - a file is considered to be split ** if it has exactly the split size. */ if (fileType->type == SLBxGCG8_1 && sscanf ((*seqPtr)->name, "%[A-Z0-9]_%[0]", name, dummy) == 2) { strcpy ((*seqPtr)->name, name); fipSave = entry->fip[1]; if (isGetSeqLenOnly) (*seqPtr)->len -= 10000; else SeqHead (*seqPtr, 100000); while (1) { SlbNextSequence (entry); SlbGetSequence (entry, &seq); if (seq->len == 110000) { if (isGetSeqLenOnly) seq->len -= 10000; else SeqHead (seq, 100000); } if (isGetSeqLenOnly) (*seqPtr)->len += seq->len; else SeqCat (seqPtr, seq); if (seq->len != 100000) /* the last of the split subentries */ break; } entry->fip[1] = fipSave; } /* ** if the sequence is split into two files (GCG format) then get the next ** sequence which is the continuation - a file is considered to be split ** if it has exactly the split size. */ else if ((*seqPtr)->len && (*seqPtr)->len == fileType->gcgSplitSize) { fipSave = entry->fip[1]; SlbNextSequence (entry); SlbGetSequence (entry, &seq); if (isGetSeqLenOnly) (*seqPtr)->len += seq->len; else SeqCat (seqPtr, seq); SeqClr (&seq); entry->fip[1] = fipSave; } if (!*fileType->find) /* no title line -> no name either */ strcpy ((*seqPtr)->name, entry->entry_nm); #endif return 1; } /****** SlbJoinList *********************************************************** ** ** implements the join function of a sequence expression. ** Creates a new function object as first member of a local list. ** The current parameter list is assigned to the sublist pointer ** of the new function object. As there is no parameter list any more, ** the local list can be assigned to the (new) parameter list. ** ** INPUT: ** IMPLICIT: ** seqRangeList changes ** ** RETURNS: nothing */ static void SlbJoinList() { SEQo *local_list = NULL; if (SeqNew(&local_list)) { /*sprintf (local_list->name, "%s", global_entry->entry_nm);*/ strcpy(local_list->name, "JOIN"); /* ** no hashing if LstHashSearch or LstDelete... is never used */ LstAssign((void**)&local_list->sublist, (void**)&seqRangeList); LstAssign((void**)&seqRangeList, (void**)&local_list); } else printf("ERROR: JOIN object could not be created in SlbJoinList !\n"); } /****** SlbComplementList ***************************************************** ** ** implements the complement function of a sequence expression. ** Simply inverts the complement flag of the current sequence object ** in the seqRangeList. ** ** INPUT: ** IMPLICIT: ** inverts the complement flag of the current sequence object ** ** RETURNS: nothing */ static void SlbComplementList() { seqRangeList->compl_f = !seqRangeList->compl_f; } /****** SlbReplaceList ******************************************************** ** ** implements the replace function of a sequence expression. ** Simply sets the replace string of the current sequence object ** in the seqRangeList. ** ** INPUT: ** address of replace string [R] ** IMPLICIT: ** sets the replace string of the current sequence object ** ** RETURNS: nothing */ static void SlbReplaceList(char *replace) { seqRangeList->replace = (char*) malloc(strlen(replace) + 1); strcpy(seqRangeList->replace, replace); } /****** SlbInsert ************************************************************* ** ** inserts a new (current) subsequence object (range) into the ** "seqRangeList". ** The accession number of a sequence object is up to now initially ** set to an empty string, i.e. the accession number equals the ** accession number of the current entry. ** In case of the CUT operator the cut_f flag has to be set afterwards. ** ** INPUT: start position of subsequence [R] ** end position of subsequence [R] ** IMPLICIT: ** new sequence object in seqRangeList ** ** RETURNS: 1 on success, 0 otherwise */ static INT4 SlbInsert (INT4 bpos, INT4 epos) { if (!SeqNew(&seqRangeList)) return 0; if (bpos<0) { seqRangeList->before_f = 1; seqRangeList->bpos = -bpos; } else { seqRangeList->before_f = 0; seqRangeList->bpos = bpos; } if (epos<0) { seqRangeList->after_f = 1; seqRangeList->epos = -epos; } else { seqRangeList->after_f = 0; seqRangeList->epos = epos; } return 1; } /****** SlbSetAccno *********************************************************** ** ** sets accession number of last (current) sequence object in the ** seqRangeList. The accession number of a sequence object is initially ** set to an empty string, i.e. the accession number equals the ** accession number of the current entry. ** ** INPUT: address of accession number [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ static INT4 SlbSetAccno(char *acc) { if (seqRangeList) strcpy(seqRangeList->accno, acc); else { _ErrMsg(e__noseqinlist); return 0; } return 1; } /****** SlbModifyBegin ******************************************************** ** ** modifies the begin positiom of the specified sequence object. ** If an illegal position (<1) would result, an error is ** reported. ** ** INPUT: address of a sequence object [R] ** delta for shift [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ static INT4 SlbModifyBegin(SEQo *range, INT4 delta) { if (range) if (range->bpos + delta > 0) range->bpos += delta; else { if (!ParGetNum("takeuncompleteshiftfeature")) { _ErrRet2 (e__shiftseqisfrag, SlbGetCurrEntryName ()); } else range->bpos = 1; } else { _ErrMsg(e__noseqinlist); return 0; } return 1; } /****** SlbModifyEnd ********************************************************** ** ** modifies the end positiom of the specified sequence object. ** If an illegal position (<1) would result, an error is ** reported. ** ** INPUT: address of a sequence object [R] ** delta for shift [R] ** IMPLICIT: ** ** RETURNS: 1 on success, 0 otherwise */ static INT4 SlbModifyEnd(SEQo *range, INT4 delta) { if (range) if (range->epos + delta > 0) range->epos += delta; else { if (!ParGetNum("takeuncompleteshiftfeature")) { _ErrRet2 (e__shiftseqisfrag, SlbGetCurrEntryName ()); } else range->epos = 1; } else { _ErrMsg(e__noseqinlist); return e__noseqinlist; } return 1; } /****** SlbSeqFromAccNo ******************************************************* ** ** gets the complete sequence string belonging to the entry with the ** specified accession number. To retrieve the sequence string the ** unique accession number is transformed into a unique id_name. ** If the sequence string is not already in the global list (seq) ** it will be retrieved by a query and the sequence object will be ** inserted into the global list. ** ** INPUT: address of accession number [R] ** IMPLICIT: ** global_entry (ENTRYo) [R] ** featureSeq (SEQo *) [W] ** ** RETURNS: address of the sequence object ** 0, in case of an error (message already printed) */ static SEQo *SlbSeqFromAccNo (char *accno) { ENTRYo *entry = global_entry; IDoENTRY *id; SEQo *seq = NULL; INT4 rv; char libEntryName[80] = "", *tmp; /* ** use external program to fetch the sequence by accession number */ if (*accno && (tmp = ParGetStr ("findAccNoCommand")) && *tmp) { if (!(seq = SlbRetrieveAccNo (accno))) return NULL; LstMove((void**)&featureSeq, (void**)&seq); } /* ** retrieve sequence if accno is specified ...no accession number means ** sequence of current entry which may not be read yet */ else { if (*accno) { #ifdef xx if (!(id = QryFindID (LibGetName (global_entry->lib, "full"), "acc", accno))) { /* _ErrMsg3(e__couldnotgetsequence,accno, global_entry->entry_nm); */ return NULL; } #endif entry = EntryOpen (id); } else if (seqCurr) return seqCurr; /* for SlbMakeFeature */ strcpy (libEntryName, EntryGetGCGName (entry)); /* ** search in the current sequence list ...to check if current entry's ** sequence is opened */ if (!LstHashSearch((void**)&featureSeq, libEntryName)) { rv = SlbGetSequence (entry, &seq); if (entry != global_entry) { EntryClose (&entry); } if (!rv) { LstDeleteAll ((void**)&seq); _ErrMsg2 (e__couldnotgetsequence, accno); return NULL; } LstMove((void**)&featureSeq, (void**)&seq); strcpy (featureSeq->name, libEntryName); } } return featureSeq; } /****** SlbRetrieveAccNo ****************************************************** ** ** Uses the command specified in "findAccNoCommand" to get entry by ** accession number. ** ** INPUT: address of accession number [R] ** IMPLICIT: ** ** RETURNS: address of the complete sequence string ** 0, in case of an error (message already printed) */ static SEQo *SlbRetrieveAccNo (char *accno) { SEQo *seq=NULL; INT4 rv; char command[256], fileName[256]; sprintf (command, ParGetStr ("findAccNoCommand"), accno, accno, accno); sprintf (fileName, ParGetStr ("inputSeqFile"), accno); system (command); rv = SeqReadAll (&seq, fileName); remove (fileName); return (rv && !_ErrIs (rv) )? seq : NULL; } /****** SeqReplace ************************************************************ ** ** ** INPUT: address of a sequence object [R] ** IMPLICIT: ** ** RETURNS: 1 on success ** e__incorrectlength */ INT4 SeqReplace (SEQo *new, SEQo *seq, char *replace, INT4 begPos, INT4 endPos, INT4 doInsert) { INT4 length; /* calculate length of output sequence */ length = strlen (seq->seq) + strlen (replace); if (!doInsert) length -= endPos - begPos + 1; new->seq = (char*) malloc (length + 1); new->len = length; if (doInsert) { strncpy (new->seq, seq->seq, begPos); new->seq[begPos] = '\0'; strcat (new->seq, replace); strcat (new->seq, &seq->seq[begPos]); /* endPos = begPos +1 */ } else { strncpy (new->seq, seq->seq, begPos - 1); new->seq[begPos - 1] = '\0'; strcat (new->seq, replace); strcat (new->seq, &seq->seq[endPos]); } if (new->len != strlen (new->seq)) _ErrRet1 (e__incorrectlength); return 1; } /****** SeqGetSubSeq ********************************************************** ** ** ** INPUT: address of a sequence object [R] ** IMPLICIT: ** ** RETURNS: 1 on success ** e__incorrectlength */ INT4 SeqGetSubSeq (SEQo *new, SEQo *seq, INT4 begPos, INT4 endPos) { INT4 length; length = endPos - begPos + 1; if (length <= 0) _ErrRet4 (e__seqwithneglen, SlbGetCurrEntryName (), begPos, endPos); new->seq = (char*) malloc (length + 1); strncpy (new->seq, &(seq->seq[ begPos-1 ]), length); new->seq[length] = '\0'; new->len = length; return 1; } /****** SlbEvalSequence ******************************************************* ** ** gets the sequence string belonging to the specified sequence object. ** If the sequence string is not already calculated the calculation ** will be done here using the complete sequence of an entry with ** an unique accession number and the begin and end of a partial ** sequence. At last the sequence string may be complemented. ** ** INPUT: address of a sequence object [R] ** IMPLICIT: ** ** RETURNS: 1 on success ** e__error, in case of an already printed error message ** e__postoohigh, position is greater than length of sequence */ static INT4 SlbEvalSequence (SEQo *new) { SEQoTranslExcept *tmp; SEQo *seq; INT4 rv; if (new->seq) return 1; /* fetch pointer (tmp) to complete sequence */ if ((seq = SlbSeqFromAccNo (new->accno)) == NULL) { _ErrMsg2 (e__couldnotgetsequence, new->accno); _ErrRet (e__error); } strcpy (new->name, seq->name); /* ** report error if begin and end positions are greater than sequence length */ /* to be fixed some time (te) */ if (feature.tExceptN > 1) { for (tmp=feature.tExcept; tmp->aa; tmp++) if (tmp->begin >= new->bpos && tmp->begin < new->bpos + new->epos) tmp->begin = tmp->begin - new->bpos + 1; } if (new->bpos > seq->len) { if (!ParGetNum ("takeuncompletefeature")) _ErrRet1 (e__postoohigh); else new->bpos = seq->len; } if (new->epos > seq->len) { if (!ParGetNum ("takeuncompletefeature")) _ErrRet1 (e__postoohigh); else new->epos = seq->len; } if (new->replace) rv = SeqReplace (new, seq, new->replace, new->epos, new->bpos, new->cut_f); else rv = SeqGetSubSeq (new, seq, new->bpos, new->epos); _ErrRet (rv); if (new->compl_f) SeqComplement (new); return 1; } /****** SlbShiftAndCheck ***************************************************** ** ** looks for the current values of the modification parameters (shift) and ** checks the global seqRangeList. In the seqRangeList there could be ** one sequence object generated by an expression like "135 .. 177" or ** one function object that has a sublist of sequence objects generated ** by an expression like "join(135 .. 177, complement(23 .. 97))". ** ** INPUT: ** IMPLICIT: ** ** RETURNS: 1 on success ** e__nothingtoevaluate ** e__invalidshift ** e__relbegandend ** */ static INT4 SlbShiftAndCheck() { SEQo *range; INT4 begPos=0, endPos=0, isBegRelEnd=0, isEndRelBeg=0; INT4 head_len=0, tail_len=0; INT4 rv; if (!seqRangeList) { _ErrRet2 (e__nothingtoevaluate, SlbGetCurrEntryName ()); } begPos = ParGetNum ("shiftbeginpos"); endPos = ParGetNum ("shiftendpos"); isBegRelEnd = ParGetNum ("isshiftbeginrelend"); isEndRelBeg = ParGetNum ("isshiftendrelbegin"); /* ** return error message for all combinations of ** modification parameters that should not occur */ if (isBegRelEnd && isEndRelBeg) _ErrRet2 (e__relbegandend, SlbGetCurrEntryName ()); else if (isBegRelEnd && begPos > endPos) _ErrRet5 (e__invalidshift, SlbGetCurrEntryName (), begPos, endPos, "end"); else if (isEndRelBeg && begPos > endPos) _ErrRet5 (e__invalidshift, SlbGetCurrEntryName (), begPos, endPos, "beg"); /* ** compute length of head or tail subsequence */ if (isEndRelBeg) head_len = endPos - begPos + 1; if (isBegRelEnd) tail_len = endPos - begPos + 1; seqRangeList->part_len = 0; /* whole sequence */ if (head_len > 0) seqRangeList->part_len = -head_len; if (tail_len > 0) seqRangeList->part_len = tail_len; range = seqRangeList->sublist; /* for shorter source code */ if (!range) { if (begPos && !isBegRelEnd) rv = SlbModifyBegin (seqRangeList, begPos); else if (begPos && isBegRelEnd) rv = SlbModifyBegin (seqRangeList, endPos - begPos); else if (endPos && !isEndRelBeg) rv = SlbModifyEnd (seqRangeList, endPos); _ErrRet (rv); /* already printed */ rv = SlbEvalSequence(seqRangeList); _ErrRet (rv); /* already printed */ } else { /* ** range is the sublist of a (Join-) function */ if (begPos && !isBegRelEnd) if (LstFirst((void**)&range)) rv = SlbModifyBegin (range, begPos); if (endPos && !isEndRelBeg) if (LstLast((void**)&range)) rv = SlbModifyEnd (range, endPos); if (LstFirst((void**)&range)) { do { rv = SlbEvalSequence(range); _ErrRet (rv); /* already printed */ } while (LstNext((void**)&range)); } else { _ErrRet(e__noparamlist); } } return 1; } /****** SlbEvaluate *********************************************************** ** ** evaluates the global seqRangeList. In the seqRangeList there could be ** one sequence object generated by an expression like "135 .. 177" or ** one function object that has a sublist of sequence objects generated ** by an expression like "join(135 .. 177, complement(23 .. 97))". ** ** INPUT: ** IMPLICIT: ** featureSeq (SEQo *) [W] ** ** RETURNS: 1 on success, 0 otherwise ** */ static INT4 SlbEvaluate() { SEQo *range; if (!seqRangeList) { _ErrMsg(e__nothingtoevaluate); return 0; } range = seqRangeList->sublist; /* for shorter source code */ if (!range) { /* the single range (seqRangeList) has been evaluated already */ SeqJoin (&featureSeq, seqRangeList); } else { /* ** range is the sublist of a (Join-) function. ** Make sure that all ranges in this list ** are already evaluated (SlbEvalSequence) ** before joining them (see SlbShiftAndCheck) */ if (LstFirst((void**)&range)) { SeqJoin (&featureSeq, range); } else { _ErrMsg(e__noparamlist); return 0; } } /* ** give sequence a name, and complement it if necessary */ if (seqRangeList->compl_f && seqRangeList->sublist) SeqComplement (featureSeq); strcpy (featureSeq->name, "RESULT"); strcpy (featureSeq->accno, "RESULT"); if (seqRangeList->part_len < 0) SeqHead(featureSeq, -seqRangeList->part_len); if (seqRangeList->part_len > 0) SeqTail (featureSeq, seqRangeList->part_len); return 1; } /**api* SlbListReset ********************************************************** ** ** deletes all local lists (seq, seqRangeList) created during evaluation ** ** INPUT: ** IMPLICIT: ** featureSeq (SEQo *) [W] ** ** RETURNS: 1 */ INT4 SlbListReset() { LstDeleteAll ((void**) &seqRangeList); if (featureSeq) LstDeleteAll ((void**) &featureSeq); return 1; } /****** SlbCitationDump **************************************** ** ** dumps all information belonging to the specified object. ** This is the print function set through LstManageClass ** for citationtype objects (see SlbCitationNew). ** ** INPUT: address of an object [R] ** file pointer [W] or NULL ** IMPLICIT: ** ** RETURNS: nothing */ static void SlbCitationDump (FILE *file, void *obj) { CITATION *tmp = (CITATION*)obj; if (!file) file = stderr; fprintf (file, "*** /CITATION %d\n", tmp->citationNum); } /**api* SlbCitationNew ************************************************* ** ** gets a new initialized citation object. ** The citationtype_id tells, if the class CITATION is already ** registered by the list module (LstManageClass). ** ** INPUT: pointer to address of citation object [W] ** IMPLICIT: ** ** RETURNS: */ INT4 SlbCitationNew (CITATION **citation) { static INT4 citationtype_id=0; if (!citationtype_id) LstManageClass (&citationtype_id, sizeof (CITATION), NULL, NULL, SlbCitationDump); return LstNew ((void **) citation, citationtype_id); } /****** SlbInitFeature ******************************************************** ** ** initializes global feature object ...functions that modify it can ** be called directly form the parser. ** For managing translation exceptions the list module has been used. ** Therefore, when resetting the feature object, an already existing ** list has to be destroyed. ** ** INPUT: feature object [W] ** IMPLICIT: ** ** RETURNS: */ static void SlbInitFeature (SLBoFEATURE *feature) { feature->tTableId = 0; /* id of translation table to be used */ feature->codonStartShifted = 0; /* normally there should be no shifting */ feature->codonStart = 1; /* default start position */ feature->isPseudo = 0; /* ** if lists of special treated codons, translation exceptions or ** citations exist, free the lists */ if (!feature->tCodon) { _addObj (feature->tCodon, feature->tCodonN, feature->tCodonAllocN, SEQoTranslCodon); } else if (feature->tCodonN > 1) feature->tCodonN = 1; feature->tCodon->aa = 0; if (!feature->tExcept) { _addObj (feature->tExcept, feature->tExceptN, feature->tExceptAllocN, SEQoTranslExcept); } else if (feature->tExceptN > 1) feature->tExceptN = 1; feature->tExcept->aa = 0; if (feature->citation) LstDeleteAll((void**)&feature->citation); feature->citation = NULL; /* no list */ if (!feature->gene) { feature->gene = BuffNew (20); feature->product = BuffNew (20); feature->note = BuffNew (20); } else { BuffReset (feature->gene); BuffReset (feature->product); BuffReset (feature->note); } } /**api* SlbSetCodonStart ***************************************************** ** ** ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSetCodonStart (PRSoST *tokList, FILo *file) { #ifdef xxx UINT4 tokval; char tokstr[20]; PrsUnSym (tokList, tokstr, &tokval); feature.codonStart = atoi (tokstr); #endif return 1; } /**api* SlbSetCodon ********************************************************** ** ** ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSetCodon (PRSoST *tokList, FILo *file) { #ifdef xxx SEQoTranslCodon *tCodon=&feature.tCodon[feature.tCodonN-1]; UINT4 tokval; char tokstr[20]; PrsUnSym (tokList, tokstr, &tokval); PrsUnSym (tokList, tokstr, &tokval); tCodon->aa = *tokstr; PrsUnSym (tokList, tCodon->codon, &tokval); _addObj (feature.tCodon, feature.tCodonN, feature.tCodonAllocN, SEQoTranslCodon); (++tCodon)->aa = 0; #endif return 1; } /**api* SlbSetTranslTable *************************************************** ** ** ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSetTranslTable(PRSoST *tokList, FILo *file) { #ifdef xxx UINT4 tokval; char tokstr[20]; PrsUnSym (tokList, tokstr, &tokval); feature.tTableId = atoi (tokstr); #endif return 1; } /**api* SlbSetTranslExcept **************************************************** ** ** ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSetTranslExcept (PRSoST *tokList, FILo *file) { #ifdef xxx SEQoTranslExcept *tExcept; UINT4 tokval; char tokstr[20], end[20]; tExcept = &feature.tExcept[feature.tExceptN-1]; PrsUnSym (tokList, tokstr, &tokval); /* ) */ PrsUnSym (tokList, tokstr, &tokval); /* aa */ tExcept->aa = *tokstr; PrsUnSym (tokList, end, &tokval); /* posend */ PrsUnSym (tokList, tokstr, &tokval); /* posbegin */ tExcept->begin = atoi (tokstr); tExcept->length = atoi (end) - tExcept->begin + 1; /* add new terminator */ _addObj (feature.tExcept, feature.tExceptN, feature.tExceptAllocN, SEQoTranslExcept); (++tExcept)->aa = 0; #endif return 1; } /**api* SlbSetCitation ***************************************************** ** ** ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSetCitation (PRSoST *tokList, FILo *file) { #ifdef xxx UINT4 tokval; char tokstr[20]; SlbCitationNew (&feature.citation); /* get new object */ PrsUnSym (tokList, tokstr, &tokval); feature.citation->citationNum = atoi (tokstr); #endif return 1; } /**api* SlbSetPseudo ********************************************************** ** ** Called during feature parsing. Sets the "pseudo gene" flag. ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSetPseudo (PRSoST *tokList, FILo *file) { feature.isPseudo = 1; return 1; } /**api* SlbSaveQualText ******************************************************* ** ** Called during feature parsing. Saves the text for certain qualifiers. ** ** INPUT: ** IMPLICIT: ** feature (SLBoFEATURE *) [W] ** ** RETURNS: 1 */ INT4 SlbSaveQualText (PRSoST *tokList, FILo *file) { #ifdef xxx UINT4 tokval; char text[500], qualName[30]; PrsUnSym (tokList, text, &tokval); PrsUnSym (tokList, qualName, &tokval); switch (tolower (qualName[0])) { case 'g': /* gene */ BuffCopyString (feature.gene, text); break; case 'p': /* product */ BuffCopyString (feature.product, text); break; case 'n': /* note */ BuffCopyString (feature.note, text); break; default: _ErrExit2 (e__unknownoption, qualName); } #endif return 1; } ** ** $RCSfile: seqlib.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:19 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** */ typedef struct { char *manager; /* the first two attributes are necessary */ INT4 type_id; /* for all objects to be managed by the list module */ INT4 citationNum; } CITATION; typedef struct SLBoFEATURE { INT4 tTableId; INT4 codonStartShifted; /* set during translation */ INT4 codonStart; /* from the databank */ struct SEQoTranslCodon *tCodon; /* List of special codon translations */ INT4 tCodonN; INT4 tCodonAllocN; struct SEQoTranslExcept *tExcept; /* List of transl_except */ INT4 tExceptN; INT4 tExceptAllocN; CITATION *citation; /* List of citations (numbers) */ INT4 isPseudo; /* only for CDS features */ SMoBUFF *gene; SMoBUFF *product; SMoBUFF *note; } SLBoFEATURE; #ifndef _SEQo typedef struct SEQo *dummytointroducestructtagSEQoinseqlib; typedef struct ENTRYo *dummytointroducestructtagENTRYoinseqlib; #endif INT4 SlbMakeFeature (SMoBUFF *featureBuff, struct ENTRYo *entry, struct SEQo *entry_seq, struct SEQo **res_seq, SLBoFEATURE **featurePtr); INT4 SlbGetFeature (struct ENTRYo *entry, struct SEQo **res_seq, SLBoFEATURE **featurePtr); INT4 SlbGetSequence(struct ENTRYo *entry, struct SEQo **res_seq); INT4 SlbListReset(); INT4 SlbNextSequence (struct ENTRYo *entry); char set_ID[] = "$Id: set.c,v 1.5 1996/08/11 22:47:19 etzold Exp $"; /* ** ** $RCSfile: set.c,v $ ** $Revision: 1.5 $ ** $Date: 1996/08/11 22:47:19 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** functions for manipulating sets of IDs ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "message.h" #include "lst.h" #include "sm.h" #include "strv.h" #include "futil.h" #include "id.h" #include "entry.h" #include "set.h" #include "library.h" #define _SRS #define _SLB #include SRSINCLUDE #define SETxNOCPY 0 #define SETxNULL 4294967295U /* long with all bits turned ON */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macro for comparing entry ID's - IDs are BIG-endian on all operating ** systems! ie, last byte of IDs are compared first, then second last... */ #define CMP(a,b,cmp,len) {\ register INT4 _i;\ for (_i = (len)-1; _i >= 0; _i--) {\ if (((cmp) = (a)[_i] - (b)[_i]) != 0) break;\ }} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macro to copy sets */ #define _SetCopyIds(b, a1, a2, len)\ len = (unsigned long) a2 - (unsigned long) a1;\ _BuffCopyNChars (b, a1, len) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** macro inits string buffer */ #define _SetInitBuff(b)\ if (!buff) \ buff = BuffNew (2000);\ else\ BuffReset (buff) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static void SetInit (void *obj); static void SetKill (void *obj); static void SetDump (FILE *file, void *obj); static IDPTR SetOr (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *cn, INT4 id_z); static IDPTR SetNot (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *cn, INT4 id_z); static IDPTR SetAnd (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *cn, INT4 id_z); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** declaration of global or module wide variables */ static SMoBUFF *buff=NULL; static SETo *set=NULL; /**api* SetDump ************************************************************** ** ** dumps all information belonging to the specified object. ** This is the print function set through LstManageClass ** for set_type objects (see SetNew). ** ** INPUT: address of an object [R] ** file pointer [W] or NULL ** IMPLICIT: ** ** RETURNS: nothing */ static void SetDump (FILE *file, void *obj) { SETo *tmp = (SETo*)obj; if (!file) file = stderr; fprintf (file, "set *%s* with %d entries\n", tmp->nam, tmp->n); } /****** SetInit ************************************************************** ** ** initializes the specified object. ** This is the init function set through LstManageClass ** for set_type objects (see SetNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void SetInit (void *obj) { SETo *tmp = (SETo*)obj; tmp->id_p = NULL; /* dummy values */ tmp->queryStr = NULL; tmp->tmp_f = FALSE; tmp->anal_f = 0; tmp->n = 0; tmp->id_d = NULL; tmp->allocN = 0; tmp->isDb = 0; } /****** SetKill ************************************************************** ** ** deletes the specified object. ** This is the delete function set through LstManageClass ** for set_type objects (see SetNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void SetKill (void *obj) { SETo *tmp = (SETo*)obj; if (tmp->id_p) free (tmp->id_p); if (tmp->queryStr) StrDel (tmp->queryStr); } /**api* SetNew **************************************************************** ** ** Creates a new set with a unique name used as identifier. ** If called with option "temp" then a unique name is created and ** in case the address of set name is not NULL copied there. ** Issues a message if set with specified name exists already. **

    ** A set can be deleted with SetDelete. SetClean deletes all ** sets created with "temp". ** Use SetGet to obtain an existing set by name. ** ** INPUT: set name [W] or NULL ** option: "temp" (or NULL) [R] ** IMPLICIT: ** set (SETo *) [W] ** ** RETURNS: address of new set ** NULL: specified set name is alredy in use */ SETo *SetNew (char *setName, char *opt) { static INT4 setclass_id=0; static INT4 setN=0; char tmpName[SETxXNAM]; if (!setclass_id) { LstManageClass (&setclass_id, sizeof (SETo), SetInit, SetKill, SetDump); } if (opt && opt[0] == 't') { /* "temp" */ sprintf (tmpName, "tmpset_%d", ++setN); if (setName) strcpy (setName, tmpName); } else if (setName) { strcpy (tmpName, setName); SmEdit (tmpName, SMxLOWCASE); } if (!SetTestName (tmpName)) { _ErrMsg2 (e__setnotuniqname, tmpName); return NULL; } LstNewNamed ((void **) &set, setclass_id, tmpName); set->tmp_f = (opt && opt[0] == 't') ? TRUE : FALSE; return set; } /**api* SetTestName *********************************************************** ** ** checks if set-name has not been previously defined or if name is ** reserved - issues a message if the case; ** ** INPUT: address of name [R] ** IMPLICIT: ** set (SETo *) [R] ** ** RETURNS: 1 if new ** 0 if not */ INT4 SetTestName (char *setName) { LINKo *link; INT4 context; char tmpName[80]; strcpy (tmpName, setName); SmEdit (tmpName, SMxLOWCASE); if (LstHashSearch ((void **) &set, tmpName)) return 0; /* for (context=0; (link = LibNextLink (&context)); ) if (SmEqs (tmpName, link->nam1) || SmEqs (tmpName, link->nam2)) return 0; */ return 1; } /**api* SetSetIsDb *********************************************************** ** ** Sets a flag in the set objects that it now represents an entire data ** bank. ** ** INPUT: set object [W] ** IMPLICIT: ** set (SETo *) [R] ** ** RETURNS: */ void SetSetIsDB (SETo *set) { set->isDb = 1; } /**api* SetIsDb *********************************************************** ** ** Returns 'true' if the set represents an entire databank. ** bank. ** ** INPUT: set object [W] ** IMPLICIT: ** ** RETURNS: 1 or 0 */ INT4 SetIsDB (SETo *set) { return set->isDb; } /**api* SetGetName ************************************************************ ** ** Returns the name of the set. ** ** INPUT: set object [W] ** IMPLICIT: ** ** RETURNS: set name */ char *SetGetName (SETo *set) { return set->nam; } /**API* SetGet ************************************************************* ** ** Searches for a set with specified name and returns its address ** (case insensitive). ** ** INPUT: set name [R] ** IMPLICIT: ** set (SETo *) [R] ** ** RETURNS: address of set object ** NULL if not found */ SETo *SetGet (char *setName) { char tmpName[80]; strcpy (tmpName, setName); SmEdit (tmpName, SMxLOWCASE); if (!LstHashSearch ((void **) &set, tmpName)) return NULL; if (set->anal_f && set->id_d != NULL) /* list libraries */ SetLibStat (set); return set; } /**API* SetSize ************************************************************* ** ** Returns the size of the set (number of IDs) with the specified name. ** ** INPUT: set name [R] ** IMPLICIT: ** ** RETURNS: number of entries in the set */ INT4 SetSize (char *nam) { SETo *set; if (!(set = SetGet (nam))) return 0; else return set->n; } /**API* SetGetSize ************************************************************ ** ** Returns the size of the set (number of IDs). ** ** INPUT: set object [R] ** IMPLICIT: ** ** RETURNS: number of entries in the set */ INT4 SetGetSize (SETo *set) { return set->n; } /**API* SetIsSubEntry ********************************************************* ** ** Returns 1 if the set contains subentry IDs. ** ** INPUT: set name [R] ** IMPLICIT: ** ** RETURNS: 1 ** 0 if not */ INT4 SetIsSubEntry (char *nam) { SETo *set; if (!(set = SetGet (nam)) || !set->id_d) return 0; else return set->id_d->siz > 4 ? 1 : 0; } /**API* SetDelete ************************************************************* ** ** Deletes a Set with specified name. ** ** INPUT: set name [R] ** IMPLICIT: ** set (SETo *) [W] ** ** RETURNS: 1 if success ** set name does not exist: e__novalnam */ INT4 SetDelete (char *setName) { char tmpName[80]; strcpy (tmpName, setName); SmEdit (tmpName, SMxLOWCASE); if (!LstHashSearch ((void **) &set, tmpName)) _ErrRet(e__novalnam); LstDelete ((void **) &set); return 1; } INT4 SetDel (SETo *setPtr) { if (!LstHashSearch ((void **) &set, setPtr->nam)) _ErrRet(e__novalnam); LstDelete ((void **) &set); } /**api* SetClean ************************************************************** ** ** Deletes all temporary sets; ** ** INPUT: ** IMPLICIT: ** set (SETo *) [W] ** ** RETURNS: number of sets deleted */ INT4 SetClean () { INT4 setDeletedN=0; if (!set) return 0; LstFirst ((void **) &set); do { if (set->tmp_f) { LstDelete ((void **) &set); setDeletedN++; } } while (LstNext ((void **) &set)); return setDeletedN;; } /**api* SetPrintAll ********************************************************* ** ** Prints information on all sets in global list; ** ** INPUT: ** IMPLICIT: ** ** RETURNS: nothing */ void SetPrintAll() { LstPrintAll((void*)set); } /**api* SetAlloc ************************************************************** ** ** allocates memory for a set of pointers; ** ** INPUT: address of set descriptor [W] ** number of IDs [R] ** id-Type object [R] or NULL ** ** RETURNS: 1 ** e__allocfail + */ INT4 SetAlloc (SETo *set, INT4 n, IDoTYPE *id_d) { if (id_d) set->id_d = id_d; if ((set->id_p = (IDPTR) malloc (n * set->id_d->siz)) == 0) _ErrRet2(e__allocfail, "set->ids by SetAlloc"); set->allocN = n; return 1; } /**api* SetGetIdBuff ************************************************************** ** ** Returns the pointer to an ID buffer with the specified size. In case ** the set's existing ID buffer is not large enough it will be increased. ** ** INPUT: set object [W] ** number of bytes [R] ** ** RETURNS: address of ID-buffer */ IDPTR SetGetIdBuff (SETo *set, INT4 n) { if (n > set->allocBytesN) { if (!set->allocBytesN) { if (!(set->id_p = (IDPTR) malloc (n))) _ErrExit2 (e__allocfail, "set ID buffer"); } else { if (!(set->id_p = (IDPTR) realloc ((void*) set->id_p, n))) _ErrExit2 (e__allocfail, "set ID buffer"); } set->allocBytesN = n; } return set->id_p; } /**api* SetAlloc ************************************************************** ** ** Reallocates memory for a set of pointers; ** ** INPUT: address of set descriptor [W] ** number of IDs [R] ** id-Type object [R] or NULL ** IMPLICIT: ** ** RETURNS: 1 ** e__allocfail + */ INT4 SetRealloc (SETo *set, INT4 n, IDoTYPE *id_d) { if (id_d) set->id_d = id_d; if ((set->id_p = (IDPTR) realloc ((void*) set->id_p, n*set->id_d->siz)) == 0) _ErrRet2(e__allocfail, "set->ids by SetRealloc"); set->allocN = n; return 1; } /**api* SetSetEntryN ************************************************************** ** ** Sets the number of the entries in the set. ** ** INPUT: set object [W] ** entry number [R] */ void SetSetEntryN (SETo *set, INT4 n) { set->n = n; } /**api* SetSetEntryN ************************************************************** ** ** Sets the number of the entries in the set. ** ** INPUT: set object [W] ** ID-type object [R] */ void SetSetIdType (SETo *set, IDoTYPE *idType) { set->id_d = idType; } /**API* SetGetNextLibStat ***************************************************** ** ** Returns next pair of library name and number of entries of set. ** This is useful information if a set is composed of IDs from ** different libraries. ** ** INPUT: name of set [R] ** pointer to address of library name [W] ** iteration context (must be initially set to 0) [W] ** IMPLICIT: ** ** RETURNS: number of entries from library ** 0 if no more value pairs exist */ INT4 SetGetNextLibStat (char *setName, char **libName, INT4 *context) { SETo *set; if (!(set = SetGet (setName))) return 0; if (!set->anal_f) SetLibStat (set); if (*context < 0 || *context >= set->lib_n) { *context = 0; return 0; } *libName = set->lib_nm[*context]; return set->lib_z[(*context)++]; } /**api* SetLibStat ************************************************************ ** ** forms an array of number of ID's per library in a set + library name ** and connects array to set-descrptor; note that all ID's of a certain ** library are always clustered since ID-block is sorted. ** ** INPUT: address of set-descriptor [W] ** IMPLICIT: ** ** RETURNS: nr of different sets found */ INT4 SetLibStat (SETo *set) { SLBo *lib; unsigned char lib_xs = 255; IDPTR x_p; INT4 k, n=0, siz, lib_n = 0; if (!set->n || set->anal_f) return 0; siz = set->id_d->siz; for (k=0, x_p = set->id_p + set->id_d->lbxbeg; k < set->n; k++, x_p += siz) if ((unsigned char ) *x_p != lib_xs) { lib_xs = *x_p; lib = (SLBo *) LibObjById ("library", *x_p); set->lib_nm[lib_n] = lib->nam; if (lib_n > 0) { set->lib_z[lib_n-1] = k-n; n = k; } n = k; lib_n++; } set->lib_z[lib_n-1] = k-n; set->lib_n = lib_n; set->anal_f = 1; return 1; } /**api* SetMakeOwn ************************************************************ ** ** allocates storage for a set that is parked in global storage or some ** other storage and copies it there. ** ** INPUT: address of set-descriptor [W] ** address of id-descr. set will receive [R] or NULL ** IMPLICIT: ** ** RETURNS: 1 ** e__allocfail + */ INT4 SetMakeOwn (SETo *set, IDoTYPE *id_d) { IDPTR id_p; INT4 siz; if (id_d) set->id_d = id_d; if (!set->id_d) _ErrRet (e__error); siz = set->n * set->id_d->siz; /*PURIFY*/ if (siz) { if ((id_p = (IDPTR) malloc (siz)) == 0) _ErrRet2(e__allocfail, "ids-block by SetMakeOwn"); memcpy (id_p, set->id_p, set->n * set->id_d->siz); } else id_p = NULL; set->id_p = id_p; return 1; } /**api* SetSort *************************************************************** ** ** heapsort the IDs in a set ** ** INPUT: set object [W] ** IMPLICIT: ** ** RETURNS: 1 ** e__allocfail + */ INT4 SetSort (SETo *set) { SetHeapSort (set->id_p, set->n, set->id_d->siz, 0, set->id_d->siz); SetRemoveDouble (set->id_p, set->n, set->id_d->siz, &set->n); return 1; } /**api* SetOp ***************************************************************** ** ** Performs logical operations AND, OR, NOT with sets of same type; ** if addres of resultant set is NULL then set a is replaced by resultant ** set "a" and memory held previously by set a is freed. ** ** INPUT: address of set a [W] ** address of set b [R] ** address of result set [W] (or NULL) ** operator: SETxAND, SETxOR, SETxNOT [R] ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 i both sets empty ** invalid set types: e__novalsettyp + ** invalid set operator: e__novalopt + */ INT4 SetOp (SETo *a, SETo *b, SETo *resultSet, INT4 op) { IDPTR idPtr; INT4 n; /* ** both sets are empty ...might not even have ** ID descriptors since, if from unsuccessful index search, were never set. */ if (a->n == 0 && b->n == 0) return 0; /* ** get the id descriptor from either of the two sets - it might not be ** defined for either; */ if (!b->id_d) b->id_d = a->id_d; if (!a->id_d) a->id_d = b->id_d; if (a->id_d != b->id_d) _ErrRet3 (e__novalsettyp, a->id_d->nam, b->id_d->nam); switch (op) { case SETxOR: idPtr = SetOr (a->id_p, b->id_p, a->n, b->n, &n, a->id_d->siz); break; case SETxAND: idPtr = SetAnd (a->id_p, b->id_p, a->n, b->n, &n, a->id_d->siz); break; case SETxNOT: idPtr = SetNot (a->id_p, b->id_p, a->n, b->n, &n, a->id_d->siz); break; default: _ErrRet3(e__novalopt, op, "logical operator"); } if (!resultSet) { if (a->id_p && (a->id_p != b->id_p)) free (a->id_p); resultSet = a; } resultSet->n = n; resultSet->id_p = idPtr; SetMakeOwn (resultSet, a->id_d); return 1; } /**API* SetGetID ************************************************************** ** ** Retrieves the ID with the specified number from the specified set. ** The first ID in set has the number 1. See also SetNextId. ** ** INPUT: address of set object [R] ** ID number within set [R] ** address of output id-object [W] ** IMPLICIT: ** ** RETURNS: 1 ** 0 if the ID number is out of range */ INT4 SetGetID (SETo *set, INT4 n, IDoENTRY *id) { if (n < 1 || n > set->n) return 0; id->id_d = set->id_d; id->siz = set->id_d->siz; memcpy (id->id, set->id_p + --n * id->siz, id->siz); IdSplit (id); return 1; } /**API* SetNextId ************************************************************** ** ** Iterates over all IDs in the set. ** See also SetGetID. ** ** INPUT: address of set [R] ** address of output ID object [W] ** address of iterator (must be set to 0 to start) [W] ** ** RETURNS: the ID object ** NULL: set exhausted */ IDoENTRY *SetNextId (SETo *set, IDoENTRY *id, INT4 *i) { if (*i < set->n) { id->id_d = set->id_d; id->siz = set->id_d->siz; memcpy (id->id, set->id_p + *i * id->siz, id->siz); IdSplit (id); (*i)++; return id; } else { *i = 0; return NULL; } } ENTRYo *SetGetEntry (SETo *set, Int4 i) { IDoENTRY id; ENTRYo *entry; SetGetID (set, i, &id); entry = EntryOpen (&id); return entry; } /**API* SetAddID ************************************************************** ** ** Adds an entry ID to an existing set. ** ** INPUT: address of set object [W] ** address of id-object describing the ID to be added [R] ** IMPLICIT: ** ** RETURNS: 1 ** allocation error: e__allocfail + */ INT4 SetAddID (SETo *set, IDoENTRY *id) { IDoTYPE *id_d; /* ** get the ID-descriptor and copy it to the set if it doesn't have one */ if (set->id_d) id_d = set->id_d; else if (id->id_d) { id_d = id->id_d; set->id_d = id_d; } else return 0; /* ** allocate more space if needed */ if (set->allocN == set->n) if (set->n == 0) _ErrStop (SetAlloc (set, 1, set->id_d)); else { set->allocN = set->allocN * 2; set->id_p = (IDPTR) realloc (set->id_p, (set->allocN) * id_d->siz); } memcpy (set->id_p + (set->n++ * id_d->siz), id->id, id_d->siz); return 1; } /**API* SetGetQueryStr ******************************************************** ** ** Returns the query string that is associated to the specified set. ** ** INPUT: set name [R] ** IMPLICIT: ** ** RETURNS: query string ** NULL if the set could not be found */ char *SetGetQueryStr (char *setName) { SETo *set; char *tmp; if (!(set = SetGet (setName))) return NULL; return _Str(set->queryStr); } /**API* SetGetQuery *********************************************************** ** ** Returns the query string that is associated to the specified set. ** ** INPUT: set name [R] ** IMPLICIT: ** ** RETURNS: query string ** NULL if the set could not be found */ char *SetGetQuery (SETo *set) { return "does not work yet"; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /***** SetOr ***************************************************************** ** ** does logical OR operation between to sets and writes a third set; ** ** INPUT: address of first element of first set [R] ** address of first element of second set [R] ** number of elements in a [R] ** number of elements in b [R] ** location that will receive number of elements in c [W] ** element size in bytes [R] ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: */ static IDPTR SetOr (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *resultN, INT4 idSize) { IDPTR a_p=a, b_p=b, a_low=a, b_low=b; IDPTR a_end=a_p + an * idSize, b_end=b_p + bn * idSize; INT4 len, cmp, k, inc = idSize-1; _SetInitBuff (buff); while (a_p < a_end && b_p < b_end) { for (k = inc; k >= 0; k--) { if ((cmp = a_p[k] - b_p[k]) != 0) break; } if (cmp == 0) { /* equal */ if (b_low != SETxNOCPY) { _SetCopyIds (buff, b_low, b_p, len) b_low = SETxNOCPY; a_low = a_p; } a_p += idSize; b_p += idSize; } else if (cmp < 1) { /* smaller */ if (b_low != SETxNOCPY) { _SetCopyIds (buff, b_low, b_p, len) b_low = SETxNOCPY; a_low = a_p; } a_p += idSize; } else { /* bigger */ if (a_low != SETxNOCPY) { _SetCopyIds (buff, a_low, a_p, len) a_low = SETxNOCPY; b_low = b_p; } b_p += idSize; } } if (a_low != SETxNOCPY) { /* collect the rest */ _SetCopyIds (buff, a_low, a_end, len) if (b_p != b_end) { _SetCopyIds (buff, b_p, b_end, len) } } else { _SetCopyIds (buff, b_low, b_end, len) if (a_p != a_end) { _SetCopyIds (buff, a_p, a_end, len) } } *resultN = BuffGetCurrOffset (buff) / idSize; return (IDPTR) BuffGetPtr (buff); } /****** SetNot **************************************************************** ** ** does logical AND NOT operation between to sets and writes a third set; ** ** INPUT: address of first element of first set [R] ** address of first element of second set [R] ** number of elements in a [R] ** number of elements in b [R] ** location that will receive number of elements in c [W] ** element size in bytes [R] ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: 1 */ static IDPTR SetNot (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *resultN, INT4 idSize) { IDPTR a_p= a, b_p=b, a_low=a, b_low=b; IDPTR a_end=a_p + an * idSize, b_end=b_p + bn * idSize; INT4 len, cmp, k, inc=idSize-1; _SetInitBuff (buff); while (a_p < a_end && b_p < b_end) { for (k = inc; k >= 0; k--) { if ((cmp = a_p[k] - b_p[k]) != 0) break; } if (cmp == 0) { /* equal */ if (a_low != SETxNOCPY) { _SetCopyIds (buff, a_low, a_p, len) a_low = SETxNOCPY; b_low = b_p; } a_p += idSize; b_p += idSize; } else if (cmp < 1) { /* smaller */ if (b_low != SETxNOCPY) { b_low = SETxNOCPY; a_low = a_p; } a_p += idSize; } else { /* bigger */ if (b_low != SETxNOCPY) { b_low = SETxNOCPY; a_low = a_p; } b_p += idSize; } } if (a_low != SETxNOCPY) { /* collect rest */ _SetCopyIds (buff, a_low, a_end, len) } else { _SetCopyIds (buff, a_p, a_end, len) } *resultN = BuffGetCurrOffset (buff) / idSize; return (IDPTR) BuffGetPtr (buff); } /****** SetAnd **************************************************************** ** ** Does logical AND operation between to sets and writes into third set. ** ** INPUT: address of first element of first set [R] ** address of first element of second set [R] ** number of elements in a [R] ** number of elements in b [R] ** location that will receive number of elements in c [W] ** element size in bytes [R] ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: */ static IDPTR SetAnd (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *resultN, INT4 idSize) { IDPTR a_p=a, b_p=b, a_low=a, b_low=b; IDPTR a_end=a_p+an*idSize, b_end=b_p+bn*idSize; INT4 len, cmp, k, inc=idSize-1; _SetInitBuff (buff); while (a_p < a_end && b_p < b_end) { for (k = inc; k >= 0; k--) { if ((cmp = a_p[k] - b_p[k]) != 0) break; } if (cmp == 0) { /* equal */ if (b_low != SETxNOCPY) { b_low = SETxNOCPY; a_low = a_p; } a_p += idSize; b_p += idSize; } else if (cmp < 1) { /* less */ if (a_low != SETxNOCPY) { _SetCopyIds (buff, a_low, a_p, len) a_low = SETxNOCPY; b_low = a_p; } a_p += idSize; } else { /* bigger */ if (a_low != SETxNOCPY) { _SetCopyIds (buff, a_low, a_p, len) a_low = SETxNOCPY; b_low = b_p; } b_p += idSize; } } if (a_low != SETxNOCPY) { /* get rest */ _SetCopyIds (buff, a_low, a_p, len) } *resultN = BuffGetCurrOffset (buff) / idSize; return (IDPTR) BuffGetPtr (buff); } /**api* SetMapIds ************************************************************* ** ** similar to SetAnd but more general -> ** copies all elements from set "a" that have a map-region owned ** by at least one element in set "b"; resultant set "c" will ** therefore contain a subset of set "a" ** though part of ID used for mapping is variable it defaults to 4 bytes ** here -> modify the "cmp =..." line so that the compared values ** are shifted by (4-mlen)*8 bits to the right -> 4 byte would then ** be the largest map-length, ** ** INPUT: address of first element of first set [R] ** address of first element of second set [R] ** number of elements in a [R] ** number of elements in b [R] ** location that will receive number of elements in c [W] ** ID-size in bytes of first set [R] ** ID-size in bytes of second set [R] ** offset of join region in first set's ID [R] ** offset of join region in second set's ID [R] ** length of join region [R] ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: */ IDPTR SetMapIds (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *resultN, INT4 aidSize, INT4 bidSize, INT4 amoff, INT4 bmoff, INT4 mlen) { IDPTR a_p=a, b_p=b; IDPTR a_end=a_p+an*aidSize, b_end=b_p+bn*bidSize; INT4 cmp; _SetInitBuff (buff); while (a_p < a_end && b_p < b_end) { CMP (a_p + amoff, b_p + bmoff, cmp, 4) if (cmp == 0) { /* equal */ _BuffCopyNChars (buff, a_p, aidSize) a_p += aidSize; } else if (cmp < 1) /* less */ a_p += aidSize; else /* bigger */ b_p += bidSize; } *resultN = BuffGetCurrOffset (buff) / aidSize; return (IDPTR) BuffGetPtr (buff); } /**api* SetMapToParent ******************************************************** ** ** Takes a set of subentry IDs, removes the subentry-no and removes ** redundant elements; ** length of PARENT-ID should be variable but is here always 4 byte! ** ** INPUT: address of ID-block [R] ** nr of IDs [R] ** adress of nr of IDs in resultant set [W] ** size of CHILD-ID [R] ** offset of PARENT-ID [R] ** length of PARENT-ID [R] ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: 1 */ IDPTR SetMapToParent (IDPTR a, INT4 a_n, INT4 *resultN, INT4 siz, INT4 off, INT4 len) { UINT4 id_s, id; IDPTR id_p; INT4 k, cmp; _SetInitBuff (buff); id_s = SETxNULL; for (k=0, id_p=a; k < a_n; k++, id_p = id_p + siz) { memcpy (&id, (id_p + off), sizeof (UINT4)); if (k > 0) { CMP ((IDPTR) &id, (IDPTR) &id_s, cmp, 4); } else { cmp = -1; } if (cmp != 0) { id_s = id; _BuffCopyNChars (buff, &id, sizeof (UINT4)) } } *resultN = BuffGetCurrOffset (buff) / sizeof (UINT4); return (IDPTR) BuffGetPtr (buff); } /**api* SetLink *************************************************************** ** ** similar to SetMapIds but more specialized -> ** compares entry-ID with link ID and creates a sorted set of ** linked ID's (the part of the link ID that was not used for ** comparison); ** ** INPUT: address of first element of first set [R] ** address of first element of second set [R] ** address of buffer reserved for third set [W] ** number of elements in a [R] ** number of elements in b [R] ** location that will receive number of elements in c [W] ** 1 or 2 copare ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: 1 */ IDPTR SetLink (IDPTR a, INT4 a_n, IDPTR b, INT4 b_n, INT4 *resultN, INT4 rev_f) { IDPTR aPtr=a, bPtr, aEnd, bEnd; INT4 cmp, shift; _SetInitBuff (buff); bPtr = b + (rev_f ? 4 : 0); aEnd = a + a_n*4; bEnd = b + (b_n * 2)*4; shift = rev_f ? -4 : 4; while (aPtr < aEnd && bPtr < bEnd) { CMP (aPtr, bPtr, cmp, 4); if (cmp == 0) { /* equal */ _BuffCopyNChars (buff, (bPtr + shift), 4) bPtr += 2*4; } else if (cmp < 1) /* less */ aPtr += 4; else /* bigger */ bPtr += 2*4; } *resultN = BuffGetCurrOffset (buff) / 4; SetHeapSort ((IDPTR) BuffGetPtr (buff), *resultN, 4, 0, 4); return (IDPTR) BuffGetPtr (buff); } /**api* SetCutLink ************************************************************ ** ** Cuts either first or second ID from each link ID and writes it ** into result set. Set is always sorted. ** Function assumes that entry ID's within link-ID's are always 4 byte ** long (will have to be changed as soon as subentry-IDs will be involved ** in links!!) ** ** INPUT: address of set with link-IDs [R] ** number of ID's in set [R] ** address of number of IDs in result set [W] ** reverse flag [R] ** IMPLICIT: ** buff (SMoBUFF *) [W] ** ** RETURNS: 1 */ IDPTR SetCutLink (IDPTR a, INT4 a_n, INT4 *resultN, INT4 rev_f) { IDPTR aPtr, aEnd; _SetInitBuff (buff); aPtr = a + (rev_f ? 0 : 4); aEnd = 8 * a_n + a; for (; aPtr < aEnd; aPtr+=8) _BuffCopyNChars (buff, aPtr, 4) *resultN = BuffGetCurrOffset (buff) / 4; return (IDPTR) BuffGetPtr (buff); } /**api* SetRemoveDouble ******************************************************* ** ** removes duplicates from a set of IDs; ** ** INPUT: address of input set [R/W] ** address of output set [W] may be the same as input set ** size of input set [R] ** address to place size of output set [W] ** ID-size [R] ** IMPLICIT: ** ** RETURNS: 1 **/ INT4 SetRemoveDouble (IDPTR idPtr, INT4 idN, INT4 idSize, INT4 *resultN) { IDPTR off, last, out; if (idN == 0) { *resultN = 0; return 0; } off = idPtr + idSize; last = idPtr + idN * idSize; out = idPtr + idSize; for (; off < last; off += idSize) if (memcmp (off, out-idSize, idSize) != 0) { memcpy (out, off, idSize); out += idSize; } *resultN = (out - idPtr) / idSize; return 1; } /**api* SetCountKey ********************************************************** ** ** counts the number of unique keys within ID ...assumes that the set ** is sorted after the key to be counted; ** ** INPUT: address of input set [R] ** size of input set [R] ** size of ID [R] ** size of key [R] ** offset of key within set [R] ** IMPLICIT: ** ** RETURNS: 1 **/ INT4 SetCountKey (IDPTR idPtr, INT4 idN, INT4 idSize, INT4 keyOff, INT4 keySize) { INT4 keyN=0; char *tmp, *tmpSave=NULL; for (tmp = (char*)(idPtr + idSize * (idN-1) + keyOff); tmp >= (char*) idPtr; tmp -= idSize) if (!keyN || memcmp (tmp, tmpSave, keySize) != 0) { keyN++; tmpSave = tmp; } return keyN; } /**api* SetHeapSort *********************************************************** ** ** uses "sort" from Numerical Recipies in C, p 247; ** sorts an array of ID's using a key-number within the ID with specified ** begin and length; ** Note that the base of array is shifted by one element to make the ** first element the element with index=1; ** ** INPUT: base address of array [W] ** number of elements [R] ** size of ID [R] ** offset of sorting key in ID [R] ** length of sorting key [R] ** IMPLICIT: ** ** RETURNS: 1 */ INT4 SetHeapSort (IDPTR ra, INT4 n, INT4 siz, INT4 beg, INT4 len) { INT4 k, l, j, ir, i, cmp; unsigned char rra[SETxXID]; IDPTR a_p, b_p; if (n <= 1) return 0; /* nothing to sort */ ra = ra - siz; /* num recipies start with "1" as first index in array */ l = (n >> 1) + 1; ir = n; for (;;) { if (l > 1) memcpy (rra, ra + --l * siz, siz); else { memcpy (rra, ra + ir * siz, siz); memcpy (ra + ir * siz, ra + 1 * siz, siz); if (--ir == 1) { memcpy (ra + 1 * siz, rra, siz); return 1; } } i = l; j = l << 1; while (j <= ir) { for (k=beg+len-1, a_p = ra + j*siz, b_p = ra + (j+1)*siz; k >= beg; k--) { if ((cmp = a_p[k] - b_p[k]) != 0) break; } if (j < ir && cmp < 0) ++j; for (k=beg+len-1, a_p = rra, b_p = ra + j*siz; k >= beg; k--) { if ((cmp = a_p[k] - b_p[k]) != 0) break; } if (cmp < 0) { memcpy (ra + i*siz, ra+j*siz, siz); j += (i = j); } else j = ir + 1; } memcpy (ra + i * siz, rra, siz); } } ** ** $RCSfile: set.h,v $ ** $Revision: 1.4 $ ** $Date: 1996/08/11 22:47:20 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #define SETxXKEY 80 /* max key size */ #define SETxXNAM 20 /* max size of set name */ #define SETxXCMNT 132 /* max size of set description */ #define SETxXID 12 /* max len of ID */ #define SETxXLIBS 64 /* max no of source libraries of a set */ enum set_op {SETxOR=40, SETxAND, SETxNOT}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description of a set. */ typedef struct SETo { char *list; /* for usage of module "list" only! should be (void *) but the gdb... */ INT4 class_id; /* for "list" module */ char nam[SETxXNAM]; /* (API) name of set */ char cmnt[SETxXCMNT]; /* set description */ struct STRo *queryStr; /* query string used to generate set*/ char time[SETxXNAM]; /* (API) creation time */ INT4 n; /* number of IDs */ struct IDoTYPE *id_d; /* pointer to ID descriptor */ IDPTR id_p; /* array of IDs */ INT4 lib_n; /* no of different source libraries */ char *lib_nm[SETxXLIBS]; /* names of these libraries */ INT4 lib_z[SETxXLIBS]; /* how many IDs of each library? */ INT4 anal_f; /* flag if libraries were counted */ INT4 tmp_f; /* flag if set is for temporary use */ INT4 allocN; /* allocated space for n Ids */ INT4 isDb; /* flag if set represents a databank */ Int4 allocBytesN; /* number of allocated bytes */ } SETo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of exported functions */ /* operations on sets */ SETo *SetNew (char *nam, char *opt); SETo *SetGet (char *nam); INT4 SetDelete (char *nam); INT4 SetSort (SETo *set); INT4 SetClean (); void SetPrintAll (); INT4 SetOp (SETo *a, SETo *b, SETo *c, INT4 op); /* info about set */ INT4 SetSize (char *setName); INT4 SetIsSubEntry (char *setName); INT4 SetGetNextLibStat (char *setName, char **libName, INT4 *context); char *SetGetQueryStr (char *setName); char *SetGetQuery (SETo *set); char *SetGetName (SETo *set); INT4 SetGetSize (SETo *set); struct ENTRYo *SetGetEntry (SETo *set, Int4 i); /* modify set */ void SetSetIdType (SETo *set, struct IDoTYPE *idType); void SetSetEntryN (SETo *set, INT4 n); IDPTR SetGetIdBuff (SETo *set, INT4 n); /* allocation */ INT4 SetAlloc (SETo *set, INT4 n, struct IDoTYPE *idType); INT4 SetRealloc (SETo *set, INT4 n, struct IDoTYPE *idType); INT4 SetMakeOwn (SETo *set, struct IDoTYPE *id_d); /* handling IDs in sets */ INT4 SetGetID (SETo *set, INT4 n, struct IDoENTRY *id); struct IDoENTRY *SetNextId (SETo *set, struct IDoENTRY *id, INT4 *i); INT4 SetAddID (SETo *set, struct IDoENTRY *id); /* others ... */ void SetSetIsDB (SETo *set); INT4 SetIsDB (SETo *set); INT4 SetLibStat (SETo *set); INT4 SetTestName (char *nam); IDPTR SetMapIds (IDPTR a, IDPTR b, INT4 an, INT4 bn, INT4 *cn, INT4 aid_z, INT4 bid_z, INT4 amoff, INT4 bmoff, INT4 mlen); IDPTR SetMapToParent (IDPTR a, INT4 a_n, INT4 *c_n, INT4 siz, INT4 off, INT4 len); IDPTR SetLink (IDPTR a, INT4 a_n, IDPTR b, INT4 b_n, INT4 *resultN,INT4 rev_f); IDPTR SetCutLink (IDPTR a, INT4 a_n, INT4 *resultN, INT4 rev_f); INT4 SetRemoveDouble (IDPTR a, INT4 a_n, INT4 id_z, INT4 *b_n); INT4 SetHeapSort (IDPTR ra, INT4 n, INT4 siz, INT4 beg, INT4 len); INT4 SetCountKey (IDPTR idPtr, INT4 idN, INT4 idSize, INT4 keyOff, INT4 keySize); char sm__ID[] = "$Id: sm.c,v 1.4 1996/08/12 19:03:47 etzold Exp $"; /* ** ** $RCSfile: sm.c,v $ ** $Revision: 1.4 $ ** $Date: 1996/08/12 19:03:47 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** D-69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: file, sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** contains functions for string manipulation ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define DEBUGNOT #include #include #include #include #include #include #include "message.h" #include "sm.h" #include "lst.h" #include "regexp.h" #define _BuffIncWrite(buff,len) (buff)->writePtr += (len) #define _BuffIncRead(buff,len) (buff)->readPtr += (len) void SmMemMove (char *to, char *from, int len); /****** SmCharSet ************************************************************* ** ** decodes strings used to describe character set; ** "A-Da-d" -> "ABCDabcd" ** "\-" -> "-" ** ** INPUT: address of string [W] ** IMPLICIT: ** ** RETURNS: address of expanded charset string ** */ char *SmCharSet (char *s) { char *loc, tmpa[512+1], tmpb[512+1]; INT4 k; for (loc=s; (loc = strchr (loc, '-')) != NULL; loc++) { if (*(loc-1) == '\\') continue; if (loc == s || *(loc+1) == '\0' || *(loc-1) >= *(loc+1)) _ErrExit (e__novalterm); memcpy (tmpa, loc-1, 3); tmpa[3] = '\0'; for (k=1, tmpb[0] = *(loc-1); tmpb[k-1] < *(loc+1); k++) tmpb[k] = tmpb[k-1] + 1; tmpb[k] = '\0'; SmSwapS (s, tmpa, tmpb); } while (SmSwapS (s, "\\-", "-")) ; return s; } /**api* SmFill **************************************************************** ** ** ** writes the specified number specified character into string address ** ** INPUT: address of string [W] ** number of characters to write [R] ** character to write [R] ** ** RETURNS: 1 */ char *SmFill (char *str, INT4 n, char c) { INT4 k; for (k = 0; k < n; str[k++] = c) ; str[k] = '\0'; return str; } /**api* SmLoc ***************************************************************** ** ** return index of string t in string s, -1 if none; ** ** INPUT: address of string1 [R] ** address of string2 that is searched in string1 [R] ** ** RETURNS: index of string2 in string1 ** -1 if not there */ INT4 SmLoc(char *str1, char *str2) { INT4 i, j, k; for (i = 0; str1[i] != '\0'; i++) { for (j = i, k = 0; str2[k] != '\0' && str1[j] == str2[k]; j++, k++) ; if (k > 0 && (str2[k] == '\0' || *str2 == '\0')) return i; } return -1; } /****** SmXLoc **************************************************************** ** ** searches string1 for occ. of string2 starting from first index ** until the second; if found then string2 is replaced by blanks in ** string1; ** ** INPUT: address of string1 ** address of string2 that is searched in string1 ** index where to start (first in string is 1) ** index where to stop (first in string is 1) ** ** RETURNS: index of string2 in string1 ** -1 if not there */ INT4 SmXLoc(char *str1, char *str2, INT4 l, INT4 r) { INT4 i, j, k; for (i = --l; str1[i] != '\0' && i < r; i++) { for (j = i, k = 0; str2[k] != '\0' && str1[j] == str2[k]; j++, k++) ; if (k > 0 && (!str2[k] || !*str2)) { while (j > i) str1[--j] = ' '; return i; } } return -1; } /****** SmMixLoc ************************************************************** ** ** same as SmXLoc but case insensitive; does no blotting out ** ** INPUT: address of string1 ** address of string2 that is searched in string1 ** index where to start (first in string is 1) ** index where to stop (first in string is 1) ** ** RETURNS: index of string2 in string1 ** -1 if not there */ INT4 SmMixLoc(char *str1, char *str2, INT4 l, INT4 r) { INT4 i, j, k; for (i = --l; str1[i] != '\0' && i < r; i++) { for (j = i, k = 0; str2[k] != '\0' && (isalpha (str1[j]) ? toupper (str1[j]) : str1[j]) == (isalpha (str2[k]) ? toupper (str2[k]) : str2[k]); j++, k++) ; if (k > 0 && (str2[k] == '\0' || *str2 == '\0')) return i; } return -1; } /**api* SmStrCmp ************************************************************** ** ** same as strcmp - but case insensitive ** ** ** INPUT: string 1 [R] ** string 2 [R] ** IMPLICIT: ** ** RETURNS: difference of first characters that differ ** 0 if equal ** */ INT4 SmStrCmp (char *a, char *b) { for (; *a && *b; a++, b++) if (tolower (*a) != tolower (*b)) break; return (tolower (*a) - tolower (*b)); } /**api* SmStrCmpLen *********************************************************** ** ** same as SmStrCmp but continues comparison until specified length ** is reached; ** ** INPUT: string 1 [R] ** string 2 [R] ** comparison length [R] ** IMPLICIT: ** ** RETURNS: difference of first characters that differ ** 0 if equal */ INT4 SmStrCmpLen (char *a, char *b, INT4 len) { for (; *a && *b && len; a++, b++, len--) if (tolower (*a) != tolower (*b)) break; return !len ? 0 : (tolower (*a) - tolower (*b)); } /**api* SmRStrCmp ************************************************************* ** ** same as strcmp - but case insensitive (strings are converted to ** uppercase first) ** once above replacement is done then SmRStrCmp may be called SmStrCmp ** ** INPUT: string 1 [R] ** string 2 [R] ** IMPLICIT: ** ** RETURNS: positive no if string 1 is greater (alphab.) ** negative if string 2 is less ** 0 if both strings are equal */ INT4 SmRStrCmp (char *a, char *b) { INT4 cmp; while (1) { if ((cmp = toupper (*a) - toupper (*b)) != 0) return cmp; if (!*a && !*b) return 0; a++, b++; } } /**api* SmRStrCmpLen ********************************************************** ** ** same as SmRStrCmpLen - but a length can be set where string comparison ** should stop; if the two strings are identical until length the ** 0 is returned; ** ** INPUT: string 1 [R] ** string 2 [R] ** length - comparison stops after length is reached [R] ** IMPLICIT: ** ** RETURNS: positive no if string 1 is greater (alphab.) ** negative if string 2 is less ** 0 if both strings are equal */ INT4 SmRStrCmpLen (char *a, char *b, INT4 len) { INT4 cmp; while (len--) { if ((cmp = toupper (*a) - toupper (*b)) != 0) return cmp; if (!*a && !*b) return 0; a++, b++; } return 0; } /****** SmBinLoc ************************************************************** ** ** return index of string t in string s, -1 if none; ** as Smloc except that it searches any bytes (not only ascii) ** ** INPUT: address of string1 ** address of string2 that is searched in string1 ** length of string 1 ** length of string 2 ** ** RETURNS: index of string2 in string1 ** -1 if not there */ INT4 SmBinLoc(char *str1, char *str2, INT4 len1, INT4 len2) { INT4 i, j, k; for (i = 0; i < len1; i++) { for (j = i, k = 0; k < len2 && str1[j] == str2[k]; j++, k++) ; if (k == len2) return i; } return -1; } /*#define _SmUpper(c) (c >= 'a' & c <= 'z') ? (223 & c) : c */ #define _SmUpper(c) charTbl [(int) c] /**api* SmEdit **************************************************************** ** ** mofifies a string: ** SMxTRIM: cuts of leading and trailing " \n\t" ** SMxTRIM2: cuts of leading and trailing " \n\t" ** SMxLEAD: only leader is trimmed ** SMxTRAIL: only trailer is trimmed ** SMxUPCASE: converts to upper case ** SMxLOWCASE: converts to lower case ** SMxDECODE: replaces \n, \b by proper character values ** SMxDETAB: replaces \t by ' ' ** ** modified: 9-OCT-1992 strcmp->strcpy (remc...) ** ** INPUT: address of string [W] ** bit mask containing constants (see above) [R] ** ** RETURNS: address of modified string */ char *SmEdit (char *s, UINT4 bm) { static char charTbl[255]; static INT4 isInit; char remc[10], remc2[10], *remc_p; INT4 code, k, l, slen; if (!isInit) { for (k=0; k < 255; k++) charTbl[k] = toupper (k); isInit = 1; } strcpy (remc, " \n\t\""); strcpy (remc2, " \n\t"); slen = strlen(s); if (bm & SMxTRIM || bm & SMxTRIM2) { remc_p = bm & SMxTRIM ? &(remc[0]) : &(remc2[0]); if (!(bm & SMxTRAIL)) { /* trim beginning */ for (k = 0; s[k] != 0 && (strchr(remc_p, s[k]) != 0); k++) ; if (bm & SMxTRIM2 && s[k] == '\"') /* " */ k++; slen -= k; if (k > 0) memcpy(s, &s[k], slen+1); } if (!(bm & SMxLEAD)) { /* trim end */ for (k = slen - 1; k >= 0 && (strchr(remc_p, s[k]) != 0); k--) ; if (bm & SMxTRIM2 && s[k] == '\"') /* " ..emacs colors */ k--; if (s[++k]) /* modify only if necess..string might be protected */ s[k] = '\0'; slen = k; } } if (bm & SMxDECODE) { for (k = 0, l = 0; k < slen; k++) if (s[k] != '\\') s[l++] = s[k]; else switch (s[++k]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': code = s[k] - '0'; while (isdigit (s[k+1])) { k++; code = code*10 + (s[k] - '0'); } s[l++] = code; break; case 'n': s[l++] = 10; break; case 'a': s[l++] = 7; break; case 't': s[l++] = 9; break; case 'b': s[l++] = 7; break; case 'r': s[l++] = 13; break; case '\"': /* " ...emacs colors */ s[l++] = 34; break; case '\\': s[l++] = 92; break; case '-': s[l++] = '\\'; /* see PrsDecode */ s[l++] = '-'; break; default: s[l++] = s[k]; break; } s[l] = '\0'; } if (bm & SMxUPCASE) for (k = slen-1; k>=0; k--) s[k] = _SmUpper (s[k]); /* s[k] = toupper(s[k]); */ if (bm & SMxLOWCASE) for (k = 0; k < slen; k++) s[k] = tolower(s[k]); if (bm & SMxDETAB) for (k = 0; k < slen; k++) if (s[k] == '\t') s[k] = ' '; return s; } /**api* SmTime **************************************************************** ** ** should become OBSOLETE ** writes current date and time in the input string address in the format: ** " 9-OCT-1989 9:12\0"; ** ** INPUT: time value (seconds) [R] or 0 ** ** RETURNS: pointer to time string */ char *SmTime (unsigned long usertime_val) { time_t time_val = usertime_val; struct tm *t_s; char min[3]; static char timstr[30]; static char *month[12] = {"JAN","FEB","MAR","APR","MAY","JUN","JUL", "AUG","SEP","OCT","NOV","DEC"}; if (time_val == 0) time (&time_val); t_s = localtime (&time_val); sprintf(min, "%2d", t_s->tm_min); /* min may need leading '0' */ if (t_s->tm_min < 10) min[0] = 48; sprintf (timstr, "%2d-%s-19%d %2d:%s", t_s->tm_mday, month[t_s->tm_mon], t_s->tm_year, t_s->tm_hour, min); return &timstr[0]; } /**api* SmSwap **************************************************************** ** ** replaces all occurances of a character in a string by another character ** ** INPUT: address of string [W] ** character to be replaced [R] ** replacement character [R] ** ** returns: 1 */ INT4 SmSwap (char *s, char a, char b) { char *loc; while ((loc = strchr (s, a)) != NULL) *loc = b; return 1; } /**api* SmSwapFirst *********************************************************** ** ** swaps only first occurrence of string; ** ** INPUT: string to be searched and modified [W] ** string to be searched [R] ** replacement string [R] ** ** RETURNS: 1 if swap ** 0 if no swap */ INT4 SmSwapFirst (char *str, char *search, char *replace) { char *tmp, *loc; INT4 sLen, rLen, diff; if (!(loc = strstr (str, search))) return 0; sLen = strlen (search); rLen = strlen (replace); if (sLen > rLen) { /* move chars AFTER searchstring from left to right */ diff = sLen - rLen; for (tmp=loc+sLen; *tmp; tmp++) *(tmp - diff) = *tmp; } else if (sLen < rLen) { /* move chars AFTER searchstring from right */ diff = rLen - sLen; for (tmp=str+strlen(str); tmp >= loc + sLen; tmp--) *(tmp + diff) = *tmp; } memcpy (loc, replace, rLen); return 1; } /****** SmReplace ************************************************************* ** ** ** INPUT: address of string [W] ** pointer inside the buff to the substring to be replaced [W] ** length of string to be replaced [R] ** replacement string [R] ** length of that substring [R] ** IMPLICIT: ** ** RETURNS: ** pointer to the beginning of the replaced string */ char *SmReplace (char *buff, char *target, INT4 targetLen, char *s, INT4 lenS) { char *endPtr; INT4 offset, shift; offset = (Int4)(target - buff) + targetLen; shift = lenS - targetLen; if (shift != 0) { endPtr = buff + offset; SmMemMove (endPtr + shift, endPtr, strlen(buff) - offset + 1); memcpy (endPtr - targetLen, s, lenS); } return endPtr-targetLen; } /**api* SmSwapS *************************************************************** ** ** swap all occurrances of old string against new string; goes from left ** to right; ** ** INPUT: address of input string [W] ** address of old string (to be searched in string) [R] ** address of new string [R] ** ** RETURNS: 1 if swap ** 0 if no swap */ INT4 SmSwapS (char *str, char *a, char *b) { INT4 off=0, strLen, a_z, b_z, swap_f, rv; #ifdef sun char *tmp; #endif swap_f = FALSE; strLen = strlen (str); a_z = strlen (a); b_z = strlen (b); while ((rv = SmLoc (str+off, a)) != -1) { off += rv; swap_f = TRUE; #ifdef sun tmp = (char *) malloc (strLen - a_z - off + 1); memcpy (tmp, &str[off+a_z], strLen - a_z - off + 1); memcpy (&str[off+b_z], tmp, strLen - a_z - off + 1); free (tmp); #else memmove (&str[off+b_z], &str[off+a_z], strLen-a_z-off+1); #endif memcpy (&str[off], b, b_z); strLen += b_z - a_z; /* string size changes */ off += b_z; } return swap_f; } void SmMemMove (char *to, char *from, int len) { #ifdef sun char *tmp; tmp = (char *) malloc (len); memcpy (tmp, from, len); memcpy (to, tmp, len); free (tmp); #else memmove (to, from, len); #endif } /****** SmFLen **************************************************************** ** ** replaces in format-string for printf '#' against width (neg. or pos) ** ** INPUT: address of format-string [W] ** any number of width numbers [R] ** IMPLICIT: ** ** RETURNS: address of modified string */ char *SmFLen (char *s,...) { static char tmps[SMxXTMP]; va_list ap; char tmp[5]; INT4 wid; strcpy (tmps, s); va_start (ap, s); while (strchr (tmps, '#') != NULL) { wid = va_arg (ap, INT4); sprintf (tmp, "%d", wid); SmSwapS (tmps, "#", tmp); } va_end (ap); return tmps; } /**api* SmElement ************************************************************* ** ** extracts string element with specified number bordered by begin, or end ** of string or specified character; first element has number 1; ** ** INPUT: address of input string [R] ** address of output string [W] ** delimiter character [R] ** element number [R] ** option SMxSKIP or SMxNOSKIP [R] ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if specified element not found */ INT4 SmElement (char *a, char *b, char tok, INT4 n, INT4 skip_o) { INT4 k, l, beg, len; for (k=0, l=0; k < n -1; k++) { /* goto element begin */ while (a[l] != tok && a[l] != '\0') l++; if (a[l++] == '\0') return 0; } beg = l; if (skip_o == SMxNOSKIP && beg != 0) beg--; while (a[l] != tok && a[l] != '\0') /* goto element's end */ l++; if (beg == l) return 0; len = l-beg; memcpy (b, &(a[beg]), len); b[len] = '\0'; return 1; } /**api* SmStrTok ************************************************************** ** ** inspired from strtok, ...tok is a separator STRING with one or more ** characters; function returns next substring bordered by tok; the ** context is reset when called with a different string ...or when ** an iteration is complete and there are no more substrings ...this ** means that it must be always iterated until the function returns NULL; ** function put '\0's into the input string; ** ** INPUT: string [W] ** string token [R] ** IMPLICIT: ** ** RETURNS: pointer to next substring ** NULL if there are no more */ char *SmStrTok (char *str, char *tok) { static char *strSave, *strPtr=NULL, *tokPtr, *tmpPtr; if (strSave != str || !strPtr) strSave = str, strPtr = str; if (!*strPtr) { /* at end of string */ strPtr = NULL; return NULL; } if ((tokPtr = strstr (strPtr, tok))) { *tokPtr = '\0'; tmpPtr = strPtr; strPtr = tokPtr + strlen (tok); return tmpPtr; } else { /* no token found */ tmpPtr = strPtr; strPtr = str + strlen (str); return tmpPtr; } } /**api* SmEqs **************************************************************** ** ** compares to strings case insensitive; ** ** INPUT: string a [R] ** string b [R] ** IMPLICIT: ** ** RETURNS: 1 if equal ** 0 if not */ INT4 SmEqs (char *a, char *b) { for (; *a && *b; a++, b++) if (toupper (*a) != toupper (*b)) break; return (!*a && !*b) ? 1 : 0; } static Int4 buffAllocN, buffAllocByte, buffFreedN, buffFreedByte; /**api* BuffNew *************************************************************** ** ** Creates a new buffer object with the specified initial size which ** will double as needed; ** ** INPUT: initial size in bytes [R] ** ** RETURNS: buffer object */ SMoBUFF *BuffNew (INT4 size) { SMoBUFF *buff; if (size < 10) /* minimum size of buffer */ size = 10; if ((buff = (SMoBUFF *) malloc (sizeof (SMoBUFF))) == NULL) _ErrExit2 (e__allocfail, "buff object"); if ((buff->buff = (char *) malloc (size)) == NULL) _ErrExit2 (e__allocfail, "buff string"); buff->writePtr = buff->buff; buff->readPtr = buff->buff; buff->size = size; *buff->buff = '\0'; #ifdef DEBUG buffAllocN++; if (!(buffAllocN%1000)) fprintf (stderr, "BUFFERS: allocN: %d, freedN, %d\n", buffAllocN, buffFreedN); #endif return buff; } /**api* BuffInit ************************************************************** ** ** Creates a new buffer object if the buffer object's address is NULL ** otherwise just resets the buffer. ** ** INPUT: address of buffer object [R] (initially NULL) ** initial size in bytes [R] ** IMPLICIT: ** ** RETURNS: buffer object */ SMoBUFF *BuffInit (SMoBUFF *buff, INT4 size) { if (!buff) buff = BuffNew (size); else BuffReset (buff); return buff; } /**api* BuffReset ************************************************************* ** ** Resets a buffer object, ie, resets the "current" pointer to the buffer ** begin. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: */ void BuffReset (SMoBUFF *buff) { buff->writePtr = buff->buff; buff->readPtr = buff->buff; *buff->buff = '\0'; } /**api* BuffResetRead ********************************************************* ** ** Resets a the read pointer of a buffer object, ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: */ void BuffResetRead (SMoBUFF *buff) { buff->readPtr = buff->buff; } /**api* BuffGetCurrOffset ***************************************************** ** ** Returns the offset of the current pointer from the buffer begin. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: offset */ INT4 BuffGetCurrOffset (SMoBUFF *buff) { return (INT4) (buff->writePtr - buff->buff); } /**api* BuffLength ************************************************************ ** ** Returns the offset of the current pointer from the buffer begin. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: offset */ INT4 BuffLength (SMoBUFF *buff) { return (INT4) (buff->writePtr - buff->buff); } /**api* BuffGetCurrPtr ******************************************************** ** ** Returns the current pointer, pointing to the current location in ** the buffer. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: current pointer */ char *BuffGetCurrPtr (SMoBUFF *buff) { return buff->writePtr; } /**api* BuffGetPtr ************************************************************ ** ** Returns the pointer to the buffer begin - this may change during buffer ** growth. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: current pointer */ char *BuffGetPtr (SMoBUFF *buff) { return buff->buff; } /**api* BuffCopyChar ********************************************************** ** ** Copies a single character to the buffer and advances current pointer. ** Doubles the buffer if the end of buffer is reached. Does NOT put ** a NULL character at the end! ** ** INPUT: address of buffer object [W] ** character value [R] ** IMPLICIT: ** ** RETURNS: */ void BuffCopyChar (SMoBUFF *buff, char c) { if ((INT4) (buff->writePtr - buff->buff) == buff->size) BuffGrow (buff, 1); *(buff->writePtr++) = c; } /**API* BuffCopyNChar ******************************************************* ** ** Copies exactly n characters to the buffer and advances current ** pointer. Doubles the buffer if the end of buffer is reached. ** Does NOT put a NULL character at the end. All the string will be ** copied if the length of s is n or more. ** ** INPUT: address of buffer object [W] ** string to be copied [R] ** IMPLICIT: ** ** RETURNS: */ void BuffCopyNChar (SMoBUFF *buff, char *s, INT4 n) { if(n > 0) { if ((INT4) (buff->writePtr - buff->buff + n) >= buff->size) BuffGrow (buff, n+1); strncpy (buff->writePtr, s, n); buff->writePtr += n; } } /**api* BuffCopyString ******************************************************** ** ** Copies a string to the buffer and advances current pointer. ** Doubles the buffer if the end of buffer is reached. ** ** INPUT: address of buffer object [W] ** string to be copied [R] ** IMPLICIT: ** ** RETURNS: */ void BuffCopyString (SMoBUFF *buff, char *s) { INT4 len; len = strlen (s); if ((INT4) (buff->writePtr - buff->buff + len) >= buff->size) BuffGrow (buff, len+1); strcpy (buff->writePtr, s); buff->writePtr += len; } /**api* BuffCat *************************************************************** ** ** Copies contents of second buffer to first buffer ** (analogous to 'strcat'). If the 'read pointer' is not at the ** buffer begin then that is used as begin of the buffer to ** be copied from. ** ** INPUT: address of buffer [W] ** address of buffer [R] ** IMPLICIT: ** ** RETURNS: */ void BuffCat (SMoBUFF *a, SMoBUFF *b) { INT4 len; len = b->writePtr - b->readPtr; _BuffCopyNChars (a, b->readPtr, len); *(a->writePtr) = '\0'; /* add NULL terminator */ } /**api* BuffPrintF ************************************************************ ** ** Copies a string to the buffer that is previously formatted (in a ** printf fashion. ** Doubles the buffer if the end of buffer is reached. ** ** INPUT: address of buffer object [W] ** string to be copied [R] ** IMPLICIT: ** ** RETURNS: */ void BuffPrintF (SMoBUFF *buff, char *formatStr, ...) { va_list ap; char s[2000]; va_start (ap, formatStr); vsprintf (s, formatStr, ap); va_end (ap); BuffCopyString (buff, s); } /**api* BuffVPrintF *********************************************************** ** ** Copies a string to the buffer that is previously formatted (in a ** printf fashion. ** Doubles the buffer if the end of buffer is reached. ** ** INPUT: address of buffer object [W] ** string to be copied [R] ** IMPLICIT: ** ** RETURNS: */ void BuffVPrintF (SMoBUFF *buff, char *formatStr, va_list ap) { char s[50000]; vsprintf (s, formatStr, ap); BuffCopyString (buff, s); } /****** BuffGrow ************************************************************** ** ** 'Grows' the buffer to double size or if this is not sufficient, ** by the specified size. ** ** INPUT: address of buffer object [W] ** minimum size by which to grow [W] ** IMPLICIT: ** ** RETURNS: */ void BuffGrow (SMoBUFF *buff, INT4 size) { INT4 offset1, offset2; if (buff->size < size) /* check if doubling is not enough */ buff->size += size; else buff->size = buff->size * 2; offset1 = (INT4) (buff->writePtr - buff->buff); offset2 = (INT4) (buff->readPtr - buff->buff); if ((buff->buff = (char *) realloc (buff->buff, buff->size)) == NULL) _ErrExit2 (e__allocfail, "buff string"); buff->writePtr = buff->buff + offset1; buff->readPtr = buff->buff + offset2; } /**api* BuffShiftCurrPtr ****************************************************** ** ** Shifts the current pointer by requested amont back (negative) or ** forward. ** ** INPUT: address of buffer object [W] ** IMPLICIT: ** ** RETURNS: */ void BuffShiftCurrPtr (SMoBUFF *buff, INT4 n) { buff->writePtr += n; /* should do some checking */ } /**api* BuffFill ************************************************************** ** ** Writes the specified number of times specified character into buffer. ** ** INPUT: address of buffer object [W] ** number of characters to write [R] ** character to write [R] ** ** RETURNS: 1 */ void BuffFill (SMoBUFF *buff, INT4 n, char c) { INT4 k; for (k=0; k < n; k++) { if ((INT4) (buff->writePtr - buff->buff + 1) >= buff->size) /* the 1 for the NULL char */ BuffGrow (buff, 1); *(buff->writePtr++) = c; } *(buff->writePtr) = '\0'; /* add NULL terminator - safer! */ } /**api* BuffTrim ************************************************************** ** ** Trims the buffer from begin and/or end ** ** INPUT: address of buffer object [W] ** option: "lf" trims line feed from end ** option: "continue" trims line feed from end ** ** RETURNS: 1 */ void BuffTrim (SMoBUFF *buff, char *option) { char *tmp; switch (tolower (option[0])) { case 'l': /* lf */ tmp = buff->writePtr; while (*(--tmp) == '\n') { *tmp = '\0'; buff->writePtr = tmp; } break; case 'c': /* continue */ tmp = buff->writePtr - 2; if (*tmp == '\\') { *tmp = '\0'; buff->writePtr -= 2; } break; default: _ErrExit2 (e__unknownoption, option); } } /**api* BuffToUpper *********************************************************** ** ** ** INPUT: address of buffer object [W] ** ** RETURNS: address of string */ char *BuffToUpper (SMoBUFF *buff) { SmEdit (buff->buff, SMxUPCASE); return buff->buff; } /**api* BuffToLower *********************************************************** ** ** ** INPUT: address of buffer object [W] ** ** RETURNS: address of string */ char *BuffToLower (SMoBUFF *buff) { SmEdit (buff->buff, SMxLOWCASE); return buff->buff; } /**api* BuffSearchSensitive ********************************************* ** ** Searches a string and returns pointer to string if found. ** Search is case sensitive. ** ** INPUT: buffer object [R] ** address of string [R] ** ** RETURNS: pointer to location if found ** NULL if not */ char *BuffSearchSensitive (SMoBUFF *buff, char *s) { BuffCopyChar (buff, '\0'); /* make sure there is a NULL terminator */ BuffShiftCurrPtr (buff, -1); return strstr (buff->buff, s); } /**api* BuffSearch ************************************************************ ** ** Searches a string and returns pointer to string if found. ** Search is case insensitive. ** ** INPUT: buffer object [R] ** address of string [R] ** ** RETURNS: pointer to location if found ** NULL if not */ char *BuffSearch (SMoBUFF *buff, char *s) { char *buf; INT4 len = strlen(s); BuffCopyChar (buff, '\0'); /* make sure there is a NULL terminator */ BuffShiftCurrPtr (buff, -1); for (buf = buff->buff; *buf; buf++) if (!SmStrCmpLen(buf, s, len)) { return buf; } return NULL; } /**api* BuffDuplicate **************************************************** ** ** Creates a new buffer object with the necessary initial size ** and copies the existing buffer to it. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: buffer object */ SMoBUFF *BuffDuplicate(SMoBUFF *oldBuff) { SMoBUFF *buff; INT4 size; size = strlen(oldBuff->buff) + 1; if ((buff = (SMoBUFF *) malloc (sizeof (SMoBUFF))) == NULL) _ErrExit2 (e__allocfail, "buff object"); if ((buff->buff = (char *) malloc (size)) == NULL) _ErrExit2 (e__allocfail, "buff string"); strcpy(buff->buff, oldBuff->buff); /* copy content of buffer */ buff->writePtr = buff->buff+size-1; buff->size = size; return buff; } /**api* BuffIsEmpty ***************************************************** ** ** Returns TRUE if buffer object is empty, FALSE otherwise ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: 1 if buffer object empty ** 0 otherwise */ INT4 BuffIsEmpty(SMoBUFF *buff) { if (buff->writePtr == buff->buff) return 1; else return 0; } /**api* BuffDelete ******************************************************* ** ** Deletes a buffer object and frees the allocated memory. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: nothing */ void BuffDelete(SMoBUFF **buff) { #ifdef DEBUG buffFreedN++; #endif free((*buff)->buff); free(*buff); *buff = NULL; } /**api* BuffPrint ******************************************************* ** ** Prints the string contained in a buffer object. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: nothing */ void BuffPrint (FILE *file, SMoBUFF *buff) { if (file) fprintf (file, "%s", buff->buff); else printf ("%s", buff->buff); } /**api* BuffReadFile ********************************************************** ** ** Prints the string contained in a buffer object. ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: nothing */ void BuffReadFile (SMoBUFF *buff, FILE *file, INT4 size) { _BuffReserve (buff, size); fread (buff->writePtr, 1, size, file); _BuffIncWrite (buff, size); } /**api* BuffReadLine ********************************************************** ** ** Reads a line from file into the buffer; ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: nothing */ int BuffReadLine (SMoBUFF *buff, FILE *file, int maxLen) { char *tmp; int len; _BuffReserve (buff, maxLen); if (!(tmp = fgets (buff->writePtr, maxLen, file))) return 0; else { len = strlen (tmp); _BuffIncWrite (buff, len); return 1; } } /**api* BuffCollapse ********************************************************** ** ** Replaces a stretch of whitespace chars by single blankl ** ** INPUT: address of buffer object [R] ** IMPLICIT: ** ** RETURNS: pointer to string */ char *BuffCollapse (SMoBUFF *buff) { char *w, *r; *buff->writePtr = '\0'; for (w=r=buff->buff; *r != '\0'; r++) { if (*r == ' ') { *w++ = ' '; while (*r == ' ') r++; r--; } else *w++ = *r; } *w = *r; buff->writePtr = buff->buff + strlen (buff->buff); return buff->buff; } /**api* BuffFormat *********************************************************** ** ** Returns the formatted string; string returned 'owned' by the function ** so make sure you do something with it before calling the function ** again. ** ** INPUT: address of buffer object [W] ** maximum length of the output line [R] ** identation of first line [R] or 0 ** identation of all/following line [R] ** text to be printed in front of each line [R] or NULL ** IMPLICIT: ** ** RETURNS: current pointer */ char *BuffFormat (SMoBUFF *buff, INT4 lineSize, INT4 firstIdent, INT4 allIdent, char *leftText) { static SMoBUFF *tmp=NULL; char *p, *pSave; INT4 k, lineLen; if (leftText) allIdent = strlen (leftText); if (!tmp) tmp = BuffNew (lineSize); else BuffReset (tmp); /* text or ident to the left of first line */ if (leftText) BuffCopyString (tmp, leftText); else if (firstIdent) BuffFill (tmp, firstIdent, ' '); lineLen = BuffGetCurrOffset(tmp); p = buff->buff; k = lineLen + (buff->writePtr - p); while (k >= lineSize) { pSave = p; p += lineSize - lineLen; while (*p != ' ' && p > pSave) /* find the next ' ' backwards */ p--; if (p == pSave) /* if no space was found break at line end */ p += lineSize - lineLen; *(p++) = '\0'; BuffCopyString (tmp, pSave); BuffCopyChar (tmp, '\n'); /* text or ident to the left of following lines */ if (leftText) BuffCopyString (tmp, leftText); else BuffFill (tmp, allIdent, ' '); lineLen = allIdent; k = lineLen + (buff->writePtr - p); } BuffCopyString (tmp, p); return tmp->buff; } char *SmScanNumber (char *s, INT4 *num) { *num = 0; while (isdigit (*s)) *num = *num * 10 + (*s++ - '0'); return s; /* points to first character after number */ } char *BuffExpandTemplate (char *template) { static char newTemplate[100]; char *tmp; INT4 k, l; for (k=0, tmp=template; *tmp;) { if (!isdigit (*tmp)) newTemplate[k++] = *tmp++; else { if (strchr ("aA", *(tmp-1)) == NULL) { tmp = SmScanNumber (tmp, &l); while (--l) { newTemplate[k] = newTemplate[k-1]; k++; } } else while (isdigit (*tmp)) newTemplate[k++] = *tmp++; } } newTemplate[k] = '\0'; return newTemplate; } #define BYTE1 0xFFUL #define BYTE2 0xFF00UL #define BYTE3 0xFF0000UL #define BYTE4 0xFF000000UL /**api* BuffPack ************************************************************** ** ** Returns the formatted string; string returned 'owned' by the function ** so make sure you do something with it before calling the function ** again. ** ** INPUT: address of buffer object [W] ** maximum length of the output line [R] ** identation of first line [R] or 0 ** identation of all/following line [R] ** text to be printed in front of each line [R] or NULL ** IMPLICIT: ** ** RETURNS: current pointer */ void BuffPack (SMoBUFF *buff, char *template, ...) { va_list ap; char *s, *tmp; INT4 n, len; va_start (ap, template); for (tmp=template; *tmp; tmp++) { switch (*tmp) { case 'a': /* ASCII string */ s = va_arg (ap, char *); if (isdigit (tmp[1])) tmp = SmScanNumber (tmp+1, &len) - 1; else len = strlen (s) + 1; _BuffReserve (buff, len); strncpy (buff->writePtr, s, len); _BuffIncWrite (buff, len); break; case 'i': /* signed integer */ n = va_arg (ap, INT4); _BuffReserve (buff, 4); buff->writePtr[0] = n & BYTE1; buff->writePtr[1] = (n & BYTE2) >> 8; buff->writePtr[2] = (n & BYTE3) >> 16; buff->writePtr[3] = (n & BYTE4) >> 24; _BuffIncWrite (buff, 4); break; default: /* digit ...or whitespace */ if (isdigit (*tmp)) { int diff; diff = tmp - template; tmp = BuffExpandTemplate (template); tmp += diff -1; } } } va_end (ap); } /**api* BuffUnPack ************************************************************ ** ** Unpacks items from buffer, a number after the item means ** repetition, except after 'a' or 'z' where it means length. ** ** a: copy of ASCII string ** z: pointer to ASCII string ** i: 4 byte signed integer ** ** INPUT: address of buffer object [W] ** template string [R] ** list of pointers to receive unpacked values ** IMPLICIT: ** ** RETURNS: 1 if successful ** 0 if not all items could be read */ INT4 BuffUnpack (SMoBUFF *buff, char *template, ...) { va_list ap; char *s, **sPtr, *tmp; INT4 *n, len; va_start (ap, template); for (tmp=template; *tmp; tmp++) { if (buff->readPtr >= buff->writePtr) return 0; switch (*tmp) { case 'a': /* ASCII string */ s = va_arg (ap, char *); if (isdigit (tmp[1])) { tmp = SmScanNumber (tmp+1, &len) - 1; strncpy (s, buff->readPtr, len); s[len] = '\0'; } else { strcpy (s, buff->readPtr); len = strlen (s) + 1; } _BuffIncRead (buff, len); break; case 'z': /* pointer to ASCII string */ sPtr = va_arg (ap, char **); *sPtr = buff->readPtr; if (isdigit (tmp[1])) tmp = SmScanNumber (tmp+1, &len) - 1; else len = strlen (*sPtr) + 1; _BuffIncRead (buff, len); break; case 'i': /* signed integer */ n = va_arg (ap, INT4 *); *n = ((UINT4) ((unsigned char) buff->readPtr[0])) + ((UINT4) ((unsigned char) buff->readPtr[1]) << 8) + ((UINT4) ((unsigned char) buff->readPtr[2]) << 16) + ((UINT4) ((unsigned char) buff->readPtr[3]) << 24); _BuffIncRead (buff, 4); break; default: /* digit ...or whitespace */ if (isdigit (*tmp)) { int diff; diff = tmp - template; tmp = BuffExpandTemplate (template); tmp += diff -1; } } } va_end (ap); return 1; } static regexp *regCurr=NULL; /****** BuffMatch ************************************************************* ** ** Matches a string against a regular expression. ** Use RegGetField to extract fields denoted by parentheses or the ** entire match. ** ** INPUT: buffer object to be searched [R] ** string with regular expression [R] ** IMPLICIT: ** ** RETURNS: 1 if string matches ** 0 if not */ int BuffMatch (SMoBUFF *buff, char *reStr) { static int classId = 0; static struct SMoRE { char *list; /* for usage of module "list" only! */ INT4 class_id; /* for "list" module */ char nam[100]; regexp *re; } *re=NULL; if (!classId) LstManageClass (&classId, sizeof (struct SMoRE), NULL, NULL, NULL); if (!LstHashSearch ((void **) &re, reStr)) { LstNewNamed ((void **) &re, classId, reStr); re->re = RegComp (reStr); } regCurr = re->re; return RegExec (re->re, buff->buff) ? 1 : 0; } /****** RegGetMatch *********************************************************** ** ** Extracts entire match (field number 0) or subfield from previous ** regular expression match by RegMatch. ** ** INPUT: number of match to be returned [R] ** IMPLICIT: ** regCurr (regexp *) ** ** RETURNS: string ** NULL if invalid number specified */ char *BuffGetMatch (int n) { static SMoBUFF *b[10]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; static INT4 cnt=0; SMoBUFF *buff=b[cnt++%10]; char *endp, *startp; int len; if (!buff) buff = BuffNew(100); else BuffReset (buff); if (n >= 0 && n <= 9 && regCurr) { startp = regCurr->startp[n]; endp = regCurr->endp[n]; len = endp - startp; _BuffCopyNChars (buff, startp, len); BuffCopyChar (buff, '\0'); return buff->buff; } return NULL; } /****** BuffSubstMatch ************************************************************** ** ** Replaces match by previous regular expression with specified number ** by specified string. ** ** INPUT: address of buffer object [W] ** number of match to be replaced [R] ** replacement string [R] ** IMPLICIT: ** regCurr (regexp *) ** ** RETURNS: */ char *BuffSubstMatch (SMoBUFF *buff, int n, char *s) { char *endp, *startp; int lenMatch, lenS, shift; if (n >= 0 && n <= 9 && regCurr) { startp = regCurr->startp[n]; endp = regCurr->endp[n]; lenMatch = endp - startp; lenS = strlen (s); shift = lenS - lenMatch; if (shift > 0) _BuffReserve (buff, shift); if (shift != 0) SmMemMove (endp+shift, endp, buff->writePtr - endp+1); memcpy (startp, s, lenS); } _BuffIncWrite (buff, shift); return buff->buff; } /****** BuffReplace *********************************************************** ** ** ** INPUT: address of buffer object [W] ** pointer inside the buff to the substring to be replaced [W] ** length of string to be replaced [R] ** replacement string [R] ** length of that substring [R] ** IMPLICIT: ** ** RETURNS: ** pointer to the beginning of the target into the buffer */ char *BuffReplace (SMoBUFF *buff, char *target, INT4 targetLen, char *s, INT4 lenS) { char *endPtr; INT4 offset, shift; offset = (INT4)(target - buff->buff) + targetLen; shift = lenS - targetLen; if (shift > 0) _BuffReserve (buff, shift); if (shift != 0) { endPtr = buff->buff + offset; SmMemMove (endPtr + shift, endPtr, buff->writePtr - endPtr + 1); memcpy (endPtr - targetLen, s, lenS); } _BuffIncWrite (buff, shift); return endPtr-targetLen; } #ifdef MAIN INT4 SDL_fnct(){} main() { SMoBUFF *test; char *ptr; test = BuffInit(NULL, 1000); BuffCopyString(test, "1234567890abcdefghi"); ptr = BuffGetPtr(test) + 5; ptr = BuffReplace(test, ptr, 3, "XXXXX", 5); printf("%s %s\n", BuffGetPtr(test), ptr); ptr = BuffReplace(test, BuffGetPtr(test), 5, "YYxxx", 2); printf("%s %s\n", BuffGetPtr(test), ptr); } #endif /**api* SmIsSeparator ******************************************************* ** ** Determines whether the input contains trivial character or not ** ** INPUT: address of input string ** separator character ** ** RETURNS: true if all the chars of input string are same ** false otherwise */ INT4 SmIsSeperator(char *s, char c) { while(*s) if( *s++ != c) return -1; return 1; } ** ** $RCSfile: sm.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:22 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** */ #include #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef MAX #define MAX(a,b) ((a)<(b) ? (b) : (a)) #endif #ifndef MIN #define MIN(a,b) ((a)<(b) ? (a) : (b)) #endif #define SMxXTMP 512 #define SMxXITEML 80 #define SMxSKIP 0 #define SMxNOSKIP 1 #define SMxMIXCASE 0 #define SMxTRIM 1 #define SMxUPCASE 2 #define SMxLOWCASE 4 #define SMxDECODE 8 #define SMxDETAB 16 #define SMxLEAD 32 #define SMxTRAIL 64 #define SMxTRIM2 128 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** buffer object; */ typedef struct SMoBUFF { char *buff; char *writePtr; char *readPtr; INT4 size; } SMoBUFF, *SMpBUFF; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of functions to be exported */ char *SmFLen (char *s,...); char *SmFill (char *str, INT4 n, char c); char *SmEdit (char *s, UINT4 bm); char *SmTime (unsigned long time_val); INT4 SmSwap (char *s, char a, char b); INT4 SmSwapS (char *s, char *a, char *b); INT4 SmElement (char *a, char *b, char tok, INT4 n, INT4 skip_o); char *SmCharSet (char *s); char *SmStrTok (char *str, char *tok); INT4 SmSwapFirst (char *str, char *search, char *replace); /* string comparison */ INT4 SmEqs (char *a, char *b); INT4 SmMixLoc(char *str1, char *str2, INT4 l, INT4 r); INT4 SmXLoc(char *str1, char *str2, INT4 l, INT4 r); INT4 SmLoc(char *str1, char *str2); INT4 SmStrCmp (char *a, char *b); INT4 SmStrCmpLen (char *a, char *b, INT4 len); INT4 SmRStrCmp (char *a, char *b); INT4 SmRStrCmpLen (char *a, char *b, INT4 len); INT4 SmBinLoc(char *str1, char *str2, INT4 len1, INT4 len2); /* buffer Management */ struct SMoBUFF *BuffNew (INT4 initSize); void BuffReset (struct SMoBUFF *buff); struct SMoBUFF *BuffInit (struct SMoBUFF *buff, INT4 initSize); void BuffResetRead (SMoBUFF *buff); void BuffGrow (SMoBUFF *buff, INT4 size); INT4 BuffLength (struct SMoBUFF *buff); INT4 BuffGetCurrOffset (struct SMoBUFF *buff); char *BuffGetCurrPtr (struct SMoBUFF *buff); char *BuffGetPtr (struct SMoBUFF *buff); void BuffCopyChar (struct SMoBUFF *buff, char c); void BuffCopyString (struct SMoBUFF *buff, char *s); void BuffPrintF (SMoBUFF *buff, char *formatStr, ...); void BuffVPrintF (SMoBUFF *buff, char *formatStr, va_list ap); void BuffShiftCurrPtr (SMoBUFF *buff, INT4 n); void BuffFill (SMoBUFF *buff, INT4 n, char c); /* buffer editing */ void BuffCat (SMoBUFF *a, SMoBUFF *b); void BuffTrim (SMoBUFF *buff, char *option); char *BuffToUpper (SMoBUFF *buff); char *BuffToLower (SMoBUFF *buff); char *BuffSearchSensitive (SMoBUFF *buff, char *s); char *BuffSearch (SMoBUFF *buff, char *s); SMoBUFF *BuffDuplicate(SMoBUFF *oldBuff); INT4 BuffIsEmpty(SMoBUFF *buff); void BuffDelete(SMoBUFF **buff); void BuffPrint (FILE *file, SMoBUFF *buff); void BuffReadFile (SMoBUFF *buff, FILE *file, int size); int BuffReadLine (SMoBUFF *buff, FILE *file, int maxLen); char *BuffCollapse (SMoBUFF *buff); char *BuffReplace (SMoBUFF *buff, char *target, INT4 targetLen, char *s, INT4 lenS); char *BuffFormat (SMoBUFF *buff, INT4 lineSize, INT4 firstIdent, INT4 allIdent, char *leftText); void BuffPack (SMoBUFF *buff, char *template, ...); INT4 BuffUnpack (SMoBUFF *buff, char *template, ...); /* regular expressions */ int BuffMatch (SMoBUFF *buff, char *reStr); char *BuffGetMatch (int n); char *BuffSubstMatch (SMoBUFF *buff, int n, char *s); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** BuffCopyNChar as macro */ #define _BuffCopyNChars(b, s, len) \ {\ if ((INT4) ((b)->writePtr - (b)->buff + (len)) >= (b)->size) \ BuffGrow ((b), (len));\ memcpy ((b)->writePtr, (s), (len));\ (b)->writePtr += (len);\ } #define _BuffReserve(buffer,len) \ if ((INT4) ((buffer)->writePtr - (buffer)->buff + (len)) >= (buffer)->size) \ BuffGrow ((buffer), len+1) ** ** $RCSfile: srs.h,v $ ** $Revision: 1.4 $ ** $Date: 1996/08/11 22:47:21 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** This file must be included by applications that bind to the SRS library ** */ #include "def.h" #include "message.h" #include "futil.h" #include "sm.h" #include "strv.h" #include "idx.h" #include "seq.h" #include "par.h" #include "variable.h" #include "arglist.h" #include "id.h" #include "set.h" #include "entry.h" #include "library.h" #include "seqlib.h" #include "query.h" #include "queryass.h" #include "templ.h" #include "link.h" #include "toklist.h" #include "cursor.h" #include "icarus.h" #include "icabnf.h" #include "view.h" # define _CONSTANTS # define _SRS # define _SLB # define _SYNTAX #ifndef DECLARE_ONLY # define _FUNCTION # define QUERY_M # define XQUERY_M # define SEQLIB_M #endif #include "srs5.h" #ifndef DECLARE_ONLY # ifndef NO_ENVIRONMENT # ifndef VMS # include "srsenv.h" # endif # endif #endif ************************* ** ** $RCSfile: srs5.h,v $ ** $Revision: 1.10 $ ** $Date: 1996/08/11 22:47:22 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** from ODD file: "srsica:srs.i" ** date of ODD compilation: 7-AUG-1996 22:36 ** */ #define O_SRSDB 12 #if defined(_SRS) && !defined(_ICAoSYNTAX) #define _ICAoSYNTAX typedef struct ICAoSYNTAX { char *name; /* Name of the syntax. */ char *fileName; /* Name of the Icarus file with the production list. */ char *rules; /* Pointer to the production list. */ struct SMoBUFF_ *buff; /* Name of the file with ICA rules */ struct ICAoSYNTAX *commandSyntax; /* The syntax of for the commands */ struct ICAoNAMELIST *prodList; /* List of productions */ struct ICAoCOMMAND *userCommand; struct taskList *taskList; char *ign; /* String containing characters to be ignored or skipped during parsing (white space). */ char *lf; /* A regular expression to skip comments. */ unsigned char linkFlag; struct VARo *prod; struct VARoSCOPE *scope; struct regexp *cmntRe; char *ignAlt; } ICAoSYNTAX; #endif #ifndef _PARo #define _PARo typedef struct PARo { char *intern; /* for internal use for the list manager */ INT4 classId; /* for internal use for the list manager */ char *name; /* name of associated global parameter */ char *str; /* Value of 'string' parameter. */ INT4 num; /* Value of 'number' parameter. */ float real; /* Value of 'real' parameter. */ INT4 (*function) (); /* Value of 'function' parameter. */ void *object; /* Value of 'object' parameter. */ unsigned char isVolatile; unsigned char type; /* Parameter type. */ char *comment; /* Short description of parameter. */ char *helpTopic; /* help topic associated to parameter */ char *key; /* keystroke associated to parameter or value */ struct PARoTYPE *parType; /* Object 'partype' for validating the parameter value. */ struct PARoTYPE *check; /* Object 'partype' for validating the parameter value. */ INT4 isLocked; /* internal use... */ char *set; /* Icarus command to set the current value. */ char *get; /* Icarus command to get the current value. */ } PARo; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Describes further a parameter type by specifying constraints or a function for checking the parameter value. */ #ifndef _PARoTYPE #define _PARoTYPE typedef struct PARoTYPE { char *intern; /* for internal use for the list manager */ INT4 classId; /* for internal use for the list manager */ char *name; /* Name of associated global parameter. */ INT4 (*check) (); /* Function that checks parameter value. */ INT4 max; /* Max value, or max length. */ INT4 min; /* Mmin value, or min length. */ float maxReal; /* Max real value. */ float minReal; /* Min real value. */ char *charSet; /* Permissible set of chars for parameter value string. */ } PARoTYPE; #endif #ifndef _PARoLIST #define _PARoLIST typedef struct PARoLIST { struct PARo *par; /* List of all predefined parameters. */ INT4 parN; /* Number of predefined parameters. */ struct PARoTYPE *parType; /* List of all predefined parameter types. */ INT4 parTypeN; /* Number of predefined parameter types. */ } PARoLIST; #endif #ifndef _arg_t #define _arg_t typedef struct arg_t { char *name; INT4 type; char *parameter; char *comment; INT4 (*check) (); INT4 defaultNum; char *defaultStr; float defaultReal; } arg_t; #endif #ifndef _ARGoLIST #define _ARGoLIST typedef struct ARGoLIST { char *name; char *usage; struct arg_t *arg; INT4 argN; } ARGoLIST; #endif #if defined(_SRS) && !defined(_SLBoFIL) #define _SLBoFIL typedef struct SLBoFIL { char *nam; /* File name without extension and directory name. */ char *lnam; /* Logical name (meaningful only for GCG programs)/ */ INT4 isBad; /* This flag will be set upon failure to open this file */ } SLBoFIL; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Top level object of the databank (library) description. */ #if defined(_SRS) && !defined(_SLBo) #define _SLBo typedef struct SLBo { char *nam; /*API Name of library. */ char *shortName; /*API Short name for library - needed for DOS file names. */ char *lnam[3]; /* Logical name(s) for the library (GCG). */ struct SRSoGROUP *group; /* Library group this library belongs to. */ struct SLBoFORM *form; /* Pointer to the format description. */ char *dirName[3]; /* Address of Name of directory with all flat files. */ char *cmnt; /* One line comment on library. */ char *ifiles; /* Name of the Icarus file(s) with the databank description. */ char *help; unsigned char on_f; INT4 idNum; INT4 *on_fp; INT4 maxNameLen; /* max length of unique entry name - important for ID-index */ INT4 maxIndexSizeKb; INT4 extend; INT4 csiz; struct SLBoFIL *fil; /* list of pointers to file descriptions */ INT4 nfil; /* number of file descriptions */ unsigned char skey; char *key; unsigned char isFromUser; unsigned char dataType; char *indexDirName; /* Address of the name of the directory with the SRS indices. */ INT4 pargroup; unsigned char upd_f; unsigned char updlink_f; unsigned char isActive; /* Flag if library is active. */ unsigned char isInit; /* Flag if library is initiated. */ struct FILo *file[4]; INT4 allEntryCnt; INT4 newEntryCnt; INT4 updEntryCnt; char *entryNam; struct IDoENTRY *idCurr; struct TOKoLIST *tokList; struct ICAoJOB *job; } SLBo; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Associates a number between 1 and 255 (library-ID) and a library (databank). */ #if defined(_SRS) && !defined(_LIBoID) #define _LIBoID typedef struct LIBoID { struct SLBo *library; /* Library object. */ INT4 n; /* Library-ID to be associated to the library */ } LIBoID; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** List of active libraries together with their directory names. A particular environment can be selected by defining the parameter 'environment' */ #if defined(_SRS) && !defined(_LIBoENV) #define _LIBoENV typedef struct LIBoENV { char *name; /* Name of the environment. */ struct LIBoLIBENV *libenv; /* List of active libraries. */ INT4 libenvN; /* Number of libraries in that list. */ } LIBoENV; #endif #if defined(_SRS) && !defined(_LIBoLIBENV) #define _LIBoLIBENV typedef struct LIBoLIBENV { struct SLBo *lib; /* Library object. */ char *dirName[3]; /* List of directory names with the library's flat files. The files will be searched in the directories in the same order as of the list. */ char *indexDirName; /* Name of the directory with the SRS indices. */ } LIBoLIBENV; #endif #if defined(_SRS) && !defined(_SRSoDB) #define _SRSoDB typedef struct SRSoDB { struct LIBoID *libId; INT4 libIdN; struct LIBoENV *environment; /* List of defined library environments. */ INT4 environmentN; /* Number of defined library environments. */ struct SLBo *slb; INT4 nslb; struct SRSoGROUP *group; INT4 ngroup; struct SRSoFLD *fld; INT4 nfld; struct IDoTYPE *iddsc; INT4 niddsc; struct SRSoFILTYP *filtyp; INT4 nfiltyp; struct LINKo *lnk; INT4 nlnk; struct ICAoSYNTAX *syntax; INT4 syntaxN; struct ARGoLIST *command; INT4 commandN; struct PARoLIST *parTable; /* table of predefined global parameters */ struct LIBoHREF *href; INT4 hrefN; INT4 xcopy_n; INT4 xlist_n; INT4 copy_fst; INT4 list_fst; struct SLBo **libTable; } SRSoDB; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description of a library (databank) group. */ #if defined(_SRS) && !defined(_SRSoGROUP) #define _SRSoGROUP typedef struct SRSoGROUP { char *key; char *com; /*API Name of library group. */ char *short_nm; /*API Short name (abbreviation) of library group. */ char *cmnt; /* A single line of text describing the group. */ char *help; unsigned char single_f; /* This flag determines if all libraries in the group can be searched simultaneously or one at a time (this is advisable if the libraries differ greatly in their data-fields. */ struct SLBo *library[25]; /* Pointers to the libraries in the group */ INT4 libraryN; struct SLBoFIELD *field[500]; INT4 fieldN; char *fieldCount; unsigned char upd_f; } SRSoGROUP; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description of a data-field within a library. */ #ifndef _SLBoFIELD #define _SLBoFIELD typedef struct SLBoFIELD { unsigned char index; /* Index type - 'show' means that the field can be displayed only; 'group' points to a group of indices. */ char *name; char *code; /* Code of the token in the 'fields' token list that contains the data-field. */ INT4 fieldTokCode; char *token; /* If the data-field is not contained in the 'fields' token list the full name 'tokenList|code' must be specified here. */ struct IDoTYPE *indexId; /* The ID-type description for the IDs that will be put into the index. */ char *indexToken[5]; /* The name of the token list that supplies the values for indexing. The list name may be followed by a token code separated by ':'. */ INT4 indexTokCode[5]; unsigned char isSystem; /* A 'system' data field is only for internal use and should be ignored by a user interface. */ struct SRSoFLD *type; /*API Object that describes the data-field type. */ struct IDXo *idx; struct INXo *inx; struct BTRo *btree; struct IDSoFILE *idFile; unsigned char do_f; INT4 *on_fp; INT4 pargroup; unsigned char done_f; unsigned char noerrmsg_f; /* Supresses printing of parsing error messages. */ float vm_fac; float relIndexSize; /* Relative size of index created over data-field. */ char *tableToken; /* Name of the table and the token code. */ INT4 tableTokCode; unsigned char tableFormat; /* The format of the default as displayed inside a 'table view'. If left unspecified then the same attribute of the 'format' object is read. */ } SLBoFIELD; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Specifies the parser to be used for parsing all data-fields of a library, its flat file format and has a list of all data-field descriptions. */ #if defined(_SLB) && !defined(_SLBoFORM) #define _SLBoFORM typedef struct SLBoFORM { struct SLBoFIELD *f; INT4 nf; unsigned char lstfld; unsigned char slctfld; INT4 crslbx; INT4 newent; INT4 updent; struct SLBoFIELD *prev; struct SLBoFIELD *first; unsigned char access_f; struct ICAoSYNTAX *syntax; /* The syntax of the flat file entry. */ struct LIBoSUBENTRY *subEntries[10]; struct SRSoFILTYP *fil_t[4]; /* List of flat file types. There can be more than (eg, the sequence and annotation are stored in two different files). */ unsigned char tableFormat; unsigned char printFormat; } SLBoFORM; #endif #ifndef _LIBoFieldFormat #define _LIBoFieldFormat typedef struct LIBoFieldFormat { char *name; char *eval; INT4 isSelected; } LIBoFieldFormat; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description of a data-field Type (eg, 'Authors'). */ #if defined(_SRS) && !defined(_SRSoFLD) #define _SRSoFLD typedef struct SRSoFLD { char *shortn; /*API Short name (abbreviation) of data-field type */ char *nam; /*API Short name of data-field type */ char *cmnt; INT4 pargroup; unsigned char ityp; /* The type of the field type. At the moment only 'header' is used. The other types should be used to enforce a certain type on all the library fields referencing them. */ unsigned char isGroup; /* field type: single or group (of other field types) */ struct SRSoFLD *group; /* pointer to the field type group */ struct LIBoFieldFormat *format; INT4 formatN; } SRSoFLD; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Every entry of every databank indexed in SRS is represented by an entry-ID which uniquely identifies it. Several ID types are defined (eg, entry-ID, seq-ID, 3D-ID). Only the subentry-ID is structurally different from the others. */ #if defined(_SRS) && !defined(_IDoTYPE) #define _IDoTYPE typedef struct IDoTYPE { char *nam; /* Name of Id-type. */ INT4 siz; /* Size of ID in number of bytes. */ INT4 fddbeg; /* Offset of fadd (file address within IDX file) within ID. */ INT4 fddlen; /* Size of fadd in bytes. */ INT4 lbxbeg; /* Offset of databank-ID within ID. */ INT4 lbxlen; /* Size of databank-ID in bytes. */ INT4 lxbeg; /* Offset of subentry number within ID. */ INT4 lxlen; /* Size of subentry number in bytes. */ INT4 (*cpy) (); /* Function for printing an individual entry represented by ID. */ } IDoTYPE; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Describes a flat file type. Databanks may have more than one flat file type, eg, databanks in PIR or GCG with 'ref'-files containing the sequence annotation and 'seq'-files with the sequence. */ #if defined(_SRS) && !defined(_SRSoFILTYP) #define _SRSoFILTYP typedef struct SRSoFILTYP { char *typ_nm; /* File extension name. */ char *searchName; /* A search string used for finding all files in the specified directory (only for file per entry databanks). Any number of wildcards ('*' - matches all, '?' matches all single character) may be used. */ INT4 ln_z; UINT4 context; char *fipVar; /* Name of the Icarus variable containing the file address of the entry begin. */ char *fieldTokens; /* Name of the token table that has one token for each data-field of the entry. */ char *find; /* Name of EBNF production for parsing the first line in entry. */ INT4 adv; unsigned char sngl_f; /* Selects a file has only one single entry. */ unsigned char type; /* Type of sequence file. This is only important on VMS and with GCG. GCG version 8.0 does not have a record separator as with version 7.0. */ char *pipe; /* Format string (printf style) to create a command for processing the entry file before reading (eg, 'uncompress %%s'). */ } SRSoFILTYP; #endif #ifndef _LIBoSUBENTRY #define _LIBoSUBENTRY typedef struct LIBoSUBENTRY { struct IDoTYPE *idType; struct SRSoFLD *first; struct SLBoFIELD *fields; /* The Definition of the fields of the subentry. Each field must correspond to a field in the parent entry. Part of the definition (such as 'token' can 'shadow' the definition of the parent). */ INT4 fieldsN; } LIBoSUBENTRY; #endif #ifndef _LIBoHREF #define _LIBoHREF typedef struct LIBoHREF { char *name; char *link; } LIBoHREF; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Specifies a link between two libraries. A link can be built by using two indices built from one data-field of each library ('type=index') or by reading one library and processing cross-reference data ('type=read'). */ #if defined(_SRS) && !defined(_LINKo) #define _LINKo typedef struct LINKo { INT4 val; /* The weight attached to a link can be used to eliminate ambiguities during path resolution, or to force a certain path. */ char *token; INT4 tokCode; INT4 codeNum; char *nam1; /* Name of the first library - in case not the library name itself. */ char *nam2; /* Name of the first library - in case not the library name itself. */ struct IDoTYPE *id1_d; /* Object describing the first library's ID's to be linked. */ struct IDoTYPE *id2_d; /* Object describing the second library's ID's to be linked. */ struct SLBo *lib1; /* Object desribing the first library. */ struct SLBo *lib2; /* Object desribing the second library. */ struct SRSoFLD *fromField; /* Object describing the data-field of first library providing link information (only for index links). */ struct SRSoFLD *toField; /* Object describing the data-field of second library providing link information (for both index- and read-links). */ unsigned char rev_f; unsigned char init_f; unsigned char isActive; unsigned char do_f; INT4 goodRefN; INT4 badRefN; /* count of unsuccessful links */ INT4 lib1EntryN; /* number of entries from library 1 linked */ INT4 lib2EntryN; /* number of entries from library 2 linked */ INT4 linkIdN; IDPTR id_p; char *idWrtOff; struct FILEo *toFile; struct FILEo *fromFile; struct BTRo *btree1; struct BTRo *btree2; struct IDSoFILE *ids1; struct IDSoFILE *ids2; struct LINKo *use; /* Reference to the link object to be used to resolve the link. */ INT4 isOpen; unsigned char typ; /* Type of the link. 'read': first library must be read to find cross-references to second library; 'index': two indices, one from each library will be used to build the link; 'parent': link between entry and subentry. */ } LINKo; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description of individual data-fields of both root and leaf databanks of a view. */ #ifndef _VIEWoFIELD #define _VIEWoFIELD typedef struct VIEWoFIELD { struct SRSoFLD *type; /* Reference the object describing the field type. */ char *format; /* If the field type has additional format options a format can be specified for the field, otherwise the default will be taken. */ } VIEWoFIELD; #endif #ifndef _VIEWoLIB #define _VIEWoLIB typedef struct VIEWoLIB { struct SLBo *lib; struct VIEWoFIELD *fields; INT4 fieldsN; INT4 fieldsAllocN; char *query; char *viewName; unsigned char printOnlyEntryN; } VIEWoLIB; #endif #ifndef _VIEWo #define _VIEWo typedef struct VIEWo { char *name; INT4 format; unsigned char isEntryNamePrinting; unsigned char useShortFieldNames; struct VIEWoLIB *root; INT4 rootN; INT4 rootAllocN; struct VIEWoFIELD *rootFields; INT4 rootFieldsN; INT4 rootFieldsAllocN; struct VIEWoLIB *leaves; INT4 leavesN; INT4 leavesAllocN; INT4 n; INT4 isNascent; INT4 isDeleted; char *templateFile; struct TEMPLo *templ; void (*entryNamePrint)(); void (*entryNPrint)(); } VIEWo; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Value in an enumeration */ #ifndef _ODDoVALUE #define _ODDoVALUE typedef struct ODDoVALUE { char *name; /* Name of value. */ INT4 n; /* Number value. */ char *rem; /* Comment field. */ } ODDoVALUE; #endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Argument of Icarus command. */ #ifndef _IARGoVALUE #define _IARGoVALUE typedef struct IARGoVALUE { char *name; /* Name of the argument in an Icarus program. */ char *rem; /* Comment field. */ unsigned char isUnnamed; /* Defines if parameter may be unnamed. */ unsigned char isRequired; /* Defines if parameter is required. */ unsigned char type; /* Type of the argument */ char *className; INT4 defInt; /* Default value of type 'int' arguments. */ char *defaultStr; /* Default value of type 'string' arguments. */ struct ODDoVALUE *vals; INT4 valsN; unsigned char isSet; struct VARo *val; } IARGoVALUE; #endif #ifndef _IARGoCOM #define _IARGoCOM typedef struct IARGoCOM { char *name; /* Name of command in Icarus programs. */ char *functionName; /* C function that implements the command. */ INT4 isShow; /* Determines whether the command should appear in the Icarus functions reference list. */ char *rem; /* Comment field. */ unsigned char returnType; /* Type of value to be returned (if any). */ INT4 time; /* Execution time of command. */ char *returnClass; unsigned char isDirectCall; /* Call function directly or via C-interface. */ char *methodOf; /* normal function. */ struct IARGoVALUE *args; INT4 argsN; INT4 (*function)(); /* Function to be executed for command. */ INT4 orderN; /* Number of arguments ordered from C function (via 'IargGetArgs'). */ INT4 orderAllocN; /* Number of orders currently allocated. */ struct IARGoVALUE **order; /* Array with a list of argument orders. */ } IARGoCOM; #endif #ifdef _FUNCTION #undef _FUNCTION INT4 LibParSetFields (char *); #define LibParSetFields_F (INT4(*)()) LibParSetFields INT4 LibParSetLibs (char *); #define LibParSetLibs_F (INT4(*)()) LibParSetLibs INT4 LibParSetLinkLibs (char *); #define LibParSetLinkLibs_F (INT4(*)()) LibParSetLinkLibs INT4 LibSetEnvironment (char *); #define LibSetEnvironment_F (INT4(*)()) LibSetEnvironment INT4 LibParSetLibsViewRoot (char *); #define LibParSetLibsViewRoot_F (INT4(*)()) LibParSetLibsViewRoot INT4 LibParSetLibsViewLeaf (char *); #define LibParSetLibsViewLeaf_F (INT4(*)()) LibParSetLibsViewLeaf typedef INT4 (*SDLoFNCTx)(); SDLoFNCTx SDL_fnctx[] = { LibParSetFields_F, LibParSetLibs_F, LibParSetLinkLibs_F, LibSetEnvironment_F, LibParSetLibsViewRoot_F, LibParSetLibsViewLeaf_F }; #endif char time_srs_ID[] = "$Id: tm.c,v 1.1 1996/05/06 15:17:31 srs Exp $"; /* ** ** $RCSfile: tm.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:31 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port by Lukas Rosenthaler and Reinhard ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: time ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #ifdef VMS #include #include #else #include #include #endif #include "message.h" #include "tm.h" /**api* TimeGet *************************************************************** ** ** gets the time elapsed since 1-jan-1970 00:00 in seconds; ** ** IMPLICIT: ** ** RETURNS: 1 */ UINT4 TimeGet () { time_t seconds; time (&seconds); return (UINT4) seconds; } /**api* TimeToString ********************************************************* ** ** converts time into a string; ** ** INPUT: time value [R] ** option: "short", "long", "date" ** IMPLICIT: ** ** RETURNS: pointer to static string */ char *TimeToString (UINT4 userTimeVal, char *opt) { static char timeStr[30]; static char *month[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul", "Aug","Sep","Oct","Nov","Dec"}; time_t timeVal = (time_t) userTimeVal; struct tm *timeRec; if (timeVal == 0) time (&timeVal); timeRec = localtime (&timeVal); switch (tolower (opt[0])) { case 's': /* short */ sprintf (timeStr, "%0d/%0d/%0d", timeRec->tm_mon+1, timeRec->tm_mday, timeRec->tm_year); break; case 'l': /* long */ sprintf (timeStr, "%02d-%s-19%0d %02d:%02d", timeRec->tm_mday, month[timeRec->tm_mon], timeRec->tm_year, timeRec->tm_hour, timeRec->tm_min); break; case 'd': /* date */ sprintf (timeStr, "%02d-%s-19%0d", timeRec->tm_mday, month[timeRec->tm_mon], timeRec->tm_year); break; default: _ErrExit2 (e__unknownoption, opt); } return timeStr; } /**api* TimeFileCreate ******************************************************** ** ** retrieves files creation and last modification date; ** ** INPUT: address of file descriptor [R] ** IMPLICIT: ** ** RETURNS: file creation time ** 0 if file could not be opened */ UINT4 TimeFileCreate (FILE *file) { struct stat buff; INT4 fileNo; if (!file) return 0; fileNo = fileno (file); fstat (fileNo, &buff); return buff.st_ctime; } char srsbuild_srs_ID[] = "$Id: srsbuild.c,v 1.9 1996/08/12 19:03:47 etzold Exp $"; /* ** ** $RCSfile: srsbuild.c,v $ ** $Revision: 1.9 $ ** $Date: 1996/08/12 19:03:47 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: Lukas Rosenthaler and Reinhard Doelz ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "strv.h" #include "seq.h" #include "seqlib.h" #include "par.h" #include "btree.h" #include "arglist.h" #include "entry.h" #include "id.h" #include "set.h" #include "ids.h" #include "idx.h" #include "library.h" #include "link.h" #include "index.h" #include "variable.h" #include "toklist.h" #include "dict.h" #include "icarus.h" #include "odd.h" #define _INITOBJS #define _SDL #define _ODD #define _FUNCTION #include "oddclass.h" #define _SRS #define _SLB #define _INDEX #define _FUNCTION #define BUILD_M #include SRSINCLUDE #define BLDxMAXTMPSETSIZE 4000 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static void BldLibIndex (char *libName); static void BldLibRead (SLBo *lib); static void BldLibRelocate (char *libName); static void BldCompress (char *libName); static void BldSetReleaseName (char *libName); static void BldIndexTouch (char *libName); static void BldIndexLink (char *lib1Name, char *lib2Name); static void BldReadLink (char *libName); static void BldLibClose (SLBo *lib); static void BldEntryFinish (ENTRYo *entry); static void BldShowWords (ENTRYo *entry, SLBoFIELD *field); static int BldIndexOpen (SLBo *lib, SLBoFIELD *field); static INT4 BldEntryId (ENTRYo *entry); static LINKo *BldLinkFind (INT4 code); static void BldMakeLinkDict (SLBo *lib); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** function used by module "message" for printing error messages */ static int PrintMessage (MSGo *msg) { if (!ParGetNum ("showWarnings")) { switch (msg->msg_code) { case e__parsefail: case e__novalreference: case e__namnotuniq: case e__bldparsefail: case e__parsererror1: case e__parsererror2: case e__parsererror3: return 0; } } IcaPrintMessage (msg); return 1; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** main section... */ int main (int argc, char **argv) { ARGoLIST *arglist; char *tmpStr; LibOpen ("srs5"); arglist = (ARGoLIST *) LibObjByName ("arglist", "srsbuild"); argc = ArgGet (arglist, argc, argv); MsgSetFnct ((Func)PrintMessage); OddInit (def, 1); IcaInitSyntax (LibObjByName ("syntax", "icarus")); if (ParGetNum ("indexLink") && argc == 3) BldIndexLink (argv[1], argv[2]); else if (ParGetNum ("compress") && argc == 2) BldCompress (argv[1]); else if (ParGetNum ("touchIndex") && argc == 2) BldIndexTouch (argv[1]); else if ((tmpStr = ParGetStr ("releaseName")) && *tmpStr && argc == 2) BldSetReleaseName (argv[1]); else if (ParGetNum ("printLibInfo") && argc == 2) LibPrintInfo (argv[1]); else if (ParGetNum ("relocateLib") && argc == 2) BldLibRelocate (argv[1]); else if (ParGetNum ("readLink") && argc == 2) BldReadLink (argv[1]); else if (ParGetNum ("buildIndex") && argc == 2) BldLibIndex (argv[1]); else ArgUsage (arglist); exit (0); } /****** BldLibIndex *********************************************************** ** ** do the indexing of a library; ** ** INPUT: name of library ** IMPLICIT: ** convert (int) [W] ** global parameter "fieldList" [R] ** global parameter "newId" [W] ** ** RETURNS: */ static void BldLibIndex (char *libName) { SLBoFIELD *field; SLBo *lib; char *fieldList, *fieldName; INT4 c; if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); _ErrMsg2 (i__processing, lib->nam); /* ** select data-fields for processing ** if an ID field is among the selected the "newId" flag must be set */ LibSetField (libName, 0, "xinit"); if ((fieldList = ParGetStr ("fieldList")) && *fieldList) while ((fieldName = strtok (fieldList, " "))) { fieldList = NULL; LibSetField (libName, fieldName, "set"); if (LibIsIdField (libName, fieldName)) ParDefNum ("newId", 1); /* new ID index must be build */ } else { LibSetField (libName, 0, "allindex"); ParDefNum ("newId", 1); /* new ID index must be build */ } if (!ParGetNum ("parseTest")) { for (c=0; (field = LibNextField (lib, &c)); ) if (LibIsField (field, "active")) BldIndexOpen (lib, field); } BldLibRead (lib); BldLibClose (lib); } /****** BldCompress *********************************************************** ** ** ** INPUT: name of library ** IMPLICIT: ** convert (int) [W] ** global parameter "fieldList" [R] ** global parameter "newId" [W] ** ** RETURNS: */ static void BldCompress (char *libName) { SLBo *lib; SLBoFIELD *field; char *fieldList, *fieldName, fileName[FILxXNAM+1]; int context; if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); LibSetField (libName, 0, "init"); if ((fieldList = ParGetStr ("fieldList")) && *fieldList) { ParDefNum ("parSetFields", 1); while ((fieldName = strtok (fieldList, " "))) { fieldList = NULL; LibSetField (libName, fieldName, "set"); } } else LibSetField (libName, 0, "compress"); for (context=0; (field = (LibNextField (lib, &context))); ) if (field->do_f) { if (LibIsField (field, "index")) { LibGetIndexName (lib, field, fileName, "write"); BtrCompress (fileName); } else _ErrMsg2 (e__inxnotcompress, field->type->nam); } } /****** BldIndexTouch ********************************************************* ** ** sets internal index date to current date ...this is necessary if ** the original flat files are moved after index building; ** ** INPUT: name of library ** IMPLICIT: ** convert (int) [W] ** global parameter "fieldList" [R] ** global parameter "newId" [W] ** ** RETURNS: */ static void BldIndexTouch (char *libName) { SLBo *lib; SLBoFIELD *field; char *fieldList, *fieldName, fileName[FILxXNAM+1]; int context; if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); LibSetField (libName, 0, "init"); if ((fieldList = ParGetStr ("fieldList")) && *fieldList) { ParDefNum ("parSetFields", 1); while ((fieldName = strtok (fieldList, " "))) { fieldList = NULL; LibSetField (libName, fieldName, "set"); } } else LibSetField (libName, 0, "allIndex"); for (context=0; (field = (LibNextField (lib, &context))); ) if (field->do_f) { if (LibIsField (field, "index")) { LibGetIndexName (lib, field, fileName, "read"); BtrTouch (fileName); if (LibIsField (field, "id")) IdxTouch (fileName); } } } /****** BldLibRelocate ******************************************************** ** ** processes a file of a sequence library; ** ** INPUT: library object [W] ** IMPLICIT: ** ** OUTPUT: ** returns: */ static void BldLibRelocate (char *libName) { SLBo *lib; SLBoFIELD *field; ENTRYo *entry; if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); LibSetField (libName, 0, "xinit"); /* activate ID-index */ entry = EntryOpenStream (lib); while (EntryNext (entry)) { BldEntryId (entry); } BldLibClose (lib); } /****** BldSetReleaseName ***************************************************** ** ** associates a release name to the library's indices ** ** INPUT: library name [W] ** IMPLICIT: ** ** OUTPUT: ** returns: */ static void BldSetReleaseName (char *libName) { SLBo *lib; SLBoFIELD *field; struct IDXo *idx; char indexName[133]; INT4 errCode; lib = (SLBo *) LibObjByName ("library", libName); if (!lib) _ErrExit3 (e__objectunknown, "library", libName); field = LibGetIdField (lib); LibGetIndexName (lib, field, indexName, "read"); idx = IdxOpen (indexName, "update", 0, &errCode); _ErrExit2 (errCode, indexName); IdxSetReleaseName (idx, ParGetStr ("releaseName")); IdxClose (idx); } /****** BldLibRead ************************************************************ ** ** processes a file of a sequence library; ** ** INPUT: library object [W] ** IMPLICIT: ** ** OUTPUT: ** returns: */ static void BldLibRead (SLBo *lib) { ENTRYo *entry; int k=0; entry = EntryOpenStream (lib); while (EntryNext (entry)) BldEntryFinish (entry); } /****** BldLibClose *********************************************************** ** ** prepares a library for indexing ** ** INPUT: library object [W] ** IMPLICIT: ** ** RETURNS: 1 */ static void BldLibClose (SLBo *lib) { LINKo *link; SLBoFIELD *field; int context; for (context=0; (field = LibNextField (lib, &context)); ) { if (!field->do_f) continue; if (field->idx) IdxClose (field->idx); if (field->inx) InxClose (field->inx); if (field->btree) BtrClose (field->btree); } } /****** BldIndexLink ********************************************************** ** ** links two libraries using two selected indices ** ** INPUT: name of one library [R] ** name of other library [R] ** IMPLICIT: ** ** RETURNS: 1 */ static void BldIndexLink (char *lib1Name, char *lib2Name) { LINKo *link; BTRoREC *record1, *record2; SETo *set1, *set2; FIP idFip1, idFip2; int opt; if (!(link = LibGetLink (lib1Name, lib2Name))) _ErrExit3 (e__novallink, lib1Name, lib2Name); if (!(link = LinkOpen (link, "writeindex"))) exit (0); set1 = SetNew (NULL, "temp"); set2 = SetNew (NULL, "temp"); SetAlloc (set1, BLDxMAXTMPSETSIZE, link->id1_d); SetAlloc (set2, BLDxMAXTMPSETSIZE, link->id2_d); for (idFip1=1, opt=BTRxFIRST; (record1 = BtrRecordGet (link->btree1, opt)); idFip1++, opt=BTRxNEXT) { if ((record2 = BtrSearch (link->btree2, record1->str, &idFip2, 0))) { LinkCollectSet (set1, record1, link->ids1); LinkCollectSet (set2, record2, link->ids2); LinkSets (link, set1, set2); link->goodRefN++; } else { _ErrMsg4 (e__novalreference, link->lib1->nam, link->lib2->nam, record1->str); link->badRefN++; } } if (link->linkIdN) LinkClose (link); } void BldPrintProgress (ENTRYo *entry) { if (entry->lib->allEntryCnt % 300 == 0) _ErrMsg3 (i__processingentry, entry->lib->allEntryCnt, EntryGetName (entry)); } /**api* BldReadLink ***************************************************************** ** ** Processes all 'read links' for specified databank. Opens the flat file, ** reads entries one by one and builds link indices. ** ** INPUT: library name [R] */ static void BldReadLink (char *libName) { SLBo *lib; SLBoFIELD *field; ENTRYo *entry; LINKo *link; TOKoLIST *tokList; TOKoTOKEN *tok; char *tokListName, *tokStr; Int4 i, j, k, code, isTest=ParGetBool ("parseTest"); if (!(lib = (SLBo *) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); BldIndexOpen (lib, LibGetIdField (lib)); for (i=0, k=0; (link = LinkNext (lib, "read", &i)); k++) { _ErrMsg2 (i__bldReadLink, LibGetLinkToName (link)); if (!isTest) link = LinkOpen (link, "writeread"); } if (!k) { _ErrMsg2 (e__bldNoReadLinks, libName); return; } entry = EntryOpenStream (lib); while (EntryNext (entry)) { BldEntryId (entry); for (i=0; (link = LinkNext (lib, "read", &i));) { for (k=0; (tokListName = LinkNextToken (link, &code, &k));) { tokList = IcaGetTokenList (EntryGetJob (entry), tokListName); for (j=0; (tok = TokNextWithCode (tokList, code, &j));) { tokStr = TokGetStringCopy (tokList, tok); if (isTest) printf (" code: %d, %s -> %s\n", code, tokStr, LibGetLinkToName (link)); else if (!LinkIdWithString (link, EntryGetId (entry), tokStr)) _ErrMsg4 (e__novalreference, LibGetLinkFromName (link), LibGetLinkToName (link), tokStr); } } } } if (!isTest) for (i=0; (link = LinkNext (lib, "read", &i));) LinkClose (link); } /****** BldIndexOpen ********************************************************** ** ** opens an index and links it to the data-field; ** ** INPUT: library object [R] ** data-field object [R] ** IMPLICIT: ** global parameter "newId" [R] ** global parameter "buildIndex" [R] ** ** RETURNS: 1 */ static int BldIndexOpen (SLBo *lib, SLBoFIELD *field) { INXo *index=NULL; char readIndexName[133], writeIndexName[133]; int errCode; /* ** two different file names...input directory is not necessarily ** the output directory */ LibGetIndexName (lib, field, readIndexName, "read"); LibGetIndexName (lib, field, writeIndexName, "write"); /* ** open index for writing */ if (ParGetNum ("relocateLib")) { field->idx = IdxOpen (writeIndexName, "write", lib->maxNameLen, &errCode); _ErrExit2 (errCode, writeIndexName); } else if (ParGetNum ("buildIndex")) { if (LibIsField (field, "id") && !ParGetNum ("newId")) { field->btree = BtrOpen (readIndexName, "read", &errCode); _ErrExit2 (errCode, FileGetName (field->btree->file, "path")); if (!(field->idFile = IdsOpen (readIndexName, "read", 0, NULL,&errCode))) _ErrExit (e__error); } else { if (LibIsField (field, "index")) { index = InxOpen (writeIndexName, "new"); if (LibIsField (field, "num")) InxSetType (index, "num"); else if (LibIsField (field, "real")) InxSetType (index, "real"); else InxSetType (index, "string"); InxSetCache (index, lib->csiz); if (LibIsField (field, "id")) { field->idx = IdxOpen (writeIndexName, "write", lib->maxNameLen, &errCode); _ErrExit2 (errCode, writeIndexName); if (LibHasNoFiles (lib) && !LibIsFilePerEntry (lib)) LibSetLibFlatFiles (lib, field->idx); } } else _ErrExit2 (e__fieldnotindex, field->type->nam); } } field->inx = index; return 1; } /****** BldEntryId ************************************************************ ** ** Gets the entry-ID and places it into the ID index if appropriate. ** ** INPUT: entry object [w] ** IMPLICIT: ** ** RETURNS: */ static INT4 BldEntryId (ENTRYo *entry) { SLBoFIELD *field; TOKoLIST *tokList; TOKoTOKEN *tok; char *tokStr; FIP fip; field = LibGetIdField (EntryGetLib (entry)); tokList = IcaGetTokenList (entry->lib->job, field->indexToken[0]); if (!(tok = TokGetFirst (tokList))) return 0; tokStr = TokGetStringCopy (tokList, tok); strcpy (entry->entry_nm, tokStr); /* ask for "entry" token list to force reading of the entry */ IcaGetTokenList (EntryGetJob (entry), "entry"); /* get entry ID and insert into index */ if (ParGetNum ("newId") && !ParGetBool ("parseTest")) { fip = IdxPut (field->idx, tokStr, VarGetInt (VarGet (&entry->lib->job->scope, "entryFip")), 0, entry->fileX); IdBuild (entry->id, LibToId (entry->lib), fip, 0); InxInsertStr (field->inx, SmEdit (tokStr, SMxLOWCASE), entry->id); } else IdBuild (entry->id, LibToId (entry->lib), entry->lib->allEntryCnt, 0); BldPrintProgress (entry); return 1; } /****** BldEntryFinish ******************************************************** ** ** INPUT: entry object [R] ** IMPLICIT: ** ** RETURNS: */ static void BldEntryFinish (ENTRYo *entry) { SLBoFIELD *field; INT4 c; if (BldEntryId (entry)) { for (c=0; (field = LibNextField (entry->lib, &c)); ) { if (LibIsField (field, "active")) { if (ParGetNum ("parseTest")) BldShowWords (entry, field); else if (LibIsField (field, "index") && !LibIsField (field, "id")) BldSaveKey (entry, field); } } } } /****** BldSaveKey ************************************************************ ** ** ** INPUT: entry object [R] ** field object [R] ** IMPLICIT ** toklist (PRSoST *) */ INT4 BldSaveKey (ENTRYo *entry, SLBoFIELD *field) { TOKoLIST *tokList; TOKoTOKEN *tok; IDoENTRY id, *idPtr; char *tokStr; INT4 c, isSubEntry, code, wantedCode; idPtr = (isSubEntry = LibIsField (field, "subEntry")) ? &id : entry->id; tokList = IcaGetTokenList (entry->lib->job, field->indexToken[0]); for (c=0; (tok = TokNext (tokList, &c));) { tokStr = TokGetStringCopy (tokList, tok); code = TokGetCode (tok); wantedCode = field->indexTokCode[0]; if (isSubEntry) IdBuildSub (&id, entry->id, TokGetCode (tok)); else if (wantedCode != ICAxUNDEFCODE && code != wantedCode) continue; InxInsertStr (field->inx, SmEdit (tokStr, SMxLOWCASE|SMxTRIM), idPtr); } return 1; } /****** BldShowWords ********************************************************** ** ** Displays for specified data-field all words that could be extracted ** from the current entry. ** ** INPUT: entry object[R] ** data-field object [R] ** IMPLICIT: ** ** RETURNS: */ static void BldShowWords (ENTRYo *entry, SLBoFIELD *field) { TOKoLIST *tokList; TOKoTOKEN *tok; INT4 c, code, wantedCode; if (LibIsField (field, "id")) printf ("---------------------------------------\nEntry no: %d, fip %d\n", entry->lib->allEntryCnt, VarGetInt (VarGet (&entry->lib->job->scope, "entryFip"))); printf (" %s:\n", LibGetFieldName (field)); tokList = IcaGetTokenList (entry->lib->job, field->indexToken[0]); for (c=0; (tok = TokNext (tokList, &c));) { code = TokGetCode (tok); wantedCode = field->indexTokCode[0]; if (wantedCode == ICAxUNDEFCODE || code == wantedCode) printf (" code: %d, %s\n", TokGetCode (tok), TokGetStringCopy (tokList, tok)); } } char srscheck_ID[] = "$Id: srscheck.c,v 1.6 1996/08/12 20:24:29 etzold Exp $"; /* ** ** $RCSfile: srscheck.c,v $ ** $Revision: 1.6 $ ** $Date: 1996/08/12 20:24:29 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** checks if all indexes are up to date and writes ** out a DCL file to keep system up to date ** ** still to be done: ** o do "srsbuild -r" if the IDX index is not of the correct version ** o compress index if date is ok but index is not compressed ** o check ALL indices for the dates ...not just the Id index ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #define NO_ENVIRONMENT 1 #include "srs.h" #include "dict.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _ODD #define _FUNCTION #include "oddclass.h" typedef struct CHECKoINDEX { char *list; /* for usage of module "list" only! */ INT4 classId; /* for usage of module "list" only! */ char name[132]; int doBuild; int doCompress; } CHECKoINDEX; static DICTv compressFieldsDict=NULL; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ static int CheckLink (LINKo *link); int CheckIsBigLib (SLBo *lib); static void CheckBuildLinks (); static void CheckPrintSrsEnvHeader (char **envPtr); static void CheckSingleIndices (SLBo *lib); static int CheckOperateIndices (SLBo *lib); static void CheckBuildAllIndices (SLBo *lib); static int CheckIsNewLibrary (SLBo *lib); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** main section */ int main(int argc, char *argv[], char *envp[]) { ARGoLIST *arglist; SRSoGROUP *group; SLBo *lib; TEMPLv templ; char *tok, *tokList, etcDirName[FILxXNAM+1]; int rv, context1, context2, isLibSelect=0, isLibUnSelect=0; char *tmp; #ifndef VMS char *scriptName = "SRSETC:srsupdate"; #else char *scriptName = "SRSETC:srsupdate.com"; #endif strcpy (etcDirName, ""); /* ** open the resource file and get pointer to all library objects */ LibOpen ("srs5"); OddInit (def, 1); IcaInitSyntax (LibObjByName ("syntax", "icarus")); arglist = (ARGoLIST *) LibObjByName ("arglist", "srscheck"); argc = ArgGet (arglist, argc, argv); if (argc > 2) { ArgUsage (arglist); _ErrorExit (); } if (ParGetNum ("srsEnvHeader")) { CheckPrintSrsEnvHeader (envp); exit (0); } else if (ParGetNum ("printLibInfo") && argc == 2) { /* print only info ? */ LibPrintInfo (argv[1]); exit (0); } if (!((tmp = ParGetStr ("updateScriptName")) && *tmp)) tmp = scriptName; templ = TemplOpen ("SRSICA:srscheck.i", tmp); FileSetMode (TemplGetOutFile (templ), "rwxr-xr-x"); TemplWith (templ, "$srscheck"); strcpy (etcDirName, getenv ("SRSETC")); if (!*etcDirName) strcpy (etcDirName, ParGetStr ("etcDir")); TemplPrint ("head.unix", etcDirName); /* ** process list of libraries to be checked...if specified */ if (*(tokList = ParGetStr ("checkLibList"))) isLibSelect = 1; else if (*(tokList = ParGetStr ("notCheckLibList"))) isLibUnSelect = 1; for (context1=0; (group = LibNextLibGroup (&context1)); ) /* set all libs */ for (context2=0; (lib = LibNextLib (group, &context2)); ) ParDefNum (lib->nam, isLibSelect ? 0 : 1); if (isLibSelect || isLibUnSelect) /* set libs specified in list */ while ((tok = strtok (tokList, " "))) { /** set the databases of "SQ" */ tokList = NULL; if (!(lib = (SLBo *) LibObjByName ("library", tok))) _ErrExit3 (e__objectunknown, "library", tok); ParDefNum (lib->nam, isLibUnSelect ? 0 : 1); } /* ** now iterate over all selected libs that are not user defined libraries */ for (context1=0; (group = LibNextLibGroup (&context1)); ) { for (context2=0; (lib = LibNextLib (group, &context2)); ) { if (LibIs (lib, "user") || !LibIs (lib, "selected")) continue; _ErrMsg2 (i__checkinglib, lib->nam); rv = CheckIsNewLibrary (lib); _ErrIf (rv) { /* if there is something wrong with library */ _ErrMsg2 (i__givinguplib, lib->nam); ParDefNum (lib->nam, 0); /* turn lib OFF ...nothing can be done */ continue; } if (!rv) { CheckBuildAllIndices (lib); lib->upd_f = TRUE; } else { lib->upd_f = FALSE; CheckSingleIndices (lib); } CheckOperateIndices (lib); } } CheckBuildLinks (); TemplEndWith (templ); TemplClose (templ); exit (0); } /******************************************************************************* ** ** Set of functions to set flags of different types for the field object. ** Utilizes flags in the field objects that are normally used in other contexts. ** */ static void CheckSetFieldIsDone (SLBoFIELD *field) { field->done_f =1; } static void CheckSetFieldDoBuild (SLBoFIELD *field) { field->do_f =1; } static void CheckSetFieldDoCompress (SLBoFIELD *field) { if (!compressFieldsDict) compressFieldsDict = DictCreate(DictCreateClassSelfPtrKey (FALSE)); DictSet (&compressFieldsDict, field, SLBoFIELD*) = field; } static INT4 CheckGetFieldIsDone (SLBoFIELD *field) { return field->done_f; } static INT4 CheckGetFieldDoBuild (SLBoFIELD *field) { return field->do_f; } static INT4 CheckGetFieldDoCompress (SLBoFIELD *field) { if (compressFieldsDict && DictWith (compressFieldsDict, field)) return 1; else return 0; } /****** CheckIdIndex ********************************************************** ** ** Creates "checkindex" objects for all indexable fields and sets ** both create and compress flags. ** ** INPUT: address of library object [W] ** IMPLICIT: ** ** RETURNS: 1 */ static void CheckBuildAllIndices (SLBo *lib) { SLBoFIELD *field; INT4 c; for (c=0; (field = LibNextField (lib, &c)); ) { if (LibIsField (field, "index")) { CheckSetFieldDoBuild (field); CheckSetFieldDoCompress (field); } } _ErrMsg2 (i__mustbuildinx, lib->nam); } /****** CheckSingleIndices **************************************************** ** ** Checks every individual index if up to date. The index will be ** rebuilt if it is: ** o older than the idx file ** o does not exist ** o is busy (which should mean it was never completed because of a ** crash) ** It will be just compressed if it is not compressed and fine otherwise. ** ** ** INPUT: address of library object [W] ** IMPLICIT: ** ** RETURNS: 1 */ static void CheckSingleIndices (SLBo *lib) { LIBoINDEX *libInx; SLBoFIELD *field; int c; UINT4 idInxCreTime; /* creation date of ID index */ if ((libInx = LibIndexOpen (lib, LibGetIdField (lib), 0))) idInxCreTime = IdxGetTimeCreated (libInx->idx); for (c=0; (field = LibNextField (lib, &c)); ) { if (LibIsField (field, "index")) { if (!(libInx = LibIndexOpen (lib, field, 1))) { CheckSetFieldDoBuild (field); CheckSetFieldDoCompress (field); _ErrMsg3 (i__indexnotexist, LibGetFieldName (field), LibGetName (lib, "full")); } else if (BtrIsBusy (libInx->btree)) { CheckSetFieldDoBuild (field); CheckSetFieldDoCompress (field); _ErrMsg3 (i__indexnotcompleted, LibGetFieldName (field), LibGetName (lib, "full")); } else if (idInxCreTime > BtrGetTimeCreated (libInx->btree)) { CheckSetFieldDoBuild (field); CheckSetFieldDoCompress (field); _ErrMsg3 (i__indexnotuptodate, LibGetFieldName (field), LibGetName (lib, "full")); } else if (!IdsIsCompressed (libInx->idsFile)) { CheckSetFieldDoCompress (field); _ErrMsg3 (i__indexnotcompressed, LibGetFieldName (field), LibGetName (lib, "full")); } } } } /****** CheckOperateIndices ************************************************* ** ** Write the commands to build and compress all indices ** of the library. ** ** INPUT: address of library object [W] ** address of template object [W] ** IMPLICIT: ** ** RETURNS: 1 */ static int CheckOperateIndices (SLBo *lib) { SLBoFIELD *field; int context, procIndexSize, procSize, indexSize; char *indexDirName, *outDirName, fieldList[512]; indexDirName = ParGetStr ("indexDirName"); outDirName = ParGetStr ("outDirName"); TemplPrint ("build.head", LibName (lib)); /* ** commands for index compression: if ids files are regarded as ** being large then the files are built and compressed by ** independent srsbuild calls; */ procIndexSize = ParGetNum ("procIndexSize"); while (1) { for (context=0, procSize=0, fieldList[0]='\0'; (field = LibNextField (lib, &context)); ) { if (LibIsField (field, "index") && !CheckGetFieldIsDone (field) && CheckGetFieldDoBuild (field)) { indexSize = field->relIndexSize * lib->maxIndexSizeKb; /* ** add index to list if ..list is still empty ...or if there ** is still space in "process memory" ...set the "on" flag of ** the field object */ if (!procSize || procSize + indexSize <= procIndexSize) { sprintf (fieldList, "%s %s", fieldList, field->type->shortn); procSize += indexSize; CheckSetFieldIsDone (field); } } } if (!procSize && indexSize) break; TemplPrint ("build.indexList", LibName (lib), fieldList, indexDirName, outDirName, ParGetStr ("env")); if (!indexSize) /* index sizes were not specified */ break; } /* compress indices one by one */ for (context=0; (field = LibNextField (lib, &context)); ) if (LibIsField (field, "index") && CheckGetFieldDoCompress (field)) { TemplPrint ("compress.index", LibName (lib), field->type->shortn, indexDirName, outDirName, ParGetStr ("env")); } /*TemplPrint ("tail");*/ return 1; } /****** CheckBuildLinks ******************************************************* ** ** processes all "index" and "read" links ** ** INPUT: ** IMPLICIT: ** ** RETURNS: 1 */ static void CheckBuildLinks () { SRSoGROUP *group; SLBo *lib; LINKo *link; char *indexDirName, *outDirName; int i, j, isFirstReadLink=1, isFirstIndexLink=1; indexDirName = ParGetStr ("indexDirName"); outDirName = ParGetStr ("outDirName"); /* ** analyze all pairwise links ...first "index" links */ for (i=0; (link = LibNextLink (&i)); ) { if (!CheckLink (link)) { _ErrMsg3 (i__mustbuildlink, LibGetLinkFromName (link), LibGetLinkToName (link)); if (LinkIs (link, "index")) { if (isFirstIndexLink) { TemplPrint ("link.indexLink.head"); isFirstIndexLink = 0; } TemplPrint ("link.indexLink.do", LibGetLinkFromName (link), LibGetLinkToName (link), indexDirName, outDirName, ParGetStr ("env")); } } } /* ** then "read" links */ for (i=0; (group = LibNextLibGroup (&i)); ) { for (j=0; (lib = LibNextLib (group, &j)); ) { if (!lib->updlink_f) continue; if (isFirstReadLink) { TemplPrint ("link.readLink.head"); isFirstReadLink = 0; } TemplPrint ("link.readLink.do", LibName (lib), indexDirName, outDirName, ParGetStr ("env")); } } } /****** CheckIsNewLibrary ***************************************************** ** ** checks if libaries indices are OK; ** ** INPUT: address of library descr. [W] ** IMPLICIT: ** ** RETURNS: TRUE ** FALSE ** e__... */ static int CheckIsNewLibrary (SLBo *lib) { LIBoINDEX *libInx; FILEo *file; int k, rv; UINT4 allCreTime, creTime, context; char searchName[132], fileName[FILxXNAM+1]; libInx = LibIndexOpen (lib, LibGetIdField (lib), 1); /* open ID index */ if (!LibIsFilePerEntry (lib)) { for (k=0, allCreTime=0; k < lib->nfil; k++) { if (!(file = LibOpenFlatFile (lib, k, LibGetFileType (lib, NULL, NULL), &rv))){ printf (" you must edit SDL file to correct error\n\n"); return 0; } creTime = FileGetTime (file, "create"); if (allCreTime < creTime) allCreTime = creTime; } if (!libInx || allCreTime > BtrGetTimeCreated (libInx->btree)) return 0; } /* ** each entry resides in a separate file, count all these files and ** compare the number of files with the number of keys in the ID index - ** for that the ID index must be opened - but first check if the index ** exists; */ else { if (*lib->form->fil_t[0]->searchName) sprintf (searchName, "%s%s", lib->dirName[0], lib->form->fil_t[0]->searchName); else sprintf (searchName, "%s*.%s", lib->dirName[0], lib->form->fil_t[0]->typ_nm); for (k=0, context=0; FilSearch (_FilTempLN (searchName), fileName, &context); k++) ; if (!libInx || k != BtrGetRecordN (libInx->btree)) { if (libInx) _ErrMsg4 (i__diffentrynum, lib->nam, BtrGetRecordN (libInx->btree), k); return 0; } } return 1; /* indices are OK */ } /****** CheckLink ************************************************************* ** ** checks if link index is up to date; ** ** INPUT: address of link descriptor [R] ** IMPLICIT: ** ** RETURNS: 1 if link OK ** 0 if update needed */ static int CheckLink (LINKo *link) { FILE *file; SLBo *lib1 = link->lib1, *lib2 = link->lib2; LIBoINDEX *libInx; UINT4 indexTime1, indexTime2, linkTime; char fileName[FILxXNAM+1]; if (!LinkIs (link, "libs")) return 1; if (LinkIs (link, "user")) return 1; /* links to user libs have not to be updated */ if (!LibIs (lib1, "selected") || !LibIs (lib2, "selected")) return 1; /* one of the 2 libs is not selected for updating */ if (!lib1->upd_f && !lib2->upd_f) { libInx = LibIndexOpen (lib1, LibGetIdField (lib1), 1); indexTime1 = libInx ? BtrGetTimeCreated (libInx->btree) : 0; libInx = LibIndexOpen (lib2, LibGetIdField (lib2), 1); indexTime2 = libInx ? BtrGetTimeCreated (libInx->btree) : 0; /* time = LinkGetCreTime (link); !!!te */ LibGetLinkName (link, 0, fileName, "read"); file = fopen (_FilTempLN (fileName), "r"); linkTime = file ? TimeFileCreate (file) : 0; fclose (file); if (!(linkTime <= indexTime1 || linkTime <= indexTime2)) return 1; } /* ** if link is of type INDEX then it is build by reading the library's ** flatfile (-> extract the crossreferences) */ if (!LinkIs (link, "index")) lib1->updlink_f = TRUE; return 0; } /****** CheckIsBigLib ********************************************************* ** ** checks if library is big ** ** INPUT: address of library object[R] ** IMPLICIT: ** ** RETURNS: 1 if big ** 0 if not */ int CheckIsBigLib (SLBo *lib) { SLBoFIELD *field; int context, totalIndexSize; if (!lib->maxIndexSizeKb) return 0; for (context=0, totalIndexSize=0; (field = LibNextField (lib, &context)); ) if (LibIsField (field, "index")) { totalIndexSize += lib->maxIndexSizeKb * field->relIndexSize; } return (totalIndexSize > ParGetNum ("procIndexSize")) ? 1 : 0; } /****** CheckPrintSrsEnvHeader ************************************************ ** ** prints a C-language header file that defines all SRS environment ** variables as they are currently defined; ** ** INPUT: ** IMPLICIT: ** envp (char **) [R] ** ** RETURNS: */ static void CheckPrintSrsEnvHeader (char **envPtr) { TEMPLv templ; char var[80], val[512]; templ = TemplOpen ("SRSICA:srsenv.i", "SRSEXE:srsenv.h"); TemplWith (templ, "srsenv.unix"); TemplPrint ("head"); for (; *envPtr; envPtr++) { val[0] = '\0'; /* there might be no defined value */ sscanf (*envPtr, "%[^=]=%[^:]", var, val); if ((SmStrCmpLen (var, "SRS", 3) == 0) && *val) TemplPrint ("name", var, var, val); } TemplPrint ("tail"); TemplEndWith (templ); TemplClose (templ); } char srsnet_ID[] = "$Id: srspict.c,v 1.1 1996/05/06 15:17:26 srs Exp $"; /* ** ** $RCSfile: srspict.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:26 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387372 ** Email: etzold@embl-heidelberg.de ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** program takes a list of coordinates (databank nodes in a graph) ** of the form: 'coord:' databankName x y and produces a GIF file ** and a image map file for the WWW server ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "gd.h" #include "srs.h" #define brown 165, 42, 42 #define darkorange 255, 140, 0 #define rosybrown 188, 143, 143 #define seagreen 46, 139, 87 #define darkred 152, 20, 0 #define olivegreen 76, 39, 0 #define steelblue 57, 127, 145 #define maize 220, 185, 22 #define mediumaquamarine 102, 205, 170 #define cornflowerblue 100, 149, 237 #define mediumvioletred 199, 21, 133 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** structure describing a databank node in the image; */ typedef struct PICToNODE { char name[20]; int x; int y; int fg, bg; int isOnGraph; } PICToNODE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external, global and module wide variables */ static SCRIPTo *script; static gdImagePtr bullet=NULL; static int light, shade, red, grey, white, black, transparent, fg[10], bg[10]; ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ static void PictClose (gdImagePtr im, char *fileName); static void PictPrintDB (gdImagePtr im, char *name, int color1, int color2, int x, int y); static void PictPrintLegend (gdImagePtr im, int left, int upper); static void PictNetwork (gdImagePtr im); static void PictInit (gdImagePtr im); static void PictPrintLinkBox (gdImagePtr im, int x, int y, int linkN); static void PictRelocateNodes (PICToNODE *node, float width, float height); void PictLinkInfo (char *s1, char *s2, int x1, int y1, int x2, int y2) { ScriptWriteFrom (script, "PIC-LINKINFO", _s(s1), _s(s2), _d(x1), _d(y1), _d(x2), _d(y2)); } void PictLibInfo (char *s, int x1, int y1, int x2, int y2) { ScriptWriteFrom (script, "PIC-LIBINFO", _s(s), _d(x1), _d(y1), _d(x2), _d(y2)); } /****** PictPrintNetwork ***************************************************** ** ** Initialises colors and other things that other functions need; ** works on global variables ...not nice ...pragmatic solution! ** ** INPUT: ** IMPLICIT: ** all variables are global ** ** RETURNS: */ static void PictPrintNetwork () { SRSoGROUP *group; SLBo *lib; LINKo *link; INT4 k, l, i, c1, c2, c, rv, x, y; PICToNODE dbNode[100], *node, *tmp; gdImagePtr im; im = gdImageCreate (750, 600); PictInit (im); script = ScriptOpen ("SRSWWW:wgetz.script", "SRSWWW:srsnet.map"); fg[0] = gdImageColorAllocate (im, black); fg[1] = gdImageColorAllocate (im, black); fg[2] = gdImageColorAllocate (im, black); fg[3] = gdImageColorAllocate (im, black); fg[4] = gdImageColorAllocate (im, black); fg[5] = gdImageColorAllocate (im, black); fg[6] = gdImageColorAllocate (im, black); bg[0] = white; bg[1] = white; bg[2] = white; bg[3] = white; bg[4] = white; bg[5] = white; bg[6] = white; /* ** assign databank names and background and foreground colors to ** the nodes */ for (k=0, l=0, c1=0; (group = LibNextLibGroup (&c1));) { for (c2=0, i=0; (lib = LibNextLib (group, &c2)); k++, i++) { node = &dbNode[k]; strcpy (node->name, LibGetName (lib, "full")); node->fg = fg[l]; node->bg = bg[l]; node->isOnGraph = 0; } if (i) /* if group is not empty */ l++; } dbNode[k].name[0] = '\0'; /* terminating node */ /* ** read the file with the coordinates and assign x and y coordinates ** to the nodes */ { FILo file; char libName[80]; rv = FilUOpen (&file, "SRSWWW:srsnet.dat", 512, 0); _ErrExit2 (rv, "SRSWWW:srsnet.dat"); do { if (sscanf (file.ln, "coord: %s %d %d", libName, &x, &y) == 3) { for (k=0; *dbNode[k].name; k++) { node = &dbNode[k]; if (SmEqs (libName, node->name)) { node->x = x; node->y = y; node->isOnGraph = 1; } } } FilURead (&file); } while (!FilEof (&file)); } /* ** find default positions for databanks not listed in the coordinate ** file */ for (tmp=dbNode, y=0; *(tmp->name); tmp++) if (!tmp->isOnGraph) { tmp->x = 0; tmp->y = y; tmp->isOnGraph = 1; y += 50; } PictRelocateNodes (dbNode, 750, 530); /* ** paint the all links between nodes */ for (c=0; (link = LibNextLink (&c)); ) if (link->lib1 && link->lib2) PictLinkDBs (im, black, dbNode, LibGetName (link->lib1, "full"), LibGetName (link->lib2, "full")); /* ** paint the nodes */ for (k=0; *dbNode[k].name; k++) { PictPrintDB (im, dbNode[k].name, dbNode[k].fg, dbNode[k].bg, dbNode[k].x, dbNode[k].y); } /* figure lengend */ /* PictPrintLegend (im, 40, 540);*/ /* default action for the clickable WWW map */ ScriptWriteFrom (script, "PIC-LIBINFO", _s("points_to_nothing"), _d(0), _d(0), _d(im->sx), _d(im->sy)); ScriptClose (script); PictClose (im, "SRSWWW:srsnet.gif"); } /****** PictRelocateNodes ***************************************************** ** ** ** INPUT: ** IMPLICIT: ** ** RETURNS: */ static void PictRelocateNodes (PICToNODE *node, float width, float height) { PICToNODE *tmp; INT4 k, hrim=40, vrim=30; float minx=1000, maxx=0, miny=1000, maxy=0; float relx, rely; width -= 2*hrim; height -= 2*vrim; for (k=0; *node[k].name; k++) { tmp = &node[k]; if (tmp->x < minx) minx = tmp->x; if (tmp->x > maxx) maxx = tmp->x; if (tmp->y < miny) miny = tmp->y; if (tmp->y > maxy) maxy = tmp->y; } maxx -= minx; maxy -= miny; relx = width / maxx; rely = height / maxy; for (k=0; *node[k].name; k++) { tmp = &node[k]; tmp->x = (tmp->x - minx) * relx + hrim ; tmp->y = (tmp->y - miny) * rely + vrim ; } } /****** PictPrintGraphTable *************************************************** ** ** Prints a picture that represents the databank network in a tabular ** form. ** ** INPUT: ** IMPLICIT: ** script (SCRIPTo *) [W] ** ** RETURNS: */ static void PictPrintGraphTable () { gdImagePtr im; im = gdImageCreate (560, 620); script = ScriptOpen ("SRSWWW:wgetz.script", "SRSWWW:srslink.map"); PictInit (im); fg[0] = gdImageColorAllocate (im, 210, 210, 250); fg[1] = gdImageColorAllocate (im, 190, 190, 230); fg[2] = gdImageColorAllocate (im, 170, 170, 210); fg[3] = gdImageColorAllocate (im, 140, 140, 190); fg[4] = gdImageColorAllocate (im, 110, 110, 170); fg[5] = gdImageColorAllocate (im, 80, 80, 150); fg[6] = gdImageColorAllocate (im, 50, 50, 130); bg[0] = black; bg[1] = black; bg[2] = black; bg[3] = white; bg[4] = white; bg[5] = white; bg[6] = white; PictNetwork (im); PictPrintLegend (im, 20, 560); PictClose (im, "SRSWWW:srslink.gif"); ScriptClose (script); } #define HRIM 4 #define VRIM 0 #define BOXLEN (12+2*VRIM) #define BOXHEIGHT (12+2*VRIM) static void PictNetwork (gdImagePtr im) { SRSoGROUP *group, *group2; SLBo *lib, *lib2; struct LINKoNOD *path; INT4 maxLen, len, textLen; INT4 c1, c2, c3, c4, i, k, x, y; char *libName, *lib2Name; /* find maximum length of databank names */ maxLen = 0; for (c1=0; (group = LibNextLibGroup (&c1)); ) for (c2=0; (lib = LibNextLib (group, &c2)); ) { len = strlen (LibGetName (lib, "full")); if (maxLen < len) maxLen = len; } textLen = maxLen*6; /* print databank names horizontally */ x=10; y=10; for (k=0, c1=0; (group = LibNextLibGroup (&c1));) { for (c2=0, i=0; (lib = LibNextLib (group, &c2)); i++) { gdImageFilledRectangle (im, x, y, x+textLen+2*HRIM, y+12+2*VRIM, fg[k]); gdImageString (im, gdFontSmall, x+HRIM, y+VRIM, LibGetName (lib, "full"), bg[k]); PictLibInfo (LibGetName (lib, "full"), x, y, x+textLen+2*HRIM, y+12+2*VRIM); y += 12 + 2 * VRIM + 1; } if (i) k++; } /* print databank names vertically */ x += textLen + 2* HRIM ; for (k=0, c1=0; (group = LibNextLibGroup (&c1));) { for (c2=0, i=0; (lib = LibNextLib (group, &c2)); i++) { gdImageFilledRectangle (im, x, y, x+12+2*VRIM, y+textLen+2*HRIM, fg[k]); gdImageStringUp (im, gdFontSmall, x+VRIM, y+HRIM+textLen, LibGetName (lib, "full"), bg[k]); PictLibInfo (LibGetName (lib, "full"), x, y, x+12+2*VRIM, y+textLen+2*HRIM); x += 12 + 2 * VRIM + 1; } if (i) k++; } y = 10; for (c1=0; (group = LibNextLibGroup (&c1)); ) for (c2=0; (lib = LibNextLib (group, &c2)); ) { x = 10+textLen+2*HRIM+1; libName = (LibGetName (lib, "full")); for (c3=0; (group2 = LibNextLibGroup (&c3)); ) for (c4=0; (lib2 = LibNextLib (group2, &c4)); ) { lib2Name = LibGetName (lib2, "full"); if (lib == lib2) goto endofline; /* proceed until diagonal is reached */ if ((LibGetLink (libName, lib2Name))){ /* direct link */ PictPrintLinkBox (im, x, y, 1); PictLinkInfo (libName, lib2Name, x, y, x+BOXLEN, y+BOXHEIGHT); } else { if ((path = LinkSearchPath (libName, lib2Name))) { PictPrintLinkBox (im, x, y, LinkGetPathLength (path)); PictLinkInfo (libName, lib2Name, x, y, x+BOXLEN, y+BOXHEIGHT); } } x += BOXLEN+1; } endofline: y += BOXHEIGHT+1; } } static void PictPrintLinkBox (gdImagePtr im, int x, int y, int linkN) { static int grey[4]; char tmp[5]; if (!grey[0] && ! grey[1]) { grey[0] = white; grey[1] = gdImageColorAllocate (im, 255, 240, 240); grey[2] = gdImageColorAllocate (im, 255, 220, 220); grey[3] = gdImageColorAllocate (im, 255, 200, 200); } gdImageFilledRectangle (im, x, y, x+BOXLEN, y+BOXHEIGHT, grey[linkN-1]); sprintf (tmp, "%d", linkN); gdImageString (im, gdFontSmall, x+HRIM, y+VRIM, tmp, linkN == 1 ? red : black); } static void PictClose (gdImagePtr im, char *fileName) { FILE *file; int rv; /* Make output image interlaced (allows "fade in" in some viewers, and in the latest web browsers) */ gdImageInterlace (im, 1); /* set transparent color */ transparent = gdImageColorExact (im, 190, 190, 190); gdImageColorTransparent(im, transparent); file = FilOpenW (fileName, &rv); _ErrExit2 (rv, fileName); gdImageGif (im, file); fclose (file); gdImageDestroy (im); } /****** PictInit *************************************************************** ** ** Initialises colors and other things that other functions need; ** works on global variables ...not nice ...pragmatic solution! ** ** INPUT: pointer to image [W] ** IMPLICIT: ** all variables are global ** ** RETURNS: */ static void PictInit (gdImagePtr im) { FILE *file; int rv; /* First color allocated is background. */ white = gdImageColorAllocate (im, 255, 255, 255); grey = gdImageColorAllocate(im, 190, 190, 190); light = gdImageColorAllocate (im, 255, 240, 255); shade = gdImageColorAllocate (im, 80, 80, 100); black = gdImageColorAllocate (im, 0, 0, 0); red = gdImageColorAllocate (im, 255, 0, 0); file = FilOpenR ("SRSWWW:bullet.gif", &rv); _ErrExit2 (rv, "SRSWWW:bullet.gif"); bullet = gdImageCreateFromGif(file); } /****** PictLinkDBs ************************************************************ ** ** ** ** ** INPUT: pointer to image [W] ** IMPLICIT: ** ** RETURNS: 1 if success ** 0 if name could not be found or if no coordinates exist */ int PictLinkDBs (gdImagePtr im, int color, PICToNODE *node, char *libName1, char *libName2) { FILE *in; PICToNODE *node1, *node2; int x, y, h, l; /* ** Search both databank names and exchange for a "node" object ** and connect them by a line */ for (node1=node; *(node1->name); node1++) if (SmEqs (node1->name, libName1)) break; for (node2=node; *(node2->name); node2++) if (SmEqs (node2->name, libName2)) break; if (!node1->isOnGraph || !node2->isOnGraph || !*node1->name || !*node2->name) return 0; gdImageLine (im, node1->x, node1->y, node2->x, node2->y, color); /* ** find the center of that line for drawing a bullet (for clicking) */ if (node1->y < node2->y) h = node2->y, l = node1->y; else l = node2->y, h = node1->y; y = l + (h - l) /2; if (node1->x < node2->x) h = node2->x, l = node1->x; else l = node2->x, h = node1->x; x = l + (h - l) /2; /* ** paste the bullet and print its coordinates into the WWW image map file */ x -= bullet->sx/2; y -= bullet->sy/2; gdImageCopy (im, bullet, x, y, 0, 0, bullet->sx, bullet->sy); ScriptWriteFrom (script, "PIC-LINKINFO", _s(node1->name), _s(node2->name), _d(x), _d(y), _d(x+bullet->sx), _d(y+bullet->sy)); return 1; } /****** PictPrintDB ************************************************************ ** ** Initialises colors and other things that other functions need; ** works on global variables ...not nice ...pragmatic solution! ** ** INPUT: pointer to image [W] ** IMPLICIT: ** ** RETURNS: */ static void PictPrintDB (gdImagePtr im, char *name, int color1, int color2, int x, int y) { /* Points for polygon */ gdPoint points[10]; int x1, y1, x2, y2, len, xrel, yrel, margin=4, outRim=2, diff; /* ** calculate size of text, and of the whole box in points */ len = strlen (name); x1 = 1; y1 = 1; x2 = x1 + len*8 + margin*2; /* font is 8*16 */ y2 = y1 + 16 + margin*2; /* ** calculate positions of that box on the image */ xrel = (x2 - x1) / 2; yrel = (y2 - y1) / 2; x1 = x-xrel; y1 = y-yrel; x2 = x+xrel; y2 = y+yrel; /* ** paste an even bigger box in "light" ...for the 3d aspect */ /* gdImageFilledRectangle (im, x1-outRim, y1-outRim, x2+outRim, y2+outRim, light); */ /* ** now paste over the "light" box a "shade" polygon ...together they will ** be ligth and shadow ...node that the polygon drawing is a bit buggy */ diff = (y2-y1)/2; points[0].x = x2 + outRim; points[0].y = y2 + outRim; points[1].x = x2 + outRim; points[1].y = y1 - outRim; points[2].x = x2 - diff - 1; points[2].y = y1 + diff - 1; /* the +1 prevents some bug ...a white line */ points[3].x = x1 + diff; points[3].y = y1 + diff; points[4].x = x1 - outRim; points[4].y = y2 + outRim; /* gdImageFilledPolygon(im, points, 5, shade); */ /* ** now print the rectangle with the databank name and write a ** "rect" statement into the WWW image map file */ gdImageFilledRectangle (im, x1, y1, x2, y2, color1); gdImageString(im, gdFontLarge, x1+margin, y1+margin, name, color2); ScriptWriteFrom (script, "PIC-LIBINFO", _s(name), _d(x1), _d(y1), _d(x2), _d(y2)); } /****** PictPrintLegend ******************************************************** ** ** Prints the legend with the color codes for the databank groups. ** ** INPUT: pointer to image [W] ** IMPLICIT: ** bullet ** fg ** black ** ** RETURNS: */ static void PictPrintLegend (gdImagePtr im, int left, int upper) { SRSoGROUP *group; int x,y, probeSize=12, space=5, bigSpace=10; int k, i, c1, c2; char tmp[132]; /* ** print the creation time and explain the bullet */ x = left; y = upper; sprintf (tmp, "Creation Date: %s\n", TimeToString (0, "date")); gdImageString(im, gdFontSmall, x, y, tmp, black); x+= 180; if (ParGetNum ("doNetworkPict")) { gdImageCopy (im, bullet, x, y, 0, 0, bullet->sx, bullet->sy); x += bullet->sy + space; } else if (ParGetNum ("doGraphTablePict")) { PictPrintLinkBox (im, x, y, 1); x+= BOXLEN; PictPrintLinkBox (im, x, y, 2); x+= BOXLEN; PictPrintLinkBox (im, x, y, 3); x+= BOXLEN; PictPrintLinkBox (im, x, y, 4); x+= BOXLEN + space; } gdImageString (im, gdFontSmall, x, y, "Press to get link information", black); /* ** print on next line a color probe and the databank group name */ x = left; y = upper+20; for (k=0, c1=0; (group = LibNextLibGroup (&c1));) { for (c2=0, i=0; (LibNextLib (group, &c2)); i++) ; if (i) { /* if group is not empty */ gdImageFilledRectangle (im, x, y, x+probeSize, y+probeSize, fg[k++]); x += probeSize + space; gdImageString(im, gdFontSmall, x, y, group->com, black); x += strlen (group->com) * 6 + bigSpace; } } gdImageRectangle (im, left-bigSpace, upper-bigSpace, x+bigSpace, upper+30+bigSpace, black); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** The main thing */ INT4 main (INT4 argc, char *argv[], char *envp[]) { ARGoLIST *arglist; gdImagePtr im_out; SrsEnv (); LibOpen ("srswin"); arglist = (ARGoLIST *) LibObjByName ("arglist", "srspict"); argc = ArgGet (arglist, argc, argv); if (ParGetNum ("doNetworkPict")) PictPrintNetwork (); if (ParGetNum ("doGraphTablePict")) PictPrintGraphTable (); return 0; } char srswww_ID[] = "$Id: srswww.c,v 1.15 1996/08/11 22:47:25 etzold Exp $"; /* ** ** $Source: /home/srs/cvsroot/srs/src/srswww.c,v $ ** $Revision: 1.15 $ ** $Date: 1996/08/11 22:47:25 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** Modified to fit the new SRS WWW interface ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include #include "message.h" #include "sm.h" #include "tm.h" #include "strv.h" #include "lst.h" #include "futil.h" #include "templ.h" #include "par.h" #include "id.h" #include "set.h" #include "library.h" #include "btree.h" #include "idx.h" #include "entry.h" #include "link.h" #include "seq.h" #include "query.h" #include "queryass.h" #include "seqlib.h" #include "icarus.h" #include "icaarg.h" #include "variable.h" #include "view.h" #include "srswww.h" #define _SRS #define _SLB #define _WWW #include "srs5.h" #define WWWxMAXLINESIZE 500000 typedef struct SCRIPTo{ void *x; }SCRIPTo; INT4 SmRemoveChar(char remoteAddr[],char c); INT4 LibShufflebuff(char s[]); void LibRevStr(char s[]); INT4 LibPower(int base, int n); extern char *ScriptFile; extern char *RParGetStr(char *strfmt, ...); /* * * * * * * * stuff from HTTP server's "util.c" * * * * * * * * * */ #define LF 10 #define CR 13 static char *makeword(char *line, char stop) { int x = 0,y; char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1)); for(x=0;((line[x]) && (line[x] != stop));x++) word[x] = line[x]; word[x] = '\0'; if(line[x]) ++x; y=0; while ((line[y++] = line[x++])); return word; } static char *fmakeword(char **buffPtr, char *buffEnd, char stop, int *cl) { int wsize; char *word; int ll; wsize = 132; ll=0; word = (char *) malloc(sizeof(char) * (wsize + 1)); while(1) { word[ll] = *(*buffPtr)++; if(ll==wsize) { word[ll+1] = '\0'; wsize+=102400; word = (char *)realloc(word,sizeof(char)*(wsize+1)); } --(*cl); if((word[ll] == stop) || (*buffPtr >= buffEnd) || (!(*cl))) { if(word[ll] != stop) ll++; word[ll] = '\0'; return word; } ++ll; } } static char x2c(char *what) { register char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return(digit); } static void unescape_url(char *url) { register int x,y; for(x=0,y=0;url[y];++x,++y) { if((url[x] = url[y]) == '%') { url[x] = x2c(&url[y+1]); y+=2; } } url[x] = '\0'; } static void plustospace(char *str) { register int x; for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' '; } /* * * * * * * * end stuff from HTTP server's "util.c" * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external, global and module wide variables */ VIEWo *wwwView=NULL; char buff[WWWxMAXLINESIZE+1]; ENTRYo *entryCurr; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static INT4 WwwViewEntryInTable (TEMPLv templ, ENTRYo *entry, VIEWoLIB *vlib, Int4 entryNum, Int4 isRoot, Int4 rowN); static void WwwViewEntryInList (TEMPLv templ, ENTRYo *entry, VIEWoLIB *vlib, Int4 entryNum, Int4 isRoot); static void WwwPrintTableEmptyEntry (VIEWoLIB *vlib, Int4 rowN); static void WwwPresentSkipChunkSet (TEMPLv templ, INT4 setSize, INT4 queryN); static void WwwDeleteQuery (); static void WwwViewTableHeader (TEMPLv templ, VIEWo *view); static Int4 WwwIsViewForQuery (VIEWo *view, char *setName); static void WwwViewPrintEntryN (VIEWoLEAFSET *leaf, ENTRYo *entry, Int4 rowN); char *WwwReadInput (int byteN, char *fileName) { static char buff[10000]; FILE *file; fread (buff, 1, byteN, stdin); if (ParGetBool ("debugSRSWWW")) { /* file with form input for debugging */ file = fopen (fileName, "w"); fwrite (buff, 1, byteN, file); fclose (file); chmod (fileName, 00777); } return buff; } Int4 WwwPrintContentType (char *s) { static Int4 isPrinted=0; char *tmp; if (*(tmp = ParGetStr ("mimeType"))) s = tmp; if (!isPrinted) { isPrinted=1; if (s && SmEqs (s, "none")) ; else if (s) printf ("%s\n\n", s); else printf ("Content-type: text/html\n\n"); return 1; } return 0; } INT4 WwwPrintMessage (MSGo *msg) { static TEMPLv templ=NULL; if (!(templ = TemplGet ())) templ = TemplOpen ("SRSICA:srswww.i", NULL); TemplWith (templ, "$messages"); WwwSetColorScheme (templ); if (WwwPrintContentType (NULL)) { TemplPrint ("head"); } switch (msg->msg_code) { case i__wroteset: break; case e__parsererror3: TemplPrint ("parseError", msg->primsg, msg->secmsg); break; default: if (msg->msg_t == MSGxINFO) TemplPrint ("info", msg->primsg, msg->secmsg); else TemplPrint ("error", msg->primsg, msg->secmsg); break; } TemplEndWith (); } int WwwParInput (int byteN, char *buff) { struct { char *name; char *val; } entry[1000]; int k, len, entryN=0, isDebug=ParGetBool ("isDebug"); char *name, *val; if (isDebug) printf ("Content-type: text/html\n\n"); /* ** the for loop contains code from the "post-query.c" shipped with Mosaic ** collect all pairs entry name and value from stdin */ for (k=0; byteN && (buff < buff+byteN); k++) { entry[k].val = fmakeword (&buff, buff+byteN, '&',&byteN); plustospace (entry[k].val); unescape_url (entry[k].val); entry[k].name = makeword (entry[k].val,'='); } entryN = k; /* ** now process these pairs into pairs of parameter name and value */ for (k=0; k < entryN; k++) { name = entry[k].name; val = entry[k].val; SmEdit (val, SMxTRIM); /* macintotsh client */ if (isDebug) printf ("#par /name=%s /str=%s
    \n", name, val); ParIsVolatileName (name); ParDefStr (name, val); } if (isDebug) printf("


    \n"); return entryN; } INT4 WwwPrintF (char *formatStr, ...) { static char *ln = NULL; va_list ap; if (!ln) if (!(ln = (char *) malloc (WWWxMAXLINESIZE+1))) _ErrExit2 (e__allocfail, "WWW output line"); /*[WWWxMAXLINESIZE+1]*/; va_start (ap, formatStr); vsprintf (ln, formatStr, ap); va_end (ap); printf ("%s", ln); if (ln[strlen (ln) -1] != '\n') printf ("\n"); return 1; } char *WwwChecked (Int4 flag) { return flag ? "CHECKED" : ""; } char *WwwSelected (Int4 flag) { return flag ? "SELECTED" : ""; } /****** WwwStringEncode ******************************************************* ** ** Replaces special characters by HTML codes; ** ** INPUT: string [W] ** IMPLICIT: ** ** RETURNS: modified string */ char *WwwStringEncode (char *s) { SmSwapS (s, "&", "&"); SmSwapS (s, "|", "|"); SmSwapS (s, "<", "<"); SmSwapS (s, ">", ">"); return s; } INT4 WwwIndexValueLink (char *formatStr, ...) { static char *libName, *fieldName; va_list ap; char *value, tmp[80], queryStr[132]; INT4 entryN; if (!formatStr) { /* init */ libName = ParGetStr ("libName"); fieldName = ParGetStr ("listIndex"); return 1; } va_start (ap, formatStr); value = va_arg (ap, char *); entryN = va_arg (ap, INT4); va_end (ap); sprintf (tmp, "%s", value); sprintf (queryStr, "[%s-%s:%s]", libName, fieldName, value); printf ("%-55s %6d entries\n", WwwTransform ("encode", queryStr), fieldName, tmp, entryN); return 1; } /**api* WwwViewFeature ******************************************************** ** ** views a sequence feature ** ** INPUT: name of set [R] ** IMPLICIT: ** ** RETURNS: */ void WwwViewFeature (char *queryStr, INT4 subEntryN) { #ifdef script SETo *set, *setSub; IDoENTRY id, idSub; SCRIPTo *script; script = ScriptOpen (ScriptFile, NULL); if (QryDo (queryStr, "Q")) { set = SetGet ("Q"); SetGetID (set, 1, &id); setSub = SetNew ("QSUB", NULL); idSub.id_d = (IDoTYPE *) LibObjByName ("idtype", "seq-ft-id"); IdBuildSub (&idSub, &id, subEntryN); SetAddID (setSub, &idSub); ParDefBool ("parSetFields", 1); ParDefBool ("Features", 1); ParDefBool ("Definition", 1); ParDefBool ("ID", 1); ParDefBool ("takeuncompletefeature", 1); WwwPrintSet ("QSUB", 1, 1, script); } #endif } /**api* WwwPresentViewsForLibs *********************************************** ** ** Presents all view where all libraries in the group ** are contained as root libraries. ** ** INPUT: library group object (or NULL) [R] */ void WwwPresentViewsForLibs (SRSoGROUP *group) { SLBo *lib; Int4 numberOfViews = ParGetNum("numberOfViews"); Int4 currViewN=0, i, c, isBadView; char *tmp; if (numberOfViews >= 0) { currViewN = ParGetNum("viewNumber"); TemplPrint ("selectView.head"); for (i=0; i <= numberOfViews; i++) { tmp = ParGetStrF("view%d_Name",i); if (i) { /* the NULL view */ for (c=0, isBadView=0; (lib = LibNextLib (group, &c));) { if (ParGetNumF ("ViewDeleted_%d", i) || !ParGetNumF ("v%d_R_%s", i, LibName (lib))) isBadView=1; } if (isBadView) continue; } TemplPrint ("selectView.name", i, WwwSelected (i == currViewN), tmp); } TemplPrint("selectView.tail"); } } /**api* WwwPresentViewsForLeaf *********************************************** ** ** As WwwPresentViewForLibs but for a single leaf library. ** ** INPUT: view object [R] ** leaf object [R] */ void WwwPresentViewsForLeaf (VIEWo *view, VIEWoLIB *vlib) { Int4 numberOfViews=ParGetNum("numberOfViews"), i; char *tmp, *viewName; viewName = ViewGetLeafView (vlib); if (numberOfViews >= 0) { TemplPrint ("selectView.head", view->n, LibName (vlib->lib), WwwSelected (!*viewName)); for (i=0; i <= numberOfViews; i++) { tmp = ParGetStrF("view%d_Name",i); if (i && ((ParGetNumF ("ViewDeleted_%d", i) && i!= numberOfViews) || !ParGetNumF ("v%d_R_%s", i, LibName (vlib->lib)))) continue; TemplPrint ("selectView.name", WwwSelected (SmEqs (tmp, viewName)), tmp); } TemplPrint("selectView.tail"); } } /****** WwwPresentViewList **************************************************** ** ** Print a menu with list all the views for selection. ** Requires that the template context is already set to a list ** with the "view labels" by TemplWith. ** ** INPUT: option: "reset", "current" [R] ** */ void WwwPresentViewList (char *option) { char *tmp; Int4 k, currentViewNumber = ParGetNum("viewNumber"); if (option[0] == 'r') /* reset */ currentViewNumber = 0; TemplPrint("head"); for(k=0; k <= ParGetNum("numberOfViews"); k++) { if( ParGetNumF("ViewDeleted_%d",k) ) continue; /* skip deleted views */ tmp = ParGetStrF("view%d_Name",k); TemplPrint("name",k, WwwSelected (k==currentViewNumber), tmp); } TemplPrint("tail"); } /**api* WwwViewPartI ********************************************************** ** ** Lets user create or edit a view, part I, which is the selection of ** the leaf and root libraries. ** ** INPUT: view number [R] ** flag whether to edit an existing view [R] ** */ void WwwViewPartI (INT4 viewNumber,INT4 isEdit) { TEMPLv templ; SLBo *lib; SLBoFIELD *field; SRSoGROUP *group; INT4 i,c1,c2,c3; INT4 numberOfViews; char *libName, *tmp; numberOfViews = ParGetNum("numberOfViews"); templ = WwwInit (); TemplWith (templ, "$viewCreate"); TemplPrint ("head"); if(!isEdit) TemplPrint("create.logo"); else ParDefNum("nascentViewN", viewNumber); TemplPrint("create.head",viewNumber,viewNumber,viewNumber,viewNumber); TemplPrint("rootHeader", viewNumber, ParGetStrF ("view%d_Name", viewNumber), viewNumber, WwwChecked (ParGetNumF ("view%d_isTable", viewNumber) || !ParIsDefinedF ("view%d_isTable", viewNumber)), viewNumber, viewNumber, WwwChecked (ParGetNumF ("view%d_isShortNames", viewNumber)), viewNumber); for(c1=0; (group = LibNextLibGroup(&c1)); ) { if( ! LibNofGroups(group) ) continue; TemplPrint("separator"); for(c2=0; (lib= LibNextLib(group,&c2)); ) { libName = LibGetName(lib,"full"); TemplPrint("rootLibsSelect",viewNumber,libName, ParGetNumF("v%d_R_%s",viewNumber,libName) ? "SELECTED" : "",libName); } } TemplPrint("rootTrailer"); TemplPrint("leafHeader"); for(c1=0; (group = LibNextLibGroup(&c1)); ) { if( !LibNofGroups(group) ) continue; TemplPrint("separator"); for(c2=0; (lib= LibNextLib(group,&c2)); ) { libName = LibGetName(lib,"full"); TemplPrint("leafLibsSelect",viewNumber,libName, ParGetNumF("v%d_L_%s",viewNumber,libName) ? "SELECTED" : "",libName); } } TemplPrint("leafTrailer"); } /**api* WwwEntryPrint ********************************************************* ** ** Prints a single entry in MANY different forms. ** ** INPUT: entry object [R] ** script object [W] ** IMPLICIT: ** ** RETURNS: */ void WwwEntryPrint (TEMPLv templ, ENTRYo *entry) { SLBoFEATURE *feature; SEQo *seq=NULL, *protseq=NULL; char *entryName, *libName; static int entryNum=0; TemplWith (templ, "$entry.inList"); if (ParGetBool ("printEntireEntry")){ /* print the complete entry */ EntryViewPrintEnvelope (entry, "head"); EntryPrint (entry); EntryViewPrintEnvelope (entry, "tail"); } else { /* entry within entry list */ entryName = EntryGetName (entry); libName = LibName (EntryGetLib (entry)); if (*ParGetStr ("userIdOpt")) TemplPrint ("entry.rootName", ++entryNum, EntryGetFullName (entry), libName, WwwTransform ("encode", entryName), EntryGetFullName (entry)); else TemplPrint ("entry.inListNoId", LibName (entry->lib), WwwTransform ("encode", entryName), libName, entryName); if (LibIsAnyFieldActive (libName)) { EntryViewPrintEnvelope (entry, "head"); ParDefBool ("isHTMLFormat", 1); EntryPrintFields (entry); EntryViewPrintEnvelope (entry, "tail"); } } TemplEndWith (); } /**api* WwwPrintHelpTopic ***************************************************** ** ** prints help topic ** ** INPUT: name of help topic [R] ** IMPLICIT: ** ** RETURNS: */ void WwwPrintHelpTopic (char *helpTopic) { TEMPLv templ; templ = TemplOpen ("SRSDB:general.it", NULL); TemplWith (templ, "$main.fields"); WwwPrintContentType (NULL); TemplPrint(helpTopic); TemplEndWith(); } /****** WwwLinkStat *********************************************************** ** ** ** */ INT4 WwwLinkStat (char *setName) { TEMPLv templ; SLBo *lib; SRSoGROUP *group; char queryStr[512], *libName; INT4 k=0, context1, context2, context3, doSkipLib, isSelected=0; Int4 entryN =0,linkLibsN =0; templ = TemplOpen ("SRSICA:srswww.i", NULL); WwwPrintContentType(NULL); WwwQueryRepeat (ParGetNum ("linkSetNumber")); TemplWith(templ,"$linkSet"); TemplPrint("head"); WwwPrintButtons (templ); TemplPrint("tableHead", setName); for (context1=0; (group = LibNextLibGroup (&context1));) for (context2=0; (lib = LibNextLib (group, &context2));) if (LibIs (lib, "linkTarget")) { TemplPrint("newRow"); doSkipLib=0; for (context3=0; (SetGetNextLibStat (setName, &libName, &context3));) if (SmEqs (lib->nam, libName)) doSkipLib = 1; /* don't link to libs contained in the set */ if (!doSkipLib) { isSelected = 1; linkLibsN++; TemplPrint("libName",linkLibsN,lib->nam,lib->nam); sprintf (queryStr, "%s > %s", setName, lib->nam); WwwQueryLinkDo(queryStr); sprintf (queryStr, "%s < %s", setName, lib->nam); WwwQueryLinkDo(queryStr); sprintf (queryStr, "%s ! (%s < %s)", setName, setName, lib->nam); WwwQueryLinkDo(queryStr); TemplPrint("endRow"); } } if (!isSelected) _ErrMsg2 (e__nolinklibselected, "LINK"); TemplPrint("tail",linkLibsN); TemplEndWith(); return k; } /****** WwwQueryLinkDo *************************************************** ** ** ** ** ** ** ** */ WwwQueryLinkDo(char *queryStr) { WWWoQUERY *query; Int4 entryN, k; k = WwwQueryDo (queryStr, "link"); if( k ) { query = WwwGetQuery(k); TemplPrint("libEntriesH",ParGetStr("userId"),k,query->entryN); WwwDelQuery(query); } else { TemplPrint("libEntries",0); } } /****** WwwWriteFile *************************************************** ** */ INT4 WwwWriteFile (char *formatStr, ...) { FILE *file; va_list ap; va_start (ap, formatStr); vfprintf (file, formatStr, ap); va_end (ap); if (formatStr[strlen (formatStr) -1] != '\n') fprintf (file, "\n"); return 1; } /****** WwwGrowQuery ********************************************************** ** ** new query string is constructed from the selected ** entry names from result page ** ** INPUT: query string [W] ** Entry name [R] ** */ void WwwGrowQuery(char *queryString, char *fullEntry) { static char oldLibName[30] =""; char entryName[30],libName[30]; if(!*fullEntry) _ErrMsg2 (i__invalidentry, fullEntry); sscanf(fullEntry,"%[^:]:%s",libName,entryName); if(!*queryString) { /* head part */ sprintf(queryString,"[%s-id:%s",libName,entryName); } else { /* tail parts */ if( SmEqs(oldLibName,libName)) sprintf(queryString,"%s | %s",queryString,entryName); else { sprintf(queryString,"%s] | [%s-id:%s",queryString,libName,entryName); } } strcpy(oldLibName,libName); } /****** WwwNextSelectedQuery ************************************************** ** ** Returns the number of the next query selected in the query manager. ** ** INPUT: the address of iterator (set to 0 to get the first) [W] ** address of pointer to the query name (or NULL) [W] ** ** RETURNS: the number of the next selected query. ** 0: no query was selected ** */ Int4 WwwNextSelectedQuery (Int4 *c, char **name) { static Int4 queryN=0; char *tmp; if (!*c) { *c = 1; queryN = ParGetNum ("numberOfQueries"); } else (*c)++; while (!*(tmp = ParGetStrF ("qmstr%d", *c)) && *c <= queryN) (*c)++; if (*c > queryN) return (*c = 0); if (name) *name = tmp; return (*c); } /****** WwwQuerySelectedEntries *********************************************** ** ** Make a set with selected entries from the query result page and ** do the query. ** ** RETURNS: the number of the resulting query/set ** 0: no entry was selected ** */ Int4 WwwQuerySelectedEntries () { char *entryName,queryString[5000]; Int4 i, entryN, queryN=0; queryString[0] ='\0'; for(i=1, entryN=0; i <= ParGetNum("viewEntriesChunkSize"); i++){ entryName = ParGetStrF("EntryNum_%d",i); if(*entryName) { WwwGrowQuery(queryString,entryName); entryN++; } } if (entryN) { sprintf(queryString,"%s]",queryString); queryN = WwwQueryDo(queryString,"query"); } return queryN; } /**api* WwwQueryPrint ******************************************************** ** ** Prints the page with the results of a query. The entry list can ** be printed either as a normal list or as a table. ** ** INPUT: the query number in the "query history" [R] ** */ void WwwQueryPrint (INT4 queryN) { WWWoQUERY *query; TEMPLv templ; Int4 startN=ParGetNum ("viewEntriesStartN"), chunkSize=ParGetNum ("viewEntriesChunkSize"); templ = WwwInit (); TemplWith (templ, "$queryResult"); TemplPrint ("head"); WwwPrintButtons (templ); /* get the query and print the header of result list*/ query = WwwGetQuery (queryN); TemplPrint ("title", WwwStringEncode (query->queryStr), query->entryN,query->entryN); TemplPrint ("options", queryN, chunkSize, queryN); TemplWith (templ, "selectView"); WwwPresentViewList ("current"); TemplEndWith (); TemplPrint ("entriesStart"); /* print entry list */ if (ParGetNum ("viewNumber")) WwwPrintSetView (templ, query->name, startN, chunkSize); else WwwPrintSet (templ, query->name, startN, chunkSize); WwwDelQuery (query); WwwPresentSkipChunkSet (templ, query->entryN, queryN); TemplPrint ("tail"); TemplEndWith (); } /****** WwwPrintSelectField *************************************************** ** ** Prints a field name in the list fields to be selected for view. ** ** INPUT: view object [R] ** number of view [R] ** field object [R] ** view library object [R] or NULL if field from root library ** number of columns per row [R] ** address of count of fields in the current row [R] ** */ void WwwPrintSelectField (VIEWo *view, Int4 viewNum, SLBoFIELD *field, VIEWoLIB *vlib, Int4 numCol, Int4 *count) { LIBoFieldFormat *format; char *fieldName,*tmp; Int4 c; fieldName = LibGetFieldName (field); if (LibIsField (field, "header")) { if (*count>0) TemplPrint ("newRow"); TemplPrint ("fieldHeader", numCol, fieldName); *count = 0; } else { if (!((*count)++ % numCol)) TemplPrint ("newRow"); if (vlib) /* field of leaf library */ TemplPrint ("field", viewNum, LibName (vlib->lib), fieldName, WwwChecked (ViewIsLeafField (view, vlib, field)), fieldName, fieldName, ""); else TemplPrint ("field", viewNum, fieldName, WwwChecked (ViewIsRootField (view, field)), fieldName, fieldName, ""); /* if field has format option print the menu with all options */ if (field->type->formatN) { if (vlib) { TemplPrint ("format.head", viewNum, LibName (vlib->lib), fieldName); for (c=0; (format=LibNextFieldFormat (field->type, &c));){ tmp = ParGetStrF("v%d_LF_%s_%s_format", viewNum, LibName (vlib->lib), fieldName); TemplPrint ("format.name",SmEqs(tmp,format->name) ? "SELECTED" : "", format->name); } } else { TemplPrint ("format.head", viewNum, fieldName); for (c=0; (format=LibNextFieldFormat (field->type, &c));){ tmp = ParGetStrF("v%d_RF_%s_format",viewNum,fieldName); TemplPrint ("format.name",SmEqs(tmp,format->name) ? "SELECTED" : "", format->name); } } TemplPrint ("format.tail"); } TemplPrint ("fieldTail"); } } /**api* WwwPrintSetView ******************************************************* ** ** Equivalent to WwwPrintSet (calls WwwPrintSet) but prints the list of ** entries using a view. ** ** INPUT: the template object [W] ** the query name [R] ** the start entry number [R] ** the chunk size [R] ** IMPLICIT: ** wwwView (VIEWo *) ** */ void WwwPrintSetView (TEMPLv templ, char *queryName, Int4 startN, Int4 chunkSize) { Int4 viewNo = 0; ParDefBool ("isHTMLFormat", 1); viewNo = ParGetNum("viewNumber"); if(!viewNo) viewNo = ParGetNum("numberOfViews"); wwwView = WwwViewGet (viewNo, templ); if (!WwwIsViewForQuery (wwwView, queryName)) { _ErrMsg3 (e__wwwnomatchingview, queryName, ViewGetName (wwwView)); WwwPrintSet (templ, queryName, startN, chunkSize); } else { ParDefBool ("isView", 1); ParSetVolatile ("isView"); if (ViewIsTable (wwwView)) { TemplWith (templ, "$entry.inTable"); WwwViewTableHeader (templ, wwwView); ParDefBool("isTable", 1); ParSetVolatile ("isTable"); } WwwPrintSet (templ, queryName, startN, chunkSize); if (ViewIsTable (wwwView)) { TemplPrint ("tail"); TemplEndWith (); } } ViewDelete (wwwView); } /****** WwwViewTableHeader **************************************************** ** ** Prints the header of the table containing a view of one or more ** entries. ** ** INPUT: template object [W] ** */ static void WwwViewTableHeader (TEMPLv templ, VIEWo *view) { SLBoFIELD *field; VIEWoLIB *vlib; Int4 m=0, k=0; TemplPrint ("head"); /* print table header/title of the root library ...*/ for (k=0; (vlib=ViewGetNextRootLib (view, &k));) TemplPrint ("title.library", LibName (vlib->lib)); for (k=0; (vlib=ViewGetNextRootLib (view, &k));) for (m=0; (field=ViewGetNextField (vlib, &m));) TemplPrint ("title.field", LibName (vlib->lib), LibGetFieldName (field), ViewIsShortNames (view) ? LibGetFieldShortName (field) : LibGetFieldName (field)); /* ... and view leaf fields names */ for (k=0; (vlib=ViewGetNextLeafLib (view, &k));) { TemplPrint ("title.library", LibName (vlib->lib)); if (!ViewLeafIsOnlyEntryN (vlib)) for(m=0; (field=ViewGetNextField (vlib, &m));) TemplPrint ("title.field", LibName (vlib->lib), LibGetFieldName (field), ViewIsShortNames (view) ? LibGetFieldShortName (field) : LibGetFieldName (field)); } TemplPrint ("title.tail"); } /****** WwwViewPrintEntryN *************************************************** ** ** Prints an entry view inside a table. ** ** INPUT: leaf object [R] ** the root entry object [R] ** number of rows to extend [R] ** ** RETURNS: number of fields printed for the entry */ static void WwwViewPrintEntryN (VIEWoLEAFSET *leaf, ENTRYo *entry, Int4 rowN) { char *viewName, *queryStr; Int4 viewN; viewName = ViewGetLeafView (leaf->vlib); viewN = *viewName ? ViewGetViewNumber (viewName) : 0; queryStr = ViewGetLeafQuery (leaf->vlib, entry); TemplPrint ("onlyEntryN", rowN, viewN, WwwTransform ("encode", queryStr), leaf->entryN); } /**api* WwwPrintSet *********************************************************** ** ** Prints a list of entries in various formats. ** ** INPUT: o template object [W] ** o name of set/query [R] ** o number of first entry to be printed, first is 1...if 0 ** then is set to 1 [R] ** o number of entries to print, if 0 then size of set is ** assumed [R] ** IMPLICIT: ** ** RETURNS: */ void WwwPrintSet (TEMPLv templ, char *setName, int firstN, int printN) { ENTRYo *entry; SETo *set; IDoENTRY id; char *tmp; INT4 setEntryN, k, lastN, moreN; if (!firstN) firstN = 1; set = SetGet (setName); setEntryN = SetSize (setName); if (!printN) printN = setEntryN; lastN = firstN + printN - 1; for (k=firstN; k <= lastN && k <= setEntryN; k++) { SetGetID (set, k, &id); entry = EntryOpen (&id); if (entry) { if (LibIs (entry->lib, "user")) chdir (_FilTempLN (ParGetStrF ("%sDirName", LibName (entry->lib)))); if(ParGetBool("isView")) EntryView (entry, wwwView); else WwwEntryPrint (templ, entry); EntryClose (&entry); } } } void WwwViewEntryNamePrint (VIEWo *view, ENTRYo *entry, Int4 entryNo, Int4 rowN, Int4 isRoot) { if (ViewIsTable (view)) { if (isRoot) TemplPrint ("rootName", rowN, entryNo, EntryGetFullName (entry), LibName (EntryGetLib (entry)), EntryGetName (entry), EntryGetName(entry)); else TemplPrint ("leafName", rowN, LibName(EntryGetLib(entry)), EntryGetName(entry), EntryGetName (entry)); } else { if (isRoot) TemplPrint ("rootName", entryNo, EntryGetFullName (entry), LibName (EntryGetLib (entry)), EntryGetName (entry), EntryGetFullName(entry)); else TemplPrint ("leafName", LibName(EntryGetLib(entry)), EntryGetName(entry), EntryGetFullName (entry)); } } /**api* WwwViewGet ************************************************************** ** ** Retrieves a view object from user context. The view number can ** be obtained by ViewGetViewNumber. Delete the object with ViewDelete. ** A view can also be logically deleted by user ** - check with ViewIsDeleted. ** ** INPUT: view number [R] * the template used for printing entries [R] ** ** RETURNS: view object ** ** */ VIEWo *WwwViewGet (INT4 viewN, TEMPLv templ) { VIEWo *view; VIEWoLIB *vlib; VIEWoFIELD *vfield; SLBo *lib; SLBoFIELD *field; SRSoGROUP *group; char *libName, *fieldName; INT4 c1,c2,c3; view = ViewNew (viewN, ParGetStrF ("view%d_Name", viewN)); ViewSetTemplate (view, templ); ViewSetEntryNamePrint (view, WwwViewEntryNamePrint); ViewSetEntryNamePrinting (view, 1); if (ParGetNumF("view%d_isTable", viewN)) ViewSetFormat (view, "table"); ViewSetUseShortNames (view, ParGetNumF ("view%d_isShortNames", viewN)); if (ParGetNumF ("ViewDeleted_%d", viewN)) ViewMarkDeleted (view); /* process root databanks */ for (c1=0; (group = LibNextLibGroup(&c1));) { for (c2=0; (lib = LibNextLib (group, &c2));) { if (ParGetNumF ("v%d_R_%s", viewN, LibName (lib))) { vlib = ViewAddRootLib (view, lib); for (c3=0; (field = LibNextField (lib, &c3));) { fieldName = LibGetFieldName (field); if (ParGetNumF ("v%d_RF_%s", viewN, fieldName)) { vfield = ViewAddRootField (view, LibFieldType (field)); ViewSetFieldFormat (vfield, ParGetStrF ("v%d_RF_%s_format", viewN, fieldName)); } } } } } /* process leaf databanks */ for (c1=0; (group = LibNextLibGroup (&c1));) { for (c2=0; (lib = LibNextLib (group, &c2));) { libName = LibGetName (lib, "full"); if (ParGetNumF ("v%d_L_%s", viewN, libName)) { vlib = ViewAddLeafLib (view, lib); ViewSetLeafQuery (vlib, ParGetStrF ("v%d_Lextra_%s_query", viewN, libName)); ViewSetLeafPrintN (vlib, ParGetNumF ("v%d_Lextra_%s_onlyEntryN", viewN, libName)); ViewSetLeafView (vlib, ParGetStrF ("v%d_Lextra_%s_view", viewN, libName)); for(c3=0; (field = LibNextField (lib, &c3));) { fieldName = LibGetFieldName (field); if(ParGetNumF("v%d_LF_%s_%s", viewN, libName, fieldName)) { vfield = ViewAddField (vlib, LibFieldType (field)); ViewSetFieldFormat (vfield, ParGetStrF ("v%d_LF_%s_%s_format", viewN, libName,fieldName)); } } } } } return view; } /**api* WwwQueryGetSet ******************************************************** ** ** This is SRSWWW's version of 'QueryGetSet' of the query module. ** The difference is that queries represented with names inside ** the query are evaluated by submitting the query associated to ** a set name. ** Evaluation of the overall query is a recursive process. ** */ INT4 WwwQuerySetGet () { WWWoQUERY *query; SLBo *lib; SETo *set; char name[132]; IargGetArgs ("name", name); if (!(set = SetGet (name))) { if ((lib = (SLBo *) LibObjByName ("library", name)) || SmEqs (name, "parent")) { set = SetNew (name, NULL); SetSetIsDB (set); } else if ((query = WwwGetQueryName (name))) { set = QueryRecursive (query->queryStr, name); } else _ErrExit2 (e__nosetorlib, name); } IcaReturn ("set", set); } /**api* WwwQueryDo ************************************************************ ** ** evaluates a query in a recursive way ...whenever a set name is ** encountered that set is reconstructed by repeating the ** associated query (if not already done). ** ** INPUT: query expression string [R] ** query type: "link", "query" [R] ** IMPLICIT: ** ** RETURNS: number of query in history if success ** 0 if not */ INT4 WwwQueryDo (char *queryStr, char *queryType) { static INT4 isInit=0; char queryName[80]; INT4 queryN=ParGetNum ("numberOfQueries"); if (!isInit) /* set SRSWWW's own function */ IcaSetFunction ("QuerySetGet", WwwQuerySetGet); sprintf (queryName, "Q%d", queryN + 1); if (Query (queryStr, queryName)) { WwwRegisterQuery (queryName, SetGetQueryStr (queryName), queryType); return queryN + 1; } return 0; } /**api* WwwQueryRepeat ******************************************************** ** ** Repeats a query already recorded in history which is identified ** by the query number. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: */ INT4 WwwQueryRepeat (INT4 queryN) { static INT4 isInit=0; WWWoQUERY *query=NULL; if (!isInit) /* set SRSWWW's own function */ IcaSetFunction ("QuerySetGet", WwwQuerySetGet); query = WwwGetQuery (queryN); Query (query->queryStr, query->name); WwwDelQuery (query); return 1; } /**api* WwwQueryExpression **************************************************** ** ** Evaluates a query expression and prints the result; ** ** INPUT: o the type of the result set: "expression", "query", ... [R] ** o the query string [R] ** IMPLICIT: ** ** RETURNS: */ void WwwQueryExpression (char *queryType, char *queryStr) { char *s; s= WwwTransform ("decode", queryStr); if (WwwQueryDo (s, queryType)) WwwQueryPrint (ParGetNum ("numberOfQueries")); else _ErrMsg2 (i__querynegative, queryStr); } /**api* WwwLinkSet ************************************************************ ** ** links a set from history to selected libraries using various options; ** ** INPUT: number of query to be linked [R] ** IMPLICIT: ** ** RETURNS: number of result query in history ** 0: no library was selected for linking */ Int4 WwwLinkSet (Int4 queryN) { QASoQUERY *qas; WWWoQUERY *query; SLBo *lib; SRSoGROUP *group; Int4 k, c1, c2; qas = QasNew (); QasInitLink (qas); query = WwwGetQuery (queryN); QasSetQueryToLink (qas, query->queryStr); WwwDelQuery (query); QasSetLinkType (qas, ParGetStr ("linkSetType")); QasSetTmpSetNum (qas, queryN); for (k=0, c1=0; (group = LibNextLibGroup (&c1));) for (c2=0; (lib = LibNextLib (group, &c2));) if (LibIs (lib, "linkTarget")) { QasSetLinkWith (qas, LibName (lib)); k++; } if (!k) { _ErrRet2 (e__nolinklibselected, "[S+L]"); return 0; } else queryN = WwwQueryDo (QasGetQueryString (qas), "link"); QasDelete (qas); return queryN; } /**api* WwwTransform ********************************************************* ** ** if a query string is put as parameter value in html script then ** <> chars are recognized as syntactic elements; ** ** INPUT: option "decode" and "encode" [R] ** string to be transformed [R] ** IMPLICIT: ** ** RETURNS: */ char *WwwTransform (char *option, char *s) { static char tmp[1000]; strcpy (tmp, s); if (option[0] == 'e') { SmSwapS (tmp, ">", ">"); SmSwapS (tmp, "<", "<"); SmSwapS (tmp, "+", "_PL_"); SmSwapS (tmp, " ", "_SP_"); } else { SmSwapS (tmp, ">", ">"); SmSwapS (tmp, "<", "<"); SmSwapS (tmp, "_PL_", "+"); SmSwapS (tmp, "_SP_", " "); } return tmp; } /**api* WwwRegisterQuery ****************************************************** ** ** records a query description as a list of parameters; ** these parameter's will be saved in the user file; ** ** INPUT: name of successful query [R] ** query expression [R] ** query type: "query", "link" ** IMPLICIT: ** ** RETURNS: */ void WwwRegisterQuery (char *queryName, char *queryStr, char *queryType) { char *libName, parName[80]; INT4 c, k, libN, queryN, entryN; entryN = SetSize (queryName); if ((SmEqs (queryType, "expression") || SmEqs (queryType, "query") || SmEqs(queryType,"link")) && entryN) { queryN = ParGetNum ("numberOfQueries"); ParDefNum ("numberOfQueries", ++queryN); sprintf (parName, "QueryStr%d", queryN); ParDefStr (parName, queryStr); sprintf (parName, "QuerySize%d", queryN); ParDefNum (parName, entryN); sprintf (parName, "QueryType%d", queryN); ParDefStr (parName, queryType); sprintf (parName, "isSubEntry%d", queryN); ParDefNum (parName, SetIsSubEntry (queryName)); sprintf(parName,"QueryDeleted_%d",queryN); /* added: Ramu */ ParDefNum(parName,ParGetNum(parName)); /* for query manager function */ sprintf(parName,"QueryComm%d",queryN); ParDefStr(parName,ParGetStr(parName)); for (c=0, k=1; (libN=SetGetNextLibStat (queryName, &libName, &c)); k++) { sprintf (parName, "QueryLibrary%d_%d", queryN, k); ParDefStr (parName, libName); sprintf (parName, "QueryLibraryN%d_%d", queryN, k); ParDefNum (parName, libN); } } } /**api* WwwDeleteQuery ****************************************************** ** ** deletes last query in history; ** ** INPUT: ** IMPLICIT: ** ** RETURNS: */ static void WwwDeleteQuery () { char parName[80]; INT4 queryN, k; queryN = ParGetNum ("numberOfQueries"); sprintf (parName, "QueryStr%d", queryN); ParDelete (parName); sprintf (parName, "QuerySize%d", queryN); ParDelete (parName); sprintf (parName, "QueryType%d", queryN); ParDelete (parName); sprintf (parName, "isSubEntry%d", queryN); ParDelete (parName); for (k=0; ; k++) { sprintf (parName, "QueryLibrary%d_%d", queryN, k); if (!ParDelete (parName)) break; /* no more items */ sprintf (parName, "QueryLibraryN%d_%d", queryN, k); ParDelete (parName); } ParDefNum ("numberOfQueries", --queryN); } /**api* WwwGetQueryName ********************************************************* ** ** Returns descriptor of query with specified name. ** ** INPUT: query name [R] ** IMPLICIT: ** ** RETURNS: query descriptor object */ WWWoQUERY *WwwGetQueryName (char *name) { INT4 queryN; if (!(sscanf (name, "Q%d", &queryN) || sscanf (name, "q%d", &queryN))) _ErrExit3 (e__objectunknown, "set", name); return WwwGetQuery (queryN); } /**api* WwwGetQuery *********************************************************** ** ** Creates a query object with all information about it from the user ** file - this object must be deleted with WwwDelQuery after use. ** ** INPUT: address of query object [W] ** IMPLICIT: ** ** RETURNS: */ WWWoQUERY *WwwGetQuery(int queryN) { WWWoQUERY *query; char parName[132]; int k; if (queryN > ParGetNum ("numberOfQueries")) { _ErrExit3 (e__objectunknown, "query" , "number?"); } query = malloc (sizeof (WWWoQUERY)); query->queryN = queryN; sprintf (query->name, "Q%d", queryN); sprintf (parName, "QueryStr%d", queryN); /* better copy query string since it will have to be encoded for printing on HTML and therefore needs some extraspace */ strcpy (query->queryStr, ParGetStr (parName)); sprintf(parName,"QueryComm%d",queryN); strcpy(query->comment,ParGetStr(parName)); sprintf (parName, "QuerySize%d", queryN); query->entryN = ParGetNum (parName); sprintf (parName, "QueryType%d", queryN); query->type = ParGetStr (parName); sprintf (parName, "isSubEntry%d", queryN); query->isSubEntry = ParGetBool (parName); sprintf(parName, "QueryDeleted_%d",queryN); query->isDeleted = ParGetNum(parName); for (k=0;; k++) { sprintf (parName, "QueryLibrary%d_%d", queryN, k+1); if (!*(query->lib[k].name = ParGetStr (parName))) break; sprintf (parName, "QueryLibraryN%d_%d", queryN, k+1); query->lib[k].entryN = ParGetNum (parName); } query->lib[k].entryN = 0; /* end marker ..."name" is also NULL! */ return query; } /**api* WwwDelQuery ********************************************************* ** ** Deletes a query object created with WwwGetQuery or WwwGetQueryName. ** ** INPUT: address of query object [W] ** */ void WwwDelQuery (WWWoQUERY *query) { if (query) free (query); } void WwwPrintValue (char *libName, char *fieldName, char *value, Int4 n, Int4 entryN) { TemplPrint ("value", n, libName, fieldName, value, fieldName, libName, fieldName, WwwTransform ("encode", value), value, entryN); } /**api* WwwParRead *********************************************************** ** ** reads parameters from user-context file ** ** INPUT: userID [R] ** true if failure to read parameter file is fatal; ** IMPLICIT: ** ** RETURNS: */ void WwwParRead (char *userId, INT4 doInsist) { INT4 rv; if (!userId || !*userId) { if (doInsist) _ErrExit (e__filnotok); else return; } rv = ParRead (WwwGetName (userId, "context")); if (_ErrIs (rv) && doInsist) _ErrExit (rv); } /**api* WwwParWrite *********************************************************** ** ** reads parameters from user-context file ** ** INPUT: userID [R] ** IMPLICIT: ** ** RETURNS: */ void WwwParWrite (char *userId) { ParSave (WwwGetName (userId, "context")); } /**api* WwwNewUserId *********************************************************** ** ** reads parameters from user-context file ** ** INPUT: userID [R] ** IMPLICIT: ** ** RETURNS: */ char *WwwNewUserId () { static char userId[80]; char tmp1[30]; char tmp2[30]; char *remoteAddr = getenv ("REMOTE_ADDR"), *dirName, command[255]; if (!remoteAddr) remoteAddr = "local"; ParDefStr("remoteAddress",remoteAddr); SmRemoveChar(remoteAddr,'.'); LibBaseConv(atoi(remoteAddr),60,tmp1); LibBaseConv(TimeGet(),60,tmp2); sprintf (userId, "%s%s",tmp1, tmp2 ); dirName = WwwGetName (userId, "directory"); if (mkdir (dirName, 00777) != 0) _ErrExit2 (e__filnotok, dirName); sprintf (command, "chmod 777 %s", dirName); system (command); ParDefStr ("userId", userId); return userId; } /**api* WwwFileName ********************************************************** ** ** returns a file or directory name ** ** INPUT: userID [R] ** option: "context", "directory" [R] ** IMPLICIT: ** ** RETURNS: file name */ char *WwwGetName (char *userId, char *option) { static char name[255], rootDirName[80]="SRSWWWTMP"; switch (tolower (option[0])) { case 'c': /* context */ sprintf (name, "%s/%s/user.par", rootDirName, userId); break; case 'd': /* directory */ sprintf (name, "%s/%s", rootDirName, userId); break; default: _ErrExit2 (e__unknownoption, option); } return _FilLN (name); } /**api* WwwGetIdParam ********************************************************* ** ** builds the Id parameter for calling wgetz via command line ** ** INPUT: ** IMPLICIT: ** ** RETURNS: parameter for command line */ char *WwwGetIdParam () { static char parStr[80]; char *userId; userId = ParGetStr ("userId"); if (!userId || !*userId) { parStr[0] = '\0'; return parStr; } else { sprintf (parStr, "-id+%s+", userId); return parStr; } } /**api* WwwGetODDFile ********************************************************* ** ** Gets, if available, the ODD file for the library; ** ** INPUT: ** IMPLICIT: ** ** RETURNS: */ void WwwGetODDFile (char *libName) { #ifdef xxx SLBo *lib; FILEo file; INT4 rv; char fileName[132]; if (SmEqs (libName, "hyperlink")) strcpy (fileName, "SRSICA:hyperlink.sdl"); else { if (!(lib = (SLBo*) LibObjByName ("library", libName))) _ErrExit3 (e__objectunknown, "library", libName); if (*lib->oddfile) sprintf (fileName, "SRSICA:%s", lib->oddfile); else return; } rv = FilUOpen (&file, fileName, 255, 0); _ErrExit2 (rv, fileName); printf ("
    ");
      do {
        fputs (WwwStringEncode (file.ln), stdout);
        rv = FilURead (&file);
      }
      while (rv != e__eof);
      printf ("
    "); FilUClose (&file); #endif } /***LibBaseConv************************************************************* ** Author: Chenna Ramu ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387372 ** Email: chenna@embl-heidelberg.de ** ** Base Conversion to any base less than the number of characters ** available in symbol table. ** ** ** INPUT: num : Decimal number to be converted ** base : ** temp : converted number as string ** */ int LibBaseConv( int num, int base,char temp[]) { char abuf[]={"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvxyz" }; Int4 i = 0, r = 0, iret = 0; temp[0] = '\0'; /* LibShuffleBuff(abuf); */ if (base > strlen(abuf) ) { _ErrMsg2 (e__illegalbaseconv,strlen(abuf)+1); base = strlen(abuf); /* assume the maximum possible base */ } for(i=0; num >= base; i++) { r = num%base; iret = iret + LibPower(10,i) * r; num = (num-r)/base ; temp[i] = abuf[r]; } iret = iret + LibPower(10,i) * num; temp[i] = abuf[num]; temp[i+1] = '\0'; LibRevStr(temp); return (iret); } /** LibPower ************************************************* ** ** ** ** raise base to the power n and return the result ** ** **/ INT4 LibPower(int base, int n) { int i = 0; for( i = 1; n > 0; --n) i = i * base; return i; } /** LibRevStr ******************************************************************* ** ** ** ** Reverse given string ** ** ** **/ void LibRevStr(char s[]) { int c,i,j; for(i=0, j = strlen(s)-1; i = setSize) return; /* do not show skip set when there is only one result page */ if( !startN) startN = 1; TemplWith (templ, "$chunkSet"); TemplPrint ("head", WwwGetIdParam(),queryN, chunkSize,ParGetNum("viewNumber")); if( ParGetNum("viewEntriesStartN") > windowSize * chunkSize) chunkStart = startN/chunkSize; if( chunkStart-5 > 0) /* slide window size */ chunkStart = chunkStart - 5 ; for( k=chunkStart; k < windowSize+chunkStart+5 ; k++) { if( (k*chunkSize+1) > setSize) break; if (startN == (k*chunkSize+1)) TemplPrint ("current",WwwGetIdParam(),queryN,k*chunkSize+1, (setSize < chunkSize) ? setSize:chunkSize, ParGetNum("viewNumber"),k+1); else TemplPrint ("other", WwwGetIdParam(), queryN,k*chunkSize+1, (setSize < chunkSize) ? setSize:chunkSize, ParGetNum("viewNumber"),k+1); } if( chunkEnd < 1 ) chunkEnd = 1; TemplPrint ("tail", WwwGetIdParam(),queryN,chunkEnd, (setSize < chunkSize) ? setSize:chunkSize,ParGetNum("viewNumber")); TemplEndWith (); } /**api* WwwIsViewForQuery **************************************************** ** ** Determines if the view is really suitable for a particular query. ** If the query has elements from more than one databank then all of ** these must be root libraries in the view. ** ** INPUT: the view object [R] ** the query object [R} ** IMPLICIT: ** ** RETURNS: 1: view is suitable ** 0: not */ static Int4 WwwIsViewForQuery (VIEWo *view, char *setName) { VIEWoLIB *vlib; char *libName; Int4 isFound, c, h, n; for (c=0; (n = SetGetNextLibStat (setName, &libName, &c));) { for (h=0, isFound=0; (vlib = ViewGetNextRootLib (view, &h));) if (libName == LibName (vlib->lib)) isFound++; if (!isFound) return 0; } return 1; } /**api* WwwPresentChunkSizes ************************************************** ** ** Prints the chunk sizes for listing and viewing entries; ** ** INPUT: script object [R] ** IMPLICIT: ** ** RETURNS: */ Int4 WwwPresentChunkSizes (TEMPLv templ) { INT4 viewChunk[20] = {5, 10, 20, 30, 40, 50, 100, 200, 500, 1000, 2000, 0}, viewChunkCurr = ParGetNum ("viewEntriesChunkSize"), k; TemplPrint("head"); for (k=0; viewChunk[k]; k++) { TemplPrint ("size", viewChunk[k] == viewChunkCurr ? "SELECTED" : "", viewChunk[k]); } TemplPrint("tail"); } /**api* WwwPresentChunkSizesMime ********************************************** ** ** prints the chunk sizes for exporting entries; ** ** INPUT: script object [R] ** IMPLICIT: ** ** RETURNS: */ void WwwPresentChunkSizesMime (TEMPLv templ) { char *viewBlock; INT4 viewStartN, viewEndN; INT4 numberOfBlocks; INT4 mimeChunks[10] = {10, 20, 50, 100, 200, 500, 1000, 2000, 0}, numberOfEntries = ParGetNum("numberOfEntries"), mimeStartN = ParGetNum ("viewEntriesStartN"), mimeChunkSize = ParGetNum ("viewEntriesChunkSize"), k; viewBlock = ParGetStr("viewEntriesBlock"); if( *viewBlock) { sscanf(viewBlock,"%d - %d",&viewStartN,&viewEndN); } if(numberOfEntries > mimeChunkSize) numberOfBlocks = numberOfEntries/mimeChunkSize; TemplWith(templ,"mime"); TemplPrint("head"); for(k=0; k < numberOfBlocks; k++) { TemplPrint("size", viewStartN == ((k*mimeChunkSize)+1) ? "SELECTED" : "", k*mimeChunkSize+1,(k+1)*mimeChunkSize ); } if( numberOfEntries%mimeChunkSize) TemplPrint("size", viewStartN == ((k*mimeChunkSize)+1) ? "SELECTED" : "", k*mimeChunkSize+1,numberOfEntries); TemplPrint("tail"); TemplEndWith(); } /**api* WwwSetColorScheme ***************************************************** ** ** Sets the color scheme for the current page. The color is specified ** by the parameter "wwwColorScheme" ** */ void WwwSetColorScheme (TEMPLv templ) { char *color, tmp[200]; color = ParGetStr ("wwwColorScheme"); if (color && *color && !(SmEqs (color, "plain"))) { TemplWith (templ, "$colorScheme"); TemplWith (templ, color); ParDefStr ("pageColor", TemplSPrint (tmp, "page")); ParDefStr ("cellColor", TemplSPrint (tmp, "cell")); ParSetVolatile ("pageColor"); ParSetVolatile ("cellColor"); TemplEndWith (); TemplEndWith (); } } /* ought to disappear soon */ void WwwPresentColorMenu () { char *color, *colorSelected; struct VARo *any, *tmp; Int4 k; colorSelected = ParGetStr ("wwwColorScheme"); if (!*colorSelected) colorSelected = "plain"; TemplPrint ("head"); any = TemplExists (NULL, "$colorScheme"); for (k=0; (tmp = VarNextInList (any, &k));) { color = VarGetName (tmp); TemplPrint ("color", SmEqs (colorSelected, color) ?"SELECTED" :"", color); } TemplPrint ("tail"); } TEMPLv WwwInit () { TEMPLv templ; templ = TemplOpen ("SRSICA:srswww.i", NULL); WwwSetColorScheme (templ); WwwPrintContentType(NULL); return templ; } typedef struct WWWoQUERY { char name[80]; char queryStr[5000]; char comment[300]; char *type; INT4 entryN; INT4 queryN; INT4 isSubEntry; struct { char *name; int entryN; } lib[20]; char linkLib[30]; char linkType[30]; int isDeleted; } WWWoQUERY; #ifndef _ENTRYo typedef struct ENTRYo *dummytointroducestructtagENTRYo; #endif #ifndef _SCRIPTo typedef struct SCRIPTo *dummytointroducestructtagSCRIPTo; #endif /* parameters, userId, messages */ INT4 WwwPrintMessage (MSGo *msg); char *WwwReadInput (int byteN, char *fileName); INT4 WwwParInput (int byteN, char *buff); void WwwParWrite (char *userId); void WwwParRead (char *userId, INT4 doInsist); char *WwwNewUserId (); char *WwwGetName (char *userId, char *option); INT4 WwwPrintF (char *formatStr, ...); INT4 WwwLinkSet (Int4 queryN); /*void WwwLinkToLibs (char *queryStr);*/ void WwwLibInfo (char *libName, char *userId); void WwwLinkInfo (TEMPLv templ, char *libName1, char *libName2); void WwwPrintHelpTopic (char *helpTopic); void WwwDoBlastSearch (); void WwwQueryExpression (char *queryType, char *queryStr); void WwwListIndex (char *userId); void WwwGetMessage (); void WwwSendMessage (); void WwwPrintLinkOptions (char *query); void WwwPrintLibNetwork (); void WwwGetODDFile (char *libName); /* retrieval, query */ void WwwInitRetrieve (); INT4 WwwQueryDo (char *expr, char *queryType); char *WwwRetrieve (); INT4 WwwQueryDoRecursive (INT4 queryN, char *queryStr); void WwwRegisterQuery (char *queryName, char *queryStr, char *queryType); struct WWWoQUERY *WwwGetQuery (int queryN); struct WWWoQUERY *WwwGetQueryName (char *name); void WwwDelQuery (struct WWWoQUERY *query); char *WwwTransformQuery (char *option, char *queryStr); /* others */ void WwwEntryPrint (struct TEMPLo *templ, ENTRYo *entry); char *WwwGetIdParam (); void WwwViewFeature (char *queryStr, INT4 subEntryN); char *WwwStringEncode (char *); char *WwwTransform (char *option, char *str); /* helpers for printing HTML pages */ TEMPLv WwwInit (); INT4 WwwPresentChunkSizes (struct TEMPLo *templ); void WwwPresentChunkSizesMime (struct TEMPLo *templ); void WwwPrintButtons (struct TEMPLo *templ); char *WwwChecked (Int4 flag); char *WwwSelected (Int4 flag); /* printing entries */ void WwwPrintSet (struct TEMPLo *templ, char *setName, int firstN, int printN); void WwwPrintSetView (struct TEMPLo *templ, char *setName, int firstN, int printN); void WwwQueryPrint (INT4 queryN); void WwwPrintValue (char *libName, char *fieldName, char *value, Int4 n, Int4 entryN); /* dealing with views */ struct VIEWo *WwwViewGet (INT4 viewN, struct TEMPLo *templ); void WwwPrintSelectField (struct VIEWo *view, Int4 viewNum, struct SLBoFIELD *field, struct VIEWoLIB *vlib, Int4 numCol, Int4 *count); void WwwPresentViewList (); void WwwPresentViewsForLibs (struct SRSoGROUP *group); void WwwPresentViewsForLeaf (struct VIEWo *view, struct VIEWoLIB *vlib); void WwwViewPartI (INT4 viewNumber,INT4 isEdit); void WwwSetColorScheme (struct TEMPLo *templ); *********************************** ** ** MODULE for management of virtually-copied strings ** ** Authors: Giorgio Verde ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: verde@embl-heidelberg.de ** *************************************************************************/ #include #include #include #include #include #include "def.h" #include "strv.h" #define DEBUGNOT static Int4 strAllocN, strAllocByte, strFreedN, strFreedByte; /****** StrBufNew ********************************************************* ** ** Creates a STRv buffer with space for a string of lenght dim ** The string length must be manually set by the user ** ** INPUT: the maximum lenght of the contained string ** RETURNS: a new STRv with the uninitialized buffer */ STRv StrBufNew(int dim) { STRv s=(STRv)malloc(sizeof(STRo)+dim); #ifdef DEBUG strAllocByte += dim; strAllocN++; if (!(strAllocN%10000)) fprintf (stderr, "allocN: %d, allocByte: %d, freedN, %d, freedByte: %d\n", strAllocN, strAllocByte, strFreedN, strFreedByte); #endif s->usage=1; s->dim=dim; /*printf("allocated:%d\n",dim);*/ return s; } /****** StrBufChange ********************************************************* ** ** Vanilla function for string modification ** Moves all characters of the string after position beg ("cut" position) ** to position end ("paste" position) **
    if end>beg this results in the creation of space for end-beg ** characters in position beg **
    if end a new STRv buffer is created only if: **
    - the STRv buffer has usage>1 (2 or more STRv's share a virtual copy) **
    - the STRv buffer needs to be grown ** ** INPUT: the pointer to the STRv to be modified ** the cut position ** the paste position */ void StrBufChange(STRv* val, int beg, int end) { STRv s=*val; int len=s->len; int dlen=end-beg; if (s->dimusage>1) { STRv old=s; s=StrBufNew(len+dlen); memcpy(s->arr+end, old->arr+beg, len-beg+1); if (dlen>0) memcpy(s->arr, old->arr, beg); else memcpy(s->arr, old->arr, end); StrDel (old); } else memmove(s->arr+end, s->arr+beg, len-beg+1); s->len=len+dlen; *val=s; } #define STRTEMP_NUM 10 STRo StrNULLObj = { 1+STRTEMP_NUM, 0, 1, '\0' }; STRv StrNULL=&StrNULLObj; STRv StrTemporary[STRTEMP_NUM]= { &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj, &StrNULLObj }; /**API* StrNew ********************************************************* ** ** Creates a new STRv containing the empty string (virtually copied) **
    See STRv creators: StrNew, StrCpy, StrCpyS, StrTemp ** ** RETURNS: a new STRv */ STRv StrNew() { return StrCpy(StrNULL); } /**API* StrCpy ********************************************************* ** ** creates a new STRv containing a ** virtual copy of the given STRv **
    See STRv creators: StrNew, StrCpy, StrCpyS, StrTemp ** ** INPUT: a STRv (can be NULL) ** RETURNS: a copy of input ** NULL if input is NULL */ STRv StrCpy(STRv val) { if (val) val->usage++; return val; } /**API* StrDel ********************************************************* ** ** Deletes a STRv (a virtual copy of the value). ** If the given STRv was the only instance of the value in ** use, the value buffer is freed. ** Must be used whenever an assigned STRv goes out of scope ** ** INPUT: a STRv (can be NULL) */ void StrDel(STRv val) { if (val && !--(val->usage)) { /* printf("freed:%s\n",&val->arr);*/ #ifdef DEBUG strFreedByte += val->dim; strFreedN++; #endif free(val); } } /**API* StrGrow ********************************************************* ** ** Reserves space so that following operations on the STRv ** can modify it's value to a longer string. This is just ** an optimization, as STRv's grow automatically if the ** value lenght exceeds the allocated buffer **
    See STRv optimizers: StrGrow, StrTrim ** ** INPUT: o [W] pointer to the STRv to be grown ** o the number of characters to be reserved for growth */ void StrGrow(STRv* val, int dlen) { STRv s=*val; int len=s->len; if (s->dimusage>1) { STRv old=s; s=StrBufNew(len+dlen); s->len=len; memcpy(s->arr, old->arr, len+1); if (!--(old->usage)) { #ifdef DEBUG strFreedByte += old->dim; strFreedN++; #endif free(old); } *val=s; } } /**API* StrTrim ********************************************************* ** ** Optimizes the value buffer to have exactly the lenght ** needed to contain the string value ** See STRv optimizers: StrGrow, StrTrim ** ** INPUT: [W] pointer to the STRv to be trimmed */ void StrTrim(STRv* val) { STRv s=*val; int len=s->len; if (s->dim>len) { STRv old=s; s=StrBufNew(len); s->len=len; memcpy(s->arr, old->arr, len+1); #ifdef DEBUG strFreedByte += old->dim; strFreedN++; #endif free(old); *val=s; } } /**API* StrClear ********************************************************* ** ** if the STRv buffer is unique, resets the content of the STRv to ** "" without freeing the buffer ** ** INPUT: [W] the STRv to be cleard */ void StrClear(STRv* sp) { STRv s=*sp; if (s->usage==1) { s->len=0; s->arr[0]='\0'; } else StrSet(sp, StrNULL); } /* operations */ /**API* StrSet ********************************************************* ** ** Assignes to one STRv the value of another STRv (virtual copy) ** The old value of the STRv is released **
    See STRv modifiers: StrSet, StrIns, StrApp, StrAdd, StrCut **
    To assign instead a char* value, see StrSetS ** ** INPUT: o [W] pointer to the STRv to be modified ** o STRv value to be assigned */ void StrSet(STRv* dest, STRv src) { if (*dest!=src) { StrDel(*dest); *dest=StrCpy(src); } } /**API* StrIns ********************************************************* ** ** Inserts in one STRv the value of another STRv at the beginning ** of the string. The destination STRv buffer is grown if needed. ** The old value of the STRv is released **
    See STRv modifiers: StrSet, StrIns, StrApp, StrAdd, StrCut **
    To insert instead a char* value, see StrInsS ** ** INPUT: o [W] pointer to the STRv to be modified ** o STRv value to be inserted */ void StrIns(STRv* dest, STRv src) { int len=src->len; StrBufChange(dest, 0, len); memcpy((*dest)->arr, src->arr, len); } /**API* StrApp ********************************************************* ** ** Appends to one STRv the value of another STRv. ** The destination STRv buffer is grown if needed. ** The old value of the STRv is released **
    See STRv modifiers: StrSet, StrIns, StrApp, StrAdd, StrCut **
    To append instead a char* value, see StrAppS ** ** INPUT: o [W] pointer to the STRv to be modified ** o STRv value to be appended */ void StrApp(STRv* dest, STRv src) { int dlen=(*dest)->len; int len=src->len; StrBufChange(dest, dlen, dlen+len); memcpy((*dest)->arr+dlen, src->arr, len); } /**API* StrAdd ********************************************************* ** ** Inserts in one STRv the value of another STRv at a certain ** position. The position must be between 0 (works like StrIns) ** and the lenght of the string (works like StrApp). If outside ** this range, a PosOutOfBounds exception is thrown. ** The destination STRv buffer is grown if needed. ** The old value of the STRv is released **
    See STRv modifiers: StrSet, StrIns, StrApp, StrAdd, StrCut **
    To append instead a char* value, see StrAddS ** ** INPUT: o [W] pointer to the STRv to be modified ** o the position of insertion. ** o STRv value to be added */ void StrAdd(STRv* dest, int pos, STRv src) { int dlen=(*dest)->len; int len=src->len; ASSERT(pos<=dlen, PosOutOfBounds); StrBufChange(dest, pos, pos+len); memcpy((*dest)->arr+pos, src->arr, len); } /**API* StrCut ********************************************************* ** ** Cuts in one STRv the characters starting at a certain ** position and for a given lenght. ** The position must be between 0 and the length of the string. ** If outside this range, a PosOutOfBounds exception is thrown. ** The given length can be longer then the length of the string; ** in that case it is adjusted to the string length ** The destination STRv buffer keeps its lenght, and must be ** explicitly trimmed with StrTrim if needed. ** The old value of the STRv is released **
    See STRv modifiers: StrSet, StrIns, StrApp, StrAdd, StrCut ** ** INPUT: o [W] pointer to the STRv to be modified ** o the cutting position ** o the cutting length */ void StrCut(STRv* dest, int pos, int len) { int dlen=(*dest)->len; ASSERT(pos<=dlen, PosOutOfBounds); if (len>dlen-pos) len=dlen-pos; StrBufChange(dest, pos+len, pos); } /**API* StrSub ********************************************************* ** ** creates a new STRv containing a ** substring of the given STRv **
    See STRv creators: StrNew, StrCpy, StrCpyS, StrTemp ** ** INPUT: a STRv ** the postition of the substring ** the length of the substring ** RETURNS: the substring */ STRv StrSub(STRv s, int pos, int len) { if (pos>s->len) pos=s->len; if (pos+len>s->len) len=s->len-pos; return StrNCpyS(s->arr+pos, len); } /**API* StrRight ********************************************************* ** ** creates a new STRv containing the characters of the given STRv ** on the right of the given position (including the one at the position) **
    See STRv creators: StrNew, StrCpy, StrCpyS, StrTemp ** ** INPUT: a STRv ** the cut position ** RETURNS: the substring */ STRv StrRight(STRv s, int pos) { if (pos>s->len) pos=s->len; return StrNCpyS(s->arr+pos, s->len-pos); } /**API* StrLeft ********************************************************* ** ** creates a new STRv containing the characters of the given STRv ** on the left of the given position (excluding the one at the position) **
    See STRv creators: StrNew, StrCpy, StrCpyS, StrTemp ** ** INPUT: a STRv ** the cut position ** RETURNS: the substring */ STRv StrLeft(STRv s, int pos) { if (pos>s->len) pos=s->len; return StrNCpyS(s->arr, pos); } /**API* StrSubst ********************************************************* ** ** Substitutes a range of characters in one STRv in a given ** position and of a certain lenght with the value of a given STRv. ** ** ** INPUT: o [W] pointer to the STRv to be modified ** o position of replacement (0<=pos<=len) ** o num char to replace in the original string ** if bigger, it's adjusted to string lenght ** o value to replace */ void StrSubst(STRv* dest, int pos, int len, STRv subst) { int dlen=(*dest)->len; int slen=subst->len; ASSERT (pos<=dlen, PosOutOfBounds); if (len>dlen-pos) len=dlen-pos; StrBufChange(dest, pos+len, pos+slen); memcpy((*dest)->arr+pos, subst->arr, slen); } /**API* StrDebug ********************************************************* ** ** Debug function to print the status of a STRv on stdout ** ** INPUT: the STRv to be displayed */ void StrDebug(STRv s) { printf("STRv:%p ", s); if (s) { char *p=s->arr, *stop; if (s->usage!=1) printf("usage:%d ", s->usage); printf("len:%d ", s->len); if (s->dim!=s->len) printf("grow:%d ",s->dim-s->len); /* check if the string is printable stop=p+s->len; while (parr; char c; if (s->usage==1) { while (c=*p) *p++=_toupper(c); } else { STRv d=StrBufNew(s->len); char* dp=d->arr; d->len=s->len; while (c=*p++) *dp++=_toupper(c); s->usage--; *sp=d; } } /**API* StrLower ********************************************************* ** ** Converts a STRv into lower case ** ** INPUT: a ponter to STRv */ void StrLower(STRv* sp) { STRv s=*sp; char* p=s->arr; char c; if (s->usage==1) { while (c=*p) *p++=_tolower(c); } else { STRv d=StrBufNew(s->len); char* dp=d->arr; d->len=s->len; while (c=*p++) *dp++=_tolower(c); s->usage--; *sp=d; } } /* queries */ /**API* StrEmpty ********************************************************* ** ** returns if the string is empty ** ** ** INPUT: the STRv (must be not NULL) ** RETURNS: TRUE if the STRv is the empty string */ BOOL StrEmpty(STRv str) { return !str->len; } /**API* StrLen ********************************************************* ** ** returns the length of the string value ** ** ** INPUT: the STRv (must be not NULL) ** RETURNS: length in chars */ int StrLen(STRv str) { return str->len; } /**API* StrEqual ********************************************************* ** ** compares 2 STRv's for equal values ** ** ** INPUT: o STRv (must be not NULL) ** o STRv (must be not NULL) ** RETURNS: TRUE if equal */ BOOL StrEqual(STRv s1, STRv s2) { if (s1==s2) return TRUE; else if (s1->len==s2->len) return strcmp(s1->arr, s2->arr)==0; else return FALSE; } /**API* StrCmp ********************************************************* ** ** compares 2 STRv's for lexicographic ordering ** ** ** INPUT: o s1:STRv (must be not NULL) ** o s2:STRv (must be not NULL) ** RETURNS: o <0 if s10 if s1>s2 */ int StrCmp(STRv s1, STRv s2) { if (s1==s2) return 0; else return strcmp(s1->arr, s2->arr); } /**API* StrHash ********************************************************* ** ** calculates a hash value for a STRv. ** ** ** INPUT: o STRv (must be not NULL) ** o upper bound for the result ** RETURNS: an integer 0<= i < max */ int StrHash(STRv val, int max) { return StrHashS(val->arr, max); } /* user */ /**API* StrConst ********************************************************* ** ** Defines a STRv value to become a constant to be never released. ** The returned char* cannot be used for modifying the string, ** and it is guaranteed to be stable. ** ** INPUT: STRv (must be not NULL) ** RETURNS: the STRv value as char* */ char* StrConst(STRv val) { val->usage++; return val->arr; } /**API* StrVal ********************************************************* ** ** Returns a C string containing a (real) copy of the STRv value ** The user can do everything with it and has the reponsability ** of freeing it. ** ** INPUT: STRv (must be not NULL) ** RETURNS: the STRv value as char* */ char* StrVal(STRv val) { int len=val->len+1; char* s=malloc(len); memcpy(s, val->arr, len); return s; } /**API* StrGet ********************************************************* ** ** Writes the STRv value into an allocated C char buffer of a ** given size. If there is enough space in the buffer, string ** will be NULL-terminated, else only the portion which fits ** is copied. ** ** INPUT: o [W] the pointer to the buffer ** o the length of the buffer ** o the STRv to be copied (must be not NULL) ** RETURNS: o a pointer to the first unused char in the buffer ** if the value fitted ** o NULL otherwhise */ char* StrGet(char* dest, int sz, STRv src) { int len=src->len+1; if (len<=sz) { memcpy(dest, src->arr, len); return dest+len; } else { memcpy(dest, src->arr, sz); return NULL; } } /* c string operations */ /**API* StrTemp ********************************************************* ** ** Creates a temporary STRv from a C string. This STRv does'nt ** need to be deleted with StrDel, but the user is not entitled ** to perform modifying operations on this string ** (for example StrAppS(&StrTemp("bla"),"alb") is unlegal) ** Basically, the only legal operation is to use StrTemp where ** the STRv is not modified. ** The maximum number of active temporary STRv is defined by ** the macro STRTEMP_NUM ** ** INPUT: a pointer to a C string ** RETURNS: a temporary STRv */ STRv StrTemp(char* src) { static int currTemp=0; STRv* s=&StrTemporary[currTemp]; StrSetS(s, src); currTemp=(currTemp+1)%STRTEMP_NUM; return *s; } /**API* StrCpyS ********************************************************* ** ** Creates a new STRv from a C string (char*) ** ** INPUT: the C string ** RETURNS: a STRv */ STRv StrCpyS(char* src) { int len=strlen(src); STRv s=StrBufNew(len); s->len=len; memcpy(s->arr, src, len+1); return s; } /**API* StrSetS ********************************************************* ** ** Assignes to a STRv the value of a C string (char*) ** The old value of the STRv is released ** ** INPUT: [W] pointer to the STRv to be assigned ** the C string */ void StrSetS(STRv* dest, char* src) { int len=strlen(src); int dlen=(*dest)->len; StrBufChange(dest, dlen, len); memcpy((*dest)->arr, src, len+1); } /**API* StrInsS ********************************************************* ** ** Inserts at the beginning of a STRv the value of a C string (char*) ** The old value of the STRv is released ** ** INPUT: [W] pointer to the STRv to be assigned ** the C string */ void StrInsS(STRv* dest, char* src) { int len=strlen(src); StrBufChange(dest, 0, len); memcpy((*dest)->arr, src, len); } /**API* StrAppS ********************************************************* ** ** Appends to a STRv the value of a C string (char*) ** The old value of the STRv is released ** ** INPUT: [W] pointer to the STRv to be assigned ** the C string */ void StrAppS(STRv* dest, char* src) { int dlen=(*dest)->len; int len=strlen(src); StrBufChange(dest, dlen, dlen+len); memcpy((*dest)->arr+dlen, src, len); } /**API* StrAppN ********************************************************* ** ** Appends to a STRv a given number of chars of a C string (char*) ** if the string is shorter, then the number of chars is the length ** of the source string ** The old value of the STRv is released ** ** INPUT: [W] pointer to the STRv to be assigned ** the C string ** the number of chars */ void StrAppN(STRv* dest, char* src, int len) { int dlen=(*dest)->len; /* copy until \0 is found */ char* p=src; while (parr+dlen, src, len); } /**API* StrAddS ********************************************************* ** ** Inserts in a STRv the value of a C string (char*) at ** a given position ** The old value of the STRv is released ** ** INPUT: [W] pointer to the STRv to be assigned ** the position of insertion (see StrAdd) ** the C string */ void StrAddS(STRv* dest, int pos, char* src) { int dlen=(*dest)->len; int len=strlen(src); ASSERT(pos<=dlen, OutOfBounds); StrBufChange(dest, pos, pos+len); memcpy((*dest)->arr+pos, src, len); } /**API* StrEqualS ********************************************************* ** ** Compares the value of a STRv with the value of a C string (char*) ** ** INPUT: the STRv to be compared ** the C string ** RETURNS: TRUE if they are equal */ BOOL StrEqualS(STRv s1, char* s2) { return strcmp(s1->arr, s2)==0; } /**API* StrCmpS ********************************************************* ** ** Compares the value of a STRv with the value of a C string (char*) ** for lexicographic ordering ** ** INPUT: s1:the STRv to be compared ** s2:the C string ** RETURNS: <0 if s10 if s1>s2 */ int StrCmpS(STRv s1, char* s2) { return strcmp(s1->arr, s2); } /**API* StrHashS ********************************************************* ** ** calculates a hash value for a C string ** ** ** INPUT: the C string (char*) ** RETURNS: an integer 0<= i < max */ int StrHashS (char* s, int max) { WORD h=0, g; while (*s) { h=(h << 4 | (h&0xf0000000L)>>28) ^ *s++; } return h%max; } /* for string initialization */ void StrInitStatic(STRoSTATIC_20* curr) { while (*(int*)curr) { STRv s=(STRv)curr++; s->usage=1; s->len=strlen(s->arr); s->dim=s->len+1; } } /* conversions */ /**API* StrFromInt ********************************************************* ** ** Creates a STRv from an int value ** ** INPUT: the integer ** RETURNS: a new STRv with the value of the integer */ STRv StrFromInt(int i) { char buf[20]; sprintf(buf, "%d", i); return StrCpyS(buf); } /**API* StrToInt ********************************************************* ** ** Converts a STRv to an integer ** The function uses atoi for the conversion ** ** INPUT: the STRv ** RETURNS: a new STRv with the value of the integer */ int StrToInt(STRv s) { return atoi(s->arr); } STRv StrFromPtr(void* p) {return NULL;} void* StrToPtr(STRv s) {return NULL;} /* functions needed for use in icarus */ STRv StrPrintf (STRv* str, char *format, ...) { va_list ap; char s[2000]; va_start (ap, format); vsprintf (s, format, ap); va_end (ap); StrAppS (str, s); return *str; } STRv StrEncode (STRv *str) { char codeStr[10], *code, *s; INT4 k; for (k = 0; k < StrLen (*str);) { s = _Str (*str); switch (s[k]) { case '\n': code = "\\n"; break; case 7: code = "\\b"; break; case '\t': code = "\\t"; break; case '\r': code = "\\r"; break; case '"': code = "\\\""; /* " ...emacs colors;-( */ break; case '\\': code = "\\\\"; break; default: if (s[k] < 8) { sprintf (codeStr, "\\%d", s[k]); code = codeStr; } else { code = NULL; k++; } break; } if (code) { StrSubst (str, k, 1, StrTemp (code)); k += strlen (code); } } return *str; } void StrDecode (STRv* str) { char *s; INT4 k,l, slen, code; StrBufChange(str,0,0); s = _Str (*str); slen = StrLen (*str); for (k = 0, l = 0; k < slen; k++) if (s[k] != '\\') s[l++] = s[k]; else switch (s[++k]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': code = s[k] - '0'; while (isdigit (s[k+1])) { k++; code = code*10 + (s[k] - '0'); } s[l++] = code; break; case 'n': s[l++] = 10; break; case 'a': s[l++] = 7; break; case 't': s[l++] = 9; break; case 'b': s[l++] = 7; break; case 'r': s[l++] = 13; break; case '\"': /* " ...emacs colors;-( */ s[l++] = 34; break; case '\\': s[l++] = 92; break; case '-': s[l++] = '\\'; /* see PrsDecode */ s[l++] = '-'; break; default: s[l++] = s[k]; break; } s[l] = '\0'; (*str)->len = l; } STRv StrNCpyS(char* src, int len) { STRv s=StrBufNew(len); s->len=len; memcpy(s->arr, src, len); s->arr[len]='\0'; return s; } void StrNSetS(STRv* dest, char* src, int len) { int dlen=(*dest)->len; StrBufChange(dest, dlen, len); memcpy((*dest)->arr, src, len); (*dest)->arr[len]='\0'; } #define _STRV_H typedef struct STRo { int usage; int len; int dim; char arr[1]; } STRo; typedef STRo* STRv; extern STRv StrNULL; /* allocation */ STRv StrNew(); STRv StrCpy(STRv src); void StrDel(STRv val); void StrGrow(STRv* val, int dlen); void StrTrim(STRv* val); void StrClear(STRv* s); STRv StrSub(STRv s, int pos, int len); STRv StrLeft(STRv s, int pos); STRv StrRight(STRv s, int pos); /* operations */ void StrSet(STRv* dest, STRv src); void StrIns(STRv* dest, STRv src); void StrApp(STRv* dest, STRv src); void StrAdd(STRv* dest, int pos, STRv src); void StrCut(STRv* dest, int pos, int len); void StrSubst(STRv* dest, int pos, int len, STRv subst); void StrDebug(STRv s); void StrUpper(STRv* s); void StrLower(STRv* s); /* queries */ BOOL StrEmpty(STRv str); int StrLen(STRv str); BOOL StrEqual(STRv s1, STRv s2); int StrCmp(STRv s1, STRv s2); int StrHash(STRv val, int max); /* user */ char* StrConst(STRv val); char* StrVal(STRv val); char* StrGet(char* dest, int sz, STRv src); #define Str(val) ((val)->arr) #define _Str(val) ((val)->arr) /* c string operations */ STRv StrTemp(char* src); STRv StrCpyS(char* src); void StrSetS(STRv* dest, char* src); void StrInsS(STRv* dest, char* src); void StrAppS(STRv* dest, char* src); void StrAppN(STRv* dest, char* src, int len); void StrAddS(STRv* dest, int pos, char* src); BOOL StrEqualS(STRv s1, char* s2); int StrCmpS(STRv s1, char* s2); int StrHashS (char* val, int dim); STRv StrNCpyS(char* s, int len); void StrNSetS(STRv* dest, char* s, int len); /* low-level */ STRv StrBufNew(int dim); void StrBufChange(STRv* val, int beg, int end); /* conversions */ STRv StrFromInt(int i); int StrToInt(STRv s); STRv StrPtr(void* p); void* PtrStr(STRv s); /* functions similar to Buff... */ STRv StrPrintf (STRv* str, char *format, ...); STRv StrEncode (STRv *str); void StrDecode (STRv* str); /* for string initialization */ typedef struct { struct { int u; int l; int d; } DontInitalize; char arr[20]; } STRoSTATIC_20; typedef struct { struct { int u; int l; int d; } DontInitalize; char arr[100]; } STRoSTATIC_100; typedef struct { struct { int u; int l; int d; } DontInitalize; char arr[1000]; } STRoSTATIC_1000; void StrInitStatic(STRoSTATIC_20* arr); #endif char template_ID[] = "$Id: templ.c,v 1.17 1996/08/12 20:24:29 etzold Exp $"; /* ** ** $Source: /home/srs/cvsroot/srs/src/templ.c,v $ ** $Revision: 1.17 $ ** $Date: 1996/08/12 20:24:29 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** facility for writing any type of command procedure within a program ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "def.h" #include "message.h" #include "sm.h" #include "futil.h" #include "library.h" #include "strv.h" #include "lst.h" #include "par.h" #include "dict.h" #include "variable.h" #include "templ.h" #include "icarus.h" #include "icaarg.h" #define TEMPLxMaxContextN 20 typedef struct TEMPLo { FILEo *inFile; FILEo *outFile; STRv outString; VARo *varList; ICAoJOB *job; struct TEMPLoLABEL *label; DICTv labelDict; INT4 labelN; INT4 labelAllocN; } TEMPLo; typedef struct TEMPLoCONTEXT { TEMPLo *templ; STRv name; VARo *var; Int4 isRoot; } TEMPLoCONTEXT; typedef struct TEMPLoLABEL { char *name; FIP fip; } TEMPLoLABEL; static TEMPLo *templCurr=NULL; static ICAoJOB *templJob=NULL; static TEMPLoCONTEXT *templContext=NULL; void TemplIcaAddLabel (); static void TemplIcaAddTemplate (); static void TemplInit (); static char *TemplContext (char *option, TEMPLo *templ, VARo *var, Int4 isRoot); static struct VARo *TemplGetTemplate (TEMPLv templ, char *name); static Int4 TemplWithImpl (TEMPLo *templ, char *label); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** for the variable dictionary */ static void* TemplToKey (DictElem* e) { return offset(templContext->templ->label, (WORD)*e - 555, TEMPLoLABEL*)->name; } static CLASSoDICT dictClass = { (ValComparer)strequal, (ValHasher)strhash, (KeyAccessor)TemplToKey, NULL, 0 }; void TemplIcaAddLabel (Int4 runTime, STRv name, Int4 fip) { TEMPLo *templ = templContext->templ; TEMPLoLABEL *tmp; if (runTime) IargGetArgs ("name|fip", &name, &fip); tmp = _addObj (templ->label, templ->labelN, templ->labelAllocN, TEMPLoLABEL); tmp->name = (char *) malloc (StrLen(name)+1); strcpy (tmp->name, _Str (name)); tmp->fip = fip; DictSet (&templ->labelDict, tmp->name, TEMPLoLABEL*) = (void *) (displ(tmp,templ->label) + 555); /* add 555 since NULL not allowed */ } static void TemplIcaAddTemplate () { VARo *var; IargGetArgs ("var", &var); } static void TemplInit () { ICAoSYNTAX *syntax; if (!templJob) { syntax = (ICAoSYNTAX*)LibObjByName ("syntax", "icarus"); templJob = IcaCreateJob (syntax); IcaSetFunction("TemplIcaAddLabel", (FUNC) TemplIcaAddLabel); IcaSetFunction("TemplIcaAddTemplate", (FUNC) TemplIcaAddTemplate); } } /**API* TemplOpen ************************************************************* ** ** Opens the template file and the output stream. ** TemplWith must be used before the first call of TemplPrint. ** ** INPUT: name of template file [R] ** name of output file (opens 'stdout' if NULL) [R] ** IMPLICIT: ** templJob (JOBo*) ** ** RETURNS: ** the new template object ** NULL if read file could not open */ TEMPLo *TemplOpen (char *inFileName, char *outFileName) { TEMPLo *templ; TemplInit (); /* new templ object */ if (!(templ = (TEMPLo *) calloc (1, sizeof (TEMPLo)))) _ErrExit2 (e__allocfail, "templ object"); /* open files, init label dictionary and variable list*/ templ->inFile = FileNew (inFileName); if (!FileOpen (templ->inFile)) return(NULL); templ->outFile = FileNew (outFileName); if (!FileOpen (FileSetWrite(templ->outFile))) _ErrExit2 (e__filnotok, FileGetName (templ->outFile, "full")); templ->labelDict = DictCreate (&dictClass); /*DictCreateClassStrKey (NULL, mPtr(TEMPLoLABEL, name), 0));*/ templ->varList = VarNew (); /* scan the templ input file for variable names and insert in dictionary */ TemplWith (templ, NULL); IcaJobSetFile (templJob, templ->inFile); IcaDoJob (templJob, "scan"); if (templJob->prog) VarExec (templJob->prog); TemplEndWith (); return templ; } static VARo *TemplGetTemplate (TEMPLo *templ, char *name) { TEMPLoLABEL *label; VARo *var; Iter i; templContext->templ = templ; var = VarGetListAssoc (templ->varList, name); if (!VarType (var)) { if ((i = DictWith (templ->labelDict, name))) label = (TEMPLoLABEL*) ((char *)templ->label + ((Word) DictIn (i, TEMPLoLABEL*) - 555)); else _ErrExit3 (e__labelnotfound, name, FileGetName (templ->inFile, "full")); FileSeek (templ->inFile, label->fip); IcaJobNext (templJob); IcaJobSetFile (templJob, templ->inFile); IcaDoJob (templJob, "template"); IcaExecProg (templJob); VarSetList (var, VarGetList (VarGet (&templJob->scope, name))); } return var; } /**API* TemplGet ************************************************************** ** ** Returns the template object set by the last TemplWith call. ** ** RETURNS: the template object ** NULL: no template open ** */ TEMPLv TemplGet () { return templContext ? templContext->templ : NULL; } FILEo *TemplGetOutFile (TEMPLv templ) { return templ->outFile; } /**API* TemplPrint ************************************************************ ** ** Prints the text contained by specified label. Additional arguments ** are required if the text contains '%' metacharacters. ** ** INPUT: o label name starting from current template context ** (see TemplWith). Instead of the name the position of ** the label within the list can be used by specifying the ** number in square brackets (eg, [2]). The first label ** in the list has number 1. [R] ** o additional arguments to be inserted into text [R] ** IMPLICIT: ** templJob (JOBo*) ** */ void TemplPrint (char *name, ...) { TEMPLo *templ=templContext->templ; STRv str; char s[50000]; va_list ap; TemplWith (templ, name); va_start (ap, name); vsprintf (s, VarGetStr (templContext->var), ap); va_end (ap); fprintf (templ->outFile->file, "%s", s); TemplEndWith (); } /**API* TemplExists *********************************************************** ** ** This function is useful for asserting that the specified label exists ** before using it for printing. The function returns the Any object ** containing the label name as well as the text or an Any list in ** case the name specifies an internal label. ** ** INPUT: the template object (or NULL) [R] ** label name (see TemplWith) [R] ** IMPLICIT: ** templJob (JOBo*) ** RETURNS: ** address of Any object ** NULL: label does not exist ** */ VARo *TemplExists (TEMPLv templ, char *name) { VARo *var=NULL; if (TemplWithImpl (templ, name)) { var = templContext->var; TemplEndWith (); } return var; } /**API* TemplSPrint *********************************************************** ** ** Same as TemplPrint except that it prints into the string with ** specified address rather than the output stream. ** ** INPUT: address of output string [W] ** label name (see TemplWith) [R] ** additional arguments to be inserted into text [R] ** IMPLICIT: ** templJob (JOBo*) ** RETURNS: ** address of output string (same as first argument) ** */ char *TemplSPrint (char *s, char *name, ...) { TEMPLo *templ=templContext->templ; STRv str; va_list ap; TemplWith(templ, name); va_start(ap, name); vsprintf(s, VarGetStr(templContext->var), ap); va_end(ap); TemplEndWith(); return(s); } /**API* TemplWith ************************************************************ ** ** Sets the template context to a new list. The context can ** be either a list contained in the list represented by the current ** context (relative name) or in another variable which may be ** forced by prefixing ** the label name with a '$' (absolute name). **

    ** The label name can contain indices for specifiying elements in ** the list which must then be inclosed in square brackets (eg, [1], ** TemplN assists in generating labels with an index). ** After printing with the 'template' context TemplEndWith must be ** called to restore to the previous context (The contexts are ** maintained as a stack where TemplWith pushes and TemplEndWith pops). ** ** INPUT: template object (or NULL) [W] ** label name [R] ** */ void TemplWith (TEMPLo *templ, char *label) { char path[200]; if (!TemplWithImpl (templ, label)) { sprintf (path, "%s.%s", TemplContext ("root", NULL, NULL, 0), label); _ErrExit3 (e__objectunknown, "label", path); } } static Int4 TemplWithImpl (TEMPLo *templ, char *label) { VARo *var=NULL, *tmp; Int4 isRoot=0, index; char *name, path[200], *context; if (!templ) { if (!templContext) _ErrExit (e__templNoCurrTemplate); templ = templContext->templ; } if (label && *label == '$') { /* start with root */ isRoot=1; label++; } else if (templContext && templ == templContext->templ) var = templContext->var; /* take root from prev context */ if (label) { strcpy (path, label); context = path; while ((name = strtok (context, ".["))) { context = NULL; if (sscanf (name, "%d]", &index)) { /* access by index */ if (!var || !(var = VarGetListIndex (VarGetList(var), index-1))) return 0; } else if (var && !isRoot) { /* access by name */ if (!(tmp = VarFindListAssoc (var, name))) return 0; else var = tmp; } else { /* root or variable name */ var = TemplGetTemplate (templ, name); isRoot = 0; /* prevents treatment of next name compononent as root */ } } } TemplContext ("push", templ, var, isRoot); return 1; } /**API* TemplEndWith ********************************************************** ** ** Destroys the current template context set by the most recent ** call of TemplWith and reinstalls the previous context. ** ** INPUT: ** IMPLICIT: ** templJob (JOBo*) ** */ void TemplEndWith () { TemplContext ("pop", NULL, NULL, 0); } static char *TemplContext (char *option, TEMPLo *templ, VARo *var, Int4 isRoot) { static TEMPLoCONTEXT contexts[TEMPLxMaxContextN]; static INT4 contextN=0; static char path[200]; char tmp[200]; Int4 k; switch (tolower (option[2])) { case 's': /* push */ if (contextN == TEMPLxMaxContextN) _ErrExit3 (f__limitexceeded, "templ contexts", TEMPLxMaxContextN); templContext = &contexts[++contextN]; templContext->templ = templ; templContext->var = var; templContext->isRoot = isRoot; break; case 'p': /* pop */ if (contextN) templContext = &contexts[--contextN]; else _ErrExit (e__templEndOfHistory); break; case 'o': /* root */ /* get the entire path from history */ for (k=contextN, path[0]='\0'; k >= 0; k--) { if ((var = contexts[k].var)) { strcpy (tmp, path); sprintf (path, ".%s%s", VarGetName (var), tmp); } else break; if (contexts[k].isRoot) break; } if (*path) path[0] = '$'; return path; } } void TemplClose (TEMPLv templ) { FileClose (templ->outFile); FileClose (templ->inFile); free (templ); /* should also 'unwind' the context if there is some left */ } static char line[999]; /**API* TemplN **************************************************************** ** ** Assists in creating a label name used when calling, eg, TemplPrint ** The generated label name's first component is an ** index number rather than a name. The specified name is added to ** the number, eg, if the index is 5 and the name is "head" then the ** generated string is "[5].head". **
    ** This function ** ** INPUT: the index number [R] ** the name to go after the index (NULL if not desired) [R] ** ** RETURNS: the string containing the label name ** */ char *TemplN (INT4 index, char *name) { static char line[999]; if (name) sprintf(line, "[%d].%s", index, name); else sprintf(line, "[%d]", index); return(line); } ** ** $RCSfile: templ.h,v $ ** $Revision: 1.8 $ ** $Date: 1996/08/12 20:24:30 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** */ typedef struct TEMPLo *TEMPLv; TEMPLv TemplOpen (char *inFileName, char *outFileName); TEMPLv TemplGet (); char* TemplSPrint (char *s, char *name, ...); char* TemplN (INT4 index, char *name); void TemplPrint (char *name, ...); void TemplWith (TEMPLv templ, char *name); struct VARo* TemplExists (TEMPLv templ, char *name); void TemplEndWith (); void TemplClose (TEMPLv templ); struct FILEo* TemplGetOutFile (TEMPLv templ); #define _s(x) (x) #define _d(x) (x) ** ** $RCSfile: tm.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:31 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V3.x Copyright by Thure Etzold ** */ UINT4 TimeGet (); char *TimeToString (UINT4 time, char *option); UINT4 TimeFileCreate (FILE *file); char toklist__ID[] = "$Id: toklist.c,v 1.12 1996/08/14 16:19:29 etzold Exp $"; /* ** ** $RCSfile: toklist.c,v $ ** $Revision: 1.12 $ ** $Date: 1996/08/14 16:19:29 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #include #include #include #include #include "message.h" #include "futil.h" #include "sm.h" #include "dict.h" #include "lst.h" #include "toklist.h" /* * * * * * * * * * Private Domain * * * * * * * * * * * * * * * */ static void ListDump(FILE *file, void *obj) { TOKoLIST *t = (TOKoLIST *)obj; printf("List/%d %s\n", t->isActive, t->name); } static void ListKill(void *obj) { TOKoLIST *tokList = (TOKoLIST *)obj; free(tokList->first); if(tokList->buff) free(tokList->buff); } /****** TokGrowList ********************************************************* ** ** This function implements growing of number of allocated tokens ** into token list class object when number of required tokens ** exceed maximum. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: */ static void TokGrowList(TOKoLIST *tokList) { INT4 offsetRead, offsetWrite; tokList->size *= 2; offsetRead = (INT4) (tokList->currTokenRead - tokList->first); offsetWrite = (INT4) (tokList->currTokenWrite - tokList->first); tokList->first = (TOKoTOKEN *) realloc(tokList->first, tokList->size*sizeof(TOKoTOKEN)); if(!tokList->first) _ErrExit2 (e__allocfail, "tokList list"); tokList->currTokenRead = tokList->first + offsetRead; tokList->currTokenWrite = tokList->first + offsetWrite; tokList->last = tokList->first + tokList->size; } /* * * * * * * * * * Public Domain * * * * * * * * * * * * * * * */ /**api* TokGetList ********************************************************** ** ** Create and initialise a new token list object if the name is not ** in the list otherwise return pointer to existing token list. ** If token list class object's address is NULL it would be created. ** ** INPUT: name of token list [R] ** address of token list object [R] (initially NULL) ** ** IMPLICIT: ** ** RETURNS: token list object */ TOKoLIST *TokGetList(char *name, TOKoLIST **tokList) { static INT4 TokListClassId = 0; TOKoLIST *tmp; if(!TokListClassId) LstManageClass(&TokListClassId, sizeof(TOKoLIST), NULL, ListKill,ListDump); if (!LstHashSearch((void **) tokList, name)) { LstNewNamed((void **) tokList, TokListClassId, name); tmp = *tokList; tmp->first = (TOKoTOKEN *) calloc(1, TOKxMAXLISTSIZE * sizeof(TOKoTOKEN)); if (!tmp->first) _ErrExit2 (e__allocfail, "tokList list"); tmp->isActive = FALSE; tmp->size = TOKxMAXLISTSIZE; tmp->style = TOKxANY; tmp->buff = NULL; tmp->currTokenWrite = tmp->first; tmp->currTokenRead = tmp->first; tmp->last = tmp->first + tmp->size; } return *tokList; } /**api* TokFindList ********************************************************** ** ** Return pointer to token list object if the name is not ** in the list exit program with error ** ** INPUT: name of token list [R] ** address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: token list object */ TOKoLIST *TokFindList(char *name, TOKoLIST **tokList) { if( !LstHashSearch((void **) tokList, name) ) _ErrExit2(e__toklistFind, name); return (*tokList); } /**api* TokIsListActive ***************************************************** ** ** Return "isActive" attribute of token list object. Token list is ** "active" when read/write operations are allowed with this token ** list ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: isActive attribute */ INT4 TokIsListActive(TOKoLIST *tokList) { return(tokList->isActive); } /**api* TokIsListEmpty ****************************************************** ** ** Check presence of token(s) in token list object. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: TRUE ** FALSE */ INT4 TokIsListEmpty(TOKoLIST *tokList) { return(tokList->first == tokList->currTokenWrite); } /**api* TokIsListStart ****************************************************** ** ** Check if the current token to read is the first in token list object. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: TRUE ** FALSE */ INT4 TokIsListStart(TOKoLIST *tokList) { return(tokList->first == tokList->currTokenRead); } /**api* TokSetStyle ********************************************************* ** ** Set style attribute for the token list object. ** ** INPUT: address of token list object [R] ** type of token list [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokSetStyle(TOKoLIST *tokList, char *style) { if(tokList->style == TOKxANY) { switch(tolower(style[0])) { case 'c': /* copy */ tokList->style = TOKxCOPY; tokList->buff = BuffInit(tokList->buff, TOKxMAXTOKBUFFSIZE); break; case 'e': /* echo */ tokList->style = TOKxECHO; break; case 'f': /* file */ tokList->style = TOKxFILE; break; default: _ErrExit2 (e__unknownoption, style); } } } /**api* TokSetFile ********************************************************** ** ** Initialize attributes for the token list object in special case ** when token list is associated with standard input stream (file). ** ** INPUT: address of token list object [R] ** address of file object [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokSetFile(TOKoLIST *tokList, FILEo *file) { tokList->file = file; tokList->isActive = TRUE; tokList->first->code= TOKxUNDEFCODE; tokList->first->isTerminal = FALSE; tokList->currTokenRead = tokList->first; tokList->currTokenWrite = tokList->first + 1; tokList->first->length = 0; tokList->style = TOKxFILE; } /**api* TokResetList ******************************************************** ** ** Deactivate the token list object. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokResetList(TOKoLIST *tokList) { tokList->isActive = FALSE; if(tokList->buff) BuffReset(tokList->buff); tokList->currTokenWrite = tokList->first; tokList->currTokenRead = tokList->first; } /**api* TokResetAllLists **************************************************** ** ** Deactivate all token list objects. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokResetAllLists(TOKoLIST *tokList) { if (tokList) { LstFirst((void **) &tokList); do { TokResetList(tokList); }while(LstNext((void **) &tokList)); } } /**api* TokRewindList ******************************************************* ** ** Set current input token in the token list objects at the beginning. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokRewindList(TOKoLIST *tokList) { tokList->currTokenRead = tokList->first; } /**api* TokDeleteList ******************************************************* ** ** Delete the token list object. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokDeleteList(TOKoLIST *tokList) { LstDelete((void **) &tokList); } /**api* TokDeleteAllLists *************************************************** ** ** Delete all token list objects. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokDeleteAllLists(TOKoLIST *tokList) { LstDeleteAll((void **) &tokList); } /**api* TokAdd ************************************************************** ** ** Add a new token to the token list objects. ** ** INPUT: address of the token list object [R] ** address of the token [R] ** length of the token [R] ** code of the token [R] ** ** IMPLICIT: ** ** RETURNS: TRUE if token was added ** FALSE otherwise */ INT4 TokAdd(TOKoLIST *tokList, char* tokStr, INT4 length, INT4 code) { TOKoTOKEN *token; if(tokList->style == TOKxANY || tokList->style == TOKxFILE) _ErrExit2 (e__toktablenotwritable, tokList->name); tokList->isActive = TRUE; if(tokList->currTokenWrite >= tokList->last) TokGrowList(tokList); token = tokList->currTokenWrite; if(tokList->style == TOKxCOPY) { token->buffOffset = BuffGetCurrOffset(tokList->buff); BuffCopyNChar(tokList->buff, tokStr, length); } else token->tokStr = tokStr; token->isTerminal = TRUE; token->length = length; token->code = code; tokList->currTokenWrite++; return(TRUE); } /**api* TokAppend *********************************************************** ** ** Append a token to the current output token in the token list objects. ** ** INPUT: address of the token list object [R] ** address of the token [R] ** length of the token [R] ** code of the token [R] ** ** IMPLICIT: ** ** RETURNS: TRUE if token was appended ** FALSE otherwise */ INT4 TokAppend(TOKoLIST *tokList, char* tokStr, INT4 length) { if(tokList->isActive == FALSE) return(FALSE); if(tokList->style == TOKxECHO) { (tokList->currTokenWrite-1)->isTerminal = FALSE; TokAdd(tokList, tokStr, length, (tokList->currTokenWrite-1)->code); } else { (tokList->currTokenWrite-1)->length += length; BuffCopyNChar(tokList->buff, tokStr, length); } return(TRUE); } /**api* TokReplaceIn ******************************************************** ** ** Replace a part of the current output token on target string ** ** INPUT: address of the token list object [R] ** start position of the replacement in the token [R] ** length of the replacement [R] ** replacement string [R] ** ** IMPLICIT: ** ** RETURN: shift between new and old buffers, if new was reallocated */ INT4 TokReplaceIn(TOKoLIST *tokList, char *tag, INT4 tagLen, char *repStr, INT4 repLen) { TOKoTOKEN *token; char *saveBuffPtr; INT4 shift, diff; if (tokList->style == TOKxFILE) { SmReplace (tokList->file->ln, tag, tagLen, repStr, repLen); return 0; } else if (tokList->style == TOKxCOPY) { saveBuffPtr = BuffGetPtr(tokList->buff); BuffReplace(tokList->buff, tag, tagLen, repStr, repLen); shift = repLen - tagLen; if(shift) { /* the token where the replacement takes place is not the current but one prior! */ (tokList->currTokenRead-1)->length += shift; token = tokList->currTokenRead-1; while(token++ < tokList->currTokenWrite) token->buffOffset += shift; } diff = (Int4)(BuffGetPtr(tokList->buff)-saveBuffPtr); return diff; } else { _ErrExit2(e__toklistReplace, tokList->name); } } /**api* TokCurrent ********************************************************* ** ** Return pointer to the current input token ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: address of the current input token */ TOKoTOKEN *TokCurrent(TOKoLIST *tokList) { return(tokList->currTokenRead); } /**api* TokGet ************************************************************** ** ** Return pointer to the current input token ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the next token if it exists ** NULL otherwise */ TOKoTOKEN *TokGet(TOKoLIST *tokList) { TOKoTOKEN *token; if(!tokList->isActive) return(NULL); token = tokList->currTokenRead; if(tokList->style == TOKxFILE) { if (!tokList->file || FileReadLn(tokList->file) == NULL) return(NULL); token->tokStr = tokList->file->ln; token->length = strlen(tokList->file->ln); return(token); } if(token < tokList->currTokenWrite) { tokList->currTokenRead = token + 1; return(token); } else return(NULL); } /**api* TokGet2 ************************************************************** ** ** Return pointer to the current input token. ** If token list object associated with standard input stream ** new line will be read if current is empty. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the next token if it exists ** NULL otherwise */ TOKoTOKEN *TokGet2(TOKoLIST *tokList) { TOKoTOKEN *token; if(!tokList->isActive) return(NULL); token = tokList->currTokenRead; if(tokList->style == TOKxFILE && tokList->file) { if (!(*tokList->file->ln)) if(FileReadLn(tokList->file) == NULL) return(NULL); token->tokStr = tokList->file->ln; token->length = strlen(tokList->file->ln); return(token); } if(token < tokList->currTokenWrite) { tokList->currTokenRead = token + 1; return(token); } else return(NULL); } /**api* TokGetMore ********************************************************** ** ** Return pointer to the next input token when current token ** consist of more that one fragment. ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the next fragment of Multioken if it exists ** NULL otherwise */ INT4 TokGetMore(TOKoLIST *tokList, char **ptr, INT4 *length) { TOKoTOKEN *token; if( TokIsMultiTok(tokList) ) { if((token = TokGet(tokList))){ *length = token->length; *ptr = token->tokStr; return(TRUE); } } return(FALSE); } /**api* TokGetFirst ********************************************************* ** ** Return pointer to the first input token ** ** INPUT: address of token list object [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the first token */ TOKoTOKEN *TokGetFirst(TOKoLIST *tokList) { tokList->currTokenRead = tokList->first; return(TokGet2(tokList)); } /**api* TokNext ************************************************************* ** ** Return pointer to the next input token. If counter equals to zero ** return address of the first token ** ** INPUT: address of token list object [R] ** address of counter [W] ** ** IMPLICIT: ** ** RETURNS: pointer to the next(first) token */ TOKoTOKEN *TokNext(TOKoLIST *tokList, INT4 *count) { (*count)++; if(*count == 1) return(TokGetFirst(tokList)); else return(TokGet(tokList)); } /**api* TokNextWithCode ***************************************************** ** ** Return pointer to the next input token that has required code. ** If counter equals to zero start search form the first token. ** ** INPUT: address of token list object [R] ** address of counter [W] ** code of input token [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the next token if it exists ** NULL otherwise */ TOKoTOKEN *TokNextWithCode(TOKoLIST *tokList, INT4 code, INT4 *count) { TOKoTOKEN *token; if(*count == 0) token = TokGetFirst(tokList); else token = TokGet(tokList); (*count)++; while( token ) { if(token->code == code || code == TOKxUNDEFCODE) return(token); else token = TokGet(tokList); } return(NULL); } /**api* TokGetString ******************************************************** ** ** Return pointer to the string content of the token ** ** INPUT: address of token list object [R] ** address of token [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the string */ char *TokGetString(TOKoLIST *tokList, TOKoTOKEN *tokenRead) { if(tokList->style == TOKxCOPY) return(BuffGetPtr(tokList->buff)+tokenRead->buffOffset); else return(tokenRead->tokStr); } /**api* TokGetStringCopy **************************************************** ** ** Return copy to the string content of the token. ** Space for the copy of the string allocated in static buffer object. ** The content of the string is stable until next call of the function. ** ** INPUT: address of token list object [R] ** address of token [R] ** ** IMPLICIT: ** ** RETURNS: pointer to the string */ char *TokGetStringCopy(TOKoLIST *tokList, TOKoTOKEN *token) { static SMoBUFF *buffTokStr = NULL; buffTokStr = BuffInit(buffTokStr, TOKxMAXTOKBUFFSIZE); if(tokList->style == TOKxCOPY) { BuffCopyNChar(buffTokStr, BuffGetPtr(tokList->buff)+token->buffOffset, token->length); BuffCopyChar(buffTokStr, '\0'); } else { BuffCopyNChar(buffTokStr, token->tokStr, token->length); while( !token->isTerminal ) { token++; BuffCopyNChar(buffTokStr, token->tokStr, token->length); } BuffCopyChar(buffTokStr, '\0'); } return(BuffGetPtr(buffTokStr)); } /**api* TokGetCode ********************************************************** ** ** Get the code of the current output token ** ** INPUT: address of token [R] ** ** IMPLICIT: ** ** RETURNS: value of the token code */ INT4 TokGetCode(TOKoTOKEN *tokenRead) { return(tokenRead->code); } /**api* TokGetLength ******************************************************** ** ** Get the length of the current output token ** ** INPUT: address of token [R] ** ** IMPLICIT: ** ** RETURNS: value of the token length */ INT4 TokGetLength(TOKoTOKEN *tokenRead) { return(tokenRead->length); } /**api* TokIsMultiTok ******************************************************** ** ** Check, does specified token consist of fragments ** ** INPUT: address of token [R] ** ** IMPLICIT: ** ** RETURNS: TRUE if token consists from fragment ** FALSE otherwise */ INT4 TokIsMultiTok(TOKoLIST *tokList) { if(tokList->style == TOKxFILE) return(TRUE); if(tokList->currTokenRead < tokList->currTokenWrite) return(!(tokList->currTokenRead-1)->isTerminal); else return(FALSE); } /**api* TokIsUniq *********************************************************** ** ** Check, does specified token is unique ** ** INPUT: address of token [R] ** ** IMPLICIT: ** ** RETURNS: TRUE if string is unique in tokList ** FALSE otherwise */ INT4 TokIsUniq(TOKoLIST *tokList, char *string, INT4 len, INT4 code) { TOKoTOKEN *token; INT4 count; if(tokList->style == TOKxFILE) _ErrExit2(e__toklistIsUniq, tokList->name); count = 0; while( (token = TokNextWithCode(tokList, code, &count)) ) if( len == token->length && strncmp(TokGetString(tokList, token), string, len) == 0) return(FALSE); return(TRUE); } /**api* TokPrintList ******************************************************** ** ** ** Print out all tokens with particular code from specify token list ** object ** ** INPUT: address of token list object [R] ** token code [R] ** ** IMPLICIT: ** ** RETURNS: */ void TokPrintList(TOKoLIST *tokList, INT4 code) { TOKoTOKEN *token; INT4 count; printf("TokList: %s\n", tokList->name); count = 0; while( (token = TokNextWithCode(tokList, code, &count)) ) printf("TOKEN%2d: |%s| -- CODE: %d\n", count, TokGetStringCopy(tokList, token), TokGetCode(token) ); } static SMoBUFF* buff=NULL; static void* BuffToKey(DictElem* e) { Word offs=cast(*e, Word)-TOKxCODESHIFT; return BuffGetPtr(buff)+offs; } static CLASSoDICT CodeDictClass = { (ValComparer)strequal, (ValHasher)strhash, (KeyAccessor)BuffToKey, NULL, FALSE }; /**api* TokStrToCode ******************************************************** ** ** Token list class has global dictionary of token codes defined as ** names. Function converts name to integer and stores unique names ** in dictionary object. ** ** INPUT: name of token code [R] ** ** IMPLICIT: ** ** RETURNS: integer value of the code */ INT4 TokStrToCode(char* str) { static DICTv codeNames=0; IntOrPtr code; char** p; if (!codeNames) { codeNames=DictCreate(&CodeDictClass); buff=BuffInit(buff, 512); } p=&DictSet(&codeNames, str, char*); if (*p) code=(IntOrPtr)*p; /* the string is already in dictionary */ else { code=BuffGetCurrOffset(buff)+TOKxCODESHIFT; /* new string */ *p=(DictElem)code; BuffCopyString(buff, str); BuffCopyChar(buff,'\0'); } return(code); } /**api* TokStrToCode ******************************************************** ** ** Token list class has global dictionary of token codes defined as ** names. Function converts integer to name of the code using the ** dictionary. ** ** INPUT: integer value of the code [R] ** ** IMPLICIT: ** ** RETURNS: name of token code */ char* TokCodeToStr(INT4 code) { return(BuffGetPtr(buff)+(code-TOKxCODESHIFT)); } /**api* TokGetBuff *********************************************************** ** ** Returns the start address of the buffer of the token table. ** Useful to memorize in order to keep track of possible reallocation ** events. ** ** INPUT: the token list object [R] ** ** IMPLICIT: ** ** RETURNS: start address of token list buffer */ char* TokGetBuff (TOKoLIST *tokList) { return tokList->buff ? BuffGetPtr(tokList->buff) : NULL; } ** ** $RCSfile: toklist.h,v $ ** $Revision: 1.6 $ ** $Date: 1996/07/26 21:15:42 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387451 ** Email: ulyanov@embl-heidelberg.de ** */ #define TOKxCODESHIFT 1000001 #define TOKxMAXNAMESIZE 40 #define TOKxMAXTOKBUFFSIZE 20 #define TOKxMAXHASHSIZE 10000 #define TOKxMAXLISTSIZE 512 #define TOKxUNDEFCODE -1 enum style {TOKxANY, TOKxECHO, TOKxCOPY, TOKxFILE}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ typedef struct TOKoTOKEN { char *tokStr; INT4 buffOffset; INT4 isTerminal; INT4 length; INT4 code; char *codeName; /* name of the code */ } TOKoTOKEN; typedef struct TOKoLIST { char *list; int listId; char name[TOKxMAXNAMESIZE]; INT4 isActive; /* FALSE if empty */ INT4 size; enum style style; /* TOKxCOPY or TOKxECHO */ struct TOKoTOKEN *first; struct TOKoTOKEN *currTokenRead; struct TOKoTOKEN *currTokenWrite; struct TOKoTOKEN *last; FILEo *file; SMoBUFF *buff; } TOKoLIST; TOKoLIST *TokGetList(char *name, TOKoLIST **tokList); TOKoLIST *TokFindList(char *name, TOKoLIST **tokList); TOKoTOKEN *TokCurrent(TOKoLIST *tokList); TOKoTOKEN *TokGet(TOKoLIST *tokList); TOKoTOKEN *TokGetFirst(TOKoLIST *tokList); TOKoTOKEN *TokNext(TOKoLIST *tokList, INT4 *count); TOKoTOKEN *TokNextWithCode(TOKoLIST *tokList, INT4 code, INT4 *count); INT4 TokAdd(TOKoLIST *tokList, char* tokStr, INT4 length, INT4 code); INT4 TokAppend(TOKoLIST *tokList, char* tokStr, INT4 length); INT4 TokGetCode(TOKoTOKEN *tokenRead); INT4 TokGetLength(TOKoTOKEN *tokenRead); INT4 TokGetMore(TOKoLIST *tokList, char **ptr, INT4 *len); INT4 TokIsListActive(TOKoLIST *tokList); INT4 TokIsListEmpty(TOKoLIST *tokList); INT4 TokIsListStart(TOKoLIST *tokList); INT4 TokIsUniq(TOKoLIST *tokList, char *string, INT4 len, INT4 code); INT4 TokIsMultiTok(TOKoLIST *tokList); INT4 TokReplaceIn(TOKoLIST *tokList, char *s, INT4 l, char *s1, INT4 l1); INT4 TokStrToCode(char *codeStr); char *TokCodeToStr(INT4 code); char *TokGetString(TOKoLIST *tokList, TOKoTOKEN *tokenRead); char *TokGetStringCopy(TOKoLIST *tokList, TOKoTOKEN *tokenRead); void TokDeleteAllLists(TOKoLIST *tokList); void TokDeleteList(TOKoLIST *tokList); void TokPrintList(TOKoLIST *tokList, INT4 code); void TokResetAllLists(TOKoLIST *tokList); void TokResetList(TOKoLIST *tokList); void TokRewindList(TOKoLIST *tokList); void TokSetFile(TOKoLIST *tokList, FILEo *file); void TokSetStyle(TOKoLIST *tokList, char *style); char* TokGetBuff (TOKoLIST *tokList); ** ** $RCSfile: transl.h,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:33 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** from ODD file: "srssdl:srswin.sdl" ** date of ODD compilation: 12-JAN-1996 18:16 ** */ #ifndef _SEQoTranslTable #define _SEQoTranslTable typedef struct SEQoTranslTable { char *name; /* Name of translation table. */ char *code; /* Short name of translation table. */ INT4 id; /* Numeric id. */ char *aa; /* Amino acid encoded by triplett. */ char *aaAlt; /* Alternative (edited) Amino acid encoded by triplett. */ char *saa; /* Amino acid encoded by triplett at translation start. */ } SEQoTranslTable; #endif #ifdef _INITOBJS SEQoTranslTable translTable[] = { {"Standard", "SGC0", 1, "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Vertebrate Mitochondrial", "SGC1", 2, "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSS**VVVVAAAADDEEGGGG", "", "--------------------------------MMMM---------------M------------"}, {"Yeast Mitochondrial", "SGC2", 3, "FFLLSSSSYY**CCWWTTTTPPPPHHQQRRRRIIMMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Mold Mitochondrial; Protozoan Mitochondrial; Coelenterate Mitochondrial; Mycoplasma; Spiroplasma", "SGC3", 4, "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "--MM---------------M------------MMMM---------------M------------"}, {"Invertebrate Mitochondrial", "SGC4", 5, "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSSSSVVVVAAAADDEEGGGG", "", "---M----------------------------M-MM---------------M------------"}, {"Ciliate Macronuclear; Dasycladacean Nuclear", "SGC5", 6, "FFLLSSSSYYQQCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Echinoderm Mitochondrial", "SGC8", 9, "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNNKSSSSVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Euplotid Macronuclear", "SGC9", 10, "FFLLSSSSYY**CCCWLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Bacterial", "", 11, "FFLLSSSSYY**CC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "---M---------------M------------M--M---------------M------------"}, {"Alternative Yeast Nuclear", "", 12, "FFLLSSSSYY**CC*WLLLSPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "-------------------M---------------M----------------------------"}, {"Ascidian Mitochondrial", "", 13, "FFLLSSSSYY**CCWWLLLLPPPPHHQQRRRRIIMMTTTTNNKKSSGGVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Flatworm Mitochondrial", "", 14, "FFLLSSSSYYY*CCWWLLLLPPPPHHQQRRRRIIIMTTTTNNNKSSSSVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"}, {"Blepharisma Macronuclear", "", 15, "FFLLSSSSYY*QCC*WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG", "", "-----------------------------------M----------------------------"} }; #endif ****************/ char trembl_ID[] = "$Id: trembl.c,v 1.1 1996/05/06 15:17:34 srs Exp $"; /* ** ** $Source: /home/srs/cvsroot/srs/src/trembl.c,v $ ** $Revision: 1.1 $ ** $Date: 1996/05/06 15:17:34 $ ** $Author: srs $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Gerald Schaefer + Thure Etzold ** EMBL, Meyerhofstrasse 1 ** 69012 Heidelberg, Germany ** Tel: 06221 387372 ** Email: schaefer@embl-heidelberg.de ** etzold@embl-heidelberg.de ** ** ** Requires: ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** program translates all CDS features of EMBL sequences. ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "srs.h" #include "lst.h" #define _INITOBJS #include "transl.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Object that contains the text of a complete data-field. ** The first two attributes are initialized and maintained by ** the list module. The third attribute must be initialized ** by the application modules. If the application module never ** uses a search by name this attribute may be skipped. */ typedef struct { char *internal; /* the first three attributes are necessary */ INT4 type_id; /* for all objects to be managed by the list */ char *name; /* dynamic (flexible) name */ /* char name[20]; /* feature name or refnumber */ SMoBUFF *buff; /* pointer to description */ } FIELDo; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Object with all information from entry that is needed to generate ** a trembl entry. */ typedef struct { ENTRYo *entry; SMoBUFF *id, *accession, *definition, *organism, *featureCurr, *refCurr; FIELDo *links; /* managed by List Module */ FIELDo *features; /* managed by List Module */ FIELDo *references; /* managed by List Module */ SEQo *entrySeq; /* complete entry sequence */ SEQo *resultSeq; /* CDS sequence */ SEQo *protSeq; /* AA sequence */ SLBoFEATURE *feature; /* feature description */ INT4 genCode; char *errorMessage; } CDSoSTORE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** external or module wide variables */ static INT4 cnt_syntaxerror=0, cnt_trerr=0, cnt_firstcodonerror=0, cnt_correct=0; extern INT4 global_before_f; static char *geneticCodeTable[] = { "Standard", /* id 1 */ "Vertebrate Mitochondrial", /* id 2 */ "Yeast Mitochondrial", /* id 3 */ "Mold Mitochondrial and Mycoplasma", /* id 4 */ "Invertebrate Mitochondrial", /* id 5 */ "Ciliate Macronuclear and Daycladacean", /* id 6 */ "Protozoan Mitochondrial", /* id 7 */ "obsolete", /* id 8 */ "Echinoderm Mitochondrial", /* id 9 */ "Euplotid Macronuclear", /* id 10 */ "Eubacterial", /* id 11 */ "Group II yeasts" /* id 12 */ }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** static functions */ static void FieldDump (FILE *file, void *obj); static void FieldInit (void *obj); static void FieldKill (void *obj); static FILE *outFile=NULL; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** default function for printing lines */ static INT4 CDSPrintF (char *formatStr, ...) { va_list ap; va_start (ap, formatStr); vfprintf (outFile, formatStr, ap); va_end (ap); if (formatStr[strlen (formatStr) -1] != '\n') fprintf (outFile, "\n"); return 1; } /**api* FieldCopyList ********************************************************* ** ** gets a new initialized feature object; ** ** INPUT: pointer to address of feature object [W] ** pointer to buffer object [R] ** IMPLICIT: ** ** RETURNS: */ INT4 FieldCopyList (FIELDo **fieldList, SMoBUFF *field) { static INT4 fieldClass_id=0; char name[40]; int rv=0; if (!fieldClass_id) LstManageClassFlex (&fieldClass_id, sizeof(FIELDo), FieldInit, FieldKill, FieldDump); rv = LstNew ((void**) fieldList, fieldClass_id); (*fieldList)->buff = BuffDuplicate (field); /* get the first word after the line code: feature name or reference no */ *name = '\0'; /* reset name */ sscanf (field->buff, "%*[^ ] %s", name); if (name[strlen(name)-1] == ';') name[strlen(name)-1] = '\0'; /* remove ; at the end */ LstChangeObjectName(*fieldList, name); return rv; } /****** FieldDump *********************************************************** ** ** dumps all information belonging to the specified object. ** This is the print function set through LstManageClass ** for ftstype objects (see FtsNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void FieldDump (FILE *file, void *obj) { FIELDo *tmp = (FIELDo*)obj; if (tmp->buff) BuffPrint (file, tmp->buff); } /****** FieldInit ********************************************************** ** ** initializes the specified object. ** This is the init function set through LstManageClass ** for ftstype objects (see FtsNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void FieldInit (void *obj) { FIELDo *tmp = (FIELDo*) obj; tmp->buff = NULL; } /****** FieldKill ********************************************************** ** ** deletes the specified object. ** This is the delete function set through LstManageClass ** for ftstype objects (see FtsNew). ** ** INPUT: address of an object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void FieldKill(void *obj) { FIELDo *tmp = (FIELDo*) obj; if (tmp->buff) BuffDelete(tmp->buff); } INT4 CheckTranslationErrors (char *pseq) { INT4 trerr=0; for ( ; *pseq; pseq++) if (*pseq == '*') trerr++; return trerr; } INT4 PrintMessage (MSGo *msg) { if (msg->msg_code == i__readingname) putc ('.', stderr); switch (msg->msg_code) { case i__wroteset: return 0; default: if (msg->msg_t != MSGxINFO) fprintf (stderr, "ERROR: %s, %s\n", msg->primsg, msg->secmsg); else fprintf (stderr, "%s\n", msg->secmsg); return 1; } } static INT4 PrintLine (char *formatStr, ...) { va_list ap; va_start (ap, formatStr); vfprintf (stderr, formatStr, ap); va_end (ap); if (formatStr[strlen (formatStr) -1] != '\n') fprintf (stderr, "\n"); return 1; } /****** TremblErrorPrint ****************************************************** ** ** prints information about entry that was rejected; ** ** INPUT: address of an entry object [R] ** IMPLICIT: ** ** RETURNS: nothing */ static void TremblErrorPrint (CDSoSTORE *val) { INT4 featureNumber=0; char id[20]="", accno[20]=""; LstFirst((void**) &val->protSeq); /* print first translation */ /* ** get the entry-ID and accession number ** and print the ID line and the link to the EMBL parent entry */ sscanf (val->id->buff, "%*[^ ] %[A-Z0-9]", id); sscanf (val->accession->buff, "%*[^ ] %[A-Z0-9]", accno); LstGetPosition((void*)val->features, &featureNumber); featureNumber++; /* 1 .. n */ if (val->protSeq) fprintf(stderr, "\nID %s_%d standard; PRT; %d AA.\n", accno, featureNumber, val->protSeq->len); else fprintf(stderr, "\nID %s_%d standard; PRT; 0 AA.\n", accno, featureNumber); fprintf(stderr, "DR EMBL; %s; %s.\n", accno, id); /* ** print "definition", "organism", "CDS-feature" data-fields */ fprintf(stderr, "%s", val->definition->buff); fprintf(stderr, "%s", val->organism->buff); fprintf(stderr, "%s", val->features->buff->buff); /* print current feature */ /* ** some error statement and both DNA and protein sequences */ fprintf(stderr, "CC ERROR: no valid translation with table \"%s\"\n", geneticCodeTable[val->genCode - 1]); if (val->protSeq && val->resultSeq && val->feature) { char *start, *curr, *illegal_codon; start = curr = val->protSeq->seq; fprintf(stderr, "CC REASON: "); while (curr = strchr(curr, (int)'*')) { illegal_codon = val->resultSeq->seq + (curr-start)*3 + val->feature->codonStart - 1; fprintf(stderr, " '%.3s'", illegal_codon); curr++; /* skip '*' */ } fprintf(stderr, " is an illegal codon\n"); } SeqWriteEMBL (val->protSeq, val->entry->entry_nm, PrintLine); SeqWriteEMBL (val->resultSeq, val->entry->entry_nm, PrintLine); } /****** TremblPrint ********************************************************** ** ** Prints TREMBL entry; ** ** INPUT: address of an entry object [R] ** number of CDS feature in entry [R] ** IMPLICIT: ** outFile (FILE *) [W} ** ** RETURNS: nothing */ static void TremblPrint (CDSoSTORE *store, int cdsN) { FILE *file; static SMoBUFF *buff=NULL; char id[20]="", accno[20]=""; char refName[20]="", fileName[200], *tmp; INT4 rv; sscanf (store->id->buff, "%*[^ ] %[A-Z0-9]", id); /* ** Open output file: one file for each entry, or only a single file ** or stdout. */ if (ParGetNum ("printSeparateFiles")) { sprintf (fileName, "%s_%d.seq", id, cdsN); file = FilOpenW (fileName, &rv); _ErrExit2 (rv, fileName); } else if ((tmp = ParGetStr ("outputFileName")) && *tmp) { if (!outFile) { file = FilOpenW (tmp, &rv); _ErrExit2 (rv, tmp); } else file = outFile; } else file = stdout; /* print to stdout */ if (!buff) buff = BuffNew (100); if (!store->protSeq->len) return; /* ** print the ID line: accession number with the feature number ** appended, a DR line that links to the parent EMBL entry */ sscanf (store->id->buff, "%*[^ ] %[A-Z0-9]", id); sscanf (store->accession->buff, "%*[^ ] %[A-Z0-9]", accno); /* LstGetPosition ((void*)store->features, &featureNumber); featureNumber++;*/ /* 1 .. n */ fprintf (file, "ID %s_%d standard; PRT; %d AA.\n", id, cdsN, store->protSeq->len); fprintf (file, "AC %s;\n", accno); fprintf (file, "DR EMBL; %s; %s.\n", accno, id); /* ** print the DE line ...but the DE from DNA entry at the end! ** print some selected qualifiers from the feature first */ BuffReset (buff); if (BuffLength (store->feature->gene)) BuffPrintF (buff, "gene: %s; ", BuffGetPtr (store->feature->gene)); if (BuffLength (store->feature->product)) BuffPrintF (buff, "product: %s; ", BuffGetPtr(store->feature->product)); /* if (BuffLength (store->feature->note)) BuffPrintF (buff, "note: %s; ", BuffGetPtr(store->feature->note)); */ BuffCollapse (buff); fprintf (file, "%s\n", BuffFormat (buff, 80, 0, 0, "DE ")); BuffPrint (file, store->definition); if (!BuffLength (store->feature->gene) && !BuffLength (store->feature->product) && !BuffLength (store->feature->note)) BuffCopyString (buff, "unnamed ORF;"); BuffPrint (file, store->organism); /* ** print literature references if explicitly listed by "citation" ** qualifier in the feature annotation */ if (store->feature->citation) { LstFirst((void**)&store->feature->citation); do { sprintf(refName, "[%d]", store->feature->citation->citationNum); if (LstFirstNamed ((void**)&store->references, refName)) LstPrint (file, (void*)store->references); else printf("CC ERROR: reference *%s* not found.\n", refName); } while (LstNext((void**)&store->feature->citation)); } LstPrint (file, (void*)store->features); /* print current feature */ /* ** print additional information obtained during evaluation of the ** feature and some warnings */ fprintf (file, "CC translated using genetic code table \"%s\"\n", geneticCodeTable[store->genCode - 1]); if (store->feature->codonStartShifted > 0) fprintf (file, "CC Warning: codon start shifted by %d\n", store->feature->codonStartShifted); if (global_before_f < 0) { fprintf (file, "CC Warning: illegal start codon\n"); cnt_firstcodonerror++; } else cnt_correct++; outFile = file; SeqWriteEMBL (store->protSeq, store->entry->entry_nm, CDSPrintF); if (ParGetNum ("printSeparateFiles")) fclose (file); } /****** TaxaToTranslTable ***************************************************** ** ** Searches various taxa (case insensitive) to find the appropriate ** translation table; ** ** INPUT: address of buffer with organism source information ** IMPLICIT: ** ** RETURNS: the translation table id number */ INT4 TaxaToTranslTable (SMoBUFF *org) { if (BuffSearch(org,"Protozoa") && BuffSearch(org,"Cili") && !BuffSearch(org,"Mitoch")) return 6; if (BuffSearch(org,"Mitochond") && BuffSearch(org,"Yeast")) return 3; if (BuffSearch(org,"Mitochond") && (BuffSearch(org,"Podospora") || BuffSearch(org,"Protozoa"))) return 7; if (BuffSearch(org,"Mitochond") && (BuffSearch(org,"Vertebrata") || BuffSearch(org,"Mammalia"))) return 2; if (BuffSearch(org,"Mitochond") && BuffSearch(org,"Echinoderm")) return 9; if (BuffSearch(org,"Mitochond")) return 5; return 1; /* default table */ } /****** CDSTranslate ********************************************************* ** ** INPUT: entry store [W] ** IMPLICIT: ** ** RETURNS: */ INT4 CDSTranslate (CDSoSTORE *store) { INT4 i, trerr=1; for (i=0; i<=2; i++) { if (SeqTranslate(store->resultSeq, &store->protSeq, store->feature->codonStart+i, store->feature->codon, store->feature->transl_except, store->genCode - 1)) { trerr = CheckTranslationErrors(store->protSeq->seq); if (!trerr) break; } } if (trerr) return 0; store->feature->codonStartShifted = i; return 1; } /****** CDSStoreInit ********************************************************** ** ** INPUT: entry store [W] ** entry [R] or NULL ** IMPLICIT: ** ** RETURNS: */ CDSStoreInit (CDSoSTORE *store, ENTRYo *entry) { if (!entry) { store->id = BuffNew(20); store->accession = BuffNew(20); store->definition = BuffNew(20); store->organism = BuffNew(20); store->featureCurr = BuffNew(20); store->refCurr = BuffNew(20); store->links = NULL; store->features = NULL; store->references = NULL; store->entrySeq = NULL; store->resultSeq = NULL; store->protSeq = NULL; store->feature = NULL; /* feature description */ store->genCode = 1; /* id of default translation table */ } else { store->entry = entry; BuffReset(store->id); BuffReset(store->accession); BuffReset(store->definition); BuffReset(store->organism); BuffReset(store->featureCurr); BuffReset(store->refCurr); if (store->links) LstDeleteAll((void**)&store->links); if (store->features) LstDeleteAll((void**)&store->features); if (store->references) LstDeleteAll((void**)&store->references); if (store->entrySeq) LstDeleteAll((void**)&store->entrySeq); if (store->resultSeq) LstDeleteAll((void**)&store->resultSeq); if (store->protSeq) LstDeleteAll((void**)&store->protSeq); store->feature = NULL; /* feature description */ store->genCode = 1; /* id of default translation table */ } } /****** CDSStoreEntry ********************************************************* ** ** INPUT: entry store [W] ** entry [R] or NULL ** IMPLICIT: ** ** RETURNS: */ CDSStoreEntry (CDSoSTORE *store, ENTRYo *entry) { SMoBUFF *buff = NULL; SLBoFIELD *field; char *name, *ln; while ((field = EntryToNextField (entry))) { name = LibGetFieldName (field); buff = NULL; if (SmEqs(name, "ID")) buff = store->id; else if (SmEqs(name, "Accession")) buff = store->accession; else if (SmEqs(name, "Definition")) buff = store->definition; else if (SmEqs(name, "Organism")) buff = store->organism; else if (SmEqs(name, "RefNumber")) { buff = store->refCurr; if (!BuffIsEmpty (buff)) FieldCopyList (&store->references, buff); BuffReset (buff); } else if (SmEqs(name, "Authors")) buff = store->refCurr; else if (SmEqs(name, "Title")) buff = store->refCurr; else if (SmEqs(name, "Reference")) buff = store->refCurr; else if (SmEqs(name, "Features")) { buff = store->featureCurr; } if (buff) { while ((ln = EntryFieldNextLine(entry))) BuffCopyString (buff, ln); if (buff == store->featureCurr) { FieldCopyList (&store->features, buff); BuffReset (buff); } } else EntrySkipField (entry); } /* save the last reference in entry */ if (!BuffIsEmpty (store->refCurr)) FieldCopyList (&store->references, store->refCurr); } /****** CDSMakeEntry ********************************************************** ** ** INPUT: entry store [W] ** entry [R] ** file position [R] ** number of CDS feature in entry [R] ** IMPLICIT: ** ** RETURNS: */ CDSMakeEntry (CDSoSTORE *store, ENTRYo *entry, FILoL_S *fileSave, int cdsN) { INT4 rv=0; if (store->resultSeq) LstDeleteAll((void**)&store->resultSeq); if (store->protSeq) LstDeleteAll((void**)&store->protSeq); store->feature = NULL; store->genCode = 1; /* id of default translation table */ store->errorMessage = NULL; global_before_f = 0; /* reset flag for next feature */ rv = SlbMakeFeature (store->features->buff, entry, store->entrySeq, &store->resultSeq, &store->feature); FilUBack (entry->file[1], fileSave); if (!rv) return 0; if (_ErrIs (rv) && (rv != e__operatorafternotallowed && rv != e__operatorbeforenotallowed)) { _ErrMsg (rv); cnt_syntaxerror++; return 0; } if (store->feature->isPseudo) /* pseudo gene */ return 0; /* ** if the sequence - for some reason - is not empty, then do the ** translation and, if all is correct, print the ** TREMBL entry, otherwise an error report */ if (!store->resultSeq) return 0; store->genCode = TaxaToTranslTable(store->organism); if (store->feature->codeTableNum>0) /* transl_table = .. */ if (store->genCode != store->feature->codeTableNum) { fprintf(stderr, "\nCC WARNING: used code table id %d instead of %d\n", store->feature->codeTableNum, store->genCode); store->genCode = store->feature->codeTableNum; } if (CDSTranslate (store)) { TremblPrint (store, cdsN); /* print value structure */ return 0; } else { TremblErrorPrint (store); /* print value structure */ cnt_trerr++; return 0; } return 1; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** main section... */ int main (int argc, char **argv) { ARGoLIST *arglist; SLBo *lib; ENTRYo *entry; CDSoSTORE store; INT4 n=0, cdsN; char *libraryName, *fileName; FILoL_S fileSave; SrsEnv (); LibOpen ("srswin"); MsgSetFnct (PrintMessage); CDSStoreInit (&store, NULL); /* ** process command line */ arglist = (ARGoLIST *) LibObjByName ("arglist", "trembl"); argc = ArgGet (arglist, argc, argv); libraryName = ParGetStr ("libName"); if (!(lib = (SLBo *) LibObjByName ("library", libraryName))) _ErrExit3 (e__objectunknown, "library", libraryName); /* ** if a file name is specified then supersede the one defined ** in ODD */ if (*(fileName = ParGetStr ("tremblInFile"))) { char dirName[80], name[80]; FilParse (fileName, dirName, FILxDEST); /* strcat (dirName, "/"); */ /* must be added */ FilParse (fileName, name, FILxNAME); LibSetFlatFileDir (lib, dirName); LibSetFlatFileName (lib, name); } /* ** open databank and iterate over all entries */ entry = EntryOpenStream (lib); while (EntryNext (entry)) { CDSStoreInit (&store, entry); if (SlbNextSequence (entry)) { SlbGetSequence (entry, &store.entrySeq); FilUSave (entry->file[1], &fileSave); } CDSStoreEntry (&store, entry); /* ** if the entry has any features, iterate and process CDS ** features */ if (store.features) { cdsN = 0; LstFirst ((void**) &store.features); do { if (!strncmp (store.features->name, "CDS", 3)) CDSMakeEntry (&store, entry, &fileSave, ++cdsN); } while (LstNext ((void**) &store.features)); } /* print progress */ if (!(++n % 1000)) fprintf(stderr, "...%d\n", n); } /* ** print final report if not translating a single file */ if (!*ParGetStr ("tremblInFile")) { fprintf (stderr, "\n********* Program correctly finished ******\n\n"); fprintf (stderr, "syntax errors: %d\n", cnt_syntaxerror); fprintf (stderr, "translation errors: %d\n", cnt_trerr); fprintf (stderr, "illegal start codon: %d\n", cnt_firstcodonerror); fprintf (stderr, "correct: %d\n", cnt_correct); } exit(0); } #include #include #include #include "srs.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _FUNCTION #include "oddclass.h" ICAoSYNTAX *IcaInitSyntax (ICAoSYNTAX *); static INT4 PrintMessage (MSGo *msg); void ReadBuiltin (ICAoSYNTAX *syntax) { FILEo *file; ICAoJOB *job; SDLo *odd; Int4 opt; /* never write C-conversion */ opt = ParGetBool("ica2C"); ParDefBool("ica2C", 0); ParDefBool ("doSection", 1); /* pointers instead of numbers */ job = IcaCreateJob (syntax); /* process class information */ odd = OddInit (def, 1); file = FileNew ("SRSSDL:builtin.ic"); if (!FileOpen (file)) _ErrExit2 (e__filnotok, "SRSSDL:builtin.ic"); IcaNewJob (job, file, NULL); IcaGetTokenList (job, "prog"); IcaEndJob (job); VarExec (job->prog); /* process objects */ odd = OddInit (odd, 2); file = FileNew ("SRSSDL:builtin.i"); if (!FileOpen (file)) _ErrExit2 (e__filnotok, "SRSSDL:builtin.i"); IcaNewJob (job, file, NULL); IcaGetTokenList (job, "prog"); IcaEndJob (job); FileClose (job->file); job->file = NULL; VarExec (job->prog); ParDefBool ("ica2C", opt); } main(int argc, char **argv) { SDLo *odd; ARGoLIST *arglist; FILEo *file; ICAoJOB *job; ICAoSYNTAX *syntax; char line[MAXLINESIZE], *tokStr, *name; INT4 printAll, tokCode, c, rv; SrsEnv (); LibOpen ("srs5"); MsgSetFnct ((FUNC)IcaPrintMessage); arglist = LibObjByName ("arglist", "try"); argc = ArgGet (arglist, argc, argv); if (!ParGetBool ("useIni")) syntax = IcaInitSyntax ((ICAoSYNTAX*)LibObjByName ("syntax", "icarus")); else syntax = (ICAoSYNTAX*)LibObjByName ("syntax", "icarus"); odd = OddInit (def, 1); if (ParGetBool ("doCommandInfo")) { IargPrintInfo (); exit (0); } if (argc != 2) { ArgUsage (arglist); _ErrorExit (); } job = IcaCreateJob (syntax); file = FileNew(argv[1]); if (!FileOpen (file)) _ErrExit2 (e__filnotok, argv[1]); IcaNewJob (job, file, NULL); IcaGetTokenList (job, "prog"); IcaEndJob (job); FileClose (job->file); job->file = NULL; if (job->prog) { if (ParGetBool ("readBuiltin")) ReadBuiltin (syntax); VarExec (job->prog); } if (ParGetBool ("doClassInfo")) { odd = OddInit (odd, 2); OddWriteClassInfo (odd); } } #include "strv.h" #include "blub.h" typedef struct TRYOBJ { OBJo head; int a; STRv b; struct TRYOBJ* part; } TRYOBJ; typedef struct TRYMORE { TRYOBJ head; STRv more; ListAttr list; int arr[10]; } TRYMORE; int main() { TRYOBJ* o=ObjCpy(Object); TRYOBJ* o1,*oc; TRYMORE* o2; void *r1, *r2, *r3,*a1; AttrIter ai; Iter i; int* list; OBJpStream s; ObjInit(); ObjAttrNew(&o, StrTemp("a"), int)=3; ObjAttrNew(&o, StrTemp("b"), STRv)=StrCpyS("ciao"); ObjAttrNewRef(&o, StrTemp("part"),TRYOBJ*)=NULL; ObjPrint(o); printf("\n"); ObjMakeClass(o,StrTemp("TRYOBJ")); o1=ObjCpy(o); ObjChange(&o1,TRYOBJ*); o1->part=ObjCpy(o); ObjChange(&ObjChange(&o1, TRYOBJ*)->part, TRYOBJ*)->a=10; o1->a=5; StrSetS(&o1->b,"containing"); o2=ObjCpy(o1); ObjAttrNew(&o2,StrTemp("more"),STRv)=StrCpyS("someMore"); list=&ObjListNew(&o2,4,int); *list++=1; *list++=2; *list++=3; *list++=4; ObjDebug(o); ObjDebug(o1); ObjDebug(o2); ObjMakeClass(o2,StrTemp("TRYMORE")); ObjListApp(&o2,int)=6; ObjListApp(&o2,int)=7; ObjDebug(o2); ObjListCut((void**)&o2,ObjListWith(o2,1),3); ObjDebug(o2); /* try access by name */ printf("%d %s\n", ObjAttr(o,StrTemp("a"),int), Str(ObjAttr(o,StrTemp("b"),STRv))); printf("%d %s\n", ObjAttr(o1,StrTemp("a"),int), Str(ObjAttr(o1,StrTemp("b"),STRv))); printf("%d %s\n", ObjAttr(o2,StrTemp("2"),int), Str(ObjAttr(o2,StrTemp("more"),STRv))); /* attribute iteration */ printf("iterating:\n"); for (ai=ObjAttrFirst(o2); ai; ObjAttrNext(o2,&ai)) { STRv name=ObjAttrName(o2,ai); printf("%s\n",Str(name)); StrDel(name); } /* testing list iteration */ printf("list:\n"); for (i=ObjListFirst(o2);i;ObjListNext(o2,&i)) { printf("%i:%i\n",ObjListPos(o2,i),ObjListIn(i,int)); } printf("%d",ObjListCard(o2)); PathInit(); oc=ObjCpy(o1); r1=PathStaticImpl(theRoot,StrTemp("o"),&o,OBJvClass,NULL); r2=PathStaticImpl(theRoot,StrTemp("o1"),&o1,OBJvClass,NULL); r3=PathStaticImpl(theRoot,StrTemp("o2"),&o2,OBJvClass,NULL); a1=Path("o1.part.a"); PathCompileImpl(a1); PathChange(a1, int)=6; ObjDebug(o1); ObjDebug(oc); /* try stream output */ printf("\n-----------------saving\n"); ObjDebug(o); ObjDebug(o1); ObjDebug(o2); ObjDebug(oc); PathPrint(a1); s=ObjStreamOpen("blabla","wb",TRUE); ObjStore(o, s); ObjStore(o1, s); ObjStore(o2, s); ObjStore(oc, s); RefStore(a1,s); ObjStreamClose(s); /* try stream input */ s=ObjStreamOpen("blabla","rb",TRUE); ObjSet(&o, ObjLoad(s)); ObjSet(&o1, ObjLoad(s)); ObjSet(&o2, ObjLoad(s)); ObjSet(&oc,ObjLoad(s)); ObjSet(&a1,RefLoad(s)); ObjStreamClose(s); ObjDebug(o); ObjDebug(o1); ObjDebug(o2); ObjDebug(oc); PathPrint(a1); /* release everything */ ObjDel(o); ObjDel(o1); ObjDel(o2); ObjDel(oc); ObjDel(a1); ObjDel(r1); } char unix_map_srs_ID[] = "$Id: unix_map.c,v 1.2 1996/06/24 13:47:02 etzold Exp $"; /* ** ** $RCSfile: unix_map.c,v $ ** $Revision: 1.2 $ ** $Date: 1996/06/24 13:47:02 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** SRS V3.0 Copyright by Thure Etzold ** Unix port: This module has been modified in major parts ** by Lukas Rosenthaler and Reinhard ** ** Author: Thure Etzold ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** Requires: sm, message ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** maps a file to memory and provides functions for ** writing to the file, saving and delteing the mapped ** memory; Either a file can be created with specified ** nr. of blocks or existing file can be extended by ** nr. of blocks. ** before deleting the mapsection the memory is saved to ** the file and the unused space of it is deleted; ** the output file is a ** Two functions for writing are provided for assuring ** that the map section is written to in a sequential ** manner. ** ** map-section-file: ** 1) LF-stream file (C-stream-file) ** 2) first longword contains number of bytes written to file ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include #include "message.h" #include "futil.h" #include "map.h" #define PAGE_SIZE (512*sizeof (char)) #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define TMPSTR_LEN 256 /***************************************************************************** * * create a map secion. This function is a dummy function which is not used * in the unix version ! It's solely included for compatibilty with the VMS * code. It should be removed later !! * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : no meaning * void *buff : no meaning * INT4 buff_z : no meaning * * side effects : none *- ***************************************************************************** */ INT4 MapCreSec (MAPo *m, void *buff, INT4 buff_z) { _ErrRet2 (e__nonounix, "MapCreSec"); return 1; } /***************************************************************************** * * <...> * *---------------------------------------------------------------------------- * * Returns : INT4 * perform page arithmetic * * Parameters : * INT4 a : dividend * INT4 b : divisor * * side effects : none *- ***************************************************************************** */ INT4 MapMOD (INT4 a, INT4 b) { INT4 quot; quot = a/b; return ((a == (quot * b)) ? quot : ++quot); } /***************************************************************************** * * Opens a file and reads it into core memory. The mechanism is read only, * that is, the core memory contents will *NOT* be updated in the file ! * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * char *fil_n : address of filename * void *buff : address of buffer or NULL. If NULL is supplied, then * the appropriate amount of core is allocated inside the * routine * INT4 buff_z : amount of core which is to be "mapped". IF "buff" is not * NULL, "buff_z" must *NOT* be larger than the size of the * "buff" ! * * side effects : none *- ***************************************************************************** */ INT4 MapMem (MAPo *m, char *fil_n, void *buff, INT4 buff_z) { char *tmp, t_fil_n[TMPSTR_LEN]; INT4 page_n; INT4 fid, n, nn; strcpy (t_fil_n, fil_n); /* ** open the file, readonly */ if ((fid = open (_FilLN (t_fil_n), O_RDONLY, 0666)) == -1) { _ErrRet (e__filopenerr); } /* ** check, if buffer memory is supplied. If so, pray that it's enough ** memory to hold the data to be read. Otherwise, a friendly core dump... ** If no buffer is supplied, detemine the amount of memory used (given by ** the file size, and allocate the memory. **/ if (buff == NULL) { /* ** get file size */ if ((buff_z = lseek (fid, 0, SEEK_END)) == -1) { _ErrRet2 (e__seekfail, t_fil_n); } /* ** set file pointer back to beginning of file */ if (lseek (fid, 0, SEEK_SET) == -1) { _ErrRet2 (e__seekfail, t_fil_n); } page_n = buff_z / 512 + ((buff_z % 512 > 0) ? 1 : 0); /* ** allocate "page_n" bytes of core */ if ((tmp = (char *) malloc (page_n * PAGE_SIZE)) == NULL) { _ErrRet2 (e__allocfail, "MapMem"); } m->isAllocBuff=1; } else { /* ** calculate the amount of memory. This calculations are remains from ** VMS ... */ page_n = buff_z / 512 + ((buff_z % 512 > 0) ? 1 : 0); m->isAllocBuff=0; tmp = buff; } /* ** now we read in the data from the file, which has been opened ** before, and the file_id is in m->chan... */ m->chan = fid; n = 0; while (n < page_n*PAGE_SIZE) { nn = read (fid, tmp + n, page_n*PAGE_SIZE - n); if (nn == -1) { _ErrRet2 (e__readerr, "MapMem"); } if (nn == 0) { /* EOF detected */ /* ** jump out of loop, we have EOF !! */ goto eof_detected; } n += nn; } eof_detected: if (close ((INT4) m->chan) == -1) { _ErrRet2 (e__filcloseerr, t_fil_n); } /* ** update "m" struct (VMS compatibilty...) */ m->data = tmp; /* pointer to allocated core memory */ m->xbyt = n; /* number of bytes read */ m->wrt_f = FALSE; /* we don't want to write to the file ! */ m->trnc_f = TRUE; /* doesn't matter... */ m->foff = (UINT4 *) m->data; /* m->off = m->data + *(m->foff); not needed and crashes on some sunos */ (void) strncpy (m->filn, t_fil_n, FILxXNAM); return 1; } /***************************************************************************** * * allocates "nbloc" pages (a 512 bytes) of memory and marks them for * "mapping" which means that upon closure/flushing the contents will be * written to a file. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * char *filn : address of filename * INT4 nbloc : number of 512 byte pages which are to be allocated and * marked for mapping * * side effects : none *- ***************************************************************************** */ INT4 MapAlloc (MAPo *m, char *filn, INT4 nbloc) { char *tmp; /* ** allocate "nbloc" pages of memory */ if ((tmp = (char *) malloc (nbloc * PAGE_SIZE)) == NULL) { _ErrRet2 (e__allocfail, "MapAlloc"); } /* ** initialize allocated memory to zero. */ (void) memset (tmp, 0, nbloc*PAGE_SIZE); /* ** update "m" struct (VMS compatibilty...) */ m->data = tmp; m->xbyt = nbloc*PAGE_SIZE; m->trnc_f = TRUE; /* truncate on closure/flushing */ m->wrt_f = TRUE; /* contents of allocated memory is written */ m->off = m->data + 4; m->foff = (UINT4 *) m->data; *(m->foff) = 4; (void) strncpy(m->filn, _FilTempLN (filn), FILxXNAM); return 1; } /***************************************************************************** *+ INT4 MapExtend (MAPo *m, char *filn, INT4 nbloc) *---------------------------------------------------------------------------- * * Description of MapExtend: * * adds "nbloc" 512 byte pages of core to existing "mapped" memory region. * In effect, adding core is done in junks of 64 pages. So "nbloc" is rounded * to be a multiple of 64! * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * char *filn : address of filename * INT4 nbloc : number of 512 byte pages to add to existing "mapped" * memory. * * side effects : none *- ***************************************************************************** */ INT4 MapExtend (MAPo *m, char *filn, INT4 nbloc) { INT4 size, orig_size; char *tmp, t_filn[TMPSTR_LEN]; INT4 fid, n, nn; /* ** get size of existing map-file to be extended */ if ((fid = open (_FilLN (filn), O_RDONLY)) == -1) { _ErrRet2 (e__filopenerr, t_filn); } /* ** determine size of file */ if ((size = lseek (fid, 0, SEEK_END)) == -1) { _ErrRet2 (e__seekfail, t_filn); } orig_size = size; /* ** set file pointer back to beginning of file */ if (lseek (fid, 0, SEEK_SET) == -1) { _ErrRet2 (e__seekfail, t_filn); } /* ** calculate new size (multiple of 64 512 byte pages */ size += 64*PAGE_SIZE; size += (MapMOD (nbloc, 64)*PAGE_SIZE); /* add at least nbloc of core */ /* ** */ if ((tmp = (char *) malloc (size)) == NULL) { _ErrRet2 (e__allocfail, "MapExtend"); } n = 0; while (n < orig_size) { if ((nn = read (fid, tmp + n, orig_size - n)) == -1) { _ErrRet2 (e__readerr, "MapExtend"); } if (nn == 0) break; n += nn; } if (close (fid) == -1) { _ErrRet2 (e__filcloseerr, "MapExtend"); } fid = 0; /* ** update map-descriptor with new values */ m->data = tmp; m->trnc_f = TRUE; m->xbyt = size; /* new size */ m->foff = (UINT4 *) m->data; m->off = m->data + *(m->foff); /* m->fid = fid; */ strcpy(m->filn, t_filn); return 1; } /***************************************************************************** *+ INT4 MapFree (MAPo *m) *---------------------------------------------------------------------------- * * Description of MapFree: * * If "mapped" core memory is readonly, then the allocated memory is just * released. Otherwise, the memory content is written to the file with the * filename given in the map-descriptor. Possibly the file is truncated to * the length actually used. This is controlled by the flag "m->trnc_f" of the * map-descriptor. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * * side effects : none *- ***************************************************************************** */ INT4 MapFree (MAPo *m) { INT4 fid; unsigned long n, nn, size; /* ** if "mapped" core memory contents will be written to file, close last ** record by '\n' ! */ if (m->wrt_f) { *(m->off) = '\n'; *(m->off + 1) = '\n'; } /* ** test, if file should be written */ if (m->wrt_f) { /* ** first we have to open the file. We will generate a new file, ** even if a file with the same name already exists ! */ #ifndef dos if ((fid = open (m->filn, (O_WRONLY | O_CREAT | O_TRUNC), 0666)) == -1) { #else if ((fid = open (m->filn, (O_WRONLY | O_CREAT | O_BINARY | O_TRUNC), 0666)) == -1) { #endif _ErrRet2 (e__filopenerr, m->filn); } /* ** let's calculate the number of bytes to write. ** ATTENTION: This code possibly has to be changed: ** to my knowlegde, VMS mapped files are written always ** in PAGE_SIZE junks (also "MapMem" reads PAGE_SIZE junks...). ** ** if the file is to be truncated to the length actually memory has been ** used, then we calculate the file size by the difference of the start ** address and the offset of the last write access to the "mapped" core ** memory. This is possible since all access is (should be !) done by ** routines which update "m->off". */ if (m->trnc_f) { size = (unsigned long) (m->off - m->data) + 1; } else { size = m->xbyt; } n = 0; while (n < size) { if ((nn = write (fid, m->data + n, size - n)) == 0) { _ErrRet3 (e__filwriteerr, m->filn, (size - n)); } n += nn; } /* ** close the file */ if (close (fid) == -1) { _ErrRet2 (e__filcloseerr, m->filn); } } /* ** now we will free the allocated memory */ if (m->isAllocBuff) free (m->data); /* free allocated memory */ m->data = NULL; /* set pointer to NIL */ m->xbyt = 0; /* set size to 0 */ return 1; } /***************************************************************************** *+ INT4 MapTruncate (MAPo *m) *---------------------------------------------------------------------------- * * Description of MapTruncate: * * Truncate a file which was mapped. This function is a dummy function * which is not used in the unix version ! It's solely included for * compatibilty with the VMS code. It should be removed later !! * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * * side effects : none *- ***************************************************************************** */ INT4 MapTruncate (MAPo *m) { _ErrRet2 (e__nonounix, "MapTruncate"); return 1; } /***************************************************************************** *+ INT4 MapNew (MAPo *m, UINT4 *fadd) *---------------------------------------------------------------------------- * * Description of MapNew: * * Returns relative section file's address of begin of unused space. * Only MapPutS and MapWrite may be used for writing to the map-section * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * UINT4 *fadd : address of address where to put file address (???) * ( too many recursive addresses for me... ;-) ) * * side effects : none *- ***************************************************************************** */ INT4 MapNew (MAPo *m, UINT4 *fadd) { long int ptr_diff; #ifndef dos /* ** the map-memory we return should be aligned at least to the pointer type */ ptr_diff = (long int) m->off % sizeof (char *); if (ptr_diff != 0) { m->off += (sizeof (char *) - ptr_diff); *(m->foff) += (sizeof (char *) - ptr_diff); } #endif *fadd = *(m->foff); return 1; } /***************************************************************************** *+ INT4 MapCNew (MAPoCCH *c, UINT4 *fadd) *---------------------------------------------------------------------------- * * Description of MapCNew: * * Returns relative file address of begin of unused space in cache. * Only MapCWrite may be used for writing to the cache. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * UINT4 *fadd : address of address where to put file address * (same comment as above...) * * side effects : none *- ***************************************************************************** */ INT4 MapCNew (MAPoCCH *cache, UINT4 *fadd) { #ifdef xxx long int ptr_diff; /* ** the map-memory we return should be aligned at least to the pointer type */ ptr_diff = (long int) cache->off % sizeof (char *); if (ptr_diff != 0) { cache->off += (sizeof (char *) - ptr_diff); *(cache->foff) += (sizeof (char *) - ptr_diff); } #endif *fadd = *(cache->foff); return 1; } /***************************************************************************** *+ INT4 MapPutS (MAPo *m, char *s) *---------------------------------------------------------------------------- * * Description of MapPutS: * * Puts a 0-terminated string at the end of used space in map-section. * map->off and map->foff are updated according to string length. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * char *s : string to add * * side effects : none *- ***************************************************************************** */ INT4 MapPutS (MAPo *m, char *s) { INT4 len; len = strlen(s); if (*m->foff + len + 1 > m->xbyt) return (e__eom); strcpy(m->off, s); m->off = m->off + len + 1; *(m->foff) = *(m->foff) + len + 1; return 1; } /***************************************************************************** *+ INT4 MapWrite (MAPo *m, char *s, INT4 n) *---------------------------------------------------------------------------- * * Description of MapWrite: * * appends "n" bytes to "mapped" core memory * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPo *m : address of map-descriptor * char *s : address of data to add * INT4 n : number of bytes to add * * side effects : none *- ***************************************************************************** */ INT4 MapWrite (MAPo *m, char *s, INT4 n) { long int ptr_diff; #ifndef dos /* * the map-memory we return should be aligned at least to the pointer type */ ptr_diff = (long int) m->off % sizeof (char *); if (ptr_diff != 0) { m->off += (sizeof (char *) - ptr_diff); *(m->foff) += (sizeof (char *) - ptr_diff); } #endif if (*m->foff + n > m->xbyt) return (e__eom); (void) memcpy(m->off, s, n); m->off += n; *(m->foff) += n; return 1; } /***************************************************************************** *+ INT4 MapMalloc (MAPo *m, INT4 n) *---------------------------------------------------------------------------- * * Description of MapMalloc: * * allocates memory in a "mapped" core memory region. The returned pointer * is aligned to the pointer type (char *). * *---------------------------------------------------------------------------- * * Returns : char * * address of allocated "mapped" memory region * * Parameters : * MAPo *m : address of map-descriptor * INT4 n : number of bytes to reserve * * side effects : none *- ***************************************************************************** */ char *MapMalloc (MAPo *m, INT4 n) { char *off_s; long int ptr_diff; #ifndef dos /* ** the map-memory we return should be aligned at least to the pointer type */ ptr_diff = (long int) m->off % sizeof (char *); if (ptr_diff != 0) { m->off += (sizeof (char *) - ptr_diff); *(m->foff) += (sizeof (char *) - ptr_diff); } #endif if (*(m->foff) + n > m->xbyt) return NULL; off_s = m->off; m->off += n; *(m->foff) += n; return (off_s) ; } /***************************************************************************** * * Description of MapFOpen: * * Open a file for reading/writing * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * INT4 acc_o : access mode (MAPxREAD or MAPxWRITE), is ignored !! * * side effects : none *- ***************************************************************************** */ INT4 MapFOpen (MAPoCCH *cache, INT4 acc_o) { #ifndef dos if ((cache->fid = open (cache->filn, (O_RDWR | O_CREAT), 0666)) == -1) { #else if ((cache->fid = open (cache->filn, (O_RDWR | O_CREAT | O_BINARY), 0666)) == -1) { #endif _ErrRet2 (e__filopenerr, cache->filn); } return 1; } /***************************************************************************** * * Opens file for block-IO and writes specified number of blocks to * block offset and closes file. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * INT4 nbloc : number of 512 byte pages to write * INT4 off : offset in file (in 512 byte pages) where to start * writing data * * side effects : none *- ***************************************************************************** */ INT4 MapWriteBlk (MAPoCCH *cache, INT4 nbloc, INT4 off) { INT4 size, wtotbytes_n, wbytes_n; if (cache->fid == 0) MapFOpen (cache, MAPxWRITE); /* ** first we skip "off" blocks */ if (off > 0) { if (lseek (cache->fid, (off - 1)*PAGE_SIZE, SEEK_SET) == -1) { _ErrRet2 (e__seekfail, cache->filn); } } /* ** now let's write nbloc * PAGE_SIZE bytes */ size = nbloc * PAGE_SIZE; wtotbytes_n = 0; while (wtotbytes_n < size) { if ((wbytes_n = write (cache->fid, cache->buff + wtotbytes_n, size - wtotbytes_n)) == -1) { _ErrRet3 (e__filwriteerr, cache->filn, (size - wtotbytes_n)); } if (wbytes_n == 0) break; wtotbytes_n += wbytes_n; } return 1; } /***************************************************************************** * * closes file theat was opend for read/update access (for fseek) * writes 1st half of cache to file, shifts 2nd half of cache to begin * and opens file again for read/upd access (no sharing possible); * * REMARK : This routine has *NOT* been undestood. Some more comment would * be appreciated (Dr. L. Rosenthaler, 30-dec-1992). * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : addresss of cache-descriptor * * side effects : none *- ***************************************************************************** */ INT4 MapFlush (MAPoCCH *cache) { INT4 shift = cache->hbloc * 512; MapWriteBlk (cache, cache->hbloc+1, cache->fstbloc); (void) memcpy (cache->buff, cache->buff + shift, shift); cache->fstbloc += cache->hbloc; cache->off -= shift; cache->coff = cache->coff + shift; return 1; } /***************************************************************************** *+ INT4 MapCWrite (MAPoCCH *c, char *s, INT4 n) *---------------------------------------------------------------------------- * * Description of MapCWrite: * * appned "n" bytes of data to cache region * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * char *s : address of data to add * INT4 n : number of bytes to add * * side effects : none *- ***************************************************************************** */ INT4 MapCWrite (MAPoCCH *cache, char *s, INT4 n) { #ifdef xxx long int ptr_diff; /* ** the map-memory we return should be aligned at least to the pointer type */ ptr_diff = (long int) cache->off % sizeof (char *); if (ptr_diff != 0) { cache->off += (sizeof (char *) - ptr_diff); *(cache->foff) += (sizeof (char *) - ptr_diff); } #endif memcpy ( (void *) cache->off, (void *) s, n); cache->off = cache->off + n; *(cache->foff) = *(cache->foff) + n; if (cache->off > cache->buff + (cache->nbloc - 1) * 512) MapFlush (cache); return 1; } /***************************************************************************** *+ INT4 MapCWriteNA (MAPoCCH *c, char *s, INT4 n) *---------------------------------------------------------------------------- * * Description of MapCWriteNA: * * appned "n" bytes of data to cache region, NOT ALIGNED !!! * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * char *s : address of data to add * INT4 n : number of bytes to add * * side effects : none *- ***************************************************************************** */ INT4 MapCWriteNA (MAPoCCH *cache, char *s, INT4 n) { (void) memcpy( (void *) cache->off, (void *) s, n); cache->off = cache->off + n; *(cache->foff) = *(cache->foff) + n; if (cache->off > cache->buff + (cache->nbloc - 1) * 512) MapFlush (cache); return 1; } /***************************************************************************** *+ INT4 MapReadBlk (MAPoCCH *c, INT4 nbloc, INT4 off) *---------------------------------------------------------------------------- * * Description of MapReadBlk: * * Opens file for block-IO and reads specified number of blocks from * block offset and closes file. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * INT4 nbloc : number of 512 byte pages to read * INT4 off : offset (in 512 byte pages) where to start reading * (first block is equal 1 !!) * * side effects : none *- ***************************************************************************** */ INT4 MapReadBlk (MAPoCCH *c, INT4 nbloc, INT4 off) { INT4 size, n, nn; size = nbloc * PAGE_SIZE; if (c->fid == 0) MapFOpen (c, MAPxWRITE); /* ** first we skip "off" blocks */ if (off > 0) { if (lseek (c->fid, (off - 1)*PAGE_SIZE, SEEK_SET) == -1) { _ErrRet2 (e__seekfail, c->filn); } } /* ** now let's read nbloc*PAGE_SIZE bytes */ size = nbloc * PAGE_SIZE; n = 0; while (n < size) { if ((nn = read (c->fid, c->buff + n, size - n)) == -1) { _ErrRet2 (e__readerr, c->filn); } if (nn == 0) break; n += nn; } return 1; } /***************************************************************************** * * initialize cache, that is allocate memory, open files etc. . * MAPoCCH->foff must be set before calling (0 = no existing file) * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * char *fil_nm : filename * unsigned *foff : address of offset in file * INT4 new_f : flag. If set, a new file will be opened * * side effects : none *- ***************************************************************************** */ INT4 MapInitCache (MAPoCCH *cache, char *fil_nm, unsigned *foff, INT4 new_f) { INT4 nbloc; if ((cache->filn = (char *) malloc (strlen(_FilTempLN (fil_nm)) + 1))==NULL){ _ErrRet2 (e__allocfail, "cache buffer"); } (void) strcpy (cache->filn, _FilTempLN (fil_nm)); cache->foff = foff; if (new_f) *foff = 0; cache->hbloc = MapMOD (cache->nbloc, 2); cache->nbloc = cache->hbloc * 2; /* even number */ if ((cache->buff = (char *) malloc (cache->nbloc * 512)) == 0) { _ErrRet2(e__allocfail, "cache buffer"); } cache->fid = 0; if (*(cache->foff) == 0) { cache->new_f = TRUE; cache->off = cache->buff; cache->fstbloc = 1; cache->coff = 0; } else { cache->new_f = FALSE; nbloc = MapMOD(*(cache->foff), 512); if ((cache->fstbloc = nbloc - cache->hbloc + 1) <= 1) { cache->fstbloc = 1; cache->coff = 0; } else { nbloc = cache->hbloc; cache->coff = NULL; cache->coff = cache->coff + cache->fstbloc-1 * 512; } cache->off = cache->buff + (*cache->foff - cache->coff); MapReadBlk (cache, nbloc, cache->fstbloc); } return 1; } /***************************************************************************** * * flushes cache to file and frees allocated memory * *---------------------------------------------------------------------------- * * Returns : INT4 * sucess code * * Parameters : * MAPoCCH *c : address of cache-descriptor * * side effects : none *- ***************************************************************************** */ INT4 MapCloseCache (MAPoCCH *cache) { INT4 nbloc; nbloc = MapMOD (*(cache->foff) - cache->coff, PAGE_SIZE); MapWriteBlk (cache, nbloc, cache->fstbloc); /* ** close file...set file descriptor to 0 to indicate that cache has been ** deleted and free allocated memory */ if (close (cache->fid) == -1) { _ErrRet2 (e__filcloseerr, cache->filn); } cache->fid = 0; free (cache->filn); free (cache->buff); return 1; } /***************************************************************************** *+ INT4 MapRdMem (char *fil_nm, void **p) *---------------------------------------------------------------------------- * * Description of MapRdMem: * * read a cache file into a private area of core memory * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * char *fil_nm : filename * void **p : pointer to address of allocated memory * * side effects : none *- ***************************************************************************** */ INT4 MapRdMem (char *fil_nm, void **p) { MAPoCCH *c; char *data; INT4 n, nn, size; /* ** allocate cache struct */ if ((c = (MAPoCCH *) calloc (1, sizeof (MAPoCCH))) == NULL) { _ErrRet2 (e__allocfail, "MapRdMem"); } c->fid = 0; if ((c->filn = (char *) malloc (strlen (_FilTempLN (fil_nm)) + 1)) == NULL) { _ErrRet2 (e__allocfail, "MapRdMem"); } /* ** open file */ (void) strcpy (c->filn, _FilTempLN (fil_nm)); MapFOpen(c, MAPxREAD); /* ** determine size of file */ if ((size = lseek (c->fid, 0, SEEK_END)) == -1) { _ErrRet2 (e__seekfail, c->filn); } /* ** set file pointer back to beginning of file */ if (lseek (c->fid, 0, SEEK_SET) == -1) { _ErrRet2 (e__seekfail, c->filn); } /* ** allocate core memory to hold file contents */ if ((data = (char *) malloc (size)) == NULL) { _ErrRet2 (e__allocfail, "MapRdMem"); } *p = data; n = 0; while (n < size) { if ((nn = read (c->fid, data + n, size - n)) == -1) { _ErrRet2 (e__readerr, c->filn); } if (nn == 0) break; n += nn; } if (close (c->fid) == -1) { _ErrRet2 (e__filcloseerr, c->filn); } c->fid = 0; free (c->filn); return 1; } /***************************************************************************** * * write a 4 byte integer to a specified location in file * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * UINT4 fadd : offset in file where to wwrite integer * UINT4 val : integer to write to file * * side effects : none *- ***************************************************************************** */ INT4 MapCUpdate (MAPoCCH *c, UINT4 fadd, char *fip) { /* ** set file pointer at position given by "fadd" */ if (lseek (c->fid, fadd, SEEK_SET) == -1) { _ErrRet2 (e__seekfail, c->filn); } /* ** now write 4 bytes */ if (write (c->fid, fip, 4) != 4) { _ErrRet3 (e__filwriteerr, c->filn, 4); } return (1); } /***************************************************************************** * * Translates relative byte offset in file into cache address if referring * to location in cache. * *---------------------------------------------------------------------------- * * Returns : INT4 * success code * * Parameters : * MAPoCCH *c : address of cache-descriptor * UINT4 fadd : offset in file * UINT4 *ptr : address in cache memory * * side effects : none *- ***************************************************************************** */ INT4 MapInCache (MAPoCCH *c, UINT4 fip, void **ptr) { if (fip < c->coff) { return 0; } else { *ptr = fip - c->coff + c->buff; } return 1; } /**api* MapDuplicateOverlap *************************************************** ** ** Addresses that need updating may be exactly on the boundary between ** file and memory cache ...in that case both locations need updating. ** This function updates in the cache only those bytes that overlaps. ** ** INPUT: address of IDS-file object [R] ** file pointer to first ID in the list [W] ** IMPLICIT: ** ** RETURNS: length of overlap ** 0 if no overlap exists */ INT4 MapDuplicateOverlap (MAPoCCH *cache, UINT4 fip, void *buff, INT4 size) { INT4 overlapLen; overlapLen = size - (cache->coff - fip); if ((cache->coff > fip) && overlapLen > 0) { memcpy (cache->buff, (char *) buff + size - overlapLen, overlapLen); return overlapLen; } else return 0; } char variable_ID[] = "$Id: variable.c,v 1.10 1996/08/11 23:24:14 etzold Exp $"; /* ** $RCSfile: variable.c,v $ ** $Revision: 1.10 $ ** $Date: 1996/08/11 23:24:14 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Authors: Thure Etzold ** Anatoly Ulyanov ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387529 ** Email: etzold@embl-heidelberg.de ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Description ** =========== ** ** functions for managing variables of various types. ** A variable is always contained in a list which can be nested ** Variables can be associated with names and be accessed by the name ** or index number within the list (index numbers do not work on the outmost ** list). ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "message.h" #include "sm.h" #include "strv.h" #include "lst.h" #include "dict.h" #include "variable.h" /* more arguments */ #define _mA 0,0,0,0,0,0,0,0,0,0,0,0 #define _VarUnalias(x) if ((x)->type == VARxALIAS) (x) = VarUnalias(x) #define _VarHandleTypeEval(x) \ if ((x)->isDelayedType) { \ if (!(x)->isTypeEval) \ VarGetType (x); \ (x)->isTypeEval = 0; \ } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** global and module wide variables */ extern VARoSCOPE *globalScope; static classId=0; static VARo *VarNewIn (VARoSCOPE **scopePtr, char *name); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** for the variable dictionary */ static void* VarToKey (DictElem* e) { return (*(VARo **)e)->name; } static CLASSoDICT dictClass = { (ValComparer)strequal, (ValHasher)strhash, (KeyAccessor)VarToKey, NULL, 0 }; static VARo *VarUnalias (VARo *alias) { if (alias->code == 1) return (alias->v.alias); else if (!alias->isReadFunction) { if (!globalScope) _ErrExit (f__noVarScope); return (VARo*) ((ULONG)globalScope->var + (ULONG)alias->v.alias); } else return (*alias->v.varGet)(alias); } /***** VarGetType ************************************************************* ** ** Return the type of argument variable ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ char VarGetType (VARo *var) { _VarUnalias(var); if (!var->isTypeEval && var->isDelayedType) { (*var->typeGet)(var,_mA); var->isTypeEval = 1; } return (var->type); } /***** VarGetTypeName ********************************************************* ** ** Converts a type (list) into a readable string (mainly used for printing ** error messages). ** Function returns the string and make sure that for at least three ** successive calls different bufferes will be used. ** ** INPUT: one or combination of types [R] ** IMPLICIT: ** ** RETURNS: string with readable type name(s) */ static char *VarGetTypeName (INT4 type) { switch (type) { case VARxSTRING: return "string"; case VARxSTRV: return "strv"; case VARxINT: return "int"; case VARxREAL: return "real"; case VARxOBJECT: return "object"; case VARxLIST: return "list"; case VARxVAR: return "var"; case VARxALIAS: return "alias"; case VARxUNKNOWN: return "unknown"; default: _ErrExit2 (e__unknownoption, "type in VarError"); } } /***** VarError *************************************************************** ** ** Common error message call ** ** INPUT: variable object [R] ** expected variable type [R] ** message line [R] ** ** IMPLICIT: ** ** RETURNS: */ static void VarError(VARo *var, char *type, char *message) { char *name; if (!(name = VarGetName (var))) name = "unnamed"; _ErrExit5 (e__icavartype, name, VarGetTypeName (var->type), message, type); return; } /***** VarInit **************************************************************** ** ** Called from the list management functions. Initializes a variable. ** ** INPUT: pointer to the object ** IMPLICIT: ** ** RETURNS: */ static void VarInit (void *obj) { VARo *tmp = (VARo*)obj; if (!classId) LstManageClassFlex (&classId, sizeof (VARo), VarInit, NULL, NULL); memset (tmp, 0, sizeof (VARo)); tmp->isTypeEval = 1; tmp->class_id = classId; } /***** VarReset *************************************************************** ** ** Called from the list management functions. Initializes a variable. ** ** INPUT: pointer to the object ** IMPLICIT: ** ** RETURNS: */ void VarReset (VARo *var) { if (var->type == VARxSTRING && !var->isReadFunction && var->v.buff) BuffDelete (&var->v.buff); memset (var, 0, sizeof (VARo)); var->isTypeEval = 1; var->class_id = classId; } /***** VarNew **************************************************************** ** ** Creates a new variable object. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: */ VARo *VarNew () { VARo *var; if (!(var = (VARo *) calloc (sizeof(VARo), 1))) _ErrExit2 (e__allocfail, "variable object"); var->isTypeEval = 1; var->class_id = classId; return var; } /***** VarNewList ************************************************************* ** ** Creates a new variable object that serves as a list header. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: address of variable object */ VARo *VarNewList () { VARo *var=NULL; if (!classId) LstManageClassFlex (&classId, sizeof (VARo), VarInit, NULL, NULL); LstNewNamed ((void **) &var, classId, "varList-header"); return var; } /***** VarGet ***************************************************************** ** ** Searches for variable with specified name and creates a new one if ** not found. ** ** INPUT: variable object that represents the variable list [W] ** variable name [R] ** IMPLICIT: ** ** RETURNS: address of variable object */ VARo *VarGet (VARoSCOPE **scope, char *name) { Iter i; VARo *var; if (*scope && (i = DictWith ((*scope)->dict, name))) var = DictIn (i, VARo*); else { var = VarNewIn (scope, name); if (!(*scope)->dict) (*scope)->dict = DictCreate (&dictClass); DictSet (&((*scope)->dict), var->name, VARo*) = var; } return var; } /***** VarTemp ***************************************************************** ** ** Returns 1 of 10 variables for temporary use. ** ** INPUT: ** IMPLICIT: ** ** RETURNS: variable for temporary use */ VARo *VarTemp () { static INT4 count=0; static VARo var[10]; VARo *tmp; tmp = &var[ count++ % 10 ]; VarReset (tmp); return tmp; } /***** VarNewIn *************************************************************** ** ** Creates a new variable in the specified scope. ** ** INPUT: scope object [W] ** name of new variable [R] ** IMPLICIT: ** ** RETURNS: initialized variable object */ static VARo *VarNewIn (VARoSCOPE **scopePtr, char *name) { VARoSCOPE *scope; VARo *tmp, *varSave; INT4 initSize = 1000; /* initial size of scope */ /* scope does not yet exist */ if (!*scopePtr) { if (!(scope = (VARoSCOPE *) calloc (sizeof (VARoSCOPE), 1))) _ErrExit2 (e__allocfail, "variable stack"); if (!(scope->var = (VARo *) malloc (sizeof(VARo) * initSize))) _ErrExit2 (e__allocfail, "icarus stack array"); scope->varN = 0; scope->varAllocN = initSize; *scopePtr = scope; } else scope = *scopePtr; /* check if scope can receive a new variable ...grow if not */ if (scope->varN >= scope->varAllocN) { scope->varAllocN *= 2; varSave = scope->var; if ((scope->var = (void *) realloc (scope->var, scope->varAllocN * sizeof (VARo))) == NULL) _ErrExit2 (e__allocfail, "variable scope"); DictOffset (scope->dict, (char *) scope->var - (char *) varSave); } tmp = &scope->var[scope->varN++]; VarInit (tmp); tmp->name = (char *) malloc (strlen (name) + 1); strcpy (tmp->name, name); return tmp; } VARoSCOPE *VarCopyScope (VARoSCOPE *scope) { VARoSCOPE *tmp; INT4 k; if (!scope) return NULL; if (!(tmp = (VARoSCOPE *) calloc (sizeof (VARoSCOPE), 1))) _ErrExit2 (e__allocfail, "variable stack"); if (!(tmp->var = (VARo *) malloc (sizeof(VARo) * scope->varN))) _ErrExit2 (e__allocfail, "icarus stack array"); memcpy (tmp->var, scope->var, sizeof (VARo) * scope->varN); tmp->varN = scope->varN; tmp->varAllocN = tmp->varN; tmp->dict = DictCreate (&dictClass); for (k=0; k < tmp->varN; k++) DictSet (&(tmp->dict), tmp->var[k].name, VARo*) = &tmp->var[k]; return tmp; } void VarScopeDestroy (VARoSCOPE **scope) { VARoSCOPE *tmp; if (scope && *scope) { tmp = *scope; if (tmp->dict) DictDestroy (tmp->dict); if (tmp->varN) free (tmp->var); free (tmp); *scope = NULL; } } /***** VarSetStr ************************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ VARo *VarSetStr (VARo *var, char *s) { _VarUnalias(var); if (var->isReadFunction) _ErrExit2 (e__varisreadonly, var->name); if (!var->type) { var->type = VARxSTRING; /* var->v.buff = BuffInit (var->v.buff, 0);*/ } if (var->type == VARxSTRING) { var->v.buff = BuffInit (var->v.buff, 0); BuffCopyString (var->v.buff, s); } else if (var->type == VARxINT) var->v.num = atoi (s); else if (var->type == VARxSTRV) StrSetS (&var->v.strv, s); else VarError(var, "string/int", "set"); return var; } /***** VarSetList ************************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetList (VARo *var, VARo *varList) { _VarUnalias(var); if (var->isReadFunction) _ErrExit2 (e__varisreadonly, var->name); if (!var->type) var->type = VARxLIST; if (var->type == VARxLIST) var->v.list = varList; else VarError(var, "list", "set"); } INT4 VarIsAlias (VARo *var) { return var->type == VARxALIAS ? 1 : 0; } /**api* VarGetAlias ************************************************************** ** ** Returns the aliased variable. ** ** INPUT: alias any object [W] ** scope object [R] ** ** RETURNS: Any object */ VARo *VarGetAlias (VARo *alias, VARoSCOPE *scope) { if (alias->code == 1) return (alias->v.alias); else if (!alias->isReadFunction) { if (!scope) _ErrExit (f__noVarScope); return (VARo*) ((ULONG)scope->var + (ULONG)alias->v.alias); } else return (*alias->v.varGet)(alias); } /**api* VarSetAlias ************************************************************** ** ** Sets an variable with a pointer to a named variable. ** If the variable with the specified name is not found it is newly ** created. An alias is either automatically 'unaliased' or can be ** explicitly unaliased with VarGetAlias. ** ** INPUT: alias any object [W] ** any object which is to be aliased [W] ** scope object [R] */ void VarSetAlias (VARo *alias, VARo *var, VARoSCOPE *scope) { if (!alias->type) { alias->type = VARxALIAS; } if (alias->type == VARxALIAS) { alias->v.alias = (VARo*) ((char *) var - (char *) scope->var); } else VarError(alias, "alias", "set"); } /***** VarSetSubStr *********************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetSubStr (VARo *var, char *s, INT4 len) { _VarUnalias(var); if (!var->type) { var->type = VARxSTRING; var->v.buff = BuffInit (var->v.buff, 0); } if (var->type == VARxSTRING) { BuffReset (var->v.buff); BuffCopyNChar(var->v.buff, s, len); BuffCopyNChar(var->v.buff, "\0", 1); } else VarError(var, "string", "set"); } /***** VarSetReadStr ********************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetReadStr (VARo *var, SMoBUFF *(*getStr)(char *)) { _VarUnalias(var); var->type = VARxSTRING; var->v.buffGet = getStr; var->isReadFunction = 1; } /***** VarSetReadStr ********************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetReadStrV (VARo *var, STRv (*strVGet)(char *)) { _VarUnalias(var); var->type = VARxSTRV; var->v.strVGet = strVGet; var->isReadFunction = 1; } /***** VarSetReadVar ********************************************************** ** ** Sets a function for evaluating an alias. ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetReadVar (VARo *var, VARo *(*varGet)(char *)) { _VarUnalias(var); var->type = VARxALIAS; var->v.varGet = varGet; var->isReadFunction = 1; } /***** VarSetReadType ********************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetReadType (VARo *var, void (*getType)(char *)) { _VarUnalias(var); var->type = 0; var->typeGet = getType; var->isDelayedType = 1; var->isTypeEval = 0; } /***** VarSetReadInt ********************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetReadInt (VARo *var, INT4 (*getInt)(char *)) { _VarUnalias(var); var->type = VARxINT; var->v.intGet = getInt; var->isReadFunction = 1; } /***** VarSetReadReal ********************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetReadReal (VARo *var, double (*getReal)(char *)) { _VarUnalias(var); var->type = VARxREAL; var->v.realGet = getReal; var->isReadFunction = 1; } /***** VarSetType ************************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetType (VARo *var, enum VAReTYPE type) { var->type = type; } /***** VarDefName ************************************************************* ** ** Sets the name of the variable. String must be allocated outside and ** will not be copied. ** ** INPUT: variable object [W] ** name ** IMPLICIT: ** ** RETURNS: xx */ void VarDefName (VARo *var, char *name) { var->name = (char *) malloc (strlen (name) + 1); strcpy (var->name, name); /* te!!!*/ } /***** VarSetName ************************************************************* ** ** Sets the name of the variable. String must be allocated outside and ** will not be copied. ** ** INPUT: variable object [W] ** name ** IMPLICIT: ** ** RETURNS: xx */ void VarSetName (VARo *var, char *name) { var->name = (char *)malloc (strlen (name)+1); strcpy (var->name, name); /*!!!tesafety measure case var gets deleted */ } /***** VarSetFunction ********************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ void VarSetFunction (VARo *var, FUNC function) { _VarUnalias(var); var->v.operator.function = function; } /***** VarSetInt ************************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ VARo *VarSetInt (VARo *var, INT4 i) { _VarUnalias (var); if (var->isReadFunction) _ErrExit2 (e__varisreadonly, var->name); if (!var->type) var->type = VARxINT; if (var->type == VARxINT) { var->v.num = i; } else if (var->type == VARxSTRING) { BuffReset (var->v.buff); BuffPrintF (var->v.buff, "%d", i); } else if (var->type == VARxSTRV) { StrClear (&var->v.strv); StrPrintf (&var->v.strv, "%d", i); } else if (var->type == VARxLIST) { if (i == 0) LstDeleteAll ((void*) &var->v.list); else _ErrExit2 (e__icainvallistassign, VarGetName (var)); } else VarError(var, "string/int", "set"); return var; } /***** VarSetReal ************************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ VARo *VarSetReal (VARo *var, double r) { _VarUnalias (var); if (var->isReadFunction) _ErrExit2 (e__varisreadonly, var->name); if (!var->type) var->type = VARxINT; if (var->type == VARxINT) { var->v.real = r; } else if (var->type == VARxSTRING) { BuffReset (var->v.buff); BuffPrintF (var->v.buff, "%f", r); } else VarError(var, "string/real", "set"); return var; } VARo *VarSetVar (VARo *var, VARo *ptr) { static char className[]="var"; if (!var->type) { var->type = VARxVAR; var->v.object.className = className; } if (var->type == VARxVAR) { var->v.object.ptr = ptr; } else VarError(var, "var", "set"); return var; } VARo *VarGetVar (VARo *var, Int4 doEval) { if (doEval) _VarHandleTypeEval (var); if (var->type == VARxVAR) { return var->v.object.ptr; } else return var; } VARo *VarFreeze (VARo *var) { var->isTypeEval = 1; return var; } /***** VarSetObject *********************************************************** ** ** Sets an object pointer variable. The class name is optional and ** will be used for comparison if available. ** The class name will not be copied and must be allocated by the ** caller. ** ** INPUT: address of class name [R] or NULL ** variable object [W] ** object pointer [R] ** IMPLICIT: ** ** RETURNS: */ VARo *VarSetObject (char *className, VARo *var, void *ptr) { _VarUnalias(var); if (!var->type) var->type = VARxOBJECT; if (var->type == VARxOBJECT) { if (className) { if (var->v.object.className) if (var->v.object.className && !SmEqs (var->v.object.className, className)) _ErrExit4 (e__varwrongclass, var->name, var->v.object.className, className); var->v.object.className = className; } var->v.object.ptr = ptr; } else VarError(var, "object", "set"); return var; } /*api* VarNextInList ********************************************************** ** ** Iterates over all elements in the list. The context set to 0 starts ** the iteration with the first element. ** If the variable is not a list then the variable itself is returned. ** The next call using the same variable will return a NULL pointer. ** Thus, a list with one element is mimicked. ** ** INPUT: variable object of "list" type [W] ** address of context variable [W] ** IMPLICIT: ** ** RETURNS: the variable at current list position ** NULL if the list is exhausted */ VARo *VarNextInList (VARo *varList, INT4 *context) { _VarUnalias (varList); if (varList->type != VARxLIST) { /* not a list variable */ if ((*context)++ == 0) return varList; else { *context = 0; return NULL; } } else { if (*context == 0) { LstFirst ((void **) &varList->v.list); } else if (!LstSetPosition ((void **) &varList->v.list, *context)) { *context = 0; return NULL; } (*context)++; return varList->v.list; } } /***** VarListAdd ************************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ VARo *VarListAdd (VARo *var) { _VarUnalias (var); if (!var->type) { var->type = VARxLIST; var->v.list = NULL; } if (var->type != VARxLIST) VarError(var, "list", "add"); LstNew ((void **) &var->v.list, classId); return var->v.list; } /***** VarListInsert ********************************************************** ** ** Inserts a new element into a list. ** ** INPUT: the variable representing the list [W] ** the new element to be added [R} */ void VarListInsert (VARo *varList, VARo *var) { _VarUnalias (varList); if (!varList->type) { varList->type = VARxLIST; varList->v.list = NULL; } if (varList->type != VARxLIST) VarError (varList, "list", "add"); LstInsertObject ((void **) &varList->v.list, (void *) var); } /***** VarListAddAssoc ******************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ VARo *VarListAddAssoc (VARo *var, char *name) { _VarUnalias (var); if (!var->type) { var->type = VARxLIST; var->v.list = NULL; } if (var->type != VARxLIST) VarError(var, "list", "addAssoc"); LstNewNamed ((void **) &var->v.list, classId, name); return var->v.list; } /***** VarGetList ************************************************************* ** ** Returns the list object inside the variable. ** ** INPUT: the variable object [R] ** ** RETURNS: the list object */ VARo *VarGetList (VARo *var) { _VarUnalias (var); VarGetType (var); var->isTypeEval = 0; return var->v.list; } /***** VarGetListIndex ******************************************************** ** ** takes as argument the list itself ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ VARo *VarGetListIndex (VARo *var, INT4 index) { _VarUnalias (var); LstSetPosition ((void **) &var, index); return var; } /***** VarGetListAssoc ******************************************************** ** ** Gets the element with specified name from the list; creates a ** new element if it is not found ** ** INPUT: the variable holding the list [W] ** the name of the element [R] ** IMPLICIT: ** ** RETURNS: the element with specified name */ VARo *VarGetListAssoc (VARo *var, char *name) { _VarUnalias (var); if (!var->type) var->type = VARxLIST; if (var->type == VARxLIST) { if (!LstHashSearch ((void **) &(var->v.list), name)) LstNewNamed ((void **) &(var->v.list), var->class_id, name); return var->v.list; } else _ErrExit3 (e__icainvalidselect, name, VarGetName (var)); } /***** VarFindListAssoc ******************************************************* ** ** Searches the element with specified name from the list; ** ** INPUT: the variable holding the list [W] ** the name of the element [R] ** IMPLICIT: ** ** RETURNS: the element with specified name ** NULL if not found */ VARo *VarFindListAssoc (VARo *var, char *name) { _VarUnalias (var); if (!LstHashSearch ((void **) &(var->v.list), name)) return NULL; else return var->v.list; } /***** VarGetStr ************************************************************** ** ** Retrieves a "buffer" object from variable. If its type is 'int' or ** 'real' then a buffer is created with value represented as ASCII string. ** If the variable pointer is NULL or the varible is existent but ** undefined then a 'default' buffer with a NULL string is returned ** ** INPUT: variable object [R] ** IMPLICIT: ** ** RETURNS: buffer object containing a string value */ char *VarGetStr (VARo *var) { static SMoBUFF *buff[50]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; static INT4 c=0; STRv str; SMoBUFF *tmp; _VarUnalias (var); _VarHandleTypeEval (var); if (var->type == VARxSTRING) tmp = (var->isReadFunction ? (*var->v.buffGet)(var,_mA) : var->v.buff); else { tmp = (buff[c%10] = BuffInit (buff[c%10], 10)); c++; if (var->type == VARxSTRV) { str = VarGetStrV (var); BuffCopyString (tmp, _Str (str)); StrDel (str); } else if (var->type == VARxINT) { BuffPrintF (tmp, "%d", var->isReadFunction ? (*var->v.intGet)(var,_mA): var->v.num); } else if (var->type) VarError(var, "string/int", "get"); } return (BuffGetPtr(tmp)); } /**api* VarDuplicate ********************************************************** ** ** Duplicates specified Any. Note that duplication is not the same ** as creation of a copy with VarCopy. ** ** INPUT: Any object to be duplicated [R] ** ** RETURNS: the duplicate */ VARo *VarDuplicate (VARo *var) { VARo *new; new = VarNew (); memcpy (new, var, sizeof (VARo)); return new; } /**api* VarCopy *************************************************************** ** ** Copies a value inside an Any into some other. The other Any ** can be supplied by the client or if left unspecified will be created. ** This function will not simply duplicate the Any as VarDuplicate ** but retrieve values in a standard fashion which can execute evaluation ** functions. ** ** INPUT: Any object to be copied [R] ** the Any which will receive the copy (or NULL) [W] ** ** RETURNS: the Any object with the copy */ VARo *VarCopy (VARo *from, VARo *to) { STRv str; Int4 type; if (!to) to = VarNew (); else VarReset (to); _VarGetType (from, type); switch (type) { case VARxINT: VarSetInt (to, VarGetInt (from)); break; case VARxSTRING: VarSetStr (to, VarGetStr (from)); break; case VARxSTRV: str = VarGetStrV (from); VarSetStrV (to, str); StrDel (str); break; case VARxLIST: VarSetList (to, VarGetList (from)); break; case VARxOBJECT: VarSetObject (NULL, to, VarGetObject (NULL, from)); break; case VARxUNKNOWN: break; /* do nothing */ default: _ErrExit2 (e__unknownoption, "type in IopAss"); } return to; } /***** VarExec **************************************************************** ** ** Executes associated 'get' or 'type' function regardless of the type. ** ** INPUT: variable object [R] ** IMPLICIT: ** ** RETURNS: */ void VarExec (VARo *var) { if (!var->isTypeEval) { VarGetType (var); var->isTypeEval = 0; } else if (var->isReadFunction) { switch (var->type) { case VARxINT: (*var->v.intGet)(var,_mA); break; case VARxREAL: (*var->v.realGet)(var,_mA); break; case VARxSTRING: (*var->v.buffGet)(var,_mA); break; } } } /**api* VarGetInt ************************************************************* ** ** Returns an integer value contained in the Any. Does implicit ** conversions from "string", "strv" and "real" Anys. ** ** INPUT: Any object [R] ** IMPLICIT: ** ** RETURNS: the integer contained in the Any */ INT4 VarGetInt (VARo *var) { INT4 num; _VarUnalias (var); _VarHandleTypeEval (var); if (var->type == VARxINT) num = var->isReadFunction ? (*var->v.intGet)(var,_mA) : var->v.num; else if (var->type == VARxREAL) num = var->v.real; else if (var->type == VARxSTRING) num = (atoi(BuffGetPtr (var->isReadFunction ? (*var->v.buffGet)(var,_mA) : var->v.buff))); else if (var->type == VARxSTRV) { STRv str; if (var->isReadFunction) { str = (*var->v.strVGet)(var,_mA); num = atoi(_Str (str)); StrDel (str); } else num = atoi (_Str (var->v.strv)); } else if (!var->type) num = 0; else VarError(var, "string/int", "get"); return(num); } /***** VarGetReal ************************************************************* ** ** ** INPUT: variable object [R] ** IMPLICIT: ** ** RETURNS: buffer object containing a string value */ double VarGetReal (VARo *var) { double real; _VarUnalias (var); _VarHandleTypeEval (var); if (!var || !var->type) return 0; if (var->type == VARxSTRING) real = (atof(BuffGetPtr (var->isReadFunction ? (*var->v.buffGet)(var,_mA) : var->v.buff))); else if (var->type == VARxREAL) real = var->v.real; else if (var->type == VARxINT) real = var->v.num; else VarError(var, "string/real", "get"); return(real); } /***** VarGetObject *********************************************************** ** ** Returns the object pointer from variable. The class name is optional ** and will be used for checking the compatibility if supplied. ** ** INPUT: class name [R] ** variable object [R] ** IMPLICIT: ** ** RETURNS: the object pointer */ void *VarGetObject (char *className, VARo *var) { _VarUnalias (var); _VarHandleTypeEval (var); if (var->type == VARxOBJECT) { if (className) { if (var->v.object.className) if (!SmEqs (var->v.object.className, className)) _ErrExit4 (e__varwrongclass, var->name, var->v.object.className, className); var->v.object.className = className; } } else VarError(var, "object", "get"); return var->v.object.ptr; } /***** VarGetFunction ********************************************************* ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ FUNC VarGetFunction (VARo *var) { _VarUnalias (var); return(var->v.operator.function); } /***** VarType **************************************************************** ** ** Return the type of argument variable ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ char VarType(VARo *var) { _VarUnalias (var); return(var->type); } /**api* VarGetCode ************************************************************ ** ** Return the code of argument variable ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ char VarGetCode(VARo *var) { /* _VarUnalias(var); */ return(var->code); } /**api* VarSetCode ************************************************************ ** ** Set the code of argument variable ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ void VarSetCode(VARo *var, char code) { _VarUnalias(var); var->code = code; } /**api* VarSetClassName ******************************************************* ** ** Sets the class name of a variable of type 'object'. ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ void VarSetClassName (VARo *var, char *className) { var->v.object.className = className; } char *VarGetClassName (VARo *var) { return var->v.object.className; } void VarSetLineN (VARo *var, INT4 lineN) { var->lineN = lineN; } INT4 VarGetLineN (VARo *var) { return var->lineN; } /**api* VarGetName ********************************************************* ** ** Returns the name of the any object. Returns the name ** of the aliased any if input is an alias. ** ** INPUT: any object ** IMPLICIT: ** ** RETURNS: the name of the any */ char *VarGetName(VARo *var) { _VarUnalias(var); return(var->name); } /**api* VarGetRealName ******************************************************** ** ** Return the real name of the variable. Does not, in contrast to ** VarGetName follow a link to an alias. ** ** INPUT: variable object [R] ** IMPLICIT: ** ** RETURNS: the var object's real name */ char *VarGetRealName(VARo *var) { return(var->name); } /***** VarGetPriority ********************************************************* ** ** Return the type of argument variable ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ char VarGetPriority(VARo *var) { _VarUnalias (var); return(var->v.operator.priority); } /***** VarSetPriority ********************************************************* ** ** Return the type of argument variable ** ** INPUT: variable pointer ** IMPLICIT: ** ** RETURNS: the type of argument variable */ void VarSetPriority(VARo *var, char priority) { var->v.operator.priority = priority; } /***** VarStackNew ************************************************************ ** ** ** INPUT: initial size of the stack [R] ** ** RETURNS: stack object */ VARoSTACK *VarStackNew (INT4 size) { VARoSTACK *stack; size = MAX(10, size); if (!(stack = (VARoSTACK *) malloc (sizeof(VARoSTACK)))) _ErrExit2 (e__allocfail, "variable stack"); if (!(stack->var = (VARo *) calloc (size*sizeof(VARo), 1))) _ErrExit2 (e__allocfail, "icarus stack array"); stack->varN = 0; stack->varAllocN = size; return (stack); } /***** VarStackClose ********************************************************** ** ** Return the stack size ** ** INPUT: stack object [R] ** IMPLICIT: ** ** RETURNS: numer of symbols in the stack */ void VarStackClose (VARoSTACK *stack) { VARo *var; INT4 c; if (stack) { for (c=0; (var = VarInStackNext (stack, &c)); ) #ifdef buff if (var->type == VARxSTRING) BuffDelete (&var->v.buff); #endif if (stack->var) free (stack->var); free (stack); } } /***** VarStackReset ********************************************************** ** ** Return the stack size ** ** INPUT: stack object [R] ** IMPLICIT: ** ** RETURNS: numer of symbols in the stack */ void VarStackReset (VARoSTACK *stack) { VARo *var; INT4 c; for (c=0; (var = VarInStackNext (stack, &c)); ) { #ifdef buff if (var->type == VARxSTRING) BuffDelete (&var->v.buff); #endif memset (var, 0, sizeof (VARo)); } stack->varN = 0; } /***** VarStackSize *********************************************************** ** ** Return the stack size ** ** INPUT: stack object [R] ** IMPLICIT: ** ** RETURNS: numer of symbols in the stack */ INT4 VarStackSize (VARoSTACK *stack) { return (stack->varN); } /***** VarStackIsEmpty ******************************************************** ** ** Check the stack size ** ** INPUT: stack object [R] ** IMPLICIT: ** ** RETURNS: TRUE - stack id empty; ** FALSE - otherwise */ INT4 VarStackIsEmpty (VARoSTACK *stack) { return stack->varN ? 0 : 1; } /***** VarStackDouble ********************************************************* ** ** Doubles the size of the stack. ** ** INPUT: initial size of the stack [R] ** IMPLICIT: ** ** RETURNS: stack object */ static void VarStackDouble (VARoSTACK *stack) { stack->varAllocN *= 2; if ((stack->var = (void *) realloc (stack->var, stack->varAllocN * sizeof (VARo))) == NULL) _ErrExit2 (e__allocfail, "variable stack var list"); memset (&stack->var[stack->varN], 0, (stack->varAllocN - stack->varN) * sizeof (VARo)); } /***** VarPushCopy ************************************************************ ** ** Pushes a copy of the variable onto the stack. ** ** INPUT: initial size of the stack [R] ** IMPLICIT: ** ** RETURNS: stack object */ void VarPushCopy (VARoSTACK *stack, VARo *var) { VARo *tmp; if (stack->varN >= stack->varAllocN) VarStackDouble (stack); tmp = &stack->var[stack->varN++]; /* make sure a string from a previously stored var is freed */ #ifdef buff if (tmp->type == VARxSTRING) BuffDelete (&tmp->v.buff); #endif *tmp = *var; } /***** VarPushNew ************************************************************* ** ** Pushes a 'new' element onto the stack and returns a pointer to it. ** ** INPUT: stack object [W] ** IMPLICIT: ** ** RETURNS: variable object */ VARo *VarPushNew (VARoSTACK *stack) { VARo *tmp; if (stack->varN >= stack->varAllocN) VarStackDouble (stack); tmp = &stack->var[stack->varN++]; /* make sure a string from a previously stored var is freed */ if (tmp->type == VARxSTRING) BuffDelete (&tmp->v.buff); memset (tmp, 0, sizeof (VARo)); return tmp; } /***** VarPushAlias *********************************************************** ** ** Pushes an alias of the variable onto the stack. ** ** INPUT: initial size of the stack [R] ** IMPLICIT: ** ** RETURNS: stack object */ void VarPushAlias (VARoSTACK *stack, VARo *var) { VARo *tmp; if (stack->varN >= stack->varAllocN) VarStackDouble (stack); tmp = &stack->var[stack->varN++]; /* make sure a string from a previously stored var is freed */ if (tmp->type == VARxSTRING) BuffDelete (&tmp->v.buff); tmp->type = VARxALIAS; tmp->v.alias = var; } /***** VarPop ***************************************************************** ** ** Pops last top element in stack into user variable. ** ** INPUT: stack object [W] ** IMPLICIT: ** ** RETURNS: stack object */ VARo *VarPop (VARoSTACK *stack) { VARo *var; if (stack->varN > 0) { var = &stack->var[--stack->varN]; return var; } else return NULL; } /***** VarInStackNext ********************************************************* ** ** Pops last bottom element in stack into user variable. ** ** INPUT: stack object [W] ** IMPLICIT: ** ** RETURNS: stack object */ VARo *VarInStackNext (VARoSTACK *stack, INT4 *count) { if (*count >= stack->varN) { *count = 0; return NULL; } else return &stack->var[(*count)++]; } /***** VarStackPrint ********************************************************** ** ** xx ** ** INPUT: xx ** IMPLICIT: ** ** RETURNS: xx */ static void VarStackPrintOne(VARo *var) { printf("%-10s: ", VarGetTypeName(VarType(var))); switch(VarType(var)) { case VARxINT: printf("%d", VarGetInt(var)); break; case VARxREAL: printf("%f", VarGetReal(var)); break; case VARxSTRING: printf("\"%s\"", VarGetStr(var)); break; case VARxALIAS: printf("%s", VarGetName(var)); break; case VARxOPERATOR: if(VarGetPriority(var)) printf("%s(%d)", IcaFunctionName(var->v.operator.function), VarGetPriority(var)); else printf(">>>SEPARATOR<<<"); default: break; } printf("\n"); } void VarStackPrint(VARoSTACK *stack) { INT4 i; for (i=0; i < stack->varN; i++) { printf("SYMBOL %d: ", i); VarStackPrintOne(&stack->var[i]); } if(!stack->varN) printf("symbolstack empty !\n"); } /****** VarNextArg *********************************************************** ** ** Returns next argument in the stack. ** ** INPUT: program object [R] ** IMPLICIT: ** ** RETURNS: ** variable object ** argument name, ** number of elements in argument if it is a list ** (0 in case of scalar argument) ** */ VARo *VarNextArg (VARoSTACK *stack, char **name, INT4 *listSize) { static char *unnamed="::::::::::"; VARo *arg; INT4 k=0, code; if (!stack->varN) arg = NULL; else { *listSize = 0; arg = VarPop (stack); if ((code = VarGetCode (arg)) == 111) /* end of the argument list */ arg = NULL; else if (code == 114) { /* end of user argument list */ VarPop (stack); /* delete function name */ arg = NULL; } else { if (code == 113) { /* a list between curly braces */ while (stack->var[stack->varN-k].code != 112) k++; *listSize = k-1; *name = VarGetStr (&stack->var[stack->varN-1-k]); VarPop (stack); /* pop first parent */ } else if (stack->var[stack->varN-1].code == 110) { /* argument name */ *name = VarGetStr (&stack->var[stack->varN-1-k]); VarPop (stack); /* pop arg name */ } else *name = unnamed; } } return arg; } /**api* VarNextListItem ******************************************************* ** ** ** INPUT: program object [R] ** current execution time [R] ** IMPLICIT: ** ** RETURNS: ** */ VARo *VarNextListItem (VARoSTACK *stack, INT4 *listSize) { (*listSize)--; return(&stack->var[stack->varN-*listSize]); } /****** VarPopList ************************************************************ ** ** ** INPUT: program object [R] ** IMPLICIT: ** ** RETURNS: ** */ void VarPopList (VARoSTACK *stack) { while( VarGetCode(VarPop(stack)) != 112) ; if (stack->var[stack->varN-1].code == 110) VarPop (stack); } /****** VarGetUserCommand **************************************************** ** ** This function gets the name of the user command which is ** unfortunately below its arguments on the bottom of the stack. ** ** INPUT: program object [R] ** IMPLICIT: ** ** RETURNS: ** */ VARo *VarGetUserCommand (VARoSTACK *stack) { VARo *var; INT4 k; for (k=stack->varN-1; k >= 0; k--) { var = &stack->var[k]; if (VarGetCode (var) == 114) return &stack->var[k-1]; } return NULL; } VARo *VarStrInterp (VARoSCOPE **scope, VARo *var) { VARo *new; char *tmp; INT4 k=0; if (!(new = (VARo *) calloc (sizeof(VARo), 1))) _ErrExit2 (e__allocfail, "variable object"); VarSetStr (new, BuffGetPtr(var->v.buff)); while (BuffMatch (new->v.buff, "(\\$([a-zA-Z0-9_-]+))")) { k++; tmp = VarGetStr (VarGet (scope, BuffGetMatch (2))); BuffSubstMatch (new->v.buff, 1, tmp ? tmp : ""); } return k ? new : var; } void VarSetArgs (VARo *var, VARo **args) { var->args = args; } VARo **VarGetArgs (VARo *var) { return var->args; } /***** VarPrintf ************************************************************** ** ** Formats a string with printf type format directives. ** '%' characters must be written '%%' if they should appear in the ** formatted string. ** If the input variable does not a list then simply the string value ** is returned. ** ** INPUT: variable object (list or others) [R] ** ** RETURNS: formatted string ** empty string if there was a problem */ STRv VarPrintf (VARo *list) { STRv str; VARo *var; INT4 c=0; char *s, *tmp, *string, saveChar; if (VarGetType (list) != VARxLIST) return VarGetStrV (list); str = StrNew (); var = VarNextInList (list, &c); s = tmp = string = VarGetStr (var); while (1) { while (*s && *s != '%') { if (*s++ == '%' && *s == '%') { /* skip %% */ s++; continue; } } if (!*s) { StrAppS (&str, tmp); break; } s += strcspn (s, "sdfxc"); saveChar = s[1]; s[1] = '\0'; if (!(var = VarNextInList (list, &c))) { _ErrMsg2 (e__missingarg, "format print"); return str; } switch (*s) { case 's': StrPrintf (&str, tmp, VarGetStr (var)); break; case 'd': StrPrintf (&str, tmp, VarGetInt (var)); break; default: _ErrMsg3 (e__novalchar, "format directive", *s); return str; } s[1] = saveChar; tmp = &s[1]; } return str; } STRv VarGetStrV (VARo *var) { STRv tmp; _VarUnalias (var); _VarHandleTypeEval (var); if (var->type == VARxSTRV) tmp = (var->isReadFunction ? (*var->v.strVGet)(var,_mA) : StrCpy(var->v.strv)); else if (var->type == VARxSTRING) { tmp = StrNew (); StrSetS (&tmp, (BuffGetPtr ((var->isReadFunction ? (*var->v.buffGet)(var,_mA) : var->v.buff)))); } else if (var->type == VARxINT) { tmp = StrNew (); StrPrintf (&tmp, "%d", var->isReadFunction ? (*var->v.intGet)(var,_mA) : var->v.num); } else if (!var->type) tmp = StrNew (); else VarError(var, "string/int", "get"); return tmp; } VARo *VarSetStrVS (VARo *var, char *s) { _VarUnalias(var); if (var->isReadFunction) _ErrExit2 (e__varisreadonly, var->name); if (!var->type) { var->type = VARxSTRV; var->v.strv = StrNew (); } if (var->type == VARxSTRV) { StrSetS (&var->v.strv, s); } else if (var->type == VARxINT) var->v.num = atoi (s); else VarError(var, "string/int", "set"); return var; } VARo *VarSetStrV (VARo *var, STRv str) { _VarUnalias(var); if (var->isReadFunction) _ErrExit2 (e__varisreadonly, var->name); if (!var->type) { var->type = VARxSTRV; var->v.strv = StrNew (); } if (var->type == VARxSTRV) { StrSet (&var->v.strv, str); } else if (var->type == VARxINT) var->v.num = atoi (_Str (str)); else if (var->type == VARxSTRING) { var->v.buff = BuffInit (var->v.buff, 0); BuffCopyString (var->v.buff, _Str (str)); } else VarError(var, "string/int", "set"); return var; } ** ** $RCSfile: variable.h,v $ ** $Revision: 1.4 $ ** $Date: 1996/08/11 22:47:27 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** Copyright by Thure Etzold ** */ enum VAReTYPE {VARxUNKNOWN, VARxINT, VARxSTRING, VARxOBJECT, VARxREAL, VARxALIAS, VARxVAR, VARxANY, VARxOPERATOR, VARxSTRV, VARxLIST=16}; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** object pointer */ typedef struct VARoOBJECT { void *ptr; char *className; } VARoOBJECT; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** operator */ typedef struct VARoOPERATOR { FUNC function; char priority; } VARoOPERATOR; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** the variable object */ typedef struct VARo { char *list; /* for usage of module "list" only! */ INT4 class_id; /* for "list" module */ char *name; char type; char code; char isReadFunction; char isTypeEval; char isDelayedType; short lineN; union { INT4 (*intGet)(); double (*realGet)(); SMoBUFF *(*buffGet)(); struct VARo *(*varGet)(); STRv (*strVGet)(); VARoOBJECT object; VARoOPERATOR operator; INT4 num; SMoBUFF *buff; STRv strv; double real; struct VARo *list; struct VARo *alias; } v; struct VARo **args; void (*typeGet)(); #ifdef xxx struct info { unsigned int type:4 code:8 isReadFunction:1 isTypeEval:1 isDelayedType:1 lineN:14 fileX:3 } #endif } VARo; typedef struct VARo *VARv; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** var scope - defines a space for contiguous allocation for variables */ typedef struct VARoSCOPE { struct DICTo *dict; VARo *var; INT4 varAllocN; INT4 varN; } VARoSCOPE; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** stack object */ typedef struct VARoSTACK { VARo *var; INT4 varAllocN; INT4 varN; } VARoSTACK; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** stack object for icarus level 4 */ typedef struct VARoStack { VARo **ptr; Int4 n; Int4 allocN; } VARoStack; #define _VarGetType(var,x) \ if ((var)->type == VARxALIAS) {\ (x) = VarGetType (var);} \ else if (!(var)->isTypeEval && (var)->isDelayedType) { \ (*(var)->typeGet)(var); \ (var)->isTypeEval = 1; \ (x) = var->type; \ } else (x) = var->type /* general functions */ VARv VarNewList (); VARv VarGet (struct VARoSCOPE **scope, char *varName); VARv VarTemp (); VARv VarNew (); void VarReset (VARv var); VARv VarGetUserCommand (VARoSTACK *stack); VARv VarStrInterp (VARoSCOPE **scope, VARv var); void VarSetType (VARv var, enum VAReTYPE type); char VarType(VARv var); char* VarGetName(VARv var); char* VarGetRealName(VARv var); void VarSetAlias (VARv alias, VARv var, VARoSCOPE *scope); VARv VarGetAlias (VARv alias, VARoSCOPE *scope); VARv VarGetVar (VARv var, Int4 doEval); VARv VarCopy (VARv from, VARv to); VARv VarDuplicate (VARv var); VARv VarGet (VARoSCOPE **scope, char *name); /* work on 'string' variables */ VARv VarSetStr (VARv var, char *s); void VarSetSubStr (VARv var, char *s, INT4 len); char* VarGetStr (VARv var); void VarSetReadStr (VARv var, SMoBUFF *(*getStr)(char *)); STRv VarPrintf (VARv list); /* work on 'STRv' variables */ STRv VarGetStrV (VARv var); VARv VarSetStrVS (VARv var, char *s); VARv VarSetStrV (VARv var, STRv str); /* work on 'real' variables */ struct VARo *VarSetReal (VARv var, double real); double VarGetReal (VARv var); void VarSetReadReal (VARv var, double (*getReal)()); /* work on 'object' variables */ VARv VarSetObject (char *className, VARv var, void *object); void* VarGetObject (char *className, VARv var); void VarSetReadObject (VARv var, void (*getObject)(char *)); /* work on 'num' variables */ VARv VarSetInt (VARv var, INT4); INT4 VarGetInt (VARv var); void VarSetReadInt (VARv var, INT4 (*getInt)(char *)); /* work on 'operator' variables */ void VarSetFunction (VARv var, FUNC function); FUNC VarGetFunction (VARv var); void VarSetPriority(VARv var, char priority); char VarGetPriority(VARv var); void VarSetCode(VARv var, char code); char VarGetCode(VARv var); /* work on 'list' variables */ VARv VarNextInList (VARv var, INT4 *context); VARv VarGetList (VARv var); VARv VarListAdd (VARv var); VARv VarListAddAssoc (VARv var, char *name); VARv VarGetListIndex (VARv var, INT4 index); VARv VarGetListAssoc (VARv var, char *name); VARv VarFindListAssoc (VARv var, char *name); /* functions for variable stack management */ void VarStackClose (VARoSTACK *stack); void VarStackReset (VARoSTACK *stack); void VarStackPrint (VARoSTACK *stack); INT4 VarStackSize (VARoSTACK *stack); VARoSTACK *VarStackCopy (VARoSTACK *stack); VARoSTACK *VarStackNew (INT4 size); VARo *VarInStackNext (VARoSTACK *stack, INT4 *c); VARo *VarPop (VARoSTACK *stack); VARo *VarPushNew (VARoSTACK *stack); void VarPushAlias (VARoSTACK *stack, VARv var); void VarPushCopy (VARoSTACK *stack, VARv var); /* functions to treat stack object */ VARv VarNextArg(VARoSTACK *stack, char **name, INT4 *ListSize); VARv VarNextListItem(VARoSTACK *stack, INT4 *ListSize); void VarPopList(VARoSTACK *stack); /* icarus level 4 stack functions */ struct VARoStack *VarStackInit (struct VARoStack *stack); void VarPush2 (struct VARoStack *stack, VARv var); VARv VarPop2 (struct VARoStack *stack); /* others */ INT4 VarIsAlias (VARv var); void VarSetArgs (VARv var, VARv *args); VARv *VarGetArgs (VARv var); char *VarGetClassName (VARv var); struct VARoSCOPE *VarCopyScope (struct VARoSCOPE *scope); INT4 VarGetLineN (VARv var); void VarSetLineN (VARv var, INT4 lineN); VARv VarSetVar (VARv out, VARv in); VARv VarFreeze (VARv var); #include #include #include "message.h" #include "sm.h" #include "strv.h" #include "futil.h" #include "templ.h" #include "library.h" #include "par.h" #include "entry.h" #define _SRS #define _SLB #include "srs5.h" #include "view.h" enum VIEWeFormat {VIEWxTable=1, VIEWxList}; /**api* ViewMarkDeleted ****************************************************** ** ** Mark deleted view to be logically deleted. ** Check if a view is deleted with ViewIsDeleted. ** ** INPUT : Address of view Object [R] ** ** RETURNS: none ** */ void ViewMarkDeleted (VIEWo *view) { char par[80], *tmp; view->isDeleted = 1; /* set the status flag */ sprintf(par,"ViewDeleted_%d", view->n); if (*(tmp = ParGetStrF ("selectedViewNo_%d", view->n))) ParDelete (tmp); ParDefNum (par,1); } /**api* ViewMarkNascent ****************************************************** ** ** Mark view to be nascent. ** ** INPUT: Address of view Object (or NULL) [W] ** view number [R] ** */ void ViewMarkNascent (VIEWo *view, INT4 viewN) { char par[80]; if (view) view->isNascent = 1; sprintf(par,"v%d_isNascent", viewN); ParDefNum (par, 1); } /****** ViewIsDeleted ********************************************************* ** ** Checks for the logical deletion of a view object with ViewMarkDeleted. ** ** INPUT: Address of view object [R] ** IMPLICIT ** ** RETURNS: delete flag */ INT4 ViewIsDeleted(VIEWo *view) { return(view->isDeleted); } /**API* ViewGetEntryNamePrinting ***************************************************** ** ** Returns if the printing of the entry name before the selected information ** from entry is selected ** ** INPUT: view object [R] ** ** RETURNS: flag if entry name should be printed */ Int4 ViewIsEntryNamePrinting (VIEWo *view) { return view->isEntryNamePrinting; } /**api* ViewIsTable *********************************************************** ** ** Checks if view is to be displayed as a table ** ** INPUT: view object [R] ** ** RETURNS: TRUE or FALSE */ INT4 ViewIsTable (VIEWo *view) { return (view->format == VIEWxTable); } /**api* ViewIsShortNames ****************************************************** ** ** Checks whether field names in the table header are abbreviations ** rather than the full names. ** ** INPUT: view object [R] ** ** RETURNS: TRUE or FALSE */ INT4 ViewIsShortNames (VIEWo *view) { return(view->useShortFieldNames); } /**api* ViewIs **************************************************************** ** ** Returns TRUE if specified characteristic applies to view. ** ** INPUT: view object [R] ** option: "selected", "nascent" [R] ** ** RETURNS: TRUE or FALSE */ Int4 ViewIs (VIEWo *view, char *option) { switch (option[0]) { case 's': return (*ParGetStrF ("selectedViewNo_%d", view->n) ? 1 : 0); case 'n': return ParGetNumF ("v%d_isNascent", view->n); default: _ErrExit2 (e__unknownoption, option); } } Int4 ViewIsRootField (VIEWo *view, SLBoFIELD *field) { SLBoFIELD *tmp; VIEWoLIB *vlib; Int4 c1=0, c2; vlib = ViewGetNextRootLib (view, &c1); for (c2=0; (tmp = ViewGetNextField (vlib, &c2));) if (field == tmp) return 1; return 0; } Int4 ViewIsLeafField (VIEWo *view, VIEWoLIB *vlib, SLBoFIELD *field) { SLBoFIELD *tmp; VIEWoLIB *tmpVlib; Int4 c1, c2; for (c1=0; (tmpVlib = ViewGetNextLeafLib (view, &c1));) if (vlib == tmpVlib) for (c2=0; (tmp = ViewGetNextField (vlib, &c2));) if (field == tmp) return 1; return 0; } /**api* ViewNew *************************************************************** ** ** Creates a new empty view which can be later identified by the ** specified number or name. ** ** INPUT: view number [R] ** view name [R] or NULL ** ** RETURNS: the view library object [R] */ VIEWo *ViewNew (Int4 n, char *name) { VIEWo *view; if (!(view = (VIEWo *) calloc (1, sizeof (VIEWo)))) _ErrExit2 (e__allocfail, "view object"); view->n = n; if (name && *name) ViewSetName (view, name); return view; } /**api* ViewAddRootField ****************************************************** ** ** Adds a field to the root library(s). ** ** INPUT: view object [W] ** field type object [R} ** ** RETURNS: the view field object [R] */ VIEWoFIELD *ViewAddRootField (VIEWo *view, SRSoFLD *fieldType) { VIEWoFIELD *vfield; VIEWoLIB *vlib; if (!view->rootN) /* _ErrExit (e__viewMissingRootLib);*/ vlib = &view->root[0]; /* add all fields to the FIRST root library */ vfield = _addObj (view->rootFields, view->rootFieldsN, view->rootFieldsAllocN, VIEWoFIELD); memset (vfield, 0, sizeof (VIEWoFIELD)); vfield->type = fieldType; return vfield; } /**API* ViewAddField ********************************************************** ** ** Adds a field to a view library. Use ViewSetFieldFormat to set ** its format, if applicable and ViewAddRootField to add a field to ** the view root library(s). ** ** INPUT: view library object [W] ** field type object [R} ** ** RETURNS: the view library object [R] */ VIEWoFIELD *ViewAddField (VIEWoLIB *vlib, SRSoFLD *fieldType) { VIEWoFIELD *vfield; vfield= _addObj (vlib->fields, vlib->fieldsN, vlib->fieldsAllocN,VIEWoFIELD); memset (vfield, 0, sizeof (VIEWoFIELD)); vfield->type = fieldType; return vfield; } /**api* ViewAddRootLib ******************************************************** ** ** Adds a new root library to the view. ** ** INPUT: view object [W] ** query string [R} ** ** RETURNS: the view library object [R] */ VIEWoLIB *ViewAddRootLib (VIEWo *v, SLBo *lib) { VIEWoLIB *vlib; vlib = _addObj (v->root, v->rootN, v->rootAllocN, VIEWoLIB); memset (vlib, 0, sizeof (VIEWoLIB)); vlib->lib = lib; return vlib; } /**api* ViewAddLeafLib ******************************************************** ** ** Adds a new root library to the view. ** ** INPUT: view object [W] ** query string [R} ** ** RETURNS: the view library object [R] */ VIEWoLIB *ViewAddLeafLib (VIEWo *v, SLBo *lib) { VIEWoLIB *vlib; vlib = _addObj (v->leaves, v->leavesN, v->leavesAllocN, VIEWoLIB); memset (vlib, 0, sizeof (VIEWoLIB)); vlib->lib = lib; return vlib; } /**api* ViewSetLeafQuery ***************************************************** ** ** Sets the query string to be used for linking from the root library ** to specified leaf library. ** ** INPUT: view library object [W] ** query string [R} */ void ViewSetLeafQuery (VIEWoLIB *vlib, char *query) { if (vlib->query) free (vlib->query); vlib->query = (char *) malloc (strlen (query)+1); strcpy (vlib->query, query); } /**api* ViewSetFormat ********************************************************* ** ** Sets the view to be in table format or not ** ** INPUT: view object [R] ** format option: "table", "list" [R] */ void ViewSetFormat (VIEWo *view, char *format) { if (format[0] == 't') view->format = VIEWxTable; else view->format = VIEWxList; } /**api* ViewSetUseShortNames ************************************************** ** ** Sets whether or not to use short field names in the header of ** table views. ** ** INPUT: view object [W] ** flag [R] */ INT4 ViewSetUseShortNames (VIEWo *view, Int4 flag) { view->useShortFieldNames = flag; } /**api* ViewSetLeafView ****************************************************** ** ** Sets a view from entries of the specified leaf library. ** ** INPUT: view library object [W] ** view Name [R} */ void ViewSetLeafView (VIEWoLIB *vlib, char *viewName) { if (vlib->viewName) free (vlib->viewName); vlib->viewName = (char *) malloc (strlen (viewName)+1); strcpy (vlib->viewName, viewName); } /**api* ViewSetLeafPrintN ***************************************************** ** ** Sets flag that only the number of linked entries is printed for a ** leaf library. ** ** INPUT: view library object [W] ** flag [R] */ void ViewSetLeafPrintN (VIEWoLIB *vlib, Int4 flag) { vlib->printOnlyEntryN = flag; } /**api* ViewSetFieldFormat **************************************************** ** ** Sets for both root and leaf library fields the format. The address ** of string argument must be static. This address can be obtained ** by LibFieldFormat. ** ** INPUT: view field object [W] ** address of format name [R] */ void ViewSetFieldFormat (VIEWoFIELD *vfield, char *format) { if (format && *format) vfield->format = format; } /**api* ViewGetNextField ****************************************************** ** ** Returns the next field in the view object. ** ** INPUT: address of view object [R] ** address of context [W] ** ** RETURNS: next field object ** NULL: end of list ** */ SLBoFIELD *ViewGetNextField(VIEWoLIB *vlib, INT4 *context) { SLBoFIELD *field; SRSoFLD *type; if (vlib->fieldsN > *context) { type = vlib->fields[(*context)++].type; if (!(field = LibHasField (vlib->lib, type))) _ErrExit3 (e__dbhasnotfield, LibName (vlib->lib), LibGetFieldTypeName (type)); return field; } else { *context = 0; return NULL; } } VIEWoFIELD *ViewGetNextVfield(VIEWoLIB *vlib, INT4 *context) { if (vlib->fieldsN > *context) return &vlib->fields[(*context)++]; else { *context = 0; return NULL; } } /****** ViewGetNumOfLeafFields ************************************************ ** ** Counts number of leaf fields defined ** ** INPUT: address of view object [R] ** IMPLICIT ** ** RETURNS: number of fields defined ** ** */ INT4 ViewGetNumOfLeafFields(VIEWo *view) { INT4 m,k; for (k=0; k < view->leavesN; k++) m += view->leaves[k].fieldsN; return m; } /****** ViewGetNumOfLeafFields ************************************************ ** ** Counts number of root fields defined ** ** INPUT: address of view object ** ** RETURNS: number of fields defined ** */ INT4 ViewGetNumOfRootFields(VIEWo *view) { INT4 m,k; return view->rootFieldsN; } /**api* ViewSetName ********************************************************* ** ** Sets the name of a view. The name is entered into ** both the view object and the user context ** ** INPUT: address of view object [W] ** the name [R] ** ** RETURNS: view name ** */ void ViewSetName (VIEWo *view, char *name) { char parName[100]; sprintf (parName,"view%d_Name", view->n); ParDefStr (parName, name); view->name = ParGetStr (parName); } /**api* ViewGetName ******************************************************** ** ** returns the name of the view ** ** INPUT: address of view object [R] ** ** RETURNS: view name ** */ char *ViewGetName(VIEWo *view) { return(view->name); } /**api* ViewDelete *********************************************************** ** ** Deletes the view object obtained with ViewGet. ** ** INPUT: address of view object [W] ** */ void ViewDelete (VIEWo *view) { if (view) { free (view); } } /**api* ViewGetViewNumber *************************************************** ** ** Gets the number of the view with the specified name. ** See also ViewGet, ViewGetLeafView. ** ** INPUT: the name of the view [R] ** ** RETURN: the number of the view ** ** */ INT4 ViewGetViewNumber (char *viewName) { INT4 i; for(i = 1; i <= ParGetNum("numberOfViews"); i++) if( SmEqs(viewName,ParGetStrF("view%d_Name",i))) return i; return 1; } static void ViewUpdateRootLib (VIEWo *view, VIEWoLIB *vlib) { vlib->fields = view->rootFields; vlib->fieldsN = view->rootFieldsN; } /**api* ViewGetNextRootLib *************************************************** ** ** Returns next view root library. context must be initially ** set to 0; ** ** INPUT: address of the view object [R] ** address of the context [W] ** ** RETURNS: the view lib object ** NULL: end of list */ VIEWoLIB *ViewGetNextRootLib(VIEWo *view, INT4 *context) { VIEWoLIB *tmp = &view->root[(*context)++]; if (*context <= view->rootN) { ViewUpdateRootLib (view, tmp); return tmp; } else { *context = 0; /* reset for reuse */ return NULL; } } /**api* ViewGetNextLeafLib *************************************************** ** ** Returns next view root library. context must be initially ** set to 0; ** ** INPUT: address of the view object ** address of the context ** ** RETURNS: name of the view leaf library ** NULL if no more leaflibrary */ VIEWoLIB *ViewGetNextLeafLib(VIEWo *view, INT4 *context) { VIEWoLIB *tmp = &view->leaves[(*context)++]; if (*context <= view->leavesN) return tmp; else { *context = 0; /* reset for reuse */ return NULL; } } /**api* ViewLeafIsOnlyEntryN ************************************************** ** ** Returns TRUE if only the number of linked entries should be displayed. ** ** INPUT: leaf library object [R] ** ** RETURNS: 1: yes ** 0: no */ Int4 ViewLeafIsOnlyEntryN (VIEWoLIB *vlib) { return vlib->printOnlyEntryN; } /**api* ViewGetLeafView ******************************************************* ** ** Returns the name of the view associated with the leaf. ** Use ViewGetViewNumber and ViewGet to obtain the view object. ** ** INPUT: leaf library object [R] ** ** RETURNS: the view name ** Null string: no view associated with leaf */ char *ViewGetLeafView (VIEWoLIB *vlib) { static char empty[]=""; return vlib->viewName ? vlib->viewName : empty; } /**api* ViewLeafQuery ******************************************************** ** ** Returns the query string associated with the leaf query. See also ** ViewGetLeafQuery. ** root entry. ** ** INPUT: leaf library object [R] ** ** RETURNS: query string */ char *ViewGetLeafQueryStr (VIEWoLIB *vlib) { static char empty[]=""; return vlib->query ? vlib->query : empty; } /**api* ViewLeafQuery ******************************************************** ** ** Returns the query with which to get the leaf entry set for specified ** root entry. ** ** INPUT: leaf library object [R] ** entry object [R] ** ** RETURNS: query string */ char *ViewGetLeafQuery (VIEWoLIB *vlib, ENTRYo *entry) { static char queryStr[500]; char *tmp, entryStr[200]; if (*(tmp = ViewGetLeafQueryStr (vlib))) { strcpy (queryStr , tmp); sprintf (entryStr, "[%s-id:%s]", LibName (EntryGetLib (entry)), EntryGetName (entry)); SmSwapFirst (queryStr, "entry", entryStr); } else sprintf (queryStr, "[%s-id:%s] > %s", LibName (EntryGetLib (entry)), EntryGetName (entry), LibName (vlib->lib)); return queryStr; } LIBoFieldFormat *ViewGetFieldFormat (VIEWoLIB *vlib, SLBoFIELD *field) { SRSoFLD *type=LibFieldType (field); VIEWoFIELD *vfield; Int4 c; for (c=0; (vfield = ViewGetNextVfield (vlib, &c));) if (vfield->type == type) return LibFieldFormat (field, vfield->format); return NULL; } /****** ViewCountRootLib ************************************************** ** ** Returns next view root library. context must be initially ** set to 0; ** ** INPUT : address of the view object ** address of the context ** ** RETURNS: name of the view root library ** NULL if no more root library ** ** ** */ Int4 ViewCountRootLibs(VIEWo *view) { Int4 k,j; for(k=0,j=0; ViewGetNextRootLib(view,&k) ;j++ ) ; return j; } /****** ViewCountLeafLib ************************************************** ** ** ** */ Int4 ViewCountLeafLibs(VIEWo *view) { Int4 k,j; for(k=0,j=0; ViewGetNextLeafLib(view,&k) ;j++ ) ; return j; } void ViewSetTemplate (VIEWo *view, TEMPLv templ) { view->templ = templ; } TEMPLv ViewGetTemplate (VIEWo *view) { return view->templ; } void ViewSetTemplateFile (VIEWo *view, char *fileName) { if (view->templateFile) free (view->templateFile); view->templateFile = (char *) malloc (strlen (fileName)+1); strcpy (view->templateFile, fileName); } ViewTemplateBegin (VIEWo *view) { char *fileName; if (!view->templ) { if (view->templateFile && *view->templateFile) fileName = view->templateFile; else fileName = "SRSICA:ascii.it"; view->templ = TemplOpen (fileName, NULL); } if (ViewIsTable (view)) TemplWith (view->templ, "$entry.inTable.entry"); else TemplWith (view->templ, "$entry.inList.entry"); } ViewTemplateEnd (VIEWo *view) { TemplEndWith (); } /**API* ViewSetEntryNamePrinting ***************************************************** ** ** Sets the printing of the entry name before the selected information ** from entry is printed. ** ** INPUT: view object [R] ** */ void ViewSetEntryNamePrinting (VIEWo *view, Int4 flag) { view->isEntryNamePrinting = flag; } void ViewSetEntryNamePrint (VIEWo *view, void (*func)()) { view->entryNamePrint = func; } void ViewSetEntryNPrint (VIEWo *view, void (*func)()) { view->entryNPrint = func; } void ViewEntryNamePrint (VIEWo *view, struct ENTRYo *entry, Int4 entryNo, Int4 rowN, Int4 isRoot) { (*view->entryNamePrint) (view, entry, entryNo, rowN, isRoot); } void ViewEntryNPrint (VIEWo *view, VIEWoLEAFSET *leaf, ENTRYo *entry, Int4 rowN) { (*view->entryNamePrint) (view, leaf, entry, rowN); } ***** ** ** $RCSfile: view.h,v $ ** $Revision: ** $Date: 1996/08/11 22:47:29 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** SRS V5.x Copyright by Thure Etzold ** ** ** Author: Chenna Ramu ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387372 ** Email: chenna@embl-heidelberg.de ** ** */ typedef struct VIEWoFIELD *VIEWvFIELD; typedef struct VIEWoLIB *VIEWvLIB; typedef struct VIEWo *VIEWv; typedef struct VIEWoLEAFSET { struct VIEWoLIB *vlib; struct SETo *set; INT4 entryN; } VIEWoLEAFSET; #ifndef _SLBoFORM typedef struct SLBoFORM *dummytointroducestructtagSLBoFORM; #endif /* prototypes for view module */ struct VIEWo *ViewGet(int viewN); struct VIEWo *ViewGetForLib(char *libName); struct VIEWoLIB *ViewGetNextRootLib(struct VIEWo *view, INT4 *context); struct VIEWoLIB *ViewGetNextLeafLib(struct VIEWo *view, INT4 *context); struct SLBoFIELD *ViewGetNextField(struct VIEWoLIB *vlib, INT4 *context); void ViewSetName (struct VIEWo *view, char *name); void ViewMarkDeleted(struct VIEWo *query); void ViewDel(struct VIEWo *v ); /* view creation */ struct VIEWo *ViewNew (Int4 n, char *name); struct VIEWoFIELD *ViewAddRootField (struct VIEWo *view, struct SRSoFLD *type) ; struct VIEWoFIELD *ViewAddField (struct VIEWoLIB *vlib, struct SRSoFLD *fieldType); struct VIEWoLIB *ViewAddRootLib (struct VIEWo *view, struct SLBo *lib); struct VIEWoLIB *ViewAddLeafLib (struct VIEWo *view, struct SLBo *lib); void ViewSetLeafQuery (struct VIEWoLIB *vlib, char *query); void ViewSetFieldFormat (struct VIEWoFIELD *vfield, char *format); void ViewSetLeafView (struct VIEWoLIB *vlib, char *viewName); void ViewSetLeafPrintN (struct VIEWoLIB *vlib, Int4 flag); void ViewSetFormat (struct VIEWo *view, char *format); /* view info */ INT4 ViewIsDeleted(struct VIEWo *v); INT4 ViewIsTable (struct VIEWo *view); Int4 ViewIsShortNames (struct VIEWo *view); INT4 ViewGetNumOfRootFields(struct VIEWo *view); INT4 ViewGetNumOfLeafFields(struct VIEWo *view); char* ViewGetName(struct VIEWo *view); INT4 ViewGetViewNumber( char *viewName); char* ViewGetLeafQuery (struct VIEWoLIB *vlib, struct ENTRYo *entry); char* ViewGetLeafQueryStr (struct VIEWoLIB *vlib); char* ViewGetLeafView (struct VIEWoLIB *vlib); Int4 ViewLeafIsOnlyEntryN (struct VIEWoLIB *vlib); struct LIBoFieldFormat *ViewGetFieldFormat (struct VIEWoLIB *vlib, struct SLBoFIELD *field); struct TEMPLo *ViewGetTemplate (struct VIEWo *view); Int4 ViewCountRootLibs(struct VIEWo *view); Int4 ViewCountLeafLibs(struct VIEWo *view); char wgetz_ID[] = "$Id: wgetz.c,v 1.22 1996/08/11 22:47:30 etzold Exp $"; /* ** ** $Source: /home/srs/cvsroot/srs/src/wgetz.c,v $ ** $Revision: 1.22 $ ** $Date: 1996/08/11 22:47:30 $ ** $Author: etzold $ ** ** $Locker: $ ** $State: Exp $ ** ** ** Copyright by Thure Etzold ** ** Author: Chenna Ramu ** EMBL, Meyerhofstrasse 1 ** W-6900 Heidelberg, Germany ** Tel: 06221 387372 ** Email: chenna@embl-heidelberg.de ** ** ** Requires: message, file, sm ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** ** Description ** =========== ** ** call getz from within WWW ...entries are fortified by hypertext links ** ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include "message.h" #include "arglist.h" #include "sm.h" #include "strv.h" #include "tm.h" #include "futil.h" #include "library.h" #include "par.h" #include "id.h" #include "idx.h" #include "set.h" #include "link.h" #include "entry.h" #include "query.h" #include "queryass.h" #include "templ.h" #include "view.h" #include "srswww.h" #include "seq.h" #include "seqlib.h" #include "icarus.h" #include "odd.h" #define _INITOBJS #define _CONSTANTS #define _SDL #define _FUNCTION #include "oddclass.h" #define _SRS #define _SLB #define _FUNCTION #define XQUERY_M #define WWW_M #include "srs5.h" #include "srsenv.h" /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** prototypes of static functions */ static void PageStart (); static void PageSelectLibrary (); static void PageQueryForm (); static void PageDownloadSetOpt (); static void PageDownloadSet (); static void PageConstructQuery (); static void PageReinspectQuery (); static void PageConstructQuery (); static void PageQueryManager (); static void PageViewCreate (); static void PageViewMgrCreate (); static void PageViewSelectFields (); static void PageViewManager (); static void PageViewEdit (); static void PageViewSelectedEntries (); static void PageEntry (); static void PageBlastOpt (); static void PageFastaOpt (); static void PageDoBlast(); static void PageDoFasta(); static void PageQueryExpression (); static void PageCombineQueries (); static void PageIndexBrowseOpt (); static void PageIndexBrowse (); static void PageValues2Query (); static void PageLinkOpt (); static void PageLinkToLibs (); static void PageMoreEntries (); static void PageHelpAbout(); static void PageLibList (); static void PageLibNetwork (); static void PageLibInfo (); static void PageLinkInfo (); void WwwGetOddFile(); void WwwMarkDeletedQuery(WWWoQUERY *query, INT4 queryN); INT4 WwwisQueryDeleted(WWWoQUERY *query); char *SmTrimAt (char *s, Int4 n); char *SmFillFrom(char *s, Int4 n, char *fill); INT4 GetEnvp(char **envPtr); void GetEnv(); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** declaration of global or module wide variables */ char pageQuery[3000]; char **envPtr; static struct functions { char name[80]; void (*function) (); } functions[] = { "PageStart", PageStart, "PageReinspectQuery", PageReinspectQuery, "PageDownloadSetOpt", PageDownloadSetOpt, "PageDownloadSet", PageDownloadSet, "PageQueryForm", PageQueryForm, "PageQueryManager", PageQueryManager, "PageConstructQuery", PageConstructQuery, "PageSelectLibrary", PageSelectLibrary, "PageViewCreate", PageViewCreate, "PageViewMgrCreate", PageViewMgrCreate, "PageViewSelectFields", PageViewSelectFields, "PageViewManager", PageViewManager, "PageViewEdit", PageViewEdit, "PageEntry", PageEntry, "PageViewSelectedEntries", PageViewSelectedEntries, "PageFastaOpt", PageFastaOpt, "PageBlastOpt", PageBlastOpt, "PageDoBlast", PageDoBlast, "PageDoFasta", PageDoFasta, "PageQueryExpression", PageQueryExpression, "PageCombineQueries", PageCombineQueries, "PageIndexBrowseOpt", PageIndexBrowseOpt, "PageIndexBrowse", PageIndexBrowse, "PageValues2Query", PageValues2Query, "PageLinkOpt", PageLinkOpt, "PageLinkToLibs", PageLinkToLibs, "PageMoreEntries", PageMoreEntries, "PageHelpAbout", PageHelpAbout, "PageLibList", PageLibList, "PageLibNetwork", PageLibNetwork, "PageLibInfo", PageLibInfo, "PageLinkInfo", PageLinkInfo, "WwwGetOddFile", WwwGetOddFile, "GetEnv", GetEnv, "", NULL }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** default function for module "arglist" for printing lines */ static INT4 WwwArgPrint (char *formatStr, ...) { static INT4 isFirst=1, isFirstOption=1; TEMPLv templ; va_list ap; char line[2000], tmp[2000], *p; if (isFirst) { printf ("

    \n");
        isFirst=0;
        templ = TemplOpen ("SRSICA:srswww.i", NULL);
        TemplWith(templ,"$argListOption");
      }
      va_start (ap, formatStr);
      vsprintf (line, formatStr, ap);
      va_end (ap);
    
      for (p=line; *p != '\0' && *p == ' '; p++)
        ;
      if (*p == '-') {
        if (isFirstOption) {
          TemplPrint("header");
          isFirstOption = 0;
        }
        line[22] = '\0';
        strcpy (tmp, &line[23]);
        TemplPrint("option",WwwStringEncode (line),  WwwStringEncode (tmp));
      }
      else
        printf ("%s", WwwStringEncode (line));
      return 1;
    }
    
    INT4 WwwGetInput (INT4 argc, char *argv[])
    {
      ARGoLIST *arglist;
      char     *buff, *tmp;
      char     *tmp1, *userId, opt[100];
      INT4     byteN, k, j, argC, isInput=0;
      INT4 funDefined = 0;
      /*
      ** check if input from form 
      */
    
    
      if ((tmp = getenv ("REQUEST_METHOD")) && SmEqs (tmp,"POST")) {
        byteN = atoi (getenv ("CONTENT_LENGTH"));
        buff = WwwReadInput (byteN, _FilTempLN ("SRSWWWTMP:buff"));
        WwwParInput (byteN, buff);
        isInput = 1;
      }
    
      /*
      ** input from command line
      */
    
      else if (argc > 1) {
        arglist = (ARGoLIST *) LibObjByName ("arglist", "wgetz");
        for (k=0; k < argc; k++)
          SmEdit (argv[k], SMxDECODE);
        argC = ArgGet (arglist, argc, argv); 
        isInput = 1;
      }
      
      /*
      ** if the userId was specified by either the form or command line
      ** input then we read the user parameters file ...after that we
      ** must read the form or command line again to give those parameters
      ** the priority they deserve
      */
    
      userId = ParGetStr("userId");
      if (userId && *userId) {
        sprintf (opt, "-id+%s+", userId);
        ParDefStr ("userIdOpt", opt);
        WwwParRead (userId, 1);
        if ((tmp = getenv ("REQUEST_METHOD")) && SmEqs (tmp,"POST"))  {
          WwwParInput (byteN, buff);
        }
        else 
          argC = ArgGet (arglist, argc, argv); 
      }
      
      /*
      ** determine the function to be executed after returning from here
      ** ..set as function parameter "wwwFunction"
      */
    
      if ((tmp = ParGetStr ("wwwFunctionName")) && *tmp) { 
        for (k=0; functions[k].function; k++)
          if (SmEqs (tmp, functions[k].name))
    	ParDefFunction ("wwwFunction", (INT4(*)()) functions[k].function);
        }
    /*
       When no wwwFunction is defined, look for wwwFunctionName1, ...
       which might be defined. get ParGetStr(ParGetStr(wwwFunctionName1)) which 
       is a function name whose value is "submitted" through submit button.
       check for its existence and define wwwFunction
    */
    
      if (!ParGetFunction ("wwwFunction")) { 
        funDefined = 0;
        for( j =0; functions[j].function; j++) {
          if( funDefined ) break;
          if( (tmp = ParGetStrF("wwwFunctionName%d",j)) && *tmp ) { 
    	if(*ParGetStr(tmp)) {
    	  ParDelete (tmp);
    	  ParDeleteF("wwwFunctionName%d",j);
    	  for (k=0; functions[k].function; k++) 
    	    if (SmEqs (tmp, functions[k].name)) {
    	      ParDefFunction ("wwwFunction", (FUNC)functions[k].function);
    	      funDefined = 1; break;
    	    }
    	}
          }
        }
      }
    
      if(!ParGetFunction("wwwFunction"))
        ParDefFunction ("wwwFunction", (FUNC) PageEntry)
     
        ; /*_ErrExit2 (e__functionnotexist, tmp); */ /* take default function!*/
       
      if (ParGetBool ("isHtml3"))
        ParDefStr ("HTML", "H3-");
      else
        ParDefStr ("HTML", "");
      
      if (SmEqs (ParGetStr ("style"),"fancy"))
        ParDefStr("FANCY","FANCY-");
      else
        ParDefStr("FANCY","");
      
      return isInput;
    }
    
    /****** main *******************************************************************
    **
    **      check wwwFunction defined, if,  then call appropriate function
    **      and delete the function parameter name, save the user context.
    **
    **      INPUT:  function name with the arguments defined in arglist under
    **              rwgetz 
    **
    **
    */
    
    main (INT4 argc, char *argv[], char *envp[])
    {
      INT4 (*function) ();
      char *userId;
    
      SrsEnv ();
      LibOpen ("srs5");
      OddInit (def, 1); 
      IcaInitSyntax (LibObjByName ("syntax", "icarus"));
    
    /*   MsgSetFnct ((FUNC)IcaPrintMessage); */
      MsgSetFnct (WwwPrintMessage);
      /*  ArgSetPrint (WwwArgPrint);*/
      setbuf(stdout,NULL); /* needed */
      envPtr = envp;
      ParDefStr("view0_Name", "* No View *");
      if (WwwGetInput (argc, argv)) {
        if (argv[1] && *argv[1]) {
          strcpy (pageQuery, WwwTransform ("decode", argv[1]));  
        }
        if ((function = ParGetFunction ("wwwFunction")))
          (*function)();
      }
      userId = ParGetStr("userId");
      if (userId && *userId)  {
        ParDelete ("wwwFunctionName"); /* no need to save function name */
        ParDeleteMatch("wwwFunctionName.+");
        WwwParWrite (userId);
      }
      exit (0);
    }
    
    
    /**api* PageStart *************************************************************
    **
    **      Prints the start page
    **
    */
    
    static void PageStart()
    {
      TEMPLv templ;
    
      templ = WwwInit ();
      TemplWith(templ,"$startPage");
      TemplPrint ("head");
      TemplEndWith ();
      TemplClose (templ);
    }
    
    
    
    /**api* PageSelectLibrary *****************************************************
    **
    **      Lists all databanks that can be searched.
    **
    */
    
    static void PageSelectLibrary()
    {
      TEMPLv    templ;
      SLBo      *lib;
      SRSoGROUP *group;
      char      *libName, *userId;
      char      label[40];
      Int4      c1, c2, ngroups = 0, nlib = 0, max = 0, numCol = 0;
    
      /* create a new user if not already existent */
      userId = ParGetStr("userId");
      if (!( userId && *userId)) {
        userId = WwwNewUserId();
        ParDefNum("makeWild",1); /* new user should have this */
      }
    
      templ = WwwInit ();
      TemplWith(templ,"$selectLibrary");
      TemplPrint("head");
      WwwPrintButtons (templ);
      TemplPrint("submit");
    
      max = LibGetMaxNameSize (NULL, NULL, "library") + 1; 
      numCol = 60/(max);          /* adjust number of columns */
      
      if(ParGetBool("isHtml3")) numCol = 65/max;
      TemplWith(templ, ParGetBool("isHtml3") ? "libs.html3" : "libs.html2");
      for (c1=0; (group = LibNextLibGroup (&c1)); ) {
        if( ! (ngroups = LibNofGroups(group))) continue;
        TemplPrint ("libGroupName", group->com);     
        for (c2=0, nlib = 0; (lib = LibNextLib (group, &c2)); nlib++) {
          libName = LibGetName(lib,"full");
          ParDefNum ("l", max-strlen (libName));
          if(nlib && !(nlib%numCol) ) TemplPrint("newRow");
          TemplPrint("library", libName, WwwChecked (LibIs (lib,"selected")), 
    		 libName, libName, "");
          if( SmEqs(group->com,"HomolSearch")) {
    	sprintf(label,"tools.%s",SmEdit(libName,SMxLOWCASE));
    	TemplPrint(label);
          }
        }
        TemplPrint("tail"); 
      }
      TemplEndWith ();
      TemplPrint("tail");
      TemplWith (templ, "colorScheme");
      WwwPresentColorMenu();
      TemplEndWith ();
      TemplEndWith ();
    }
    
    /****** LibNofGroups **************************************************
    **
    **      Counts number of databanks in a group
    **
    **      INPUT:    group object 
    **           IMPLICIT
    **
    **      RETURNS: number of databanks in the group
    **     
    **
    **
    */
    
    INT4 LibNofGroups( SRSoGROUP *group)
    {
      INT4 i,j;
      for( i = 0, j=0; LibNextLib(group,&i) ; j++)
        ;
      return(j);
    }
    
    /**api* PageQueryForm ********************************************************
    **
    **      Builds a queryform page for the selected databanks.
    **
    */
    
    static void PageQueryForm ()
    {
      TEMPLv   templ;
      SLBo      *lib, *libSave;
      SRSoGROUP *group, *groupCurr;
      SLBoFIELD *field;
      char      *tmp, *tmp1, *fieldName, *userId;
      INT4      max, c1, c2, i, currentViewNumber=0, numberOfViews=0;
    
      ParDefNum("listEntriesStartN",1);
      ParDefNum("viewEntriesStartN",1);
    
      /* create a new user if not already existent */
      userId = ParGetStr("userId");
      if (!( userId && *userId)) {
        userId = WwwNewUserId();
        ParDefNum("makeWild",1); /* new user should have this */
      }
    
      templ = WwwInit ();
      TemplWith(templ, "$queryForm");
      TemplPrint("head");
      WwwPrintButtons (templ);
     
      /* loop over selected databanks */
      TemplPrint("searchInfo");
      groupCurr = LibGroupNew (NULL);
      for (c1=0; (group = LibNextLibGroup (&c1)); ) 
        for (c2=0; (lib = LibNextLib (group, &c2));) { 
          if (LibIs (lib, "selected")) {
    	libSave = lib;
    	LibGroupAddDb (groupCurr, lib);
            TemplPrint("listLibs",LibName (lib), LibName (lib));
          }
        }
      if (!groupCurr->libraryN) 
        _ErrExit (e__nolibslct); /* no databanks were selectect */
      TemplPrint("submit");
      TemplWith (templ, "chunkSize");
      WwwPresentChunkSizes (templ);  
      TemplEndWith ();
      WwwPresentViewsForLibs (groupCurr);
      TemplPrint ("searchOptions", WwwChecked (ParGetNum("makeWild")));
      TemplWith(templ, ParGetBool("isHtml3") ? 
    	    "queryInput.html3" : "queryInput.html2");
      TemplPrint("head");
    
    
      max = LibGetMaxNameSize (groupCurr, NULL, "field")+1;
    
      for (c1=0; (field = LibNextGroupField (groupCurr, 
    			 ParGetBool ("isOnlyCommonFields"), &c1));) {
        fieldName = LibGetFieldName (field);
    
        ParDefNum ("l", max-strlen (fieldName));
        if (LibIsField (field, "header")) {
          if (LibFieldHeaderHasWith (libSave, field, "doQuery"))
    	TemplPrint ("fieldHeader", fieldName);
        }
        else if (LibIsField (field, "num") || LibIsField (field, "real")) {
          tmp = ParGetStrF("query_%s_begmod",fieldName);
          tmp1 = ParGetStrF("query_%s_endmod",fieldName);
          TemplPrint("fieldNum",
    		 fieldName, fieldName, "", fieldName,
    		 WwwSelected (SmEqs (tmp,">=")), WwwSelected (SmEqs (tmp,">")),
    		 fieldName, fieldName,
    		 WwwSelected (SmEqs (tmp1,"<=")),WwwSelected (SmEqs(tmp1,"<")),
    		 fieldName, fieldName);
        } 
        else if (LibIsField (field, "doQuery")) 
          TemplPrint("fieldText", fieldName,fieldName,"",fieldName,fieldName); 
        if (LibIsField (field, "subEntry")) {
          tmp = ParGetStrF("%s",fieldName);
          TemplPrint("subEntry",fieldName,WwwChecked (*tmp));
        }
        TemplPrint("rowEnd");
      }
      TemplPrint("tail"); 
      TemplEndWith ();
      TemplPrint("tail");  
    }
    
    
    /****** PageIndexBrowseOpt ****************************************************
    **
    **      Presents the options of browsing an index.
    **
    */
    
    static void PageIndexBrowseOpt ()
    {
      TEMPLv    templ,
                templInfo;
      SLBo      *lib;
      SRSoGROUP *group;
      char      libList[200]="",
                path[999],
                *fieldName,
    	    *infoName,
    	    *tmp;
      INT4      c1,c2;
    
      templ = WwwInit ();
    
      TemplWith(templ,"$dataField");
      TemplPrint ("head");
      WwwPrintButtons (templ);
    
      /* make string with library list */
      if (*(tmp = ParGetStr ("browseLibs")))
        strcpy (libList, tmp);
      else {
        for (c1=0; (group = LibNextLibGroup (&c1)); ) 
          for (c2=0; (lib = LibNextLib (group, &c2));) {
    	if (LibIs(lib, "selected")) {
    	  sprintf (libList, "%s%s ", libList, LibName (lib));
    	}
          }
        libList[strlen(libList)-1] = '\0';
      }
     
     /* the page line */
      fieldName = ParGetStr("browseIndex");
      TemplPrint ("title", fieldName, libList);
      TemplPrint ("browse", fieldName, libList);
      if ( strlen(libList) ) {
        templInfo = TemplOpen ("SRSDB:general.it", NULL);
        TemplWith(templInfo, "$main");
        strcat(strcpy(path, "fields.") ,fieldName);
        if( TemplExists(templInfo, path) )
          TemplPrint(path);
        TemplEndWith();
        for (c1=0; (group = LibNextLibGroup (&c1)); ) 
          for (c2=0; (lib = LibNextLib (group, &c2));)
    	if( LibIs(lib,"selected") ) {
    	  infoName = LibGetIcarusFileName(lib, "info");
    	  if( (templInfo = TemplOpen(infoName, NULL)) ) {
                TemplWith(templInfo, "$main");
                if( TemplExists(templInfo, path) )
                  TemplPrint(path);
    	    TemplEndWith();
     	  }
    	}
      }
      TemplPrint ("inEntry", ParGetStr ("browseIndex"));
      TemplPrint ("tail");
    }
    
    /****** PageIndexBrowse *******************************************************
    **
    **      Prints all or some values of an index.
    **
    */
    
    static void PageIndexBrowse ()
    {
      TEMPLv templ;
      char   *libList, *fieldName, queryStr[200];
    
      templ = WwwInit ();
      TemplWith(templ,"$browseList");
      TemplPrint ("head");
      WwwPrintButtons (templ);
      
      libList = ParGetStr ("browseLibs");
      fieldName = ParGetStr ("browseIndex");
      sprintf (queryStr, "[{%s}-%s:%s]", libList, fieldName, 
    	   ParGetStr ("browseMatch"));
      TemplPrint ("title", fieldName, fieldName, libList, 
    	      ParGetNum("printIndexValN") + ParGetNum ("printIndexFirstValN"));
    
      ParDefNum ("queryListValues", 1);
      ParDefNum ("isHTMLFormat", 1);
      /* Query prints the values!*/
      QuerySetPrintValue (WwwPrintValue);
      TemplWith (templ, "values");
      Query (queryStr, "");
      TemplEndWith ();
      TemplEndWith ();
    }
    
    
    
    /**api* PageValues2Query *****************************************************
    **
    **      Collects all selected values and combines them to a query.
    **  
    */
    
    static void PageValues2Query ()
    {
      STRv str=NULL;
      char *tmp;
      Int4 valN = ParGetNum ("printIndexValN"), k;
    
      for (k=1; k<=valN; k++)
        if (*(tmp = ParGetStrF ("value_%d", k))) {
          tmp = WwwTransform ("decode", tmp);
          if (!str) 
    	str = StrCpyS (tmp);
          else
    	StrPrintf (&str, " | %s", tmp);
        }
      
      if (str) {
        WwwQueryExpression ("query", _Str (str));
        StrDel (str);
      }
    }
    
    
    
    /**api* PageQueryManager *****************************************************
    **
    **      Shows all successful queries and allows various operations on them.
    **  
    */
    
    static void PageQueryManager()
    {
      WWWoQUERY *query ;
      TEMPLv templ;
      char      *tmp, *par, *userId;
      INT4      Nqueries, k, j, currentViewNumber=0;
    
    /* initialize the parameters */
      ParDefStr("expr","");
      ParDefNum("listEntriesStartN",1);
      ParDefStr ("fieldList", "reset"); 
      Nqueries = ParGetNum("numberOfQueries");
    
      templ = WwwInit ();
      TemplWith(templ,"$queryManager");
      TemplPrint("head");
      WwwPrintButtons (templ);
      if( ParGetBool("isHtml3"))
        TemplWith(templ,"queryOptions.html3");
      else
        TemplWith(templ,"queryOptions.html2");
      TemplPrint("head");
      TemplEndWith();
      TemplWith(templ,"chunkSize");
      WwwPresentChunkSizes (templ);
      TemplEndWith();
      TemplWith(templ,"selectView");
      WwwPresentViewList ("current");
      TemplEndWith();
      if(ParGetBool("isHtml3")) 
        TemplWith(templ,"queryOptions.html3.queryInfo");
      else
        TemplWith(templ,"queryOptions.html2.queryInfo");
      TemplPrint("head"); 
      for ( k = 1; k <= Nqueries; k++) {
        query = WwwGetQuery (k);
        if (SmEqs (query->type, "singleentry") || 
    	SmEqs (query->type, "linkentry"))continue;
        if(WwwisQueryDeleted(query)) continue;
        
        if(*(ParGetStrF("qmstr%d",k))){
          WwwMarkDeletedQuery(query,k);
          continue;
        }
        if (!(ParGetBool("isHtml3"))) {
          TemplPrint("title", k,query->name,query->name,query->type,
    		 WwwStringEncode(query->queryStr),query->entryN);
          for(j=0; query->lib[j].entryN;j++) {
    	TemplPrint("entryN", query->lib[j].entryN, query->lib[j].name);
    	if( query->isSubEntry)
    	  TemplPrint("subEntry");
          }
        }
        else {
          TemplPrint("title",k,query->name,query->name,
    		 query->type,query->entryN);
          TemplPrint("libAlign");
          for(j=0; query->lib[j].entryN; j++) {
    	TemplPrint("library",(query->lib[j].name));
          }
          TemplPrint("numAlign");
          for(j=0; query->lib[j].entryN;j++) {
            TemplPrint("entryN",(query->lib[j].entryN));
          }
          TemplPrint("queryStr",WwwStringEncode(query->queryStr),
    		 k,query->comment);
          if( query->isSubEntry)
            TemplPrint("subEntry");
          TemplPrint("rowEnd");
        }
        WwwDelQuery(query);
      }
      TemplEndWith();
      TemplPrint("tail");
    }
    
    
    
    /****** PageQueryExpression ***************************************************
    **
    **      Does an query expression.
    **
    */
    
    static void PageQueryExpression()
    {
      WwwQueryExpression ("expression", ParGetStr ("expr"));
    }
    
    /****** PageCombineQueries ****************************************************
    **
    **      Combines several queries with a single set operator.
    **
    */
    
    static void  PageCombineQueries ()
    {
      WWWoQUERY *query;
      STRv str;
      INT4 k,j;
      char *tmp, op;
    
      tmp = ParGetStr("operator");
      if (SmEqs(tmp,"AND"))
        op = '&';
      else if (SmEqs(tmp,"OR"))
        op = '|';
      else if (SmEqs(tmp,"BUTNOT"))
        op = '!';
      else 
        return;
    
      for (j=0, k=0; WwwNextSelectedQuery (&j, &tmp); k++) {
        if (!k)
          str = StrCpyS (tmp);
        else
          StrPrintf (&str, " %c %s", op, tmp);
      }
      if (!k)
        _ErrExit (e__wwwNoQueryOrEntriesSelected);
      else
        WwwQueryExpression ("expression", _Str (str));
    }
    
    /**api* PageReinspectQuery ****************************************************
    **
    **      Repeats a query selected in the QueryManager form.
    **
    */
    
    static void PageReinspectQuery ()
    {
      INT4 j=0;
    
      if ((j=WwwNextSelectedQuery (&j, NULL))) {
        WwwQueryRepeat (j);
        WwwQueryPrint (j);
      }
      else 
        _ErrExit (e__wwwNoQueryOrEntriesSelected);
    }
    
    /****** PageBlastOpt *********************************************************
    **
    **      Displays the input form for a BLAST search
    **
    */
    
    static void  PageBlastOpt ()
    {
      TEMPLv templ;
    
      templ = WwwInit ();
      TemplWith (templ, "$blastPage");
      TemplPrint ("head");
    }
    
    /****** PageFastaOpt **********************************************************
    **
    **      Prepares input form a fasta run
    **
    */
    
    static void PageFastaOpt ()
    {
      TEMPLv templ;
      templ = WwwInit ();
      TemplWith(templ,"$prepFasta");
      TemplPrint("head");
      WwwPrintButtons(templ);
      TemplPrint("tail");
    
    }
    
    FILE *file;
    INT4 wwwWriteFile (char *formatStr, ...)
    {
      va_list ap;
      
      va_start (ap, formatStr);
      vfprintf (file, formatStr, ap);
      va_end (ap);
      
      if (formatStr[strlen (formatStr) -1] != '\n')
        fprintf (file, "\n");
      
    }
    
    
    /****** PageDoBlast *******************************************************
    **
    **         Prepares a c-shell for launching blastp...
    **
    **         There are three type of options wiht Blastp
    **         switches ( -sort_by_pbalue, -sort_by_count ...etc., )
    **         options (-hspMax 100, .... etc., )
    **         parameters   ( E=10, S= 5, ... etc.,)
    **
    **	INPUT:	    
    **	        IMPLICIT:
    **
    **	RETURNS:    
    */ 
    
    static void PageDoBlast()
    {
      TEMPLv  templ, cshTempl;
      SLBo    *lib;
      SEQo    seq;
      char    parName[80];
      INT4    errCode;
    
      char blastDir[80];
      char seqFile[80];
      char cshFile[80];
      char blastCmd[512];
    
      char *tmp;
      INT4 i = 0;
      char *blaParams[] = {"E","S","E2","S2","W","T","X","H","Y","Z","V","B",""};
      char *blaSwitch[] = { "gi","span2","span1","span","sump","poissonp","prune",
                             "sort_by_pvalue","sort_by_count","sort_by_highscore",
                              "sort_by_totalscore","echo_filter",""};
    
      char *blaOptions[] = {"filter","qoffset","hspmax",""};
      char *userId = ParGetStr("userId");
      
      blastCmd[0] = '\0';
      seqFile[0] = '\0';
      cshFile[0] = '\0';
    
      if (!(lib = (SLBo *) LibObjByName ("library", "Blast")))
        _ErrExit3 (e__objectunknown, "library", "Blast");
    
      seq.seq = ParGetStr ("inputSequence");
      seq.len = strlen (seq.seq);
      
      sprintf(seqFile,"%s:%s/x.seq","SRSWWWTMP",userId);
      sprintf(cshFile,"%s/%s/blast","SRSWWWTMP",userId);
    
      sprintf(blastDir,"SRSWWWTMP:%s",userId);
      sprintf(blastCmd,"blastp %s x.seq ",ParGetStr("bla_SearchLib"));
    
      for(i=0; *blaParams[i] ; i++) {
        if( ! *(tmp = ParGetStrF("bla_%s",blaParams[i]))) continue;
        sprintf(blastCmd," %s %s=%s",blastCmd,blaParams[i],tmp);
      }
      for(i=0; *blaSwitch[i] ; i++) {
        if( ! *(tmp = ParGetStrF("bla_%s",blaSwitch[i]))) continue;
        sprintf(blastCmd," %s -%s",blastCmd,(blaSwitch[i]));
      }
      for(i=0; *blaOptions[i] ; i++) { /* eg -hspMax 100  etc., */
        if( ! *(tmp = ParGetStrF("bla_%s",blaOptions[i]))) continue;
        sprintf(blastCmd," %s -%s %s",blastCmd,blaOptions[i],tmp);
      }
    
      sprintf(blastCmd," %s > tmp.blast",blastCmd);
    
      file = FilOpenW (seqFile, &errCode);
      SeqWriteFasta (&seq, "tmp", (INT4(*)(char*,...)) wwwWriteFile);
      fclose (file);
      ParDefStr ("inputSequence", ""); 
    
      templ = TemplOpen ("SRSICA:srswww.i", NULL);
      WwwPrintContentType (NULL);
      TemplWith (templ, "$blastResult");
      TemplPrint ("head");
      fflush (stdout);
    
      /* prepare a blast c-shell file and run it*/
      cshTempl = TemplOpen ("SRSICA:srswww.i", cshFile);
      TemplWith (cshTempl, "$blastScript");
      TemplPrint ("body", SmEdit(blastCmd,SMxTRIM));
      TemplEndWith ();
      TemplClose (cshTempl);
      FilChMod (cshFile,"X"); /* there is no 'X' mode opt., but changes */
      sprintf(blastCmd,"$%s",cshFile);
      system(blastCmd);
    
      sprintf (parName, "%sDirName", lib->nam);
      ParDefStr ("libGroup", lib->group->com);
      ParDefStr ("libList", lib->nam);
    
      ParDefStrF (parName, "SRSWWWTMP:%s/",userId); 
    }
    
    
    
    /****** PageDoFasta ***********************************************************
    **
    **       Does a fasta search and outputs the result.
    **
    */
    
    static void PageDoFasta()
    {
      TEMPLv  templ, cshTempl;
      SLBo    *lib;
      SEQo    seq;
      char    parName[80];
      INT4    errCode;
    
      char fastaDir[80];
      char seqFile[80];
      char cshFile[80];
      char fastaCmd[512];
    
      char *tmp;
      INT4 i = 0;
      char *userId = ParGetStr("userId");
      
      fastaCmd[0] = '\0';
    
      if (!(lib = (SLBo *) LibObjByName ("library", "Fasta")))
        _ErrExit3 (e__objectunknown, "library", "Fasta");
    
      seq.seq = ParGetStr ("inputSequence");
      seq.len = strlen (seq.seq);
      
      sprintf(seqFile,"%s:%s/tmp.seq","SRSWWWTMP",userId);
      file = FilOpenW (seqFile, &errCode);
      SeqWriteGCG (&seq, "tmp", (INT4(*)(char*,...)) wwwWriteFile);
      fclose (file);
      ParDefStr ("inputSequence", ""); 
    
      sprintf(cshFile,"%s/%s/fasta","SRSWWWTMP",userId);
      sprintf(fastaDir,"SRSWWWTMP:%s",userId);
      sprintf(fastaCmd,"fasta -infile1=%s -infile2=%s -wordsize=%s -list=%s",
    	  seqFile,ParGetStr("fasta_SearchLib"),ParGetStr("fasta_ktup"),
    	  ParGetStr("fasta_listSeq"));
    
      sprintf(fastaCmd," %s > tmp.fasta",fastaCmd);
    
      templ = TemplOpen ("SRSICA:srswww.i", NULL);
      WwwPrintContentType (NULL);
      TemplWith (templ, "$fastaResult");
      TemplPrint ("head");
      fflush (stdout);
    
      /* prepare a fasta c-shell file and run it*/
      cshTempl = TemplOpen ("SRSICA:srswww.i", cshFile);
      TemplWith (cshTempl, "$fastaScript");
      TemplPrint ("body", SmEdit(fastaCmd,SMxTRIM));
      TemplEndWith ();
      TemplClose (cshTempl);
      FilChMod (cshFile,"X"); /* there is no 'X' mode opt., but changes */
      sprintf(fastaCmd,"$%s",cshFile);
      system(fastaCmd);
    
      sprintf (parName, "%sDirName", lib->nam);
      ParDefStr ("libGroup", lib->group->com);
      ParDefStr ("libList", lib->nam);
      ParDefStrF (parName, "SRSWWWTMP:%s/",userId); 
    }
    
    
    
    /****** WwwMarkDeletedQuery *********************************************
    **
    **      Mark deleted query. 
    **
    **      INPUT :   Address of query Object [W]
    **                 query number (INT)
    **
    **      RETURNS:   none
    **
    */
    void WwwMarkDeletedQuery(WWWoQUERY *query, INT4 queryN)
    {
      char par[80];
    
      query->isDeleted = 1; /* set the status flag */
      sprintf(par,"QueryDeleted_%d",queryN);
      ParDefNum(par,query->isDeleted);
    }
    
    /****** WwwisQueryDeleted *********************************************
    **
    **      Checks whether a query marked deleted or not.
    **
    **      INPUT :   Address of query Object [R]
    **
    **      RETURNS:   query status flag.
    **
    */
    INT4 WwwisQueryDeleted(  WWWoQUERY *query)
    {
      return(query->isDeleted);
    }
    
    
    /**api* PageConstructQuery ***************************************************
    **
    **      Constructs a valid query from form input, performs it and 
    **      displays the result.
    **
    */
    static void PageConstructQuery()
    {
      SLBo      *lib;
      SLBoFIELD *field;
      SRSoGROUP *group, *groupCurr;
      QASoQUERY *query;
      char      *fieldName, *tmp;
      INT4      c1,c2;
      
      query = QasNew ();
      QasSetOp (query, ParGetStr ("query_operator"));
      
      /* set selected libraries */
      groupCurr = LibGroupNew (NULL);
      for (c1=0; (group = LibNextLibGroup (&c1)); ) 
        for (c2=0; (lib = LibNextLib (group, &c2));) {
          if (!(LibIs(lib, "selected"))) 
    	continue;
          QasSetLibrary(query, LibGetName(lib,"full"));
          LibGroupAddDb (groupCurr, lib);
        }
    
      /* set index queries */
      for (c1=0; (field = LibNextGroupField (groupCurr, 1, &c1));) {
        fieldName = LibGetFieldName(field) ;
        if(LibIsField(field,"num") || LibIsField (field, "real")) {
          if(*(tmp = ParGetStrF("query_%s_begin",fieldName)))
    	QasSetRangeBegin (query, fieldName, tmp);
          if(*(tmp = ParGetStrF("query_%s_end",fieldName)))
    	QasSetRangeEnd (query, fieldName, tmp); 
          if (SmEqs (ParGetStrF("query_%s_beginmod",fieldName), ">"))
    	QasSetRangeBeginExcl (query, fieldName);
          if (SmEqs (ParGetStrF("query_%s_endmod",fieldName), "<"))
    	QasSetRangeEndExcl (query, fieldName);
        }
        else
          if( *(ParGetStrF("query_%s",fieldName)))
    	QasSetRetrieveStr(query,fieldName,ParGetStrF("query_%s",fieldName));
        if( LibIsField(field,"subEntry") && 
    	ParGetBoolF ("subEntry_%s", fieldName))
          QasSetSubEntries(query,fieldName);
      } 
      if(ParGetNum("makeWild"))
        QasSetMakeWild (query);
    
      ParDeleteMatch ("^query_");
      if (QasGetQueryString(query))
        WwwQueryExpression ("query", QasGetQueryString(query));
      else 
        _ErrExit (e__wwwNoQuerySpecified);
      
    }
    
    
    /****** PageMoreEntries ************************************************
    **
    **      Lists entries of already existing query.
    **
    */
    
    static void  PageMoreEntries ()
    {
      WwwQueryRepeat (ParGetNum ("listSetNumber"));
      WwwQueryPrint (ParGetNum ("listSetNumber"));
    }
    
    
    
    /****** PageLinkOpt ***********************************************************
    **
    **       Lets the user link an entire set or an entry selection to other
    **       databanks.
    **
    */
    
    static void PageLinkOpt ()
    {
      TEMPLv    templ;
      SLBo      *lib;
      SRSoGROUP *group;
      char *querystr, *opt; 
      Int4  ngroups = 0, num[10], c1=0, c2,setN;
      Int4  nlib = 0, max, numCol, queryN;
    
      templ = WwwInit ();
      TemplWith (templ, "$linkPage");
      querystr = ParGetStr("queryString");
    
      /* get either set selected from query manager or the list of
         selected entries */
      if ((queryN=WwwNextSelectedQuery (&c1, NULL)) ||
          (queryN=WwwQuerySelectedEntries ()))
        ParDefNum("linkSetNumber",queryN);
      else
        _ErrExit (e__wwwNoQueryOrEntriesSelected);
      setN = ParGetNum("linkSetNumber");
    
      max = LibGetMaxNameSize (NULL, NULL, "library") + 1;
      numCol = 60/(max);          /* adjust number of columns */
      if(ParGetBool("isHtml3")) numCol = 65/max;
    
      TemplPrint ("head", querystr);
      WwwPrintButtons (templ);
      opt = ParGetStr ("linkSetType");
      TemplPrint ("linkType", setN);
    
      TemplWith(templ,"$queryManager.chunkSize");
      WwwPresentChunkSizes (templ);
      TemplEndWith();
      TemplWith(templ,"$queryManager.selectView");
      WwwPresentViewList ("reset");
      TemplEndWith();
    
    
      TemplWith (templ, ParGetBool("isHtml3") ? "html3" : "html2");
      for (c1=0; (group = LibNextLibGroup (&c1)); ) {
        if( ! (ngroups = LibNofGroups(group))) continue;
        TemplPrint ("dbGroup", group->com);     
        for (c2=0, nlib = 0; (lib = LibNextLib (group, &c2)); nlib++) {
          ParDefNum ("l",max-strlen(LibGetName(lib,"full")));
          if (!(nlib%numCol)) 
    	TemplPrint ("newRow");
          TemplPrint ("library", LibGetName (lib,"full"),
    		  WwwChecked (LibIs (lib,"linkTarget")),
    		  LibGetName(lib,"full"), LibGetName(lib,"full"), "");
        }
        TemplPrint ("tail");
      }
      TemplEndWith ();
      TemplPrint ("tail");
    }
    
    
    
    /****** PageLibNetwork ********************************************************
    **
    **	Prints the library network in a tabular representation;
    **
    */ 
    
    void PageLibNetwork ()
    {
      TEMPLv    templ;
      SRSoGROUP *fromGroup, *toGroup;
      SLBo      *fromLib, *toLib;
      LINKo     *link;
      LINKvNode path;
      Int4      c1, c2, c3, c4;
      char      *fromLibName, *toLibName, *letter;
    
      templ = WwwInit ();
      TemplWith (templ, "$libNetwork");
      TemplPrint ("head");
      WwwPrintButtons (templ);
      TemplPrint ("title");
    
      /* iterate over all 'from' libs */
      for (c1=0; (fromGroup = LibNextLibGroup (&c1)); )
        for (c2=0; (fromLib = LibNextLib (fromGroup, &c2)); ) {
          fromLibName = LibName (fromLib);
          TemplPrint ("fromLib", fromLibName, fromLibName);
          /* iterate over all 'to' libs */
          for (c3=0; (toGroup = LibNextLibGroup (&c3)); ) {
    	for (c4=0; (toLib = LibNextLib (toGroup, &c4)); ) {
    	  toLibName = LibName (toLib);
    	  if (fromLib == toLib)
    	    break; /* link with 'self' - diagonal is reached */
    	  else { 
    	    if ((link = LibGetLink (fromLibName, toLibName))) 
    	      TemplPrint ("link.direct", fromLibName, toLibName);
    	    else {
    	      if ((path = LinkSearchPath (fromLibName, toLibName))) 
    		TemplPrint ("link.indirect", fromLibName, toLibName,
    			    LinkGetPathLength (path));
    	      else
    		TemplPrint ("link.none");
    	    }
    	  }
    	}
    	if (fromLib == toLib)
    	  break;
          }
          TemplPrint ("rowEnd");
        }
      
      /* print all databank names vertically */
      TemplPrint ("toLibs");
      for (c1=0; (toGroup = LibNextLibGroup (&c1)); )
        for (c2=0; (toLib = LibNextLib (toGroup, &c2)); ) {
          toLibName = LibName (toLib);
          TemplPrint ("toLib.head");
          for (letter=toLibName; *letter; letter++)
    	TemplPrint (*(letter+1) ? "toLib.letter" : "toLib.last", *letter);
          TemplPrint ("toLib.tail");
        }
    
      TemplPrint ("tail");
      TemplEndWith ();
      TemplClose (templ);
    }
    
    
    /****** PageLinkInfo *********************************************************
    **
    **	Prints information about a link between two data banks.
    **
    */ 
    
    void PageLinkInfo ()
    {
      TEMPLv    templ;
      LINKo     *link;
      LINKvNode path, p;
      char      *from, *to, *tmp;
      Int4      isReverse, toN, fromN, totalN;
    
      templ = WwwInit ();
      TemplWith (templ, "$linkInfo");
      TemplPrint ("head");
      WwwPrintButtons (templ);
      TemplPrint ("title");
    
      to = ParGetStr ("toLibName");
      from = ParGetStr ("fromLibName");
    
      if (!(path = LinkSearchPath (to, from)))
        TemplPrint ("noLink", from, to);
      else {
        if (LinkGetPathLength (path) == 1) /* direct link */
          TemplPrint ("direct", from, to);
        else { /* indirect link */
          TemplPrint ("indirect.head", WwwGetLinkedEntriesN (to, from), from,
    		  WwwGetLinkedEntriesN (from, to), to, from);
          for (tmp=NULL, p=path; (p = LinkBackTrack (p, &link, &isReverse));
    	   tmp=isReverse? LibName (link->lib1) : LibName (link->lib2))
    	if (tmp)
    	  TemplPrint ("indirect.pathLib", tmp);
          TemplPrint ("indirect.lastLib", tmp);
        }
    
        TemplWith (templ, "table");
        TemplPrint ("head");
        while ((path = LinkBackTrack (path, &link, &isReverse))) {
          to = LibName (link->lib2);
          from = LibName (link->lib1);
    
          if (LinkOpen (link, "read")) {
    	toN = LinkGetEntryN (link, 1);
    	fromN = LinkGetEntryN (link, 0);
    	totalN = LinkGetLinkN (link);
          }
          else 
    	toN=0, fromN=0, totalN=0;
    	
          if (isReverse)
    	TemplPrint ("names", to, to, toN, from, from, fromN);
          else
    	TemplPrint ("names", from, from, fromN, to, to, toN);
          
          TemplPrint("total", totalN);
          if (link->typ == LNKxREAD)
    	TemplPrint("read", from, link->toField->nam, to);
          else 
    	TemplPrint("index", link->fromField->nam, to, link->toField->nam,from);
    
          /* creation time */
          if (toN)
    	TemplPrint ("creTime", TimeToString (LinkGetCreTime (link), "long"));
          else 
    	TemplPrint ("notCreated");
    
          TemplPrint ("rowEnd");
        }
      }
      TemplEndWith ();
      TemplPrint ("tail");
      TemplClose (templ);
    }
    
    
    Int4 WwwGetLinkedEntriesN (char *from, char *to)
    {
      SETo *set;
      STRv str;
      Int4  n;
    
      str = StrNew ();
      if ((set = Query (_Str (StrPrintf (&str, "%s>%s", from, to)),"linkN"))) 
        n = SetGetSize (set);
      else 
        n = 0;
      SetDelete ("linkN");
      StrDel (str);
      return n;
    }
    
    
    
    /****** PageLibList **********************************************************
    **
    **      Displays information about available databanks
    **
    */
    
    void PageLibList ()
    {
      TEMPLv    templ;
      SLBo      *lib;
      SRSoGROUP *group;
      LIBoINDEX *libInx;
      INT4      c1, c2; 
      char      *tmp, *libName;
    
      templ = WwwInit ();
      TemplWith (templ, "$libList");
      TemplPrint ("head");
      WwwPrintButtons (templ);
      TemplPrint ("title", TimeToString (0, "long"));
    
      for (c1=0; (group = LibNextLibGroup (&c1)); )
        for (c2=0; (lib = LibNextLib (group, &c2)); ) {
          libName = LibName (lib);
          if ((libInx = LibIndexOpen (lib, LibGetIdField (lib), 1))) 
    	TemplPrint ("libraryGood", WwwGetIdParam (), libName, libName,
    		    tmp && *(tmp = IdxGetReleaseName (libInx->idx)) ? 
    		    tmp : " ",
    		    BtrGetRecordN (libInx->btree),  
    		    TimeToString (BtrGetTimeCreated (libInx->btree), "date"),
    		    LibGetGroupName (group, "full"));
          else 
    	TemplPrint ("libraryBad", WwwGetIdParam (), libName, libName,
    		    LibGetGroupName (group, "full"));
        }
      TemplPrint ("tail");
      TemplEndWith ();
    }
    
    /****** PageLibInfo **********************************************************
    **
    **      Displays information about a databank.
    **
    */
    
    void PageLibInfo ()
    {
      TEMPLv    templ;
      SLBo      *lib;
      SLBoFIELD *field;
      LINKo     *link;
      LIBoINDEX *libInx;
      INT4      c, count; 
      char      *tmp, *libName;
    
      templ = WwwInit ();
      TemplWith (templ, "$libInfo");
      TemplPrint ("head");
      WwwPrintButtons (templ);
    
      libName = ParGetStr ("libInfo");
      if (!(lib = (SLBo *) LibObjByName ("library", libName)))
        _ErrExit3 (e__objectunknown, "library", libName);
    
      TemplPrint ("title", libName);
      if ((libInx = LibIndexOpen (lib, LibGetIdField (lib), 1))) {
        tmp = IdxGetReleaseName (libInx->idx);
        if (tmp && *tmp)
          TemplPrint ("release", tmp, BtrGetRecordN (libInx->btree),
    		  TimeToString (BtrGetTimeCreated (libInx->btree), "date"));
        else 
          TemplPrint ("noRelease", BtrGetRecordN (libInx->btree),
    		  TimeToString (BtrGetTimeCreated (libInx->btree), "date"));
      }
      else 
        TemplPrint ("notIndexed");
    
      /* print information about the fields */  
    
      TemplWith (templ, "fields");
      TemplPrint ("head");
      for (c=0; (field = LibNextField (lib, &c));) {
        if (LibIsField (field, "group") || LibIsField (field, "header"))
          continue;
    
        TemplPrint ("names", LibGetFieldName (field), LibGetFieldName (field), 
    		LibGetFieldShortName (field));
    
        if (LibIsField (field, "id"))
          TemplPrint ("type", "ID");
        else if (LibIsField (field, "real"))
          TemplPrint ("type", "real");
        else if (LibIsField (field, "num"))
          TemplPrint ("type", "int");
        else if (LibIsField (field, "index"))
          TemplPrint ("type", "string");
        else if (LibIsField (field, "link"))
          TemplPrint ("type", "link");
        else if (LibIsField (field, "show"))
          TemplPrint ("type", "show");
    
    
        if (LibIsField (field, "index")) {
          if ((libInx = LibIndexOpen (lib, field, 1))){
    	TemplPrint ("numbers", BtrGetRecordN (libInx->btree), 
    		    IdsGetIdN (libInx->idsFile),
    		    TimeToString (BtrGetTimeCreated (libInx->btree), "long")); 
    	if (BtrIsBusy (libInx->btree))
    	  TemplPrint ("status", "busy");
    	
    	else if (!IdsIsCompressed (libInx->idsFile))
    	  TemplPrint ("status", "not compressed");
    	else
    	  TemplPrint ("status", "ok");
          }
          else
    	TemplPrint ("notIndexed");
        }
        else
          TemplPrint ("showField");
      }
      TemplPrint ("tail");
      TemplEndWith ();
    
      /* links to other databanks */
    
      TemplPrint ("links.to");
      for (c=0, count=0; (link = LibNextLink (&c));) 
        if (lib == link->lib1) {
          TemplPrint ("links.toLib", LibName (link->lib1), LibName (link->lib2), 
                      LibName (link->lib2), LibName (link->lib2));
          count++;
        }
      if (!count)
        TemplPrint ("links.none");
      TemplPrint ("links.from");
      for (c=0, count=0; (link = LibNextLink (&c)); ) 
        if (lib == link->lib2) {
          TemplPrint ("links.fromLib", LibName (link->lib2), LibName (link->lib1), 
                      LibName (link->lib1), LibName (link->lib1));
          count++;
        }
      if (!count)
        TemplPrint ("links.none");
      TemplPrint ("links.tail");
    
    
      TemplPrint ("tail");
      TemplEndWith ();
    }
    
    
    
    /****** WwwGetOddFile *******************************************************
    **
    **      Display odd description of a databank
    **
    **       INPUT:
    **
    **
    */
    
    void  WwwGetOddFile()
    {
      char *tmp = ParGetStr("getOddFile");
      if (tmp)
        WwwGetODDFile(tmp);
      
    }
    
    
    /****** PageHelpAbout ********************************************************
    **
    **      Displays help about a topic.
    **
    */
    
    void  PageHelpAbout()
    {
      char *tmp = ParGetStr("printHelpTopic");
      if ( tmp )
        WwwPrintHelpTopic(tmp);  
    }
    
    
    
    /****** PageEntry *************************************************************
    **
    **      Prints single entry. if the userId is defined AND option -sl
    **      used then a within a session context normal entry list is printed.
    **
    */
    
    static void PageEntry ()
    {
      TEMPLv templ;
    
      templ = WwwInit ();
    
      ParDefBool ("isHTMLFormat", 1);
      if (*ParGetStr ("userIdOpt") && ParGetBool ("wwwSessionEntryList")) {
        ParSetVolatile ("wwwSessionEntryList");
        WwwQueryExpression ("query", pageQuery);
      }
      else if (Query (pageQuery, "Q")) { 
        WwwPrintSet (templ, "Q", 1, 0);
      }
    }
    
    
    /****** WwwDeleteQueryByNum ******************************************************
    **
    **	deletes the selected query from history;
    **
    **	INPUT:	    
    **	        IMPLICIT:
    **
    **	RETURNS:    
    */ 
    
    INT4 WwwDeleteQueryByNum(INT4 j)
    {
      char parName[80];
      INT4 queryN, k;
      
      queryN = ParGetNum ("numberOfQueries");
      sprintf (parName, "QueryStr%d", j); 
      ParDelete (parName);
      sprintf (parName, "QuerySize%d", j); 
      ParDelete (parName);
      sprintf (parName, "QueryType%d", j); 
      ParDelete (parName);
      sprintf (parName, "isSubEntry%d", j);
      ParDelete (parName);
    
      for (k=1; ; k++) {
        sprintf (parName, "QueryLibrary%d_%d", j, k); 
        if (!ParDelete (parName))
          break; /* no more items */
        sprintf (parName, "QueryLibraryN%d_%d", j, k); 
        ParDelete (parName);
      }
      ParDefNum ("numberOfQueries", --queryN);
    }
    
    
    /****** GetEnv **************************************************************
    **
    **      Get the environment variables
    **
    **	INPUT:	    
    **	        IMPLICIT:
    **
    **	RETURNS:    
    **
    **
    */
    void  GetEnv()
    {
    
      GetEnvp(envPtr);
      
    }
    
    /****** GetEnvp **************************************************************
    **
    **
    **
    **
    **	INPUT:	    
    **	        IMPLICIT:
    **
    **	RETURNS:    
    **
    */
    
    INT4 GetEnvp(char **envPtr)
    {
    #ifdef script
      INT4 i=0;
      char *tmp;
      char name[80], value[80];
    
      SCRIPTo *script;
    
      script = ScriptOpen (ScriptFile,NULL);
    
      ScriptCopyFrom(script,"ENVIRONMENT-VAR");
      for (i=0;*envPtr; envPtr++) {
        sscanf (*envPtr, "%[^=]=%[^:]", name,value);
        ScriptWriteFrom(script,"LIST-ENV-VAR",name,++i,value);
      }
      ScriptCopyFrom(script,"ENV-END");
      return 1;
    #endif
    }
    
    /*** GetEnvByName ***************************************************************
    **
    **     Returns Environment variable values referred.
    **
    **
    **     INPUT : 
    **               
    **    RETURNS:
    **               
    **
    */
    
    char *GetEnvByName(char *ename)
    {
      static char value[80];
      INT4 i=0;
      char name[80];
      value[0] = name[0] = '\0';
      for (i=0;*envPtr; envPtr++) {
        sscanf (*envPtr, "%[^=]=%[^:]", name,value);
        if(SmEqs(ename,name) == 1) 
          return(value);
      }
      return(NULL);
    }
    
    
    /**api* PageDownloadSet ******************************************************
    **
    **      Refine the output with more options like alter flanking 
    **      regions, sequence format etc., 
    **
    **	INPUT:	    
    **
    **	RETURNS:    
    **
    */ 
    
    static void PageDownloadSetOpt()
    {
      TEMPLv templ;
      WWWoQUERY *query;
      char *tmp,  *tmp1;
      char *tmp2, *tmp3;
      INT4 queryN, queryNum=0, c=0;
    
    
      /* check whether individual entries selected, if then do a query and 
         define the queryNumber, ( can be done with numberOfQueries ?) */
      
      if ((queryNum=WwwNextSelectedQuery (&c, NULL)) ||
          (queryNum=WwwQuerySelectedEntries ()))
        ParDefNum("queryNumber",queryN);
      else
        _ErrExit (e__wwwNoQueryOrEntriesSelected);
      query = WwwGetQuery(queryNum);
    
      templ = WwwInit ();
      TemplWith (templ, "$downloadSet");
      TemplPrint("head");
      WwwPrintButtons (templ);
    
    
      TemplWith(templ, ParGetBool("isHtml3") ?"inputInfo.html3":"inputInfo.html2");  
      if( query->isSubEntry) {
        tmp = ParGetStr("shiftbeginpos");
        tmp1 = ParGetStr("shiftendpos");
        tmp2 = ParGetStr("checkbegin");
        tmp3 = ParGetStr("checkend");
        
        ParDefBool("isshiftendrelbegin",0);   /* default, keep as it is */
        ParDefBool("isshiftbeginrelend",0);
    
        if( (SmLoc(tmp2,"begin") != -1) &&  (SmLoc(tmp3,"begin") != -1) )
          ParDefBool("isshiftendrelbegin",1); /* change if both are begin , meaningfull */
        
        if( (SmLoc(tmp2,"end") != -1) &&  (SmLoc(tmp3,"end") != -1) )
          ParDefBool("isshiftbeginrelend",1);/* change if both are end , meaningfull */
        
        TemplPrint("shift",(*tmp ? tmp : ""),(*tmp1 ? tmp1 : "" ));
        TemplEndWith();
        TemplPrint("unComplete");
      }
      else
        TemplEndWith();
    
      WwwPresentChunkSizesMime(templ);
      TemplWith(templ,"$queryManager.selectView");
      WwwPresentViewList ("reset");
      TemplEndWith();
    
      tmp1  = ParGetStr("localDirName");
      TemplPrint("useMime", (WwwChecked(ParGetBool("useMime"))),
    	     (*tmp1 ? tmp1 : "" ));
      TemplPrint("tail");
      WwwDelQuery(query);
    }
    
    /**api* PageDownloadSet *******************************************************
    **
    **      Saves the selected set to the user's directory.
    **
    */
    
    static void PageDownloadSet()
    {
    
      TEMPLv  templ;
    
      WWWoQUERY *query;
      char *dirName;
      INT4 queryN;
      INT4 viewStartN = 0;
      INT4 viewEndN = 0;
      char *viewBlock = ParGetStr("viewEntriesBlock");
    
      if( *viewBlock) {
        sscanf(viewBlock,"%d - %d",&viewStartN,&viewEndN);
      }
      templ = WwwInit ();
      if(!ParGetBool("useMime")) {
        ;/*WwwViewMoreEntries();*/
      }
      else {
        dirName = ParGetStr("localDirName");
        if(!(*dirName))
         dirName = "trash" ;
        TemplPrint("head");
        TemplPrint("start","tempfile",dirName,"Ver1","copy",
    	       ParGetStr("seqFormat"));
    
        queryN = ParGetNum("queryNumber");
        query = WwwGetQuery(queryN);
        WwwQueryRepeat (queryN);
        ParDefBool ("isHTMLFormat", 0);
        WwwPrintSet(templ,query->name,viewStartN,viewEndN);
        ParDefBool ("isHTMLFormat", 1);
        WwwDelQuery(query);
        ParDelete("useMime");
      }
      TemplEndWith();
    }
    
    
    
    /**api*  PageViewEdit *********************************************************
    **
    **      Lets the user edit an existing view.
    **
    */
    
    static void PageViewEdit ()
    {
      char *viewName;
      INT4  viewNumber, j, numberOfViews = ParGetNum("numberOfViews");
    
      viewName = ParGetStr("viewName"); /* get from viewcreate page */
      if(!*viewName) /* otherwise from view manager page */
        for (j = 1, viewName = NULL; j <= numberOfViews; j++) {
          if (!(*(viewName = ParGetStrF ("selectedViewNo_%d",j)))) continue;
          viewNumber = j;
          break;
        }
      else
        viewNumber = ViewGetViewNumber(viewName);
    
      if(!*viewName)
        _ErrExit (e__noviewselect);
    
      WwwViewPartI (viewNumber,1);
    }
    
    /**api* PageViewCreate ********************************************************
    **
    **      Lets the user create a new view.
    **
    */
    
    static void PageViewCreate ()
    {
      INT4 viewNumber = ParGetNum("numberOfViews") + 1; 
      WwwViewPartI (viewNumber, 0);
      ViewMarkNascent (NULL, viewNumber);
    }
    
    /**api*  PageViewMgrCreate ****************************************************
    **
    **       Create a new view from  from view manager.
    **
    */
    
    void  PageViewMgrCreate ()
    {
      INT4 viewNumber = ParGetNum("numberOfViews") + 1; 
      WwwViewPartI (viewNumber, 0); 
      ViewMarkNascent (NULL, viewNumber);
    }
    
    
    /**api* PageViewSelectFields **************************************************
    **
    **      View creation part II - selection of fields for 'root' and 'leaf'
    **      libraries
    **
    */
    
    static void PageViewSelectFields ()
    {
      TEMPLv          templ;
      SRSoGROUP       *group;
      SLBoFIELD       *field;
      VIEWo           *view;
      VIEWoLIB        *vlib;
      INT4            k, c, c2, viewNum, isOnlyCommon, numCol;
      char            viewName[100], *libName;
    
      templ = WwwInit ();
    
      viewNum = ParGetNum ("viewNumber");
      view = WwwViewGet (viewNum, templ);
      if (ViewIs (view, "nascent"))
        ParDefNum ("numberOfViews", ParGetNum ("numberOfViews")+1);
      ParDelete ("isNewView");
      if (!*ParGetStrF("view%d_Name", viewNum)) {
        c=0;
        if (!(vlib = ViewGetNextRootLib (view, &c)))
          _ErrExit (e__nolibslct);
        sprintf (viewName, "%s_view%d", LibName (vlib->lib), viewNum);
        ViewSetName (view, viewName);
      }
    
      TemplWith(templ, "$viewSelectFields");
      TemplPrint ("head", viewNum, viewNum, viewNum, viewNum, ViewGetName (view), 
    	      ParGetStrF ("view%d_Name",viewNum));
    
      /* print all root libraries and fields */
      TemplWith (templ, "root");
      group = LibGroupNew (NULL);
      for (c=0; (vlib = ViewGetNextRootLib (view, &c));) {
        numCol = 70 / LibGetMaxNameSize (NULL, vlib->lib, "formatted")+1;
        LibGroupAddDb (group, vlib->lib);
        TemplPrint ("lib", LibName (vlib->lib), LibName (vlib->lib));
      }
    
      isOnlyCommon = ParGetBool ("isOnlyCommonFields");
      for ( c=0, k=0; (field = LibNextGroupField (group, isOnlyCommon, &c));) {
        if (LibIsField(field, "show") || LibIsField (field, "header"))
          WwwPrintSelectField (view, viewNum, field, NULL, numCol, &k);
      }
      TemplPrint ("tail");
      TemplEndWith ();
    
      /* iterate over leaf libraries */
      TemplWith (templ, "leaf");
      for(c=0; (vlib = ViewGetNextLeafLib (view, &c)); ) {
        numCol = 70 / LibGetMaxNameSize (NULL, vlib->lib, "formatted") +1;
        libName = LibName (vlib->lib);
        TemplPrint ("head", libName, "", libName, libName, viewNum, libName);
        for(c2=0, k=0; (field = LibNextField (vlib->lib, &c2));) {
          if (LibIsField(field,"show") || LibIsField (field, "header"))
    	WwwPrintSelectField (view, viewNum, field, vlib, numCol, &k);
        }
        TemplPrint ("extraOptions", viewNum, libName, 
    		WwwStringEncode (ViewGetLeafQueryStr (vlib)));
        WwwPresentViewsForLeaf (view, vlib);
        TemplPrint ("tail", viewNum, libName, 
    		WwwChecked (ViewLeafIsOnlyEntryN (vlib)));
      }
      TemplEndWith ();
      TemplPrint ("tail");
      TemplEndWith ();
    
    }
    
    
    
    /****** PageViewManager ***************************************************
    **
    **      Displays all defined views and some operations on them.
    **
    */
    
    static void PageViewManager()
    {
      VIEWo           *view;
      TEMPLv          templ;
      SLBoFIELD       *field;
      VIEWoLIB        *vlib;
      LIBoFieldFormat *format;
      char            *tmp, *formatName;
      Int4            j, k, m, l, 
                      nViews = ParGetNum("numberOfViews"), nfield=0 ,nlibs=0;
      Int4            leafLibsN = 0, f;
    
      templ = WwwInit ();
      TemplWith(templ,"$viewManager");
      TemplPrint("head");
      WwwPrintButtons (templ);
    
      TemplPrint("actions");
    
      TemplWith(templ,"viewList");
      /* delete still nascent (incomplete views) or views marked for deletion */
      for(j=1; j <= nViews ; j++) {
        view = WwwViewGet (j, templ);
        if (ViewIsDeleted (view)) 
          continue;
        if (ViewIs (view, "nascent") || ViewIs (view, "selected")) {
          ViewMarkDeleted (view);
          continue;
        }
        leafLibsN = ViewCountLeafLibs(view);
        TemplPrint("head",leafLibsN,j,ViewGetName(view),
    	       ViewGetName (view), leafLibsN,
                   (ViewIsTable (view) ? "table" : "list"), leafLibsN);
        TemplPrint (ViewIsShortNames (view) ? "shortNames" : "longNames", 
    		leafLibsN);
    
        for(k=0; (vlib = ViewGetNextRootLib(view,&k));) { 
          TemplPrint("root",LibName(vlib->lib));
        }
        TemplPrint("tableData",leafLibsN);
        vlib = ViewGetNextRootLib(view,&k);
        for(m=0;(field=ViewGetNextField(vlib,&m));) {
          TemplPrint("rootField",LibGetFieldName (field));
          formatName = ParGetStrF("v%d_RF_%s_format",j,LibGetFieldName(field));
          if(*formatName)
    	 TemplPrint("format",formatName);
        }
        TemplPrint("tableDataEnd");
    
        /* leaf */
        for(k=0, l=0; ( vlib = ViewGetNextLeafLib(view,&k)); l++) {
          if (l) 
    	TemplPrint("rowEnd");
          TemplPrint("leaf.lib",LibName (vlib->lib));
          for(m=0;(field=ViewGetNextField(vlib,&m));) {
    	TemplPrint("leaf.field", LibGetFieldName (field));
    	formatName  = ParGetStrF("v%d_LF_%s_%s_format",j,LibName(vlib->lib),
    			 LibGetFieldName(field)); 
    	if(*formatName)
    	   TemplPrint("leaf.format",formatName);
          }
          tmp=ViewGetLeafQueryStr (vlib);
          TemplPrint (*tmp? "leaf.query" : "emptyCell", WwwStringEncode (tmp)); 
          tmp=ViewGetLeafView (vlib);
          TemplPrint (*tmp? "leaf.view" : "emptyCell", tmp); 
          TemplPrint (ViewLeafIsOnlyEntryN (vlib) ? 
    		  "leaf.onlyEntryN" : "emptyCell");
        }
        TemplPrint("tail");
      }
      TemplEndWith();
      TemplPrint("tail");
      ViewDelete(view);
    }
    
    
    
    
    /**api* PageViewSelectedEntries **********************************************
    **
    **      Views selected entries.
    **
    */
    
    static void PageViewSelectedEntries ()
    {
      TEMPLv    templ;
      INT4      queryN;
    
      templ = WwwInit ();
      queryN = WwwQuerySelectedEntries ();
      if(!queryN) { /* when no entries then do query for "queryNumber" */
        queryN = ParGetNum("queryNumber"); 
        WwwQueryRepeat (queryN); 
      }
      WwwQueryPrint (queryN);
    }
    
    
    /*** API* SmTrimAt ****************************************************************
    **
    **
    **  	INPUT:	address of string [W]
    **  		position to truncate
    **  
    **  	RETURNS:   
    **
    **
    */
    
    char *SmTrimAt (char *s, Int4 n)
    {
      if(strlen(s) >= n)
        s[n] = '\0';
      return s;
    }
    
    /*** API* SmFillFrom ****************************************************************
    **
    **  	INPUT:	address of string [W]
    **  		position to fill from
    **              address of the string to fill
    **  
    **  	RETURNS:  modified string
    **
    **
    */
    
    char *SmFillFrom(char *s, Int4 n, char *fill)
    {
      Int4 m = strlen(s)+strlen(fill),k=0;
    
      if( (m) > n ) {
        for(k=n; *fill ; k++) 
          s[k] = *fill++;
        s[k] = '\0';
      }
      return s;
    }
    
    
    /****** PageLinkToLibs ********************************************************
    **
    **
    **
    */
    
    static void PageLinkToLibs ()
    {
      INT4 queryN;
    
      if ((queryN = ParGetNum ("linkSetNumber"))) {
        if (SmEqs ("linkStat", ParGetStr ("linkSetType"))) 
          WwwLinkStat (queryN);
        else {
          if ((queryN = WwwLinkSet (queryN)))
    	WwwQueryPrint (queryN);
          else
    	_ErrMsg (i__noentriesfound);
        }
      }
    }
    
    
    /**api* WwwPrintButtons ******************************************************
    **
    **      Prints buttons at the top of the page.
    **      The function finds out the current page by looking at what function
    **      is defined.
    **      The function assumes that the "templ" object is already opened.
    **
    */
    
    void WwwPrintButtons (TEMPLv templ)
    {
      Func function;
    
      if (!*(ParGetStr ("userId")))
        return;
    
      TemplWith (templ, "$buttons");
    
      TemplPrint ("head");
      TemplPrint ("selectDatabanks");
      TemplPrint ("queryForm");
      TemplPrint ("queryManager");
      TemplPrint ("views");
      TemplPrint ("databank");
    
      TemplPrint ("help.head");
      function = ParGetFunction ("wwwFunction");
      if (function == (Func)PageSelectLibrary)
        TemplPrint ("help.top");
      else if (function == (Func)PageQueryForm)
        TemplPrint ("help.query");
      else if (function == (Func)PageViewCreate)
        TemplPrint ("help.viewLibs");
      else
        TemplPrint ("help.default");
      TemplPrint ("help.tail");
    
      TemplPrint ("tail");
      TemplEndWith ();
    }
    
    
    
    
    
    
    
    
    
    
    /srs/tmp
    
    
    
    
    /srs/www
    
    
    
    
    /srs/www/bin
    
    
    
    
    /srs/www/images
    
    7:31 1996/-ko/
    /arrow_icon.gif/1.1/Tue Jul  9 20:57:32 1996/-ko/
    /blue_paper.gif/1.1/Tue Jul  9 20:54:00 1996/-ko/
    /gray_aluminum.gif/1.1/Tue Jul  9 20:54:01 1996/-ko/
    /gray_rock.gif/1.1/Tue Jul  9 20:54:02 1996/-ko/
    /greenred_marble.gif/1.1/Tue Jul  9 20:54:02 1996/-ko/
    /greenwhite_paper.gif/1.1/Tue Jul  9 20:53:56 1996/-ko/
    /home_icon.gif/1.1/Tue Jul  9 20:57:32 1996/-ko/
    /lavender_swirl_marble.gif/1.1/Tue Jul  9 20:54:03 1996/-ko/
    /lin_icon.gif/1.1/Tue Jul  9 20:57:33 1996/-ko/
    /linked_icon.gif/1.1/Tue Jul  9 20:57:33 1996/-ko/
    /linkop.gif/1.1/Tue Aug 13 11:46:38 1996//
    /linkopts.gif/1.1/Tue Jul  9 20:57:34 1996/-ko/
    /lipurple_weave.gif/1.1/Tue Jul  9 20:54:03 1996/-ko/
    /logop.gif/1.1/Tue Aug 13 11:46:39 1996//
    /manual_icon.gif/1.1/Tue Jul  9 20:57:34 1996/-ko/
    /news_icon.gif/1.1/Tue Jul  9 20:57:35 1996/-ko/
    /orange_paper.gif/1.1/Tue Jul  9 20:54:04 1996/-ko/
    /peach_paper.gif/1.1/Tue Jul  9 20:54:05 1996/-ko/
    /red_rock.gif/1.1/Tue Jul  9 20:54:05 1996/-ko/
    /red_stucco.gif/1.1/Tue Jul  9 20:54:06 1996/-ko/
    /redball.gif/1.1/Tue Jul  9 20:57:35 1996/-ko/
    /smallsrsnet.gif/1.1/Tue Jul  9 20:57:36 1996/-ko/
    /srswww.gif/1.1/Wed Jul 24 22:26:10 1996//
    /srswww.map/1.1/Wed Jul 24 22:26:11 1996//
    /status_icon.gif/1.1/Tue Jul  9 20:57:36 1996/-ko/
    /summer_paper.gif/1.1/Tue Jul  9 20:54:06 1996/-ko/
    /tan_paper.gif/1.1/Tue Jul  9 20:54:07 1996/-ko/
    /tanblue_marble.gif/1.1/Tue Jul  9 20:54:07 1996/-ko/
    /teal_paper.gif/1.1/Tue Jul  9 20:54:08 1996/-ko/
    /yellow_paper.gif/1.1/Tue Jul  9 20:54:08 1996/-ko/
    /yellow_rock.gif/1.1/Tue Jul  9 20:54:09 1996/-ko/
    /yellow_stucco.gif/1.1/Tue Jul  9 20:54:10 1996/-ko/
    /yellow_weave.gif/1.1/Tue Jul  9 20:54:10 1996/-ko/
    
    GCh٩	ZiyIi**Ji::zj{0i*8ۋ;k	|דkj>}[Y-_dϞ?/0
    ^^{=F[rlN6
    
    $RB"zH'"EČTrNHRÄS;DHJio5X/m!j+Vdcs&85tPq-f&i&,O$Nl;
    _UDOU6;79+GS(y*)s
    **[2*t
    R'hclD
    B
    Wu(m;V<_yiB*.	7NxENX4`3%'v+q]hYBflP~Y0A``V@WGy€1)=ta	.r>*'$0#-J
    2MpA
    ց1!"GMg|YWX5j2o)FyY$(P	~B)aSq(\'Aɗ70y`!0gP`BE`5Hz,pGMElKysO*L^L|>f	Q
    	\ЅOHZ_)Dn\Q4mrwPhv=Z@k$TJ `)
    DbzR9vCQ),$bOj6J P_-!
    $ak  ZQR%̂; p\sDS|$d
    NDf=cmiŰ-Hу,>nI14FD^(հU$ ȵdQ$
    D`Cƪ}C`>pAB*lht`t*~
    	HG(5aVO, C.
    M|#1$9cYD
    1hDr'2P׆%a2GIϵ$E
    du
    !C)0U0`l
    z$\T<3Hx-2`49 g
    &p0k^Xy6CF'6mNJ!B@_#Vp@	R+Ihh%pxi=F0%_JȠG *<Po<%:G\ x
    ,0y}UbAtb&tWRqv6@=`j6dg	@/Ӑ.9 ;8
    '0%e($&.V@-		"#>PWjXX%%mp=E%Yk@?Pgx&N 1la
    `T#TZVV@Eg$`$^GjBb$#$Ӑ-_לiiUU-@N A`AIsȚ"ʐHo'Lz}=8WXЖH."T]́U"0pL`$Te
    6$+P(r6P`5%
    W!#7*ѳ0J9FCgTQ0PKRWbH5F/`Vi:iAq^l26
    k$z-+
    X0zΣ7	R4_o13dsYa[c8;:M+x3ᄋ"绱Ӱ%u!4uH_qeHdebaOܕg'Ťz`JNp3a-kЖ;	 `%e2|3P.qR .TBbq782>@tc
    8c js.I=joC#S6>cKګy]Yvcq$	8>o$а R2ankP8dQ&$@kis*3_TttE1AEkK|,$I
    Q((5@È]f'2"d`Jjܿgu`4zl`۴ 8"MsAImxN[9[?))-%x }81cgjf|2zJ
    "[rk[
    20%t9;Q(IW:`A`@JVcK2Z0;bdVE3P531KM.:T`F-MTl̈1D
    kEw4҆AZLi%#;^@!S$]R9*5a7ZtT<r
    mJ L āQc9V__1LE(IL c[/*aRac2А+~:8Ca
     jK#
    eD=5K%!Y\d
    0%>$3*aD	3fDݡ1R1[€4	y}ƒgebIPBCCc4$H&poGuYX
    A"dò/!1)@	ij!R|6(*	]xDajSRrKO#[3 AʙFT@
    ij@w8TR	Rl;`0bP%
    cGјÅY)
    z129\(*?n
    3
    A(SD覊_Wۺ|,v#Da"ӑY6HƂH(ga-
    ϱ8X|4)6b,N[&7:6K"]⯇_Unt7=M%
    $MTDIFVRET#yMYuWdӒp80wrF%VIh"Ԑ$(Aa*ҩ'2ײ*)
     !CC.10Lj`Xn] v"2,0@[\L,bY*\*`:8~,&D:$6
     Q
    !uʲ("U'B;TɐtAdD	h
    
    >RR[]PȬY
    ܖUdŞBO(-E;D]xPsA?5\EZ'qޑ\&*b
    *DD?fC+GɴDDatL3zmv8XZ}Ro8džU(9{0
    /p'v@>V@sƆmZl %
    $]Ձ%R'zHw*Lq?
    #nLryRnMiI	)
    vf@ݷI']op@2$?&7_5cFnʟixX5wqzr;>j0[,dI(!wE#c!
    9iؗfU?o-1uѪnX4ЇD]PtT
    ڃtA	|L@(pj`ZV0+>D3T)Ya
    g6g\A#+x˓%@,UYebBZ3U~$Bz'L͚:ƣ4lE(\Nu03vUr-L=}] Y8$Z>G5>!7Rn6Y oVfb39%P]g!w:KӺiPGQ6M`;&;z.-`P0-QBKCW'ݳ63H`ƷAAyfW@cj"FAF]z-y|
    D{&{YcD`7A6QuhT6e![pnmDC
    AX,YXzDWX!E
    h/l7Uq#z.t)C`;.nI@oz/gn^,.CsB|S c &+Lw
    C=qxWsbO|JZ|*Bdd[lDOzftwh:(%pТwI䕪M
    P
    6lVp
    :a+	1PS
    =9Nizj	_9&Mb!x:@mh8rc,h rm31CH7ىu 3kU
    ypT8P
    q ʢ:i,A)|36#;J)Vau֔3McFsRO	>\﫧>jYRF]I\fiNnz7Id),Q+ɕ5&uč7 ̨[|,&rd0P_8$virk%dn([}t`fz
    [IqtAA7JBb
    @'O_v!ۀE
    Ek7v@,ݲ
    QWqd4 wrDvh<\M
    vQbYYz6f!HBr@]9SxbCBf\ٛkKA,֢%[E?إO
    1k˩!>ë(0|Iޥ[$96.L
    \
    t8k":$=	@yF2A5l} ҷK,JZ
    C@B'0
    `/"hr᜺?M<(rv$"uLVlX/=!M\5oZ
    M3ąH*'G?LGF;hp\ӉaO	 BRHCT/;s8q+Q;ŅK|C[G#=eMmT%*u.?0pqE$w=`/XrFD\bl!K6Ud]$$AbF3QKA&A^X`!\!IVvof'.=Fule
    ?l$jl0ވ
    CDN_:xXŦ U!d\T@Ztff*8@R0-~
    E/'DK
    c>0L/17U|PBa{w{M2>N[3NYS igr5o5
    -skcY)婰o!&;`@ F,KƊDEWB"U
    Ξ8-pUm8\FQ
    (UʆT[>!'0IhK57Ak*Uޫ/z|fLIgYR	`\M8:@iEL	KK=
    @#
    [F]!@BpI/u1uGˁW[:eG&d6|Ǯ	dlhepKXW[8IsW@<U
    	FJʍ= }
    tHLfN%U.eP!cjh@qɦЁRk8d~3	`Fgp
    L=ˆ`2<ȽU"\/΅Gʎ<ޢTd`!(O͖Q?jmW0`WK|G
    `S L͹pO`*ILxJraV/
    T2أҊ 6G	Pe)A#Lsћ	DPQ_C:x}l?5Iʇq(R+?mՍ]g`Ah*ifŌ1!:O-\LPMd4`A<G1BVޗT(	!baap/gʙ>P#=ZVͅ"v@ɀQIK0mDT?ԠםdLSnR!Pv}fTz7WhLLuWp`,
    LtjBIr#N]Bd!Ma#
    !E]i)”
    Rn!
    Vgi(*x=o
    `]~
    e6pT\M	4͞.ЅxJRZMK
    B(M'} iZ,nVD6:!ED}^E*1Шk
    lB.᙭j
    W&nK!+hU&]/?P32)Ĕ| 
    UhM3za+VekGD4\Ijtʀ+ӅՉLtÄ
    
    $$J0MjM3#	$)@u#((ؠ7@lS{	z+T{2
    )ȥAеON0LhR(%|'h`X\,2Jry6\pk	(j0)z/-xRY4A$+͛\	#74d,IZ
    !d@ETBp,E#.cyJ.zF҂p8o^@3`6zۨR'\+ 
    0t,TTBxpM2^"*G*6\(!h`>G]g2)t4<U9˘%87H
    ,p(x	0l2}1 -ߖФ	T/O~Ǡ)I69B/A}
    `q
    	PCs0)BI3ySN18E:w@3	Ĥqmax/D@P@/f(9c2##dq
    ("%xA\T03jYOZf‚\BtYx,^067IMWDBCdQJQ6TGNmZRE5>a}78z&o@A	jЂ0b
    	zxDs/pPz"l}
    1ٌ
    3>biGS> ;-8eb.lw
    t/v,kc
    nPڊBM
    ((JA0q^!R~^zj3P`0.+KJQp@Y%PsJeNr,o#VP2Np*@$+%jr4@L4#4>/fӨL
    C5E-@~Ii3AXBcƵA$15"d*>^FNnjDca	%Y.,|>i#m
    h@SV]#P0!TD@LC`c_q6G( 20	jB
    h4Z
     r	^P~ y4
    C]$[sWM:
    ɣܧg)HJn%iXd W$`\+B5(xW$֍r"
    H+`E$>Oj{l5( /	l!Am7	p+[wCBЖ
    3GG!
    
    6 6w+@x603o%NMPxp#
    da3 @qa
    Y
    '.qAG#b'(P%
    7f- 
    7F,0QC
    TZj$rK1@|I` 
    
    ̐>	'h@P@P
    5AV4>B
    5pwX$P#5p`
    .
    #<(Ӂ#+܀Gik1
    #ԀTBH36Δ&#0&2
    Ar@0b;@SeRA0\*$WXpeQAuɀ@,԰N*@I
    waVpȁ'‰^
    P
    46	
    f 	t2Wn5{/FA5.hJTL`m.@7 C/
    `(HC9U
    =!h,`0J=UPL@ 
    PP'Po|RP8 A/3zA/.)Hh 	B"|M,N/2
    2B$d&
    4
    `lC"
    R
    !h
    4p 1x/`ތ$(Ll h	ľ〉#
    >l
    l ЁAnB-PJ0H'-D
     	~@3
    > GJ	pttKKqQǤ{Dt+&`1 a @5jm6BghQ
    8
    ,@ O$?A
    qF4l:]%Q`3@N<
    
    (XnIkі^qAJW
    :p+$&v
    \p2? !Lq
    S84!̈́93`d@
    \_0j		4 <`G>
    B_"p2WQ*<?2 OS"00,
    v
    ABL0v3#*K+@B
    @
    GΔ	(M*s^hC@7tq#7e2E[
    
    EU#لf=P)f:(2>(@Pp.Q/'f
    `E09@sLl_-0+e @06
    :`
    @fˁ0-`.DG",RY$
    4,3q%1dz90WQA`_p#
    !&5X"-@
    {R
    U$եUDS\Qkb-%GL20`w?rs9'}W# ;0m*4q'R	KE @prJ?YC%s0_x-fu^&"^rKn6J#V9 /@`?|c"<0
    VT>@?f7#fC-)"$
    F33-(j`RaxXqGt!*1`<}BJ&y5qP65+33vDq?R
    '<
    R!F~fA ?^Tc
    /"0m$0
    pa)
    c4{!iPD	p" DGP
    #
    DPU5 
    V`#'!@aC.
    c-
    	}%N5  0"p*]@E7uV
    Ԧ
    k(CyT&-
    [ewbV
    
    jS*O<
    [30QcfC
    0^$!d!)^0"NŌ
    % |pPSh
    l0BVFÅdH1Auka,8	aąF'OCUJ`X'Âv1UC
    qQ@a$u0b:õR+ObX~.PИ$d pC)UM"]x`0TW.P*p*|-/d1uB,$@o1r| ^	(8w`	7(1@[#p$	U
     h
    3T"7+,DDIpA7a
    B
    $h`
    TA@+ׂ,Sh1pь
    ,
    M4XIP@Af60~`= g	iA+4p8\
    'xBBysGt~ޜB8sh0F4"@D	hV'Hdh5j\jCB
    2 #$PÁ-43*h&
    ՀX'-	6xd#liH	2p
    2T	 e*'MГq`fIUaTqh?r~pyd"jr|hL*.s0ACG3_'
    11.uF`AҁX^I|pxR	rޘ`^"
    ā5I-S*ܮ̪Zj4^<(=N]͋LKD!`A	e`FЃL.hX
    fd
    ,,f"햖j0eUg$	k3b(&
    $j0 xКjV+9DŽ4
    	XAE`2L:a`#dM*
    07$4l+n&Ylq,RB|
    @тqu+ J`)A7,kbRp:hGU(E	" hlK.Vh,/k݀a.Wl@L9X  + @^Cw'
    xy9${Ĥ: ɛ'^ٚX
    `iM,=[|'
    fM8Wd@U<@",`B**!2c, $
     
    "7F(<αhIo`XBA!R)@]o!&RKij27<2vȡ.?E@'\CQ2ȷAU12~# F	s	8'aI%$-
    kr^%Zf)@/(Qbg,KRR7Kh
    c
    ]U8ޠys|0PCZ$BxQq$7 a!&߃5%
    2v%8'tGKزƴ#l7Ke)2+#&d
    Dcr HܒTh$eU" h+
    vTnATHAb%JPkV
    r2h
    4r0!{41+A/0T	.@{E9Д.lX7"0$ղ3!T,!+23A-EI63f|&*4pZp(1%
     ->I5vm(DeG-T#'
    -	T
    U60H&@M0|tDQ]Mt
    B=
    68GT5/!`0" \Qu2'P
    3P0F[ZD9p7tM5M7G3D*ITE'07S'Ys20rV'CeZOZ37?uE	8F=TV'&ς1(.p<*7B!+m3rfI70h8DTI`RAcoO#N:o2T&pu
    X&b1ܷ/&`11`yh*aMc1/6Q
    D@:' YB^B+J"{BIՎuF2j:)I#0mrBk
    )JN,SP$8&,b)Tpt0H-r
    F-t|һA!rEc9TM#*+2
    
    j2$vv|0lAECJfe`QPV^TV[LHNHIHeBk<;w+=iJebNaYVT\ЕRg
    Dly<*l?>=D
    P
    RX P'8*c4k7Qċ|څ+#D:$B'IN< ͙JW5y@|&1MD@S#18>lɨOOi2JU11	Lk>{cгdBʎts`ؑ]tf@VLESDE+$75p+;mYheXfu5,ⱊˆUQ66jv\F ̗VUB틘vc4lzONE
    Cj]t\$2B&=_ioС=oFDԏbJ*C!0^f4gRDE{}^F>d8"1H1W"%zms	8q򢂈46O]&7C	/]X	؀(fMuhOm'(( ` q]D,N4ЅVZ'wީqJ
    ]NeI
     EЛ%\iP?-*,}z([gͦL`1-,?<ǩPOl=%eq!`|P
    `|ޓ@ٍ/|](Ex͆jfubG$B
    F۞:9Ju88ٽ8A
    pQ+֙)!N_4HiD%YID&8q$v1Ghh؁\ 5ڋ|
    Bҙli;/C 
    
    Pl@zO C2ުc=Oў$uf)=IJ(E[Ԡ&P`!COYdRzU`q$iftjwt*X,8~W_C06mP
    ӳ`7gA?>DzQc
    i2Br
    h	d^0RI% P&?6|\ȏHI3ƍKtАV
    y:DY EƉU
    2q	:**6
    <4b-6??HKʡklz	qZE&#WPU7_%!Ł?ەWX	)*jꭓJnAٓ#	SVE- 5`	5Ue'e
    ؑʭi9(ˡi!
    =	m(jriQ	Z98[g`:"+JЙ-ۦʡN{g*tuK@r92Z
    G+Ί_HWlʌ[Xʦ	)າ)؏m[kg1HZS:ƅjE
    &I+jߪPk)
    ҥBw%?5)$J$
    oiK	r
    	r˴u˹iwEiy}˔S̫"4W'PxUҪ5k겚K۴(;ʙ~Y[!!^0jysTg뇧)y 
    !j`lH"ٖWYV
    #dnl_eb`Zٚ٭Hjj`*ll'f.ΒeK1ڳK-gSg7lFK,'P;	v,ܶbgRePS$ї3yNU*c*n*,tqa)q~6ov't~vXvbJ̌U+Z.x2*+܏XR.x5dfPWwZˉ
    þ.l"bN2.$;Ș_gB;yġ	s
    M]bŕ
    ;'Ћ.]n5{JkqG&>Ǘ:IZ._U
    4Y>D.Ydu
    O?v@<9y!mɗC	@בSA,YqefYsv@)H &8C
    T}.y*Ȉ
    uT/J9\hR0rDOhJ8rX	aB
    %FQ|ʤa)* gm!_Ȩ(1i>HţlrwkHTxJj{Jֶ#WB(k-xS
    .8ª/`g|6ɪ>ed	XRAUMc2
    M\vFԉV@P2TH^=r6,g|-1I=pVp=öDkgMG37$"LLizuԹEu"AQW+v<8(AYt"wZ5|sud&uMSY{^[<Ҧ.ɰ',?22۱ɶC>^)hr)rt
    Kac=cjd;b8>qI
    o+^V]"&_gx㐟 #xz5"wmy?CMp4}"-:˻&
    DFB47)GRq}	
    X@M=b趋pGY3fE+#6%bsRt=#ǐǏd9ăH1Ri@F(2@7?rc8LI|>+r.&cSQ<2"/`ncFsdLPgx|2,{d$M"NQxHbq3g|= ^qsqŏ*b!25:kR'vCZʸre-ed41rɐl$P7;ث^5Un
    _dYOeӈ#^<2bN@jVϴ)`o-lKH9m/p,g
    "7вޑ+
    kœLOr
    _]"N`4&`
    b๱26ȴ5auKy*ʠ6*n4N*r冑|[BU
    dN_J\
    X^B6^MřbQPe=e^Ƣ	A.PI$-beNB_Z;`V>)bRd
    ]XE_U^!:m
    =f
    
    EY$#-|f
    Wa-ȼoY0Q`Ib\
    ƽֽƽ޽ֵƽ罵޵֭オ絭ޭ֥筥ޥޜ絥ޭ֥ޥ罭޵֭ε޽ֵέεֽεƜޭ֥罥޵֭Υεƭ޽ֵέֽ֭ε޵֭εƭƥ޽ֵέ֭֭νΥֽεƭ޽ֵέεƭƭΜֽε޽֥νƵƵέƔֽεޜֽ޵֜νƵέΥƔνޥΜֵέƽ֭ΥƵޭ֥Μ
    _ȥDvlytC.^N "L!!
    :U Lci$
    |xØ^0QlxA`B(x5)1F~$V{B cy1BuxC	40w\⊫}&H:
    j%YhlyA]:LZ{DDaq*a&B5La8M2`"[i%q9eHd,“::H
    Z
    HlEz"РA"bT5yE"]`;A
    
    -a +v@%BL ,ȁxP
    ʠdar0/c9/l!J@<@Zx?d2@gPrpKj.P
    x
    9P+RSļ`p:g3hx%as'4`;`<L2d$P.Sp&LpvKJDjUm~0OaJC)gLPR#J4|M.VK
    A E
    FEd1\\k}R#@rc 0q<6(ذ @_@C`~JnHd"i Pe
    ^4dmB< ӀI9(Lg?#<Q0j;̉ Q$"K
    EQGl Tz4\BUHi'@悗	*X
    F&$aOAcvLU3hh",n8K:7B 
    	18yP*@t9B24]'IHU+h@ZB>5UaYv1
    Fh05`L@
    h
     D
    
    wkH	J
    
    *
    U@ZnS4:
    /T+I	
    P]lmy ~s
    Ƞ1@"`
    hPT01SVJ6D×]w*D	v@|pkU|Y*	Y	f?)
    V,]D@`ba(D0	
    PNJ	(
    
    ]?`
    ;
    ?
    w	A	X@Ϡ]L T^v
    өC{` 
    ^w@
    	04
    e$;4bLLA	MPlP|
    y*
    	U	L B
    P
    
    p0*.
    BF`	i`Mđ?	9`! t94Dѿ=
    W5`eOD~0:@S		-y`bUTNL&p^?a
     a
    
    6.
     NJP
    p
    B*eH
    Yys%Iee0
    Plp:	Q@ː.4r
    @
    r o rZYUsPxpPhLPr|0O
    P
    	'
    AJπEU汻m*0Wv	S."}o  0߫p
    %
    v?09
    yMюP=7^Vp` Ƣf%@if$' 
    b	ab L1P
    =[
    Up 	\.h`hIJ)5	
    u0zWBT0
    V@Fɀԅ@?]py04p]sa%al,\^g
    @	1PU0J}u[`
     Y
    l.3t 
    ]m*PM<8Ol
    0
    u;,
    %9r*c˺ ")=*g?z	TA"U
    4]tʔ-2D4ɡA;r3&440PQDFrqs=lhȕD1)2DG' A)1ܫX0RFȣI”< ‹<iWhB0@Ð<0` 8&.$zy<@4c\"΃DC	(Ot
    	c,TVDd[@,@ @ p$$hȁ
    -	
    P>C7ABSfŘ/U8d%SDA3.A7Myd	GP<Ɂ$atvHPYA΀
    ,bpĂ3ASIƑ;8$‡ fa	LHHXaE
    $
    WrC6pjrG\
    .pE1zDahXIrx_!zw;$]&6B	%`r45;&!E,C/NР
    ?ÑE^Ab``^ɂP
    Gb*eQnP
    6
    JpE P^)^1	Wg/ DP`I .J!bb5Jy@,`:`%,D83$JQ0~	L	ر:
    1S8:]hGHDvBhZec1OB|&TM
    H
    @!PLhCX`l9PQXWpjЅKp3,%
    -XV G\bWH
    #$ӅCQKG;r 8M]P҃`[:kO8.FkE:hAG]p?
    ؁1G6
    
    [KS݉LsW?@D
    B21x.@2okkⲃIE@rQxwʃ2F&"$xA\iUA3\hj
    `lCh-r8:STBhrM%/@A'0;xf`,hj%<
    4=5$&_]ȅ:(G'x
    4yC ÃI@x
    4I9WrIh4
    :HxA`
    l!dDP4x%hIDJby,2Byd1d聆;p#g`Edq$AVdAi@F$hI6wF#hr5ʪn1kkc܁ChxGe&k
    ^qX#@0#&d8#`@!I'N`%-@]+\'l8`4hmр0@ZrE
    p!ȋ"5X(BT/<%E<`lE#`R0!
    v: yt+,D^GD2#](A	 )  ܁
    `
    `@ )<+AfA&x0Ƥ}.x
    pM$A)$#4ArĀ!1ND\֡@D
    tW=)Brl*“-3+aYЌX|
    44MVZg04
    ^\љ#Wưdɢh
    P(xr
    
    D(F`,hA,`2񌔄
    ذj(4`@aRpVT!6 *
     
    kp
    0hف
    4)v2bwp
    |hH/eb%)+t*
    MDj$*P$|	)'&MB+涀@;hžr@152FHCwdCXc(^Қ$@.8tђdt`PB)J+~	@jT7ĭFG4B5z\`@[#1%Ћ<`Bo:
    .@
    4dgp)PDD`^
    \\8U`, $	
    `C^<PKQe@8 `z`vP\dr
    
    C	\O
    -^
    Atz!0h`!pe4d
    X菖I`$,@.
    F!53R@q&-58 J@9ԇTa 3!^!`4`b
    
    p 
    tVt~
    F
    (Pt4`a
    `
    n_~@aU,&!T0c1
    aҀ<$ԫ
    
    f$ȅ  +@F'	`	`jF`.
    
    P ,-p+@71q
    h
    D	&8L ) r\D8Au`
    74ma\΀#f
    0+ W5XrbL@u4A`%S8^ T
    MKhЀ0aan	kdP5@	^`Ԙs
    3v 9! 9lxI>@	:8Fm!	lj
    T 0!dyAh@>!
     tSs&<
    r0A
    @!A
    dv-%zG Q
    
    Bn;&m`< u@:*|JdFЀ@U`hA`]R R8
    M4(Evx I!C9M)rƒ2yA6sȡ.#骕'2JԱs	C6lX_0uy*L0!'ǖC`р"W^̢HQ08ädrr.v<0T.,b;BâIhRyT&݅AUN(1[y|  ":0:HYDY&(h1JΠ+Z4	*0H`^$@"hxI00.(*(gh@E
    Y@T:9JM4A4a))(2)u9ud8J-v J@"4#d^v`Z:h
    4cxq%YT'9D2HaDlA	H&41"L噢
    .x`D-lB420Q$Ud!I*>6Fl|BcRzPBFU2VB
    JR9h ]؈	: +zE#
    p@&z|3qG#|A-341I.Ȑy8~C#Fq$tJ1,"jbZ
    
    z\H*bm$h:qrlR(1xB@ Q7BL9d).vNz!AvD4FГC^1ZL?D`"M$'E.‰-%`
    g
    P`wpV4҂܄$cpukMp|^0'
    |Dђ`%34*0s			͡ct8	?j xH) -	/2kg@LM1Pxp+?AZ Z0h z)~x2]
    UP:^RC`g	H	Q6Cpsi
    ,dw@ZBI(%l`
    WVy2Nclv0	]0*sK
    5_ ^(#CpKC}?0@dnY
    ;^QpV
    PPQit[j{x:	Q{$hʤsj1suPri0	**n^#C|`!1#_r`#`
    blD |D ʼn)Di	sH:pR"*L?yP˸3p-_"2y
    
    |ͳ5`
    $Q	`gpZ[B u	2R^OBF	Q+SZ"Aq}7%LiV(Z	HB|2)ZA;VЯuc-br`\%GLgA
    BRj(s	0;t;6\dPFT<><з#LMVTLg|i]x"8wxsLYp!V(
    f_lG1hHpVp	
    `!Rz;]P!L!
    &
    |\oO|#>6	6VuV#@4V
    γv@	P)@m^
    %>]+.S!z:b 0BHPy_ན7gp.?d0l)"<,v*[-"R&3=rS&iZqj`e !:=*;P
    d&P;_*0yLyx8[10
    
    wWv	JCy#tByp
    }W^h)Ba¨@"
    ;s`yϘ%b
    @92fPe'B| a`xJ¸Y-Ccd\W"+&]OP:c{x&h2Kt$	G*ա_D;3DOC,%Wi1#D3	A@g
    +,\GY$E*eyzKf
    ^F0E
    }AY
    ձ*"UqE>Y#+RP<$'@oI\"#F+`
    4b*e&4z@
    tabʒ(eZHb%7,|g(ߩa)ۼ@`‹lASB%rqG1QI8
    (
    Ja!*
    nb8SY50@^"` fwR+'
    c- ;hʅ+!A+5@?l.+T;('y,
    r.mjD
    ZZsͻw\m@ȓ+_O]Spśk9ܲGgi:ӧPwxW7gj_k=5}٧otI75Y!WgRrw ׄH@b!uQg`
    /p`B3h_%))Mƽ&{7y5[u
    ض
    =HHk9%f5woäۄ$:!-Wb۳Zk.;`⚂%'!1;ň[Eh__mc2#)֭
    UQ;AƗ:08JaW.Z7z  ł|X	f.m{մ񕅜ka[QfHkljKWnr=]i^\ٵ(,uQd*7zl^hNwiyQԦ	j{YyFucPӋGN,fa*iO[&>E
    8T.wu\F\HRDo{b;6nzә1'Ą,W&l{
    Bv
    Ij+̤\_8fSǕ
    ~`.__^Kw9X2>h%fFի=˽O."Eц471O3FOs'7v*}wr""CL1a*Zիe|cĚVیC׼=E*.jR)`i
    A"6nS*#IJ6tY7bw6szdMkn|W7Æ4qCP$
    {v3Is-8X'amP5Kyt'>D]8P-l?Tx/Mv‡d.Mݮ-M`u1Lu _Zzx^|Y0}&UtȖYO5nؓw^d^~^֫ԐӼ|pw<ɳfgJZ|=stOOYs:Z?r?EzprߟKc?Y
    ]GDo0
    |QDvqx{C}ɏ]#فg]&8ˡBk7~.ph}tqQWz8t'qwVi\{%qH=(g(^!8|DF,tcXr#j!7'}#Hho1O&S!H_Hhu~{hjr&rz&wxVg,~x])%ZW>'8T\geqaY}G`aK6Zaֆdxs?Vp4yhAQG4؅ZAWs' 8f]Uc7eMg8h?8whXD|kaj{熙zG{؆Cp8E׃BzeGCC(47.t׳!UHwM-7ӌUBvhSRhVY扫-&xh8ߧIx}Q7M#($os)u;72tw'Xȇ9_s+JՄ7Vh{&+Q-q@)f(2'`|Dѓ&#c胦WTvH	Fw~9NYW> K.RbfI{ -f}cmd@?ຳ
    !!@J#6eH3hGۀa{"N&E
    1+tC!$NF%'Jw-@~ߠj^whAH9% HaE`d[P-c 
    (<
    /vLW=A$McY^/: Ua%U
    pbǖzPM$H!a$Cw}tQ@豪{58A3p"i@^԰u(0jX䳗oBtq"D5È9$&n=+&Pf`ebOC.DFK.F1# +- H\u%w	#B*a2޸mݐ
    "G?Jb
    ФXH#Ǣ+"l
    >$GTz#"*rE&]
    bҭR5t#(CE9"„`Ch
    >L5-EHNDMD;n?z˛h)5&ǰt1.z.r=KUЇ4`-{EIs5`;%U!CLOBi͇wŐճ(e;sLZC >\[Y1r@֒>Ԍ\p8C!)ũ?lRbٹn8N4#LiJ=/Z
    Lu`L
    b~$̟CgysQ[Ua沄
    O~1Н5U+K*{2C>yڀFr["d*Wk#aOQ)A#>@g;>"ZCx
    i;B^&S#=*Ti=J4b=F}l$fz6],@3G%
    ~+&afq0$[!
    w
    g2+BQ!?0$BsY#XXc#ABFR7EU0>dL(
    h-}Qbl
    2cb@CMOtV9P~Q6B OTEG#g8
    B_#"$	pJ5
    !
    GY
    hF00g8iP.ձ~$>EG--C(qܨ@RaaV
    {l	=dTA.ڈ0p: "+V#dcYDd5*	^+*8=tP"b9s7
    )5?s8PIk
    !;@&G!bgEA%2A,QiU\c!,%V5
    sDŇ9[?Dy,;"ZPCw"x
    
    °s	[I"ŢeKv΃6`
    8D=ۈWt[1RC"
    5%r$I*J
     -H#kF8Fbd8:><,""n.ыbOPfpBB鎁+<=1; G@"|jEK65QYzRGxVI-#SSp1YqbXtq3InK
    ERJ߀su4U6fm+GKsBssڒ9/7.l#$f`cfLZ7#?	~qC!aqQ'Z
    \'@fɫͪ8>eeGP0FFSkjbzI I$ї&Yi(.	}Y%RO?2J^d*((]
    r3ë䀌6HSWK1<:70#уp>w7`W%Z9SaAPjs
    *lk_O`%a|13{K0{t#d90,)+b)%@"
    l'Rjbkf-nbiSEAְ衮d;y7@96*K	(5+
    j
    *h3"jB
    QCQp`KסE8_8A9tUQel
    W><J
    O)VX{6TT@vW6R<R<0BuI,Fe8dznp(aZ2PYq^˚#QpzD1D8 3P3GkJZDxBdri8HImhZbrH p*.>}	(gDGy: u#SĀJ:qy)QQjJ5iredgIOn1ܜbh% 	tJ>J𗆰IEp$)D")}d8d&"M$h>V΅b.2%ߺC˨vlͨ$ՏIhd	-Q4b9(*J\&H,8&k5)
    ~?LmmDbri4:tb$0p[
    JYJBH-mfoP@\:&.QĈȖ,u&q-^-Ƽnt=PD+h⪤B0thcvݢGR8O*Dl̉@F)3ψO$msqb
    &p)D+K
    tDr.Ka]n,-f*CZXjd팅šM38lfD
    ,8QŃٮN:nb_
    <&/EFzꁐ&&h
    :j*hNJo]/zOQv[3BD`gV9Q·ypXIPnѢ.ð?m+mrDk
    SS\¼8xi[`6	O&	z,5ߋxq%-;9R>ef L
     ~0r va@8LV3C0#}^<ȭqPx\cBֺۍ_xAn0,C\DGb~
    ֝BӲ:~BD7Jv`t"Y.ikY݆HD tvE5r9"e5yݸj`Ov2
    4eRK*L	IkaM(cCU#aνf
    
    lʱݦMݫ&޵{vѾHEߞu5*何!sc%3k(VAV7i̬mVzڤcnm;ًuCo3Fxo^E;_<7sq.iݿS>u.yя^.~F'^i~~od]B&GTq6`gҕ`	5ׄ
    F!FHQm螇رH[*b[1fݍ8^u9fHِo!edpKb3dmdaTrY"[J`J	eho\Ryfc`$fjٛ*UgNe)axX%&lyWKjp	&iA\ש&iaii}ɵiHobYeq"sI!'qji꫙:\Q+iڪp*+Zk򊣰+탐(,wdݸdR"Z1RjwNnF߾~/Wkٛmݭ\簪™6hS̳o_St<Ž#W_C_pG+yY-|-fΉ.yR׸MvkzV.9&=}~!,9X@H+M_DAډ(b>uq=%pDLD-ꐌS)%Be#3/揍G<>]ľ"ƎY>5Ao3dH?b I1^Q3I5nMtc
    Oks(Q
    4GP9Ќ*B%GSFъ?aJk׺iysM=
    [>i^-IZ4pSד5vLjibh~mhm1i]\6n	M{-.>ve;YM)wwcxlܶv=n"慏\o?˼恎5UCO9cS/x7=u/`w}ZcY^{W|523٥9?7{.u+v< >_]߈g{{kcc28S`g.8O#K1Ro`PyD  ~|eYs&7y{S-0@€`
    YB	6%(%@/y;A'1S~r^1
    W"`W*mi6- vpm8$K-ڳ⍥Q_ ]@rVYx `p!!M
    qdb
    myBKZO_`70R'FiUBx
    ^%FgBX#f>q2&1w
    f.cM3Q?
    B#@
    AÒ逘"y6ÐxF
    -+cE
    >DؑY&Pq~Q0B652xrO@VH
    D@[g
    Fl<HS!Q.)f$+!:@^n(`TO"E&td}OEKZ8&Pg+@*05IFc(ѾeK`Y#e$r,4A.&HIzx4،nU>#P+uqZ28p #ZfCW'"2Qԏnj\6xyOU% pBњ1ơ/9
    	|~!HCνjɌLb	;J2	bX3D{cP0YUkк7)po~IG(<WKNy4߫YTcҪəmrm9\63yT
    @VB+mg#OH]xxQu+#h}xӱM_:*nQG716R
    
    =Bl-Pܗn
    @P>ոGTln>]Чl*$!`qo@ >j7B{xdJ[caށ0Ɏ1Ԏ!jUK<a[!ĥ3$Ԣ
    (Ppqr~Ԛ_|cظFI3-FS]-	B'lo:]79_*Q`M*RdQϵEKEYd#bZbL@?xذ	lx8i3'GݯՅp8`<44.	
    Fm"4Ɨ 8Ű4.l,G(kQRXnR
    jJkjm(0ju	#!CAÈsU)ub#oB7NJMˠa7)	q¨`/sQ)a
    s۱H`Tu%$(ā
    (>~{4WTq5|:e\*2i#SpfkeX),e6L	\KQ85U;	
    4~s-Khb[$bQƑ$wò"x8"'+M:>*Ñs;+#q 
    WXff'&x`LG{>ʲ=pis
    9g"E
    r,Mrcٙe(B	3E5.*=GCɥ]jȆ6A>.q0N1Et.I>
    &8a`;^q[[[@eeEz
    +d+OQ]|"
    O%\
    
    .QӶ`3`>B
    Ѯ0@m[M$z%"Ve5-9c
    Q,('&"FI'&J0ƱJbPoȩnG|-4|:pfPVp&BbZQbD-t5B$
    $H1F8!6&Z)V.	Ɂp
    "B*q03. .~cxOG<'
    !ZBL
    $ykHlFm5a(YdMEIE5L^@?꾧s[a}e)	`g*$E/4
    >!*jBd T<AѣP)) 1YU8BCe*^"[iX%4&QʣkF	"
    ٜV4Kann(A\Hم
    "hU
    iFt2k
    8RV!KFQ53hl	>J"20MM"\bd>e&MK0GdnfKH!܁Y
    aRQQƋ u/x*\$+Qg2/	'HrTsc{
    b$
    9ꀪ8"rȮs
    Xbt#
    iT8?fLUq"	,ngor>N1L>L=K=K&z /a1H`T)
    I(2!H
    `'^T 1Ӽ-FB	'3	
    >mx2,qE`Na
    Fc^@1%8:-\LL7@0tCC
    l`*+ӃT~yu~th;5S*ПBL:
    ՙ
    .0
    $lbDW~
    'G<ACFl79<М2ąH
    hLc[QE<®`Ygr@٠fRN7#$i5,l)9=@h7툸:a&TR ּJZ!\evt(]v&RӉy:{,G0"tA'%r
    C{H5p5fE-;.
    5=0i|0Rg|'t1'P
    U
    P%Ǻu
    1
    ~C0DB0ggppڥpqkǀ0.W\@VK9Hca!;Lz06pQX'*ec0ɔq2t#	_X3&@Z
    10ypoR1)v,|p('ʑV!P
    &?E&?
    #5kHRoU%	
    TW4$gD>yDiHdS=M!@p
    m*'L`Hrzbj.7(@X
    P#@f3n"G%(]*@ǶކS5
    [6	ټ:2n+?	Kb1pqa`C0O	 Пp2◜@VUEqkP a	-; =~@$c7P	CP1k
    cgd
    #H.0J@tD#w
    $WOF3ZEU6Rt5@0r<
    2 E75Ƞ&w&.X=0F"^!oH1Afm
    6$Y=@=404P
    RWqP=P$P7$cd=U
    W'mq!
     fq.Tf(#FqYZ	GAPzj0b}O_)m26c:&0
    )bkDs~Ao-~%
    nsyފ*bĘKE$7r!ވ(XHR/A,Hi#asPX*dJhqCU$ɁЄ>@AbC!f@E
    )?HD:I+^B+	)qа
    RPtqyBA.v"h@1
    d`_7ЈV=PA)BМ*3	=LC"|^a0'B12Azc%HCBZ,&H2OzҼP
    @y
    dX')
    k#L0
    |b
    w!u#	,l	v"k&LPC&%	(h"'	4(4u0A&$60COQ
    f0*DpX̣OC-@2`G`ChC50@	@c '_:X
    hAE+
     A
    npk [18$ i@0pT^e(9f.b \͘ybMg3˙0`Ѐ8$hxI	8`Ml)BFPU摔\I+3K=^H=
    A3O0xd!G_RI|W5O+؀$siM(x!z`rl
    [BF.f耋˘V.4
    SA^T*#TRr+%&r&]$1
    R+PL
    ȭ 1&$hdhέ.`ў7ؼ
    XbcxPœ:ΎҘV`૰0% R]}G(_mY$D{2H|!퉅:PdO%*mE}
    :wJͣ
    6I,逴4Iy? +pt~'	:+	pWj,؞/mxizl(O	,]Cb 3l$k1%!|$zAw0!6?@9H,G~(:$VnQ2@KNdDi,]iqV*-b&QP(XG]! p"0Ԫ+ZL>"Pkٵ:PCir` .
    rQ({a4v((!$Hgx)iOj@7Fc>ѹ0N3@Ob`(@F| ǙgA )`'1X8z>`LP4`WRrqRrx$!5U@_<@
    dOR%	
    R
    P~~K	H	( &1j߈f) ARP A% i4T5=)@|'$m Ai5x 1LWS20;3d!
    1Fd:")\sX6%-iStMB*q1^@33
    MBROm'$ǤC\T4?R@p	0T2F@u`i$6JӔZR)_5="l$*
    V 8/_#-
    }Dh%&]h'L?3
    r
    	+:Q4$.CEÅ52P^<?tp~ "D0eP*:P[94c#*HD%- d1cjDb06,A1.m}B,. %6DwPH;D*mRFr?QaƳ8BwB*o}Ci^b*SF
    /pŔ
    Qz"3++p#v=(6
    &(	B+	5sV(!2"a
    قx:=E	3
    WD%Rq,p`"5[WB>'a3l1D)"#60<@)
    0P0>Ag&"ŷ`DjB9%Иf^	@	,PHӅ
    TZ%>3Nd	0G?)tw
    48yl}4FaEbW;)FoɁEnEc:0@n=Xa9 ?ۺ8 `q
    %)6A2B9)MT
    KvճSK!fָ!Poȑ`,Ipϧ45HA啩+6aĂ<9c	!ڑ0'nPS
    IZ :5D2+Iv@Mu	*
    9`9Nvk!Id)?`@}!7 ,$'6ML!>\{!PI3
    Dz\70z	0	V"K7?
    .X1DV
    @$`'%ӴL9st#2<
    87Ez\wM'}1i
    -0|oą
    $tTzbF .;<#{]@n(rʼn&
    8
    hB
    ,6B
    p 2Qs	86 @	09D	hOAI"Dؐ0YSR;
    uAm
    )qP	$LЂ[04~, @)`0A
    /0xPze)HR@C$	׉-UC
    (B&+`c'!t0Bt	0\
    뀀19xBD i$Z&dv6p3u 	7j#|@~0̉AuB{5.+V8e|ЁY-T#dW9u0%2lܺAP0	6v;v)D%	mF,r#4Ad0B*Xq_4YMWBy5yhA`T QeK(3!fK]W&*L B
    vB$eBe	Ċ&JDa%>1AV
    
    7*ݑM2	>ÙP+v
    7
    EJTЃwx@`ETPz
    >pL,qh
    Z
    TE &Na@m6
    BA8V"
    g^
    .*XtpU)/TS	2Iy`\(Vx7YЂт1M^`*
    d@<ʣV!@P|BCTdA:(PG=,ˆDD ;$	-(P78Z\Hr
    |11O5	GyIbJjPnW1Mr0h$8}.r$(,9JW:m(QaS4Ag \Q:=%xDP&{
    +u	WAbJЀcڥO3H`'@5U"q7
    :Cp4np]HWsT
    Hq+*$cmFt\*P8
    5`>{<ʃA6"SrH@"0
    ?bw
    2VS
    2@%B$";@D
    B2j"@L3: *
    '<)./nZ\=l@|*dc$~"#?
    /:
    `\u
    Q%S qېa#dԲ8`nQҰ`-16,:%@- >N'0q1Dh
    wc!(a#1E	
    젅o&`?7@\AP04 9#3			BE7<H:;
    AP\$?#G:
     A-䏄08kfJ"zt
    # 0+bu͓Qv5P4H% 60F:683
    400e@
    70*0Fr
    	>Dh1	 
     7#TW5F'h
    ezO2Vૣ[=Pa5 !
    KD16@lX	YA>@kc'wSQP$2
    h!F
    ^!$QV<Gv2%79qWۓ
    -osj,`~)+S81&0Q)v,{<!1	f"0?Zs77гQ![&t9`V7'B	dg#76g#:G&Z,w-' 
    ^Qf\ac[!1 6$B+)6`,\(!:>J˃P.b
    p\K(	"d!\1%`(di
    <*1/)qh@ruE\su5`!
    ц^h'18F!P&B9J
    $Kd!
    7@c)p ~[}N20x4 !ȰӅ21`)Et
    2
    5 2%_h'C+(
    wq0*`K )49pxXSIiFvp14.>]
    qu"FY3L"MCj#f&0'1t
    8m+&zDFUy";  r@akYnnvw iBP Bү0T
    4;m]zV~cXS1	!"9@=8W":˨ՙ[#3<(		SF)Cv"q5?@ւXʕH
    :j(+^䈙dp@5!~PQS f@cZ1a-d#yx11@ntjbk58("G"%Xn @@\$)Ѕ[4#ԯjA`dS{vԋc2x˵gqbA ^/d%S	ͼ-,R+59ۍZeG*)iR!'F(7@$8Mz((8~LA|@I=
    ha SKWl0C3?8O8hI5OMBU$t,u,"UPE`1-H>5H
    .X)~XDA/41c&\R@(cH{)X	D#)5oXH
    P(#3j#.OH=nr@j
    QPb@T<2bfXg#ō
    
    N\BEsBK
    E3x\4{	6\9f,P`邥#K`c%XQL=FlG^@0U1qXw
    9@@n
    'p
    2G	*KVMYBXF\ AzE@0	'[)^^"DOHO!	}/|&2N+$L;J
    UbTon*#/~@ JPN"
    gD(8
    UUȰ!E	C\Oxa%
    GMv
    )3ee
    ~
    *D.Px`'0[K-HVp8d]nS~
    Hvv6	@
    + T(N:2k
    (%
    C+c>z)PO, 4#EOp	F8,`p)8R@@pA'b^>+:<WXqiB271"6*08.h9pa?h0h5q/8r0MPK@e|Ai#<a2YR
    
    BX?N"WѵG^mAmN:Gf:N
    !;^qd(T\9B/P81Ç%W@B*WXqÊKT	:bX1!
    /BʼnBr2Ę4pyb˗-T 2f
    )H
    ċ$jㅈ8r
    (9F@\rL@y\c
    t.ax`R`eHxB'\H8l@3"ƈ8
    0"l "S
    02-dCD֜6.
    A
    p'h1fB ;AU4 ̠&Z(󼅆/`PT."0p`:ML$
    *`pzA#lJ'
    +A	P X(5	B:,ab8
    H"4`@hT;",Q~h`tFRUZ.$
    ? 0>%
    "L^+
    
    
    !P|dQIio CmɊJj豉I+C8kl (+
    *D
    
    >	_Z^i"A
    0)##1h
    a1&pAz	юc(d!#6?$z7<$
    2/
    &>
    
    `
    +T<A$e4/N#Ё
    
    {"*@D/>IŁ	($Nai$&y"+#P	P
    -SāGZ3@h
    }	Y(RJQ
    GҐbp1@.,X5Ϋ<"m
    3x6X!-8
    k PIHJ86<؃-`(ـ # 7$tƨm#У-P@#bicPrV*؛)Y~؁
    X'82B358J<J
    -}$0E	܂9ڀ؁-؂_8
    9	O*.('
    GڣQh.9rx/Xh\#ܚHEsDZY*ґ>h'hG7)0,iA
    \ɂ.Р>{
    ؀xH;æ
    >8$.\1GY D8.HPhD-B@eqD00GXFrdXhF\hqlTD40OlQ9
    (/iG@O!Dg!.nX`qC
    y60`zo
    i1
    8
    NpYJ8@sǨf	L8K3
    d'	z@vj$rkń4zP)La0
    2,#?Π6"#–|!KS`Bh/jd	
    8]
    @#
    BL@	WB0(@L$P@hMP|nKAp+
    Ơ=`0
    X,D
    #ăAxwS7	O`
    ~PAN"P*P
    )a6Gh8$ 0,V&,@qnR0
    sqBEhܯP1*SbdpvP¬	;8SM	e㋾!d&,M^XC0!^#b
    Ipnr+yC5N4P?#8`B_T
    dPA t,@W Q 	J!bdW؍T Ὄ^YNC1XHf@0
    @"BD
    %
    
    |
    dRF@ >Ym
    @N0A|Lm	!\C"ZfIHmC N`h&ء)+ hk>"%(bるI_h%xS)
    pC)b	L4	JkB`h!@5
    %$kgP8aC584#j c#&жmS\x! |{A&*lk8Zb03T0a
    m'bȡG7x	GA0:,0Pzl	"n3-
    섁3X@"V3l	XHd3TkV"Lu#H$d~
    PrȠwP
    M!K>0̀
    g
    ;s phʆ&+	;I#
    MXwP4:BX(,̄P`p@3A^Z@ͪ1HFmt1
    r(f2xO3yph1&4!& Wh
     	^ WFHj
    Gb`X`q4%`
    
    +(
    dBƀ#o74Ãzhk
    @ldFB . #0@
    `~k~v 	
    	b΂n"eZ|$-L	"U%BBC	ljfBB-\H
    fO2/i`
    :Xn
    {\ @
    cmg@`^`	FL
    `Po!@`6n 
    Td@
    Þ.O/#, ZGTeРV\ t@E;
    
    w`	 ,YFNYXkln
    k2(zk.Bb&V(
    >rd?g'
    &i029C2tf@
    `
    @+bX@LOE\d` "}@^nQ\c" pvDͤ p	@28qt>|-Q%+2.
    
    xgXmbF(cB Hc".D
    .
    	b,Ex-v4@8NM{^`x@t--C&~7XqZDf zT
    `pxeF&T.f	ln+v
    
    H4y|~HD@hL0%	"3Vav`	@fBlz@c(
    
    ̃^)`N3&K<&%	&Fy|Tvs8xQTd@gE$f`GLr.r:dtwPEv8t ⿎
    42$j
    Rt*^%^FdSbZr-
    bQLÁFFmmznmzUxDm0"w#4"Nw &3J-GBGn^P$%	#Τ$̓Dnes[%Gl@DGFD8`*6Ӡ@6g*¤VFjZ@p
    V	5\2l`I#(f?
    RWlNCbj
     mߒNdMd9Bpݠ.^pF(nNWzn`Pv`C$؁FbH-v3#d-0
    c=+X΢NVT,OP)b%
    
    21Ȩ
    B<@#bpC۠6X @('v*DzWv"$^nF'䁐XbpG<8%vWD$&/F"FB<,0c,jDr`n	4R%MaOc$xac~`6b^$&\/(CNF`Eav4R"
    ]W-D+&b-F9WyD@
    uEQX
    s >B~[Ht
    /(nӳ$gA"	)wW.@	ȯ_
    FEn^˩dsV"Bċ]K^	ey/ћ""75qoھ? 
    f#}R
    W%
    
    ZrÜ؜ŕ$mvZkg.7Zv*S:	1cEG
    jX؍#?&P|bX-ǰ|dU8VKuj$+vVgBƔDfʯUl-n.B:ְ&
    O`ڠ}`P.g؆`za	Hijj${X[b[;rrz`Bl?,˲$"`GxaҨ{;=]7֑AI	ʅKulXKprSPDбʳ9F![zt#ڦpIĶ)FEO$llvkŖZ%˃iճ?׮kuP
    ;U-]Za_}A.L57IW_$+~$:ypORp[E.aluy*
    X[LG_ǿI}jKԎ%}Nb.Įrʑi:Fe@RTԕ,Ώ%,;`SJ!p#0o5
    @u
    0
    JD+k+,n	.n,pnAj[*LLMuOϐ7҂¯CUC{<||yFX
    bE$k.&uRm`r
    vj]Tm@`a)H̀M7Mke@
    X8[s<&&m"Qjcp>Ѻ`=2BH0
    p)5ڂT@`	oc4GvIـc6(,L	,1Z
    M@
    =>'%ºm@ܠ`uB,=Z
    t@C\!"@'X#twQ:{dǿ{#
    
    A]!"|Dn0#
    LxiQ$ESTG!+M_;<ؔIيU\"=Q$]YT'UDi!l&$%;]>
    Xj[
    `*8ŦRJ%Ly^nh
    ,8
    j	ݱs1+ǑEbC"^(6XO8+vt]yx]w-94vcHs[*X	-1
    ?T"5تqUvs$E.MA`1		q$(ޕ2qZ욆
    
    Bƻ
    	/դYҊ~3
    蹆VNeBg:)E4
    Ӗӥ3^aijw
    x0\(u$G,n~9Ys_Mh(	*8#tEw+	)V:}S3+ꩭ(0X=IȫQkT"6Tjh&T	@2+ZFd]jqxG
    =hZ6e>`#lHnuYaf6Z|foaW)
    њ)xiپ)/?iGM#
    6V_WRfHLb6uK\Hߚ$	RjqWNKػa`黀tY"dLD1g_y[|WfٲgbZcaUl5Up&.CNd鬴5[hLʬHfacv{e'~dO0kSx,=ޜe"wlD"IWd$"LRB
    Ȟe8rU{>v[Xtcޑ^m1	1ע$=r3;{vAt.42iqdpQ
    M6$HU4R4j.VAܢhG(cCX0
    l@
    y@B-XPT`a4A:4xalGPj!:&W|6z(z+cBm;ɨw"7FyUjiSiescSusL=)8Z68;P=#tpȊ>pp'h('T
    nukWWgocVAUlWEf8ч3xZ}p&PP*s	$T3 z IhxLiIhNx'FӲZs+D4\.0E\el#)
    
    Uw
    
    vu`+>R'E4RL騊mhcZA9D%B_ys{?Fjᴤ~
    I2ƞ@c)5EfWSop6ghZjzxhکf(9iPA'7XF:~ZJFDXO&zV'0Dɓ/bݥ\݅8汩gl*"x=:clJתDnFjڧGꗱRʞVS7
    ,nzjl#cQ8yKwtbNۜd'j(y@
    V)[V~3дG9wPd
    rN,c
    U&2>V_ZCHd;*۳K[51Ā0;R஭s'(0h;U.LK۩oKçuKt5xQyvdM
    {KڄS
    2@>v%% SNWkjlo;Q_,[yx@1I0@MiLꓟ1I@eJZ+aœ
    ʈ͏y[Ȱk*Ǥz<jC
    =K#p,ZK{L'Z˽<ޗ[ū͹[JʦK'|Q;LcM҅[=={ᛪJBԼj!yjJ*x5!OZBkһëXjSX?~9&әJE.eYO^תG
    W=,.K`}=^̬S
    )>ƚopդn[3lh= mpͪ+m⊤η߮/.⋸$fk.ksjdn<ʳ0uǪqN-˲)p6
    ;[W9ɖFΚ	4;j
    :(,ȵp6ZbɄkN0ɞ>z*N벎߅ڶh]5o.q\m˜LH2u,J./U嚌Z|$u8޴ӃvLHo^)9#!قzO2R5xlO7&n#<&
    
    %!J6aUUQi1iz
    ˵-543lY	VDJFF
    :6>"roogVZOcޡx&ʛؠs*t
    0CM7B
    %
    |rOSqڲ҆Y1T+Z
    ⤓Etбkɦ53pd+\k[e܀{,B˟OWnto&]9i!Qԉ
    ^j	y}!LvK=wXnk
    "(ad7qA$QKO Rc,bi6cu5SڕgXdBd`xnX"KW&ni֤TPRKH68W#~ąWgDSwb5hN!Y",Zٖ5=@D1案j"fYD[ВZZ֖`	gj(B&z*W!,rH(ŨF4[mQFDbKmǙ*&TB/EQm[u	(̜?-2!H>4|1.~3̪V_Y+`ʲV{t<}U%]ӤDg\
    FxblATN-P(i-Վ
    8AAB̄cm`A2ag5%	Uv
    [xA΀=/aX02>o[[
    p*;Jn+"It+b>dBӷqNav*pyu!^9rH.wiuAy6jT~E)O@WEW
    -Uh.|hG{X8rahw8v/4"O(ow#QX\C[ydSw2f!^/BX0YfQDh&焊y`
    4W
    G" Xi5-H.wwPW'	e؆P#o1mXk%~X$QyEܑ'mAl(;H9"U#ԕN!+e#ZP]N9	Py\66VY]ڕrHxbtt9HqgIF=#Gu05tGxwZ&$zV5DVQkԍ	oT0gUCJ9r$U,?ybywF)GV.b)y+V
    -pȩty2SWG0	=|YIc	KH4Y??%թ9zzwṌ	9k)mRqsI0t$I'9Ts߀R&1aVʕqnENh|WVf
    gycZJ'*ꎮ*g㧧 cr3H:eJާ"E/ڬjk:[ZšZzʭӺ=cjnb
    VۊvY;eyx㺍
    :l;!Ү[
    2ڰ
    s!Z$JBzc&!"[f!kh_4ˉ-֯!3VѲ*6/kh:+ݺr
    Z(x{Xtvfy
    n["[4cI}yDI@Mn|[k8yH:pˏ"չӴs
    V;lĆ5'%qF|Ky?\߹ț{.S=XG)
    򋡏
    5JC)x"tnqMj~2I
    ̽fjٚeYXB|{EQ|2ևŋ뽟i :8b[){d@`TÝc`v	k)y*[0ܘ<&5!\oڡ*'\;e<+9QcOiT~Z"VHsufeOusj	tWqB G6S;`0RƸGnȝ,`Ǫ@&JQU|5fXo:[ɹsɩ%L/CwJ;Ú49
    ռ4@4J̣1ìQk̝H0̮ܺ@Ntb O[Ι{΋	4i?ܾl{
    :T зo;0+ٌ͒Gp9z;
    h~ooƺ[6~sa&Mnea<3&VXSw3&$cD?+Q{	{hl,
    [oܡ&ziϭ='-0W?.TQsҟvUd
    PF ?RH*#|ˁ4$
    Atg_Y&У\0sښ$*[8mpy?PV!rQ<=IAEvaHM[;EY4┕q	<$f'HBæ4`u>u}"N53"lXY='NErUx`j(Rg.4pvF'&
    HƳ>N@m뷨#*i->89)fr:owZ
    #
    h?3PNgi;IQ RTS6=hb4x$HBxPC3wr1?Tj8T,﹔0jtLCӈ͓F;TƧ9ڊ~| FWUUcj)KUQT!Biq6=IVU{DҳU3iE[3|elcj{I-dVgj
    5lfK$džVb,,#MImZKPK9Z涯̢|[Wnk?&WerZJ24Dt{Жnw{zW%/90*&2xkF@m-_WM}p4o
    #ifPK3\L& abE|b
    ',S_Om/FrJq:M)Ah 9<ـ>zL=;:ϛEpXK Nt:x*cr_gD6QqttbLDB">D2Ă%FHGa㏼P&\y+ꄏ=tAfy(*/xZ>~~!?euI\ſSԓ|Uξ'`&"sB;QzZ4d<o™Jr?S<һA;쳿k*:#Sr
    z,GQ@c@"?g8A3y*;8;ۆ0`Ap:|:S4D6 <8!Bf{@9)<t.iAI9$%&BC(YB"B,D89(qC]+y;;,"K1Bɝ;8,D(8BKKBt:D=dBCYXˎKħDM
    2:rDA>x/?$>U|B5,Nu9DALoDÉP4;Y^lZ:[5@c7"+
    ^8f`0d' 	7`kAD`-T13Â #jX9)mdu 	JXQ9@v%LBYC!<5v:y ڀͥmTC8*T `#Ip!v	5ɉB&0aJQ&{IRB%`AfP8К@(B{(\LdC`/
    C+W39)6+hK53
    `l@P>2
    h5@8[rf0Dx%.Bl9l@z%ȠB.䧗sK
    yR砂P8zYS/N	K-/X h..Ae
    6b}r&yc 2aբE]HʛL eoA;h
    {ifpeeoyKso8;)VW4
    "C>+(
    N]XقyBpdFB;!x3b6ɀ,AyDnK R@F&a_怈zAH(*
    c=DG!D
    F^QPbfiG`Q0X
    *ADe32yT4\PP\)Nm?0Dd@9 @~9*sbW
    BwH;O0[U˲ٿD@XpPX@'y
    0
    $6.:4A#;gR"?s5NkUhd3HlpR ^0'cpCI
    /AXi%IXb zP$@
    A}‹9uԒ11&lPB
    xl 
    
    ٕYy'M:6k	 Cg>74"A؄Ml4>|jbfR¬p"M<Æ23#!8
    &a*dƃ
    4cS:TlXm"&bXe	eX$-(x*]L8 }^UIdBex)!വD5	>
    *	9XQ6M.;kD,9$%psLC-Ğ'Xl/	%8{D(L;64^4;5	pD. $&Hh.p)0H(1'[GWqMa0$LS	&e"rX
    æB		G8?v&"`T%R>44D@1/-_aLg.5ƒcl_GB/j!`Dd06-GjHOK1TXFd
    :%bp3Dn
    ]H fح-E;h(>~
    BihD!@`9c)kۗHyYL@Tbl6C
    ZLjUsdX$
    Hy
    p[#h-*pkbD|_`(
    v
    <
    f 4Jyaihp`d"
    8!
    B@0 JgAg{1'+$`M!y$ac
    E3b9t簞‚T=5jHXa`1@#!76g=i8qPt
    2L+,`
    >8/ZU@?'+x
    T ;!`o
    ˰4I2Tx.BW5
    0(x%`Tj}Aq7	&*!(
    XM3!44<3SZAfe
    a.3ETR1ITON6pG
    2ҭCwJea%Hh	z\[?;Pq{>x5@Ib	a	
    HM5XWQ
    E@
    `YP)j<,$ߑF*	k19V(Hq6	i)t/GX6PP>ܢ=*
    H'D1y@(yE2,
    kZ!!E7m0KwۘTHC]6XEs$Z]7P4?pRh/:@:p
    8U7
     `o
    1!Ćˢ)2Log^{IA;N֟eSf"#cԀӕ2RB	còCH9 
    Snc2s#S@h#bbcCR#e"deC`l0±1GXX
    *;!dF1XBG.LIH/쬁
    ȊH"@#	a,*\
    .V qoX)̘b-L8o/ABm.xT$2y.&K2_f7U,2e8PQHX<SH;fDk93v+r_ W4`
    [&sj`~q
    .fL1V
    qR`PC*T
    	Ԅ=լTkT!k$?ذa[>	l%`RuTLX핐	O@L	3AJでW[ka@00CQ?RS
    pf8&*f#D*QR1`F.;D!
    rDn MC@ZM2C	B9NZ=–,drAʬH
    5}$ 
    `
    `3=_2qOqO9+ӎ!Uj
    )CM'(>kXp.2T]e¤^LTPa	XJ1Ee
    	@
    bL0 @$ш,xnQJ$Ie+C	~
    Mnzo`q	/p^-JW3\T{Մ$f"0Y7@T<V[x
    6!\Ch*A
    :
    18x6,|L>@R!%R@[)x7އ^8P{БPV-
    1JY
    11^Jd
     `
    %LAN8Acfp	$g/
    7߈/#z=>0EeP
    C&V2	8
    *B@$Q/᠎H +2t_O<*XS1(T_+1aMI`'As!
    %0.[R <^2-=4
    $Fp_Hr5gDb%&!{'eAܡBhw@jo8d`Ќ5NB'7!'P;D@&V@5z!u}y/J# !10Xlq?0&CV(
    /7,(@b`0f@eP
    *PY>C
    "Q6`e, 
     
    *44l1W`
    Փ?p|<`
    $%fҜJsf~upT}'e\SK
    SA78m
    
    Pb!Pw7,x
    0
    <[2nU,݈E
    t$.&s/1,t,@"\D9XBT 
    z#乓=/%K!Eh
    (1Jl$1E#&HO%dB:A&@
    du8A!#H
    $%)$/u
    i|BDia&iZĹȲf
    |.
    P P`93"H
    <_0
    U<#E(]dNJb.\&@{X]@nR)Pt@WU~9@)WAbp+:ܢ.XΑ;I!X
    A_@BAp
    [ ܀@ăX!"EnBWj݈8LCN	,X"&+0VHK܈A	> ob4B8r )LpCH8@' A@u_J<x Fqoͭ%*U, 	<@y"Q\
    |eɴpSL!7	
    /B
    ?/ @(
    5~	7 V-C&WEc49Ef
    r2gL?r|2a 
    7'xD-CF	
    #M$>%;YVE]
    M
    I
    jcymU>2it<.Yb}PД2:6oǴA]ϑP ob!'.
    }@@CmP&Dg0nҶ
    %8`-utfX64
    c;3c#Cj3sC,Ã+6#c;0EmcP
    p48 b2"?fA4H83.JHVD1`
    f6Bfj͢W($J6>"
    B(`B,4P̓0L+㸒J;EfKؠ4,$46erT7	õo?,
    c
    3[#
    (<|FS20Z.zc@8e(%₅R@&8	95+4f7185k.AʂV
    qf%Ӑ
    $Y$ːXfZ͑"BQDINBY"L[$N
    @:e7@_zv	P+0 $!(Wp T0Pek
    
    VX8@]+OcKL$543"IR6
    ,8
    |9"
    #%H
    #%&~
    |`F
    mP
    Upc
    	Ҩf(E:UYP\jdxޔ2g~Up \@'>u!A!$ BDQ0npǚ[}ր
    \`E@G,
    
    !x!1L(V!"hźg.xuqU@Q(0ba)B=Ơ2DA0TI7l9NX]ÂPQ%ЅC;Lpa x@uV%
    Xצ(C`-ap!~IFT߁
    ^9
    @v#'x$G2ҠXn܇XׯF9
    wNW?ɩw)ʗD&d#
    7`a+?1W
    G3̙:d3,vCcڔ[6C;@hDoN/-	MAVQBPAmg ʌ.s1@'0ތ0TCJ
    )|):#8&%+q,r)Oh
    QhNekR@%r!6V!o?!B&XM&H%FS6&pPg0g~$Yގ~rl0}K	TV
    '9/Vrgd|J!~%>@daP
    }n.!P.3D#イΖ=wMj!+c[,丶!k	A2EQ
    K҇Qy.VZ&n
    e0WRu3{aVqVtG
    ݥ}`%CFPPXȗE':f r4SoTp.|`<\Kj߀
    @_~b	ڐ>S
    آ`>yj7{vsi_
    T"EӘDu
    hG+3FB pi P\`׈Z1`cg0
    #OiqhapHi4K(	G>~Nζs qh6(2jXǷ@nlwSL
    SMfiH4dǫ覷RC9J35;e)3
    *34[
    9pƈB!:s‰f&aVlTn=@Phj3Q*@k !Kxd?D
    ޢIpB['̘)2ػJJKγAsW#!
    !
    Hӑ
    -r1AEpӆ!!&g6P"1
    PO`"'Z\Q.C@#spMR+
    
    sH )j0/1]OHi:OS)E-95gD2!P[w\
    Ax!L>4/#FCG
    uRv_
    G1	Dj9`%1X`T
    s
    #ZCuFb_Ypq[wLahvwA%A*F8qF/jqu 
    +2XrFlұ(7&Z0W FImLE-2/1#a4s,O/a-Qb:R:GQZi:uLI
    	ua@`<&n
    UprKR?xBIê$&&do0)<@c)b^ab8JJ
    4$K'4EL fpA	)
     BJ;/gLayʭ\42NHb8)
    cƳ :J.Oa
    2
    $;䔶U"'LSP(hlỏ+A5wIB(X?bO0[]M
    (DFҬvDQA5
    B~Q)fiPT89AeE_N; =/2hs@HG*[
    %N'Ư騌$yH
    P T
     	B1Q+!Ln&%MPKB"6^9RL]D5bP";cQl!D৓R
    
    Q!#gx𹦘ULZ-U"؝ev>C>n/4Q~$<
    ԈQ3%[6՗2!NusԉjW(j1/-(u#_$p`Nv+4{ajI'H2@QlbP(|	a`GՕL1oE@!;**93@!$y)G9i=tYZSѠ_dFP&Q
    I
    	cJ쐯,0e+4#^ٰ
    <(C3yaR2
    nOd,4"~'̈/~Zf
    $AT-G	-ߢv0"*M-Ydd,
    
    *
    6 KYҏ
    {@`~hs?z8H
    lC@Ld"ALIN 1! 02Q?, $ha@@n &"VH iiڣp(2
    csf	iI!ȯJ+
    aZAvR4$6'F!@ugC(8:A
    .@$\J%CAAnyBOE;*e+O↾uJ>epQ
    s&(0">6%b0f?4,b-7*_pF~`0hk"t85A!0bw@Z
    a6OpD-@8bK[wCt
    >]T/WSrKl
    
    J`m?ai'߄a)}3ج+~.xxB# VPkJ%
    VKHp!U8'>
    ݠ1F ԵRtҲN
    5
    bU@
    CU=@-Nf%>Q%/
    0Ui]~]:eڈD" hʨaIXP&'n:e5#5s-
    2DAsV8]v:Q|.f$KEa%n†/`R&:
    BKU"5
    3wH_b^fNEH[
    3!$>fV/VLڴ6$ȏ% B8btQ	݀fcRn*
    ]cpϷf
    0+<&##/"o[CH,cbk\blQJ۳Sd #1Zl
    kdd&͛25E'"WhY7\X$zNJD0!/NlZPFP}L)0^
    j1
    `Ì&$~i#y2jhF2sAћSlqaj%!?>$G"6vN9N`ী4Y`iqe8?%.vQs݁%;eomDRL:.&82/7INsI}vju6
    Haf"+FEPI$%04+D+v_i@iaɅ!@uyum1E=5<,-f9UU<XV]21`!i1!!-<IT
    Fː!UrqchmQ15UG-=`Ե))0Q4bwP'`pS8HSGanY
    ŵ 7 
    
    o-Eպ(R"/PT*K動%Ul#G,=zz=j]hz
    *ԭ]*Zt֯H)yǒeʪbH)S EkY.\.V/0s3(sJ2̵օR.&#<52#xa1-z-}ՍBJ/6$\%8/
    JqŻ-c#\/E]4#GpETh\*QbDHA
    $"ᱰh-ud!!I.3"F
    D$D`_`"lj.aPAqCfXt)r/=O]/~ITl(L_\0*G$4gDNdQk1{aʐ3!.
    w(`pd)`zvCPxf0 
    Щ)!w
    ?D1;eJQ0|Q]C\C +0ޫMjP{ߕ0Ct]84-$;tac˂p_cX 2aoe#
    P69PEde202X#Sد)
    QȏYYWW׿XzidPCP/^("@$^O;XGVA=H"VgdHEXV{p^??A@h#VY4{a]&~<sENKd&e 
    4t0>qG-
    @J
    
    R	7RV'v
    
     B~ 		touY
    A"-d	f3eOF؁	2(̐
    b		1+{
    r'0JD`jS *d"~!-ς% 
    H0=
    T‡Q
    
    P	V	A	xP
    Hmڠ
    d
    
    @1* kp:8Lp0huD>Ft
    Z
    g fME
    x&eDPp	b=z"`
    px ̀
    PjGb3B~V8@VX6ZQ%R`T!(-J@X{	 &= |
    I	X
    ldVˀfP~:P]C&V۵Sc
    	
    
    NA
    
    P@F^ar
    
    @,p
    
     
    PSSTp1a
    [6!0AcyVE&*'MlUo
    @J\0
    EQE`
    (	<է饬ڐ
    
    xYUIH)QȀ
     2MH(j4#
    
    ~50-ǔЇ:rLcy~%dU!=;RHW,R2ok&ܨ
    8T
    +Z
    l	:
    
    _0	/'Db0	
    2 1pB+&C		B6	 
    	Q;2i[8B 1=`gHx!,I$AV	e`P4p<
    O6
    &	
    5Qo|
    Uk`Z5
    ,Xhx
    p
     2\(;]ayh	Ⱥı
    xB
    R
    
    ?pa?uʠ
    X́NG3k	=P
    t/s;	{[rF
    
    Qᴟ`ҪT 8
    |	$=)<[WE¾0F{'YkT(
    0Լ@
    of
    ptьY_~ܗ1g
    T6PqHo
    7t|w
    =ʠ	1
    @	{bfY
    }h
    o c
    .ZZMJ[cy-ʗ`pXhmhE
    
    (
    0*n	
    `	pt;}ѭ@NЩy
    QD0
    b>
    `c1ٰ
    8!	[b4A^mvР軲P1Ϡp)X8⺟/o{w
    
    `9	0	~@	!hId}7
    t0P!@	
    5J.ѝ,~=[`
    (R3m.`Mcχb05뵞P
    +
    V8Ves`Ă^{B`"Ԝ`DP	DU Za?G- z
    ׭fJ/*=-/|ڵKWϛ{T_P
    *?V0PxW[zJ%i="IRhpU^VjW\B:eJTMtAʧ\OٙIUI)_V)N$Zq!GS(`p94VTڀx-]̅WBk
    >Rfӧ_NB"ATbUݻyEr8㠱ē1SR$"|!3@3E,*
    I"%\*2C@1]rqZTFrѸ[r*2T&Q|SD
    %\䬐 nRT0rUw#f$qp$S	
    ]OPQX#Q]	Ko\)R^1MO#< @"Ib؃ph#RV/>`W<*H#A[8/BQ)y{H
    +0&qBD+Mʃ/3d^؉OTPd؅`RH[PClSx0EQ>
    SPN؄p+e`XG0
    PH@TH\p
    GTЃG@hkCd
    i==EVSG`]jL^[bdHV kUkHBkIDHN0f4d^^4݅X)EȆ700އ
    ͦJ>yJCۦIЃFhPj/Qhv2SXP@Obi
    2Qp(B+.0+5
    hړt=B =Ѓ'
    
    /]@Bժ RaIR=dIDRֶ*Z%/]:ryj%|,Q%K~LzJY.^%ĕ-;PIXHT$-	ɔHz%I*+)GBuKUflSlW:T]>%
    Ujש
    -"׮RD-S*REiÉC/\Z|bN0JXP/>b˷/^esc꪿|ji;"A*$IL	n)F╋gpy굋)qa0(!r
    BJCGI%
    {iZGm4
    /Ė
    m-Ƌ-
    *"8*L)"2xP/2)U2$NRIDS
    *'rK$,P@praaOAz	/P`-2ؘ$`&I*JZRVz{i%gKt2J#8+0L3	.`(
    (	)
    ]T%2}PS8Bz0(hU|
    **v=q
    p*
    p\$
    h,ml
    3
    KJTH83أ0M.H)@$BI	qdBE.FC0E(FÇ(N+A0e!PFN_F^
    T7bc0$0ePB3Ѐ^<ȚFv
    >)LCXuvRrD#DAme#Phc((„Jebh%+,(K"(@>xT[EAA.!0(TBpלV,:ZRa[0%ZJH<jй<l<?41
    QE|_&f%2a$CE(@rQR$!?IyT٨O~b	`3iI%CJ/0Lt
    h
    g()l6\T=(sPI"-(
    Uf"lgO(10"kR仐0>Pa
    lVC$Rx`-p.r=T"8ZYh@*dQTF1ۉ	)ld"ِ."+_BiQx=^'[I	8QX{Ft@\E)2_B!"P
    H)BH?schf3g셲kGp{6x!Dt)H
    Q0.lqZ6M$hLZv&!vQ+0;g-!HH|Zy^*xl)xqd7-8ZPHb}+D`-Bib--4/v!٨*_y8jN"4Ce1&~]VbϺ3%D$	ڐ>Lo6#
    Hv~p/p
    *0B)H?IW2(3`+
    uz$aI)Mi\T00M%P_='
    i@M/`.$6A
    65@0$6y)d$LF`H$/ $&EE(LMHä†p
    gB"
    @T#
    106B 
    
    f8$)l)002A/AADXH%M*4y/"d.'$IVyG!6(TIp`l#Ē:e 9{e|B( -I 
    RCY䘘՝!ɯG%Df!C"(ZbB$,YDBt*M0C(_"EĀ	VђI[xЃ%ȥE^hBqZ@hF2܊Z*	/!xZ3X塂Mt1\ ~pۣ?H-qtUQBwo0Z*>PQ	PE3_'ROI ĻPAw
    NPlnTt])Tۥ2x
    hqS"/&u@㰹9dDJѭCNI%$Z#X!p!~hA)Lv!jBǤG
    pHal8D&`(
    B8*榊A@AqX'
    %BdJRH,PA\8ʎ4jnM>	@nVdLa
    JH^faB!._İ:6!Vflad.%bBra
    k!2PQTl013fm:菒lخ1
    c%eN
    KjP(A8:VrasqvAB~.Mmn320V~rl!6)WO,vISY-!PrRqF?!XGH,
    `l1>A.P
    .PEp3q	 s*fWDSVTݯ!naaPV!~>ZaV s
    2
    d-KJ!J*Q4|dA")}pWK"K~5
    .X04/'/o%.0M^S5LMbJ)xE$xHG$"R%z3Ήb'4&ڕK/&V_*i
    .K-8)!I~"ʔW)L*20-d)
    $c.,czI(u3k˅3d.r.pL6b	 R,5%F*+Y"%횡`t($RR%`)-41#$8R#DY-L2J)K*
    }1f)Š[)lPKdL2\_r`~54Ê%I~Fb
    %"$y!	"	ZHe,J'bqy{a9Js8b\s͈RJ)H#ԢKru
    SD`(B[`b^FxPeД79OtQI" 
    [b&+1hظ2g=XD
    KRPD$&}GFg`OJIj#>2fӐ&R9L*`
    3d#SXf3$@MQpE;u6B#	d=# 'Qi5O0U_VR)
    -xlp$Y<0VHAP[
    \W&3(p"ΌdZXA
    6p*dbc*PLD/Vq(`M
    -*@pp!
    F)`ʌpk#@6ФDJ:ra$
    !6H
    Ixa)[ZmİNڸ&#qu#lo@
    @!]X !@!oqk, &c P$Lly<Lb09n:ҝA<>2Rr]A+?qÙ`Џ5!"@TĠɲMj$@~#jbzCJe%`l
    (5{(	T;`. u!
    .[gO =D
    A63?L9DfĘIǣz8`vY@[q`Y-ȉΨV=ۮ_oA
    Jؚm
     J}
    mDM,XiBAxg?'`Xt90jtļ1	!!
    rfj6g	kڼE$,pNFa?3GřKP4TFJ>xŒhDb	ue2Axt	Q 6aG%K1'n#?FC=(Tk.1tH`(i'rjo&Qe`8P
    
    w0ĔCćcFTMBG[c"'>/_0<`W&.GFjh
    q$dô2A
    PaCgJ
    ?be:"cQD-6DR#u0t{
    slbϐ1n*Mtc>G=(Ia!+Dz42JMӒHW
    Z#Dw	#r,Wnv x=pnAfC]&-Wejz?uD}	2	b3g0
    8<9
    +ŔFv!'
    Vz$
    Pfb3dХ]T
    gU@n":4PgF08'(JPs`ް; @EN73$OƐPsmGVA,9aU3b
    s!j-`R6Q%4v'~.JO1038e{ӵ",x
    v+Qeb,ŚL#@d:O3(@0=F= "):oV17.x4#)[a0n:xA"VU2$,yLFU2M3Ɨa'Z3mnW
    =,vkZ`M5dGq:4	
    90.`mI#p!1Wzs
    57
    ;0ԢQ bH‡aH||9!g$:FC#C ԱaJ  I ET〇(npKP5bp$EPh11bQEd#q4~"w ,X l:VTKR6` 20 L*^ vS b\ACCUAPGGXBCTsWl}BH; DrG*c8y1?XuIM dn @fEa'IbV  lM1\Q=e( kY8`: c=4~4QD|Aq@c! iCi뱅7 ZՂmkV f2j su0xuϒ ^%, ԽE\G`V؆,Jg1L ygiMDăg$<\\ 2IKj')Z0-_*]abTiCP dV!T _(u\<)T XE|d\ mKD0TN a MlՉl !#SUڝoţyJTZ91 LѸ&Of`=X^4KJCe/Q4)^2⯧P^-rq$↉mZpжX*wMV@|.@\Vh5t ;\H~0I"a*J 8ɔOp>rxմmZ 9zsnm_LmpLټ l0 włJj^0m\MGCEVVcDDX*_{3Ӓ![e|CWm(D$r(.vp܈K*"Km_vDqq¢6 8c4vՈ𨙩)0JĶ, G4c/aR" J*lDP CͅvsM PKhq~MU/QΘ [+Fxpu |`pB($ω "u Bxh؜Za@DHO b %1,Z[80Z%yG^ &)`-$t 4B *P.} 5|Ne( sf%l0 )w C" :F$| /BTP@_$O[b?ifs 1`9'P}Q7 / >@ODb&m89V ' d\VH = NZ@\V-PӁ0Ж+G*O٬Ss@Hh$0_/}V j9AlAD,^ Qp_6!+`!4` )$`0"gԐ@X re |P@m Ϋ>qʾANAh ` Sp6@ĺ)HtbVTA$bft);Ӗ)bC!|JF™6@0 .w}x]1 l "D#4t"`zXi;T mb [vc1A% fDҁ{7 p{[I(ѐ <8 D3 +q @6 pZ=mAgq!`v/AV UiC4B"" V ?K."=S@FIn PA4%.J#K(YG?J(@?`:%Q&)@.|m"' 3s&r3 F0h  A p .u!g&) 4T9&yc\ ~aws  `"b[[܆ \~a&o*`0E Xvts>=@TFaF $e#Ÿ+8T k'1ߡ |80 Cp#p@9N]aNf1Rg=c5O" 4 9(gs es #;_:`=(  Am" e<@C)ڕ) Vp!a\GaDq?mm;* JB r ĕ& "\fxP ?-`('?m,w >!a,PƈA BO<kEQ{ Q`% .8 '+p8-?l@}`&CRl^C2E@`z AaQ&d[@< *rf"9 "!b4#/hf=w/` Z4X-p\8A'"@cm0E1(ޤ @\ P\7< }2<3 - idG 3J%jP|곺{w 9 xo#0N@h:t|(^;Ѯ&a8("$(-*!"+((.11''37*693"76( !"*030*%39, ҂UhƐ T hxl?.E0~dZGUGR"܂ \3|.άp6'.!D" R M &`w2#V5no_<;5R p e &@:v 䦋`odzLԄR Du8n}˸T~QNpy1PA\9P QHP9[b T P"`QD,c!)`竏rl1b'<. $P#lZ\2B dH3רY)r11P=I `*BY@1@A b d! r$D|` ` `dnDUt '^` =dd@uZƬϱ@:p <B9I{P@iAt6;@ aT -@o'0`a$ =uVY*pF( C0SrT5OR^EE9Jd B8#y" !O6. V&Feco *s>- @`QB^Q $|7&e+kC5 #M0b86#-`F2o._̀,}( tfd4V)Q]6  ` a?2^r q>Q5}$bS=09Cd, 5ZS<$!1X.J ) 3E> -s>Z ut,`j1v q9iPC }Ie>C7 9p %}+'{}9 b# peD0Yo1sNp ,n:aC FuǤuh !*Be'g0l$"1Nh_jH7#-# ,X}QV >`A°aDhC f40@ $%ʤ }FW4f s1 kt gCa⃫0K: `T$I4aaJ?0,YnB:-/ ?Vs8D`o1:W%%Mc _E9Iĕ a)3#10!+Cx͠g5dxcrCCQG#7:/%P/Qхrh  tkE 0!5%bg`ab)) uzֺޑmhYtA)J D8o!rD?a6RS=94Q4 q&@~@AP;AOy6'YC 8@$ %pl6Q)5KI#@% )t/P9%"݆- 'Xnv85 B&2L<2%.:R!093`:_X + 7X$'0,A+e'(Z) 3BZW 7 #btV\;mC!D#03SHȔ& 4j+ l ?L9ײ&b r>AOq0TR )gc1' X#PW:V!""Ơ-+0bn HH%p!$Ik7 psqj)7HC p~BG#%ttĢ '32pk<4  V2/Cr3-@Qн`;j; C$ҳ 5\;IZ4$. `Ԁ+" ްb?ct$,R/p-:=+I"gp)P'shR@@Q&0)FtY)2&B%Vgu uk5 *`Av4"T!}һ\rO#1"g('s[g)Қ9RI$P:@x $(,.0.'$%*+--*'"%+13+#!!%'*.-+%%%""(0430*31$#-.+*(+.%"3==3$&(0640&"!(6<˓'+(""*00,-/*=6( (+!,  F4Ԫl Ph$ 2h7I'TU*"7lhQ'6`!CG4jC =@+`XP7xXq@8"w$@0AhβӨ3r3E}'`pєbV$B'%j7fh6ք0z A&@D .EaщM 8o EZ-}!&H9TY4ch8o.Å/6aRWTĘiE vb I-}`X$PxIBxtC( -0 704!s:FRHO*cu 23F8B9iUatner$3*hm(O ;ApLde##UkGrDm1yN4Q)B!Z/p3AS}!,2`|Lb h<xbUa#z" ;-RД<3s K= Nݔ"3D748he!Vi("PAOI}dLA9R}N Hp !VO"A֥G# v`GD,pdQ3,JwH pbhpր)r&0R!ucG,).o6#&K\c (@ k V;"گ$H30@ NHGRcǏĘARI Bl>CQ!6CuTE'U w"1htxdjiC Wuw`= &/pBLRxe1F")67A"&  hy<߲ y6xG,X0 N:d(i"/2&ءz rdbL':myc #2wu:`/XQy@lVF# +!]C]05[!A w:30$#[e 'KC98" "T$kyaLV9) i7iE6+5@OpXul0!(b F;O@yѶPӱ'ۀ+r  sϝŃh-IB !h!E1U1Q&3;ئ䄑O*߹32lKх..8s8KT[Jv?q 0G2XZs{۔0ra<1[Q`otdGtd/`G&&NNV?`c"DQw8luؘcv  8ގռt䏲0u$cݣ5>O}|11R *7 ϱ)+nU&{:IiLpRznQ7 8Ҭ~vXa sғ\H`YHdj-6`=CN k8!BpepR['֒R|5p |8rxt nR $vD5N'x8f Wyy\CRY>VBtRp!ubImn|mE) 1!I˩DŽjDITHp' $ %\%Y:k빓H (D. H8H͛1IC#-M ׹EHntT4thSD߁CBƝSY QՁ FB\SɈ@QSFJMe EDd$S\3Br]ƃ8F͡LUwbΧ6Ł+ ##eYIKM hՃA ab) 6iCe&Q=GNfT &a(1dq/HH#gXQ"͉y1 ( 4C4R-aB`L/DRm4"<0mOjvMsD!d:q~챊T\hIHd&#`@hȡUA  Z䚉khBpxQ7^='AB!ABX D}W۠ >jS ¯6`,P_,Xŭ.greXb58f;6#"%W7+ H (e ȵD%Ճ$Z*#` D`xڷ.(&$.W)A1UP_~:{K~Q%cZh !463dS_I$B<E1]p"h[pA7 VTN2U)D:_0Ȫ&!85NŌ;6ٻ!6$Tٻ/liu]1AA} 5E9֜ Cb$ ,\B;g|rܗM~Q`,N[X ²|1))h]!D "ak0G6O"PeZODwĮ!DT@ Ae4ᜃ堉D7Q}o,Y"!ܫ]lD@LHA$TU,zD雤N*T 4DU B ;cT׿ em|^u[:`,Q ݈KBޅ E#}l‰Mha\uc1H`\(i€"8GA$D$kuĔ_ySv5H IɽR%JF,ul$U\\Ÿ}U ʉӲTjr1ODW~hT@8Iހ^ơX0Q"H% PيF]~[SU:ߞ8QV TVAhbJb)R dr,$.dF3XJ˨` D8'P IAFH˨ DA|8GpgH:b)ME-:YPǠ@ua!6WY@u#5F P@J'xd? Tq]j S@=O;ǂ yZ$p `m\@ٌ @ sؒNYXG5 )MW$]Q~ЃŃF"i EG0M/UhdOП8 >L _F9Z٥Ld3V& ȅB' ŵ4ޫ xTݖWzGT" HsJXa6 ͹P[HMP2C)>a#& 7j, |$̡<{f.u }R4 $c όB'8CTSgw݄ ~ Y'{J$hL_򓘰"}(lX6\hC(/݊OS@TH*afhްSk4[br: ;I\6哵 ˎڐ J&`),hs܇ ='JOr:F}*Ċp_xEOس)=[ =m o AB~Z *F5Ju5eNURH-'" fL0-_\QLV.N~6eBZ!ނ<  _qZ謄HYM"BZrIy |fn!$NmӑÇVA``XJL\Zh`͟U[M *]ƢQl@Mp1F3†4R^$~T C/teHp4XdAF͸*zbXPNZ6jZ$DAš$R Б /srs/www/man /srs/www/tmp TN2U)D:_0Ȫ&!85NŌ;6ٻ!6$Tٻ/liu]1AA} 5E9֜ Cb$ ,\B;g|rܗM~Q`,N[X ²|1))h]!D "ak0G6O"PeZODwĮ!DT@ Ae4ᜃ堉D7Q}o,Y"!ܫ]lD@LHA$TU,zD雤N*T 4DU B ;cT׿ em|^u[:`,Q ݈KBޅ E#}l‰Mha\uc1H`\(i€"8GA$D$kuĔ_ySv5H IɽR%JF,ul$U\\Ÿ}U ʉӲTjr1ODW~hT@8Iހ^ơX0Q"H% PيF]~[SU:ߞ8QV TVAhbJb)R dr,$.dF3XJ˨` D8'P IAFH˨ DA|8GpgH:b)ME-:YPǠ@ua!6WY@u#5F P@J'xd? Tq]j S@=O;ǂ yZ$p `m\@ٌ @ sؒNYXG5 )MW$]Q~ЃŃF"i EG0M/UhdOП8 >L _F9Z٥Ld3V& ȅB' ŵ4ޫ xTݖWzGT" HsJXa6 ͹P[HMP2C)>a#& 7j, |$̡<{f.u }R4 $c όB'8CTSgw݄ ~ Y'{J$hL_򓘰"}(lX6\hC(/݊OS@TH*afhްSk4[br: ;I\6哵 ˎڐ J&`),hs܇ ='JOr:F}*Ċp_xEOس)=[ =m o AB~Z *F5Ju5eNURH-'" fL0-_\QLV.N~6eBZ!ނ<  _qZ謄HYM"BZrIy |fn!$NmӑÇVA``XJL\Zh`͟U[M *]ƢQl@Mp1F3†4R^$~T C/teHp4XdAF͸*zbXPNZ6jZ$DAš$R Б /srs/www/man .