SlideShare a Scribd company logo
USING THE COMMON SPACE:
•FREE YOUR SITE FROM CUSTOM I-DESCRIPTORS
•IMPROVE READABILITY OF CODE
presented by
MIKO
Programmer/Analyst III
Dept Technology Solutions of ASD
University of California, Berkeley
(510) 643-5015
miko@uclink4.berkeley.edu
Datatel Users Group Conference
March 1999
Session TT849 of the Tools and Technology Track
INTRO: Problems Associated With I-Descriptor Clutter
Selecting data using a Unidata UNIQUERY statement requires reference to fields that must be defined in data
dictionaries, called DICT files. UNIQUERY requires that selection is based upon the content of data fields or
virtual fields. Virtual fields, or I-descriptors, as they are often called, can be used to pass arguments to
subroutines. Arguments represent the means by which data can be sent from one program to another. This
functionality allows the programmer to take advantage of the UNIBASIC language to analyze, “crunch”or
translate data through the Uniquery selection process, making use of code that cannot be incorporated into
Uniquery statements.
Traditionally, a person working with Uniquery has had to suffer through the creation of new I-descriptors in
order to call subroutines using the data that he would specifically like to pass as arguments. This is because I-
descriptors don't have a built-in interface to anything outside of the Uniquery statement within which they're
called. To change arguments being sent by an I-descriptor to a specific subroutine, a programmer must edit the
I-descriptor or create a new version. The problematic nature of this process is compounded by the simple fact
that I-descriptors do not delete themselves.
After going LIVE, many sites quickly see a dramatic growth in the number of I-descriptor type fields in the data
dictionaries of their files. These virtual fields pose several problems:
1. They make it harder to read or list out the items in our larger data dictionaries.
2. There is often no adequate process in place for documenting the purpose or use of these many I-descriptors.
This is hard to implement even when it becomes a site goal. Therefore, there often end up many "dead" but
very "specific" I-descriptors that no one dares destroy for fear of messing up someone else's work.
3. Creating new I-descriptors requires editing a database's DICT and then compiling the DICT item, tasks
which are separate from the process of writing a paragraph and therefore more time-consuming than
working completely within a paragraph.
4. Consequently, because I-descriptor arguments live inside of I-descriptors and not Uniquery paragraphs,
traditional I-descriptors inherently “hide”data from phantom files and paragraphs, where you would ideally
want to see the values that are being used as part of your selection criteria.
5. I-descriptors make it more difficult to make repetitive use of Envisionized processes with front end screens,
such as DMP (mail merge), which may require a change of text in only one field- such as correspondence
code- for each savedlist used.
6. Some users of Uniquery cannot create their own I-descriptors because they do not have access to an editor
such as AE. These same users may nonetheless desire to make use of I-descriptors that call subroutines
without being limited to passing arguments that were passed by other programmers. Custom I-descriptors
with situation-specific arguments are useless to these users.
The good news is this: Use of the shell process-based “COMMON”space can solve all of these problems for
your users and help you to work toward data dictionaries with few items that are customizable from the
command line. In fact, the common space can be used to circumvent a broad range of the limitations imposed
by the "data field" nature of I-descriptors and the often "closed" nature of other UNIBASIC programming.
Making Use Of The COMMON Space
There is a way to create I-descriptors to which you can pass arguments from within a Uniquery paragraph or
from the command line!! Moreover, by doing the methods described in this document, you can avoid
having to customize I-descriptors, or create new custom I-descriptors, for selection and reporting.
You do this by populating a "pocket" of computer memory called a COMMON space. These areas exist for
storing data in active memory so that it can be used by different queries and subroutines within a single login (or
“process”). There exist two types of COMMON spaces in the Unidata environment- named or unnamed.. A
“named COMMON” will retain values stored within it during a full Unidata session- that is, the entire time you
remain logged into a specific Unidata account in a particular screen, or will retain values though the entire life
of a phantom process. An “unnamed COMMON”, on the other hand, is set within a process and cleared upon
return to the ECL “:”(colon) prompt. In this document you will find a clear bias toward the "named"
COMMON spaces since they more fully realize the primary advantage of these areas- to keep data available to
your processes.
Note: For the "official information" of COMMON spaces, you can refer to APPENDIX A, which includes the
Unibasic HELP entry for COMMON.
It is important to remember, as you begin thinking about how to use COMMON areas, that the data in these
areas is never shared among different user logins or between your colon prompt environment and your phantom
processes. Every single login and each phantom process for each user starts with a clean slate and makes use of
its own unique, separate COMMON space. The word “COMMON”does not mean that the information stored
in this space is shared - or “COMMON”- between users and login processes. Rather, it means that the data is
shared by or is COMMON to selection, reporting and other process events that take place within a specific
single login or phantom process. To understand the COMMON space it will be crucial to keep this in mind.
U.C. Berkeley Subroutines That Make Use of COMMON Space
The truth is, you don’t have to understand much about the COMMON space, nor worry about its limits, to be
able to begin to use it right away. This is because, in APPENDIX C you will find the code for one UC Berkeley
program (XMIK.COM) and one UC Berkeley subroutine (XMIK.GETCOM), which will allow you to gain
access to a named COMMON space in a very simple manner. You can use the UC subroutines as templates for
your own, once you feel you understand them better. Following is a description of how these programs are
used.
• XMIK.COM - SUBROUTINE THAT POPULATES A "NAMED COMMON" AREA
XMIK.COM was inspired by the Rotman and Sjoquist SELINP subroutine available at the Cedarville
download site (Appendix B). SELINP is an excellent tool, but it hardwires the number of COMMON space
variables that will be allowed. XMIK.COM was written to overcome this limitation but also has a slightly
different logical structure to it. Other differences are:
a) that XMIK.COM is not bound to in-line prompts
4
b) it uses a dynamic array instead of a MAT-type array
c) allows entry of multi-values with the use of a “left brace”(“{“) delimiter. This delimiter, which
will be discussed further on, doesn't have to be a left curly brace, by the way. If you modify the
code for your site you can change this delimiter to some other esoteric character (one that will be
unlikely to be part of most arguments that you pass.
XMIK.COM is used to create a space for a certain type of information and then to fill that space with data that
you would like to retrieve later from within a select statement in a paragraph or perhaps a report program. At
UC Berkeley, XMIK.COM is used to populate a named COMMON space called /XMIKCOM/.
XMIK.COM is currently written is always at the colon prompt. To use it to create a COMMON space for data,
think of a unique name for the data group (technically it will be a “dynamic array”), and then type:
:XMIK.COM uniquename value{value{value{value…
For example, if I want to create a COMMON area for mail rules and fill it with a set of mail rules to be used for
comparison in a subroutine, I would perhaps type:
:XMIK.COM MAILRULE UCNADR{UCBADR{UCNCON{UCNS
If the TRIM option is kept in XMIK.COM (see the code), these values can also be assign like this:
:XMIK.COM MAILRULE UCNADR
:{UCBADR
:{UCNCON
:{UCNS
The second way of doing it makes it easier to modify previously stored lists to add and remove values that you
want to store.
In both examples above, I have created a data group (“array”) called MAILRULE. The left brace character
“{“ is the data value delimiter and will be converted into a “value mark”(also known as an @VM or
CHAR(253)) before the data is stored in memory. This character was chosen because it’s rarely used in actual
data and is also easier to type than “:@VM:”. Any site choosing to adopt an XMIK.COM type of subroutine
will of course have the option to re-code the subroutine so that their version uses a different delimiter.
The data will be stored as if you had a free-floating multi-valued field in memory, called “MAILRULE”,
containing the values “UCNADR”, “UCBADR”, “UCNCON”, “UCNS”.1
Data can be cleared from a COMMON space variable by typing:
:XMIK.COM variablename CLEAR
For example, to clear the MAILRULE variable so that it still exists but contains no values, type:
1
Geek note: It will be stored with all of your other assigned COMMON area “data groups”in one large array that is itself separated by attribute
makers (@AMs)
5
:XMIK.COM MAILRULE CLEAR
One special note, or “trick”: you can store blank (null) values by starting or ending with a “{“or by putting 2
“{{“together to create a “data pocket”. In other words, @VMs end up wherever brackets are, and so you get
the same dynamic array outcome that you get with @VMs in programs, data fields and I-descriptors.
An even more special note: This document discusses only a command line "program" version of XMIK.COM.
It would be fairly easy, though, to create "subroutine" version of XMIK.COM that could be called from within
an I-descriptor or another program that doesn't have access to the colon prompt. All you'd need to do is take the
2 arguments that are parsed from the command line sentence - the COMMON area variable name it associated
value(s) - and pass these instead as two arguments in your first line of code in your program, as follows:
SUBROUTINE XMIK.COM(X.RESULT,X.VAR.NAME,X.VAR.VALUES)
Such a version of an XMIK.COM-type of program offers some interesting benefits. Since it can be called in I-
descriptor, it allows something truly astounding to happen- it allows you to pass information from one I-
descriptor to another as you pass though a savedlist. This is a great ability to have if you want to create a
"toggle" flag on data being uploaded into a data file.
For instance, if I have a file sorted by ZIP and I want to send two different test letters in exactly equal numbers
to two near-identical geographic groups, I could toggle the letter flag through the zip sort.
You could also use an XMIK.COM type of I-descriptor to do COMMON area "math" - so that, perhaps, you
could count the number of items in various categories without sorting on that data and using TOTAL.
Wow- great features. But how does one get this data out of the name COMMON area when it's needed?
There are two ways (*examples of both are in APPENDIX C):
1. you can retrieve these stored values from within a UNIBASIC program or subroutine
2. you can use a subroutine like XMIK.GETCOM in an I-DESC.
• XMIK.GETCOM- "GETS" DATA OUT OF /XMIK.COM/ FROM WITHIN AN I-DESC
XMIK.GETCOM is used from inside an I-descriptor or is called using the UNIBASIC CALL statement, to
retrieve the value or values you stored in the COMMON space using XMIK.COM. XMIK.COM only retrieves
data, so it cannot be used when the COMMON space is empty. This will cause an error.
IMPORTANT: You can’t make use of XMIK.GETCOM in an I-DESC
unless you ALWAYS store the data being called by XMIK.GETCOM first.
To use this great subroutine, simply insert SUBR(“XMIK.GETCOM”,”uniquename”) where you want the
values to be inserted into the I-DESC in field 2, the LOC entry. For example, to insert the mail rules stored via
XMIK.COM in the above example above into an I-Descriptor, you would create an I-DESC that has a LOC
(field 2) that looks like this:
SUBR(“XC10.SPECIAL.MAIL”,SUBR(“XMIK.GETCOM”,”MAILRULE”))
6
Note: XMIK.GETCOM can replace each argument in your I-Descriptor if necessary and is especially useful for
storing often-changed strings of “:@VM””-separated data, such as mail rules, departments, funds, city names,
country names, zip codes, etc. HOWEVER, you cannot “cross commas”or “cross arguments”inside ONE
GETCOM statement. If you need to supply mail rules and then, after a comma, also need to supply city names,
you will need a separate XMIK.GETCOM section (and XMIK.COM statement) for these two different
arguments in your I-descriptor. This is actually a standard rule for string variables, and that’s all that
XMIK.GETCOM returns, in the end- a string variable.
Thus, note also that outside of the exception of its use in subroutine arguments, you CAN play with the
XMIK.GETCOM result as if it were an ordinary string. You can create an I-DESC that does this:
FIELD(SUBR("XMIK.GETCOM","TESTING"),@VM,2):" plus text":@VM:"Second value"
This results in the printed multi-valued field looking something like:
xmik.getcom value with this appended
Second value
To take advantage of retrieving data from within a program, you will always include the following statement in
your program, before you try to retrieve any of the variables you have stored:
COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES
This statement announces the existence of a named common space called /XMIKCOM/, which is the name
given to the common space created using XMIK.COM. It also heralds the existence and arrangement (relative
position) of two arrays within the /XMIKCOM/ space.
After this statement, you need to determine the position of the string of data that you desire to retrieve from
common space in order to determine its value. You do this by looking for the position of the name that you
gave to the array, as a sort of "variable name", in the larger array in the named common area called
/XMIKCOM/. One technique for doing this would be to use the UNIBASIC LOCATE command, as follows:
LOCATE 'value' IN VAR.NAMES<1> SETTING VAR.POS ELSE…
Note: often when using the LOCATE command in UNIBASIC, you would search an array at the multi-value level
by typing <1,1> instead of searching the level that includes multi-valued information- the attribute level, indicated
above by the <1> next to VAR.NAMES. Since XMIK.COM was designed to allow storing multi-values and
potentially even sub-values, the delimiter BETWEEN the values stored in the common space was chosen to be the
attribute mark.
After finding the value in the COMMON space, you can set a dynamic array variable to equal to the data stored
at the LOCATE-returned position, VAR.POS, in VAR.VALUES:
newvariable = FIELD(VAR.VALUES,@AM,VAR.POS)
Look to APPENDIX C for an example of this implemented in a subroutine.
SPECIAL ADVICE: KNOWING WHEN TO CLEAR COMMON SPACE
7
Sometimes you will want to use a subroutine that populates COMMON space over and over within the same
paragraph or other single process or linked set of processes. When you do this, it is good to remain aware that,
within the same phantom, login, or program, the COMMON space does not clear itself out. If you have a
subroutine that expects a named or unnamed COMMON to be clear when it starts, you will have to make sure
that you do this manually.
For this purpose, there is a command called CLEARCOMMON available to UNIBASIC. Regrettably, I don't
think there's an ECL (Uniquery verb) form of CLEARCOMMON, so you will normally have to write a minimal
UNIBASIC program and catalog it in order to do this.
For example, if you've created a program that fills a named COMMON space for certain savedlists called
/XCLSTS/, you'd create a UNIBASIC program to clear that space, let's call it X.CLEARLISTS, which would
have only one line in it:
001: CLEARCOMMON /XCLSTS/
See APPENDIX D for a complete code example involving the specific circumstance mentioned above.
CONCLUSION
Hopefully you’ll quickly develop an understanding of how to use the COMMON space to your advantage.
You’ll surely learn that using this space will allow you to work more efficiently from within your ad-hoc
paragraph or program, where you can better keep track of and audit how tasks are completed and how items are
selected, without cluttering DICT files with gazillions of new single-use I-descriptors that we’re forever afraid
to delete…
Good luck!
8
APPENDIX A: UNIBASIC HELP FILE FOR “COMMON”
COMMON
Syntax:
COMMON [/COMMON.name/] var1 [,var2][MAT1]...
COM [/COMMON.name/] var1 [,var2][MAT1]...
The UNIBASIC COMMON command makes named variables available to external subroutines and programs. COMMON.name may
have any valid variable name no longer than 7 characters.
The COMMON statement must appear before you use any of the variables (i.e., var1, var2, MAT1) it declares. You may enter a
COMMON statement on several lines by using a comma after each line.
Variables may have one name in the main program and a different name in each subroutine where the COMMON statement appears.
The statement refers to the position of the variables in the statement to identify matching variables.
• Passing Matrices
You may declare matrices with a COMMON statement. You may not declare matrices by both a COMMON and a DIMENSION
statement. Matrices you declare in a COMMON statement may not be dynamically re-dimensioned. All variables and matrices you
create by a COMMON statement are initialized to zero.
• Passing Variables
Variables you declare by a COMMON statement without a COMMON.name lose their values when the Unidata Environment Control
Language (ECL) prompt redisplays. You may access the values by any program you call or chain to. The values of variables you
declare by a COMMON statement without a COMMON.label are stored in a single area called: unnamed COMMON.
Variables you declare by a COMMON statement with a COMMON.name retain their value until the end of the Unidata session. The
system clears the when you terminate your Unidata session.
The number of variables that a COMMON statement may contain depends on the virtual memory of your system. For information on
virtual memory, refer to the System Administrator's Guide.
• Examples
In the following example, the program statement uses an unnamed COMMON statement to declare the matrices, NAME and DATES,
as well as the variable DCHANGE.
COMMON NAME(100),DATES(100,2),DCHANGE
In the next example, the program segment creates two named COMMON areas. The second COMMON statement continues on a
second line with the comma ( , ) continuation character.
COMMON /MENU/ X,Y,X DIM,Y DIM,S.CHAR
COMMON /CALC/ RATE(10),AMOUNT(10),DATE1, DATE2,LATE
In the following example, the program segment in invalid since the COMMON statement must appear first. You cannot redefine a
variable in the COMMON statement after it has been assigned. Unidata requires one-to-one correspondence between main line and
subprograms.
VALUE = 253
COMMON VALUE,SUBVALUE,ATTRIBUTE
9
APPENDIX B: CEDARVILLE “SELINP” SUBROUTINE
SUBROUTINE SELINP(RETURN.VALUE,VARIABLE,PROMPT.TEXT,CONV.CODE)
*
* INFO/BASIC PROGRAM
*
* TITLE ----- SELINP
*
* PURPOSE: SUBROUTINE TO ASK FOR INPUT WHEN A SELECT IS FIRST RUN
*
* Last updated by LIVE (ROTMAN) at 10:06:07 on 08/11/1989.
* Echo input value to screen so that paragraphs using in-line
* prompts do not confuse the user (thinking he/she has to enter a value
* more than once).
* Last updated by LIVE (SJOQUIST) at 11:29:42 on 05/12/1988.
* Use FIRST.RECORD & labeled COMMON
* Last updated by LIVE (SJOQUIST) at 08:28:58 on 10/07/1987.
*
***********************************************************************************
* This program is provided 'as is' for your use by ROTMAN & SJOQUIST.
* You are encouraged to verify the accuracy of program functions prior
* to use with actual data files.
*
* If you have questions about this program, or if you wish to obtain
* a list of programs available for purchase from ROTMAN & SJOQUIST,
* contact Dave Rotman or Doug Sjoquist:
*
* Rotman and Sjoquist
* c/o Cedarville College
* PO Box 601
* Cedarville, OH 45314
* (513) 766-2211
************************************************************************************
MAX.VAR = 25
COMMON /SELINP/ NUM.VAR,
VAR.NAME(MAX.VAR),
VAR.VALUE(MAX.VAR)
THIS.IS.THE.FIRST = ''
CALL FIRST.RECORD(THIS.IS.THE.FIRST,'SELINP')
IF THIS.IS.THE.FIRST THEN
NUM.VAR = 0
MAT VAR.NAME = ''
MAT VAR.VALUE = ''
END
PROMPT ''
VAR.NUM = 0
LOOP
VAR.NUM += 1
UNTIL VAR.NUM > NUM.VAR OR VARIABLE = VAR.NAME(VAR.NUM)
REPEAT
* NEW VARIABLE
IF VAR.NUM > NUM.VAR THEN
NUM.VAR += 1
VAR.NUM = NUM.VAR
VAR.NAME(VAR.NUM) = VARIABLE
IF PROMPT.TEXT THEN
TEXT = PROMPT.TEXT:': '
END ELSE
TEXT = VARIABLE:': '
END
* IF CONV CODE USED, FORCE CORRECT VALUE
LOOP
CRT TEXT:
INPUT VALUE
IF CONV.CODE THEN
NEW.VALUE = ICONV(VALUE,CONV.CODE)
ISTAT = STATUS()
END ELSE
NEW.VALUE = VALUE
ISTAT = 0
END
IF ISTAT = 0 THEN
CRT NEW.VALUE
END
UNTIL ISTAT = 0
CRT '"':VALUE:'" DOES NOT MATCH THE CONV CODE "':CONV.CODE:'"'
REPEAT
VAR.VALUE(VAR.NUM) = NEW.VALUE
END
RETURN.VALUE = VAR.VALUE(VAR.NUM)
RETURN
END
10
APPENDIX C: XMIK.COM, XMIK.GETCOM, XMIK.MEM.ONLY
XMIK.COM: this subroutine can be used to populate a named COMMON called /XMIKCOM/
SENTENCE = @SENTENCE
VAR.NAME = FIELD(SENTENCE,' ',2)
VAR.VAL.LEN = LEN(SENTENCE) - (10 + LEN(VAR.NAME))
VAR.VAL.START = 11 + LEN(VAR.NAME)
VAR.VAL = SENTENCE[VAR.VAL.START,VAR.VAL.LEN]
VAR.VAL.TEMP = ''
COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES
IF UPCASE(VAR.VAL) = 'CLEAR' THEN
LOCATE VAR.NAME IN VAR.NAMES<1> SETTING POS THEN
VAR.NAMES = DELETE(VAR.NAMES,POS,0,0)
VAR.VALUES = DELETE(VAR.VALUES,POS,0,0)
MESSAGE = VAR.NAME:" is cleared"
PRINT MESSAGE
STOP
END
END ELSE
BRACE.CT = DCOUNT(VAR.VAL,"{")
IF BRACE.CT GT 1 THEN
FOR BRACE.MARK = 1 TO BRACE.CT
THIS.VALUE = FIELD(VAR.VAL,"{",BRACE.MARK)
VAR.VAL.TEMP<1,-1> = TRIM(THIS.VALUE)
** place a TRIM statement above if you want to allow data to be spread across
** paragraph lines with “” and you don’t mind ignoring leading or trailing
** spaces - otherwise, don’t use trim above
NEXT BRACE.MARK
VAR.VAL = VAR.VAL.TEMP
END
LOCATE VAR.NAME IN VAR.NAMES<1> SETTING POS THEN
MESSAGE = "Old value of ":VAR.NAME:" was ":FIELD(VAR.VALUES,@AM,POS)
PRINT MESSAGE
VAR.VALUES = REPLACE(VAR.VALUES,POS,0,0,VAR.VAL)
MESSAGE = "New Value of ":VAR.NAME:" is ":FIELD(VAR.VALUES,@AM,POS)
PRINT MESSAGE
END ELSE
VAR.NAMES = INSERT(VAR.NAMES,-1,0,0,VAR.NAME)
VAR.VALUES = INSERT(VAR.VALUES,-1,0,0,VAR.VAL)
MESSAGE = VAR.NAME:" set to ":VAR.VAL:" in XMIKCOM VAR.VALUES at position
":DCOUNT(VAR.VALUES,@AM)
PRINT MESSAGE
END
END
XMIK.GETCOM: this subroutine is used to recall values stored in /XMIKCOM/ with XMIK.COM
SUBROUTINE XMIK.GETCOM(RESULT,VAR.NAME)
RESULT = ''
COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES
LOCATE VAR.NAME IN VAR.NAMES<1> SETTING POS THEN
RESULT = FIELD(VAR.VALUES,@AM,POS)
END
RETURN
XMIK.MEM.ONLY: A UNIBASIC code that gets the value of “MEMRL” from /XMIKCOM/
SUBROUTINE XMIK.MEM.ONLY(RESULT,PERSON.ID)
COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES
LOCATE 'MEMRL'* IN VAR.NAMES<1> SETTING VAR.POS ELSE
PRINT "Submit MEMRL to XMIK.COM!!!!"
RETURN
END
MEMRL = FIELD(VAR.VALUES,@AM,VAR.POS)
CONVERT ',' TO @AM IN MEMRL
* MEMRL is set up in the paragraph, before the subr is called, with: “XMIK.COM MEMRL values”
11
APPENDIX D: XMPE.CHECK.SAVEDLISTS & X.CLEARLISTS
XMPE.CHECK.SAVEDLISTS stores savedlist ids in an array in COMMON so that IDs in an active savedlist
can be sought within that array.
* UNIBASIC SUBROUTINE: XMPE.CHECK.SAVEDLISTS
* BY: MICHAEL ERNST
* DATE: 11/20/96
* DESCRIPTION: CHECKS EACH OF A PASSED LIST OF SAVEDLISTS FOR THE
* EXISTENCE OF A PASSED RECORD KEY. RETURNS THE LIST
* OF SAVEDLISTS IN WHICH THE RECORD KEY IS FOUND.
* USES ACTIVE LIST 9.
**********
* Last updated by bendev (ur0mpe) at 15:38:10 on 11/20/1996.
**********
SUBROUTINE XMPE.CHECK.SAVEDLISTS(RESULT,KEY,LISTS,OUTPUT,TYPE)
X.PRESERVE.RECORD = @RECORD
COMMON /XCLSTS/ LIST.ARRAY, NUM.LISTS, ARRAY.BUILT
IF ARRAY.BUILT # 1 THEN
EXECUTE "HUSH ON"
LIST.ARRAY = ''
NUM.LISTS = DCOUNT(LISTS,@VM)
FOR EACH.LIST = 1 TO NUM.LISTS
LIST.NAME = LISTS<1,EACH.LIST>
GETLIST LIST.NAME TO 9 THEN
READLIST R.LIST FROM 9 ELSE
R.LIST = ''
END
END
CONVERT @AM TO @VM IN R.LIST
LIST.ARRAY<-1> = R.LIST
NEXT EACH.LIST
ARRAY.BUILT = 1
EXECUTE "HUSH OFF"
END
RESULT = ''
FOUND = ''
FOR EACH.LIST = 1 TO NUM.LISTS
IF TYPE # "S" OR FOUND # "1" THEN
LOCATE KEY IN LIST.ARRAY<EACH.LIST,1> SETTING POS THEN
IF LEN(OUTPUT) THEN
RESULT<1,-1> = OUTPUT<1,EACH.LIST>
END ELSE
RESULT<1,-1> = LISTS<1,EACH.LIST>
END
FOUND = 1
END
END
NEXT EACH.LIST
@RECORD = X.PRESERVE.RECORD
RETURN
END
The I-DESC that is used at UCB to determine whether certain IDs are in certain lists is the following, called
XMIK.CHK.LISTS:
SUBR("XMPE.CHECK.SAVEDLISTS",@ID,SUBR("XMIK.GETCOM","LISTS"),SUBR("XMIK.GETCOM","RESULTS"),'S')…
The savedlist array can be cleared, between reports within a single paragraph, with the command:
X.CLEARLISTS
This subroutine has a single line of code in it, which is all that is needed. The code is:
CLEARCOMMON /XCLSTS/

More Related Content

PPT
DB2 Interview Questions - Part 1
PDF
Ibm db2 interview questions and answers
PPT
Hacking Windows IPC
PDF
Chap16 scr
PDF
Xs path navigation on xml schemas made easy
RTF
Bt export
PDF
DB2 Interview Questions - Part 1
Ibm db2 interview questions and answers
Hacking Windows IPC
Chap16 scr
Xs path navigation on xml schemas made easy
Bt export

Similar to Using-The-Common-Space-DUG-Datatel-Miko (20)

PPTX
File Structures and Access in Data Structures
PPTX
File Structures and File Access in Data Structures
PPTX
File Strucutres and Access in Data Structures
PDF
File system in operating system e learning
PPTX
2.7 use of ict in data management
PDF
A relational model of data for large shared data banks
PPT
358 33 powerpoint-slides_16-files-their-organization_chapter-16
PDF
File system
PDF
File organization
PPT
D.dsgn + dbms
PDF
File Types in Data Structure
PDF
PPTX
PPTX
15 wordprocessing ml subject - fields and hyperlinks
DOC
Basic IMS For Applications
PPTX
File Organization, Indexing and Hashing.pptx
PPTX
Operating Systems - File Management
PPTX
Operating Systems: File Management
PPTX
storage techniques_overview-1.pptx
File Structures and Access in Data Structures
File Structures and File Access in Data Structures
File Strucutres and Access in Data Structures
File system in operating system e learning
2.7 use of ict in data management
A relational model of data for large shared data banks
358 33 powerpoint-slides_16-files-their-organization_chapter-16
File system
File organization
D.dsgn + dbms
File Types in Data Structure
15 wordprocessing ml subject - fields and hyperlinks
Basic IMS For Applications
File Organization, Indexing and Hashing.pptx
Operating Systems - File Management
Operating Systems: File Management
storage techniques_overview-1.pptx
Ad

Using-The-Common-Space-DUG-Datatel-Miko

  • 1. USING THE COMMON SPACE: •FREE YOUR SITE FROM CUSTOM I-DESCRIPTORS •IMPROVE READABILITY OF CODE presented by MIKO Programmer/Analyst III Dept Technology Solutions of ASD University of California, Berkeley (510) 643-5015 miko@uclink4.berkeley.edu Datatel Users Group Conference March 1999 Session TT849 of the Tools and Technology Track
  • 2. INTRO: Problems Associated With I-Descriptor Clutter Selecting data using a Unidata UNIQUERY statement requires reference to fields that must be defined in data dictionaries, called DICT files. UNIQUERY requires that selection is based upon the content of data fields or virtual fields. Virtual fields, or I-descriptors, as they are often called, can be used to pass arguments to subroutines. Arguments represent the means by which data can be sent from one program to another. This functionality allows the programmer to take advantage of the UNIBASIC language to analyze, “crunch”or translate data through the Uniquery selection process, making use of code that cannot be incorporated into Uniquery statements. Traditionally, a person working with Uniquery has had to suffer through the creation of new I-descriptors in order to call subroutines using the data that he would specifically like to pass as arguments. This is because I- descriptors don't have a built-in interface to anything outside of the Uniquery statement within which they're called. To change arguments being sent by an I-descriptor to a specific subroutine, a programmer must edit the I-descriptor or create a new version. The problematic nature of this process is compounded by the simple fact that I-descriptors do not delete themselves. After going LIVE, many sites quickly see a dramatic growth in the number of I-descriptor type fields in the data dictionaries of their files. These virtual fields pose several problems: 1. They make it harder to read or list out the items in our larger data dictionaries. 2. There is often no adequate process in place for documenting the purpose or use of these many I-descriptors. This is hard to implement even when it becomes a site goal. Therefore, there often end up many "dead" but very "specific" I-descriptors that no one dares destroy for fear of messing up someone else's work. 3. Creating new I-descriptors requires editing a database's DICT and then compiling the DICT item, tasks which are separate from the process of writing a paragraph and therefore more time-consuming than working completely within a paragraph. 4. Consequently, because I-descriptor arguments live inside of I-descriptors and not Uniquery paragraphs, traditional I-descriptors inherently “hide”data from phantom files and paragraphs, where you would ideally want to see the values that are being used as part of your selection criteria. 5. I-descriptors make it more difficult to make repetitive use of Envisionized processes with front end screens, such as DMP (mail merge), which may require a change of text in only one field- such as correspondence code- for each savedlist used. 6. Some users of Uniquery cannot create their own I-descriptors because they do not have access to an editor such as AE. These same users may nonetheless desire to make use of I-descriptors that call subroutines without being limited to passing arguments that were passed by other programmers. Custom I-descriptors with situation-specific arguments are useless to these users. The good news is this: Use of the shell process-based “COMMON”space can solve all of these problems for your users and help you to work toward data dictionaries with few items that are customizable from the command line. In fact, the common space can be used to circumvent a broad range of the limitations imposed by the "data field" nature of I-descriptors and the often "closed" nature of other UNIBASIC programming.
  • 3. Making Use Of The COMMON Space There is a way to create I-descriptors to which you can pass arguments from within a Uniquery paragraph or from the command line!! Moreover, by doing the methods described in this document, you can avoid having to customize I-descriptors, or create new custom I-descriptors, for selection and reporting. You do this by populating a "pocket" of computer memory called a COMMON space. These areas exist for storing data in active memory so that it can be used by different queries and subroutines within a single login (or “process”). There exist two types of COMMON spaces in the Unidata environment- named or unnamed.. A “named COMMON” will retain values stored within it during a full Unidata session- that is, the entire time you remain logged into a specific Unidata account in a particular screen, or will retain values though the entire life of a phantom process. An “unnamed COMMON”, on the other hand, is set within a process and cleared upon return to the ECL “:”(colon) prompt. In this document you will find a clear bias toward the "named" COMMON spaces since they more fully realize the primary advantage of these areas- to keep data available to your processes. Note: For the "official information" of COMMON spaces, you can refer to APPENDIX A, which includes the Unibasic HELP entry for COMMON. It is important to remember, as you begin thinking about how to use COMMON areas, that the data in these areas is never shared among different user logins or between your colon prompt environment and your phantom processes. Every single login and each phantom process for each user starts with a clean slate and makes use of its own unique, separate COMMON space. The word “COMMON”does not mean that the information stored in this space is shared - or “COMMON”- between users and login processes. Rather, it means that the data is shared by or is COMMON to selection, reporting and other process events that take place within a specific single login or phantom process. To understand the COMMON space it will be crucial to keep this in mind. U.C. Berkeley Subroutines That Make Use of COMMON Space The truth is, you don’t have to understand much about the COMMON space, nor worry about its limits, to be able to begin to use it right away. This is because, in APPENDIX C you will find the code for one UC Berkeley program (XMIK.COM) and one UC Berkeley subroutine (XMIK.GETCOM), which will allow you to gain access to a named COMMON space in a very simple manner. You can use the UC subroutines as templates for your own, once you feel you understand them better. Following is a description of how these programs are used. • XMIK.COM - SUBROUTINE THAT POPULATES A "NAMED COMMON" AREA XMIK.COM was inspired by the Rotman and Sjoquist SELINP subroutine available at the Cedarville download site (Appendix B). SELINP is an excellent tool, but it hardwires the number of COMMON space variables that will be allowed. XMIK.COM was written to overcome this limitation but also has a slightly different logical structure to it. Other differences are: a) that XMIK.COM is not bound to in-line prompts
  • 4. 4 b) it uses a dynamic array instead of a MAT-type array c) allows entry of multi-values with the use of a “left brace”(“{“) delimiter. This delimiter, which will be discussed further on, doesn't have to be a left curly brace, by the way. If you modify the code for your site you can change this delimiter to some other esoteric character (one that will be unlikely to be part of most arguments that you pass. XMIK.COM is used to create a space for a certain type of information and then to fill that space with data that you would like to retrieve later from within a select statement in a paragraph or perhaps a report program. At UC Berkeley, XMIK.COM is used to populate a named COMMON space called /XMIKCOM/. XMIK.COM is currently written is always at the colon prompt. To use it to create a COMMON space for data, think of a unique name for the data group (technically it will be a “dynamic array”), and then type: :XMIK.COM uniquename value{value{value{value… For example, if I want to create a COMMON area for mail rules and fill it with a set of mail rules to be used for comparison in a subroutine, I would perhaps type: :XMIK.COM MAILRULE UCNADR{UCBADR{UCNCON{UCNS If the TRIM option is kept in XMIK.COM (see the code), these values can also be assign like this: :XMIK.COM MAILRULE UCNADR :{UCBADR :{UCNCON :{UCNS The second way of doing it makes it easier to modify previously stored lists to add and remove values that you want to store. In both examples above, I have created a data group (“array”) called MAILRULE. The left brace character “{“ is the data value delimiter and will be converted into a “value mark”(also known as an @VM or CHAR(253)) before the data is stored in memory. This character was chosen because it’s rarely used in actual data and is also easier to type than “:@VM:”. Any site choosing to adopt an XMIK.COM type of subroutine will of course have the option to re-code the subroutine so that their version uses a different delimiter. The data will be stored as if you had a free-floating multi-valued field in memory, called “MAILRULE”, containing the values “UCNADR”, “UCBADR”, “UCNCON”, “UCNS”.1 Data can be cleared from a COMMON space variable by typing: :XMIK.COM variablename CLEAR For example, to clear the MAILRULE variable so that it still exists but contains no values, type: 1 Geek note: It will be stored with all of your other assigned COMMON area “data groups”in one large array that is itself separated by attribute makers (@AMs)
  • 5. 5 :XMIK.COM MAILRULE CLEAR One special note, or “trick”: you can store blank (null) values by starting or ending with a “{“or by putting 2 “{{“together to create a “data pocket”. In other words, @VMs end up wherever brackets are, and so you get the same dynamic array outcome that you get with @VMs in programs, data fields and I-descriptors. An even more special note: This document discusses only a command line "program" version of XMIK.COM. It would be fairly easy, though, to create "subroutine" version of XMIK.COM that could be called from within an I-descriptor or another program that doesn't have access to the colon prompt. All you'd need to do is take the 2 arguments that are parsed from the command line sentence - the COMMON area variable name it associated value(s) - and pass these instead as two arguments in your first line of code in your program, as follows: SUBROUTINE XMIK.COM(X.RESULT,X.VAR.NAME,X.VAR.VALUES) Such a version of an XMIK.COM-type of program offers some interesting benefits. Since it can be called in I- descriptor, it allows something truly astounding to happen- it allows you to pass information from one I- descriptor to another as you pass though a savedlist. This is a great ability to have if you want to create a "toggle" flag on data being uploaded into a data file. For instance, if I have a file sorted by ZIP and I want to send two different test letters in exactly equal numbers to two near-identical geographic groups, I could toggle the letter flag through the zip sort. You could also use an XMIK.COM type of I-descriptor to do COMMON area "math" - so that, perhaps, you could count the number of items in various categories without sorting on that data and using TOTAL. Wow- great features. But how does one get this data out of the name COMMON area when it's needed? There are two ways (*examples of both are in APPENDIX C): 1. you can retrieve these stored values from within a UNIBASIC program or subroutine 2. you can use a subroutine like XMIK.GETCOM in an I-DESC. • XMIK.GETCOM- "GETS" DATA OUT OF /XMIK.COM/ FROM WITHIN AN I-DESC XMIK.GETCOM is used from inside an I-descriptor or is called using the UNIBASIC CALL statement, to retrieve the value or values you stored in the COMMON space using XMIK.COM. XMIK.COM only retrieves data, so it cannot be used when the COMMON space is empty. This will cause an error. IMPORTANT: You can’t make use of XMIK.GETCOM in an I-DESC unless you ALWAYS store the data being called by XMIK.GETCOM first. To use this great subroutine, simply insert SUBR(“XMIK.GETCOM”,”uniquename”) where you want the values to be inserted into the I-DESC in field 2, the LOC entry. For example, to insert the mail rules stored via XMIK.COM in the above example above into an I-Descriptor, you would create an I-DESC that has a LOC (field 2) that looks like this: SUBR(“XC10.SPECIAL.MAIL”,SUBR(“XMIK.GETCOM”,”MAILRULE”))
  • 6. 6 Note: XMIK.GETCOM can replace each argument in your I-Descriptor if necessary and is especially useful for storing often-changed strings of “:@VM””-separated data, such as mail rules, departments, funds, city names, country names, zip codes, etc. HOWEVER, you cannot “cross commas”or “cross arguments”inside ONE GETCOM statement. If you need to supply mail rules and then, after a comma, also need to supply city names, you will need a separate XMIK.GETCOM section (and XMIK.COM statement) for these two different arguments in your I-descriptor. This is actually a standard rule for string variables, and that’s all that XMIK.GETCOM returns, in the end- a string variable. Thus, note also that outside of the exception of its use in subroutine arguments, you CAN play with the XMIK.GETCOM result as if it were an ordinary string. You can create an I-DESC that does this: FIELD(SUBR("XMIK.GETCOM","TESTING"),@VM,2):" plus text":@VM:"Second value" This results in the printed multi-valued field looking something like: xmik.getcom value with this appended Second value To take advantage of retrieving data from within a program, you will always include the following statement in your program, before you try to retrieve any of the variables you have stored: COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES This statement announces the existence of a named common space called /XMIKCOM/, which is the name given to the common space created using XMIK.COM. It also heralds the existence and arrangement (relative position) of two arrays within the /XMIKCOM/ space. After this statement, you need to determine the position of the string of data that you desire to retrieve from common space in order to determine its value. You do this by looking for the position of the name that you gave to the array, as a sort of "variable name", in the larger array in the named common area called /XMIKCOM/. One technique for doing this would be to use the UNIBASIC LOCATE command, as follows: LOCATE 'value' IN VAR.NAMES<1> SETTING VAR.POS ELSE… Note: often when using the LOCATE command in UNIBASIC, you would search an array at the multi-value level by typing <1,1> instead of searching the level that includes multi-valued information- the attribute level, indicated above by the <1> next to VAR.NAMES. Since XMIK.COM was designed to allow storing multi-values and potentially even sub-values, the delimiter BETWEEN the values stored in the common space was chosen to be the attribute mark. After finding the value in the COMMON space, you can set a dynamic array variable to equal to the data stored at the LOCATE-returned position, VAR.POS, in VAR.VALUES: newvariable = FIELD(VAR.VALUES,@AM,VAR.POS) Look to APPENDIX C for an example of this implemented in a subroutine. SPECIAL ADVICE: KNOWING WHEN TO CLEAR COMMON SPACE
  • 7. 7 Sometimes you will want to use a subroutine that populates COMMON space over and over within the same paragraph or other single process or linked set of processes. When you do this, it is good to remain aware that, within the same phantom, login, or program, the COMMON space does not clear itself out. If you have a subroutine that expects a named or unnamed COMMON to be clear when it starts, you will have to make sure that you do this manually. For this purpose, there is a command called CLEARCOMMON available to UNIBASIC. Regrettably, I don't think there's an ECL (Uniquery verb) form of CLEARCOMMON, so you will normally have to write a minimal UNIBASIC program and catalog it in order to do this. For example, if you've created a program that fills a named COMMON space for certain savedlists called /XCLSTS/, you'd create a UNIBASIC program to clear that space, let's call it X.CLEARLISTS, which would have only one line in it: 001: CLEARCOMMON /XCLSTS/ See APPENDIX D for a complete code example involving the specific circumstance mentioned above. CONCLUSION Hopefully you’ll quickly develop an understanding of how to use the COMMON space to your advantage. You’ll surely learn that using this space will allow you to work more efficiently from within your ad-hoc paragraph or program, where you can better keep track of and audit how tasks are completed and how items are selected, without cluttering DICT files with gazillions of new single-use I-descriptors that we’re forever afraid to delete… Good luck!
  • 8. 8 APPENDIX A: UNIBASIC HELP FILE FOR “COMMON” COMMON Syntax: COMMON [/COMMON.name/] var1 [,var2][MAT1]... COM [/COMMON.name/] var1 [,var2][MAT1]... The UNIBASIC COMMON command makes named variables available to external subroutines and programs. COMMON.name may have any valid variable name no longer than 7 characters. The COMMON statement must appear before you use any of the variables (i.e., var1, var2, MAT1) it declares. You may enter a COMMON statement on several lines by using a comma after each line. Variables may have one name in the main program and a different name in each subroutine where the COMMON statement appears. The statement refers to the position of the variables in the statement to identify matching variables. • Passing Matrices You may declare matrices with a COMMON statement. You may not declare matrices by both a COMMON and a DIMENSION statement. Matrices you declare in a COMMON statement may not be dynamically re-dimensioned. All variables and matrices you create by a COMMON statement are initialized to zero. • Passing Variables Variables you declare by a COMMON statement without a COMMON.name lose their values when the Unidata Environment Control Language (ECL) prompt redisplays. You may access the values by any program you call or chain to. The values of variables you declare by a COMMON statement without a COMMON.label are stored in a single area called: unnamed COMMON. Variables you declare by a COMMON statement with a COMMON.name retain their value until the end of the Unidata session. The system clears the when you terminate your Unidata session. The number of variables that a COMMON statement may contain depends on the virtual memory of your system. For information on virtual memory, refer to the System Administrator's Guide. • Examples In the following example, the program statement uses an unnamed COMMON statement to declare the matrices, NAME and DATES, as well as the variable DCHANGE. COMMON NAME(100),DATES(100,2),DCHANGE In the next example, the program segment creates two named COMMON areas. The second COMMON statement continues on a second line with the comma ( , ) continuation character. COMMON /MENU/ X,Y,X DIM,Y DIM,S.CHAR COMMON /CALC/ RATE(10),AMOUNT(10),DATE1, DATE2,LATE In the following example, the program segment in invalid since the COMMON statement must appear first. You cannot redefine a variable in the COMMON statement after it has been assigned. Unidata requires one-to-one correspondence between main line and subprograms. VALUE = 253 COMMON VALUE,SUBVALUE,ATTRIBUTE
  • 9. 9 APPENDIX B: CEDARVILLE “SELINP” SUBROUTINE SUBROUTINE SELINP(RETURN.VALUE,VARIABLE,PROMPT.TEXT,CONV.CODE) * * INFO/BASIC PROGRAM * * TITLE ----- SELINP * * PURPOSE: SUBROUTINE TO ASK FOR INPUT WHEN A SELECT IS FIRST RUN * * Last updated by LIVE (ROTMAN) at 10:06:07 on 08/11/1989. * Echo input value to screen so that paragraphs using in-line * prompts do not confuse the user (thinking he/she has to enter a value * more than once). * Last updated by LIVE (SJOQUIST) at 11:29:42 on 05/12/1988. * Use FIRST.RECORD & labeled COMMON * Last updated by LIVE (SJOQUIST) at 08:28:58 on 10/07/1987. * *********************************************************************************** * This program is provided 'as is' for your use by ROTMAN & SJOQUIST. * You are encouraged to verify the accuracy of program functions prior * to use with actual data files. * * If you have questions about this program, or if you wish to obtain * a list of programs available for purchase from ROTMAN & SJOQUIST, * contact Dave Rotman or Doug Sjoquist: * * Rotman and Sjoquist * c/o Cedarville College * PO Box 601 * Cedarville, OH 45314 * (513) 766-2211 ************************************************************************************ MAX.VAR = 25 COMMON /SELINP/ NUM.VAR, VAR.NAME(MAX.VAR), VAR.VALUE(MAX.VAR) THIS.IS.THE.FIRST = '' CALL FIRST.RECORD(THIS.IS.THE.FIRST,'SELINP') IF THIS.IS.THE.FIRST THEN NUM.VAR = 0 MAT VAR.NAME = '' MAT VAR.VALUE = '' END PROMPT '' VAR.NUM = 0 LOOP VAR.NUM += 1 UNTIL VAR.NUM > NUM.VAR OR VARIABLE = VAR.NAME(VAR.NUM) REPEAT * NEW VARIABLE IF VAR.NUM > NUM.VAR THEN NUM.VAR += 1 VAR.NUM = NUM.VAR VAR.NAME(VAR.NUM) = VARIABLE IF PROMPT.TEXT THEN TEXT = PROMPT.TEXT:': ' END ELSE TEXT = VARIABLE:': ' END * IF CONV CODE USED, FORCE CORRECT VALUE LOOP CRT TEXT: INPUT VALUE IF CONV.CODE THEN NEW.VALUE = ICONV(VALUE,CONV.CODE) ISTAT = STATUS() END ELSE NEW.VALUE = VALUE ISTAT = 0 END IF ISTAT = 0 THEN CRT NEW.VALUE END UNTIL ISTAT = 0 CRT '"':VALUE:'" DOES NOT MATCH THE CONV CODE "':CONV.CODE:'"' REPEAT VAR.VALUE(VAR.NUM) = NEW.VALUE END RETURN.VALUE = VAR.VALUE(VAR.NUM) RETURN END
  • 10. 10 APPENDIX C: XMIK.COM, XMIK.GETCOM, XMIK.MEM.ONLY XMIK.COM: this subroutine can be used to populate a named COMMON called /XMIKCOM/ SENTENCE = @SENTENCE VAR.NAME = FIELD(SENTENCE,' ',2) VAR.VAL.LEN = LEN(SENTENCE) - (10 + LEN(VAR.NAME)) VAR.VAL.START = 11 + LEN(VAR.NAME) VAR.VAL = SENTENCE[VAR.VAL.START,VAR.VAL.LEN] VAR.VAL.TEMP = '' COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES IF UPCASE(VAR.VAL) = 'CLEAR' THEN LOCATE VAR.NAME IN VAR.NAMES<1> SETTING POS THEN VAR.NAMES = DELETE(VAR.NAMES,POS,0,0) VAR.VALUES = DELETE(VAR.VALUES,POS,0,0) MESSAGE = VAR.NAME:" is cleared" PRINT MESSAGE STOP END END ELSE BRACE.CT = DCOUNT(VAR.VAL,"{") IF BRACE.CT GT 1 THEN FOR BRACE.MARK = 1 TO BRACE.CT THIS.VALUE = FIELD(VAR.VAL,"{",BRACE.MARK) VAR.VAL.TEMP<1,-1> = TRIM(THIS.VALUE) ** place a TRIM statement above if you want to allow data to be spread across ** paragraph lines with “” and you don’t mind ignoring leading or trailing ** spaces - otherwise, don’t use trim above NEXT BRACE.MARK VAR.VAL = VAR.VAL.TEMP END LOCATE VAR.NAME IN VAR.NAMES<1> SETTING POS THEN MESSAGE = "Old value of ":VAR.NAME:" was ":FIELD(VAR.VALUES,@AM,POS) PRINT MESSAGE VAR.VALUES = REPLACE(VAR.VALUES,POS,0,0,VAR.VAL) MESSAGE = "New Value of ":VAR.NAME:" is ":FIELD(VAR.VALUES,@AM,POS) PRINT MESSAGE END ELSE VAR.NAMES = INSERT(VAR.NAMES,-1,0,0,VAR.NAME) VAR.VALUES = INSERT(VAR.VALUES,-1,0,0,VAR.VAL) MESSAGE = VAR.NAME:" set to ":VAR.VAL:" in XMIKCOM VAR.VALUES at position ":DCOUNT(VAR.VALUES,@AM) PRINT MESSAGE END END XMIK.GETCOM: this subroutine is used to recall values stored in /XMIKCOM/ with XMIK.COM SUBROUTINE XMIK.GETCOM(RESULT,VAR.NAME) RESULT = '' COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES LOCATE VAR.NAME IN VAR.NAMES<1> SETTING POS THEN RESULT = FIELD(VAR.VALUES,@AM,POS) END RETURN XMIK.MEM.ONLY: A UNIBASIC code that gets the value of “MEMRL” from /XMIKCOM/ SUBROUTINE XMIK.MEM.ONLY(RESULT,PERSON.ID) COMMON /XMIKCOM/ VAR.NAMES,VAR.VALUES LOCATE 'MEMRL'* IN VAR.NAMES<1> SETTING VAR.POS ELSE PRINT "Submit MEMRL to XMIK.COM!!!!" RETURN END MEMRL = FIELD(VAR.VALUES,@AM,VAR.POS) CONVERT ',' TO @AM IN MEMRL * MEMRL is set up in the paragraph, before the subr is called, with: “XMIK.COM MEMRL values”
  • 11. 11 APPENDIX D: XMPE.CHECK.SAVEDLISTS & X.CLEARLISTS XMPE.CHECK.SAVEDLISTS stores savedlist ids in an array in COMMON so that IDs in an active savedlist can be sought within that array. * UNIBASIC SUBROUTINE: XMPE.CHECK.SAVEDLISTS * BY: MICHAEL ERNST * DATE: 11/20/96 * DESCRIPTION: CHECKS EACH OF A PASSED LIST OF SAVEDLISTS FOR THE * EXISTENCE OF A PASSED RECORD KEY. RETURNS THE LIST * OF SAVEDLISTS IN WHICH THE RECORD KEY IS FOUND. * USES ACTIVE LIST 9. ********** * Last updated by bendev (ur0mpe) at 15:38:10 on 11/20/1996. ********** SUBROUTINE XMPE.CHECK.SAVEDLISTS(RESULT,KEY,LISTS,OUTPUT,TYPE) X.PRESERVE.RECORD = @RECORD COMMON /XCLSTS/ LIST.ARRAY, NUM.LISTS, ARRAY.BUILT IF ARRAY.BUILT # 1 THEN EXECUTE "HUSH ON" LIST.ARRAY = '' NUM.LISTS = DCOUNT(LISTS,@VM) FOR EACH.LIST = 1 TO NUM.LISTS LIST.NAME = LISTS<1,EACH.LIST> GETLIST LIST.NAME TO 9 THEN READLIST R.LIST FROM 9 ELSE R.LIST = '' END END CONVERT @AM TO @VM IN R.LIST LIST.ARRAY<-1> = R.LIST NEXT EACH.LIST ARRAY.BUILT = 1 EXECUTE "HUSH OFF" END RESULT = '' FOUND = '' FOR EACH.LIST = 1 TO NUM.LISTS IF TYPE # "S" OR FOUND # "1" THEN LOCATE KEY IN LIST.ARRAY<EACH.LIST,1> SETTING POS THEN IF LEN(OUTPUT) THEN RESULT<1,-1> = OUTPUT<1,EACH.LIST> END ELSE RESULT<1,-1> = LISTS<1,EACH.LIST> END FOUND = 1 END END NEXT EACH.LIST @RECORD = X.PRESERVE.RECORD RETURN END The I-DESC that is used at UCB to determine whether certain IDs are in certain lists is the following, called XMIK.CHK.LISTS: SUBR("XMPE.CHECK.SAVEDLISTS",@ID,SUBR("XMIK.GETCOM","LISTS"),SUBR("XMIK.GETCOM","RESULTS"),'S')… The savedlist array can be cleared, between reports within a single paragraph, with the command: X.CLEARLISTS This subroutine has a single line of code in it, which is all that is needed. The code is: CLEARCOMMON /XCLSTS/