Digital PDFs
Documents
Guest
Register
Log In
EY-AY008-SP-1
1978
258 pages
Original
8.1MB
view
download
Document:
BLISS Primer Volume 2
Order Number:
EY-AY008-SP
Revision:
1
Pages:
258
Original Filename:
OCR Text
EY-AY008-SP-001 BLISS Primer I nterm ediate This course reflects: COMPILERS: BLISS-16c BLISS-32 BLISS-36 Educational Services Digital Equipment Corporation Marlboro, Massachusetts BLISS Primer The information in this document is subject to change without notice and should not be construed as a commitment by Digital Equipment Corporation. Digital Equipment Corporation assumes no responsibility for any errors that may appear in this document. The information in this document is furnished under a license and may be used or copied only in accordance with the terms of such license. Digital Equipment Corporation assumes no responsibility for the use or reliability of its software on equipment that is not supplied by DIGITAL. Copyright @ 1978, 1979 by Digital Equipment Corporation The following Corporation: DIGITAL DEC PDP DECUS UNIBUS COMPUTER LABS COMTEX DDT DECCOM are trademarks DECsystem-10 DECtape DIBOL EDUSYSTEM FLIP CHIP FOCAL INDAC LAB-8 DECSYSTEM-2'" of Digital Equipment MASSBUS OMNIBUS OS/8 PHA RSTS RSX TYPESET-8 TYPESET-I'" TYPESET-Il I LANGUAGE ABSTRACT MODULE 11-1 1I-1-1 BLISS Primer V~lume 2: Intermediate . Language Abstract Course Map II-1-2 BLISS Primer Volume 2: Intermediate Language Abstract Introduction This unit presents BLISS from an abstract, conceptual viewpoint. The language is described in terms of a few very general rules and these rules are contrasted with non-BLISS languages. The presentation assumes a familiarity with BLISS syntax as presented in the prerequisite units. 11-1-3 BLISS Primer Volume 2: Intermediate Language Abstract ---------------Objectives - - - - - - - - - - - - - - - - Given an arbitrary BLISS expression using contructs from the prerequisite units, be able to determine if it is valid and, if so, its val ue • . - - - - - - - - - - - - - - S a m p l e Test Items - - - - - - - - - - - - _ Given that the location A is initially zero, determine whether the following expressions are valid and, if so, their value. 1) X = INCR COUNT FROM 9 TO 4 A = .A + 1; DO 2) (IF.A GTR 9 THEN 2 ELSE 5 ) = .A; ,--------------Additional Resources - - - - - - - - - - - - - . None. 11-1-4 BLISS Primer Volume 2: Intermediate Language Abstract GENERAL This primer has thus far de-emphasized the interaction of expressions in order to emphasize the fundamental concepts of the language. Now that a substantial subset of the syntax has been presented, it is appropriate to examine the general semantics of the language. From a conceptual viewpoint, the language can be described with 2 general rules: 1) 2) Every expression has a value. The context of a value determines its meaning. However, the characteristics of the language which allow this simple generalization and the characteristics which make the language versatile also create the most confusion in the minds of new users. This is why a specific discussion of these rules has been deferred until now. BLISS IS AN EXPRESSION LANGUAGE The statement "BLISS is an expression language" can usually be better appreciated by programmers familiar with an expression language such as LISP, than by programmers familiar with non-expression languages such as FORTRAN. This is at least partially true because users who are not familiar with an expression language tend to associate the term "statement" with the term "expression". As will become apparent, statements and expressions are not at all synonymous. BLISS has three types of expressions: primary, control, and compound. Since primary expressions have not previously been explicitly identified as such, they are depicted below with an example of each: Primary Expressions Examples literal 3 plit PLIT(%ASC1Z'STR',5) name SYM TABLE routine call EXCHANGE (X,Y) block (where the "ens are expressions) (eli structure reference TABLE[5] I1-1-5 e2i e3) BLISS Primer Volume 2: Intermediate Language Abstract Of course, most of these primaries are also available in other languages; however, in non-expression languages they frequently have meaning only in specific contexts. In BLISS they can be used anywhere an expression is permitted. This distinction is very apparent when comparing the allowable expressions in BLISS and non-BLISS control constructs. Control constructs include conditional, case, select, and loop expressions. Although most languages have one or more equivalent constructs, a comparison between expression and non-expression languages as to the type of expression permitted in the various control constructs emphasizes a fundamental difference: BLISS Non-Expression IF expression THEN expression ELSE expression IF Boolean-construct THEN statement ELSE statement WHILE expression DO expression WHILE Boolean-construct DO statement INCR name FROM expression TO expression BY expression DO expression INCR name FROM arithmetic-statement TO arithmetic-statement BY arithmetic-statement DO statement In BLISS, an expression is an expression is an expression. That is to say, there is, in general, no restriction on the type of expression which can be used in the various parts of a control expression. You can, for example, use another control expression as the test condition, permitting constructions like: IF (IF .A THEN ••• ELSE ••• ) THEN ••• ELSE ••• This is not true in many other languages. For example, in other languages, it is common to allow only Boolean constructs in conditional tests (after IF or WHILE), and arithmetic constructs where numeric values are anticipated (after FROM, TO, BY, etc.). The more general BLISS syntax has many advantages. For example, 11-1-6 BLISS Primer Volume 2: Intermediate Language Abstract IF (IF .P NEQ 0 THEN •• P GTR 0 ELSE 0) THEN ••• ELSE ••• forces the test of the pointer p to be performed before using whereas it; IF .P NEQ 0 AND •• P GTR 0 THEN ELSE ••• may not perform the test ".P NEQ 0" first and therefore could result 1n an illegal memory reference on some systems. This conceptual difference between BLISS and non-BLISS-like languages also extends to the creation of compound expressions. Compound expressions result from combining primary and/or control expressions with assignment, arithmetic, Boolean, or relational operators. Compound constructs in BLISS and non-BLISS languages have the general forms shown below: BLISS expression OPERATOR expression (control-expression) OPERATOR (control-expression) non-BLISS arithmetic-expression OPERATOR arithmetic-expression name = arithmetic-expression Note that there are two forms shown for the BLISS and the non-BLISS languages. The second form in each is an exception to the more general rule above it: i.e., in BLISS, control expressions used where a value is required must be enclosed in a block (in this case parentheses); and, in most non-BLISS languages, explicit names are usually required on the left side of an assignment operator. The BLISS exception (control expressions) is illustrated by the following examples: x = (IF condition THEN ••• ELSE ••• ); 11-1-7 BLISS Primer Volume 2: Intermediate Language Abstract and x = (SELECTONE index OF SET [label 1]: expression 1; ... [label n]: expression n; TES); Note: When writing production programs, the VAX-II Software Engineering Manual should be consulted for acceptable coding practices. This is necessary because the misuse of the language, through valid but exotic expressions, creates more problems than it solves: although BLISS will compile exotic constructs, they may be confusing to readers of the code and defeat the purpose of BLISS as an implementation language, or they maybe be confusing to the user and require substantial debugging time. These examples should suggest both the relative simplicity of BLISS, taken in the abstract, and the complexity of the expressions which the language permits you to construct. In order to achieve this generality which permits, among other things, the arbitrary nesting of control constructs, each expression must return a value when used in a context which requires one. EVERY EXPRESSION HAS A VALUE This is perhaps the most significant distinction between an expression language like BLISS and non-expression languages. Non-expression languages tend to be comprised of "statements" which, in general, describe actions to be taken but do not have a value as such. These statements merely perform an operation or step. For example, the assignment TEMP = 256; would store the value 256 at the symbolic address TEMP; however, in non-expression languages the statement itself would have no value. As a result, INCR COUNT FROM 0 TO TEMP = 256 DO BUFF[.COUNT] = TTY_GET_CHAR(); would be meaningless. Non-expression languages 11-1-8 therefore permit BLISS Primer Volume 2: Intermediate Language Abstract only arithmetic expressions in such contexts, since they are the only statements that produce a value. In BLISS an assignment expression (as a entity) has a value, and that value is the same as the value being stored. This means in BLISS that the above example would be equivalent to: INCR COUNT FROM 0 TO 256 DO BUFF[.COUNT] = TTY_GET_CHAR()i with the additional "side-effect" of storing the value 256 in location TEMP. It is therefore common to combine the first test of a value with its assignment to a temporary, e.g., IF (TEMP = TTY_GET_CHAR(» THEN ••• GEQ %0'40' The value of an assignment expression is in fact a fullword bit pattern and need not be a numeric value (logically) as such. For example, the assignment TEMP = PLIT(%ASCIZ'A MESSAGE'); has as its value the address of the PLIT. Since the assignment operator associates to the right, this value could in fact be "reused" by adding yet another level of assignment, PTR = TEMP = PLIT(%ASCIZ'A MESSAGE'); and so on. Rules for determining the operator expressions include: * * * * * * * value of common primary and The value of a PLIT is its address. The value of a name is its address. The value of the fetch operator (".") applied to a name is the contents of the corresponding memory location. The value of a routine call is the value returned by the called routine. The value of a block is the value of the last expression executed in the block. The value of a compound expression made from a relational operator is 1, if true, and 0, if false. The result of a compound expression made from a Boolean operator is the resulting bit pattern. These are relatively straightforward results with exception of a NOVALUE routine call. Because II-1-9 the possible no value is BLISS Primer Volume 2: Intermediate Language Abstract returned, NOVALUE routine calls are therefore not permitted (they are invalid) in any context which requires a value. For example, in the following expressions the NOVALUE routine EXCHANGE is used in an erroneous and invalid manner: EXTERNAL ROUTINE EXCHANGE: NOVALUE; ... A = EXCHANGE (X,Y) + 20; INVALID EXPRESSION IF EXCHANGE (X,Y) THEN expression ELSE expression; INVALID EXPRESSION It is important to note however that these expressions be correct if the routine EXCHANGE returned a value. The rules governing the value of somewhat less intuitive. They include: * * * * control would expressions are For SELECT and SELECTONE: the value of the last (or only) expression evaluated or -1 if none are selected. For CASE: the value of the expression executed or undefined if no match is found. For loops: -1 on normal complet!on or the value of the LEAVE or EXITLOOP. expressIon that terminated the loop. For IF-THEN-ELSE: the value of the THEN or ELSE expression SELECTed. Note that although the defined value of -1 for SELECT/SELECTONE and loop expressions may seem arbitrary, it does provide a means of determining the action taken during execution. For example: TYPE = BEGIN SELECTONE SET [%C 'A ' TO %C'Z']: [%C''''' TO %C'9']: TES; END; ALPHA; NUMERIC; which will read a character, assign it TYPE: 11-1-10 to CHAR, and return in BLISS Primer Volume 2: Intermediate Language Abstract the value of ALPHA if an alphabetic character the value of NUMERIC if a numberic character the value -1 if not alphanumeric The value of any expression is a fullword bit pattern which can be determined by applying the above rules; however, the meaning associated to that value depends entirely upon the context in which the value is used, and not on the way it was generated. THE MEANING OF A VALUE The meaning of a value is determined by the context in which it is used, not by any intrinsic quality of the expression which produces the value. Consequently, the expressions TEMP = %C'S'; TEMP = SAM; TEMP = 10 * 8 + 3; would all have exactly the same value, assuming the address of SAM was decimal 83. In many non-expression languages, special declarations (implicit or explicit) are necessary to store numbers, strings, and addresses since they are thought of as being different kinds of data. Furthermore, identical expressions can have different values depending upon the context in which they are used. For example, the assignment: A = A + 1; In most non-BLISS-like languages the value of A on the left of the assignment operator is its address, whereas the value of A on the right of the assignment operator is its contents. In BLISS the value of a symbolic name is always the same, i.e., an address. Hence, in this example A would be assigned the address of the next memory location - not one more than its present contents. To add one to the contents of A would require the use of the "dot" operator, as follows: A = .A + 1; Although this unit can not discuss all of the implications resulting from these three BLISS rules (abstracted above), a few of the more significant considerations are presented below. II-I-II BLISS Primer Volume 2: Intermediate Language Abstract FURTHER RAMIFICATIONS A common programming requirement is to assign one of two values to a given location depending upon the results of some test. This operation could be diagrammed as, X: * * I Y: * I Z: • where the condition (depicted by the arrow) acts as a switch to direct either the contents of Y or Z to be transferred to X. The code in most languages would be equivalent to: IF condition THEN ELSE X = .Y X = .Z; In BLISS this same sequence can be written equivalently as: X = (IF condition THEN .Y ELSE .Z); The value of the IF statement becomes the value of the selected THEN or ELSE part (i.e., the contents of Y or Z), and this value is in turn stored in X. The syntax corresponds very closely to the diagrammatic logic of the situation. It is important to again note that the control expression has been enclosed in parentheses. This restriction (i.e., having to enclose control expressions used as a value - in a block) is imposed for the user's benefit. It is necessary because of the ambiguity which can and frequently does result without an explicit indication of the end of the ELSE expression. For example, the expression X = IF A GTR B THEN A ELSE B+4; has two possible interpretations: X = (IF A GTR B THEN A ELSE B) + 4; X = (IF A GTR B THEN A ELSE B + 4); 11-1-12 BLISS Primer Volume 2: Intermediate Language Abstract Another common programming requirement is to assign a value to one of two locations, depending on the result of some test. The resulting construct in most languages could be illustrated as: Y: * ..........- - * Z: X: * This would be programmed in most languages as: IF condition THEN Y ELSE = •X Z = • X; BLISS, on the other hand, permits the more direct construction: (IF condition THEN Y ELSE Z) = .X; Observe that the parentheses in this example are essential achieve the intended result, as the expression would interpreted differently without them. to be Expressions in BLISS may be arbitrarily complex and nested to great depths. The block is a good example: BEGIN declarations; ••• expressions; ••• END or equivalently, (declarations; ••• expressionsi ••• ) The block is itself a primary expression, but it can be composed of many more blocks each with many sub-expressions. For instance, (eli e2; e3i ••• (elli e12; e13; eln); ••• en) where each block may also contain its own 11-1-13 separate declarations. BLISS Primer Volume 2: Intermediate Language Abstract It is in fact common practice in BLISS to declare local variables or macros for an inner block. For example: IF ••• THEN BEGIN LOCAL. x, , Y; ... x= Y = END ELSE ••• ... 11-1-14 BLISS Primer Volume 2: Intermediate Language Abstract Exercises Given: A =0 B = %C'S' POSC) - a routine which always returns the value 1 EXCH() - a NOVALUE routine For each expression below, determine its value if reason it is invalid. 1) A = 25 - 5; 2) A = (8 = 5; C = .8 + 5; 3) A = (IF POS () THEN A = 6 ELSE A = 4); 4) A = 5) INCR COUNT FROM A = .A + 1; 6) A = %C '8 ' ; 7) A = EXCH () ; 8) A = IF pas () THEN .8 ELSE .A; 9) A = (SELECT .8 OF SET [%C I S I ] 1; [ %C IT' ] 2; [ %C 10 1 ] 3; [ALWAYS] 4; TES) ; 10) • (A + 5) = 16; 11) 7 = (INCR COUNT FROM o TO 100 DO IF .COUNT GTR 50 THEN EXITLOOP 5 ELSE A = .A + 1) ; o = 0) ; (I F .8 THEN 7) ; 12 ) A = • pas () ; 13) A = (.8 + 1 ; o TO 4 DO ); II-I-IS valid, or the BLISS Primer Volume 2: Intermediate Language Abstract This page intentionally left blank. II-1-16 BLISS Primer Volume 2: Intermediate Language Abstract Solutions 1) 20 2) 0 3) 6 4) invalid (the ELSE part is required when an IF control expression is used as a va~ue) 5) -1 (normal termination) 6) %C'B' (or octal la2) 7) invalid (this context requires a value) 8) invalid (control expressions require parentheses when used in a context which requires a value such as in this assignment) 9) 4 (ALWAYS is last label selected) 10) 16 11 ) 5 12) 13) (the value of EXITLOOP - it is always a premature exit) contents of location one (the expression is equivalent to: A=(.B+l;a);) 11-1-17 BLISS Primer Volume 2: Intermediate Language Abstract. This page intentionally left blank. 11-1-18 BLISS Primer Volume 2: Intermediate Language Abstract Unit Test 1. Given that the contents of A is initially zero in each expression below, determine whether each expression is valid and, if so, its value: a) X = (WHILE .A GTR 15 DO A = .A + 1) ; b) (IF .A GTR c) X = INCR COUNT FROM A = .A + 1; 2. ~ THEN 2 ELSE 5) ~ = .A; TO 4 DO Given: the contents of B = %C'X' the address of B = 112 For each question below, determine the value of each expression: a) SELECT .B OF SET [%C 'B ' ] [%C '0' ] [ %C 'X, ] [OTHERWISE] TES; b) TEMP = B; c) BAND • B; d) .B A = 1; A = 2; B = 3; B = 4; GTR B; II-1-19 BLISS Primer Volume 2: Intermediate Language Abstract This page intentionally left blank. II-1-20 LEXICAL FUNCTIONS MODULE 11-2 11-2-1 BLISS Primer Volume 2: Intermediate Lexical Functions Course Map I I-2-2 BLISS Primer Volume 2: Intermediate Lexical Functions Introduction The lexical string, protect, and macro functions are introduced along with examples. These functions are primarily used with macros although the string functions can be used to simplify certain string processing operations. Conditional macros are also discussed. 1I-2-3 BLISS Primer Volume 2: Intermediate Lexical Functions _-------------Objectives - - - - - - - - - - - - - - - - . Be able to use arbitrary lexical functions correctly in solution to a specified problem involving conditional macros • the . - - - - - - - - - - - - - - Sample Test Items - - - - - - - - - - - -...... Write a program, using a conditional macro named AVG, that accepts an arbitrary number of ·integer arguments and subsequently computes their average. The solution must use at least four different lexical functions • . . - - - - - - - - - - - - - Additional Resources BLISS-32 Language Guide Chapter 16: Lexical Processing Section: 16.2 11-2-4 BLISS Primer Volume 2: Intermediate Lexical Functions Lexical functions are a means of producing or controlling substitutions in the input stream to the compiler. As such, these functions allow the user to create or manipulate literals and symbols in ways which would not otherwise be permitted. One case of lexical substitution occurs in a macro expansion when the macro name (and its arguments) is removed from the input, and the text of the macro is substituted in its place. The final result is as if the text had been typed in the original source code. Although the lexical string functions have some direct application outside of macros, lexical functions are primarily used in conjunction with the macro facility. Since several of the lexical functions have special applications in conditional macros, the latter will be discussed before proceeding to specific lexical functions. CONDITIONAL MACROS A conditional macro has the general form MACRO name (fo rmal-parameters, ••• ) [] = text %; with the expansion contingent upon both the number of formal parameters in the macro definition and the number of actual arguments in the macro call. In general, expansion occurs as long as the number of actual arguments in the macro call equals or exceeds the number of formal parameters in the macro definition. This means that if you define a conditional macro as having two parameters and then call it with five actual parameters, the macro will be expanded twice: once for the first two arguments and once for the second set. No expansion occurs for the third set because only one of the two required arguments was supplied. Examples will be deferred until the specific lexical functions which normally occur in conditional macros are discussed. STRING FUNCTIONS The lexical string functions include: %CHAR %CHARCOUNT II-2-5 BLISS Primer Volume 2: Intermediate Lexical Functions %NAME %NUMBER %STRING The function %CHAR(integer, ••• ) accepts a series of one or more integers, separated by commas, and produces a concatenated string of ASCII characters. For example (using 32-bit architecture): A = %CHAR(79,88); x o A: The function %CHARCOUNT(string, ••• ) accepts a series of string literals, separated by commas, and produces a count of the number of characters in the concatenated strings. For example: A = %CHARCOUNT('A','LONG','STRING'); 11 A: The function %NAME(string, ••• ) accepts a series of string literals and returns a concatenated string that is interpreted as a name. This function is necessary to reference names containing special characters. For example, MACRO SYSCALL = %NAME('.$SYSCALL') %; constructs an equivalent name for an external systems service routine name that begins with a period, even though the period has other meanings in BLISS. Using the macro name, the service routine can then be referenced in a normal manner as shown below: EXTERNAL ROUTINE SYSCALL; ••• SYSCALL(); Since this function accepts multiple string arguments, it is used to construct new names. For example, MACRO LOCAL SYM(A)= LOCAL %NAME('LOC_',(A» ... %; LOCAL_SYM('VEC'); 11-2-6 also BLISS Primer Volume 2: Intermediate Lexical Functions concatenates the strings LOC and VEC to produce the declaration: LOCAL LOe VEC; The function %NUMBER(item) accepts either a string literal or a literal name and returns the appropriate decimal value. For example: LITERAL TYPE A = 3; .. . A = %NUMBER(TYPE_A); 3 A = %NUMBER('65'); 65 The function %NUMBER has meaningful conjunction with macros. For example, MACRO CTRST(A,B) = OWN %NAME«A), %NUMB~R(B» accepts a literal name or a numeric macro calls of the form: application only in %; literal and makes possible LITERAL TYPE_A = 3; CTRST('LVAL_' ,TYPE_A); to produce: OWN LVAL_3; The last lexical string function is %STRING(string, ••• ) which concatenates multiple string literals, separated by commas, into a single string literal. This function is useful in creating strings which require special characters that could not otherwise be incorporated. For instance, . TTY_PUT_QUO(%STRING('EXIT LINE ',%CHAR(%O'15',%O'12'»); would output to the terminal the string "EXIT LINE " followed by a carriage return and line feed. As shown in the above example, lexical functions may be nested arbitrarily, one 'inside the other. 11-2-7 BLISS Primer Volume 2: Intermediate Lexical Functions It is important to emphasize that lexical functions effect a substitution by the processor which occurs before compilation. This is depicted below using a few of the previous examples: Before Lexical Processing After Lexical Processing A = %CHAR(79,88); A = %CHARCOUNT (' A' , 'LONG I , I STRING I ) ; A = 'OX'; A = 11; " Therefore an expression like A = %CHAR (. TEMP) ; is invalid because ".TEMP" (the contents of location TEMP) value until run-time. has no In general, there are three types of lexemes in a macro: string literals names numeric literals ( i • e ., %C' A " , GO', etc) ( i • e ., A, F00 , etc.) (i.e., 1, 345, etc.) In conjunction with macros, it is often necessary or desirable to convert from one type of lexeme to another when the type of the desired result is known but the type of the argument is not. The following table summarizes the possible arguments and their result: Function Argument type Result %STRING (st ring-l i teral) same ( name) concatenation of each character in the name taken in textual order (numeric-literal) the character representation of the numeric literal (string-literal) name corresponding to the string (name) same (numeric-literal) %NAME(%STRING(numericliteral)) %NAME II-2-8 BLISS Primer Volume 2: Intermediate Lexical Functions %NUMBER (string-literal) %DEC1MAL'string-literal' (I i teral value of the literal name name) PROTECT FUNCTIONS Without the protect functions, many useful applications of the macro facility would be made more difficult if not impossible. For example, an attempt to pass, in a macro call, an argument which contained a comma, as in FUNC(A,B); FUNC ( ,) ; would not succeed. The first call would be interpreted as two arguments (A and B) rather than one (A,B), and the second would also have two parameters, both null. Furthermore, it would not be possible to nest macro declarations since the attempt to end the inner macro declaration with a "%" would terminate the outermost macro and generate subsequent compiler errors because the leftover code would not be syntactically correct. The following nested macros illustrate this problem: = MACRO FMA(X) MACRO FMB = text %; %; The lexical functions %QUOTE and %UNQUOTE are therefore expedient. The function %QUOTE prevents the next lexeme (i.e., an entity such as a" keyword, name, literal, string, delimiter, etc.) from being interpreted (bound) until it is expanded at the time of the macro call. This function provides the needed mechanism to pass parameters that contain a comma or another delimiting character as part of the argument. For example, the macro calls on FUNC above can now be correctly written as: FUNC(A %QUOTE, B); FUNC(%QUOTE,); Similarily, the nested macros above would be written: MACRO FMA(X) = MACRO FMB = text %QUOTE %; 11-2-9 BLISS Primer Volume 2: Intermediate Lexical Functions ••• %; The function %UNQUOTE has the opposite effect. That is, the lexeme following the function is lexically bound in the current block. This is used to associate a name to the declaration in effect within the current block. Normally, a name is not bound to an address until the time that the macro is expanded; at that time, the name is associated with the appropriate declaration in effect in that block. The following code demonstrates this application: BEGIN OWN X; MACRO MES(A) = BEGIN LOCAL X; X = PROC(.A); END; %; BEGIN ~N X; MES(X); END; MES(X); END; This example has two calls on the macro MES, both in different blocks. Since the name X has been redeclared twice, three distinct locations for X are possible; however, X will always refer to the local declaration of X in the macro. To force X to refer to the declaration in effect within the block declared, the function %UNQUOTE can be used. Using %UNQUOTE in the call causes X to be bound to the declaration in effect in the block the macro was declared. For example, BEGIN OWN X; MACRO MES(A) = LOCAL 11-2-10 BLISS Primer Volume 2: Intermediate Lexical Functions X; X = PROC ( .A) %; MES (%UNQUOTE X); END; causes the argument A in the macro to refer to the declaration of X contained in the call, rather than the declaration of X in the macro. MACRO FUNCTIONS The macro lexical functions are defined only for use macro body itself. They include these three functions: in the %COUNT %LENGTH %REMAINING The function %REMAINING is frequently used with conditional macro calls because it provides a means to obtain the actual arguments in excess of the number declared. The value of the function is the list of arguments that are in excess of those required for the present copy (incarnation) of the macro. Consider, for example, the recursive macro below which has two formal parameters (X and Y): MACRO MAC(X,Y) [] = X = ALPHA (Y ) ; MAC(%REMAINING)%; If this macro were called with four actual arguments as in, MAC(A,B,C,D); it would produce as its first copy A = ALPHA (B) ; MAC (%REMAINING) (where %REMAINING equals "C,D") then as its second copy A = ALPHA (B); C = ALPHA(D); MAC (%REMAINING) where %REMAINING equals null. Since the final 11-2-11 call to MAC has BLISS Primer Volume 2: Intermediate Lexical Functions fewer arguments than the formal parameters declared, the value of the macro call is null, and the final result of the call would be: A = ALPHA (B) ; C = ALPHA (D) ; The %COUNT function is also used with both recursive and conditional macros and returns the number of the current copy of the macro. The orginal is given number, 0, the first copy, 1, etc. For example, the conditional macro MACRO IUC(X) [] = FUNC IUC(X,%COUNT); IUC(%REMAINING)%; generates a new copy for each argument in the macro call, and for each copy, %COUNT is incremented and that value substituted for %COUNT. Hence, the macro call IUC(A,B,C); expands as: FUNC IUC (A, 0) ; FUNC-IUC (B, 1); FUNC=IUC (C, 2) ; The function %LENGTH on the other hand returns as its value the number of actual parameters passed in that call. For example, MACRO MMC(X,Y,Z) = IF %LENGTH NEQ 3 THEN TTY PUT QUO('REQUIRES THREE ARGUMENTS ••• ') ELSE BEGIN AVERAGE = .X + .Y + .Z; AVERAGE = .AVERAGE / 3; END %; when called with MMC(A,B,C); would produce: AVERAGE = .A + .B + .C; AVERAGE = .AVERAGE / 3; I I-2-12 BLISS Primer Volume 2: Intermediate Lexical Functions Note that the IF expression is not generated in the final form of this example.' Since %LENGTH is a lexical function, the macro expansion at compile time for the above call would be: IF 3 NEQ 3 THEN TTY PUT_QUO('REQU1RES THREE ARGUMENTS ••• ·) ELSE BEGIN AVERAGE = .A + .B + .C; AVERAGE = .AVERAGE / 3; END; Because the test condition in this case (3 NEQ 3) is a constant zero (i.e., false), only the code for the ELSE part would be generated. In general, you can expect a conditional expression to disappear without warning if the test condition is constant. This results from optimizations that occur at compile time. 11-2-13 BLISS Primer Volume 2:· Intermediate Lexical Functions This page is for notes. II-2-14 BLISS Primer Volume 2: Intermediate Lexical Functions Exercises 1. Given the macro: MACRO CEX (A, B) [] = A = • A + %C OUNT ; A = BETA(B) / %LENGTH; CEX(%REMAIN1NG)%; Determine the expansion which would result from the macro call: CEX(R, S %QUOTE, 3, T, W) 2. Determine expression: the output to the TTY of the following 1NCR COUNT FROM %CHAR(%O'60') TO %CHAR(%O'66') BY 2 DO TTY_PUT_CHAR(.COUNT); 3. Determine the value of the expre'ssion: %CHARCOUNT(%CHAR(l2,13,14,15»; 11-2-15 BLISS Primer Volume 2: Intermediate Lexical Functions This page intentionally left blank. 11-2-16 BLISS Primer Volume 2: Intermediate Lexical Functions Solutions 1) R = .R + 0; R = BETA(S,3) / 4; T = .T + Ii T = BETA(W) / 2; 2) 0246 3) 4 II-2-17 BLISS Primer Volume 2: Intermediate Lexical Functions This page intentionally left blank. II-2-l8 BLISS Primer Volume 2: Intermediate Lexical Functions Unit Test Write a program, using a conditional macro named AVG, that accepts an arbitrary number of integer arguments and subsequently computes their average which is stored at the predeclared symbolic address AVERAGE. Obtain the average by dividing the sum of the arguments by the number of arguments (you do not have to round-off the result). Show a call to AVG which directs the output to the terminal. The solution must use at least four different lexical functions. 11-2-19 BLISS Primer Volume 2: Intermediate Lexical Functions This page intentionally left blank. CHARACTER HANDLING FUNCTIONS MODULE 11-3 11-3-1 BLISS Primer Volume 2: Intermediate Character Handling Functions Course Map 11-3-2 BLISS Primer Volume 2: Intermediate Character Handling Functions Introduction The built-in character handling functions are introduced. These functions allow the user to build and manipulate character sequence pointers; to manipulate, compare, search, and move character strings; and to perform character translation. II-3-3 BLISS Primer Volume 2: Intermediate Character Handling Functions ---------------Objectives------------------. Given a problem which requires the manipulation of character sequences, be able to write a solution which correctly uses an arbitrary number of character handling functions. - - - - - - - - - - - - - - Sample Test I t e m s - - - - - - - - - - - - - - - , Write a routine'which, when passed the address of an ASCIZ string (having less than l~~~ characters) and the address of a work area: 1) 2) 3) translates each character in the string into its equivalent stores the resulting translation in a work area terminates the string with a null character The solution should use at least 5 functions. different character Radix-5~ handling Additional Resources BLISS-32 Language Guide Chapter 2~: Se c t ions: II-3-4 Character Handling Functions all BLISS Primer Volume 2: Intermediate Character Handling Functions The character handling functions are built-in functions. As such, the syntax for invoking them is the same as that for calling a routine. An actual routine call, however, does not necessarily take place; usually, the necessary code will be generated in-line, saving the overhead of a routine call. These functions are the preferred method of dealing with characters in BLISS, replacing most of the direct manipulation techniques employed in the examples and exercises throughout the introductory units. They provide code efficiencies as well as being functionally equivalent between machine types. The character functions are discussed below in groups of general class of facilities they provide. the FUNCTIONS USED IN ALLOCATING STORAGE A character sequence, sometimes referred to as a "string", is any series of coded characters stored. contiguously in memory. Allocating storage to hold such character sequences is ordinarily the. responsibility of the user. To assist the user, two functions have been provided: CH$ALLOCATION CH$SIZE The function CH$ALLOCATION(length, character-size) returns the number of fullwords needed to represent a sequence of a given character length (in number of characters) and a specified size in bits per character. The returned value is: (number-of-characters + 3) / (characters-per-fullword) For example, if storage for a character sequence is allocated by means of a vector and the length of the sequence is 45 characters then OWN CH_STORE:VECTOR[CH$ALLOCATION(45)]i will produce the correct storage allocation. Character size second argument) is optional and has the following defaults: BLISS-32 ••••• IS A CONSTANT: 8 BLISS-16 ••••• IS A CONSTANT: 8 BLISS-36 ••••• VARIABLE FROM I TO 36 BITS (DEFAULT: 7) II-3-5 (the BLISS Primer Volume 2: Intermediate Character Handling Functions The function CH$SIZE(source-pointer) returns bits per character. FUNCTIONS THAT BUILD CS-POINTERS the AND number of MANIPULATE A character sequence is specified by two numbers: a character sequence pointer (CS-pointer) which points to the start of the sequence, and its length in number of characters. The three functions which deal with character sequence pointers are: CH$PTR CH$PLUS CH$DIFF The function CH$PTR(address, position-index, character-size) builds a CS-pointer. It returns as its value a CS-pointer which represents the beginning address of the sequence plus an offset to the specific character in the sequence. The position index is the offset, or number of character positions from the initial address, and if not specified, it defaults to zero; size is the number of bits per character, and it defaults to eight (BLISS-l6/32) or to seven (BLISS-36). The function CH$PLUS(CS-pointer, index) performs logical addition on the CS-pointer, incrementing it by the specified number of characters. It returns a CS-pointer to the subsequent beginning, now "index" number of characters from the original CS-pointer. The function CH$DIFF(CS-pointer-l, CS-pointer-2) performs logical subtraction on a pair of CS-pointers and an integer index. For example: returns OWN !POINTER STORAGE !POINTER STORAGE IOTHER STORAGE CSP, CSP2, INDEX; CSP = CH$PTR (PLIT (' EXAMPLE') ) ; lCSP CONTAINS A ! CS-POINTER WHICH 1 POINTS TO THE INITIAL 11-3-6 BLISS Primer Volume 2: Intermediate Character Handling Functions ! E IN 'EXAMPLE' CSP2 = CH$PLUS(.CSP, 5); !CSP2 CONTAINS A CS-POINTER WHICH POINTS TO THE L IN 'EXAMPLE' INDEX = CH$DIFF (.CSP, .CSP2); !INDEX CONTAINS INTEGER 5 Many functions return a CS-pointer. The function CH$PTR creates a CS-pointer while other functions, such as CH$PLUS, return an updated CS-pointer. In either event, it is the responsibility of the user to insure that the correct length stays associated with each CS-pointer. This is essential because the length of the source and/or destination pointer is required as an input argument in several of the following character handling functions. FUNCTIONS WHICH MANIPULATE CHARACTERS The two basic functions which manipulate characters are: CH$RCHAR CH$WCHAR The read function CH$RCHAR(source-CS-pointer) fetches the character referenced by the given pointer the CS-pointer itself unchanged. but leaves The write function CH$WCHAR(character, destination-CS-pointer) stores the indicated character at the location referenced by destination pointer, again leaving the pointer unchanged. ex ample: OWN !CHARACTER STORAGE CHI, CH2, CSP, DSPi !SOURCE POINTER !DESTINATION POINTER 11-3-7 the For BLISS Primer Volume 2: Inter,mediate Character Handling Functions CSP = CH$PTR (P'LIT (' EXAMPLE') ); lCSP IS A CS-POINTER TO ! THE STRING 'EXAMPLE' DSP = CH$PTR(CH2); !DSP IS A CS-POINTER TO ! CH2 CHI = CH$RCHAR(.CSP); CH$WCHAR(.CHI,.DSP); !CSP STILL POINTS TO E !DSP STILL POINTS TO FIRST CHARACTER POSITION IN CH2 Note that the CS-pointers remain unchanged. That is, the value of the pointer after executing the function is exactly the same as the original pointer. Two such calls in succession would therefore read (or write) the same character position twice. These functions, with the appropriate extension, can also be used to advance the CS-pointer during the read or write operation. If the CS-pointer is to be advanced after the read or write occurs, a "A" is appended to the function name; if it is to be advanced befo~e performing the indicated operation, a "A" is prefixed to the function name after CH$. As these functions update the CS-pointer, in addition to returning a character value, they require the ADDRESS of the CS-pointer as their argument, rather than its current value. Each function advances the CS-pointer at the appropriate time and updates the pointer location. For example, continuing from the above illustration: CHI = CH$A_RCHAR(CSP); !CSP POINTS TO X CH$WCHAR_A(CH$RCHR(.CSP), nsP); !DSP POINTS TO CH~+1 = CH$PLUS(.CSP,I)i !CSP POINTS TO A CHI = CH$RCHAR~(CSP)i rcsp POINTS TO M CH$WCHAR (I I I , • nsP) ; !DSP POINTS TO CH2+1 CH$A_WCHAR(CH$RCHR(.CSP), nsP); !nsp POINTS TO CH2+2 CSP CHI = CH$RCHAR_A(CSP)i !CSP POINTS TO P Note that it is only the " A" and "A "forms of these functions which require the address-of the CS-pointer. character functions take the value of the CS-pointer. FUNCTIONS WHICH INITIALIZE AND MOVE CHARACTER STRINGS 11-3-8 character All other BLISS Primer Volume 2: Intermediate Character Handling Functions The following three functions move and strings: initialize character CH$MOVE CH$COPY CH$FILL The function CH$MOVE(length, source-pointer, destination-pointer) is used for another. copying a character sequence from one place to The function CH$COPY(length-l, source-pointer-l, ••• ,length-n, source-pointer-n, fill-character, destination-length, destination-pointer) copies the concatenated character sequences to the given destination, filling unused positions with the fill character. Since this function accepts an arbitrary number of arguments, the last three arguments are always assumed to be the fill character, the destination length, and the destination pointer (in that order) • The value of the CH$MOVE and CH$COPY functions is a CS-pointer referencing the destination character position following the last character moved. The function CH$FILL(fill-character, length, destination-pointer) is used for initializing a character sequence. The value of this f uncti on is a CS-po inter referenc ing the' destination character position following the last character filled. To illustrate these functions, assume the following declarations (BLISS-32): OWN CSP, DSP, CSP2, WKSP:VECTOR[CH$ALLOCATION(100)]; BIND STP = UPLIT( PLIT BYTE PLIT BYT E PLIT BYTE PLIT BYTE ('NOW'), (' IS' ) , ('THE '), ('TIME I»~ 11-3-9 !SOURCE POINTER !DESTINATION POINTER !SECOND SOURCE POINTER !WORKING STORAGE BLISS Primer Volume 2: Intermediate Character Handling Functions : VECTOR [4]; and the CS-pointer assignments: DSP = CH$PTR(WKSP[0]); CSP = CH$PTR(.STP[3]); !CS-POINTER TO WORK ! AREA ICS-POINTER TO T IN ! THE STRING 'TIME' ICS-POINTER TO I IN THE STRING 'IS' CSP2 = CH$PTR(.STP[l]); With these declarations and assignments, the expressions CH$FILL (%C' " IFILL WORK AREA WITH ! SPACES 100, • DSP) ; DS P = C H$M OVE (5 , • CS P, • DS P) ; !MOVE 'TIME ' TO ! WKSP [0-4] !DSP POINTS TO WKSP[5] DSP = CH$MOVE(3,.CSP2,.DSP); !MOVE 'I S TO ! WKSP[5-7] !DSP POINTS TO WKSP [8] , and the expression DSP = CH$COPY (5, .CSP, 3, .CSP2, %C' " 100, .DSP); both produce the same result in the work space WKSP and the string "TIME IS II FUNCTIONS TO COMPARE CHARACTER SEQUENCES The following six functions are sequences: CH$GTR CH$GEQ CH$LSS CH$LEQ CH$EQL CH$NEQ The general form of these functions is 11-3-10 used to compare character BLISS Primer Volume 2: Intermediate Character Handling Functions CH$xxx(length-l, CS-pointer-1, 1ength-2, CS-pointer-2, fill-character) where xxx indicates one of the relational operators (e.g., LSS, LEQ, etc.) and the fill character defaults to 0. These functions perform character-by-character comparisons, so that: IF .CS-pointer-l xxx .CS-pointer-2 THEN 1 ELSE o For example, using the plit STP above, CH$N EQ (2 , • CS P , 2 , • CS P 2) ; returns the value 1 (for true). Alternatively, IF CH$NEQ (2, .CSP, 2, .CSP2) THEN TTY PUT QUO (' TRUE I ) ELSE TTY_PUT_QUO('FALSE'); outputs to the terminal the string 'TRUE'. FUNCTIONS USED TO SEARCH SEQUENCES The following four character sequences: functions are provided for searching CH$FINO SUB CH$FINO-CH CH$FINO-NOT CH CH$FAILTh e funct i on CH$FIND_SUB(length-1, CS-pointer-l, 1ength-2, CS-pointer-2) searches the sequence described by CS-pointer-l and length-l for the first occurrence of an embedded subsequence precisely identical to the sequence described by CS-pointer-2 and 1ength-2. 11-3-11 BLISS Primer Volume 2: Intermediate Character Handling Functions The function CH$FIND_CH(length, CS-pointer, character) searches the sequence described by the CS-pointer and the length for the first occurrence of the specified character. given Conversely, the function CH$FIND_NOT_CH(length, CS-pointer, character) searches for the first occurrence of a character not equal to the specified character. All three functions return either a CS-pointer referencing the matched subsequence/character or a null, if no match occurs. The function CH$FAIL(CS-pointer) is used in conjunction with these three functions to CS-pointer so that its value is: examine the !EQUAL TO NULL POINTER IF CS-pointer EQL 0 THEN 1 ELSE o The following example uses the plit STP (above) to d~monstrate the CH$FAIL function: !+ THIS LOOP SEARCHES FOR THE SUBSTRING' 'ME' IN EACH ENTRY IN THE PLIT STP 1- INCR I FROM 0 TO 3 DO BEGIN LOCAL FOUND PTR, LENGTH; MACRO PLIT LENGTH (APLIT)= ~«APLIT)-4) %i BIND ME = PLIT('ME'); 11-3-12 BLISS Primer Volume 2: Intermediate Character Handling Functions LITERAL ME SIZE = %CHARCOUNTC'ME'); CSP = CH$PTR(.STP[.I]); LENGTH = PLIT LENGTH(.STP[.I]) * 4; FOUND PTR = CH$FIND SUB(.LENGTH, .CSP, ME_SIZE, CH$PTR(ME); IF NOT CH$FAIL(.FOUND PTR) THEN EXITLOOP; END; This example returns a CS-pointer in CSP (on the fourth iteration) to the character M (matched in .STP[3]). FUNCTIONS USED TO PERFORM CHARACTER TRANSLATION The two functions translation are: which are used to perform character CH$TRANSTABLE CHSTRANSLATE The first builds a translate table; character by character translation. the second performs a The function CH$TRANSTABLE(translation) builds a translation table at compile time. The translation syntax is the same as that for plits except that it must not include an allocation unit and it is limited to 256 characters. The function CH$TRANSLATE(translate-table, length, source-pointer, fill-character, length, destination-pointer) performs the actual transformation. Each character in the source sequence is interpreted as an index in the translation table, and the corresponding character in the table (at that index) is moved to the destination string. If the destination sequence is longer than the source sequence, the destination is filled with the specified fill character. The value of the function is a CS-pointer referencing the character following the last character 11-3-13 BLISS Primer Volume 2: Intermediate Character Handling Functions moved into the destination translation table sequence. For example, given the BIND TBL = CH$TRANSTABLE(REP 36 OF (0) , 38, 39, REP 8 OF (0) , 37, 0, 1, 2, 3, 4, 5, 6, 7, REP 7 OF (0) , 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 27, 28, 29, 30, 31, 32, 35, 36, REP 37 OF (0) ) ; the routine 8, 9, 10, 17, 18, 25, 26, 33, 34, ROUTINE ASCII TO RAD50(CSP,DSP): NOVALUE = CH$TRANSLATE(TBL, 1, .CSP, 0, 1, .DSP); when passed the source pointer to a seven bit ASCII character and a destination pointer, will write the corresponding RADIX-50 character representation to the destination address. Zero will be written for any character not in the Radix-50 set. 11-3-14 BLIS S P rim e r Vo 1 urn e 2: In term ec:i ate Character Handling Functions Exercises 1. Write a translation table called NR TBL which will translate a number from zero to nine into its ASCII equivalent, e.g., to octal 60, 1 to octal 61, etc •• ° 2. Given the address of an ASCIZ string (stored in ADDR), determine how many characters the first word (i.e., to the first space) contains. Assume the string starts with the first character of the word. 3. Determine the final result in after excuting the following code: TBL OWN TBL: VECTOR [5] , CSP, DSP, CHAR; DSP = CH$PTR(TBL); CSP = CH$PTR(PLIT('POINTER •••• '); CH$COPY(7,CH$PLUS(.CSP,3),0,8,.DSP); CH$FILL(%C'D',4,.DSP); CHAR·= CH$A RCHAR(CSP); CH$A WCHAR(~CHAR,DSP); CSP ; CH$PLUS(.CSP,2); CHAR = CH$RCHAR A(CSP); CH$A WCHAR(.CHAR,.DSP); CH$A=WCHAR(CH$A_RCHAR(CSP),DSP); 11-3-15 (list as a string) BLISS Primer Volume 2: Intermediate Character Handling Functions This page intentionally left blank. 11-3-16 BLISS Primer Volume 2: Intermediate Character Handling Functions Solutions 1) BIND 2) OWN NR TBL = eH$TRANSTABLE(48,49,5~,51,52,53,54,55,56,58)i esp, NRi CSP = CH$PTR (.ADDR) i NR = CH$DIFF(.esp,eH$F1ND_eH(5~,.esp,'O·4~·»i 3) The ASC1Z string: DONE ••• 11-3-17 BLISS Primer Volume 2: Intermf:~d iat,! Character Handl ing Funct i()n~; This page intentionally left blank. BLISS Primer Volume 2: Intermediate Character Handling Functions Unit Test Write a routine which, when passed the address of an ASCIZ string (having less than 1000 characters) and the address of a work area: 1) 2) 3) translates each character in the string into its Radix-50 equivalent stores the. resulting translation into a work ar,ea terminates'the string with a null The routine should use at least five different character functions. 11-3-19 handling BLISS Primer Volume 2: Intermediate Character Handling Functions This page intentionally left blank. 11-3-20 DATA STRUCTURES MODULE 11-4 II-4-1 B~ISS Primer Volume 2: Intermediate Data Structures Course Map 11-4-2 BLISS Primer Volume 2: Interme·liate Data St ructures Introduction This unit introduces the STRUCTURE declaration along with the related MAP declaration and REF attribute. The STRUCTURE declaration permits the user to define an arbitrary data structure; the MAP declaration associates a new accessing algorithm to existing storage; and the REF attribute simplifies indirect references to a structure. 11-4-3 BLISS Primer Volume 2: Intermediate Data Structures ---------------Objectives --------------------"11 Given an arbitrary data structure, be able to use the STRUCTURE declaration to create an accessing algorithm for that structure. - - - - - - - - - - - - - - Sample Test Items - - - - - - - - - - - - - - - . Write a STRUCTURE declaration that implements a three dimensional array MATX3[row,co1umn,p1ane], so that MATX3[1,2,~] references the second row, third column of the first plane. Show the declaration which allocates the storage and also a subsequent reference to the third column of the fifth row of the fourth plane. Additional Resources Chapter 12: Data Structures Sections: 12.3 and 12.7 BL1SS-32 Language Guide 11-4-4 BLISS Primer Volume 2: Interr·:·ediate Data Structures BLISS provides the capability to implement any arbitrary data structure. This is accomplished with the STRUCTURE declaration which permits the user to define an accessing algorithm for a given storage. As such, the accessing algorithm is simply an expression that returns an address based upon the access formal(s) for each reference. This declaration can also be used to compute the storage required for allocation of such a structure. The predefined structures introduced earlier have been declared using this declaration mechanism. They are, in a sense, declared in an outer block of the user's program and, therefore, accessible from any block in the program. Since these structures should be familiar to most users, they are used as examples throughout this unit to illustrate the STRUCTURE declaration. STRUCTURE FORMALS The general form of the STRUCTURE declaration is: STRUCTURE name[access-formalsi allocation-formals] = (structure-size] (accessing-algorithm) <field-selector>; As depicted in this declaration, there are two types of formal parameters: access formals, which are derived from the arguments used at the time of a structure reference, and allocation formals, which are constants derived from arguments at the time the structure is allocated. These formals a·re separated by a semicolon with access formals on the left and allocation formals on the right. For example, ' STRUCTURE VECTOR [I iN] = ••• has one access formal, I, and one allocation formal, time of the storage declaration N. At the OWN TABLE: VECTOR[101i each occurrence of the allocation formal N is replaced by the allocation actual of 10. This is a one-time substitution. Similarily, the reference TABLE[5l 11-4-5 BLISS Primer Volume 2: Intermediate Data Structures causes each occurrence of the access formal I to be replaced by the access actual of five in the accessing algorithm. The distinction is that allocation formals, once declared, are constants which do not change value; whereas access formals can vary with each access reference to the structure. The user has an option of assigning default values for allocation formals. This is achieved by assigning a value to the formal. For example, STRUCTURE VECTOR[I;N,UNIT=4] = ••• designates UNIT as having a default value of four. Consequently, if only one allocation actual were given in the storage declaration, the default value four would be substltuted for each occurrence of UNIT. STORAGE ALLOCATION The next part of the STRUCTURE declaration is an optional size component that is used to compute the amount, in bytes (BLISS-16/32) or words (BLISS-36), of storage to be allocated. For example (BLISS-32), . STRUCTURE VECTOR[I;N,UNIT=4] = [N *UNIT] ••• when invoked within the storage declaration OWN TABLE: IVECTOR OF WORDS VECTOR[1~,2]; allocates 20 bytes [10 * 2] or symbolic name TABLE; whereas l~ OWN TABLE: words of storage with the IVECTOR OF LONGWORDS VECTOR[l~]; allocates 4~ bytes [10 * 4] or l~ longwords. Note that in the latter example, the default value for UNIT was used since only one allocation actual was provided. In a routine call, parameters are evaluated and stored at a temporary location given by the applicable symbolic name of the formal parameter. This is not the case in either macros or 11-4-6 BLISS Primer Volume 2: Intermediate Data Structures structures where access actuals are substituted directly for the appropriate formal. As a consequence, the dot operator is not used to obtain the value of the access actual as is done in routines. That is, the following is erroneous, [. N * • UNIT] if the value of N or UNIT is required. Because a user may want to allocate structures in bytes, words, and longwords, the keywords BYTE, WORD, and LONG are predefined as literals having the values 1, 2, and 4 respectively when used as structure actuals or formals. (BLISS-l6 does not recognize "LONG", while BLISS-36 recognizes only "WORD".) Consequently, the declarations OWN TABLE: VECTOR[10,BYTE], STORE: VECTOR[10,LONG]; IVECTOR OF .BYTES IVECTOR OF LONGWORDS are equivalent to: OWN TABLE: VECTOR[10,1], STORE: VECTOR[10,4]; IVECTOR OF BYTES !VECTOR OF LONGWORDS ACCESSING ALGORITHM The third part of a STRUCTURE declaration is the actual accessing algorithm or structure body. It ,is this algorithm that determines the address for each reference made to a specific log ical element of the structure. For": example, the· STRUCTURE declaration for a vector of longwords (BLISS-32) could be written: STRUCTURE L VECTOR [I iN] - [N *4] = (L_VECTOR + I * 4); The subsequent storage declaration OWN TABLE: L_VECTOR[100]; would then result in the allocation formal being replaced, producing: 11-4-7 (in this example N) RLISS Primer Volume 2: Intermediate Data Structures STRUCTURE TABLE [I ;N] = [1""*4] (TABLE + I * 4); 1"" This results in longwords being allocated and in producing an algorithm where only the access formals remain to be determined. In a reference, such as TABLE[S]; the access actual (in this example, the argument five) replaces the access formal (in this example the parameter I), and the address resulting from the accessing algorithm is substituted in place of the reference producing the address: (TABLE + S * 4); FIELD SELECTOR The final component of the STRUCTURE declaration is the field selector. In BLISS the user has the capability to reference and/or access any size field within a fullword. This is accomplished with a field selector enclosed in "()" of the form, (position, size, sign) where position is an offset in bits from the address designated by the symbolic name; size is the number of bits in the field; and sign is the extension rule which applies to the field (zero extension or sign extension). For this purpose, the keywords SIGNED and UNSIGNED when used in structures are predefined literals with the values 1 and ~ respectively. The sign default is UNSIGNED. Note that BLISS-36 supports WORDs only; the zero-extension vs. sign extension is meaningless for such word-sized elements. For example, assume a variable named FLAG contains following bit pattern as the result of the assignment: F LA G = %0' 6 S ' ; the 1 ••• 0110101 To depict the resulting bit patterns, the rightmost digit (in this example 1) represents bit zero; the digit to its left, bit one, and so forth. The three dots at the left of the pattern indicate that the remaining bits in the longword (through bit 31) are the 11-4-8 BLISS Primer Volume 2: Intermediate Data Structures same as the leftmost digit shown (in this case 0). Therefore, the reference 1 ••• 0110101 FLAG<4,3> represents an unsigned field (by default) starting at the fifth bit (bit four) and extending for three bits through the seventh bit (bit six). As might be apparent, every reference to a name not declared as a structure and not having an extension attribute (SIGNED/UNSIGNED) or an allocation unit (BYTE, WORD, OR LONG) contains an implied field selector. The default values are: BLISS.:..16: BLISS-32: BLISS-36: <0,16,0> <0,32,0> <0, 36, 0>. This means that the assignments (in, say, BLISS-36) FLAGS = .SAVE_FLAGS; and FLAGS<0,36,0> are equivalent. ass ignment SAVE FLAGS = .SAVE_FLAGS<0,36,0>; As FLAG now contains the value 53 (octal 65), the = .FLAG<4,3>; ! ••• 01l sets SAVE FLAGS to the value three. Note that fields are always filled from right to left (left to right in BLISS-36) and that 1) if the receiving field is larger than the sending field, the unspecified bits are set to zero; whereas 2) if the receiving field is smaller than the sending field, the leftmost bits of the sending field are truncated. The application of these rules is ex amples : SAVE FLAGS = .FLAG<0,6>; SAVE-FLAGS<0,4> = 0; SAVE=FLAGS<0,S> = .FLAG<0,1>; illustrated in the following ! ••• 0ll0l0l 1 ••• 0110000 1 ••• 0100001 In actual practice, however, field selectors are only rarely 11-4-9 used BLISS Primer Volume 2: Intermediate Data St ructures in a direct assignment expression. They usually appear as the last component of a STRUCTURE declaration where the same effect can be achieved without cluttering in-line code. VECTOR STRUCTURE The BLISS-32 VECTOR structure is predefined as: , STRUCTURE VECTOR[I;N,UNIT=4,EXT=0] = [N*UNIT] (VECTOR + I * UNIT)<0,8*UNIT,EXT>; The definition of this structure permits a vector. of signed or unsigned bytes, words, or longwords. As examples, the declaration OWN BYTE TABLE: VECTOR[10,BYTE], WORD-TABLE: VECTOR[10,2,SIGNED], LONG-TABLE: VECTOR[10]; !UNSIGNED BYTE VECTOR !SIGNED WORD VECTOR !UNSIGNED LONGWORD ! VECTOR * 1] 110 BYTES 110 WORDS ! 10 LONGW ORDS allocates [10 [10 [10 * 2] * 4] and defines the accessing algorithms: (BYTE TABLE + 1 * 1)<0,8*1,O> (WORD-TABLE + I * 2)<O,8*2,1> (LONG-TABLE + 1 * 4)<0,8*4,O> !BYTE FIELDS lWORD FIELDS !LONGWORD FIELDS Compare this declaration to the BLISS-16 VECTOR declaration: STRUCTURE VECTOR[I;N,UNIT=2,EXT=0] = [N*UNIT] (VECTOR+I*UNIT)<0,S*UNIT,EXT>i and the VECTOR declaration for BLISS-36: STRUCTURE VECTOR [I iN] = 11-4-10 BLISS Primer Volume 2: Data Structures Interm~diate [N] (VECTOR+I)<~,36>; (Note that the VECTOR structure declaration for BLISS-36 is simplified due to the lack of a need to specify the Allocation Unit default value.) BITVECTOR STRUCTURE The BITVECTOR structure is predefined in BLISS-32 as: STRUCTURE BITVECTOR[I;N] = [ (N+7) /8] B ITVECTOR <I ,1>; Note that storage declaration is always allocated in bytes so that the OWN SWITCH 1: BITVECTOR[l~]; SWITCH-2: BITVECTOR[6~]; Il~ 16~ BIT VECTOR BIT VECTOR allocates: [ (1 ~+7) /8] [ (6~+7) /8] 12 BYTES OF STORAGE 18 BYTES OF STORAGE The accessing algorithm for this structure selector position offset from the Consequently, computes the field beginning address. SWITCH 1[5] SWITCH=2[4S] generates SWITCH 1<5,1,0> 15 IS THE SPECIFIED BIT 145 IS THE SPECIFIED BIT SWITCH=2<45,1,~> and selects the fifth and forty-fifth bits respectively, from zero. 11-4-11 counting BLISS Primer Volume 2: Intermediate Data Structures BLISS-16 declares the BITVECTOR structure as: BITVECTOR[1;N] = [«(N+15)/16) *2] (BITVECTOR+I/16)<I MOD 16,1,O>; while BLISS-36 uses this declaration: BITVECTOR[1;N] = [ (N+35) /36] (B1TVECTOR+((36 18+1)/36-l 18» «36 18+1)MOD 36,1,O>; A A A BLOCK AND BLOCKVECTOR STRUCTURES The BLISS-36 BLOCKVECTOR structure is predefined as: STRUCTURE BLOCKVECTOR[1,O,P,S,E;N,BS] = [N *BS] (BLOCKVECTOR + 0 + 1*BS)<P,S,E>; As an illustration declaration (using 36-bit architecture), consider the OWN 5 WORDS PER BLOCK 3 WORDS PER BLOCK 2 WORDS PER BLOCK' B BLOCKVEC: BLOCKVECTOR[10,5], W BLOCKVEC: BLOCKVECTOR[10,3], L BLOCKVEC: BLOCKVECTOR[10,2]; which allocates ° [10*5] [10*3 ] [10*2 ] ! 5 WORDS - 10 BLOC KS ! 30 WORDS - 10 BLOCKS 120 WORDS - 10 BLOCKS and defines the accessing algorithms (B BLOCKVEC + 0 + I * 5)<P,S,E> (W-BLOCKVEC + 0 + I * 3)<P,S,E> (L-BLOCKVEC + 0 + I * 2)<P,S,E> where the accessing formal I is the block number; 11-4-12 0 is the word BLISS Primer Volume 2: Data St ructures Interm~~diate within the block; P is the field position; S is the field size; and E is the sign extension rule. A typical reference to this structure would be W_BLOCKVEC[S,2,18,18,0]; which, after replacing access formals in the algorithm with access actuals, determines the desired address and its field selector as shown below: (W BLOCKVEC + 2 + 5 * 3)<18,18,0>; In this example, it is the address of the lefthalf of the 18th word or logically to the user a data field in the righthalf of the third word of the sixth block. The BLISS-16 declaration for the BLOCKVECTOR structure is: STRUCTURE BLOCKVECTOR[1,O,P,S,E;N,BS,UN1T=2] = [N*BS*UNIT] (BLOCKVECTOR+(1*BS+O)*UN1T)<P,S,E>; BLISS-32 predefines the BLOCKVECTOR structure as: STRUCTURE BLOCKVECTOR[O,P,S,Ei N,BS,UNIT=4] = [N *BS *UNIT] (BLOCKVECTOR+(1*BS+O)*UN1T)<P,S,E>; The predefined BLOCK structures are identical BLOCKVECTOR structure without the access formal I allocation formal BS. to and the the MAP Frequently, it is convenient to redefine an existing structure to have different properties. Savings in space, time, and readability can result. The MAP declaration provides this capability by permitting the user to associate a new accessing algorithm with, an existing storage. As a declaration, MAP has the same scope rules as any other declaration. Therefore, the MAP declaration only applies within the block declared and all inner 11-4-13 BLISS Primer Volume 2: Intermediate Data Structures blocks so long as the name of that storage is not redeclared or a Consider the new accessing algorithm assigned to that storage. example (BLISS-36) BEGIN OWN SWITCH TABLE: BITVECTOR[36]; ••• , BEGIN MAP SWITCH_TABLE; ... SWITCH TABLE = 9; END; END; which uses the MAP declaration to redefine SWITCH TABLE from a BITVECTOR to a scalar. This enables SWITCH TABLE to be set to zero with a single assignment. After executing the assignment, the block with the MAP declaration is exited, and the BITVECTOR structure is again the accessing algorithm for SWITCH_TABLE. Another example which uses the MAP declaration is the BLISS-32 routine OUT HEX below, which permits hexadecimal characters, stored in a general purpose work area, to be output without having to use shifts or field selectors explicitly. 11-4-14 BLISS Primer Volume 2: Data Structures Interm~diate BEGIN LITERAL WK SIZE = 10; OWN ... ROUTINE OUT HEX: NOVALUE = BEGIN STRUCTURE HEXVEC[I,J]= (HEXVEC + I)<J,4>; LITERAL FIRST = 0, SECOND = 4; MAP WK_AREA: HEXVEC; INCR COUNT FROM 0 TO (WK_SIZE*4-1) DO BEGIN IF .WK AREA[.COUNT,FIRST] GTR 9 THEN TTY PUT CHAR (.WK AREA[.COUNT,FIRST] + %0'67') ELSE TTY_PUT_CHAR(.WK_AREA[.COUNT,FIRST] + %0'60'); IF .WK AREA[.COUNT,SECOND] GTR 9 THEN TTY PUT CHAR (.WK AREA[.COUNT,SECOND] + %0'67') ELSE TTY_PUT_CHAR(.WK_AREA[.COUN~,SECOND] + %0'60'); TTY PUT CRLF(); END~ END; END; Note that octal 60 is added to the contents of each produce the ASCII code required for output to the TTY. byte to In general, the use of field selectors should be restricted to STRUCTURE declarations, as in the above example, since it makes the resulting code easier to read, debug, and modify. 1I-4-15 BLISS Primer Volume 2: Intermedi~te Data Structures REF VECTOR W~len using routines, it is common to pass the address of a storage area as an argument of the routine call. In this instance the location cannot be referenced directly by name but is pointed to by the value of a variable. This unfortunately adds an additional level of complexity by requiring an additional level of indirection. The following routine, which exchanges the contents of two vectors, illustrates the problem: ROUTINE EXCH(VEC1,VEC2,SIZE): NOVALUE BEGIN LOCAL TEMP; = INCR COUNT FROM ~ TO (.SIZE - 1) DO BEGIN TEMP = • (.VECl + .COUNT); (.VECl + .COUNT) = • (.VEC2 + .COUNT); (.VEC2 + .COUNT) = .TEMP; END END; This is more complicated than necessary. One solution is to declare a new structure which returns the address of an element of the vector. For example: ROUTINE EXCH(VECI,VEC2,SIZE): NOVALUE = BEGIN STRUCTURE PTR VEC[C] = -(.PTR_VEC + C); LOCAL TEMP; MAP VECI: PTR VEC, VEC2: PTR VEC; INCR COUNT FROM ~ TO (.SIZE - 1) DO BEGIN TEMP = .VECI[.COUNT]; VEC1[.COUNT] = .VEC2[.COUNT]; VEC2[.COUNT] = .TEMP; END; END; 11-4-16 BLISS Primer Volume 2: Data Structures Interm~diate This however requires a STRUCTURE declaration for a requirement which is very common. Therefore, the REF attribute has been provided. It enables a name, which contains a pointer to a structure, to be used to reference the structure as if the name were the structure itself, i.e., using only a single dot operator instead of two. This is effectively equivalent to defining a new structure definition. Using the REF attribute, the above example can be rewritten as: ROUTINE EXCH(VEC1,VEC2,SIZE): NOVALUE BEGIN LOCAL TEMP; = PVEC2: REF VECTOR; PVEC1: REF VECTOR; PVEC2 = • VEC2; PVECl = • VEC1; INCR COUNT FROM 0 TO (.SIZE - 1) DO BEGIN TEMP = .PVEC1[.COUNT]; PVEC1[.COUNT] = .PVEC2[.COUNT]; PVEC2[.COUNT] = .TEMP; END; END; Note: The REF attribute may be used with any structure. 11-4-17 BLISS Primer Volume 2: Intermediate Data St ructures This page intentionally left blank. 11-4-18 BLISS Primer Volume 2: Intermediate Data Structures Ex.ercises 1. Using the predefined BLISS-36 VECTOR structure definition given in this unit, write a BLISS-36 STRUCTURE declaration named VECTORI to create an accessing algorithm which starts at one rather than zero (i.e., TABLE[l] references the first longword in TABLf~) • 2. Write a BLISS-36 STRUCTURE declaration named MATX[row,column] that implements a two dimensional zero origin array, so that MATX[~,l] is the first row, second column. Show the initial declaration which allocates the storage and a subsequent reference to the third column of the fifth row. 11-4-19 BLISS Primer Volume 2: Intermediate Data Structures This page intentionally left blank. II-4-2~ BLISS Primer Volume 2: Intermediate Data Structures Solutions 1) STRUCTURE VECTOR1 [I;N]= [N] (VECTOR1 + (I - 1) ) <S., 36>; 2] STRUCTURE MATX [I,J;K,L]= [K*L] (MATX + (I*L + J) )<S,36>; ... OWN X: MA TX [ 1 S, 1S ] ; ! ISS WORDS !lS ROWS, IS ! COLUMNS ••• X[4,2]; Note: The array MATX starts at [S,S]. 11-4-21 BLISS Primer Volume 2: Intermediate Data Structures This page intentionally left blank. I1-4-22 BLISS Primer Volume 2: Data Structures Interm~diate Unit Test Write a STRUCTURE declaration that implements a three dimensional array MATX3[row,column,plane], so that MATX3[1,2,0] references the second row, third column of the first plane. Show the initial storage declaration and a subsequent reference to the third column of the fifth row of the fourth plane. 11-4-23 BLISS Primer Volume 2: Intermediate Data Structures This page intentionally left blank. 11-4-24 ADDITIONAL DATA STRUCTURES MODULE 11-5 11-5-1 ~LISS Primer Volume 2: Intermediate Additional Data Structures Course Map II-5-2 BLISS Primer Volume 2: Intermediate Additional Data Structures Introduction This unit depicts several more examples of data structures and their associated field macros. These examples illustrate programming requirements for which the STRUCTURE declaration is appropriate. The structures presented in this unit involve bounds checking and linked lists. 11-5-3 BLISS Primer Volume 2: Intermediate Additional Data Structures _ - - - - - - - - - - - - - - Objectives - - - - - - - - - - - - - - - Given an arbitrary data structure, be able to implement this structure using the STRUCTURE declaration and appropriate field macros. _ - - - - - - - - - - - - S a m p l e Test I t e m s - - - - - - - - - - - -__ Given that a block contains the fields (for a 32-bit machine) LEFT_LINKCl6) TYPE (4) I I RIGHT_LINK (l6) DATA(28) and that these blocks form a doubly linked ring, write a STRUCTURE declaration named RING and the field macros necessary to implement this structure.· Show the initial declaration allocating storage for the ring and a reference to the field TYPE made with a variable RING PTR which is a REF to the ring. Additional Resources BLISS~32 Chapter 12: Data Structures Section: 12.8 Language Guide 11-5-4 BLISS Primer Volume 2: Intermediate Additional Data Structures The predefined data structures are adequate for most programming requirements. However, it can be anticipated that special requirements will arise that necessitate the creation of new data structures. For this reason, BLISS provides the STRUCTURE declaration rather than attempting to define an all-purpose set of data structures which the user must force his program to use. Since the algorithm generated by a STRUCTURE declaration is substituted in-line for the actual structure reference, a STRUCTURE declaration should not be used to manipulate data or otherwise perform complex operations. A routine is the appropriate declaration when these operations are required. This unit depicts examples which use the STRUCTURE declaration. These examples are intended to illustrate conditions when a new structure can be more appropriate than a predefined structure. ERROR CHECKING Error checking can be used advantageously during program debugging and for certain user application programs. As an example, consider the following BLISS-36 two dimensional array STRUCTURE declaration, which includes a simple bounds checking facility: STRUCTURE ARRAY2[I,J;M,N] = [M*N] (IF I*J GTRU M*N THEN "ERROR(ARRAY2,I,J) ELSE ARRAY2 + (I*M + J»<0,36>; This structure, in addition to returning an address, also verifies that each reference is within the storage space allocated. It does not, however, ensure that each index is within bounds, only that their product does not exceed the storage space. (Note that the unsigned comparison (I*J GTRU M*N) precludes having to explicitly check that the product is less than zero, since a negative number would appear as a very large unsigned number which would always exceed the available storage.) If the product is within bounds, the normal address calculation is performed and returned. If the product of the access actuals (I*J) exceeds the declared storage (M*N), an error routine is invoked. In this example the' routine ERROR is assumed to return a default address 11-5-5 BLISS Primer Volume 2: Intermediate Additional Data Structures for the illegal structure reference. Since the value returned from the accessing algorithm will be used as a reference, the STRUCTURE declaration must provide a default address for out-of-bounds conditions to preclude terminating the program because of an illegal address or, worse yet, an erroneous address which is still within the user's space. A NON-CONTIGOOUS STRUCTURE The predefined structures declare storage that is contiguous in memory. This may, however, not be consistent with the logical structure which is necessary for a particular programming problem. For example, consider a program which requires a fixed number of blocks, each consisting of three fu1lwords, and an additional block, consisting of four fu1lwords, to store supplementary data. The additional data mayor may not be applicable to each of the fixed blocks required. One possible solution is to allocate the entire seven fullwords for each block. This would of course necessitate substantial storage that would be poorly utilized. A better solution is to obtain the storage for the supplementary data erom a common area on an as-needed basis. The implementation requires that the block of supplementary data be linked to the appropriate fixed block. This is depicted in the following diagram: 216 ~. ~ B I :100 A C D 200 B I :116 A C D 200 B I :132 A C II-5-6 BLISS Primer Volume 2: Intermediate Additional Data Structures D E = 0 :200 F = 0 H = 0 IG = 0 I = 0 E :216 F H I G I where A through D represent the data fields for the initial fixed blocks, and E through I represent the data fields for the supplementary data block. Note that the first fullword of each initial block is a pointer to the additional data block and that those with no additional data point for compatibility to a common block which is preset to zero. The method used to allocate the storage would depend upon the initialization stragegy. Because this example deals with blocks, the predefined BLOCKVECTOR structure would probably be appropriate. For example, OWN DATA_BASE: BLOCKVECTOR[100,4]; declares 100 blocks having four fullwords each. A predetermined number of these blocks would be initialized with the first fullword set to the address of the first free block (in this example 200) which is preset to zero. The accessing algorithm to implement the storage depicted above requires a STRUCTURE declaration. Since a STRUCTURE declaration and its associated field macros are necessary to understand the structure, they should be physically located together in the program to convey this relationship. For example (BLISS-32): 11-5-7 BLISS Primer Volume 2: Intermediate Additional Data Structures STRUCTURE !+ B = BLOCK NUMBER, 0 = LONGWORD OFFSET, P = FIELD POSITION, S = FIELD SIZE, E = SIGN EXTENSION, I = INDIRECT ADDRESS !- BLOCK LINK[B,O,P,S,E,I] = (IF I EQL 0 THEN (BLOCK LINK + B*16 + 0*4) ELSE (.BLOCK LINK + B*16 + 0*4) )<P,S,E>; MACRO 1+ FIELD DEFINITIONS FOR BLOCK LINK STRUCTURE FOR O,P,S,E,I RESPECTIVELY !- A = 1,0,16,0,0 %, B = 1,16,16,0,0 %, C = 2,0,32,0,0 %, D = 3,0,32,0,0 %, E = 0,0,32,1,1 %, F = 1,0,32,1,1 %, G = 2,0,16,1,1 %, H = 2,16,16,1,1 %, I = 3,0,32,1,1 %; This STRUCTURE declaration implements the structure discussed above. Note that the BLOCK LINK structure contains no allocation formals. This structure is used to access storage only and allocates no storage. As written, this structure can be associated to the previously allocated storage DATA BASE using the declaration MAP so that subsequent references to form: the structure would have the DATA_BASE[block-number, macro A-I] The first entry is the desired block number, and the second entry is one of the macros A through I defined above. Explicitly, DATA BASE[2,G] references the data field G in the 11-5-8 third block. Al though the BLISS Pr imer Vo I ume 2: Intermt:d iate Additional Data Structures physical block containing this supplementary data may be any block in the vector, it is associated to block three through the BLOCK LINK structure. The REF attribute could have been used instead of the MAP declaration. The choice would depend to a large extent upon the manipulation requirements of the program. With the REF attribute, the block number is not necessary, but the address of the desired block must be maintained. An example using REF is provided below. TREE STRUCTURE The structure illustrated above can also be applied to a tree structure. Assume a block configuration of, PARENT ~.~----------+--* LEFT CHILD ~~~----~~-_-_:_* build DATA ________~_____*::::-------.. RIGHT CHILD where the pointers for this discussion are offsets into the storage vector rather than an actual address. As such, this configuration can be used to define a binary tree (each parent having at the most two children) as shown below: The declaration to allocate this storage can either'be part of the structure declaration or independent of it, depending upon the initialization requirements. For example, the following STRUCTURE declaration, and its corresponding field macros, implements the algorithm for a tree but allocates no storage for that structure. (The declaration is patterned for a 32-bit word length.): 11-5-9 BLISS Primer Volume 2: Intermediate Additional Data Structures STRUCTURE + I = INDIRECT ADDRESS, 0 = FULLWORD OFFSET, PI = INDIRECT FIELD POSITION, Sl = INDIRECT FIELD SIZE El = INDIRECT FIELD SIGN, P = FIELD POSITION, S = FIELD SIZE TREE[I,O,Pl,Sl,El,P,S] = ~IF I EQL 0 THEN • (TREE + O*4)<Pl,Sl,El> + TREE ELSE TREE )<P,S>; MACRO !+ FIELD DEFINITION FOR TREE STRUCTURE FOR I,O,P1,Sl,E1,P,S RESPECTIVELY !- PARENT = 0,0,16,16,1,0,32 %, DATA = 1,0,0,0,0,0,16 %, LEFT CHILD = 0,1,16,16,0,0,32 %, RIGHT_CHILD = 0,1,O,16,0,O,32 %; Because this structure uses offsets instead of addresses, the algorithm must add the contents of the field to the base address of the storage area. The TREE structure, defined above, can be referenced by establishing a pointer with the declaration OWN NODE: REF TREE; where subsequent references such as NODE = NODE [PARENT] TEMP = .NODE[DATA] would conceptually be replaced by the algorithms: NODE = (.NODE[PARENT]<16,16> + NODE[PARENT])<0,32> TEMP = .NODE[DATA]<0,16> The first example assigns to NODE the address of the parent node (an offset in fu1lwords plus the current address in the TREE); whereas the second example assigns to TEMP the data for that node. 11-5-10 BLISS Primer Volume 2: Intermediate Additional Data Structures TREE TRANSVERSAL To demonstrate the use of the TREE structure defined consider a tree constructed from parsing the equation (5 - • B) = (.A above, + 7); as depicted below: Assuming that the data is stored as ASCII characters in the data field, the following recursive routine could be used to perform an inorder (left-child, parent, right-child) transversal of any binary tree constructed with similar fields and output the contents of the data fields: ROUTINE OUT TREE (TOP NODE): NOVALUE= BEGIN LOCAL NODE: REF TREE; NODE = .TOP NODE; IF NODE [LEFT CHILD] NEQ .NODE THEN OUT TREE (NODE [LEFT CHILD]); TTY PUT-CHAR(.NODE[DATA]); IF NODE[RIGHT CHILD] NEQ .NODE THEN OUT TREE (NODE [RIGHT CHILD]); END i The routine OUT TREE is recursive and continues to call itself so long as a left- or right-child exists. That is, so long as a left- or right-child field contains an offset other than zero. The routine searches first for a left-child; therefore, the algorithm prints the, data inorder: left-child, parent, right-child until the entire tree has been transversed. 11-5-11 BLISS Primer Volume 2: Intermediate Additional Data Structures As mentioned, the fields in the above example contain offsets which must be added to the current base address; therefore, the parent field must be signed. In fact, had larger fields been allocated initially, they could have contained the actual addresses. 11-5-12 BLISS Primer Volume 2: Interm~diate Additional Data Structures Exercises· 1. Create a BL1SS-36 structure named VECTOR BCK that has a normal predefined VECTOR accessing algorithm but-also does bounds checking on the access actual used in the reference. Call a routine named ERROR if the access actual is not in bounds and pass the reference actual as a parameter. You can assume that the routine ERROR returns a default address. 2. Same as Exercise 1) above except this exercise assumes ERROR does not return a default address. Make the first fullword of the storage area the default address (i.e., return the address of the first fullword of the array VECTOR_BCK[~] if a referencing error occurs). 11-5-13 BLISS Primer Volume 2: Intermediate Additional Data Structures This page intentionally left blank. 11-5-14 BLISS Primer Volume 2: Intermediate Additional Data Structures Solutions 1) STRUCTURE VECTOR BCK[I;K] = [KT (IF I LSS 0 OR I GTR (K-1) THEN ERROR (VECTOR BCK,I) ELSE VECTOR BCK + I) <0;36>; 2) STRUCTURE VECTOR BCK[I;K] = [KT (LOCAL TEMP; TEMP = I; IF I LSS 0 OR I GTR K-1) THEN BEGIN ERROR (VECTOR BCR,I); TEMP = 0; END; VECTOR BCK + .TEMP <0;36>; 11-5-15 BLISS Primer Volume 2: Intermediate Additional Data Structures This page intentionally left blank. II-5-l6 BLISS Primer Volume 2: Intermediate Additional Data Structures Unit Test Given that a block contains the fields (32-bit machine) LEFT_LINK (16) TYPE (4) I I RIGHT_LINK(16) DATA(28) and that these blocks form a doubly linked ring, - - write a BLISS-32 structure declaration named RING and the field macros necessary to implement this structure. For purposes of accessing this structure declare RING PTR as a REF to the ring. Show the initial declaration which allocates the storage for the ring and a reference which accesses the field TYPE. Assume that LEFT-LINK and RIGHT-LINK contain offsets from the address of the current block to the address of the desired block. 11-5-17 BLISS Primer Volume 2: Intermediate Additional Data Structures This page intentionally left blank. 11-5-18 TABLE BUILDING MODULE 11-6 11-6-1 BLISS Primer Volume 2: Intermediate Table Building Course Map 11-6-2 BLISS Primer Volume 2: Interm9diate Table Building Introduction Initialization, which is the final step in establishing a data structure, is discussed in this unit. Two methods of initializing a table are depicted: the INITIAL attribute for storage, which may subsequently be modified, and the PLIT declaration for applications where storage is not subject to chang e. 11-6-3 BLISS Primer Volume 2: Intermediate Table Building - - - - - - - - - - - - - - - Objectives----------------. Given a data structure and its required initial value, be able to initialize the given structure using the INITIAL attribute or the PLIT declaration as appropriate. r---------------Sample Test Items - - - - - - - - - - - - - - . Given that a BLOCKVECTOR named TBL consists of six blocks, each having three fullwords, where the first three blocks (named MASK_BLK) have the logical fields (for 32-bit architecture) PTR (3 2) S (16) MASK BLK: I R (16) MASK(32) and the last three blocks (named DATA_BLK) have logical fields, TYPE (4) I DATA(28) DATA BLK: DATAl (32) DATA2(32) write the macros and declarations necessary to allocate and initialize TBL, so that: 1) MASK BLK contains an offset of three (points to the fourth block) in PTR; zeroes in S; the address of the symbolic names Al through A3, respectively, in R; and the value -1 in MASK 2) DATA BLK contains the value nine in TPYE and the value zero in DATA, DATAl, and DATA2 11-6-4 BLISS Primer Volume 2: Intermediate Table Building There are three distinct structures: 1) 2) 3) steps in establishing most data defining an accessing algorithm establishing field macros initializing the storage The process of defining the accessing algorithm has been discussed in the two previous prerequisite units. This process includes either using predefined structures or creating new structures with the STRUCTURE declaration. In general, the predefined structures are adequate for most applications and their use is encouraged. When a predefined structure would suffice, creating a new structure could prove to be inefficient with respect to execution time and could result in increased debugging time. It is, of course, not recommended that an algorithm be manipulated to fit a predefined structure when a new structure is clearly necessary. It is suggested that the data structure is an essential part of an efficient algorithm and should, therefore, be given considerable thought. Field macros are also an essential part of a data structure. Field macros help to improve readability and documentation by providing easily recognized mnemonics, simplifing coding through textual substitution, and making the program easier to modify and debug by isolating the code. The final phase of implementing a given data structure is its initialization. The particular method of initialization is contingent on the data structure's size, complexity, and subsequent utilization. Two methods will be illustrated: initializing with the INITIAL attribute and with the PLIT declaration. BASIC TECHNIQUE The basic technique in table building is to fill up the table one fullword at a time, by shifting and- ORing the values of individual fields as necessary. For example, the expression 1 A 28 OR 100 A 12 OR ·S. would generate one fullword, consisting of organized as follows (36-bit machine): II-6-5 A 4 four OR 3 separate fields BLISS Primer Volume 2: Intermediate Table Building A(S) I 8(16) C(8) D (4) The shift factor is computed as the sum of the sizes of fields to the right of the one in the current fullword. all the INITIALIZATION WITH THE INITIAL ATTRIBUTE The INITIAL attribute permits the user to initialize permanent storage to any given value at the time it is allocated. Fo r example, OWN TABLE: VECTOR [10] INITIAL(REP 10 OF (0»; sets each of the 10 locations in the vector TABLE to zero, while OWN B TABLE: VECTOR [4] INITIAL('EXAMPLE'); initializes the vector B TABLE to 'EXAMPLE'. However, the initialization becomes increasingly more complicated as fields within each· word unit require individual values. This is especially true with blocks or vectors of blocks. Consider, for example, the diagram IA(S) I 8(16) CIS) 10 (4) I which is logically divided into fields A through D. The number of bits in each field is indicated by the numbers in parentheses. The initialization of these fields to 1, 100, 's ' and 3, respectively, could be achieved with the INITIAL attribute as in the following declaration: OWN However, this form is awkward and is also not particularly descriptive. Furthermore, this is a relatively simple example having only one fullword. A vector of 25 fullwords would be tedious, more prone to errors, and a considerable headache if one or more of the fields required modification. One solution to this 11-6-6 BLISS Primer Volume 2: Intermediate Table Building problem is to use a macro to initialize the fields. MACRO WORD INIT(A,B,C,D)= INITIAL«A)A28 OR (B)AI2 OR (C)A4 OR (D» VEC INIT(A,B,C,D)= -«A)A28 OR (B)AI2 OR (C)A4 OR (D» %; For example, %, could be used to initial a fullword as in the example above, X: FULL_INIT(I,100,'S',3); or to initialize a vector of these fullwords: OWN TABLE: VECTOR[10] INITIAL(VEC INIT(I,100,%C'A',3), VEC=INIT(2,101,%C'B',4), ... VEC_INIT(10,110,%C'J',12»; The procedure is easily adapted to BLOCKS, BITVECTORS, or any other structure. In addition, initialization macros offer the same advantages discussed for field macros above and should therefore be an essential part of any initialization. As declared above, the initialized values could easily be modified. Where the storage once initialized is not subject to further modification, a PLIT declaration can be used t6 advantage. INITIALIZATION WITH PLITS As the following example illustrates, plits can be used to build a table much in the same manner as was achieved with the OWN declarations above: BIND TABLE = UPLIT( VEC INIT(I,100,%C'A',3), VEC=INIT(2,lI0,%C'B',4), ... VEC INIT(10,110,%C'J',l2» - VECTOR[10]; II-6-7 BLISS Primer Volume 2: Intermediate Table Building Note that both the OWN and PLIT declarations use initialization macros and also that both can subsequently be referenced with TABLE [ ••• ] if the plit is used in conjunction with the BIND declaration as above. Note that UPLIT is the preferred declaration unless the count is required.' AN INITIALIZATION EXAMPLE The tec~nique for multiword tables is simply a repetition of the packing methods discussed above, with commas separating the values for each word. Consider initializing a symbol table having three fullwords per block, where each block is logically defined as: Nl (32) T (10) I N2 (22) A (32) In the above diagram, Nl is the Radix-50 representation of the first six letters in the name; N2 is the Radix-50 representation of the last four letters, T is a type field giving information about the name; and A is the address of the routine which processes that name. To keep this example simple, only four names of this table will be initialized. The following macro initializes the block: MACRO INIT TBL(A,B,C,D) = %RAD50ll(%STRING(A», (C)A22-0R %RAD50 11(%STR1NG(B», (D) %; - The storage for these blocks can be allocated and initialized in a plit since the symbol table will not be subsequently modified. Fo r example, BIND SYM TABLE = UPLIT( INIT TBL('INCR',0,2,SINCR), INIT-TBL (' IF' ,0,2, SIF) , INIT-TBL('ROUTIN',%C'E',l,SROUTINE), INIT-TBL('SELECT','ONE',0,SSELECT» :BLOCKVECTOR[4,3]; 11-6-8 BLISS Primer Volume 2: Intermediate Table Building initializes storage as depicted below, INCR 2 • I " * ROUTINE SINCR IF 2 1 " * .. ROUTINE SIF ROUTIN 1 I E * ROUTINE SROUTINE SELECT "I ONE * where the names would be in Radix-5". pointer to the specified data. 11-6-9 ..... ROUTINE An arrow SSELECT (~) indicates a BLISS Primer Volume 2: Intermediate Table Build ing This page is for notes. 11-6-10 BLISS Primer Volume 2: Intermediate ,Table Building Exercises 1. Declare a macro named INIT VAL which initializes (BLISS-16/32) with the logical fields: XSIGN(l) EXPONENT (6) MANTISSA(8) a WORD MSIGN (1) where the numbers in parentheses represent the number of bits in each field. Show the macros and the actual declaration necessary to initialize a word named REAL declared in an OWN declaration so that: XSIGN = 1 EXPONENT = 24~ MANTISSA = 128 MSIGN = ~ 2. Using the format in Exercise 1) above, declare a macro to initial a plit bound to the name REAL TBL consisting of l~ words. Show the first and l~th entries (use " ••• " for the missing data in between) using any data. 3. Construct a BLISS-36 macro named INIT BLK to initialize a block with the fields: TYPE (6) I I DATA (18) I PTR (12) Show the initialization of a BLOCK named HEAD so that: L ADDR = l~~ R-ADDR = 2~~ TYPE = 1 DATA = •A' PTR = 1(tJ~ II-6-ll BLISS Primer Volume 2: Intermediate Table Building This page intentionally left blank. 11-6-12 BLISS Primer Volume 2: Intermediate Table Building ; Solutions 1) MACRO INIT VAL(A,B,C,D) = INITIAL«A)A1S OR (B)Ag OR (C)Al OR (D» OWN REAL: WORD INIT_VAL(1,240,128,~)i 2) MACRO INIT VAL(A,B,C,D) = TA)A1S OR (B)Ag OR (C)Al OR (D) %i BIND REAL TBL = UPLIT( INIT_VAL(1,24~,128,~), ... INIT VAL(1~,2S~,138,19» :VECTOR[l~,WORD]i 3) MACRO INIT BLK(A,B,C,D,E) = INITIAL«A)A18 OR (B), (C)A3~ OR (D)A12 OR (E» %i OWN HEAD: BLOCK [2] INIT_BLK(1~~,2~~,1,'C'A',1~~) 11-6-13 %i BLISS Primer Volume 2: Intermediate Table Building This page intentionally left blank. 11-6-14 BLISS Primer Volume 2: Intermediate Table Building Unit Test Given that a blockvector named TBL consists of six blocks, each having three fullwords, where the first three blocks (named MASK_BLK) have the logical fields (for a 36-bit machine) PTR(36) S (18) MASK BLK: I R (18) MASK(36) and the last fields, three blocks (named TYPE(6)IDATA(39) DATA_BLK) have the logical to allocate DATA BLK: DATAl (36) DATA 2 (36) write the macros and declarations initialize TBL, so that: necessary 1) MASK BLK contains an offset of three (points to the fourth block) in PTR; zeroes in S; the address of the symbolic names Al through A3, respectively, in R; and the value -1 in MASK 2) DATA BLK contains the value nine in TYPE and the value zero in DATA, DATAl, and DATA2 11-6-15 and BLISS Primer Volume 2: Intermediate Table Building This page intentionally left blank. II-6-16 CONDITIONAL COMPILATION MODULE 11-7 II-7-1 BLISS Primer Volume 2: Intermediate Conditional Compilation Course Map 1I-7-2 BLISS Primer Volume 2: Intermediate Conditional Compilation Introduction This unit discusses the conditional compilation mechanism available in BLISS along with various lexical functions which are useful in combination with this capability. II-7-3 BLISS Primer Volume 2: Intermediate Conditional Compilation ---------------Objectives - - - - - - - - - - - - - - - - . Given a programming problem, be able to develop a solution which correctly uses the conditional compilation mechanism and related lexical functions. _ - - - - - - - - - - - - Sample Test I t e m s - - - - - - - - - - - - _ Write a macro named INIT that uses conditional compila~ion to initialize a vector depending upon the compiler used, so that: - BLISS 36 Fields: - BLISS 32 Fields: A = <O,18> B = <18,18> A = <O,8> B = <8,8> C = <16,16> In addition, the solution should terminate the compilation with an error diagnostic if: * * required arguments are missing the macro is called more than some arbitrary number of times (use two compile-time constants named LIMIT and COUNT) Assume that COUNT is initially set to zero; LIMIT is set to an arbitrary value at the beginning of each vector initialization; and COUNT is incremented by one on each call. Additional Resources None 11-7-4 BLISS Primer Volume 2: Intermediate Conditional Compilation Conditional compilation provides a means to select, during compilation, one of two alternative sources of input text. The choice is determined by testing a compile-time expression. The general form is: 'IF compile-time expressidn 'THEN source-code sequence one 'ELSE source-code sequence two 'FI The compile-time expression is evaluated, and the value of the low-order bit is used to select the appropriate source code sequence. A one selects the 'THEN part whereas a zero selects the 'ELSE part. The sequence selected is incorporated into the program, while the sequence not selected is discarded. The 'ELSE part is optional and, if not present, a null lexeme is assumed. Note that a conditional compilation begins with a 'IF and ends with a 'Fl. As a consequence, a semicolon is not required. An example of a conditional compilation: 'IF COND FLAG %THEN MACRO FIELD = 0,8 %i 'ELSE MACRO FIELD = 0,7 '; 'FI Assuming COND FLAG is a compile-time expression with a value of zero, the following source code would be generated: MACRO FIELD = 0,7 %i Code that is discarded as a result of a conditional compilation is never seen by the compiler and therefore may contain syntactic errors that will not be detected. The code may also contain partial declarations that will not be processed until substitution is complete. For example, it is legal to say: 11-7-5 BLISS Primer Volume 2: Intermediate Conditional Compilation %IF VISIBLE %THEN GLOBAL X %ELSE OWN %FI x : VECTOR[10]; It is equally important to understand that compile-time functions and conditional compilations occurring in macro declarations are not evaluated and therefore do not take effect until the time of the macro call. COMPILE-TIME DECLARATIONS A compile-time declaration creates a symbolic name whose value can be changed at any time during the compilation of the program. In all other respects, a compile-time name is equivalent to a literal name and can be used in the same ways that a literal name can be used. A compile-time name is declared with the keyword COMPILETIME. For example, COMPILETIME FLAG = 0; declares the name FLAG as a compile-time name with the value zero. As such, it is equivalent to a LITERAL declaration with the exception that its value may subsequently be changed. The function %ASSIGN(compile-time-name, compile-time-constant) modifies the value of the compile-time name by assigning the specified compile-time constant as its value. The function %ASSIGN( ••• ) is replaced by the null lexeme (i.e., it disappears) after the assignment is made; consequently, it should not be followed by a ";" since the semicolon would not disappear and might introduce syntactic complications. An example of this function is %ASSIGN(FLAG,I) which resets the compile-time literal FLAG to the value one, and %ASSIGN(FLAG, FLAG + 2) II-7-6 BLISS Primer Volume 2: Intermediate Conditional Compilation which resets the current value to the value of FLAG plus two. Note that FLAG is a compile-time literal and, therefore, the dot operator is not used to obtain its value. Together, these two functions provide added flexibility in controlling the compilation process. For example, COMPILETIME COUNT = 0; .. . COUNT + 1) .%ASSIGN(COUNT, .. %IF COUNT GTR 4 %THEN code segment one ... %ELSE code segment two ... %FI allows the user to select a specific source code based upon a compile-time counter which is incremented during the course of the compilation. LEXICAL FUNCTIONS The conditional compilation mechanism iSl,further enhanced by a number of special lexical functions.' They include test, functions, which are used to evaluate compile-time constants; advisory functions, which are used to ~enerate compile-time messages; and macro functions, which are used in conjunction with the conditional compilation of macros. TEST FUNCTIONS Each test function contains one or more arguments which are evaluated to determine whether a given condition is true or false. The test function is then replaced by a one (true) or zero (false) as a.ppropriate. II-7-7 BLISS Primer Volume 2: Intermediate Conditional Compilation The function %NULL(argument, ••• ) returns a one if all of its arguments are null or a zero if one or more of its arguments are not null. For example, MACRO NR LINES (LINE SIZE)= - %IF NOT %NULL(LINE SIZE) %THEN LINES = .CHARS / LINE SIZE %FI %; generates a null if the argument because %NULL ze ro) • macro NR LINES is called without an returns a-one (i.e., NOT %NULL returns a The function %DECLARED(name) returns a one if its argument is a user declared name and a zero if it is not. For example, the test condition in OWN .%IF.. STORE; %DECLARED(STORE) %THEN TABLE[.K] = .STORE; %FI returns a one because STORE is a user-defined name and, consequently, the THEN sequence is included in the compilation. This function accepts only one argument. The function %SWITCHES(argument, ••• ) returns a one if the standard BLISS compilation switches included as arguments are true (activated) at that time, and a zero if one or more are not. For example, %IF %SW1TCHES(DEBUG) %THEN INCR I FROM 0 TO 9 DO TTY_PUT_1NTEGER(.TABLE[.1],10,10); %FI succeeds and generates the INCR activated for the compilation. loop if the DEBUG switch is The function %IDENTICAL(arguments, ••• ) requires a minimum of two arguments and returns a one if these arguments are exactly the same, or a zero if they are not. "Exactly", in this context, requires that both the value and the type of literal agree. This 1I-7-8 BLISS Primer Volume 2: Intermediate Conditional Compilation is illustrated by the following example, where each conditions fail for the indicated reason: of the test LITERAL SIXFIVE = 65; . .. %IF %IDENTICAL(65,%C'A') ••• %IF %IDENTICAL(65,%O'10l') ••• %IF %IDENTICAL(65,SIXFIVE) ••• %IF %IDENTICAL(%ASCII'A',%C'A') ••• !NUMBER VS STRING ! LITERAL lONE VS TWO LEXEMES !LITERAL VS NAME !TWO VS ONE LEXEME The function %BLISS(argument) accepts the generic name BLISS compiler, i.e., of a BLISS16 BLISS32 BLISS36 and returns a one if the compiler is processing the program or a zero if another compiler is processing the program. For example, %IF %BLISS(BLISS32) %THEN CHAR PER WORD = 4; %ELSE %IF %BLISS(BLISS36) %THEN CHAR PER WORD = 5; %ELSE CHAR PER WORD = 2; %FI %FI results in the appropriate source code being generated to assign to CHAR PER WORD the correct number of characters per word, depending upon the compiler which is processing the source code. ADVISORY FUNCTIONS The advisory functions provide a means to generate compile-time diagnostic and/or other messages which will appear in the program listing being generated. These functions do not produce source code and therefore have no run-time effect on the program being compiled. II-7-9 BLISS Primer Volume 2: Intermediate Conditional Compilation The function %ERROR(quoted-string, ••• ) produces an error diagnostic in the listing which includes the quoted string as its message. For example, %IF NOT %BLISS(BLISS36) %THEN %ERROR('YOU HAVE THE WRONG COMPILER'); generates a compile-time error and the diagnostic message 'you have the wrong compiler' if the BLISS-36 compiler is not the one being used. Because the error indicator is incremented when this function is invoked, no object module is generated. The function %WARN(quoted-string, ••• ) produces a warning diagnostic which includes the quoted string. The warning indicator is incremented and an object module is produced. The function %INFORM(quoted-string, ••• ) produces a diagnostic but does not increment the error or warning indicators. The quoted string is output on both the listing file and the terminal as a message. The function %PRINT(quoted-string, ••• ) prints string in the compilation listing but does not diagnostic. For instance, the quoted generate a %IF %SWITCHES(DEBUG) %THEN %PRINT('DEBUG SWITCH ON .); %ELSE %INFORM('DEBUG SWITCH NOT ACTIVIATED') ·%FI prints a message in the compilation listing, reminding the user that the debug switch was activated, or else prints a diagnostic, indicating that the debug switch was not activated. The message generated by %INFORM is output to the terminal and included in the compilation listing; whereas the %PRINT message appears in the compilation listing only. The last advisory function is %ERRORMACRO(quoted-string), which provides a method to stop macro processing within complex macros when there appears to be no reason to continue normal expansion. An error diagnostic is produced which includes the quoted string and the function terminates all currently active macro expansions. For example, II-7-leJ BLISS Primer Volume 2: Intermediate Conditional Compilation MACRO A VG TW 0 (I , J) [] = -%IF NOT (%LENGTH MOD 2) %THEN I = (. I * . J ) /2 ; AVG_TWO(%~EMAINING) %ELSE %ERRORMACRO('ODD NUMBER OF ARGUMENTS') %FI %; terminates the macro expansion, if an odd number of passed to the macro call. arguments is MACRO FUNCTIONS The macro functions have no meaning outside of a macro expansion; however, within a macro expansion, these functions terminate the expansion of the macro in which they are contained. The function %EXITITERATION has no arguments. In an iterative macro expansion, this function terminates the expansion of the current iteration and is replaced by a null. In a noniterative macro %EXITITERATION is functionally equivalent to %EXITMACRO. The function %EXITMACRO also has no arguments. It terminates the expansion of the macro in which it is contained and is replaced with a null. Using this function, the example above could have been written: MACRO A VG TW 0 (I , J) [] = -%IF NOT (%LENGTH MOD 2) %THEN I = (. I * •J ) /2 ; AVG_TWO(%REMAINING) %ELSE %INFORM('ODD NUMBER OF ARGUMENTS') %EXITMACRO %FI %; The advantage of this construction is that an object module is produced although the macro expansion was terminated; whereas in the former example an object module would not have been produced because the error indicator was incremented. 11-7-11 BLISS Primer Volume 2: Intermediate Conditional Compilation This page is for notes. 11-7-12 BLISS Primer Volume 2: Intermediate Conditional Compilation Exercises 1. Write an initialization macro named INIT that initializes the fields BLISS-16 Fields: BLISS-32 Fields: BLISS-36 Fields: A = <~, 8> B = <8,8> A = <~,8> B = <8,8> C = <16,8> D = <24, 8> A = <0,12> B = <12,6> C = <18,1~> D = <28,8> depending upon the specific compiler used. Print message if any of the required arguments are missing. a warning 2. Write an initialization macro named INIT that initializes the fields in Exercise 1) depending upon the specific compiler used. In addition to initializing the fields, store the values of the arguments in a table named SAVE if the debug switch is activiated. 3. Same as Exercises 1) and 2) and, in addition, terminate the macro with an error diagnostic if the user has not declared a variable named SAVE. 11-7-13 BLISS Primer Volume 2: Intermediate Conditional Compilation This page intentionally left blank. 11-7-14 BLISS Primer Volume 2: Intermediate Conditional Compilation Solutions 1) MACRO INIT(A,B,C,D)= %IF %BLISS(BLISS16) %THEN %IF %NULL(A) OR %NULL(B) %THEN %WARN('MISSING ARGUMENT') %ELSE «B) 8 OR (A» %FI %ELSE %IF %BLISS(BLISS32) %THEN %IF %NULL(A) OR %NULL(B) OR %NULL(C) OR %NULL (D) %THEN %WARN ('MISSING ARGUMENT') %ELSE «D) 24 OR (C) 16 OR (B) 8 OR (A» %FI %ELSE %IF %BLISS(BLISS36) %THEN %IF %NULL(A) OR %NULL(B) OR %NULL(C) OR %NULL(D) %THEN %WARNC'MISSING ARGUMENT') %ELSE . «D) 28 OR (C) 18 OR (B) 12 OR (A» %FI %FI %FI %FI %; A A A A 11-7-15 A A A BLISS Primer Volume 2: Intermediate Conditional Compilation 2) COMPILETIME COUNT = 0; ••• MACRO INIT(A,B,C)= %IF %SWITCHES(DEBUG) %THEN SAVE [COUNT] = (A); %ASSIGN(COUNT, COUNT + 1) SAVE [COUNT] = (B); %ASSIGN(COUNT, COUNT + 1) %FI %IF %BLISS(BLISS16) %THEN (B ,.. 8 OR A) %ELSE %IF %BLISS(BLISS32) %THEN %IF SWITCHES(DEBUG) %THEN SAVE [COUNT] = (C); %ASSIGN(COUNT, COUNT + 1) SAVE [COUNT] = (D); %ASSIGN(COUNT, COUNT + 1) %FI «D) ,.. 24 OR (C) 16 OR (B) 8 OR (A» %ELSE %IF %BLISS(BLISS36) %THEN %IF SWITCHES (DEBUG) %THEN SAVE [COUNT] = (C); %ASSIGN(COUNT,CQUNT + 1) SAVE [COUNT] = (D) i' %ASSIGN(COUNT,COUNT +1) %FI «D) 28 OR (C) ,.. 18 OR (B) ,.. 12 0R (A» %FI %FI A A %FI %; II-7-l6 A BLISS Primer Volume 2: Intermediate Conditional Compilation 3) COMPILETIME COUNT = 0; ... MACRO INIT(A,B,C)= %IF NOT %DECLARED(SAVE) %THEN ERRORMACRO('SAVE NOT DECLARED') %FI %IF %SWITCHES(DEBUG) %THEN SAVE [COUNT] = (A); %ASSIGN(COUNT, COUNT + 1) SAVE [COUNT] = (B); %ASSIGN(COUNT, COUNT + 1) %FI %IF %BLISS(BLISS16) %THEN «B) 8 OR (A» %ELSE %IF %BLISS(BLISS32) %THEN %IF SWITCHES(DEBUG) %THEN SAVE [COUNT] = (C); %ASSIGN(COUNT, COUNT + 1) SAVE [COUNT] = (D); %ASSIGN(COUNT, COUNT + 1) %FI «D) 24 OR (C) 16 OR (B) 8 OR (A» %ELSE %IF %BLISS(BLISS36) %THEN %IF SWITCHES (DEBUG) %THEN SAVE [COUNT] = (C); %ASSIGN(COUNT, COUNT + 1) SAVE [COUNT] = (D); %ASSIGN(COUNT, COUNT + 1) %FI «D) 28 OR (C) 18 OR (B) 12 OR (A» %FI %FI %FI %; A A A A A A II-7-17 A BLISS Primer Volume 2: Intermediate Conditional Compilation This page intentionally left blank. II-7-l8 BLISS Primer Volume 2: Intermediate Conditional Compilation Unit Test Write a macro named INIT that uses conditional compilation to initialize a vector depending upon the compiler used, so that: - BLISS 36 Fields: - BLISS 32 Fields: A = <0,18> B = <18,18> A = <0,8> B = <8,8> C = <16,16> In addition, the solution should terminate the compilation with an error diagnostic if: * * required arguments are missing the macro is called more than some arbitrary number of times (use two compile constants named LIMIT and COUNT) Assume COUNT is initially set to zero; LIMIT is set to an arbitrary value at the beginning of each vector initialization; and COUNT is incremented by one on each call. 11-7-19 BLISS Primer Volume 2: Intermediate Conditional Compilation This page intentionally left blank. II-7-29 OPTIMIZATION MODULE 11-8 11-8-1 BLISS Primer Volume 2: Intermediate Optimization Course Map 11-8-2 BLISS Primer Volume 2: Intermediate Optimization Inttoduction This unit presents source-code optimizations intended for programmers that need to minimize space requirements or want to produce highly optimized code. 11-8-3 BLISS Primer Volume 2: Intermediate Optimization __----------------------------Obj8Ctiv8S------------------------------~ Given an algorithm coded in BLISS-32, be able to rewrite the source code so that the object code produced by the compiler is more highly optimized than the original with respect to program size. 11-8-4 BLISS Primer Volume 2: Intermediate optim izati on - - - - - - - - - - - - - Sample Test Items - - - - - - - - - - - - - _ Modify the following BLISS-32 source code to reduce the current routine size of the object code produced by the compiler by at least 11 bytes: MODULE TEST (MAIN=SP CHAR)= BEGIN EXTERNAL ROUTINE PROCi EXTERNAL LITERAL NULL, SETONE; 1=0 1=1 GLOBAL FLAG; ROUTINE SP_CHAR(TYPE)= !ROUTINE SIZE 86 BYTES !++ THIS ROUTINE CONVERTS SELECTED SPECIAL CHARACTERS TO THEIR FUNCTIONAL EQUIVALENT AND RETURNS THE VALUE. !-- BEGIN LOCAL TEMP; TEMP = • TYPE; SELECT .TYPE OF SET [ %C I [ I ] : [%C '\' ] : [%C ' ] , ] : [OTHERWISE] : [ALWAYS] : TES; RETURN .TEMP; END; TEMP = %C I ( I ; TEM P = %C I / ' ; TEM P = %C I) I ; FLAG = SETONE; (FLAG = NULL; PROC(.TEMP»; END ELUDOM 11-8-5 BLISS Primer Volume 2: Intermediate Optimization This page is for notes. II-8-6 BLISS Primer Volume 2: Intermediate Optimization The BLISS compilers are optimizing compilers which in general produce highly,optimized object code. The code generated by the compilers compares favorably with that produced by competent system programmers using assembly language. As a consequence, BLISS programmers are encouraged to write source code so that it can be easily read by other competent programmers, and to leave the optimization to the compiler. That remains sound advice even though this unit discusses optimization! For most applications, coherent code is preferred even at the expense of program size and/or execution time. . There are, however, many different options available when coding any given algorithm, and these choices tend to be arbitrary. This unit therefore attempts to identify source code trade'offs or selective options that enable programmers, when necessary, to conserve space and/or time. In addition, this unit provides coding conventions which make it possible for the compiler to produce more efficient object code. No~ You are cautioned that the assembly code depicted in this unit was derived using version lD(114) of the BLISS,32 compiler and may not be duplicable with other BLISS compilers. This is due to continual improvements being made to the compilers and the on'going effort to produce more highly optimized code. The focus of each example is to show that a savings of generated code is possible; the actual number of bytes saved will vary, depending upon the compiler. NOVALUE ROUTINES The NOVALUE attribute was introduced in an earlier unit and has been used extensively throughout subsequent units in routines that did not return a value. Although this attribute is not mandatory, even when a routine does not return a value, its use is recommended since it can effect savings in both program size and execution time. When a routine is identified as NOVALUE, the compiler does not provide for return value generation and can therefore avoid allocating storage for potential return values. The compiler does not have to generate instructions that would otherwise be necessary to move and store these values. Of course, the actual s~vings for any given routine are highly dependent upon 11-8-7 BLISS Primer Volume 2: Intermediate Optimization the complexity of the routine. BLISS optimization occurs at the routine level. Consider, as an example, the routine: ROUTINE NVR(X,Y)= BEGIN IF .Y EQL 1 THEN .X = 5 ELSE , •Y = 3 END; NVR: 1 $: .WORD MOVL CMPL BNEQ MOVL MOVL RET MOVL MOVL RET AM<> 8(AP),R0 ReJ,#l 1$ #5,@4(AP) #5,R0 #3, (ReJ) i3,R0 Because this routine does not contain the NOVALUE attribute, it requires code to move the potential values of X '(i.e., five) and of Y (i.e., three) to the return reqister R0. The routine size of the resulting object code is 26 bytes. The same routine with the NOVALUE attribute is six bytes smaller and no longer requires the longword moves to register R0. In addition, someone reading the program would know immediately that this routine does not return a val ue. o For routines that do return a value, the keyword RET~RN improves program readability and also provides additional information to the compiler, which can facilitate optimization by identifying the specific variable that will contain the value to be returned. Being able to identify which variable will contain the return value, prior to code generation, the compiler can often assign it to the retu~n register. Even when no saving results, no additional code is generated! For example, the routine RTN: ROUTINE RTN= BEGIN LOCAL X; IF .Y THEN X = .Y 1 $: ELSE .x .WORD MOVL BLBC MOVL RET MNEGL RET AM<> Y,Rl Rl,l$ Rl,R0 Rl,R0 X = ~.Y; END; which does not explicitly identify the return value requires seven instructions and has a program size of 18 bytes; whereas the same routine, using an explicit RETURN expression which eliminates the II-8-8 BLISS Primer Volume 2: Intermediate optimization local X, requires two fewer instructions and is reduced in size by four bytes: ROUTINE RTN= BEGIN RETURN IF .Y THEN .Y ELSE ".Y ) ; END; RTN: 1 $: .WORD MOVL BLBS MNEGL RET . . M<> Y,R0 R0,l$ R0,R0 This code is also easier to read. It should be noted that the examples in this unit are necessarily small and that this limits many opportunities for optimization which can occur as a result of using the suggested coding techniques. EXTERNAL LITERALS As a general rule, external literals should not be used: it is better to define the values of the literals locally than to reference them through external literals. If external literals are essential, they should contain the size of each field. Without size information, the compiler assumes a fullword literal. The extensive use of fullword literals can produce a significant increase in the size of the program. This is especially applicable if these literals have small numeric values. For example, consider the declaration: LITERAL TYPE A = 1, TYPE-S = 2, TRUE = 1; The use of fullword external literals in comparisons and in other expressions effect both program space execution time. For example, using the external literals EXTERNAL LITERAL ONE, TRUE; II-8-9 BLISS Primer Volume 2: Intermediate Optimization the routine (BLISS~32) ROUTINE EXT= BEGIN LOCAL X; X = 0; IF TRUE EQL 1 THEN X = .X + ONE; END; EXT: 1 $: .WORD CLRL CMPL BNEQ ADDL2 CLRL RET AM<> R0 iTRUE,il 1$ iONE,R0 R0 has a size of 23 bytes. On the other hand, the same routine using external literals that include the field size EXTERNAL LITERAL ONE: UNSIGNED (4 ) , TRUE:UNSIGNED(4); generates the same code but has a routine size of only 15 bytes. Of course, completely eliminating these external literals decreases the routine size to nine bytes and produces better code: EXT: .WORD CLRL INCL CLRL RET AM<> R0 R0 R0 MINIMIZING TEMPORARIES In general, th~ use of temporary storage is also discouraged. This will probably appear strange to more experienced higher~level programmers, particularily those who are accustomed to FORTRAN type languages. For example, code equivalent to the BLISS II-8-l0 BLISS Primer Volume 2: Intermediate Optimization TEX: ROUTINE TEX= BEGIN LOCAL TEMP; TEMP = .A + .B ~ .C; IF .TEMP GTR 100 THEN 1 1 $: ELSE ~ .WORD ADDL3 SUBL2 CMPL BLEQ MOVL RET CLRL RET AM<> B,A,R0 C,R0 R0,1100 1$ Il,Re R0 END; is often necessary. The variable TEMP is used in this example to provide a single variable on which to perform the conditional test. Assuming that TEMP is a local variable, the routine size is 31 bytes. In this example the compiler is able to allocate TEMP to a register, because this routine is small and, therefore, the object code is identical to that produced for the following source code without the temporary variable: ROUTINE TEX= BEGIN IF (.A + .B ~ .C) GTR 100 THEN 1 ELSE o END; However, as the complexity of the algorithm and the number of temporary variables increases, the ability of the compiler to best utilize the existing registers and, therefore, to produce optimum code is severly hampered. This is particularily true of control~flow values since these values need not necessarily be allocated storage. Control~flow expressions evaluate to a true or false indicator which determines whether or not to jump. If st~tic storage had been used in the original example instead of local storage, the routine size would have increased five bytes to 36 bytes. This is depicted below: II-8-ll BLISS Primer Volume 2: Intermediate Optimization TEX: M<) B,A,R0 C, R0, TEMP TEMP,#100 1$ #1,R0 .WORD ADDL3 SUSL3 CMPL BLEQ MOVL RET 1 $: CLRL RET A R0 A more reasonable example that involves several temporary variables and which does result in savings, even when using local variables, is shown below: ROUTINE CMP= CMP: "M<R2) BEGIN .WORD LOCAL MULL3 #10,X,Rl MCOML A, Z, R2 BICL3 B, R2,Y,R0 #20,y,R2 SUBL3 C; BISL2 Rl,R0 A = .X * 10; B = .Z AND .Yi BISL3 R2,R0,Rl C = .Y ., 20; BLBC Rl,l$ A = .A OR .B OR .C; #1, R0 MOVL IF .A RET THEN R0 1 $: CLRL RET 1 ELSE o END; The temporary variables in this example require five additional bytes of storage and also preclude the compiler from generating code that could avoid evaluation of unnecessary expressions. Note the difference when the temporary variables are eliminated: ROUTINE CEX= BEGIN IF (.x * 10) OR ( • Z AND .Y) OR (.Y" 20) THEN 1 ELSE END; CEX: 1 $: 2$ : ° 3 $: 11-8-12 .WORD MULL3 BLBS BLBC BLBS SUBL3 BLBC MOVL RET CLRL RET "M<) #10,X,R0 R0,2$ Z,l$ Y,2$ #20,Y,R0 R0,3$ #1,R0 R0 BLISS Primer Volume 2: Intermediate Optimization In addition to significantly reducing the routine size, produced is better optimized. It now evaluates expressions necessary to satisfy the test condition. the code only the There is, however, a trade~off between source code optimization and obscurity. After all, production programs must be maintained and programmers attempting to maintain code that has been unnecessarily "tweaked" may have difficulties understanding and, subsequently, modifying it. The Style Guide in the VAX,11 Software Engineering Manual should therefore be consulted for coding practices which are to be avoided. Also applicable to a discussion of minimizing temporaries is the capability of the compiler to recognize common subexpressions, because the elimination of common sUbexpressions is a typical use of temporaries. The BLISS-32 compiler can and does recognize common sUbexpressions if they are written correctly. For example, ROUTINE CSB= BEGIN IF .N THEN BEGIN X = .X + 1; Z = 0; END ELSE BEGIN Z = 4; X = 1 + .X; END END; CSB: M<> .WORD MOVL BLBC ADDL3 X,R0 N,l$ #1,R0,X C~L Z 1$: BRB MOVL ADDL3 2$: C~L 2$ #4,Z #1,R0,X R0 RET contains code which is common to both branches; however, as written, it was not identified by the compiler as a common subexpression. If the two expressions had been written identically each time, the compiler would h~ve recognized them as common subexpressions and would have produced the following code: 11-8-13 BLISS Primer Volume 2: Intermediate Optimization ROUTINE eSB BEGIN IF • N THEN BEGIN X = .X + 1; CSB: .WORD ADDL3 MOVL BLBC CLRL BRB MOVL CLRL RET Z = 0; END 1 $: 2$: ELSE BEGIN Z = 4; X = .X + 1; END M<> #1,X,R0 RO,X N,l$ Z 2$ #4,Z R0 END; This routine is six bytes smaller than the previous version, which required 38 bytes. CROSS JUMPING Common sUbexpressions are recognized as parts of expressions which are identical, wherever they occur. Another source of optimization is cross jumping which occurs when common code can be identified in two or more branches. For example, the routine GP below ROUTINE GP= BEGIN IF .K GTR 0 THEN (RTN (. X) ; K = • K + 1) ELSE RTN (3) END; GP: 1 $: .WORD TSTL BLEQ PUSHL CALLS ADDL3 MOVL RET PUSHL CALLS RET AM<> K 1$ X #1, RTN #1,K,R0 R0,K #3 #1, RTN calls the function RTN in both the THEN and ELSE branches. As it is written, it has a routine size of 37 bytes and requires 11 instructions. But by rearranging the routine call so that it is the last entry in each branch, the compiler can combine the calls to RTN. The resulting routine II-8-14 BLISS Primer Volume 2: Intermediate Optimization ROUTINE GP= BEGIN IF .K GTR 0 THEN (K GP: = •K + 1; RTN ( • X) ) ELSE RTN(3) END; 1$: 2 $: .WORD MOVL BLEQ ADDL3 PUSHL BRB PUSHL CALLS RET . . M<> K,R0 1$ #1,R0,K X 2$ #3 #l,RTN is smaller in size by eight bytes and has only nine instructions. Another example of cross jumping where expressions are involved is depicted below: ROUTINE CSX= CSX: BEGIN CASE N FROM o TO 2 OF SET 1 $: (0] : (X=.X+l;Y=.Y+l;Z=0); (1 ] : (Y=l+.Y;Z=l;X=.X+l); (2] : (Z=2;Y=.Y+l;X=1+.X); 2$: (OUTRANGE] : Z=3 TES END; 3 $: 4 $: 5$: .WORD MOVAL CASEL .WORD .WORD .WORD MOVL MOVL RET INCL ,INCL CLRL CLRL RET INCL MOVL BRB MOVL INCL ADDL3 MOVL RET several common . . M<> N,Rg R0,#0,#2 2$=-1$ 3 $,,1 $ 4$=-1$ #3,Z #3, R0 X Y Z R0 Y #l,Z 5$ #2,Z Y #1,X,R0 R0,X Notice that much of the code is duplicated for in=-range values; however, as it is written, this code was not identified by the compiler as common and was therefore not eliminated. If the common code had been arranged in a group and positioned at the end of.each block, as shown below, 11-8-15 BLISS Primer Volume 2: Intermediate Optimization ROUTINE CSX= BEGIN CASE N FROM " TO 2 OF SET CSX: 1$: [ "] : (Z="iX=.X+liY=.Y+l); [1 ] : (Z=liX=.X+l;Y=.Y+l); '[ 2] : (Z=2;X=.X+l;Y=.Y+l); [OUTRANGE] : Z=3 i TES; END; 2$: 3$: 4$: 5$: .WORD MOVAL CASEL .WORD .WORD .WORD MOVL MOVL RET CLRL BRB MOVL BRB MOVL INCL ADDL3 MOVL RET AM<> N,R" R0,#",#2 2$",,1$ 3$"..1$ 4$",,1$ #3,Z #3,R" Z 5$ #l,Z 5$ #2,Z X #l,Y,R" R",Y the compiler could recognize this duplication and would generate only one such sequence. The resulting routine is 13 bytes smaller than the previous version. SEQUENTIAL PROCESSING Another source of potential optimization occurs when accessing storage. In general, the compiler can optimize accessing and/or storing operations if the code is sequentially executed. This means that the programmer should attempt to perform like operations together. For example, ROUTINE SBX = BEGIN BV<0,4> = 0; T = • z; BV<7,1> = 0; BV<S,3> = 0; END; SBX: .WORD BICB2 MOVL BICB2 CLRL RET M<> #15,BV Z,T #224,BV R" resets the three fields of the longword, BV but the code does not perform the operation sequentially. It is interrupted with an unrelated assignment. Because the impact of. this unrelated assignment can not be anticipated by the compiler, the interruption results in the execution of the first assignment. As a result, the routine requires two instructions to store this data 11-8-16 BLISS Primer Volume 2: Intermediate Optimization into the three fields. Note that the two were consolidated into one instruction. bytes of storage. If, on the other hand, these sequentially, as below, subsequent assignments The routine requires 23 assignments ROUTINE SBX BEGIN BV<0,4> = 0; BV<7,l> = 0; BV<S,3> = 0; T = .Z; END; had been written SBX: .WORD BICB2 MOVL CLRL RET M<> i239,BV Z,T R0 the compiler would be able to consolidate the three storage operations into one instruction. The resulting code requires less space by five bytes and is also faster. CONDITIONALS In BLISS the user has many ways of coding a conditional expression, including case, select, selectone, and nested IF-THEN-ELSE. Besides the differences in readability, there are also differences with respect to optimization. To demonstrate this, consider the problem of counting the occurrences of the numbers one through four stored in a vector named TABLE. Although the solution is obviously well-suited to a case expression, it could be accomplished with anyone of the various conditional expressions and therefore provides a reasonable comparision. As a case expression the routine 11-8-17 BLISS Primer Volume 2: ROUTIN E COND= . BEGIN INCR I FROM 0 TO 999 DO CASE .TABLE[.I] FROM 1 TO 4 OF SET Intermediate Optimization COND: 1 $: 2$: [1 ] : FRESHMAN(); [2] : SOPHMORE () ; 3$: [3] : JUNIOR () ; 4$: [4 ] : SENIOR () ; [OUTRANGE] : ERROR () TES END; 5$: 6$: 7$: .WORD CLRL CASEL .WORD .WORD .WORD .WORD CALLS BRB CALLS BRB CALLS BRB CALLS BRB CALLS AOBLEQ MNEGL RET "M(R2> R2 T[R2],#1,#3 3$-2$ 4$-2$ 5$-2$ 6$-2$ #~,ERROR 7$ #~,FRESHMAN 7$ #~,SOPHMORE 7$ #~,JUNIOR 7$ #~,SENIOR #999,R2,1$ #l,R~ generates particularly fast code because it has an equivalent machine instruction. Having a routine size of 64 bytes, it is also the smallest possible configuration produced by any of the conditional expressions below. 11-8-18 BLISS Primer Volume 2: Intermediate Optimization The equivalent select expression ROUTINE COND= BEGIN INCR I FROM 0 TO 999 DO SELECT .1 OF SET COND: 1$: [1 ] : FRESHMAN () ; [2] : SOPHMORE () ; 2$: [3] : JUNIOR (); [4] : SENIOR () ; [OTHERWISE] : ERROR (1 TES END; 3$: 4$: 5$: 6$: .WORD CLRL MOVL CMPL BNEQ CLRL CALLS CMPL BNEQ CLRL CALLS CMPL BNEQ CLRL CALLS CMPL BNEQ CLRL CALLS BLBC CALLS AOBLEQ MNEGL RET "M<R2,R3,R4> R2 T[R2],R4 R4,tl 2$ R3 to,FRESHMAN R4,t2 3$ R3 to,SOPHMORE R4,t3 4$ R3 to,JUNIOR R4,t4 5$ R3 to,SENIOR R3,6$ to,ERROR t999,R2,1$ tl, R0 requires 81 bytes and utilizes slower compare and branch instructions. Although a select expression is probably easier to read, the code produced strongly resembles the code generated for the equivalent nested IF-THEN-ELSE construction: 11-8-19 BLISS Primer Volume 2: ROUTINE COND= BEGIN INCR I FROM ~ TO 999 DO IF .I EQL 1 THEN FRESHMAN () ELSE IF .I EQL 2 THEN SOPHMORE () ELSE IF .I EQL 3 THEN JUNIOR () '"' ELSE IF .I EQL 4 THEN SENIOR () ELSE ERROR () END; Intermediate Optimization COND: 1 $: 2$: 3 $: 4$: 5$: 6$: .WORD CLRL MOVL CMPL BNEQ CALLS BRB CMPL BNEQ CALLS BRB CMPL BNEQ CALLS BRB CMPL BNEQ CALLS BRB CALLS AOBLEQ MNEGL RET M<R2,R3> R3 T[R3],R2 R2,#1 2$ #0,FRESHMAN 6$ R2,#2 3$ #0,SOPHMORE 0$ R2,#3 4$ #0,JUNIOR 6$ R2,#4 5$ A #~,SENIOR 6$ #0,ERROR #999,R3,1$ #1,R0 However, the routine with the nested IF-THEN-ELSE expression requires only 75 bytes and has the advantage of exiting the routine after executing the expressions following the match. The IF-THEN-ELSE expression generates identical code· to that produced for the equivalent selectone expression: ROUTINE COND= BEGIN INCR I FROM 0 TO 999 DO SELECTONE .TABLE[.I] OF SET [1 ] : FRESHMAN () ; [2] : SOPHMORE () ; [3] : JUNIOR (); [4] : SENIOR () ; [OTHERWISE] : ERROR(); TES END; II-8-2~ BLISS Primer Volume 2: Intermediate Optimization Exercises In each of the exercises below, modify the BLISS-32 source code so that the routine size of each object module produced by the compiler is reduced by at least six bytes: 1) ROUTINE SX= !ROUTINE SIZE 67 BYTES !++ THIS ROUTINE CHANGES SQUARE AND FANCY BRACKETS INTO THEIR EQUIVALENT PARENTHESIS. "TYPE" IS STATIC STORAGE DECLARED IN AN OUTER BLOCK. 1-- BEGIN TYPE = ( SELECT .TYPE OF SET [%C ' [ " %0' 173 ' ]: %C' ( , ; [%C ' ] " %0 'I 7 5 %C ' ]: %C')'; [OTHERWISE]: ~ TES) END; 2) ROUTINE SP CHAR (TYPE)= lROUTINE SIZE 71 BYTES 1++ THIS ROUTINE CONVERTS SELECTED SPECIAL CHARACTERS TO THEIR FUNCTIONAL EQUIVALENTS AND RETURNS THAT VALUE. 1-- BEGIN EXTERNAL FLAG; EXTERNAL LITERAL SETONE; !SETONE = 1 LOCAL TEMP; SELECT .TYPE OF SET [ %C ' [ , ] : [ %C ' , ] : [ %C ' ] , ] : [OTHERWISE] : TEM P = %C' ( , ; TEMP = %C I I ; TEMP = %C') , ; BEGIN FLAG = SETONE; TEMP = .TYPE END TES; • TEMP END; 11-8-21 BLISS Primer Volume 2: Intermediate Optim i zation This page intentionally left blank. II-8-22 BLISS Primer Volume 2: Optimization Intermediate Solutions 1) !ROUTINE SIZE 61 BYTES ROUTINE SX: NOVALUE= 1++ THIS ROUTINE CHANGES SQUARE AND FANCY BRACKETS INTO THEIR EQUIVALENT PARENTHESES. "TYPE" IS STATIC STORAGE DECLARED IN AN OUTER BLOCK. BEGIN TYPE = ( SELECTONE .TYPE OF SET [%C ' [ , , %0 ' 1 7 3 ' ]: %C' ( , ; [ %C • ] , , %0 ' 1 75 ' ]: %C')'; [OTHERWISE]: 0 TES) END; 2) lROUTINE SIZE 39 BYTES ROUTINE SP CHAR (TYPE)= 1++ THIS ROUTINE CONVERTS SELECTED SPECIAL CHARACTERS TO THEIR FUNCTIONAL EQUIVALENTS AND RETURNS THAT VALUE. 1-- BEGIN EXTERNAL FLAG; EXTERNAL LITERAL SETONE: UNSIGNED(l); RETURN ( CASE .TYPE FROM %0'133' TO %0'135' OF SET [ %C ' \ ' ]: %C' /' ; [ %C ' [ , ]: %C' ( , ; [ %C ' ] , ]: %C')'; [OUTRANGE]: (FLAG = SETONE; .TYPE) TES) END; 11-8-23 BLISS Primer Volume 2: Intermediate Optimization This page intentionally left blank. 11-8-24 BLISS Primer Volume 2: Intermediate Optimization Unit Test Modify the following BLISS,32 source code so that the current routine size of the object code produced by the compiler is reduced by at least 11 bytes: MODULE TEST(MAIN= BEGIN EXTERNAL ROUTINE PROC; EXTERNAL LITERAL NULL, SETONE; 1=0 1=1 GLOBAL FLAG; ROUTINE SP_CHAR(TYPE}= !ROUTINE SIZE 86 BYTES 1++ THIS ROUTINE CONVERTS SELECTED SPECIAL CHARACTERS TO THEIR EQUIVALENT AND RETURNS THAT VALUE. 1,- BEGIN LOCAL TEMP; TEMP = .TYPE; SELECT .TYPE OF SET [%C ' [ , ] : TEMP = %C' ( , ; [%C '\ ' ] : TEM P = %C' /' ; [ %C '] , ] : TEMP = %C')'; [OTHERWISE] : FLAG = SETONE; [ALWAYS] : (FLAG = NULL; PROC(.TEMP) TES; .TEMP END; END ELUDOM 11-8-25 BLISS Primer Volume 2: Intermediate Optimization This page intentionally left blank. 11-8-26 DEBUGGING TECHNIQUES MODULE 11-9 11-9-1 BLISS primer Volume 2: Intermediate bebugging Techniques Course Map II-9-2 BLISS Primer Volume 2: Intermediate Debugging Techniques Introduction This unit illustrates a variety of code which can be added to a module to facilitate subsequent testing and debugging. In general, the code consists of macros constructed with the conditional compilation mechanism. 1I-9-3 BLISS Primer Volume 2: Intermediate Debugging Techniques _-------------Objectives - - - - - - - - - - - - - - - , Given a module with one or more routines, be able to insert conditional code that can be used to monitor and debug the module • . . . . - - - - - - - - - - - - - Sample Test Items - - - - - - - - - - - -..... Given the module TEST.BLI (on your disk area and in Attachment II), which includes trace and monitor macros, insert the necessary macro calls to test and debug the program. Execute the program and identify the existing bugs. - - - - - - - - - - - - Additional Resources None II-9-4 BLISS Primer Volume 2: Intermediate Debugging Techniques As most production programmers are aware, debugging can and usually does consume a significant part of the time required to produce a substantially error free program, i.e., a program containing no branches that: * * * produce exception conditions that prematurely terminate execution result in an infinite loop produce an erroneous result When one or more of these error conditions are encountered, the programmer has the problem of identifying and isolating the "bug". A variety of methods can be used including (but not limited to): * * * * reviewing the source code consulting with the local "expert" inserting code to output periodic messages/data using a debugger program A point to consider when reviewing segments of source code, which logically (to you) should contain the problem but which appear correct, is that this code may in fact be correct. Therefore, after a thorough analysis of the segment has been conducted without finding the "bug", consider other reasons which could produce the error condition. This will frequently reveal the problem and save many frustrating hours. A more aggressive approach in the attempt to error-free code is to program defensively. This includes: * * * prod~ce checking input parameters for validity making internal consistency checks providing built-in testing facilities This unit concentrates on techniques for the latter and explores a variety of possible source code insertions which can be used at execution time to identify and isolate "bugs". This code is constructed using conditional compilation so as not to adversely affect the execution time of the finished program. 1I-9-5 BLISS Primer Volume 2: Intermediate Debugging Techniques TRACE FACILITY The mere isolation,of a "bug" can be a significant task. This is apparent to anyone who has had a program-stop with the diagnostic: ?ILL MEM REF AT USER PC xxxxxxx Because this address mayor may not be in a routine, the diagnostic does not necessarily isolate the problem to a routine, and, even if it did, it can not identify the recursion level at which the error occurred. As a consequence, many hours can be spent attempting to isolate the problem. The time is, of course, dependent upon the experience of the programmer, the debugging facilities available, and the size of the program. Infinite loops can cause similar difficulties. One solution is a simple trace mechanism to identify the routine and the level of nesting at which the problem appears. Fo r example, MACRO $TRACE(TIND, TNAME) = %IF %SWITCHES(DEBUG) %THEN TTY PUT QUO(%STRING«TIND),' ROUTINE ',(TNAME), %CHAR(%O'IS',%O'12'») %FI %; can be used with any routine such as ROUTINE EVAL STACK (STACK ADDR,STACK_LEN,CURRENTOP) = BEGIN ••• $TRACE('ENTER', 'EVAL_STACK'); · .. $TRACE ('EXIT', 'EVAL_STACK'); ·.. END; to produce a trace of each call of that subsequent exit by providing the messages: ENTER ROUTINE EVAL STACK EXIT ROUTINE EVAL STACK 11-9-6 routine and each BLISS Primer Volume 2: Intermediate Debugging Techniques Because the macro is constructed with a conditional compilation dependent upon the debug switch, the code for the trace is generated only when the debug switch is activated. This simple mechanism can isolate a problem regardless of the nesting level at which it appears. It therefore facilitates testing because the routine order is generally known. FORMATTED VARIABLES Another potentially annoying problem, even using a debugger program, is the display of data. Data frequently consists of varying types (i.e., integer, ASCII, etc.) or is packed into irregular size fields. For example, the block (32-bit machine) NAME(32) TYPE (2) where I TABLE: DATA(30) NAME = 'Rl' TYPE = 1 (designating an integer) DATA = 38 (decimal) would, if dumped in hexadecimal with a conventional debugger, be displayed as TABLE/ TABLE+4/ 00005231 40000026 or if dumped in ASCII mode: TABLE/ Rl TABLE+4/ @ *1 Neither is extremely useful, and a long table displayed in either format would be extremely frustrating. An alternative is to insert code which interpretes the structure and displays the data in the appropriate mode. For example (BLISS-32), 1I-9-7 BLISS Primer Volume 2: Intermediate Debugging Techniques MACRO $DUMP BLOCK = 'IF 'SWITCHES(DEBUG) 'THEN INCR I FROM ~ TO 24 BY 8 DO IF .TABLE[~]<.I,8> EQL 9 THEN EXITLOOP ELSE TTY_PUT_CHAR(.TABLE[~]<.I,8»; TTY_PUT_CRLF (); IF TTY PUT INTEGER(.TABLE[I]<39,2>,1~,1) EQL 1 THEN TTY PUT INTEGER(.TABLE[l]<9,39>,1~,1~) ELSE BEGIN TTY PUT INTEGER(.TABLE[1]<15,15>,1~,5); TTY-PUT-QUO (. / .); TTY-PUT-INTEGER(.TABLE[1]<~,15>,1~,5); END- 'FI - %; ••• ROUTINE EVAL STACK (STACK ADDR,STACK LEN,CURRENT OP)= BEGIN - ·.. $DUMP_BLOCK; ••• $DUMP_BLOCK; · .. END; dumps the data in TABLE at the beginning and end of each the routine EVAL STACK in the format: Rl 38 1 or if TYPE = 0 (designating a fraction) DATA = 3~~010 (in octal) in the format: Rl 3/8 11-9-8 call to BLISS Primer Volume 2: Intermediate Debugging Techniques This macro could also have been whistles: written with a few bells and MACRO $DUMP BLOCK = %IF %SWITCHES(DEBUG) %THEN TTY PUT QUO (%STRING( 'TYPE "Y" FOR DUMP', %CHAR(%0'IS,%0'12'»); IF TTY GET CHAR() EQL %C'Y' THEN BEGIN TTY_PUT_QUO ('NAME: '); INCR I FROM 0 TO 24 BY 8 DO IF .TABLE[0]<.I,8> EQL 0 THEN EXITLOOP ELSE TTY_PUT_CHAR(.TABLE[0]<.I,8»; TTY_PUT_CRLF (); IF .TABLE[I]<30,2> EQL 1 THEN BEGIN TTY PUT QUO (' INTEGER: '); TTY-PUT-INTEGER(.TABLE[I]<0,30>,10,10); ENDELSE BEGIN TTY PUT QUO('FRACTION: I); TTY-PUT-INTEGER(.TABLE[I]<IS,IS>,10,S); TTY-PUT-QUO (' / '); TTY-PUT-INTEGER(.TABLE[1]<0,IS>,10,5); END; END %FI %; This version permits, the user to determine at the time "$DUMP BLOCK" is invoked whether or not to dump the data in TABLE by responding to ,the message: TYPE "Y" FOR DUMP II-9-9 BLISS Primer Volume 2: Intermediate Debugging Techniques If a Y is typed, the following output occurs: NAME: INTEGER: Rl 38 NAME: FRACTION,: Rl 3/8 or It is important to note that the the macro with a conditional compilation and, therefore: 1) 2) is constructed No debugging code is generated unless the appropriate switch is activitated; consequently, execution time is not affected when that switch is off. Using a macro permits a simple one line entry that makes the code convenient to generate and also permits it to be used for more than one routine. MONITORING VALUES Another convenient facility is the ability to examine the value of predetermined variables while the program is executing. Minimally, one would like to know the initial and final values of selected variables within each routine. A macro to accomplish this is depicted below: COMPILETIME TESTING = 1; ••• MACRO $LOOK(NAME, VAL) []= %IF TESTING %THEN BEGIN TTY PUT QUO(%STRING«NAME), ': I); TTY-PUT-INTEGER«VAL),lS,lS); TTY-PUT-CRLF ( ) ; $LOOK(%REMAINING); END %FI %; II-9-lS BLISS Primer Volume 2: Intermediate Debugging Techniques ROUTINE EVAL STACK (STACK ADDR, STACK_LEN, CURRENT_OP)= BEGIN - ... ... $TRACE('ENTER', 'EVAL STACK'); $LOOK('STACK ADDR', .STACK ADDR, 'STACK-LEN', .STACK LEN, 'CURRENT_OP', .CURRENT_OP); $TRACE (' EXI T', 'EVAL STACK'); $LOOK (' RETURN', • TEMP) ; RETURN .TEMP; END; As used in the routine "EVAL STACK" above, ENTER ROUTINE EVAL STACK STACK ADDR xxx STCK LEN xxx CURRENT OP xxx is output to the TTY each time the routine is entered and EXIT ROUTINE EVAL STACK RETURN xxx is output as the final instruction prior to returning to the calling routine. Note that once the macro is constructed, the additional coding to insert this facility or any other is negligible especially considering the potential benefits. ERROR CHECKING A more subtle form of debugging occurs in bounds checking. This facility cari be performed without obvious interaction, at least until an error is detected. Debugging in this manner is feasible since many parameters are predictable within reasonable limits and can therefore be bounded. For example, SELECT .OPNAMES OF SET .[ .%C. • ( • ]: 0 ; [%C ' =' ]: 9; [OTHERWISE]: ERROR(3); II-9-11 BLISS Primer Volume 2: Intermediate Debugging Techniques produces an error message (e.g., "?ILL OP TYPE - RETYPE LINE") if the contents of OPNAMES is not one of the acceptable characters; however, the actual problem producing this message would have to be further researched. However, if the code had been wr~tten [OTHERWISE] : BEGIN ERROR(3); $LOOK ( 'OPNAMES " END; • OPNAMES) ; the output would have been displayed as ?ILL OP TYPE - RETYPE LINE OPNAMES xxx depicting at least the contents of OPNAMES at the time of the error and possibly indicating the source of the problem. Another example of bounds checking performed only during debugging is shown below: MACRO $CHECK(NAME, NR, LOW, HIGH)= %IF %SWITCH(DEBUG) %THEN IF (NR) LSS (LOW) OR (NR) GTR (HIGH) THEN BEGIN TTY PUT_QUO {%STRING( , %WARN , (NAME) , , EXCEEDS BOUNDS TTY PUT_INTEGER ( (NR) ,10, 10) ; END%FI %; ... ' ); .$CHECK .. ('VAL', • VAL, 0, 1000); IF .VAL LSS .CONDITION THEN ... ELSE IF .VAL GTR .PROCESS THEN ...,. Thus, as in the above example, critical values can be monitored and reported, via the TTY, when they exceed reasonable limits established by the programmer: %WARN VAL EXCEEDS BOUNDS ••• 11-9-12 xxxx BLISS Primer Volume 2: Intermediate Debugging Techniques This is particularly beneficial when values are assumed never to be outside of a given range, and, therefore, an error indicates an oversight in design or a "bug" in the program. Although many of the above mechanisms are possible with a debugger, some "bugs" can elude detection without extensive testing but can be detected from a display of intermediate data and/or traces during execution. Most important, this code is easily eliminated with a switch, yet it can be reactiviated for subsequent testing or modification if necessary. ~------------------------Note------------------------~ A word of caution: the use of debugging code which is not thoroughly tested can generate "bugs" which are more elusive than those the code was intended to detect. Therefore, use only those features that contribute to identifying potential problems, aid in subsequent elimination of "bugs", and/or which have been tested prior to use - i.e., keep it simple. This can be accomplished by confining the code to macros (or routines) and by possibly maintaining it in tested REQUIRE files. II-9-l3 BLISS Primer Volume 2: Intermediate Debugging Techniques This page is for notes. 11-9-14 BLISS Primer Volume 2: Intermediate Debugging Techniques ATTACHMENT #1 MODULE TEST (MAIN=R1) BEGIN = REQUIRE 'TUTIO'; COMPI LETIME TESTING = 1; LITERAL CR = 13, LF = 10, ASCII ZERO = 48, YES =78, NO = 67; CARRIAGE RETURN LINE FEED = "0" = "Y" = "N" OWN X: INITIAL (0) ; MACRO STRIP CRLF () = TTY_GET_CHAR() %; MACRO $TRACE(TIND, TNAME} = %IF TESTING %THEN TTY PUT QUO(%STRING«TIND),' ROUTINE ',(TNAME), %CHAR(CR,LF»} %FI %; MACRO $LOOK(NAME, VAL) []= %IF TESTING %THEN TTY PUT QUO (%STRING «NAME), ':'}}; TTY-PUT-INTEGER«VAL},10,10}; TTY-PUT-CRLF (); $LOOK(%REMAINING) %FI %; FORWARD ROUTINE R1, R2, R3, R4; 11-9-15 BLISS Primer Volume 2: Intermediate Debugging Techniques ROUTINE Rl = BEGIN LOCAL ANS, TEMP; IF .X NEQ ({J THEN R3(~); TTY PUT QUO('TYPE A NUMBER 1 THRU 7 I); TEMP = TTY GET CHAR() - ASCII_ZERO; STRIP CRLF; X = • TEMP; TTY PUT CRLF () ; TTY-PUT-QUO('YOU TYPED ••• I); TTY-PUT-CHAR(.TEMP+ASCII ZERO); TTY-PUT-CRLF(); TTY-PUT-QUO (' TYPE tty II FOR YES OR .. N" FOR NO ANS-= TTY GET CHAR(); TTY PUT CRLF (f; STRIP_CRLF; IF .ANS EQL YES THEN R2 ( • TEMP) ELSE IF .ANS EQL NO THEN R3 (.TEMP-l); IF .X NEQ THEN Rl () ; ~ R4 (); END; II-9-16 ' ); BLISS Primer Volume 2: Intermediate Debugging Techniques ROUTINE R2(ARH)= BEGIN IF .ARH NEQ .X THEN BEGIN TTY PUT QUO('YOU CHEATED'); TTY-PU~-CRLF (); R1 (); - END; TTY_PUT_QUO('MODULUS 4 OF YOUR INPUT IS?? IF (TTY GET CHAR() - ASCII_ZERO) NEQ R3(ARH) THEN BEGIN STRIP CRLF; R1 () ; - END; STRIP CRLF; END; ROUTINE R3(A)= BEGIN IF .A EQL .X THEN X = " ELSE R2(.A); RETURN (.A MOD 2); END; ROUTINE R4 = BEGIN TTY PUT QUO('EXIT'); TTY-PUT-CRLF () ; END; END ELUDOM II-9-17. I); BLISS Primer Volume 2: Intermediate Debugging Techniques This page is for notes. 11-9-18 BLISS Primer Volume 2: Intermediate Debugging Techniques Exercises 1. Write two macros $SAVE and $CHANGE which can be used conditionally with the debug switch to monitor a single variable. The macro $SAVE should save the initial value of the variable at the time of the macro call and the macro $CHANGE should report its old and current value if a change has occurred. 2. Write the macro $PAUSE which would allow a user to conditionally invoke the debugging routine DUMP STRU which dumps global data structures. The macro should be conditional on the COMPILETIME constant TESTING. II-9-19 BLISS Primer Volume 2: Intermediate Debugging Techniques This page intentionally left blank. 11-9-29 BLISS Primer Volume 2: Intermediate Debugging Techniques Solutions 1) MACRO $SAVE{VAL) = 'IF 'SWITCHES{DEBUG) %THEN LOCAL 'NAME {'STRING {' S$', (VAL»; 'NAME {'STRING (' S$', (VAL» = • (VAL) 'FI %, $CHANGE (VAL) = 'IF %SWITCHES{DEBUG) %THEN IF .%NAME{'STRING ('S$', (VAL» NEQ • (VAL) THEN BEGIN TTY PUT QUO {%STRING «VAL), 'OLD'); TTY-PUT-INTEGER{.'NAME('STRING('S$', (VAL}),19,5); TTY PUT QUO ('NEW' ) ; TTY-PUT-INTEGER (. (VAL) ,19, 5) ; END; %FI %; 2) MACRO $PAUSE = %IF TESTING %THEN TTY PUT QUO (' TYPE "Y" TO CALL DEBUG ROU·rINE '); IF TTY GET CHAR() EQL %e'Y' THEN DUMP STRU () ; STRIP_CRLF () ; %FI %; Note: The routine (or macro) STRIP CRLF strips the carriage return and/or. line feed characters- so that other input is not affected. 11-9-21 BLISS Primer Volume 2: Intermediate Debugging Techniques This page intentionally left blank. 11-9-22 BLISS Primer Volume 2: Intermediate Debugging Techniques Unit Test Given the module TEST.BLI (on your disk area and in Attachment II) which includes trace and monitor macros, insert the appropriate macro calls to test and debug the program. Execute the program and identify the existing bugs. Note: Do not attempt to debug the program before inserting the debugging code: the routines are small and therefore not difficult to debug by analyzing the source code. For your convenience, the macros $TRACE $LOOK are included in the module. Assuming the given, the order of execution is: correct responses in Rl --> in R2 --> in R3 --> out R3 --> out R2 --> i,n R4 --> out R4 --> out Rl 11-9-23 are BLISS Primer Volume 2: Intermediate Debugging Techniques This page intentionally left blank. 11-9-24 UTILITIES MODULE 11-10 11-11-1 BLISS Primer Volume 2: Intermediate Utilities Course Map II-1S-2 BLISS Primer Volume 2: Intermediate Utilities I "troduction This unit presents some of the useful utilities provided for the BLISS language translators. Included utilities are PRETTY, BLSCRF, CONDEN, CVT10 and CVTll, and MODULE. 11-10-3 BLISS Primer Volume 2: Intermediate Utilities - - - - - - - - - - - - - - - O b j e c t i v e s - - - - - - - - - - - - - - -..... This unit exists for the purpose of acquainting the reader with a subset of the utilities provided for the BLISS programmer • . . . . . - - - - - - - - - - - - - Sample Test Items - - - - - - - - - - - - - - . Using the text as necessary, list provided for the BLISS programmer, usage • at least four utilities along with their intended . . . . . - - - - - - - - - - - - . Additional Resources, VAX-ll BLISS-32 USER'S GUIDE Chapter 8 Section 2 Certain .DOC and .HLP files, including 11-10-4 PRETTY. HLP BLSCRF.HLP CVT10.HLP,.DOC CVTll.HLP, .DOC MODULE.BLI BLISS Primer Volume 2: Intermediate Utilities PRETTY PRETTY is a utility program which accepts a BLISS source file and produces a reformatted source file (and optionally a specially formatted listing file), using formatting rules as specified in the VAX-II Software Engineering Manual. The output file will have all whltespace (except in strings, macro definitions, comments, and certain PLIT bodies) removed and replaced. Control expressions are indented according to hierarchical structure. To invoke PRETTY, type ·PRETTY'. It will prompt with for a file specification line of the form 'BLF>' input.ext [/OUTPUT:name.ext] [/LISTING :name.ext] [/EXIT] where 'input.ext' is the source file specification. The bracketed options are available: prompting may be used also. The default file names are that of the input file. The output file extension .defaults to that of the input; the listing file extension defaults to '.LST'. (Note: Production of the listing file doubles PRETTY run time.) Specific formatting options can be supplied to PRETTY by means of directives inserted as full-line comments into the source text. (There are more than 2rtJ such options. For a full list, see the file, PRETTY.HLP.) Using these options, one can specify variations in the formatting of pages, macros, PLITs, error messages, upper and lower case, and synonyms. Here's an example of PRETTY usage. is called UGLY.BLI and looks like this: The file to be PRETTYed MODULE UGLY (MAIN = B) = BEGIN ROUTINE B = BEGIN TTY_PUT_QUOC'YUP'); END; END ELUDOM UGLY is syntactically correct; 'PRETTY' it up. but difficult to read. @pretty PRETTY version 6 BLF>ugly.bli/output:nice.bli/exit MODULE SMA LL ROUTINE B @ty nice.bli MODULE SMALL CMAIN = B BEGIN ROUTINE B = BEGIN ) = II-lrtJ-S Now we'll BLISS Primer Volume 2: Intermediate Utilities TTY PUT QUO ('YUP I ) ; END; ~D ELUDOM @ Note that PRETTY tells the user what modules and routines it is in the process of 'PRETTY'ing up. By the use of PRETTY, one can tell at a glance if the code indention properly reflects the program "logic. If the 'PRETTY'ed file has a different indention format than the original file, perhaps it is due to the program logic being different than intended. PRETTY is, in this manner, a valuable tool for program development. BLSCRF - (BLISS CROSS REFERENCE) BLSCRF is a program which cross references BLISS source files. BLSCRF is invoked by the command 'BLSCRF', returning a single asterisk as a command line prompt. The user may now type a series of cross reference requests. The command line has the form: outfil,gxrfil=srcfil/switch/switch ••• where either "outfil" or ",gxrfil" (but not both) may be omitted and where all switches are optional. The default file extensions are srcfil: outfil: BLI (,B32, B16, B36, B10, Bll) XRF (GXR if IF is specified with a single output file) gxrfil: GXR REQUIRE file: REQ (,B32, B16, B36, B10, Bll, R32, R16, R36, BLI) Upon completion, if no switches have been specified, outfil contains a numbered listing of srcfil and its REQUIRE files followed by a cross reference of srcfil suitable for printing on a 132 column line printer; gxrfil contains a cross reference which is formatted so it can be sorted with other files of its type to produce a master cross reference listing of multiple source files. All REQUIRE files requested in srcfil are included in the cross reference. All Common BLISS reserved words are excluded from the II-10-6 BLISS Primer Volume 2: Intermediate Utilities cross reference. All line numbers which correspond to lines within REQUIRE files are flagged by a "+" in the cross reference; all routine definitions are flagged ty "*". All symbols directly proceeding the assignment operator are flagged with "t ... In addition, if the BLISS source module has been edited style described in the VAX-II Software Engineering Manual in the a list of all lines affected by each edit is output at the end the cross reference. ' of (i.e., inserted lines marked by !Aedit as in !A9S modified lines marked by !Medit as in !Mll deleted lines marked by !Oedit as in !077) For a list of the allowable command switches, see the help file on BLSCRF. CONOEN CONDEN is a program which CONDENses and cleans up the and sorted cross reference (see BLSCRF, above). merged The following sequence of commands can be used to create a set of GXR (Global X-Reference) files, append them together to form one large GXR file, sort the produced GXR file, and produce the final cross reference: @blscrf *filea,filea=filea *fileb,fileb=fileb *filec,filec=filec @copy allfil.gxr=filea.gxr,fileb.gxr,filec.gxr @sort *files.sor=/record:150/alphanumeric/ascii/key:l:40:a allfil.gxr @conden *files.xrf=files.sor FILEA.XRF, FILEB.XRF, and FILEC.XRF now contain the individual cross reference listings. FILES.XRF contains the sorted, merged cross reference of all three. II-10-7 BLISS Primer Volume 2: Intermediate Utilities CVTI~ and CVTII (CONVERT) CVTI~ is a tool for converting BLISS-l~ into BLISS-36c. (CVTIl, a sister version, converts BLISS-II into BLISS-16c.) CVTI~ will do a large percentage of the syntax conversions and a smaller set of other conversions. CVTI~ assumes that the input is compilable, without errors, by the BLISS-l~ compiler. It also makes no provisions for expanding macros in order to see what was meant. 'Reasonable' macros and 'reasonable' code will go through CVTI~ unscathed. To use CVTl~, enter the command 'CVTI~'. CVTI~ will respond by asking for the names of the input files (separated by spaces). Next, the names of the output files are requested. (The default in both cases is TTY:.) When all the files have been converted, CVTI~ will ask for another set of input and output files. Typically, the input file extension- will be file extension will be .B36. .BI~ and the output For help on using CVTI0, see the file, CVTI~.HLP. For a full description of the CVTl0 (and CVTIl) programs, including instructions for expanding the range of conversions, see the files CVT10.DOC and CVTIl.DOC. MODULE MODULE.BLI is the standard BLISS source module template. It provides a standard outline for writing BLISS programs. Included in MODULE.BLI are the full Module headers and Routine headers, as presented in the VAX-II Software Engineering Manual. II-I~-8 BLISS Primer Volume 2: Intermediate Utilities Exercises None 11-19-9 BLISS Primer Volume 2: Intermediate Utilities This page intentionally left blank. 1I-19-19 BLISS Primer Volume 2: Intermediate Utilities Unit Test Using the text as necessary, list provided for the BLISS programmer, usage. 11-18-11 at least four utilities along with their intended BLISS Primer Volume 2: Intermediate Utilities This page intentionally left blank. 11-10-12 BLISS-32 APPENDIX 11-11-1 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix This page intentionally left blank. 11-11-2 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix Introduction This unit illustrates the steps necessary to execute a BLISS-32 program on the VAX-ll/7S8 system. Specifically, it describes the following procedures: • • • • • Getting started on the VAX system Editing the source file Compiling the BLISS source file Linking the resultant OBJ file Running the program II~11-3 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix Additional Resources - - - - - - - - - VAX-II BLISS-32 User's Guide VAX/VMS Pr imer VAX/VMS Text Editing Reference Manual VAX/VMS LINKER Reference Manual VAX!VMS Command Language User's Guide Introduction to VAX-II RMS VAX/VMS VAX-ll RMS Reference Manual VAX/VMS Programmer's Guide to Debugging VAX-II Common Run-Time Procedure Library Reference Manual VAX/VMS System S~rvices Reference Manual VAX/VMS Symbolic Debugging Reference Manual 11-11-4 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix This unit teaches you how to transform a BLISS-32 program into a running program on the VAX-ll/788 system. source There are five steps involved in the process: • • • • • Get logged on to the VAX system Write a BLISS-32 source program using EDIT Compile the source program by invoking the BLISS-32 compiler Link the resultant object module using LINK, yielding an executable image of your program Run the image on the VAX system GENERAL PROCEDURE: STEP 1: Get LOGGED on to the system. First, see the system manager to arrange an account with a user-name and password. Let's assume that you've found a terminal that's connected to a VAX-ll/789 system. Get the system's attention by hitting RETURN. The VAX system will respond with USER-NAME: Enter the user-name and hit RETURN. request the password Next, the system will PASSWORD: Enter your password and hit RETURN. If your USER-NAME and PASSWORD are correct, the VAX system will display a greeting like this: WELCOME TO VAX!VMS VERSION 1.99 $ The '$' is the VAX/VMS system prompt. You are now logged on to the system. If you have any question about the commands which you can give VAX, try typing 'help'. You'll get a list of subjects for which the system has a HELP message. For example, command: if you 11-11-5 want help on the DIRECTORY BLISS Primer Volume 2:· Intermediate BLISS-32 Appendix $ help directory DIRECTORY Provides a list of files or info about a file or group of files. Format: DIRECTORY [file-spec, ••• ] Additional info available: Parameters Qualifiers Note the 'Additional info' list. This is a time saving feature. By giving more information only when you ask for it, you can zero in on just the help you need. Say you want qualifiers: more help on the DIRECTORY command $ help dir qua DIRECTORY QUALIFIERS /BRIEF Lists only the file name, filetype, and file version of each file to be listed. /FULL ... • Note that you only n·eed to type enough of uniquely specify it, as in 'hel dir qua'. a command to If you wish to see the present time: $ show time lS-JAN-78 17:34:23 There are several other things the VAX system can Find out which ones by getting HELP on SHOW. 'show'. When you are finished using the system, command to end the terminal session: LOGOUT use the $ logout For more information on using the VAX VAX/VMS Primer. 11-11-6 system, see: The BLISS Primer Volume 2: Intermediate BLISS-32 Appendix STEP 2: Create a BLISS-32 source program using EDIT. The editor is invoked to create or modify with a command like this: a source file $ edit test.b32 If the file already exists, the EDITor retrieves it and prepares it for your modifications. If no such file exists, the EDITor creates it for you. Note: file. '832' is the proper file type for a BLISS-32 source An editing session now begins, during which you will direct the EDITor using certain special commands. The default EDITor for the VAX system is called 'SOS'. Its commands are nearly identical with those of the SOS editors on other DEC computer systems. SOS is a line-oriented editor; that is, it 'sees' text in terms of lines. A line is a string of characters and spaces. Every line in an SOS file has a line number associated with it. When SOS displays a line, it is preceeded by its line number: 00100 This is a sample line of text. SOS responds to the EDIT command by displaying its version number and the full file specification. SOS then prompts you to begin entering lines: $ edit test.b32 SOS V02.04A I NPUT: DB 0: [3 00 , 21 ] TEST. B32 ; 1 00100 The line number prompt, '00100', indicates that you are in INPUT MODE. In this mode, each line you enter is placed into the file. hitting RETURN. Terminate each line by automatically increments the line number by 199 prompts you for more input. SOS and When you are finished inputting lines, hit the ESCAPE «esc» key to get out of INPUT MODE. (On some terminals, the equivalent'key is labeled 'ALTmode', 'SELect', or 'PREfix'.) The <esc> key is echoed to your terminal as a 11-11-7 BLISS Primer Volume 2: Intermediate BLISS-32'Appendix dollar sign ($). Upon the echo of the $, you are in the EDIT MODE. In this mode, SOS interprets each line you enter as one of its .special commands. The EDIT MODE prompt is a '*'. When you are done with the file, you can exit EDITor by entering an 'E' at the EDIT MODE level. will write the entered lines into a disc file under specified name and return you to VAX command level. Summary of Frequently Used SOS Commands: Command <RET> None <ESC> None position or range position p I N R D F Print the next line in the file Print the previous line Di splay 1 ine (s) Insert new 1ine(s) into file Renumber the lines in file increment and/or range Replace one or more lines position or range wi th new line (s) position Delete 1ine(s) from the file or range string<ESC> Find and print the next line containing the specified string *key: position range increment string Function Arguments* means you can specify a single line number means you can specify a range of line numbers of the form <firstline>: <lastline> is a numeric value for line number incrementing is any string of characters For more information on the SOS Text EDITor, see: VAX/VMS Text Editing Reference Manual. 11-11-8 the SOS the BLISS Primer Volume 2: Intermediate BLISS-32 Appendix STEP 3: Compile the program. The BLISS-32 source file that you've created must now be compiled. The compiler checks your source program for syntax and programming errors, then translates this input source file into a binary form. The translated code, called the 'object module', is written by the compiler into a file called the 'object module file', which has the f i 1 e type, 'OBJ'. You can invoke the BLISS-32 compiler command string of the form: by entering a BLISS [<qualifiers>] <sourcefile>[,<sourcefile>, ••• ] Source file names may be separated following qualifiers are supported: QUALIFIER by a comma. DEFAULT /[NO]LIST: [<filespec>] / [NO] OBJECT: [<f i lespec>] / [NO] LIBRARY: [<f i lespec>] / [NO]DEBUG /[NO]QUICK /(NO]CODE /VARIANT[=<n>] /TERMINAL: ( [NO] ERRORS, [NO] STATISTICS) /SOURCE: ( [NO]HEADER PAGE SIZE=<n> [NO] LIBRARY [NO] REQUIRE [NO] SOURCE [NO]EXPAND MACROS [NO]TRACE MACROS) /OPTIMIZE:( LEVEL=<n> SPACE I SPEED [NO] SAFE) /MACHINE CODE: ( [NO] ASSEMBLER [NO] SYMBOLIC [NO] COMMENTARY [NO] BINARY [NO]UNIQUE_NAMES) 11-11-9 /NOLIST /OBJECT /NOLIBRARY /NODEBUG /NOQUICK /CODE /VARIANT=0 /TE:(ERR,NOSTAT) /SOURCE:(HEAD,PAGE=55, NOLIB,NOREQ,SOURCE, NOEXP,NOTRACE) /OPT:(LEVEL=2,SPACE,SAFE) /MACH:(NOASS,SYM,BIN,COM, NOUNIQUE) The BLISS Primer Volume 2: Intermediate BLISS-32 Appendix If no <filespec> is supplied in LIST, OBJECT or LIBRARY qualifiers, default is to the name of the first input file (with the appropriate file type, i.e., LIS, OBJ, L32). The OBJECT and LIBRARY qualifiers are mutually exclusive. (See APPENDIX qualifier.) A for a detailed description of each STEP 4: 'Link the object module. The OBJECT module produced by the BLISS-32 compiler is not in itself, executable: generally, an object module contains references to other programs or routines that must be bound with the object module before it can be executed. This is the function of the LINKer. The LINKer is invoked by a command of the form: LINK [/<command qualifiers>] qualifiers>] <filespec(s»[<file </command qualifiers> specify output file options <filespec(s» specify the input OBJect file(s) linked (Default filetype in <filespec> is OBJ.) to be </file qualifiers> specify input file options Note that the LINK command can be entered without an accompanying file specification. The system responds with the prompting message: $ FILE: You should type the file specification on the same line as the prompting message. Multiple file specifications can be entered, each separated from the preceding specification by a comma. A single executable image is created from the input files specified. If no output file is specified, the LINKer produces an executable image with the same name as the first object module, and the type EXE. (No executable image is produced if the /NOEXECUTE qualifier is specified.) The following table lists some of the most often used LINKer qualifiers. II-II-I~ BLISS Primer Volume 2: Intermediate BLISS-32 Appendix LINKer Qualifiers Command qualifiers Default /[NO]BRIEF /[NO]CROSS REFERENCE /[NO]DEBUGT:<filespec>] /[NO]EXECUTABLE[=<filespec>] /[NO]FULL /[NO]MAP[=<filespec>] /NOBRIEF /NOCROSS REFERENCE /NODEBUG/EXECUTABLE /NOFULL /NOMAP File qualifiers Default /[NO]INCLUDE[=<module-name>[, ••• ]] /[NO]LIBRARY /NOINCLUDE !NOLIBRARY LINKer command qualifiers affect the output produced by the LINKer. By including the appropriate qualifiers, you can determine the type of executable image produced (if any), and the type of map file produced (.if any). (See APPENDIX qualifier.) STEP 5: B for a detailed description of each Run the program. The LINKer has created an executable image of your program. You can now run the program by the use of the following general command string: RUN [<qualifiers>]<filespec> If the <filespec> does not include a file command assumes a file type of EXE. type, the RUN Normally, no <qualifiers> are used in the RUNning of a program. However, by the use of the proper <qualifiers>, you can influence such RUN factors as: o o o o o o o delay time interval time priority privileges process-name swapping user identification code 11-11-11 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix For more information, see: VAX-II Common Run-Time Procedure Librarr Reference Manual, VAX/VMS System SerVlces Reference Manua , or VAX/VMS Command Language User's Guide. AN EXAMPLE OF THE WHOLE PROCEDURE: Suppose that you wanted a BLISS program that looked like this: MODULE SKELETON (MAIN = MAINLOOP) = BEGIN !++ This is a test BLISS program 1-- REQUIRE 'TUTIO'; ROUTINE MAIN LOOP: NOVALUE = BEGIN TTY PUT QUO {'WHAT HO 1'); END; END ELUDOM Let's look at the steps necessary to take this program from paper to an executing program on the VAX-ll/780 system. STEP 1: Log on to the system. Make sure the terminal is powered ON. Hit RETURN enter USER-NAME and PASSWORD when VAX requests them. system will respond with a message like this: and The WELCOME TO VAX/YMS VERSION 1.00 $ Note the system prompt ($) ending the message. STEP 2: Enter the BLISS-32 source program into a file. We will call our program something clever, like 'TEST.B32'. Here's the way the editing session would go. $ edit test.b32 SOS V02.04A INPUT:DB0: [300,21 ]TEST.B32; 1 00l0~ MODULE SKELETON (MAIN = MAINLOOP) 0020eJ BEGIN 0030eJ 1++ 11-11-12 = BLISS Primer Volume 2: Intermediate BLISS-32 Appendix 00400 00500 00600 00700 00800 00900 01009 01100 01200 This is a BLISS test program. 1-- REQUIRE 'TUTIO'; ROUTINE MAIN LOOP: NOVALUE = BEGIN TTY PUT QUO ('WHAT HO 1'); END; END ELUDOM$ The $ in the last line is the echoed <ESC> that you hit to go from INPUT MODE to the EDIT MODE. SOS responds with * The file looks OK, so exit SOS by entering 'E': *E [DB0: [300,2l]TEST.B32;1] $ Note that SOS displays the full file specification. STEP 3: Compile the program. Now you are ready to invoke the BLISS-32 compiler. Let's say, as an option, that you want a listing of the compile. The command string to enter is: BLISS /LIST TEST BLISS-32 will compile TEST.B32. If the compilation is successful, the produced OBJECT module is named TEST.OBJ, and the compiler listing is named TEST. LIS. STEP 4: Link the object module. Invoke the LINKer with the command: LINK TEST If the link is successful, it will produce the file TEST.EXE. 11-11-13 named BLISS Primer Volume 2: Intermediate BLISS-32 Appendix STEP 5: Run the program. You can now run your program by entering RUN TEST 11-11-14 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix APPENDIX A Compilation Qualifiers [NO]LIST: [<filespec>] Specifies that the listing file is to be <filespec>. [NO]OBJECT: [<filespec>] Specifies that the object <filespec>. code is to be placed in [NO]DEBUG Indicates whether or not the compiler should symbol table that may be used with the debugger. produce a [NO]QUICK Requests a faster, non-optimized compilation. (The lack of optimization may make it easier to relate the source code to the generated code.) [NO]CODE Specifies whether or not the compiler should produce object code. You might use /NOCODE to simply perform syntax checking of the source program; because the compiler does not produce code, the compilation time is reduced. VARIANT [=<n>] Specifies the value of the predeclared literal %VARIANT. If no value is specified for <n>, it defaults to a value of 1; otherwise %VARIANT has the specified value. If /VARIANT is not specified at all, %VARIANT has a value of 9. TERMINAL: ([NO]ERRORS,[NO]STATISTICS) Controls whether or not ERROR and STATISTICal information are displayed on the user terminal during the compilation. If STAT is specified, the compiler will display the names and sizes of all routines that are being compiled. SOURCE: «spec>,<spec>,<spec>, ••• ) Specifies what information is to appear in the listing file. [NO]HEADER Indicates whether the compiler should print normal page header information at the top of each page of the listing file. If NOHEADER is specified, the page header is supressed, as well as the form feed and any compiler sp~ce dependent summary information. PAGE SIZE=<n> Specifies the number of lines in a page in -the listing file. II-II-IS BLISS Primer Volume 2: Intermediate BLISS-32 Appendix [NO]REQUIRE Controls whether or not the contents of all the require files be included in the listing. [NO]SOURCE Indicates whether or not the BLISS-32 source statements will appear in the listing. [NO]EXPAND MACRO Specifies whether or not all MACROs shall be expanded wherever they appear in the source listing. [NO]TRACE MACROS Requests that the listing include a trace of MACRO expansions. OPTIMIZE:(LEVEL=<n),SPACE I SPEED, [NO]SAFE) Indicates whether the compiler should optimize code across mark points. Optimization can be set for either SPACE efficiency or time .efficiency (SPEED). [NO]SAFE indicates whether or not named variables in the source code will be addressed only by name. Use NO SAFE to indicate that variables can be addressed by pointers, and not just by name. MACHINE CODE: «spec),<spec),<spec), ••• ) The-MACHINE CODE qualifier requests a listing of the generated object code, the format of which is determined by the following subqualifiers: [NO]ASSEMBLER Specifies whether or not a listing of the object code is to be produced in a suitable format for assembly. [NO]SYMBOLIC Specifies whether or not a listing of the object code is to be produced in a suitable format for symbolic interpretation by the programmer. [NO]COMMENTARY Specifies whether or not a listing of the object code is to be produced with a compiler commentary. [NO]BINARY Specifies whether or not a listing of the object code in binary format is to be produced. [NO]UNIQUE NAMES Indicates whether the compiler should produce unique names for OWN variables and non-global routine names when it creates a listing that is to be assembled. 11-11-16 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix APPENDIX B LINKer Qualifiers [NO]BRIEF Requests the LINKer to produce a brief map (memory allocation) file. The /BRIEF qualifier is valid only if /MAP is also specified; and it must follow the /MAP qualifier in the command line. The /BRIEF listing contains: o A summary of the image characteristics o A list of all object modules included in the image o A summary of the LINK-time performance statistics (The effect of the /BRIEF qualifier is to withhold the summary of global symbols from the memory allocation 1 isting.) [NO]CROSS REFERENCE Controls whether or not the memory allocation listing (map) contains a symbol cross reference. The /CROSS REFERENCE qualifier is valid only if /MAP is also specified;- and it must follow the /MAP qualifier in the command line. A symbol cross reference lists each global symbol referenced in the image, its value, and all modules in the image that refer to it. [NO]DEBUG[=<filespec>] Controls whether or not an executable image is bound with a debugger. /DEBUG is valid only if /EXECUTABLE is specified, either explicitly or by default. The /DEBUG qualifier optionally accepts the name of an alternate, user-specified debugger. If a file specification is entered, and it does not contain a file type, the LINKer assumes the default file type of OBJ. If /DEBUG is specified without a file specification, the default VAX/VMS Debugger, DEBUG, is linked with the image. For more information on DEBUG, see the VAX/VMS Programmer's Guide to Debugging. [NO] EXECUTABLE [=<filespec>] Controls whether or not the LINKer produces an executable image and optionally provides a file specification for the output image file. By default, the LINKer creates an executable image with the same file specification as the first input file specified and a file type of EXE. Use !NOEXECUTABLE when you want to determine the outcome of linking a set of modules, without incurring the LINKer overhead required to create an image file. II-11-17 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix [NO] FULL Requests the LINKer to produce a full map (memory allocation) listing. The /FULL qualifier is valid only if /MAP is specified, and must follow the /MAP qualifier in the command line. A /FULL listing contains the following information: o A summary of the image characteristics o A list of all object modules included in the image o A summary of LINK-time performance statistics o A iist of global symbols o Detailed descriptions of each program section in the image file [NO]MAP[=<filespec>] Controls whether or not a memory allocation listing (map) is produced and optionally defines the file sp.ecification. If /MAP is specified, the qualifiers /BRIEF, /FULL, or CROSS REFERENCE may also be specified to control the contents of the map. If none of these qualifiers if specified, then the map will contain: o A summary of the image characteristics o A list of all object modules included in the image . 0 A summary of LINK-time performance statistics o A summary of global symbols If /MAP is specified without an output file specification, the output file is given the same file name as the first input file specified and a file type of MAP. [NO]SHAREABLE[=<filespec>] Requests the LINKer to produce a shareable image file rather than an executable image. If no file specification is given, the LINKer provides the image file with the same file name as the first input file and a file type of EXE. If /SHAREABLE is specified, /DEBUG may not be specified. Shareable images cannot be run with the RUN command; however, they may be linked with object modules to produce executable images. (See the /SHAREABLE qualifier in the information on file qualifiers, below.) [NO]SYMBOL TABLE[=<filespec>] Requests the LINKer to create a separate file in object module format containing symbol definitions for all symbols contained in the image. If /SYMBOL TABLE is specified without a file specification, the LINKer creates a file with the same file name as the image file and a file sype of STB. If /DEBUG is specified, the LINKer includes the symbol definitions in the image for use by the debugger, and also creates a separate symbol table file. The symbol table file can be used as input to subsequent 11-11-18 BLISS Primer Volume 2: Intermediate BLISS-32 Appendix LINK commands, images. to provide File qualifiers can set file(s). the symbol definitions to other certain options for the input [NO]INCLUDE[=<module-name>[, ••• ]] /NOINCLUDE indicates that the associated input file is an object module library, and that only the module names specified are to be unconditionally included as input to the LINKer. If /INCLUDE is specified, /LIBRARY can also be specified, to indicate that the same library should also be used to search for unresolved references. At least one <module-name> must be specified. If more than one is specified, they must be enclosed in parentheses and separated by commas. [N 0] LIB RARY /LIBRARY indicates that the associated input file is an object module library, which is to be searched for modules that resolve any undefined symbols in the input file(s). If the associated input file specification does not include a file type, the LINKer assumes the default file type of LIB. A library may not be specified as the first input file unless the /INCLUDE qualifier is also specified to indicate which modules in the library are to be included in the input. You can use both /INCLUDE and /LIBRARY to qualify a file specification; in that case, the explicit inclusion of modules occurs first, then the library is used to search for any unresolved references. [NO] SHAREABLE /SHAREABLE indicates whether the associated input file is a previously-linked shareable image. If /SHAREABLE is specified the associated input file specification does not include a file type; the LINKer assumes the default file type of EXE. 11-11-19 BLISS Primer Volume 2: Intermediate BL1SS-32 Appendix This page intentionally left blank. 11-11-29 BLISS-36 APPENDIX II-12-1 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix This page intentionally left blank. 11-12-2 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix Introduction This unit illustrates the steps necessary to execute a BLISS-36 program on the DECSYSTEM-10/20. Specifically, it describes the following procedures: • • • • • Getting started on the DECSYSTEM-10/20 Editing the source file Compiling the BLISS source file Linking the resultant REL file Running the program 11-12-3 BLISS Primer Volume 2: IntermediatE~ BLISS-36 Appendix Additional Resources Getting Started with the DECSYSTEM-20 DECSYSTEM-l0 Software Notebooks (13 Volumes) DECSYSTEM-20 Edit User's Guide DECSYSTEM-20 User's Guide DECSYSTEM-20 LINK Reference Manual DECSYSTEM-l0 Operating System Command Manual DECSYSTEM-20 EDIT Reference Manual DECSYSTEM-20 EDIT Reference Card VAX-ll BLISS-32 User's Guide 11-12-4 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix This unit teaches you how to transform a BLISS-36 source program into a running program on the DECSYSTEM-10/20. For the sake of simplicity, all examples will be given from the point of view of TOPS-20, the mon~tor that runs on the DECSYSTEM-20. (For more information on TOPS-10, see the appropriate references as mentioned in ADDITIONAL RESOURCES.) There are five steps involved in the process: • • • • • Get logged on to the DECSYSTEM-10/20 Write a BLISS-36 source program using EDIT Compile the source program by invoking the BLISS-36 compiler Link the resultant object module, load it into core, and save the executable image of your program Run the image on the DECSYSTEM-10/20 system GENERAL PROCEDURE: STEP 1: Get LOGGED on to the system. First, see the system manager to arrange an account with a user-name and password (and possibly an account number). Let's assume that you've found a terminal that's connected to a DECSYSTEM-10/20. Get the system's attention by hitting CTRL-C (that's the <CTRL> and C keys simul taneously) • The DECSYSTEM-20 will respond wi th a message like this: EDUCATIONAL SERVICES, TOPS-20' Monitor 3(1371) @ The '@' is the TOPS-20 system prompt. It says are at 'command level' • Now type the i n form a t i on : that you following LOGIN <user-name> <password> [<account>] If your user-name, password, (and account number, if applicable) are correct, TOPS-20 will display a message like this: Job 9 on TTY31 13-Jun-78 10:23:42 @ You are now logged on to the system. If you have any question about the commands which you can give TOPS-20, 11-12-5 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix try typing 'help *'. You'll get a list which the system has a HELP message. of subjects for For example, if you want help on BLISS: @help bliss BLISS-36 is the new BLISS compiler (BLISS. EXE) wh·ich runs under TOPS-l~ or TOPS-29 and generates code for KA, KI, and KL processors. The BLISS system is . ' • • If you wish to see the present time: @daytime Friday, October 13, 1978 11:34:32 You can gather a great deal of information TOPS-29 commands using the 'HELP *' facility. about When you are finished using the system, command to end the terminal session: the use the LOGOUT @logout Killed Job 9, User WITHROW, Account 234, TTY 31, at lS-Jun-78 2~:23:42, Used 9:3:13 in 9:23:34 For more information on using the see: The DECSYSTEM-29 User's Guide. 11-12-6 DECSYSTEM-2~ system, BLISS Primer Volume 2: Intermediate BLISS-36 Appendix STEP 2: Create a BLISS-36 source program using EDIT. The editor is invoked to create or modify with a command like this: a source file $ edit test.bli If the file already exists, the EDITor retrieves it and prepares it for your modifications. If no such file exists, the EDITor creates it for you. Note that 'Bli' for BLISS-36. (and 'b36') are the two default file types An editing session now begins, during which you will direct the EDITor using certain special commands. The default EDITor for the DECSYSTEM-29 system is called 'SOS'. Its commands are nearly identical with those of the SOS editors on other DEC computer systems. SOS is a line-oriented editor; that is, it 'sees' text in terms of lines. A line is a string of characters and spaces. Every line in an SOS file has a line number associated with it. When SOS displays a line, it is preceeded by its line number: 99199 This is a sample line of text. SOS responds to the EDIT- command by displaying its version number and the full file specification.· SOS then prompts you to begin entering lines: @edit test.bli %File not found, Creating New file Input: TEST.BLI.l 99199 The line number prompt, '99199', indicates that you are in INPUT MODE. In this mode, each line you enter is placed into the file. RETURN. hitting Terminate each line by automatically increments the line number by 199 prompts you for more input. SOS and When you are finished inputting lines, hit the ESCAPE «esc» key to get out of INPUT MODE. (On some terminals, the equivalent key is labeled 'ALTmode', 'SELect', or 11-12-7 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix , PREf ix' .) Th e <esc> key is echoed to your terminal as a dollar sign ($). Upon the echo of the $, you are in the EDIT MODE. In this mode, SOS interprets each line you The EDIT MODE enter as one of its special commands. prompt is a '*'. When you are done with the file, you can exit the EDITor by entering an 'E' at the EDIT MODE level. SOS will write the entered lines into a disc file under the specified name and return you to TOPS-20 command level. Summary of Frequently Used SOS Commands: Command Arguments* , <RET> None <ESC> None position or range posi tion p I N R D F Print the next line in the file Print the previous line Display line(s) Insert new line(s) into file Renumber the lines in file increment and/or range position Replace one or more lines or range with new line(s) position Delete line(s)from the file or range string<ESC> Find and print the next line containing "the specified string *key: position range increment string Function means you can specify a single line number means you can specify a range of line numbers of the form <firstline>: <lastline> is a numeric value for line number incrementing is any string of characters For more information on the SOS Text EDITor, see: DECSYSTEM-20 EDIT User's Guide 11-12-8 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix STEP 3: Compile the program. The BLISS-36 source file that you've created must now be compiled. The compiler checks your source program for syntax and programming errors, then translates this input source file into a binary form. The translated code, called the 'object module', is written by the compiler into a file called the 'object module file', which has the file type, 'REL'. You can invoke the BLISS-36 compiler by typing simply 'BLISS'. The BLISS-36 compiler will next display its prompt: BLISS> You should now enter the command line, which, simplest form contains one filename, like this: in its BLISS>file This will cause FILE.B36 (or FILE.BLI) to be compiled, and the FILE.REL to be created. A number of switches can also be specified on the command line. (For a full list of switches, see Appendix A.) STEP 4: Link the object module. The OBJECT module produced by the BLISS-36 compiler is not in itself, executable: generally, an object module contains references to other programs or routines that must be bound with the object module before it can be executed. This is the function of the linker. The linker is invoked by a command of the form: LOAD file (Default filetype is REL.) The LOAD command will not only invoke the linker; it will also load the linked module into core. At this point, the easiest way to start the program running is to enter the command 'START'. However, if you wish to run the program in the future, you can avoid the repeated LOADing and STARTing by now SAVING the core image of the LOADed program. To do this enter the command: 11-12-9 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix @save file.exe The executable core image is now permanently SAVEd in file with extension, 'EXE'. the For more information, see: DECSYSTEM-29 LINK Reference Manual STEP 5: Run the program. The SAVEd core image file can now be executed, by entering the command: @run file.exe If the <filespec> does not include a file type, the RUN command assumes a file type of EXE. For more information, see: DECSYSTEM-29 User's Guide AN EXAMPLE OF THE WHOLE PROCEDURE: Suppose that you wanted a BLISS program that looked like this: MODULE SKELETON (MAIN = MAINLOOP) BEGIN = 1++ This is a test BLISS program 1-- REQUIRE 'TUTIO'; ROUTINE MAINLOOP: NOVALUE = BEGIN TTY PUT QUO('! AM FLATll)~ END; END ELUDOM Let's look at the steps necessary to take this program paper to an executing program on the DECSYSTEM-29. STEP 1: from Log on to the system. Make sure the terminal is powered ON. Hit CTRL-C. Let's say that USER-NAME, PASSWORD, and ACCOUNT are 'WITHROW', 11-12-19 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix 'PAL', and '432', respectively. In response opening message of TOPS-2~ enter this line: to the of the @login withrow pal 432 Note that TOPS-20 will not echo the password (for the sake of security.) characters The system will respond with a message like this: Job 15 on TTY52 14-Aug-78 ~~:34:22 @ Note the system prompt (@) ending the message. STEP 2: Enter the BLISS-36 source program into a file. We will call the program 'FLAT.BLI'. Here's the way the editing session would go. @edit flat.bli %File not found, Creating New file Input: FLAT.BLI.l ~~1~~ MODULE SKELETON (MAIN = MAINLOOP) ~~2~0 BEGIN ~~3~0 1++ 0~4~0 ~~5~~ 1-- 0~6~0 ~~7~~ ~~8~0 ~09~~ ~1~~~ ~1100 012~0 = This is a BLISS test program. REQUIRE 'TUTIO'; ROUTINE MAINLOOP: NOVALUE = BEGIN TT Y PUT QUO ( I I AM FLAT! END; END ELUDOM$ I ) : The $ in the last line is the echoed <ESC> that you hit to go from INPUT MODE to the EDIT MODE. SOS responds with * The file looks OK, so exit SOS by entering 'E': *E [FLAT.BLI.l] @ 11-12-11 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix STEP 3: Compile the program. Now you are ready to invoke the BLISS-36 compiler. Let's say, as options, that you want a listing of the compile, statistics to be displayed, and to return to monitor level upon completion of the compile. The command strings to enter are: @b1iss BLISS>flat/1ist/stat/exit BLISS-36 will compile FLAT.BLI. If the compilation is successful, the produced object module is named FLAT.REL, and the compiler listing is named FLAT. LIS. STEP 4: Link the object module. Invoke the Linker with the command: @load flat If the link/load is successful, it will generate the message 'EXIT', and return to monitor level. You can then save the core image with the command: @save flat There now exists a new executed. STEP 5: file, 'FLAT.EXE', Run the program. You can now run your program by entering RUN FLAT 11-12-12 which can be BLISS Primer Volume 2: Intermediate BLISS-36 Appendix APPENDIX A BLISS-36 Compiler Switches A listing of the available switches is given Defaults are marked with an asterisk(*). SWITCH below. DESCRIPTION /C(ODE)* Generate object code. /0 (EBUG) Generate symbols for debugging, emit debug linkages, and disable certain optimizations so the debugger doesn't get confused. /ER(RS)* Report errors to the terminal. /EXI (T) Exit back to EXEC after compilation. /EXT(ENDED) Program to run in a Model B processor. /F (ORMAT) : Specify certain options to control the format of the listing file (for full list of FORMAT switches, see below.) /H(EADER)* Produce a heading on the top of each page of the listing file including configuration information. /KA (1 ~) Assume generated code is to be executed on KA-lg. a /KI (1 ~) Assume generated code is to be executed on KI -lg. a /KL (1 ~) * Assume generated code is to be executed on KL-lg or KL-2~. a /LIB(RARY) Interpret the source file(s) as a library source file. The resultant object file (.L36) is the precompiled library file that can be requested from a source program with a library-declaration. A library file can only be requested by a compiler if that same compiler was the one that built the library. 11-12-13 non-zero section on a BLISS Primer Volume 2: Intermediate BLISS-36 Appendix /LIS(TING):fs Produce a listing file. If no filespec (fs) is given as an argument, use the default extension .LST. /NOxxx Invert the meaning of switch /xxx. /OPTI(MIZE)* /OPTL(EVEL):n Perform full flow analysis. Specify the degree of optimization. N must be in the range ~ to 3. Request 3 for maximum optimization. Default is 2. /P(AGSIZ):n Specify the number of lines printed on each page of the listing file. N must be in the range 2~ to 52. Default is 52. /Q(UICK) Requests a "quick" compilation,_ possibly the expense of some optimization. /SA(FE)* Specifies that the source program is coded in a "safe" manner, i.e. values of named variables are changed only by explicit assignment to the named variable. If /NOSAFE is specified, the compiler assumes that indirect assignments invalidate a larger class of variables. /ST(ATISTICS) Produce routine names on the terminal as they are compiled. /TOPSl(~) Produce code to run under TOPS-l~. /TOPS2(~)* Produce code to run under TOPS-2~. /U(NAMES) Produce unique names for own variables and non-global routine names in the listing file when it is to be assembled. /V(ARIANT):n Assign n to be the value of the lexical function %VARIANT. If not present (default), zero is assumed. If present and no value is given, 1 is assumed. /Z(IP) Optimized for time over space if there choice to be made. is at a The following are the options that can be given with the /FORMAT switch. The form of the /FORMAT switch is given by: 11-12-14 BLISS Primer Volume 2: Intermediate BLISS-36 Appendix /FORMAT:option or /FORMAT:(option,option, ••• ) /A(SSEMBLY) Produce a listing file that can be assembled. (Some modification may be necessary.) /B(INARY)* Include in the listing file the generated. /C(OMMENTARY)* Include in the listing file commentary on the operands of each instruction. Currently, this consists of a source line number. /E(XPAND) Include the invocation. /L(IBRARY) Include a trace identifying the library accessed by each library-declaration and the first use of each name whose definition is obtained from a library file. /NOxxx Invert the meaning of option xxx. /0 (BJECT) * List the compiled code. The ASSEMBLY, SYMBOLIC, BINARY, and COMMENTARY options determine the format of the compiled code. /R(EQUIRE) Do not mod~fy the listing control counter when openlng or closing files specified in a REQUIRE declaration. In the default case, this results in not listing each REQUIRE file. See SOURCE. /SO(URCE)* Increments the listing control counter. The initial value of the counter is 1. When the counter is greater than ~, source is listed. Require-declarations automatically decrement the counter for the length of the require file unless REQUIRE is set. /SY(MBOLIC)* List the instructions generated, many program symbols as possible. /T(RACE) Trace macro expansion expansion. 11-12-15 binary of This each code macro using as includes the BLISS Primer Volume 2: Intermediate BLISS-36 Appendix resulting EXPAND. stream II-12-16 of 1exemes produced by BLISS-16 APPENDIX 11-13-1 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix This page intentionally left blank. II-13-2 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix Introduction This unit illustrates the steps necessary to translate a Specifically, it BLISS-16 program on the DECSYSTEM-19/29. describes the following procedures: • • • Getting started on the DECSYSTEM-19/2~ Editing the source file Compiling the BLISS source file 11-13-3 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix Additional Resources Getting Started with the DECSYSTEM-20 DECSYSTEM-10 Software Notebooks (13 Volumes) DECSYSTEM-20 Edit User's Guide DECSYSTEM-20 User's Guide DECSYSTEM-10 Operating System Command Manual DECSYSTEM-20 EDIT Reference Manual VAX~11 BLISS-32 User's Guide DECSYSTEM-20 EDIT Reference Card various documentation for the PDP-l1 systems 11-13-4 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix This unit will show you how to transform a BLISS-16 source program into an object file ready to be transported to a PDP-II system and run there. The translator system for BLISS-16 is actually a pre-processor chaining to a compiler chaining to a cross-assembler. The whole system is called BLISS-16c ('c' for cross-compiler.) Most of that operation is performed without the need of· user ini tiation. Th is uni t wi 11 assume that the user is new to the use of the DECSYSTEM-19/29, and will, therefore, explain the generation of the final object file in detail. For the sake of simplicity, all examples will be given from point of view of TOPS-29, the monitor that runs on DECSYSTEM-29. (For more information on TOPS-19, see appropriate references as mentioned in ADDITIONAL RESOURCES.) the the the There are four steps involved in the process: • • • • Get logged on to the DECSYSTEM-19/29 Write a BLISS-16 source program using EDIT Compile the source program by invoking the BLISS-16c translator package Transport the resultant object file to a PDP-II system for task-building and execution GENERAL PROCEDURE: STEP 1:. Get LOGGED on to the system. First, see the system manager to arrange an account with a user-name and password (and possibly an account number). Let's assume that you've found a terminal that's connected to a DECSYSTEM-19/20. Get the system's attention by hitting CTRL-C (that's the <CTRL> and C keys simultaneously). The DECSYSTEM-29 will respond with a message like this: EDUCATIONAL SERVICES, TOPS-20 Monitor 3(1371) @ The '@' is the TOPS-2m system prompt. It says are at 'command level'. Now type the information: LOGIN <user-name> <password> [<account>] II-13-5 that you following BLISS Primer Volume 2: Intermediate BLISS-16 Appendix If your user-name, password, (and account number, if applicable) are correct, TOPS-20 will display a message like this: Job 9 on TTY31 l3-Jun-78 10:23:42 @ You are now logged on to the system. If you have any question about the commands which you can give TOPS-20, try typing 'help *'. You'll get a list of subjects for which the system has a HELP message. For example, if you want help on BLISS-16c: @help bls16c The BLISS-16c is a translator and compiler in one package: the translator produces BLISS-II code from BLISS-16c source code; the compiler is in fact the BLISS-l1 compiler. • • • If you wish to see the present time: @daytime Friday, October 13, 1978 11:34:32 You can gather a great deal of information TOPS-20 commands using the HELP * facility. about When you are finished using the system, command to end the terminal session: the use the LOGOUT @logout Killed Job 9, User PEGRAM, Account 234, TTY 31, at lS-Jun-78 2~:23:42, Used 0:3:13 in 0:23:34 For more information on using the DECSYSTEM-20 see: The DECSYSTEM-20 User's Guide. 11-13-6 system, BLISS Primer Volume 2: Intermediate BLISS-16 Appendix STEP 2: Create a BLISS-16 source program using EDIT. The editor is invoked to create or modify with a command like this: a source file $ edit test.b16 If the file already exists, the EDITor retrieves it and prepares it for your modifications. If no such file exists, the EDITor creates it for you. Note: 'b16' is the default file type for BLISS-16. An editing session now begins, during which you will direct the EDITor using certain special commands. The default EDITor for the DECSYSTEM-20 system is called 'SOS'. Its commands are nearly identical with thos~ of the SOS editors on other DEC computer systems. SOS is a line-oriented editor; that is, it 'sees' text in terms of lines. A line is a string of characters and spaces. Every line in an SOS file has a line number associated with it. When SOS displays a line, it is preceeded by its line number: 00100 This is a sample line of text. SOS responds to the EDIT command by displaying its version number and the full file specification. SOS then prompts you to begin entering lines: @edit test.b16 %File not found, Creating New file Input: TEST.B16.l 00100 The line number prompt, '00100', indicates that you are in INPUT MODE. In this mode, each line you enter is placed into the file. Terminate each line by hitting RETURN. automatically increments the line number by 100 prompts you for more input. SOS and When you are finished inputting lines, hit the ESCAPE «esc» key to get out of INPUT MODE. (On some terminals, the equivalent key is labeled 'ALTmode', 'SELect', or 'PREfix'.) The <esc> key is echoed to your terminal as a 11-13-7 BLISS Primer Volume 2: Intermediate BLISS-l6 Appendix dollar sign ($). Upon the echo of the $, you are in the EDIT MODE. In this mode, SOS interprets each line you enter as one of its special commands. The' EDIT MODE prompt is a ' . ' . When you are done with the file, you can exit the EDITor by entering an IE' at the EDIT MODE level. SOS will write the entered' lines into a disc file under the specified name and return you to TOPS-29 command level. Summary of Frequently Used SOS Commands: Command Arguments· <RET> None <ESC> None position or range position P I N R D F Print the next line in the file Print the previous line Display line(s) Insert new line(s) into file Renumber the lines in file increment and/or range Replace one or more lines position or range with new line(s) position Delete line(s)from the file or range string<ESC> Find and print the next line containing the specified string ·key: position range increment string Function means you can specify a single line number means you can specify a range of line numbers of the form <firstline>: <lastline> is a numeric value for line number incrementing is any string of characters For more information on the SOS Text EDITor, see: DECSYSTEM-29 EDIT User's Guide 11-13-8 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix STEP 3: Compile the program. The BLISS-16 source file that you've created must now be compiled. The BLISS-16c compiler package checks your source program for syntax and programming errors, then translates this input source file into a form suitable for passing to an assembler. That code is then translated by a cross-assembler (MACYll) into 'object' code, and placed in a file called the 'object module file', which has the file type, 'OBJ'. You can invoke the BLISS-16 compiler by typing simply 'BLS16C'. The BLISS-16 compiler package will next display its prompt: * You should now enter the command line, form: which is of the *objfil,lstfil=srcfill,srcfi12, ••• /switch/switch ••• where either "objfil" or ",lstfil" (or both) may be omitted and where all switches and all but the first "srcfil" specification may be omitted. Defaults for the relevant file extensions are: srcfil: lstfil: objfil: intfil: B16 PII (BLISS-II listing file) LST (MACYIl listing file) OBJ I16 (BLISS-16c Intermediate file) The BLISS-16 pre-processor translates the BLISS-16 source into BLISS-II source, passing on the objfil and lstfil specifications to the BLISS-II compiler. If both files are specified, MACYII will be invoked after BLISS-II completes its compilation (assuming the compilation was successful!) Objfil and lstfil specifications from the BLISS-16c command line will be passed on to MACYll and will become the names of the object and listing files output by MACYIl. Both object and listing files are always produced by MACYII when invoked from BLISS-16c. If either objfil or lstfil is specified on 11-13-9 the BLISS-16c BLISS Primer Volume 2: Intermediate BLISS-16 Appendix command line without the other, the one specified is taken to be lstfil. In such case, MACYII is not invoked, and the assembly can then be performed either on the DECSYSTEM-lB/2B by MACYll, or on the PDP-II, itself. The BLISS-16 pre-processor normally produces a BLISS-II source file, called the intermediate file, or intfil, with the file name taken from srcfil. This intermediate file will normally be deleted by BLISS-II when it is finished. If MACYll is invoked, the BLISS-II listing file is also normally deleted (after the assembly completes). Both files (intfil and lstfil) can be optionally retained. A number of switches can be specified on the command line. (For a full list of switches, see Appendix A.) STEP 4: Link (Taskbuild) the object module. The OBJECT module produced by the combined BLISS-16 pre-processor/BLISS-II compiler/MACYII cross-assembler package is not in itself, executable: generally, an object module contains references to other programs or routines that must be bound with the object module before it can be executed. This operation is the function of the LINKER (or TASKBUILDER). At this point (with the object file "in your hands") options are twofold: your • invoke one of the several PDP-II simulator packages to taskbuild an executable image of your program, or • transport the object file (from MACYII) to a PDP-II then taskbuild and run it there. II-13-IB BLISS Primer Volume 2: Intermediate BLISS-16 Appendix AN EXAMPLE OF THE WHOLE PROCEDURE: Suppose that you wanted a BLISS program that looked like this: MODULE SKELETON (MAIN = MAINLOOP) BEGIN !++ ! This is a test BLISS program = !-- ROUTINE MAINLOOP: NOVALUE = BEGIN END; END ELUDOM Let's look at the steps necessary to take this program paper,to an object file on the DECSYSTEM-2a. STEP 1: from Log on to' the system. Make sure the terminal is powered ON. Hit CTRL-C. Let's say that USER-NAME, PASSWORD, and ACCOUNT are 'PEGRAM', 'PAL', and '432', respectively. In response to the opening message of TOPS-2A enter this line: @login pegram pal 432 Note that TOPS-2a will not echo the password (for the sake of security.) characters The system will respond with a message like this: Job 15 on TTY52 14-Aug-78 99:34:22 @ Note the system prompt (@) ending the message. 11-13-11 of the BLISS Primer Volume 2: Intermediate BLISS-16 Appendix STEP 2: Enter the BLISS-16 source program into a file. We will call the program 'NOFLAT.B16'. Here's the way the editing session would go. @edit nof1at.b16 %Fi1e not found, Creating New file Input: NOFLAT.B16.1 ~0100 MODULE SKELETON (MAIN = MAINLOOP) = 00200 BEGIN 9939g !++ 99490 This is a BLISS test program. ggS0g !-9g69g ROUTINE MAINLOOP: NOVALUE = gg7gg BEGIN ggagg END; gg9g0 END glg00 ELUDOM$ The $ in the last line is the echoed <ESC> that you hit to go from INPUT MODE to the EDIT MODE. SOS responds with * The file looks OK, so exit SOS by entering 'E': *E {NOFLAT.B16.l] @ 11-13-12 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix STEP 3: Compile the program. Now you are ready to invoke the BLISS-16c translator package. Let's say, as options, that you want a listing of the translation, statistics to be displayed, and to save all intermediate files created by the translator package. The command strings to enter are: @blsl6c *noflat,noflat=noflat/stat/noidelete The BLISS-16c translator package will pre-process, compile, and assemble NOFLAT.B16. If the translation is successful, the produced files will be: • NOFLAT.II6 - the BLISS-II equivalent of the original BLISS-16 source file. (It is normally deleted.) • NOFLAT.PII - produced by the BLISS-II compiler. It contains the assembly language translation of the Intermediate BLISS-II source file.) It is also normally deleted.) • NOFLAT.LST - the listing file produced by MACYll. • NOFLAT.OBJ - the purpose of the whole exercise: the object file, ready for taskbuilding. It's produced by MACYll. STEP 4: Link (Taskbuild) the object module. You are now NOFLAT.OBJ, and PDP-II. ready to taskbuild the object file, run it on either a simulator or a real 11-13-13 BLISS Primer Volume 2: Intermediate BLISS-l6 Appendix APPENDIX A BLISS-16C Compiler Switches The allowable command switches are: Switch Default Description /ADDRESS:opt /ADDRESS:RELATIVE Controls addressing mode to be used in the generated code • an • ABSOLUTE will cause .ENABL AMA control directive to be emitted into the output file and addressing mode 37 (absolute) will be used instead of mode 67 (relative) • • RELATIVE will cause addressing mode 67 (relative) to be used. /BLISSII:"switch(es)" no switches The switches specified within the quotes will be passed by BLISS-16C into the BLISS-II command line. Example: BLISSll:"/S/A" will print routine lengths on the terminal as they are compiled and will allow EIS instructions. /CODE /NOCODE Generate BLISS-II code as a result of translation. /NOCODE is used to do a syntax check only. /COMPRESS /NOCOMPRESS Compress the intermediate file. COMPRESS leaves out generated comments and indenting and replaces "BEGIN"-"END" with "("_H)". 11-13-14 BLISS Primer Volume 2: Intermediate BLISS-16 Appe:ndlx /DEBUG /NODEBUG Sets up an appropriate linkage for DEB16C (formerly called SIXI2). The /DEBUG switch is passed to BLISS-II. However, the SIXl2 debugger for BLISS-II (developed at CMU) is not supported by this release. /ERRS /ERRS Print warnings and error messages on the terminal. /IDELETE /IDELETE Delete the intermediate file after BLISS-II compilation. If MACYll is invoked, delete the BLISS-II listing file after the assembly completes. /INTER:file /LIST: (sw, ••• ) or /LIST:sw srcfil.I16 /LIST(COMMENTARY, NOEXPAND, NOREQUIRE, NOTRACE, OBJECT, SOURCE, SYMBOLIC) 11-13-15 Override the default intermediate file name assign~ent with 'file'. COMMENTARY List the BLISScode produced by the translator 11 EXPAND of Show result macro expansion. OBJECT Allow object code to be listed as indicated below. With NOOBJECT set no object code is listed. REQUIRE List files. SOURCE List BLISS-16C so urce code. SYMBOLIC List the MACRO code generated by BLISS-II. TRACE Trace REQUIRE macro BLISS Primer Volume 2: Intermediate BLISS-16 Appendix expansions. /MACYll="switch(es)" /OBJECT:opt no switches The switches specified within the squotes will be passed by BLISS-16C via BLISS-II into the MACYll command line. A comma and/or an equals sign may occur within the quotes to show which switches are to be associated with which command line files. If no comma or equals sign is present, the switches are appended to the end of the MACYll command line. Example: MACYll=" ,/SP/NL=/EN: PNC" would associate /SP and /NL with the listing file and /EN:PNC with the source file. /OBJECT:RELOCATABLE Controls object file format: • ABSOLUTE will cause an .ENABL ABS control directive to be emitted into the output file. PSECT and EXT~RNAL declarations will not be allowed • • RELOCATABLE will generate an object file which must be processed by the task builder. /OPTIMIZ E /OPTIMIZE Perform optimization according to OPTLEVEL. /OPTLEVEL: n /OPTLEVEL: 2 Controls amount optim i zat ion: QJ of = None 1 = Final only 2 = Code motion and Final OPTLEVEL:0 is equivalent 11-13-16 to BLISS Primer Volume 2: Intermediate BLISS-16 Appendix NOOPTIM IZ E. /PAGSIZ E:n /PAGSIZE:52 Set page size to Un" lines per page for the listing file. Un" is interpreted as a decimal number and must be between 29 and 52 inclusive. The default is 52. /RBLISSll /RBLISSIl Run the BLISS-II compiler on the intermediate file. /SAFE /NOSAFE Asserts, of the source code, that named variables will be addressed only by name. /NOSAFE is used when, because of the use of pointers to named variables, the value of a variable may be referenced or altered without the specific use of its name. /STATISTICS /NOSTATISTICS Print routine names and sizes on terminal while compil ing. /UNAMES /NOUNAMES Generate unique names for OWN variables and non-global ROUTINE names when producing a listing which is to be assembled. /VARIANT /VARIANT: 8 Set value of the %VARIANT predefined literal. If /VARIANT is specified without, Un", the value is one. /ZIP /NOZIP Optimize time at the expense of space. /NO ••• The prefix "NO" in a switch, as in /NOERRS generally reverses the sense of the switch. Exceptions to this are noted in the definitions above. 11-13-17 BLISS Primer Volume 2: Intermediate BLISS-16 Appendix This page intentionally left blank. 11-13-18
Home
Privacy and Data
Site structure and layout ©2025 Majenko Technologies