UBC Theses and Dissertations

UBC Theses Logo

UBC Theses and Dissertations

Pascal-F, A portable Fortran-based Pascal Compiler Manning, Joseph 1981

Your browser doesn't seem to have a PDF viewer, please download the PDF to view this item.

Notice for Google Chrome users:
If you are having trouble viewing or searching the PDF with Google Chrome, please download it here instead.

Item Metadata

Download

Media
831-UBC_1981_A6_7 M36.pdf [ 4.6MB ]
Metadata
JSON: 831-1.0051835.json
JSON-LD: 831-1.0051835-ld.json
RDF/XML (Pretty): 831-1.0051835-rdf.xml
RDF/JSON: 831-1.0051835-rdf.json
Turtle: 831-1.0051835-turtle.txt
N-Triples: 831-1.0051835-rdf-ntriples.txt
Original Record: 831-1.0051835-source.json
Full Text
831-1.0051835-fulltext.txt
Citation
831-1.0051835.ris

Full Text

PASCAL-F : A PORTABLE FORTRAN-BASED PASCAL COMPILER by JOSEPH MANNING B . S c , The N a t i o n a l U n i v e r s i t y of I r e l a n d , 1974 M.Sc, The N a t i o n a l U n i v e r s i t y of I r e l a n d , 1975 A THESIS SUBMITTED IN PARTIAL FULFILMENT OF THE REQUIREMENTS FOR THE DEGREE OF MASTER OF SCIENCE in THE FACULTY OF GRADUATE STUDIES (Department of Computer Science) We accept t h i s t h e s i s as conforming to the r e q u i r e d standard THE UNIVERSITY OF BRITISH COLUMBIA September 1981 © Joseph Manning, 1981 In presenting t h i s thesis i n p a r t i a l f u l f i l m e n t of the requirements for an advanced degree at the University of B r i t i s h Columbia, I agree that the Library s h a l l make i t f r e e l y a v a i l a b l e for reference and study. I further agree that permission for extensive copying of t h i s thesis for scholarly purposes may be granted by the head of my department or by his or her representatives. It i s understood that copying or pu b l i c a t i o n of t h i s thesis for f i n a n c i a l gain s h a l l not be allowed without my written permission. Department o The University of B r i t i s h Columbia 2075 Wesbrook Place Vancouver, Canada V6T 1W5 Da te \W . \ & \ 11 ABSTRACT T h i s t h e s i s examines the subject of compiler p o r t a b i l i t y and d e s c r i b e s a p r o j e c t which adopts one p a r t i c u l a r approach to a c h i e v i n g t h i s g o a l : generate code i n an e x i s t i n g widely-implemented language as output from the c o m p i l e r . Pascal-F t r a n s l a t e s P a s c a l to F-code, an intermediate language which can be processed d i r e c t l y by any Standard FORTRAN compiler. The design of the F-code machine i s t r e a t e d i n d e t a i l , and problems with the use of FORTRAN as a t a r g e t language are d i s c u s s e d . i i i TABLE OF CONTENTS 1 I n t r o d u c t i o n 1 2 Compiler P o r t a b i l i t y 5 A The A b s t r a c t Machine Approach 7 B A Standard A b s t r a c t Machine 9 C The Pascal-F Approach 11 3 The F-code Machine 16 A The S t r u c t u r e of F-code Programs 16 B The Problems of Recursion 18 C Storage A l l o c a t i o n and Addressing of v a r i a b l e s 20 D The R o u t i n e - C a l l i n g Mechanism 26 E F-code I n s t r u c t i o n s and The Run-time L i b r a r y 29 4 The Pascal-F T r a n s l a t o r 34 A General D e s c r i p t i o n 34 B F-code Generation P a t t e r n s 37 5 R e s u l t s and Conclus i o n s 42 B i b l i o g r a p h y 45 Appendix A Language R e s t r i c t i o n s under Pa s c a l - F 47 Appendix B Sample T r a n s l a t i o n s 48 Appendix C L i s t i n g of the Run-time L i b r a r y 56 i v LIST OF FIGURES 1 S t r u c t u r e of a P o r t a b l e Compiler 6 2 D i r e c t T r a n s l a t i o n of a Recursive Procedure 18 3 Storage A l l o c a t i o n f o r a Routine 25 4 The Routine CALLUP 28 5 Machine-Dependent Constants i n the T r a n s l a t o r 35 V ACKNOWLEDGEMENT I would l i k e to express my s i n c e r e thanks to my Su p e r v i s o r , P r o f e s s o r Harvey Abramson, f o r h i s constant encouragement, optimism, guidance, and p a t i e n c e , d u r i n g the development of Pasc a l - F and the w r i t i n g of t h i s t h e s i s . T h i s t h e s i s i s d e d i c a t e d to a l l the f r i e n d s I have known in b e a u t i f u l Vancouver 1 Chapter 1 : INTRODUCTION With the ever-expanding use and a p p l i c a t i o n of computers, the t o p i c of Software P o r t a b i l i t y has become i n c r e a s i n g l y important. P o r t a b i l i t y i s a measure of the ease with which a p a r t i c u l a r p i e c e of software may be t r a n s f e r r e d from one environment to another, r e l a t i v e to i t s i n i t i a l implementation e f f o r t . Such a t r a n s f e r c o u l d be e i t h e r s p a t i a l (between two computer i n s t a l l a t i o n s ) or temporal (between an o l d environment at an i n s t a l l a t i o n and a newer replacement), and the change of environment c o u l d be to a d i f f e r e n t machine, or o p e r a t i n g system, or both. P o r t a b l e software o f f e r s a number of c o n s i d e r a b l e b e n e f i t s : • the cost of implementation i n a new environment i s g r e a t l y reduced i f the software can be t r a n s f e r r e d e a s i l y from an e x i s t i n g implementation, thus a v o i d i n g e i t h e r a t o t a l r e w r i t e or a major c o n v e r s i o n e f f o r t (the c u r r e n t annual c o s t of t r a n s f e r r i n g software i s estimated to be i n excess of $10 b i l l i o n i n the U.S.A. a l o n e ' 3 1 , much of which would be saved i f the o r i g i n a l software were w r i t t e n i n a more p o r t a b l e manner). • i f the t r a n s f e r process i s simple so that the l i k e l i h o o d of i n t r o d u c i n g new e r r o r s i s s m a l l , then the t r a n s f e r r e d software w i l l g e n e r a l l y be f a r more r e l i a b l e than a s e p a r a t e l y - w r i t t e n v e r s i o n s i n c e i t w i l l have been t e s t e d by use i n i t s o r i g i n a l environment. Chapter 1 : INTRODUCTION 2 • i n the academic and r e s e a r c h worlds, p o r t a b i l i t y of software encourages communication, c o - o p e r a t i o n , software interchange and u n i t y of r e s e a r c h , while a v o i d i n g much d u p l i c a t i o n of e f f o r t . In the- e a r l y days of computing, only machine and assembly languages were a v a i l a b l e f o r the w r i t i n g of software. P o r t a b i l i t y was then n e a r l y impossible to achieve, s i n c e a l l software w r i t t e n i n these l o w - l e v e l languages had to be s p e c i f i c a l l y o r i e n t e d towards the d e t a i l s of i t s environment. The s i t u a t i o n was g r e a t l y improved with the advent and widespread use of h i g h - l e v e l languages, which were designed to be uniform a c r o s s a l l environments. Software w r i t t e n i n one of these languages c o u l d be t r a n s f e r r e d to any environment i n which the language was implemented. (In p r a c t i c e , however, problems s t i l l remained due to non-uniform implementations: the l a c k of r i g i d l y - d e f i n e d language standards gave r i s e to d i f f e r i n g i n t e r p r e t a t i o n s of c e r t a i n f e a t u r e s ; l o c a l " b e l l s and w h i s t l e s " were added as e x t e n s i o n s ; environment-dependencies, such as d e t a i l s of the c h a r a c t e r set or machine wordlength, were o f t e n s t i l l present i n programs; e t c . See P o o l e ' 1 3 ) f o r a lengthy d i s c u s s i o n ) . However, i n order to make a given h i g h - l e v e l language widely a v a i l a b l e , some form of compiler or i n t e r p r e t e r must be provided f o r each environment. The most common approach i n the past was to w r i t e a separate compiler, g e n e r a l l y i n assembly Chapter 1 : INTRODUCTION 3 language, f o r each new and s u b s t a n t i a l l y d i f f e r e n t environment, with very l i t t l e emphasis on p o r t a b i l i t y . More r e c e n t l y , much res e a r c h has been done and c o n s i d e r a b l e progress made i n producing compilers which are p o r t a b l e . These p r o v i d e a l l of the b e n e f i t s o u t l i n e d above, with i n c r e a s e d r e l i a b i l i t y being of p a r t i c u l a r importance i n c o m p i l e r s . In a d d i t i o n , the use of p o r t a b l e compilers leads to f a r more s t a n d a r d i z e d language implementations, thereby c o n t r i b u t i n g to the p o r t a b i l i t y of software i n g e n e r a l . Since a compiler must u l t i m a t e l y generate machine language which i t s e l f must i n t e r a c t with i t s o p e r a t i n g system, i t i s c l e a r that c o m p i l e r s , by t h e i r very nature, are f a r more environment-dependent than g e n e r a l a p p l i c a t i o n s software. As a r e s u l t , i n the o v e r a l l study of software p o r t a b i l i t y the t o p i c of compiler p o r t a b i l i t y i s a p a r t i c u l a r l y i n t e r e s t i n g and c h a l l e n g i n g one. T h i s t h e s i s d e s c r i b e s the design and implementation of P a s c a l - F , a h i g h l y p o r t a b l e compiler f o r the programming language P a s c a l 1 7 j 6 > . The Pascal-F compiler t r a n s l a t e s P a s c a l source programs i n t o F-code, an intermediate language which may be processed d i r e c t l y by any Standard FORTRAN compiler to generate machine language. Chapter 2 d i s c u s s e s the o v e r a l l q u e s t i o n of compiler p o r t a b i l i t y , s t u d i e s some general s o l u t i o n s , and p r e s e n t s the P a s c a l - F approach. Chapter 3 presents the F-code machine and d e s c r i b e s the v a r i o u s f a c t o r s Chapter 1 : INTRODUCTION 4 which i n f l u e n c e d i t s d e s i g n . Chapter 4 g i v e s a gen e r a l d e s c r i p t i o n of the Pascal-F t r a n s l a t o r and shows how the v a r i o u s s y n t a c t i c c o n s t r u c t s i n P a s c a l are t r a n s l a t e d i n t o F-code. Chapter 5 concludes the t h e s i s with some r e f l e c t i o n s on the p r o j e c t . 5 Chapter 2 : COMPILER PORTABILITY A compiler i s i t s e l f a computer program. I t s task i s to analyse programs w r i t t e n i n a h i g h - l e v e l language and t r a n s l a t e them i n t o e q u i v a l e n t programs i n the machine language of a given computer. Thus, compiler p o r t a b i l i t y has two d i s t i n c t a s p e c t s : • the a b i l i t y to t r a n s f e r the compiler i t s e l f to a new environment. • the ease with which the compiler can be a l t e r e d to generate machine language f o r t h i s new environment. Both of these aspects are now examined. The former r e l a t e s to the general problem of software p o r t a b i l i t y ; the l a t t e r s p e c i f i c a l l y to compiler p o r t a b i l i t y . In order that the compiler i t s e l f may be e a s i l y t r a n s f e r r e d , l i k e any p o r t a b l e software i t should be w r i t t e n i n a language which i s environment-independent. At f i r s t s i g h t the most a p p r o p r i a t e c h o i c e would seem to be an e x i s t i n g h i g h - l e v e l language which has a l r e a d y been widely implemented. However, most p o r t a b l e compilers (e.g. B C P L l 1 5 ) , P a s c a l - P ( 1 2 > , B l i s s ' 2 1 ' , C ' 8 )) are i n f a c t w r i t t e n i n the very language which they themselves c o m p i l e ' 1 0 ' and are g e n e r a l l y implemented at a new i n s t a l l a t i o n v i a some form of b o o t s t r a p p i n g technique. Such s e l f - c o m p i l i n g compilers have the important advantage of now being independent of the a v a i l a b i l i t y or c o r r e c t n e s s of another s p e c i f i c language at the new i n s t a l l a t i o n . Chapter 2 : COMPILER PORTABILITY 6 In d e a l i n g with the second aspect of compiler p o r t a b i l i t y , experience has shown that the task of modifying a compiler to produce machine language f o r a new environment i s c o n s i d e r a b l y s i m p l i f i e d i f that p a r t of the compiler i n v o l v e d i n code g e n e r a t i o n i s c l e a r l y separated by a w e l l - d e f i n e d i n t e r f a c e from the remainder of the compiler. Thus i t i s usual f o r a p o r t a b l e compiler to be s t r u c t u r a l l y d i v i d e d i n t o what R i c h a r d s ( 1 " ) terms a s y n t a c t i c phase (SP) and a code generator phase (CGP): Source Language => Program S y n t a c t i c Phase SP / CGP = > => I n t e r f a c e Code Generator Phase Machine => Language Program F i g . 1 : S t r u c t u r e of a P o r t a b l e Compiler The SP reads the source language program, breaks i t i n t o a stream of l e x i c a l tokens, and parses these to determine i t s s y n t a c t i c s t r u c t u r e ; i t w i l l a l s o issue d i a g n o s t i c s i f syntax e r r o r s are encountered. Having e s t a b l i s h e d the s t r u c t u r e of the e n t i r e program or of an i n d i v i d u a l c o n s t r u c t , the SP determines to some degree what a c t i o n s are r e q u i r e d f o r i t s exe c u t i o n . T h i s i n f o r m a t i o n i s then t r a n s m i t t e d across the i n t e r f a c e to the CGP, which generates a c o r r e s p o n d i n g sequence of i n s t r u c t i o n s i n the machine language of the given computer. The SP i s almost t o t a l l y independent of i t s environment so that apart from some minimal adjustments (e.g. to d e t a i l s of the c h a r a c t e r set or the value of the l a r g e s t i n t e g e r ) i t can remain unchanged d u r i n g a t r a n s f e r of the compiler. On the other hand, Chapter 2 : COMPILER PORTABILITY 7 the CGP w i l l o b v i o u s l y need to be a l t e r e d c o n s i d e r a b l y t o s u i t d i f f e r e n t environments. Note t h a t the presence i n the source language of those f e a t u r e s which can be handled completely by the SP, such as r i c h c o n t r o l s t r u c t u r e s , w i l l not hinder p o r t a b i l i t y , whereas f e a t u r e s i n v o l v i n g the CGP, such as the p r o v i s i o n of a REAL data type, may cause d i f f i c u l t i e s . The SP / CGP i n t e r f a c e can assume a number of very d i s t i n c t forms. I t c o u l d c o n s i s t of a data s t r u c t u r e , such as a parse t r e e which the SP b u i l d s and the CGP subsequently t r a v e r s e s . A l t e r n a t i v e l y , i t c o u l d simply be a set of procedure c a l l s ; once the SP has determined what semantic a c t i o n s are r e q u i r e d f o r the c u r r e n t s y n t a c t i c c o n s t r u c t , i t is s u e s a d i r e c t c a l l to the r e l e v a n t procedure i n the CGP. A f u r t h e r p o s s i b i l i t y , which i s now examined i n d e t a i l , i s perhaps the most f l e x i b l e of a l l such i n t e r f a c e s , p a r t i c u l a r l y with r e s p e c t to p o r t a b i l i t y . A. The A b s t r a c t Machine Approach The o p e r a t i o n a l semantics of the source language may g e n e r a l l y be formulated i n terms of a .set of p r i m i t i v e o p e r a t i o n s , which are independent of both the o r i g i n a l language syntax and any p a r t i c u l a r environment. An a b s t r a c t machine i s a ( h y p o t h e t i c a l ) computer whose i n s t r u c t i o n set c o n s i s t s of p r e c i s e l y these o p e r a t i o n s ; i t s assembly language comprises the a s s o c i a t e d intermediate code. Having d e f i n e d an a b s t r a c t machine f o r the source language, i t s intermediate code can serve Chapter 2 : COMPILER PORTABILITY 8 as a very s u i t a b l e i n t e r f a c e between the SP and CGP of the compiler. The SP t r a n s l a t e s the source language program i n t o a program i n the intermediate code; the CGP i n turn t r a n s l a t e s t h i s i n t o a machine language program. C l e a r l y , f o r any p a r t i c u l a r source language there are many p o s s i b l e designs f o r an a b s t r a c t machine. The g e n e r a l design c r i t e r i a w i l l i n c l u d e such f a c t o r s as the o v e r a l l c l e a n l i n e s s of the r e s u l t i n g machine, i t s s u i t a b i l i t y f o r e x p r e s s i n g the semantics of the source language, the compactness and e f f i c i e n c y of i t s intermediate code, the ease with which t h i s can be generated by the SP, and the ease of implementing the CGP across a v a r i e t y of environments. These c r i t e r i a f r e q u e n t l y c o n f l i c t amongst themselves; the compromise reached w i l l depend on t h e i r r e l a t i v e importance i n a given s i t u a t i o n . The a b s t r a c t machine approach has proved to be very s u c c e s s f u l i n the c o n s t r u c t i o n of p o r t a b l e compilers f o r a number of languages. The most notable and well-known examples in c l u d e the OCODE and INTCODE machines for B C P L ( 1 5 ) , the P-code machine for Pascal* 1 2 > and the Z-code machine f o r A l g o l 6 8 - C ( 2 ) . A major advantage with respect to p o r t a b i l i t y of having the SP / CGP i n t e r f a c e i n the e x p l i c i t form of intermediate code i s that f o r s e l f - c o m p i l i n g c o m p i l e r s , such as those j u s t mentioned, the compiler i t s e l f can be d i s t r i b u t e d as a program i n the intermediate code, so as soon as the CGP has been implemented at an i n s t a l l a t i o n the e n t i r e compiler becomes a v a i l a b l e . Chapter 2 : COMPILER PORTABILITY 9 The task of implementing the CGP i s a l s o s i m p l i f i e d and very c l e a r l y d e f i n e d by the e x p l i c i t form of the SP / CGP i n t e r f a c e . I t b a s i c a l l y c o n s i s t s of p r o v i d i n g a t r a n s l a t i o n i n t o machine language f o r each of the d i f f e r e n t intermediate code i n s t r u c t i o n s , which are g e n e r a l l y very simple i n nature. (An o u t s t a n d i n g example of such s i m p l i c i t y i s INTCODE, which i s composed of e s s e n t i a l l y only 8 very elementary i n s t r u c t i o n s ; however, t h i s case i s somewhat extreme, and P-code, with some 58 i n s t r u c t i o n s , i s f a r more t y p i c a l of the general s i t u a t i o n ) . A common technique i s to use a macro-processor i n implementing the CGP, w r i t i n g an i n d i v i d u a l macro f o r each intermediate code i n s t r u c t i o n to produce the corresponding machine language. An a l t e r n a t e approach i s to r e a l i z e the CGP i n the form of an i n t e r p r e t e r f o r the intermediate code i n s t r u c t i o n s . T h i s method has an added advantage i n that i t completely avoids the problem of generating machine language, thereby r e s u l t i n g i n even g r e a t e r p o r t a b i l i t y . I t has been used to s u c c e s s f u l l y implement languages such as SNOBOL4 < 5 ) and P a s c a l - S ( 2 0 > . B. A Standard A b s t r a c t Machine As o u t l i n e d above, an a b s t r a c t machine i s designed to m i r r o r the p r i m i t i v e o p e r a t i o n a l semantic a c t i o n s of a p a r t i c u l a r language as c o n v e n i e n t l y as p o s s i b l e . I t i s not s u r p r i s i n g then that a b s t r a c t machines f o r d i f f e r e n t languages are themselves q u i t e d i f f e r e n t . N e v e r t h e l e s s , there i s s t i l l a Chapter 2 : COMPILER PORTABILITY 10 remarkable degree of s i m i l a r i t y between a l o t of the p r i m i t i v e s f o r many languages and t h i s suggests the very i n t e r e s t i n g and powerful concept of a standard a b s t r a c t machine (SAM), i . e . a s i n g l e a b s t r a c t machine capable of exp r e s s i n g and implementing the p r i m i t i v e s of a l l languages. Although i t s design poses many problems, the c r e a t i o n of a SAM would c l e a r l y have a tremendous impact on the whole q u e s t i o n of compiler p o r t a b i l i t y . Once a SAM became widely implemented, the task of t r a n s f e r r i n g a SAM-based compiler to a new environment would now be g r e a t l y s i m p l i f i e d s i n c e a s u i t a b l e CGP ( i . e . p r e c i s e l y the SAM's own implementation) would a l r e a d y be a v a i l a b l e at t h i s new environment. The SAM concept i s not new; i n f a c t i t was suggested as f a r back as 1 9 5 8 ( 1 1 ) . The int e r m e d i a t e code f o r t h i s proposed SAM was known as UNCOL (UNive r s a l Computer O r i e n t e d Language). The ba s i c m o t i v a t i o n was to s i m p l i f y the problem of implementing L languages i n E environments. Using the UNCOL SAM (!), only a s i n g l e SP need be w r i t t e n f o r each language ( t r a n s l a t i n g the language to UNCOL), and s i m i l a r l y a s i n g l e CGP f o r each environment ( t r a n s l a t i n g UNCOL to machine language). T h i s y i e l d s a t o t a l of only L + E t r a n s l a t o r s compared with the L * E t r a n s l a t o r s which would otherwise be r e q u i r e d . A key f a c t o r i n the UNCOL scheme was that to achieve p o r t a b i l i t y , the SP f o r each language should i t s e l f be w r i t t e n i n UNCOL. T h i s added g r e a t l y to the task of d e s i g n i n g UNCOL, Chapter 2 : COMPILER PORTABILITY 11 s i n c e i t now had to be r i c h and e x p r e s s i v e to f a c i l i t a t e the w r i t i n g of these t r a n s l a t o r s , as w e l l as being simple enough both to r e f l e c t the very p r i m i t i v e o p e r a t i o n s of a wide v a r i e t y of languages and to be e a s i l y implemented ac r o s s a range of environments. These d i f f i c u l t i e s were f u r t h e r compounded by the f a c t that c o m p i l e r - w r i t i n g techniques at that time were not w e l l developed. Although a c e r t a i n amount of i n i t i a l progress was made 1 1 7', the o r i g i n a l UNCOL p r o j e c t was f i n a l l y abandoned. A more recent attempt by Waite's team at the U n i v e r s i t y of Colorado, based on many years of advances i n c o m p i l e r - w r i t i n g , has r e s u l t e d i n the f o r m u l a t i o n of the " u n i v e r s a l intermediate language" J a n u s 1 " ' . The r e s u l t s are encouraging: Janus has been used s u c c e s s f u l l y i n the c o n s t r u c t i o n of compilers f o r BCPL and P a s c a l 1 1 8 ' , and .has been implemented in a number of d i f f e r e n t environments. By c o n t r a s t with the o r i g i n a l UNCOL, Janus i s intended to be used s o l e l y as an intermediate code and not as a problem-oriented language f o r w r i t i n g the SP of a c o m p i l e r . C. The P a s c a l - F Approach The SAM concept has tremendous p o t e n t i a l as regards compiler p o r t a b i l i t y . However, i t s r e a l i z a t i o n i s a monumental undertaking; not alone must the machine be designed to u n i f o r m l y c a t e r f o r the p r i m i t i v e s of a whole spectrum of languages, but i t must subsequently be implemented a c r o s s a wide range of environments. The P a s c a l - F p r o j e c t d e s c r i b e d i n t h i s t h e s i s Chapter 2 : COMPILER PORTABILITY 12 i s an attempt to r e t a i n the advantages of a SAM while a v o i d i n g both of these major d i f f i c u l t i e s . The c e n t r a l idea u n d e r l y i n g the Pascal-F approach i s to generate an intermediate code which can be processed d i r e c t l y by the compiler of an e x i s t i n g widely-implemented language. T h i s approach o f f e r s two s i g n i f i c a n t advantages which solve the corresponding problems above. F i r s t l y , the r e s u l t i n g somewhat u n s p e c i f i e d a b s t r a c t machine i s e x c e p t i o n a l l y f l e x i b l e and e x t e n s i b l e — almost any semantic a c t i o n can be r e a l i z e d merely by coding an a p p r o p r i a t e t a r g e t language r o u t i n e and adding a new intermediate code i n s t r u c t i o n which c a l l s t h i s r o u t i n e . Thus the a b s t r a c t machine i s very e a s i l y adapted to i n c o r p o r a t e the p r i m i t i v e s of a great v a r i e t y of languages. Secondly, the problem of general implementation of the a b s t r a c t machine now no longer a r i s e s — the t a r g e t language's compiler serves d i r e c t l y as the CGP f o r the intermediate code. Such a compiler w i l l a l r e a d y have been thoroughly t e s t e d by other uses, and can t h e r e f o r e be expected to be f a r more r e l i a b l e than any newly-written s p e c i a l - p u r p o s e CGP. C l e a r l y , the success of t h i s approach hinges on the widespread a v a i l a b i l i t y of the t a r g e t language s e l e c t e d . Of a l l e x i s t i n g languages, at present the most u n i v e r s a l l y implemented i s probably FORTRAN. Because of t h i s (and t h i s a l o n e ! ) , i t was the t a r g e t language chosen f o r the c u r r e n t p r o j e c t . More p r e c i s e l y , ANSI ( 1966) Standard FORTRAN1 1 * 1 6 ' was used; Chapter 2 : COMPILER PORTABILITY 13 although most "FORTRAN IV" compilers f e a t u r e a c o n s i d e r a b l e number of e n t i c i n g extensions to the standard language, these are very implementation-dependent and must c l e a r l y be avoided s i n c e p o r t a b i l i t y i s of the utmost importance. In many ways, FORTRAN i s f a r from i d e a l f o r t h i s task, s i n c e i t s numerous r e s t r i c t i o n s as a c o m p i l e r - o r i e n t e d language ( i n p a r t i c u l a r , the absence of r e c u r s i o n and l o w - l e v e l I/O) present many d i f f i c u l t i e s . From t h i s s t a n d p o i n t , a language such as BCPL or C would have been much more a p p r o p r i a t e ; however, these languages are not widely a v a i l a b l e and s i n c e t h i s f a c t o r was of prime concern, FORTRAN was the eventual c h o i c e . The d i f f i c u l t i e s were then accepted as a c h a l l e n g e to be overcome in e s t a b l i s h i n g the v i a b i l i t y of the o v e r a l l approach. In keeping with the great t r a d i t i o n a l scheme f o r naming intermediate codes, that of the FORTRAN-based SAM i s known as F-code. I t i s important to again note that F-code i s not a f i x e d s t a t i c language. Rather, i t c o n s i s t s of a general framework with a c e r t a i n core set of i n s t r u c t i o n s ( p r i m a r i l y d e a l i n g with r o u t i n e i n v o c a t i o n and I/O), to which new i n s t r u c t i o n s may be added with ease to meet the needs of d i f f e r i n g s i t u a t i o n s . The P a s c a l - F p r o j e c t i t s e l f c o n s i s t e d of d e f i n i n g and c r e a t i n g a s u i t a b l e F-code machine for the language P a s c a l and w r i t i n g a t r a n s l a t o r from P a s c a l to F-code. A f a i r l y simple stack machine was designed, implemented and found a p p r o p r i a t e ; Chapter 2 : COMPILER PORTABILITY 14 i t i s d e s c r i b e d in some d e t a i l i n the f o l l o w i n g chapter. Once the machine's o v e r a l l s t r u c t u r e had been decided upon, the development of the i n d i v i d u a l F-code i n s t r u c t i o n s proceeded hand-in-hand with the w r i t i n g of the t r a n s l a t o r , with new i n s t r u c t i o n s being added as the need arose. T h i s served to demonstrate the inherent f l e x i b i l i t y of the method. Although i t was at f i r s t hoped that t h i s F-code machine c o u l d be implemented e n t i r e l y using only Standard FORTRAN and so y i e l d an almost t o t a l l y p o r t a b l e compiler, a f t e r much e f f o r t i t was e v e n t u a l l y found that a c e r t a i n small number of o p e r a t i o n s j u s t c o u l d not be r e a l i z e d t h i s way. These i n c l u d e d o p e r a t i o n s to empty an e x t e r n a l f i l e , to read a v a r i a b l e - l e n g t h input l i n e , to d e t e c t the e n d - o f - f i l e c o n d i t i o n , e t c . ; they are d i s c u s s e d i n more d e t a i l l a t e r . The s o l u t i o n reached was to c a r e f u l l y i s o l a t e these o p e r a t i o n s and implement each by means of an environment-dependent r o u t i n e , using e i t h e r assembly language or, as was sometimes p o s s i b l e , extensions to FORTRAN. Although t h i s s o l u t i o n u n f o r t u n a t e l y c o n f l i c t s somewhat with the o r i g i n a l design concept, n e v e r t h e l e s s the r e s u l t i n g i n t e r f a c e which must be w r i t t e n f o r each environment i s very s m a l l , c l e a r l y - d e f i n e d and s t r a i g h t f o r w a r d to implement, and the o v e r a l l compiler s t i l l remains extremely p o r t a b l e . In f a c t , by c o n t r a s t with a l l of the other p o r t a b l e compilers that were examined ( p a r t i c u l a r l y those f o r P a s c a l — see Lecarme and T h o m a s ' 1 0 1 ) , the t r a n s f e r of Pascal-F to a new environment i n v o l v e s only a f r a c t i o n of the e f f o r t which i s normally r e q u i r e d . Chapter 2 : COMPILER PORTABILITY 15 The P a s c a l to F-code t r a n s l a t o r , i . e . the SP of the compiler, was w r i t t e n i n P a s c a l . Note that t h i s d i f f e r s from the UNCOL approach which would have r e q u i r e d i t to be w r i t t e n d i r e c t l y i n F-code, a much more d i f f i c u l t u ndertaking. P a s c a l was used because of i t s general s u i t a b i l i t y f o r such a task, the o v e r a l l c l a r i t y , m o d i f i a b i l i t y and r e l i a b i l i t y of the r e s u l t i n g t r a n s l a t o r , and of course c h i e f l y f o r the i m p l i c a t i o n s of s e l f - c o m p i l a t i o n on p o r t a b i l i t y . Once an o r i g i n a l v e r s i o n of the t r a n s l a t o r was w r i t t e n , i t was f i r s t l y compiled under an e x i s t i n g P a s c a l compiler, and then executed with i t s e l f as i n p u t . T h i s produced an F-code program capable of t r a n s l a t i n g P a s c a l to F-code! The Pascal-F compiler was then completely s e l f - c o n t a i n e d , and the e x i s t i n g P a s c a l compiler c o u l d be d i s c a r d e d . T h i s s e l f - c o m p i l a t i o n was c a r r i e d out as soon as the t r a n s l a t o r c o u l d handle a l l the f e a t u r e s necessary to t r a n s l a t e i t s e l f . F u r t h e r expansion of the t r a n s l a t o r was then p o s s i b l e by modifying the P a s c a l v e r s i o n , and t r a n s l a t i n g t h i s under the c u r r e n t F-code program to y i e l d an F-code v e r s i o n of the expanded t r a n s l a t o r . 1 6 Chapter 3 : THE F-CODE MACHINE Thi s chapter presents the u n d e r l y i n g f a c t o r s which shaped the design of the F-code machine, and d e s c r i b e s the r e s u l t which f i n a l l y emerged. Although the p r e s e n t a t i o n here i s given i n terms of p l a n n i n g the machine as a t a r g e t s p e c i f i c a l l y f o r the t r a n s l a t i o n of P a s c a l , t h i s i s done p r i m a r i l y f o r i l l u s t r a t i v e purposes. I t w i l l be c l e a r that many of the c o n c l u s i o n s a r r i v e d at apply e q u a l l y w e l l i n a more general s e t t i n g . A. The S t r u c t u r e of F-code Programs One of the e a r l i e s t and most fundamental d e c i s i o n s concerned the o v e r a l l s t r u c t u r e of the F-code program r e s u l t i n g from the t r a n s l a t i o n of a P a s c a l program. The simplest and most ap p e a l i n g s t r u c t u r e i s the monolith — t r a n s l a t e the P a s c a l program together with a l l i t s e n c l o s e d procedures and f u n c t i o n s i n t o one l a r g e s i n g l e main program i n F-code. T h i s approach had been very s u c c e s s f u l l y used i n a pr e v i o u s course p r o j e c t to implement a subset of P a s c a l , which i n c l u d e d f u l l n e s t i n g of procedures and f u n c t i o n s but was never meant to be s e l f -c o m p i l i n g . Routine c a l l s can be implemented i n a h i g h l y e f f i c i e n t manner by simply ASSIGNing the l a b e l of the f o l l o w i n g statement to a " r e t u r n address" v a r i a b l e and performing a GOTO the s t a r t of the r o u t i n e ' s code. T h i s scheme a l s o very n i c e l y s o l v e s a s u b s t a n t i a l problem connected with the t r a n s l a t i o n of r e c u r s i v e r o u t i n e s . In f a c t , the m o n o l i t h i c approach i s i d e a l l y Chapter 3 : THE F-CODE MACHINE 17 s u i t e d to the task, and there i s no fundamental reason why i t c o u l d not be used; however, i t had to be r e j e c t e d because of a f a i r l y mundane c o n s i d e r a t i o n . The a l l - i m p o r t a n t F-code v e r s i o n of the Pas c a l - F t r a n s l a t o r i t s e l f i s c l o s e to 10,000 l i n e s long. A s i n g l e main program of t h i s s i z e i s f a r beyond the c a p a c i t y of the average FORTRAN compiler — experiments showed that even at a reasonably l a r g e i n s t a l l a t i o n (IBM 4341), a monolith of fewer than 3,000 " t y p i c a l " F-code l i n e s a l r e a d y exceeds the compiler l i m i t s . Since i t i s e s s e n t i a l f o r p o r t a b i l i t y that Pascal-F i t s e l f should l i e w i t h i n the c a p a c i t y of a wide range of FORTRAN implementations, c l e a r l y the m o n o l i t h i c approach i s not f e a s i b l e . The a l t e r n a t i v e i s to t r a n s l a t e each procedure and f u n c t i o n of the P a s c a l program i n t o a separate SUBROUTINE i n F-code. T h i s approach was adopted and u l t i m a t e l y proved s u c c e s s f u l . Assuming that the P a s c a l source program has been s u i t a b l y o r g a n i z e d as a s e r i e s of subprograms, i t s F-code t r a n s l a t i o n w i l l now c o n s i s t of a number of short separate u n i t s which can e a s i l y be handled i n d i v i d u a l l y by any FORTRAN comp i l e r . (Note that f u n c t i o n s i n P a s c a l become SUBROUTINES, r a t h e r than FUNCTIONS, i n F-code. T h i s r e s u l t s i n a f a r simpler and more uniform scheme while a v o i d i n g a number of troublesome d e t a i l s a s s o c i a t e d with FUNCTIONS i n FORTRAN). Chapter 3 : THE F-CODE MACHINE B. The Problems of Recursion 18 However, a major d i f f i c u l t y was soon encountered using t h i s approach: r e c u r s i o n i s allowed i n P a s c a l but not i n FORTRAN. T h i s s i n g l e f a c t o r was to have a very profound impact on the o v e r a l l design of the F-code machine. I t g i v e s r i s e to two s e r i o u s problems which are now i l l u s t r a t e d . Consider the f o l l o w i n g r e c u r s i v e Pascal procedure (which simply w r i t e s out each number from 1 to N), and an attempt to t r a n s l a t e i t d i r e c t l y i n t o FORTRAN: procedure COUNT (N : INTEGER); begin i f N > 1 then C0UNT(N-1); WRITELN(N) end SUBROUTINE COUNT (N) IF (N .GT. 1) CALL COUNT(N-l) WRITE(-,-) N RETURN END F i g . 2 : D i r e c t T r a n s l a t i o n of a Recursive Procedure The f i r s t problem concerns storage a l l o c a t i o n f o r l o c a l v a r i a b l e s . In the P a s c a l v e r s i o n , each i n c a r n a t i o n of COUNT i s dyn a m i c a l l y a l l o c a t e d a new memory l o c a t i o n f o r N. On the other hand, FORTRAN g e n e r a l l y uses a s t a t i c storage a l l o c a t i o n scheme, s i n c e r e c u r s i o n need not be c a t e r e d f o r . T h i s means that i n the FORTRAN v e r s i o n , each i n c a r n a t i o n of COUNT w i l l use the same memory l o c a t i o n f o r N, and consequently on every r e c u r s i v e c a l l COUNT w i l l a l t e r the value of i t s predecessor's N. (One attempt to run the program produced a s e r i e s of "1"s as o u t p u t ) . Chapter 3 : THE F-CODE MACHINE 19 The second problem concerns the RETURN from a r o u t i n e , and stems from b a s i c a l l y the same cause. In many implementations, each FORTRAN r o u t i n e i s pro v i d e d with one f i x e d l o c a t i o n i n which to s t o r e i t s r e t u r n address, i . e . the p o s i t i o n i n i t s c a l l e r ' s code to which i t should r e t u r n . Suppose a main program i s s u e s a CALL C0UNT(2). COUNT s t o r e s a p o s i t i o n i n the main program as i t s r e t u r n address, and proceeds to c a l l i t s e l f r e c u r s i v e l y . The second i n c a r n a t i o n of COUNT now s t o r e s a p o s i t i o n i n COUNT as i t s r e t u r n address, thus o v e r w r i t i n g the l i n k back to the main program. When the f i r s t i n c a r n a t i o n e v e n t u a l l y t r i e s to r e t u r n , i t jumps to the p o s i t i o n i n COUNT and not i n the main program, and of course an endless loop r e s u l t s . Although c e r t a i n implementations (e.g. that on the VAX-11/780) a v o i d t h i s problem by p r o v i d i n g a separate l o c a t i o n f o r the r e t u r n address of each c a l l , the above scheme i s used on many machines (e.g. IBM 4341, Amdahl 470); c l e a r l y the F-code machine must be designed to work i n a l l s i t u a t i o n s . There e x i s t s a f a i r l y standard technique f o r s i m u l a t i n g r e c u r s i o n i n FORTRAN, which i s w e l l presented i n Larmouth's p a p e r ( 9 ) . Each l o c a l v a r i a b l e i n a r e c u r s i v e ' r o u t i n e i s re p l a c e d by a pushdown stack, with a f u r t h e r such stack being used f o r i n d i c a t i n g statement l a b e l s to which c o n t r o l i s t r a n s f e r r e d upon " r e t u r n i n g " . The r e s u l t i n g r o u t i n e i s never a c t u a l l y c a l l e d r e c u r s i v e l y ; i n s t e a d , i t i s c a l l e d once and simply jumps around w i t h i n i t s e l f , pushing and popping l o c a l v a r i a b l e s and statement l a b e l s , u n t i l i t s task i s accomplished. Chapter 3 : THE F-CODE MACHINE 20 The transformed r o u t i n e i s w r i t t e n e n t i r e l y i n Standard FORTRAN. The method appears to be a p p l i c a b l e to a l l d i r e c t l y r e c u r s i v e r o u t i n e s , and the r e q u i r e d t r a n s f o r m a t i o n s should not be very d i f f i c u l t to automate. However, i t has a number of s e r i o u s drawbacks which l e d to i t s r e j e c t i o n as a technique f o r F-code: the r e s u l t i n g r o u t i n e s are somewhat lengthy, the i n t r o d u c t i o n of numerous i n d i v i d u a l s t a c k s consumes a l o t of storage as w e l l as c r e a t i n g dangers of stack overflow at many p o i n t s , and worst of a l l , the method becomes extremely complicated when p r o v i s i o n i s made f o r mutually r e c u r s i v e r o u t i n e s . A f a r simpler and more elegant s o l u t i o n was d e v i s e d f o r the F-code machine and t h i s i s now d e s c r i b e d . Storage a l l o c a t i o n i s d e a l t with f i r s t ; l a t e r i t i s shown how the problem with r e t u r n addresses was s o l v e d . C. Storage A l l o c a t i o n and Addressing of V a r i a b l e s The F-code machine has one s i n g l e stack, which i s used fo r implementing a l l v a r i a b l e s i n a l l r o u t i n e s of the t r a n s l a t e d P a s c a l program. Thus, while procedures and f u n c t i o n s . i n Pascal become SUBROUTINES i n F-code, there i s no correspondence between t h e i r l o c a l v a r i a b l e s — i n f a c t , F-code SUBROUTINES have no v a r i a b l e s whatsoever! (They do have four s p e c i a l - p u r p o s e s t a t e i n d i c a t o r s , but these are r a r e l y used and do not r e a l l y behave as v a r i a b l e s ) . I t i s of i n t e r e s t to note that the F-code i t s e l f never a c t u a l l y provides a d e c l a r a t i o n of t h i s stack, and has Chapter 3 : THE F-CODE MACHINE 21 l i t t l e knowledge of i t s p r e c i s e form or implementation; i t may be regarded as part of the "hardware" of the F-code machine, manipulated only by means of p a r t i c u l a r i n s t r u c t i o n s . The stack i s u l t i m a t e l y r e a l i z e d as a l a r g e one-dimensional a r r a y of INTEGERS. P a s c a l ' s fundamental data types ( i n t e g e r , char, boolean, enumerated types) may a l l be e a s i l y mapped to INTEGERS using t h e i r ORD v a l u e s ; P a s c a l ' s data type r e a l i s c a t e r e d f o r by the very convenient device of EQUIVALENCEing an a r r a y of REALs over the o r i g i n a l stack, so that stack elements may a l s o be used to h o l d r e a l data d i r e c t l y . The stack i s organized i n a c o n v e n t i o n a l manner, s i m i l a r to that found i n many compilers f o r b l o c k - s t r u c t u r e d languages. Whenever a r o u t i n e i s entered, storage i s a l l o c a t e d on the top of the stack f o r i t s l o c a l v a r i a b l e s (as w e l l as c e r t a i n l i n k a g e i n f o r m a t i o n ) ; t h i s storage i s l a t e r r e l e a s e d when the r o u t i n e e x i t s . A major advantage of t h i s scheme i s i t s economy of storage, s i n c e the same area can be reused f o r a number of r o u t i n e s at d i f f e r e n t times. The bottommost stack p o s i t i o n a l l o t t e d to a r o u t i n e i s known as i t s base. Within a r o u t i n e , each l o c a l v a r i a b l e i s a s s i g n e d a f i x e d o f f s e t , denoting i t s r e l a t i v e p o s i t i o n i n the r o u t i n e ' s data area, with o f f s e t s being assigned to v a r i a b l e s i n the order i n which they are d e c l a r e d . The run-time address of a v a r i a b l e , i . e . i t s p o s i t i o n on the stack, i s then given by: Chapter 3 : THE F-CODE MACHINE 22 ADDRESS of v a r i a b l e = BASE of r o u t i n e + OFFSET of v a r i a b l e Note that each v a r i a b l e ' s o f f s e t i s a f i x e d constant which can be determined at compile-time, whereas the value of a r o u t i n e ' s base depends on which r o u t i n e s are c u r r e n t l y below i t on the stack, and so cannot be known u n t i l run-time. Because of P a s c a l ' s nested scoping r u l e s , when any r o u t i n e i s e x ecuting i t can access the v a r i a b l e s of a l l t e x t u a l l y e n c l o s i n g r o u t i n e s (which c l e a r l y are a l r e a d y a c t i v e on the s t a c k ) . Thus, f o r the a d d r e s s i n g of n o n - l o c a l v a r i a b l e s , the base values f o r a l l such r o u t i n e s must be a v a i l a b l e . A s p e c i a l a r r a y BASE — o f t e n known as a " d i s p l a y " — i s t h e r e f o r e maintained, where each element BASE(k) s t o r e s the base of the (unique) r o u t i n e with s t a t i c n e s t i n g l e v e l k which t e x t u a l l y encloses the c u r r e n t l y executing r o u t i n e . The s t a t i c l e v e l of each r o u t i n e i s of course known at compile-time. T h i s serves as an index i n t o BASE, and so the above formula may be used i n the a d d r e s s i n g of v a r i a b l e s at a l l l e v e l s . (For the present d i s c u s s i o n , only simple v a r i a b l e s are c o n s i d e r e d ; s t r u c t u r e d v a r i a b l e s such as ARRAYS and RECORDS i n v o l v e some e x t r a d e t a i l s and w i l l be d e a l t with l a t e r ) . C l e a r l y , the d i s p l a y BASE must be updated when a r o u t i n e i s entered, and r e s t o r e d to i t s former value when the r o u t i n e e x i t s . Suppose a l e v e l m r o u t i n e Rm c a l l s a l e v e l n r o u t i n e Rn. Since t h i s i m p l i e s that the name Rn must be known to Rm, e x a c t l y Chapter 3 : THE F-CODE MACHINE 23 one of the f o l l o w i n g three cases must h o l d : • Rn e n c l o s e s Rm (n < m) • Rn and Rm are at the same l e v e l and are d i r e c t l y enclosed by the same r o u t i n e (n = m) • Rn i s d i r e c t l y e nclosed by Rm (n = m+1) In a l l cases, Rn and Rm are both t e x t u a l l y e n c l o s e d by the same l e v e l n-1, n-2, ... 2, 1 r o u t i n e s , so that the f i r s t n-1 e n t r i e s i n BASE remain unchanged when Rm c a l l s Rn and only the s i n g l e entry i n BASE(n) needs to be a l t e r e d . Hence, the e n t i r e m a n i p u l a t i o n of the d i s p l a y reduces t o : CALL ROUTINE Rn : Save the c u r r e n t value of BASE(n) and set BASE(n) to the n e w l y - a l l o c a t e d base of Rn. RETURN FROM Rn : Restore BASE(n) to i t s p r e v i o u s l y - s a v e d v a l u e . (The o l d BASE(n) value i s s t o r e d on the stack i n the " l i n k a g e i n f o r m a t i o n " area of Rn). Note that t h i s scheme i s both simpler and more e f f i c i e n t than the widely-used method, d e s c r i b e d by W i r t h ( 1 9 ) , where an e x p l i c i t " s t a t i c c h a i n " i s maintained f o r updating the d i s p l a y . There i s one s i t u a t i o n however which cannot be handled by the above scheme and must be t r e a t e d s p e c i a l l y : c a l l - b y - r o u t i n e . If Rm takes a formal r o u t i n e parameter Rf and i s thereby passed Rn, then Rm need no longer know the name of Rn d i r e c t l y and so the s t a t i c environments of these two r o u t i n e s can d i f f e r Chapter 3 : THE F-CODE MACHINE 24 d r a s t i c a l l y . To c a t e r f o r t h i s , a s p e c i a l d i s p l a y - s i z e d region i s r e s e r v e d i n Rm's data area. When Rm i s invoked with a c t u a l parameter Rn, the s t a t i c environment of Rn i s c a l c u l a t e d and c o p i e d i n t o t h i s s p e c i a l d i s p l a y . When Rm now c a l l s Rf (= Rn), the c u r r e n t and s p e c i a l d i s p l a y s are sw.apped, thus e s t a b l i s h i n g the c o r r e c t s t a t i c environment f o r Rn. When Rn r e t u r n s , the d i s p l a y s are swapped back. Note t h a t while Rn i s e x e c u t i n g , i t accesses the d i s p l a y i n the normal way — i t does not even know that i t i s a parameter! The e x t r a work o u t l i n e d above w i l l not s e r i o u s l y degrade o v e r a l l performance s i n c e i n general r o u t i n e s are very r a r e l y passed as parameters. A l l F-code SUBROUTINES are parameterless, s i n c e parameters behave as l o c a l v a r i a b l e s and hence encounter the aforementioned problem i n cases of r e c u r s i o n . The parameters of a P a s c a l r o u t i n e are i n s t e a d a l l o c a t e d storage on the s t a c k , d i r e c t l y a f t e r the " l i n k a g e i n f o r m a t i o n " of i t s c orresponding F-code SUBROUTINE. The three d i f f e r e n t parameter-passing mechanisms allowed i n P a s c a l are handled as f o l l o w s : CALL BY VALUE : the a c t u a l parameter must be an e x p r e s s i o n ; i t i s e v a l u a t e d and i t s value loaded onto the stack. CALL BY ADDRESS : the a c t u a l parameter must be a v a r i a b l e ; at the time of c a l l , i t s address can be completely determined, and t h i s address i s loaded onto the s t a c k . Chapter 3 : THE F-CODE MACHINE 25 CALL BY ROUTINE : the a c t u a l parameter must be a r o u t i n e ; i t s " r o u t i n e number" (see s e c t i o n D below) i s loaded onto the stack. The parameters are loaded i n t o the data area of the c a l l e d r o u t i n e . Note that t h i s l o a d i n g i s done by the c a l l e r , before the a c t u a l t r a n s f e r of c o n t r o l takes p l a c e . The value of a P a s c a l f u n c t i o n may be simply t r e a t e d as another c a l l - b y - a d d r e s s parameter, with the address in t h i s case r e f e r r i n g to an anonymous l o c a t i o n i n the c a l l e r ' s data area to which the f u n c t i o n value i s r e t u r n e d . A l l storage a l l o c a t e d to a r o u t i n e i s r e l e a s e d upon e x i t , by r e s e t t i n g the stack p o i n t e r TOP to below the r o u t i n e ' s base. To f a c i l i t a t e t h i s , a s p e c i a l v a r i a b l e BASEXC p o i n t s to the base of the executing r o u t i n e , which in t u r n p o i n t s back to the base of i t s c a l l e r — t h i s i s the standard "dynamic l i n k " . The top p o r t i o n of the stack when a r o u t i n e i s entered i s shown below; note that the bottom three l o c a t i o n s are used f o r the l i n k a g e i n f o r m a t i o n , so that the o f f s e t values begin at 3. stack grows t h i s way ===> b a s e l e v e l s a v e d I I I i i o f o f BASE p a r a m e t e r s l o c a l s c a l l e r c a l l e d v a l u e i I I i i BASEXC TOP F i g . 3 : Storage A l l o c a t i o n f o r a Routine Chapter 3 : THE F-CODE MACHINE D. The R o u t i n e - C a l l i n g Mechanism 26 The problem concerning r e t u r n addresses can now be s o l v e d by s t o r i n g them on the s t a c k . Before c a l l i n g a r o u t i n e , the c a l l e r f i r s t l y a l l o c a t e s a "save area" on the stack, immediately below the base of the c a l l e d r o u t i n e , f o r s t o r i n g the address in i t s code to which c o n t r o l should l a t e r be r e t u r n e d . Upon e x i t from the c a l l e d r o u t i n e , t h i s r e t u r n address i s r e t r i e v e d from the stack and used in a d i r e c t jump back to the c a l l e r . The a c t u a l s t o r i n g of the r e t u r n address and the subsequent r e t u r n jump are performed by the r o u t i n e s SAVENV and GOBACK r e s p e c t i v e l y . These r o u t i n e s are h i g h l y machine-dependent and must g e n e r a l l y be w r i t t e n i n assembly language. (However, they are t y p i c a l l y very simple; f o r example, on the IBM 4341 or Amdahl 470, they have a combined t o t a l of e s s e n t i a l l y only 11 i n s t r u c t i o n s ) . They form p a r t of the small i n t e r f a c e that must be w r i t t e n to i n s t a l l the F-code machine i n each environment. F o r t u n a t e l y , i n some cases (e.g. VAX-11/780) r e t u r n addresses are a u t o m a t i c a l l y saved on the machine's own stack, so that SAVENV and GOBACK are then unnecessary and can simply be empty r o u t i n e s . For c e r t a i n FORTRAN implementations, i t was found that some a d d i t i o n a l r e g i s t e r s from the c a l l e r a l s o have to be preserved d u r i n g a r o u t i n e c a l l . In such s i t u a t i o n s , the save area can be enlarged, and SAVENV and GOBACK used to save and r e s t o r e a l l of the necessary environment. Chapter 3 : THE F-CODE MACHINE 27 A s p e c i a l r o u t i n e CALLUP a c t s as an i n t e r f a c e between the c a l l e r and the c a l l e d r o u t i n e s . I t i s l i s t e d o v e r l e a f , and summarizes the a c t i o n s i n v o l v e d i n r o u t i n e - c a l l i n g . C o n t r o l i s t r a n s f e r r e d between r o u t i n e s a c c o r d i n g to the scheme: c a l l e r ===> CALLUP ===> c a l l e d ===> CALLUP ===> c a l l e r The r e t u r n " c a l l e d ===> CALLUP" i s simply c a r r i e d out by the RETURN statement i n the c a l l e d r o u t i n e . However, (unless the machine i t s e l f s t a c k s r e t u r n a d d r e s s e s ) , the f i n a l r e t u r n "CALLUP ===> c a l l e r " i n v o l v e s the stacked r e t u r n address and w i l l a c t u a l l y be performed by the r o u t i n e GOBACK, not by CALLUP's RETURN statement, s i n c e the s i n g l e l o c a t i o n provided fo r CALLUP's r e t u r n address would be o v e r w r i t t e n i n the case of nested c a l l s . Each P a s c a l r o u t i n e i s as s i g n e d a unique r o u t i n e number, and F-code r o u t i n e s are c o r r e s p o n d i n g l y named R1, R2, R3, e t c . (For u n i f o r m i t y , P a s c a l ' s main program i s a l s o t r e a t e d as a ro u t i n e — R1 — which i s a u t o m a t i c a l l y invoked from the F-code main program). T h i s number serves as the f i r s t parameter to CALLUP and i d e n t i f i e s the r o u t i n e to be c a l l e d . I t a l s o p r o v i d e s an extremely convenient method of d e a l i n g with c a l l - b y - r o u t i n e parameters: as mentioned e a r l i e r , the r o u t i n e number i s passed on the stack and can l a t e r be used d i r e c t l y , as CALLUP's f i r s t parameter, to invoke the passed r o u t i n e . Chapter 3 : THE F-CODE MACHINE 28 SUBROUTINE CALLUP (NUMBER, LEVEL, PARSIZ) C C >>> Routine C a l l i n g I n t e r f a c e f o r F-code C INTEGER NUMBER, LEVEL, PARSIZ, SAVEPT, OLDBSX, LEV INTEGER STACK(5000), TOP, BASE(30), SAVESZ, LINKSZ, BASEXC COMMON STACK, TOP, BASE, SAVESZ, LINKSZ, BASEXC C C >>> Save the c a l l e r ' s environment on the stack C SAVEPT = TOP - PARSIZ - LINKSZ + 1 CALL SAVENV(STACK(SAVEPT)) C C > » Set the dynamic l i n k and update the d i s p l a y C OLDBSX = BASEXC BASEXC = SAVEPT + SAVESZ STACK(BASEXC) = OLDBSX STACK(BASEXC + 1) = LEVEL STACK(BASEXC + 2) = BASE(LEVEL) BASE(LEVEL) = BASEXC C C >>> C a l l the r o u t i n e C GOTO (1, 2, ..., n) NUMBER 1 CALL R1 GOTO n+1 2 CALL R2 GOTO n+1 n CALL Rn GOTO n+1 C C >>> Reset the d i s p l a y and r e l e a s e storage C n+1 LEV = STACK(BASEXC + 1) BASE(LEV) = STACK(BASEXC + 2) SAVEPT = BASEXC - SAVESZ BASEXC = STACK(BASEXC) TOP = SAVEPT - 1 C C >>> Restore the c a l l e r ' s environment and r e t u r n C CALL GOBACK(STACK(SAVEPT)) RETURN END F i g . 4 : The Routine CALLUP Chapter 3 : THE F-CODE MACHINE 29 Notes on CALLUP: • NUMBER = r o u t i n e number of c a l l e d r o u t i n e LEVEL = s t a t i c n e s t i n g l e v e l of c a l l e d r o u t i n e PARSIZ = s i z e of parameter block of c a l l e d r o u t i n e SAVESZ = s i z e of save area LINKSZ = SAVESZ + 3 ( f o r l i n k a g e information) n = t o t a l number of r o u t i n e s i n P a s c a l source program. • Since n depends on the p a r t i c u l a r program being t r a n s l a t e d , the r o u t i n e CALLUP must be w r i t t e n each time by the t r a n s l a t o r . • Before invoking CALLUP, the c a l l e r w i l l a l r e a d y have c r e a t e d space on the stack f o r both the save area and the l i n k a g e i n f o r m a t i o n . T h i s must be done by the c a l l e r , s i n c e i t now proceeds to loa d the a c t u a l parameters onto the stack beyond t h i s space. • A f u l l example of the e n t i r e r o u t i n e - c a l l i n g mechanism may be found i n Appendix B (Towers of Hanoi). E. F-code I n s t r u c t i o n s and The Run-time L i b r a r y The P a s c a l - F t r a n s l a t o r takes a P a s c a l program and from i t generates an e q u i v a l e n t F-code program. The o v e r a l l s t r u c t u r e of t h i s r e s u l t a n t program has al r e a d y been d e s c r i b e d ; i t s i n d i v i d u a l i n s t r u c t i o n s are now c o n s i d e r e d . It must f i r s t be emphasized that every i n s t r u c t i o n i n F-code i s a FORTRAN statement — F-code i s not i n any way Chapter 3 : THE F-CODE MACHINE 30 " t r a n s l a t e d " i n t o FORTRAN, • F-code a c t u a l l y ijs FORTRAN! Ne v e r t h e l e s s , f o r the general d i s c u s s i o n i t s t i l l remains c o n c e p t u a l l y simpler and more convenient to view F-code as the assembly language of an a b s t r a c t machine which has a d i r e c t "implementation" in FORTRAN. Some F-code i n s t r u c t i o n s are simple FORTRAN statements, but the m a j o r i t y r e q u i r e more complex a c t i o n s and take the form of a c a l l to a corresponding r o u t i n e . C o l l e c t i v e l y , these r o u t i n e s c o n s t i t u t e the run-time l i b r a r y . A complete l i s t i n g of t h i s l i b r a r y i s given in Appendix C, together with a f u l l e x p l a n a t i o n of each a s s o c i a t e d F-code i n s t r u c t i o n . Note that t h i s p r o v i d e s a t o t a l d e f i n i t i o n of the F-code machine f o r P a s c a l . The run-time l i b r a r y may be d i v i d e d i n t o the f o l l o w i n g major s e c t i o n s ( f o r d e t a i l s , c o n s u l t the l i s t i n g ) : ENVIRONMENT INTERFACE: Four r o u t i n e s i n t e r f a c e the F-code machine with the r e a l computer; they provide F-code with d e t a i l s of the c h a r a c t e r set and algorit h m s f o r packing / unpacking i n d i v i d u a l words. A f u r t h e r four r o u t i n e s are used to i n t e r f a c e with the o p e r a t i n g system; these d e a l with c e r t a i n I/O p r i m i t i v e s that e i t h e r cannot be implemented i n Standard FORTRAN or w i l l vary between d i f f e r e n t systems. The p a r t i c u l a r i n t e r f a c e given i n the l i s t i n g i s that f o r the Amdahl 470 running under MTS. S t r i c t l y speaking, these r o u t i n e s do not correspond d i r e c t l y to any F-code i n s t r u c t i o n s , but serve to i s o l a t e a l l of the Chapter 3 : THE F-CODE MACHINE 31 environment-dependent a c t i o n s needed by the other r o u t i n e s . (The i n t e r f a c e r o u t i n e s SAVENV and GOBACK are g e n e r a l l y w r i t t e n i n assembly language and are not i n c l u d e d i n the l i s t i n g . They are invoked only by CALLUP). STACK MANIPULATION: The Pascal-F t r a n s l a t o r generates p o s t f i x code f o r expre s s i o n s and t h i s i s executed on the stack i n the c o n v e n t i o n a l manner. The corresponding stack i n s t r u c t i o n s i n c l u d e v a r i o u s loads and s t o r e s , together with a wide range of a r i t h m e t i c , l o g i c a l , s e t - t h e o r e t i c and r e l a t i o n a l o p e r a t o r s . I t may be of i n t e r e s t to note that a f t e r t h i s set of i n s t r u c t i o n s had been f u l l y developed, i t was d i s c o v e r e d that many have almost exact c o u n t e r p a r t s i n OCODE, the intermediate code of BCPL. T h i s concurrence, while not t o t a l l y s u r p r i s i n g , does provide a l i t t l e e x t r a encouragement f o r the f e a s i b i l i t y of a standard a b s t r a c t machine. INPUT / OUTPUT: FORTRAN'S READ and WRITE statements always t r a n s f e r a complete r e c o r d each time they are executed. P a s c a l ' s more " f l e x i b l e READ and WRITE, on the other hand, can s u c c e s s i v e l y move along on the same r e c o r d . To brid g e the gap between these two methods, the F-code run-time l i b r a r y e x p l i c i t l y implements a f u l l b u f f e r e d I/O system. A s s o c i a t e d with each f i l e i s a b u f f e r LINE, which s t o r e s ( i n i n t e g e r form) the c h a r a c t e r s of the l i n e c u r r e n t l y being read or w r i t t e n . For inp u t , a l i n e Chapter 3 : THE F-CODE MACHINE 32 i s read and pl a c e d i n the b u f f e r by the s p e c i a l system i n t e r f a c e r o u t i n e GETLN, which a l s o r e t u r n s the l e n g t h of the l i n e and an e n d - o f - f i l e f l a g (these cannot be determined using Standard FORTRAN). For output, the r o u t i n e WRLN changes the b u f f e r to c h a r a c t e r form and tr a n s m i t s i t using a FORTRAN WRITE statement. The reading and w r i t i n g of i n d i v i d u a l items then c o n s i s t s of t r a n s f e r r i n g data between stack and b u f f e r . RDCH, f o r example, gets the next c h a r a c t e r from the b u f f e r and st o r e s i t i n the v a r i a b l e whose address i s on the top of the stack, while WRCH takes the next- t o - t o p c h a r a c t e r on the stack and p l a c e s i t i n the b u f f e r , using the top stack element as f i e l d - w i d t h . (This e n t i r e I/O system i s f o r P a s c a l TEXT f i l e s o nly; non-TEXT f i l e s r e q u i r e no such b u f f e r i n g and simply use FORTRAN'S unformatted I/O statements d i r e c t l y ) . RUN-TIME ERROR HANDLER: Run-time e r r o r s i n an F-code program are handled by the ro u t i n e RUNERR, which outputs a message d e s c r i b i n g the nature and l o c a t i o n of the e r r o r , and then terminates e x e c u t i o n . T h i s e r r o r l o c a t i o n i s given i n the form of the (approximate) source program l i n e number at which the e r r o r occurred, t h i s form being by f a r the most h e l p f u l . In order that such i n f o r m a t i o n be a v a i l a b l e at run-time, the F-code i n s t r u c t i o n s f o r every major s y n t a c t i c c o n s t r u c t being t r a n s l a t e d are preceded by the s p e c i a l i n s t r u c t i o n : LINNUM = <current source program l i n e number> . Note that t h i s a l s o p r o v i d e s a very u s e f u l r e f e r e n c e f o r Chapter 3 : THE F-CODE MACHINE 33 manually checking the generated F-code a g a i n s t the o r i g i n a l P a s c a l source program — see Appendix B f o r examples. MAIN PROGRAM: The main program f o r F-code i s a c t u a l l y part of the run-time l i b r a r y . As mentioned e a r l i e r , i t invokes the P a s c a l main program, which has been t r a n s l a t e d i n t o the SUBROUTINE R1. I t a l s o i n i t i a l i z e s the stack, e t c . , as w e l l as pr e p a r i n g f i l e s at the s t a r t and c l o s i n g them at the end of program e x e c u t i o n . A study of the run-time l i b r a r y should demonstrate how e a s i l y new i n s t r u c t i o n s can be f i t t e d i n t o the F-code framework by simply adding a p p r o p r i a t e r o u t i n e s to the l i b r a r y . Although i n g e n e r a l , an intermediate code's i n s t r u c t i o n s tend to be kept s e m a n t i c a l l y weak i n order to ease t h e i r implementation a c r o s s a wide range of environments, with F-code there i s c l e a r l y no such c o n s t r a i n t . Even i f c e r t a i n semantic a c t i o n s which occur together are o v e r a l l f a i r l y complex, they can n e v e r t h e l e s s be i d e n t i f i e d as " p r i m i t i v e " and implemented by a s i n g l e F-code i n s t r u c t i o n (see f o r example LDKYCH and PREFOR), T h i s helps s i g n i f i c a n t l y i n keeping F-code programs compact. 34 Chapter 4 : THE PASCAL-F TRANSLATOR T h i s chapter f i r s t p r o v i d e s a b r i e f overview of the t r a n s l a t o r , and then g i v e s d e t a i l s of the F-code p a t t e r n s generated f o r each P a s c a l c o n s t r u c t . A. General D e s c r i p t i o n The P a s c a l - F t r a n s l a t o r takes a Pascal program as input and generates an e q u i v a l e n t F-code program as output. I t a l s o produces a l i s t i n g , c o n t a i n i n g the Pascal source together with d i a g n o s t i c s f o r any e r r o r s which were d e t e c t e d . In order to minimize storage requirements, a second input f i l e i s used to h o l d the (very bulky) t e x t of these e r r o r messages, rather than keeping them i n an i n t e r n a l a r r a y . L i n e s are then read from t h i s f i l e , as needed, and w r i t t e n onto the l i s t i n g . The t r a n s l a t o r i s of course w r i t t e n i n P a s c a l , so that i t can u l t i m a t e l y c r e a t e an F-code v e r s i o n of i t s e l f . Although i t was i n i t i a l l y developed under e x i s t i n g compilers which provided many language e x t e n s i o n s , the t r a n s l a t o r was w r i t t e n with p a r t i c u l a r a t t e n t i o n to ensuring that only standard P a s c a l was used. Thus no d i f f i c u l t i e s arose with non-standard f e a t u r e s when a s e l f - t r a n s l a t i o n was performed. Furthermore, i t was p o s s i b l e t o t r a n s f e r the t r a n s l a t o r with the g r e a t e s t ease between three q u i t e d i f f e r e n t environments (on two c o n t i n e n t s ! ) d u r i n g i t s development. Chapter 4 THE PASCAL-F TRANSLATOR 35 With the exception then of a small number of s p e c i a l machines-dependent c o n s t a n t s , shown i n F i g . 5 below, the e n t i r e t r a n s l a t o r i s completely independent of i t s environment. These con s t a n t s are gathered together at the very s t a r t of the program where they may e a s i l y be m o d i f i e d to s u i t d i f f e r e n t machines. E s s e n t i a l l y , they a l l depend on only two f a c t o r s : the machine's wordlength and i t s c h a r a c t e r s e t . F i g . 5 : Machine-Dependent Constants i n the T r a n s l a t o r Because a l l machine dependencies have been i s o l a t e d i n t o these c o n s t a n t s , generating a copy of the t r a n s l a t o r f o r a machine with d i f f e r e n t c h a r a c t e r i s t i c s i s a very s t r a i g h t f o r w a r d task. At an e x i s t i n g P a s c al-F i n s t a l l a t i o n , simply a d j u s t the values of these c o n s t a n t s i n the P a s c a l v e r s i o n of the t r a n s l a t o r and then feed t h i s through the c u r r e n t F-code v e r s i o n . The r e s u l t w i l l be a new copy of the t r a n s l a t o r , w r i t t e n i n F-code, capable of both running on the t a r g e t machine and gen e r a t i n g s u i t a b l e F-code f o r i t . (To allow f o r such " c r o s s - c o m p i l a t i o n " , note that a separate constant MAXINTEGER i s used above, r a t h e r than the p r e d e f i n e d MAXINT). const MAXINTEGER MAXINTDIV10 MAXINTM0D10 MAXORDCHAR CHARSPERINT MAXORDSET INTSPERSET Max INTEGER value on t h i s machine MAXINTEGER d i v 10 MAXINTEGER mod 10 Max ORD value f o r CHARs No of c h a r a c t e r s per INTEGER storage u n i t Max ORD value f o r SET elements (MAXORDSET+1) d i v (no of b i t s per INTEGER) Chapter 4 : THE PASCAL-F TRANSLATOR 36 The o v e r a l l s t r u c t u r e of the Pascal-F t r a n s l a t o r i s b a s i c a l l y s i m i l a r to those of the well-known P a s c a l - P ( 1 2 ) and P a s c a l - S ( 2 0 ' t r a n s l a t o r s . The e n t i r e t r a n s l a t i o n i s c a r r i e d out in a s i n g l e pass, the three a c t i v i t i e s of scanning, p a r s i n g , and F-code gener a t i o n being i n t e r l e a v e d . The r e c u r s i v e - d e s c e n t p a r s i n g technique i s used, with a separate p a r s i n g procedure f o r each p r o d u c t i o n i n P a s c a l ' s grammar. Rather than w r i t e the e n t i r e P a s c al-F t r a n s l a t o r from s c r a t c h , c o n s i d e r a t i o n was i n i t i a l l y given to modifying Pascal-P to produce F-code rather than P-code. However, t h i s approach was soon r e j e c t e d f o r a number of reasons. S u b s t a n t i a l changes would be necessary i n order to allow f o r c e r t a i n aspects of r e c u r s i o n and v a r i a b l e - a d d r e s s i n g i n F-code; i t was f e l t that the r e s u l t i n g t r a n s l a t o r then c o u l d s t i l l be f a i r l y i n d i r e c t . Moreover, d e s p i t e i t s d i s t i n g u i s h e d b i r t h p l a c e , the Pascal-P code i t s e l f was found s u r p r i s i n g l y d i f f i c u l t to read. F i n a l l y , i t should be s a i d that the c r e a t i v e prospect of d e s i g n i n g and implementing an o r i g i n a l program appeared f a r more a t t r a c t i v e than the thought of ploughing through an e x i s t i n g program to i s o l a t e and c a r r y out the. l a r g e number of necessary m o d i f i c a t i o n s . I t may be of i n t e r e s t t o note that the Pascal-F t r a n s l a t o r e v e n t u a l l y c o n t a i n e d fewer than h a l f the number of statements o c c u r r i n g i n Pascal-P, while a l s o being ( h o p e f u l l y ! ) q u i t e easy to read and understand. Chapter 4 : THE PASCAL-F TRANSLATOR B. F-code Generation P a t t e r n s 37 For f u l l d e t a i l s of a l l the F-code i n s t r u c t i o n s r e f e r r e d to below, c o n s u l t the run-time l i b r a r y l i s t i n g i n Appendix D. P a r t i c u l a r i n s t a n c e s of most of the f o l l o w i n g p a t t e r n s may be found i n the sample t r a n s l a t i o n s of Appendix C. P a s c a l programs c o n s i s t of d e c l a r a t i o n s and statements. D e c l a r a t i o n s are e s s e n t i a l l y d i r e c t i o n s to the t r a n s l a t o r to guide the way i t analyses and generates code f o r statements. However, a l l the d e c l a r a t i o n s i n a r o u t i n e themselves r e s u l t i n the g e n e r a t i o n of only a s i n g l e F-code i n s t r u c t i o n : a c a l l to UPTOP to a l l o c a t e a block of storage on the stack f o r a l l the l o c a l v a r i a b l e s d e c l a r e d i n the r o u t i n e . The t r a n s l a t i o n to F-code of both the i n d i v i d u a l components of statements, as w e l l as the statements themselves, i s now c o n s i d e r e d . CONSTANTS: A l l s c a l a r c onstants i n the P a s c a l source program, r e g a r d l e s s of t h e i r data-type, are represented by INTEGERS i n F-code using the n a t u r a l ORD mapping. S t r i n g c o n s t a n t s , on the other hand, are represented by corresponding H o l l e r i t h s t r i n g s . Constants can occur only w i t h i n e x p r e s s i o n s ; whenever a constant i s encountered, a LDVALU ( f o r s c a l a r s ) or LDSTR ( f o r s t r i n g s ) i n s t r u c t i o n i s generated to l o a d i t s value onto the stack. Chapter 4 : THE PASCAL-F TRANSLATOR 38 VARIABLES: As d e s c r i b e d i n the p r e v i o u s chapter, the stack i s used to represent a l l P a s c a l v a r i a b l e s , which are i d e n t i f i e d by means of t h e i r stack addresses. The t r a n s l a t o r ' s symbol t a b l e s t o r e s the d e c l a r a t i o n l e v e l and o f f s e t of each v a r i a b l e , which together with the d i s p l a y BASE completely determine i t s address. The address of an e n t i r e v a r i a b l e i s loaded onto the stack by the i n s t r u c t i o n LDADDR. For a s t r u c t u r e d v a r i a b l e , an ARRCMP or RECFLD i n s t r u c t i o n can then be added to load the address of an a r r a y component or r e c o r d f i e l d , r e s p e c t i v e l y . For v a r i a b l e s which are formal VAR parameters, an e x t r a d e r e f e r e n c i n g i n s t r u c t i o n LDSIMP i s used to load the address of the a c t u a l parameter, s i n c e t h i s address i s s t o r e d as the formal's v a l u e . The value of a v a r i a b l e i s loaded by f i r s t l y l o a d i n g i t s address and then using LDSIMP ( f o r simple v a r i a b l e s ) or LDSRUC (f o r s t r u c t u r e d v a r i a b l e s ) to dereference t h i s address. F i e l d i d e n t i f i e r s o c c u r r i n g on t h e i r own i n s i d e a WITH statement are t r e a t e d e x a c t l y as v a r i a b l e s — see the d e s c r i p t i o n of WITH below. FILES: Although f i l e s i n P a s c a l are c o n s i d e r e d to be v a r i a b l e s , i t i s more convenient to deal with them s e p a r a t e l y f o r purposes of code g e n e r a t i o n . F i l e s are represented i n F-code by FORTRAN " l o g i c a l u n i t numbers", these being used d i r e c t l y i n a l l I/O Chapter 4 : THE PASCAL-F TRANSLATOR 39 i n s t r u c t i o n s . L o g i c a l u n i t numbers are a s s i g n e d to P a s c a l f i l e s i n the order i n which the f i l e s are l i s t e d i n the program heading. EXPRESSIONS: Exp r e s s i o n s are t r a n s l a t e d i n t o c o n v e n t i o n a l p o s t f i x n o t a t i o n . For each operator, code i s f i r s t generated to load the v a l u e ( s ) of i t s operand(s) ( t h i s process may i n turn i n v o l v e f u l l e x p r e s s i o n e v a l u a t i o n ) , f o l l o w e d by an i n s t r u c t i o n to apply the operator to these v a l u e s . P r e d e c l a r e d f u n c t i o n s each have a separate F-code i n s t r u c t i o n , which i s generated a f t e r the code to l o a d i t s argument's va l u e . U s e r - d e c l a r e d f u n c t i o n s are c a l l e d i n a manner s i m i l a r to procedure i n v o c a t i o n d e s c r i b e d below. Note that a f t e r an e x p r e s s i o n has been f u l l y evaluated, i t s r e s u l t i s always l e f t on the top of the stack, a l l intermediate values having been popped. ASSIGNMENT STATEMENT: "VAR := EXPR" load address of VAR e v a l u a t e EXPR CALL STSIMP / CALL STSRUC(length) {VAR simple/structured} PROCEDURE CALL STATEMENT: "P ( A1, A2, ..., An )" CALL MKLINK for each a c t u a l parameter A i i n t u r n , l o a d i t s value/address/routine-number as the corresponding formal parameter i s v a l u e / v a r / r o u t i n e , r e s p e c t i v e l y CALL CALLUP(number, l e v e l , p a r s i z ) Chapter 4 : THE PASCAL-F TRANSLATOR 40 IF STATEMENT: " i f EXPR then STMT1 [ e l s e STMT2] L1 L2 e v a l u a t e EXPR IF (FALSE(0)) GOTO L1 code f o r STMT1 GOTO L2 <=== CONTINUE code f o r STMT2 <=== CONTINUE <=== omit these i f there i s no " e l s e STMT2" CASE STATEMENT: "case EXPR of C1 : STMT1; C2A, C2B : STMT2; C3 : STMT3 end" L2 L3 L4 L5 L6 L1 e v a l u a t e EXPR CALL UNLOAD(CASNDX) IF (CASNDX .NE. c1) code f o r STMT1 GOTO L1 IF (CASNDX .NE. GOTO L4 IF (CASNDX .NE. CONTINUE code f o r STMT2 GOTO L1 IF (CASNDX .NE. code f o r STMT3 GOTO L1 CALL RUNERR(13) CONTINUE GOTO L2 c2a) c2b) GOTO L3 GOTO L5 c3) GOTO L6 {'CASE index out of range'} WHILE STATEMENT: "while EXPR do STMT" L1 CONTINUE eva l u a t e EXPR IF (FALSE(0)) GOTO L2 code f o r STMT GOTO L1 L2 CONTINUE Chapter 4 : THE PASCAL-F TRANSLATOR 41 REPEAT STATEMENT: "repeat STMT1; STMT2; ...; STMTn u n t i l EXPR" L1 CONTINUE code f o r STMT1 code f o r STMT2 code f o r STMTn eva l u a t e EXPR IF (FALSE(0)) GOTO L1 FOR STATEMENT: " f o r VAR := EXPR1 to/downto EXPR2 do STMT" eval u a t e EXPR1 evaluate EXPR2 CALL PREFORO/-1, d e c l e v , o f f s e t , NOLOOP) IF (NOLOOP) GOTO L1 L2 CONTINUE code f o r STMT CALL TESTEP(MORE, 1/-1) IF (MORE) GOTO L2 L1 CONTINUE WITH STATEMENT: "with REC-VAR do STMT" load address of REC-VAR CALL RECBAS(level) code f o r STMT CALL RSTBAS(level) The scope of a WITH statement i s e s s e n t i a l l y a new n e s t i n g l e v e l i n which a l l the f i e l d s of REC-VAR are d e c l a r e d as v a r i a b l e s . The base address f o r t h i s new l e v e l i s the address of REC-VAR, which i s s t o r e d i n the d i s p l a y by RECBAS; the o f f s e t of each v a r i a b l e ( i . e . f i e l d ) i s the r e l a t i v e p o s i t i o n of the f i e l d w i t h i n REC-VAR. On e x i t from the WITH statement, the d i s p l a y i s r e s t o r e d to i t s former s t a t u s by RSTBAS. 42 Chapter 5 : RESULTS AND CONCLUSIONS Pas c a l - F has so f a r been i n s t a l l e d i n the f o l l o w i n g three environments: • Amdahl 470 running under MTS • IBM 4341 running under CMS • VAX-11/780 running under VMS Although f u r t h e r experiments are needed to t e s t i t s p o r t a b i l i t y more f u l l y , the r e s u l t s to date have been encouraging and suggest that the Pascal-F system i s h i g h l y p o r t a b l e . The environment i n t e r f a c e i s i s o l a t e d i n t o a small set of constants i n the t r a n s l a t o r and a number of very short and simple r o u t i n e s i n the run-time l i b r a r y . M o d i f y i n g these was q u i t e s t r a i g h t f o r w a r d i n the above cases. By c o n t r a s t with r e s u l t s f o r other p o r t a b l e P a s c a l c o m p i l e r s ! 1 0 ' the t r a n s f e r of Pascal-F to a new environment i n v o l v e s only a f r a c t i o n of the e f f o r t which i s normally r e q u i r e d . Because of time c o n s t r a i n t s on t h i s p r o j e c t , the c u r r e n t v e r s i o n of the t r a n s l a t o r does not implement the f u l l P a s c a l language. A l i s t of the unsupported f e a t u r e s i s given i n Appendix A. With only two excepti o n s , the implementation of a l l these missing f e a t u r e s has been f u l l y designed, and i t was found that they can be g r a f t e d on without any fundamental changes to the e x i s t i n g F-code machine and without i n t r o d u c i n g any f u r t h e r environment-dependencies. A problem a r i s e s , however, with i n t e r n a l f i l e s , i . e . f i l e s not l i s t e d i n the program heading, Chapter 5 : RESULTS AND CONCLUSIONS 43 s i n c e these do not appear to have any n a t u r a l implementation w i t h i n the present framework. Co n s i d e r a b l e d i f f i c u l t i e s a l s o occur with implementing a GOTO which jumps out of a r o u t i n e ; i n the o p i n i o n of many language d e s i g n e r s , such a f e a t u r e should not be allowed i n the f i r s t p l a c e ! N e v e r t h e l e s s , the c u r r e n t language r e s t r i c t i o n s are not con s i d e r e d to be a s e r i o u s drawback, s i n c e P a s c a l - F i s b a s i c a l l y a study i n p o r t a b i l i t y , and the t r a n s l a t o r does possess the c r u c i a l a b i l i t y to perform s e l f - t r a n s l a t i o n . The t r a n s l a t o r i s a remarkably short program, c o n s i s t i n g of some 1,400 P a s c a l statements o n l y . I t s F-code v e r s i o n c o n s i s t s of fewer than 10,000 i n s t r u c t i o n s , i n d i c a t i n g a t y p i c a l P a s c a l to F-code expansion f a c t o r of about 7. Because the t r a n s l a t o r i s so short and both i t and F-code are ( h o p e f u l l y ! ) easy to read and understand, i t i s planned to use Pascal-F i n an upcoming i n t r o d u c t o r y course on the implementation of programming languages. An i n t e r e s t i n g s i d e - e f f e c t of the Pascal-F p r o j e c t was the development of a number of u s e f u l "extensions" to FORTRAN, p a r t i c u l a r l y the b u f f e r e d I/O system, which can be used w i t h i n FORTRAN programs q u i t e independently of P a s c a l - F . Of course, the e n t i r e P a s c a l - F system may even be viewed as a h i g h l y c o n g e n i a l preprocessor f o r FORTRAN . — simply feed i n the s p e c i f i c a t i o n s i n the ple a s a n t n o t a t i o n of P a s c a l , and the Chapter 5 : RESULTS AND CONCLUSIONS 44 t r a n s l a t o r w i l l a u t o m a t i c a l l y generate the r e q u i r e d FORTRAN program! I t has been seen that the o v e r a l l concept of u s i n g an e x i s t i n g h i g h - l e v e l language to d i r e c t l y implement an intermediate code has two s u b s t a n t i a l advantages: p o r t a b i l i t y and e x t e n s i b i l i t y . The c h i e f c o n t r i b u t i o n of the Pa s c a l - F p r o j e c t i s towards h e l p i n g e s t a b l i s h the v i a b i l i t y of t h i s approach. Because of i t s widespread a v a i l a b i l i t y , FORTRAN was chosen as the t a r g e t language, d e s p i t e i t s s e r i o u s d e f i c i e n c i e s . Even with such c o n s t r a i n t s , i t was s t i l l p o s s i b l e to develop a po r t a b l e t r a n s l a t o r . With b e t t e r - s u i t e d languages becoming more widely a v a i l a b l e , the concept of a standard a b s t r a c t machine based on a h i g h - l e v e l language may have an i n t e r e s t i n g and promising f u t u r e . 45 BIBLIOGRAPHY 1 American N a t i o n a l Standards I n s t i t u t e [1966] American  Standard FORTRAN — X3.9, New York 2 Bourne, S.R., B i r r e l l , A.D., and Walker, I.W. [1975] Z-code, an intermediate o b j e c t code f o r A l g o l 68, The Computer Laboratory, Cambridge. 3 Brandon, D.H. [1977] "Commercial Software", i n Software  P o r t a b i l i t y ( E d i t o r : Brown, P.J.), Cambridge U n i v e r s i t y Press; chapter VI.D 4 Coleman, S.S., Poole, P.C., a n d W a i t e , W.M. [1974] "The Mobile Programming System, Janus" Software — P r a c t i c e and  Experience, V o l 4, pp 5-23 5 G r i s w o l d , R.E. [1972] The Macro Implementation of SN0B0L4;  A Case Study i n Machine-Independent Software Development, W.H. Freeman, San F r a n c i s c o 6 I n t e r n a t i o n a l Standards O r g a n i z a t i o n [1981] D r a f t Proposed  P a s c a l Standard, ISO dp 7185 7 Jensen, Kathleen, and Wirth, N i k l a u s [1974] Pa s c a l  User Manual and Report, S p r i n g e r - V e r l a g , New York 8 Kernighan, B r i a n W., and R i t c h i e , Dennis M. [1978] The C  Programming Language, P r e n t i c e - H a l l , New J e r s e y 9 Larmouth, J . [1973] "Serious FORTRAN — Part 2" Software — P r a c t i c e and Experience, V o l 3, pp 197-225 10 Lecarme, O l i v i e r , and Peyrolle-Thomas, Marie-Claude [1978] " S e l f - c o m p i l i n g Compilers: An A p p r a i s a l of t h e i r Implementation and P o r t a b i l i t y " Software — P r a c t i c e and  Experience, V o l 8, pp 149-170 11 Mock, 0., O l s t z y n , J . , Strong, J . , S t e e l , T., T r i t t e r , A., and Wegstein, J . [1958] "The problem of programming communications with changing machines: a proposed s o l u t i o n " Communications of the ACM, V o l 1 12 N o r i , K.V., Ammann, U., Jensen, K., and N a g e l i , H.H. [1974] The P a s c a l (P) Compiler: Implementation Notes, B e r i c h t e des I n s t i t u t s f u r Informatik, No. 10, Ei d g e n o s s i s c h e Technische Hochschule, Z u r i c h 13 Poole, Peter C. [1976] "P o r t a b l e and Adaptable Compilers", i n Compiler C o n s t r u c t i o n ( E d i t o r s : Bauer, F.L. and E i c k e l , J . ) , S p r i n g e r - V e r l a g , New York; chapter 5.A B i b l i o g r a p h y 46 14 R i c h a r d s , Martin [1977] " P o r t a b l e Compilers", i n Software  P o r t a b i l i t y ( E d i t o r : Brown, P.J.), Cambridge U n i v e r s i t y Press; chapter III.D 15 R i c h a r d s , M a r t i n , and Whitby-Strevens, C o l i n [1979] BCPL —  the language and i t s compiler, Cambridge U n i v e r s i t y Press 16 R i d l e r , P h i l i p F. [1979] A FORTRAN Reference Manual, Pitman, London 17 S t e e l , T.B. [1961] "A f i r s t v e r s i o n of UNCOL" Proc. AFIPS  WJCC, V o l 19 18 Weber, L.B. [1973] A Machine Independent P a s c a l Compiler, M.S. T h e s i s , Univ. of Colorado, Boulder 19 Wirth, N i k l a u s [1971] "The Design of a P a s c a l Compiler" Software — P r a c t i c e and Experience, V o l 1 , pp 309-333 20 Wirth, N i k l a u s [1975] Pascal-S : A Subset and i t s Implementation, B e r i c h t e des I n s t i t u t s f u r Informatik, No. 12, Eidgen o s s i s c h e Technische Hochschule, Z u r i c h 21 Wulf, W., Johnsson, R.K., Weinstock, C.B., Hobbs, S.O., and Geschke, CM. [1975] The Design of an O p t i m i z i n g Compiler, American E l s e v i e r , New York 47 Appendix A : LANGUAGE RESTRICTIONS UNDER PASCAL-F The f o l l o w i n g P a s c a l f e a t u r e s are not supported by the cu r r e n t P a s c a l - F t r a n s l a t o r : LABELS S t r i n g s i n CONST d e f i n i t i o n s The data type REAL P o i n t e r s V a r i a n t records without t a g - f i e l d s M u l t i - d i m e n s i o n a l a r r a y d e c l a r a t i o n s of the form ARRAY [T1, T2, . . . ] ; (use ARRAY [T1] OF ARRAY [T2] OF ...) Non-TEXT f i l e s I n t e r n a l f i l e s (not l i s t e d i n the program heading) The d e f a u l t f i l e s INPUT and OUTPUT F i l e b u f f e r s U s e r - d e f i n e d FUNCTIONS The GOTO statement The operator / The ope r a t o r s <= and >= f o r SETs The form EXPR .. EXPR i n SET c o n s t r u c t o r s M u l t i - d i m e n s i o n a l a r r a y s u b s c r i p t s of the form [E1 , E2, . . . ]; (use [E1][E2] ...) F i l e s , PROCEDURES, or FUNCTIONS as parameters The p r e d e c l a r e d procedures DISPOSE GET NEW PACK PAGE PUT UNPACK The p r e d e c l a r e d f u n c t i o n s ABS ARCTAN COS EXP LN ODD ROUND SIN SQR SQRT TRUNC In a d d i t i o n , compile-time checks on t y p e - c o m p a t i b i l i t y are incomplete, and run-time range checking (except f o r CASE index values) i s not implemented. 48 Appendix B : SAMPLE TRANSLATIONS The F-code generation p a t t e r n s of the t r a n s l a t o r are d i s c u s s e d i n Chapter 4, s e c t i o n B. These are now i l l u s t r a t e d by l i s t i n g two Pa s c a l programs, each followed by i t s t r a n s l a t i o n i n t o F-code. Appendix B SAMPLE TRANSLATIONS 4 ===>> P a s c a l - F T r a n s l a t o r 1 program TowersOfHanoi ( F ) ; 2 3 const 4 TOTALRINGS = 4; 5 6 var 7 F : TEXT; 8 g {  10 procedure HANOI . (RINGS, FROMPEG, TOPEG, WORKPEG : INTEGER); 1 1 20 2 1 { 22 begin 23 REWRITE(F); 24 25 WRITELN(F, 'Towers of Hanoi f o r ', TOTALRINGS:1, ' r i n g s ' ) ; 26 WRITELN(F); 27 WRITELN(F, 'Move top r i n g from peg _ to peg _ ' ) ; 28 29 HANOI(TOTALRINGS, 1, 2, 3) 30 end . 12 13 1 4 1 5 16 17 18 19 begin i f RINGS > 0 then begin HANOI(RINGS-1, FROMPEG, WORKPEG, TOPEG); WRITELN(F, FROMPEG:25, TOPEG:9); HANOI(RINGS-1, WORKPEG, TOPEG, FROMPEG) end end {HANOI} ; ==>> No e r r o r s d e t e c t e d Appendix B : SAMPLE TRANSLATIONS 50 SUBROUTINE R2 LOGICAL FALSE, NOLOOP, MORE INTEGER LINNUM, CASNDX, DFLTBW COMMON /LINCOM/ LINNUM LINNUM = 13 CALL LDADDR(2,3) CALL LDSIMP CALL LDVALU(O) CALL GT IF (FALSE(0)) GOTO 1 LINNUM = 15 MKLINK LDADDR(2,3) LDSIMP LDVALU(1) SUB LDADDR(2,4) LDSIMP LDADDR(2,6) LDSIMP LDADDR(2,5) LDSIMP CALLUP(2,2,4) LINNUM = 16 LDADDR(2,4) LDSIMP LDVALU(25) WRINT(1) LDADDR(2,5) LDSIMP LDVALU(9) WRINT(1) WRLN ( 1 ) LINNUM = 17 CALL MKLINK CALL LDADDR(2,3) CALL LDSIMP CALL LDVALU(1) CALL SUB CALL LDADDR(2,6) CALL LDSIMP CALL LDADDR(2,5) CALL LDSIMP CALL LDADDR(2,4) CALL LDSIMP CALL CALLUP(2,2,4) 1 CONTINUE RETURN END CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL . CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL CALL Appendix B : SAMPLE TRANSLATIONS 51 SUBROUTINE R1 LOGICAL FALSE, NOLOOP, MORE INTEGER LINNUM, CASNDX, DFLTBW COMMON /LINCOM/ LINNUM LINNUM = 23 CALL REWRIT(1) LINNUM = 25 CALL LDSTR(5, 20, 20HTowers of Hanoi f o r ) CALL LDVALU(20) CALL WRSTR(20,1) CALL LDVALUU) CALL LDVALU(1) CALL WRINT( 1 ) CALL LDSTR(2, 6, 8H r i n g s ) CALL LDVALU(6) CALL WRSTR(6,1) CALL WRLN( 1 ) LINNUM = 26 CALL WRLN(1) LINNUM = 27 CALL LDSTR(9, 33, 36HMove top r i n g from peg _ to peg _ ) CALL LDVALU(33) CALL WRSTR(33,1) CALL WRLN(1) LINNUM = 29 CALL MKLINK CALL LDVALUU) CALL LDVALU( 1 ) CALL LDVALU(2) CALL LDVALU(3) CALL CALLUP(2,2,4) RETURN END C C ============================================================== c SUBROUTINE CALLUP (NUMBER, LEVEL, PARSIZ) as i n Chapter 3, page 28, with n = 2 Appendix B : SAMPLE TRANSLATIONS 52 ===>> P a s c a l - F T r a n s l a t o r 1 program SIEVE ( F ) ; 2 3 { = = = = = = = = = = = = = = = = = = = = = =} 4 { S i e v e o f E r a t o s t h e n e s } 5 { = = = = = = = = = = = = = = = = = = = = = = } 6 7 const 8 TESTLIMIT = 200; 9 PRIMESPERLINE = 10; 10 1 1 var 12 F : TEXT; 13 ISPRIME : a r r a y [2 .. TESTLIMIT] of BOOLEAN; 14 INDEX, 15 TESTNUMBER, 16 PRIMECOUNT : INTEGER; 1 7 18 begin 19 REWRITE(F) ; 20 WRITELN(F, 'The primes up to ', TESTLIMIT:1, ' a r e : ' ) ; 21 PRIMECOUNT := 0; 22 23 { I n i t i a l i z e the s i e v e } 24 f o r INDEX := 2 to TESTLIMIT do ISPRIMEfINDEX] := TRUE; 25 26 { C a l c u l a t e and output the primes } 27 f o r TESTNUMBER := 2 to TESTLIMIT do 28 i f ISPRIMEfTESTNUMBER] then 29 begin 30 31 { Output and count TESTNUMBER } 32 WRITE(F, TESTNUMBER:6); 33 PRIMECOUNT := PRIMECOUNT + 1; 34 i f PRIMECOUNT mod PRIMESPERLINE = 0 then WRITELN(F); 35 36 { Remove a l l remaining m u l t i p l e s of TESTNUMBER } 37 INDEX := TESTNUMBER * TESTNUMBER; 38 while INDEX <= TESTLIMIT do 39 begin 40 ISPRIMEfINDEX] := FALSE; 41 INDEX := INDEX + TESTNUMBER 42 end 43 end; 44 45 WRITELN(F); 46 WRITELN(F, 'The number of primes up to ', TESTLIMIT:1, 47 ' i s ', PRIMECOUNT:1) 48 end . ===>> No e r r o r s d e t e c t e d Appendix B : SAMPLE TRANSLATIONS 53 SUBROUTINE R1 LOGICAL FALSE, NOLOOP, MORE INTEGER LINNUM, CASNDX, DFLTBW COMMON /LINCOM/ LINNUM LINNUM = 18 CALL UPTOP(202) LINNUM = 19 CALL REWRIT(1) LINNUM = 20 CALL LDSTR(5, 17, 20HThe primes up to ) CALL LDVALU(18) CALL WRSTR(18,1) CALL LDVALU(200) CALL LDVALU(1) CALL WRINT(1) CALL LDSTR(2, 5, 8H are: ) CALL LDVALU(5) CALL WRSTR(5,1) CALL WRLN(1) LINNUM = 21 CALL LDADDR(1,204) CALL LDVALU(O) CALL STSIMP LINNUM = 24 CALL LDVALU(2) CALL LDVALU(200) CALL PREFOR(1,1,202,NOLOOP) IF (NOLOOP) GOTO 1 2 CONTINUE LINNUM = 24 CALL LDADDR(1,3) CALL LDADDR(1,202) CALL LDSIMP CALL ARRCMP(2,1) CALL LDVALU(1) CALL STSIMP CALL TESTEP(MORE,1) IF (MORE) GOTO 2 1 CONTINUE LINNUM = 27 CALL LDVALU(2) CALL LDVALU(200) CALL PREFOR(1,1,203,NOLOOP) IF (NOLOOP) GOTO 3 4 CONTINUE LINNUM = 28 CALL LDADDR(1,3) CALL LDADDR(1,203) CALL LDSIMP CALL ARRCMP(2,1) CALL LDSIMP IF (FALSE(0)) GOTO 5 Appendix B : SAMPLE TRANSLATIONS 54 CALL LDADDR(1,203) CALL LDSIMP CALL LDVALUU) CALL WRINT( 1 ) CALL LDADDR(1,204) CALL LDADDR(1,204) CALL LDSIMP CALL LDVALU(1) CALL ADD CALL STSIMP CALL LDADDR(1,204) CALL LDSIMP CALL LDVALU(10) CALL MOD CALL LDVALU(O) CALL EQ IF (FALSE(0)) GOTO 6 CALL WRLN(1) 6 CONTINUE CALL LDADDR(1,202) CALL LDADDR(1,203) CALL LDSIMP CALL LDADDR(1,203) CALL LDSIMP CALL MUL CALL STSIMP 7 CONTINUE CALL LDADDR(1,202) CALL LDSIMP CALL LDVALU(200) CALL LE IF (FALSE(0)) GOTO 8 CALL LDADDR(1,3) CALL LDADDR(1,202) CALL LDSIMP CALL ARRCMP(2,1) CALL LDVALU(O) CALL STSIMP CALL LDADDR(1,202) CALL LDADDR(1,202) CALL LDSIMP CALL LDADDR(1,203) CALL LDSIMP CALL ADD LINNUM = 32 LINNUM = 33 LINNUM = 34 LINNUM = 34 LINNUM = 37 LINNUM = 38 LINNUM = 40 LINNUM = 41 Appendix B : SAMPLE TRANSLATIONS 55 CALL STSIMP GOTO 7 8 CONTINUE 5 CONTINUE CALL TESTEP(MORE,1) IF (MORE) GOTO 4 3 CONTINUE LINNUM = 45 CALL WRLN(1) LINNUM = 46 CALL LDSTR(7, 27, 28HThe number of primes up to ) CALL LDVALU(27) CALL WRSTR(27,1) CALL LDVALU(200) CALL LDVALU(1) CALL WRINT(1) CALL LDSTR(1, 4, 4H i s ) CALL LDVALU(4) CALL WRSTR(4,1) CALL LDADDR(1,204) CALL LDSIMP CALL LDVALU(1) CALL WRINT(1) CALL WRLN(1) RETURN END C C ====================================================== c SUBROUTINE CALLUP (NUMBER, LEVEL, PARSIZ) as i n Chapter 3, page 28, with n = 1 56 Appendix C : LISTING OF THE RUN-TIME LIBRARY A complete l i s t i n g of the run-time l i b r a r y i s given on the f o l l o w i n g pages. A general overview of i t s o r g a n i z a t i o n and purpose may be found i n Chapter 3, s e c t i o n E. The environment i n t e r f a c e r o u t i n e s are those f o r the Amdahl 470 V8 running under the Michigan Terminal System (MTS) with the FORTRAN H (21.8/4.1) co m p i l e r . The l i s t i n g below has been re-formatted somewhat from the a c t u a l program, i n order that i t may f i t onto these pages. Appendix C : LISTING-OF THE RUN-TIME LIBRARY 57 Q ****************************************************** C * P a s c a l - F R u n t i m e L i b r a r y * C * ===================================================== * c * * c * * C * L i s t of Routines : * c * * C * * C * BLOCK DATA (Machine I n t e r f a c e ) * C * UPKCWD (Machine I n t e r f a c e ) * C * PKSWD (Machine I n t e r f a c e ) * C * UPKSWD (Machine I n t e r f a c e ) * C * * C * OPENRD (Operating System I n t e r f a c e ) * C * OPENWR (Operating System I n t e r f a c e ) * C * GETLN (Operating System I n t e r f a c e ) * C * WRNULN (Operating System I n t e r f a c e ) * C * * C * UNPKSR * C * * C * UPTOP * C * MKLINK * C * * C * LDVALU * C * LDADDR * C * LDSIMP * C * LDSRUC * C * LDSTR * C * LDKYCH * C * * C * STSIMP * C * STSRUC * C * COPY * C * * C * RECBAS * C * RSTBAS * C * ARRCMP * C * RECFLD * C * * C * ADD * C * SUB * C * MUL * C * DIV * C * MOD * C * * C * NOT * C * AND * C * OR * C * * C * UNION * C * INTER * C * DIFF * Appendix C : LISTING OF THE RUN-TIME LIBRARY 58 c * IN * c * MKSET * c * PKSET * c * UPKSET * c * * c * EQ * c * NE * c * LT * c * LE * c * GT * c * GE * c * MKRELN * c * * c * PRED * c * SUCC * c * EOF * c * EOLN * c * * c * FALSE * c * UNLOAD * c * * c * PREFOR * c * TESTEP * c * * c * SETFLS * c * CLSFLS * c * CLSFIL * c * * c * RESET * c * GET * c * RDCH * c * RDINT * c * DGTEST * c * RDLN * c * * c * REWRIT * c * PUT * c * WRCH * c * WRINT * c * WRBOOL * c * DFLTBW * c * WRSTR * c * WRLN * c * * c * RUNERR * c * * c * Main Program * c * * c * * c * Machine - Dependent Constants : * c * * Appendix C : LISTING OF THE RUN-TIME LIBRARY 59 C * MAXORDCHAR + 1 ( s i z e of char set) * C * = no of e l t s i n CHR * C * CHR(n) = P a s c a l ' s CHR(n-l), 1 <= n <= MAXORDCHAR+1 * C * * C * ORDSPC = ORD(' ') * C * ORDPLS = ORD('+') * C * ORDMNS = ORD(* -') * C * ORDO = ORD('0') * C * ORD9 = ORD('9') * C * MXDV10 = MAXINT d i v 10 * C * MXMD10 = MAXINT mod 10 * C * SAVESZ = s i z e of save area * C * * C * CHARSPERINT (no of chars per INTEGER storage u n i t ) * C * = no of e l t s i n second param of r o u t i n e UPKCWD * C * = no of e l t s i n UWORD i n r o u t i n e UNPKSR * C * = no used to set UWDPOS in r o u t i n e UNPKSR * C * = used to set le n g t h s i n c a l l s to LDSTR i n WRBOOL * C * * C * WORDLENGTH (no of b i t s per INTEGER storage u n i t ) * C * MAXORDSET (max ORD value f o r SET elements) * C * INTSPERSET ((MAXORDSET+1) d i v WORDLENGTH) * C * = constants used i n * C * UNION, INTER, DIFF, IN, MKSET, PKSET, UPKSET * C * * C * MAXLINELEN (max l i n e l e n g t h f o r TEXT f i l e s ) * C * = no of rows i n LINE * C * = no of e l t s i n f o u r t h param of GETLN * C * = overflow l i m i t on LINLEN i n GET and PUT * C * = no of Al f i e l d s i n FORMAT stmt i n WRLN * C * * C * T r a n s l a t o r - Dependent Constants : * c * * C * * C * MAXFILES (max no of f i l e s permitted) * C * = no of c o l s i n LINE * C * = no of e l t s i n FILSTS, LINLEN, RDPOSN, * C * WINDOW, ENDFIL, ENDLIN * C * = upper l i m i t of FILNUM i n SETFLS and CLSFLS * C * * C * MAXSTACKSIZE (max s i z e of STACK) * C * = no of e l t s i n STACK * C * = overflow l i m i t i n r o u t i n e UPTOP * C * * C * MAXLEVEL (max s t a t i c n e s t i n g of r o u t i n e s ) * C * = no of e l t s i n BASE * C * = upper l i m i t of BASNUM i n Main Program * C * * C * F = 0 = ORD(FALSE) * C * T = 1 = ORD(TRUE) * C * * Q *************************************************** Appendix C : LISTING OF THE RUN-TIME LIBRARY 60 C BLOCK DATA C C Machine I n t e r f a c e Routine C Defin e s the values of the FILCOM c o n s t a n t s : C R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORD0,ORD9,MXDV10,MXMD10 C C V e r s i o n here f o r : C A l l machines using the EBCDIC char set C INTEGER LINE(254,6), FILSTS(6), LINLEN(6) , RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORD0, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORD0,ORD9,MXDV10,MXMD10 C DATA R/0/, W/1/, U/-1/, F/0/, T/1/ C DATA CHR( 1 ) /1 H /, CHR( 2) /1 H /, CHR( 3) /I H /, CHR( 4) /I H /, + CHR( 5) /1 H /, CHR( 6) /I H /, CHR( 7) /1 H /, CHR( 8) /I H /, + CHR( 9) /I H /, CHR( 10) /I H /, CHR( 1 1 ) /I H /, CHR( 12) /I H /, + CHR( 13) /1 H /, CHR( 14) /1 H /, CHR( 15) /1 H /, CHR( 16) /1 H /, + CHR( 17) /I H6/, CHR( 18) /1 H€/, CHR( 19) /1 H£/, CHR( 20) /I Hn/, + CHR( 21 ) /1 H e / , CHR( 22) /1 He/, CHR( 23) /1 H K / , CHR( 24) /I HX./, + CHR( 25) / I H»./, CHR( 26) /1 H i / / , CHR( 27) / I Ht/, CHR( 28) /1 Ho/, + CHR( 29] / I Hrr/, CHR( 30] /1 H/>/, CHR( 31 ) /1 Hff/, CHR( 32] /1 Hr/, + CHR( 33! / 1 Hu/, CHR( 34] / 1 H*/f CHR( 35] / 1 Hx/, CHR( 36! / I H*/, + CHR( 37] / 1 Ho/, CHR( 38] / 1 H r / , CHR( 39! / 1 HA/, CHR( 40 1 /1 H6/, + CHR( 41 : / 1 HA/, CHR( 42 1 / 1 H E / , CHR( 43 / 1 H n / , CHR( 44 / 1 HI/, + CHR( 45 1 / 1 HT/, CHR( 46 / 1 H#/, CHR( 47 / 1 H*/, CHR( 48 1/1 HQ/, + CHR( 49 1/1 H /, CHR( 50 >/1 H /, CHR( 51 /1 H /, CHR( 52 1/1 H /, + CHR( 53 >7i H /, CHR( 54 )/' H /, CHR( 55 >/' H /, CHR( 56 1/1 H /, + CHR( 57 )/ H /, CHR( 58 )/• H /, CHR( 59 )/ H /, CHR( 60 >/l H /, + CHR( 61 )/ H /, CHR( 62 )/ H /, CHR( 63 )/ H /, CHR( 64 1/1 H /, + CHR( 65 )/ H /, CHR( 66 )/ Hb/, CHR( 67 )/ UL/, CHR( 68 ) / l H0/, + CHR( 69 )/ HB/, CHR( 70 )/ HU/, CHR( 71 )/ H£/r CHR( 72 )/ HCE/, + CHR( 73 )/ H®/, CHR( 74 )/ H-/, CHR( 75 )/ HC/, CHR( 76 )/ H./ DATA + CHR( 77 )/ H</, CHR( 78 )/ H(/, CHR( 79 )/ H+/, CHR( 80 )/ H|/, + CHR( 81 )/ IH&/, CHR( 82 )/ IH,/, CHR( 83 )/ IH 2/, CHR( 84 )/ H 3/, + CHR( 85 )/ IH/,/, CHR( 86 )/ IH 5/, CHR( 87 )/ H 6/, CHR( 88 )/ H 7/, H$/, + CHR( 89 )/ IH 8/, CHR( 90 )/ 1H 9/, IH)/, CHR( 91 )/ IH!/, CHR( 92 )/ + CHR( 93 )/ IH*/, CHR( 94 )/ CHR( 95 )/ IH;/, CHR( 96 )/ IHV, + CHR( 97 )/ I H - / , CHR( 98 )/ IH//, CHR( 99 )/ 1HJ/, CHR( 100 )/ IH0/, + CHR( 101 )/ iHd/, CHR( 1 02 )/ IHb/, CHR( 103 )/ IHac/, CHR( 1 04 )/ lHos/, + CHR( 105 )/ IHi/, CHR( 106 )/ IH"/, CHR( 107 )/ IH!/, CHR( 108 )/ IH,/, + CHR( 109 )/ 1H%/, CHR( 1 10 )/ IH /, CHR( 1 1 1 )/ 1H>/, CHR( 1 12 )/ IH?/, + CHR( 1 13 >/ IH'/, CHR( 1 1 4 )/ I H V , CHR( 1 15 )/ IH"/, CHR( 1 16 )/ IH~/, + CHR( 1 17 )/ IH'/, CHR( 118 )/ IH ' /, CHR( 119 )/ IH,/, CHR( 120 )/ IHV, + CHR( 121 >/ IH"/, CHR( 1 22 )/ IH V , CHR( 123 )/ IH:/, CHR( 124 )/ 1H#/, + CHR( 125 )/ 1H@/, CHR( 1 26 )/ IH'/, CHR< 127 )/ IH-/, CHR( 128 )/ IH"/, Appendix C : LISTING OF THE RUN-TIME LIBRARY 61 + CHR( 129) /1 H 0/, CHR( 1 30) /I Ha/, CHR( 131) /1 Hb/, CHR( 132) /1 He/, + CHR( 133) /1 Hd/, CHR( 134) /1 He/, CHR( 135) / I H f / , CHR( 136) / I Hg/, + CHR( 137) /1 Hh/, CHR( 138) / I H i / , CHR( 139) / I H V , CHR( 140) /1 H{/, + CHR( 141 ) /1 H</, CHR( 1 42) / I H V , CHR( 143) / I H V , CHR( 144) / I H + / f + CHR( 1 45) /1 H /, CHR( 146) /I H j /, CHR( 147) /1 Hk/, CHR( 148) /I H I / , + CHR( 1 49) /I Hm/, CHR( 150) /I Hn/, CHR( 151 ] /I H o / , CHR( 1 52) /1 Hp/ DATA + CHR( 1 53) /I Hq/, CHR( 1 54] /I Hr/, CHR( 1 55] /I H*/, CHR( 156] /I H}/, + CHR( 157) /1 Ha/, CHR( 1 58] /1 H V , CHR( 1591 /1 H±/, CHR( 160] /1 H"/, + CHR( 161 ] / 1 H"/, CHR( 1 62] / 1 H 0/, CHR( 1 63] / 1 Hs/, CHR( 164] / I Ht/, + CHR( 1651 / 1 Hu/, CHR( 1 66 1 / 1 Hv/, CHR( 167; / I Hw/, CHR( 168] / 1 Hx/, + CHR( 169] /1 Hy/, CHR( 1 70 1 1/1 Hz/, CHR( 171 1/1 Ho/, CHR( 172] / 1 H L/, + CHR( 173] / 1 H r / , H V , CHR( 1 74 1/1 H[/, CHR( 175 >/l H>/, CHR( 1 76 1 / 1 H«/, H V , H V , + CHR( 1 77 >/1 CHR( 1 78 1/1 H V , CHR( 1 79 1/1 H 2/, CHR( 180 / 1 + CHR( 181 )/ Hfl/, CHR( 182 >/ H V , H 9/, CHR( 183 )/ H 6/, CHR( 184 1/1 + CHR( 185 >/ H 8/, CHR( 1 86 >/ CHR( 187 )/ H V , CHR( 188 >/ H V , + CHR( 189 ) / H - , / , CHR( 190 )/ H ] / , CHR( 191 )/ H V , CHR( 192 >/ H-/, + CHR( 1 93 )/ H /, CHR( 1 94 ) / HA/, CHR( 195 )/ HB/, CHR( 196 >/ HC/, + CHR( 1 97 )/ HD/, CHR( 1 98 ) / HE/, CHR( 199 ) / HF/, CHR( 200 >/ HG/, + CHR( 201 )/ HH/, CHR( 202 ) / HI/, CHR( 203 ) / H V , CHR( 204 >/ H V , + CHR( 205 ) / H,/, CHR( 206 ) / H,/, CHR( 207 )/ H V , CHR( 208 )/ H V , + CHR< 209 )/ H /, CHR( 210 ) / HJ/, CHR( 21 1 ) / HK/, CHR( 212 >/ HL/, + CHR( 213 ) / HM/, CHR( 214 )/ HN/, CHR( 215 )/ HO/, CHR( 216 )/ HP/, + CHR< 217 )/ 1HQ/, CHR( 218 )/ HR/, CHR( 219 )/ IH©/, CHR( 220 )/ H£/, + CHR< 221 >/ IH*/, CHR( 222 )/ Hr/, CHR( 223 )/ IH./, CHR( 224 )/ H ./, + CHR< 225 )/ 1H\/, CHR( 226 )/ IH /, CHR( 227 )/ IHS/, CHR( 228 )/ HT/ DATA + CHR 229 )/ 1HU/, CHR< 230 )/ 1HV/, CHR< 231 )/ 1HW/, CHR< 232 )/ IHX/, + CHR 233 )/ 1 HY/, CHR 234 )/ 1 HZ/, CHR( 235 )/ IH./, CHR< 236 )'/ IH_/, + CHR [237 >/ IHf/, CHR 238 )/ IH V , CHR< 239 )/ IH V , CHR< 240 )/ IH*/, + CHR [241 >/ 1H0/, CHR ,242 )/ 1H1/, CHR 243 )/ 1H2/, CHR ,244 )/ 1H3/, + CHR [245 >/ 1H4/, CHR [246 )/ 1H5/, CHR 247 )/ 1H6/, CHR [248 )/ 1H7/, + CHR [249 )/ 1H8/, CHR [250 )/ 1H9/, CHR ,251 )/ IH"/, CHR [252 )/ 1 H V , + CHR [253 >/ 1H /, CHR [254 )/ IH /, CHR [255 )/ 1H /, CHR [256 )/ IH / c DATA + ORDSPC/64/, ORDPLS/78/, ORDMNS/96/, ORD0/240/, ORD9/249/, + MXDV10/214748364/, MXMD10/7/ END C c =========================================================== c SUBROUTINE UPKCWD (PWORD, UWORD) C C Machine I n t e r f a c e Routine C Unpack a s i n g l e word of chars C Input Parameter: C PWORD - an INTEGER v a r i a b l e , c o n t a i n i n g CHARSPERINT C chars packed i n H o l l e r i t h format C Output Parameter: C UWORD - an ar r a y of CHARSPERINT INTEGERS, c o n t a i n i n g C the ORD values of these chars Appendix C : LISTING OF THE RUN-TIME LIBRARY 62 C C V e r s i o n here f o r : C CHARSPERINT=4, 32-bit word, 2's complement a r i t h m e t i c , C chars packed i n word from high-order to low-order end C e.g. IBM 4341, IBM 370, Amdahl 470 C INTEGER PWORD, UWORD(4), MAXINT, CHRCNT, UWDPOS LOGICAL NEGATV DATA MAXINT/2147483647/ C NEGATV = (PWORD .LT. 0) IF (NEGATV) PWORD = (PWORD + MAXINT) + 1 DO 1 CHRCNT = 1 , 4 UWDPOS = 5 - CHRCNT UWORD(UWDPOS) = MOD(PWORD, 256) 1 PWORD = PWORD / 256 IF (NEGATV) UWORD(I) = UWORD(l) + 128 RETURN END C c ================================================== c SUBROUTINE PKSWD (UWORD, PWORD) C C Machine I n t e r f a c e Routine C Pack i n d i v i d u a l b i t s i n t o a s i n g l e word C Input Parameter: C UWORD - an arr a y of WORDLENGTH INTEGERS, C c o n t a i n i n g i n d i v i d u a l b i t valu e s C Output Parameter: C PWORD - a s i n g l e INTEGER v a r i a b l e , C c o n t a i n i n g the packed b i t s of UWORD C C V e r s i o n here f o r : C 32-bit word, 2's complement a r i t h m e t i c C e.g. IBM 4341, IBM 370, Amdahl 470 C INTEGER UWORD(32), PWORD, MAXINT, UPOS DATA MAXINT/2147483647/ C PWORD = 0 DO 1 UPOS = 2, 32 1 PWORD = 2 * PWORD + UWORD(UPOS) IF (UWORDO) .EQ. 1) PWORD = (PWORD - MAXINT) - 1 RETURN END C C ================================================== c SUBROUTINE UPKSWD (PWORD, UWORD) C C Machine I n t e r f a c e Routine Appendix C : LISTING OF THE RUN-TIME LIBRARY 63 C Unpack a word i n t o i n d i v i d u a l b i t s C Input Parameter: C PWORD - an INTEGER v a r i a b l e C Output Parameter: C UWORD - an arr a y of WORDLENGTH INTEGERS, C c o n t a i n i n g the i n d i v i d u a l b i t s of PWORD C C V e r s i o n here f o r : C 32-bit word, 2's complement•arithmetic C e.g. IBM 4341, IBM 370, Amdahl 470 C INTEGER PWORD, UWORD(32), MAXINT, BITCNT, UPOS DATA MAXINT/2147483647/ C IF (PWORD .GE. 0) GOTO 1 UWORDO) = 1 PWORD = (PWORD + MAXINT) + 1 GOTO 2 1 CONTINUE UWORD(1) = 0 2 DO 3 BITCNT = 2, 32 UPOS = 34 " BITCNT UWORD(UPOS) = MOD(PWORD, 2) 3 PWORD = PWORD / 2 RETURN END C C ===============================================: c SUBROUTINE OPENRD (FILNUM) C C Operating System I n t e r f a c e Routine C Open a f i l e f o r reading, by p o s i t i o n i n g to i t s C Input Parameter: C FILNUM - the INTEGER l o g i c a l u n i t number of C C V e r s i o n here f o r : C MTS on Amdahl 470 V8 at UBC, with FORTRAN H C INTEGER FILNUM C REWIND FILNUM RETURN END C C =============================================== C SUBROUTINE OPENWR (FILNUM) C C Operating System I n t e r f a c e Routine C Open a f i l e f o r w r i t i n g , by emptying i t C Input Parameter: s t a r t the f i l e compiler Appendix C : LISTING OF THE RUN-TIME LIBRARY 64 C FILNUM - the INTEGER l o g i c a l u n i t number of the f i l e C C V e r s i o n here f o r : C MTS on Amdahl 470 V8 at UBC, with FORTRAN H compiler C EMPTYS i s an MTS System Subroutine that empties a f i l e C INTEGER FILNUM C CALL EMPTYS(FILNUM) RETURN END C C SUBROUTINE GETLN (FILNUM, ENDFIL, LNLEN, LN) C C Operating System I n t e r f a c e Routine C Attempt to read a l i n e of chars C Input Parameter: C FILNUM - the INTEGER l o g i c a l u n i t no of the input f i l e C Output Parameters: C ENDFIL - an INTEGER v a r i a b l e ; i f a l i n e was obtained, C set to 0 (= F ) , otherwise set to 1 (= T) C LNLEN - an INTEGER v a r i a b l e ; i f a l i n e was obtained, C set to the number of chars on the l i n e C LN - an a r r a y of MAXLINELEN INTEGERS; i f a l i n e C was obtained and had at most MAXLINELEN chars, C s t o r e s the ORD value s of these chars C C V e r s i o n here f o r : C MTS on Amdahl 470 V8 at UBC, with FORTRAN H compiler C READ i s an MTS System Subroutine that reads a s i n g l e l i n e C INTEGER FILNUM, ENDFIL, LNLEN, LN(254) INTEGER PKDLN(64), RDMOD, F, T, LINNUM, INTLEN INTEGER*2 CHRLEN(3) DATA RDMOD/Z08004000/, F/0/, T/1/ C CHRLEN(2) = 256 CALL READ(PKDLN, CHRLEN, RDMOD, LINNUM, FILNUM, &1) ENDFIL = F LNLEN = CHRLEN(1) IF (LNLEN .GT. 254) GOTO 2 INTLEN = (LNLEN + 3) / 4 CALL UNPKSR(PKDLN, INTLEN, LNLEN, LN) GOTO 2 1 CONTINUE ENDFIL = T 2 RETURN END Appendix C : LISTING OF THE RUN-TIME LIBRARY 65 C SUBROUTINE WRNULN (FILNUM) C C Operating System I n t e r f a c e Routine C Output a n u l l (empty) l i n e C Input Parameter: C FILNUM - the INTEGER l o g i c a l u n i t no of the output f i l e C C V e r s i o n here f o r : C MTS on Amdahl 470 V8 at UBC, with FORTRAN H compiler C INTEGER FILNUM C WRITE(FILNUM,1) RETURN 1 FORMAT( ) END C C ============================================================== C SUBROUTINE UNPKSR (PSTR, INTLEN, CHRLEN, USTR) C C Unpack a s t r i n g of chars C Input Parameters: C PSTR - an arr a y of INTEGERS, c o n t a i n s a H o l l e r i t h s t r i n g C INTLEN - the no of e l t s (INTEGERS) i n PSTR C CHRLEN - the no of chars packed i n PSTR ( l e f t - j u s t i f i e d ) C Output Parameter: C USTR - an arr a y of CHRLEN INTEGERS, c o n t a i n s C the ORD values of these chars C INTEGER INTLEN, CHRLEN, PSTR(INTLEN), USTR(CHRLEN) INTEGER PPOS, UPOS, PWORD, UWORD'(4), UWDPOS C PPOS = 0 DO 1 UPOS = 1, CHRLEN UWDPOS = MOD(UPOS-1, 4) + 1 IF (UWDPOS .NE. 1) GOTO 1 PPOS = PPOS + 1 PWORD = PSTR(PPOS) CALL UPKCWD(PWORD, UWORD) 1 USTR(UPOS) = UWORD(UWDPOS) RETURN END C C ============================================================== c SUBROUTINE UPTOP (INCREM) C C Increment STACK p o i n t e r TOP by INCREM, checking f o r overflow C INTEGER INCREM Appendix C : LISTING OF THE RUN-TIME LIBRARY 66 INTEGER STACK(5000), TOP COMMON STACK, TOP C TOP = TOP + INCREM IF (TOP .GT. 5000) CALL RUNERR(1) RETURN END C C ==================================================== C SUBROUTINE MKLINK C C Make space on top of STACK f o r r o u t i n e l i n k a g e i n f o C INTEGER STACK(5000), TOP, BASE(30), SAVESZ, LINKSZ COMMON STACK, TOP, BASE, SAVESZ, LINKSZ C CALL UPTOP(LINKSZ) RETURN END C C ==================================================== c SUBROUTINE LDVALU (VALU) C C Load onto STACK the value VALU C INTEGER VALU INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL UPTOP(1) STACK(TOP) = VALU RETURN END C C ==================================================== C SUBROUTINE LDADDR (DECLEV, OFFSET.) C C Load onto STACK the address BASE(DECLEV) + OFFSET C INTEGER DECLEV, OFFSET INTEGER STACK(5000), TOP, BASE(30) COMMON STACK, TOP, BASE C CALL UPTOP(1) STACK(TOP) = BASE(DECLEV) + OFFSET RETURN END C C ==================================================== Appendix C : LISTING OF THE RUN-TIME LIBRARY 67 C SUBROUTINE LDSIMP C C Load onto STACK the simple value at C address STACK(TOP), popping t h i s address C INTEGER ADDR INTEGER STACK(5000), TOP COMMON STACK, TOP C ADDR = STACK(TOP) STACK(TOP) = STACK(ADDR) RETURN END C C ========================================================= C SUBROUTINE LDSRUC (LENGTH) C C Load onto STACK the s t r u c t u r e d value of le n g t h LENGTH, C which s t a r t s at address STACK(TOP), popping t h i s address C INTEGER LENGTH, SRCADR, DSTADR INTEGER STACK(5000), TOP COMMON STACK, TOP C SRCADR = STACK(TOP) DSTADR = TOP CALL UPTOP(LENGTH-1) CALL COPY(LENGTH, SRCADR, DSTADR) RETURN END C C ========================================================= C SUBROUTINE LDSTR (INTLEN, CHRLEN, PSTR) C C Load onto STACK an unpacked copy of the s t r i n g PSTR C PSTR i s an ar r a y of INTLEN INTEGERS, c o n t a i n i n g a C l e f t - j u s t i f i e d H o l l e r i t h s t r i n g of CHRLEN chars C INTEGER INTLEN, CHRLEN, PSTR(INTLEN), STRADR INTEGER STACK(5000), TOP COMMON STACK, TOP C STRADR = TOP + 1 CALL UPTOP(CHRLEN) CALL UNPKSR(PSTR, INTLEN, CHRLEN, STACK(STRADR)) RETURN END C Appendix C : LISTING OF THE RUN-TIME LIBRARY 68 C SUBROUTINE LDKYCH (LENGTH) C C Load onto STACK the key c h a r a c t e r s f o r comparison of s t r i n g s C On entry, there are two char s t r i n g s each of l e n g t h LENGTH C on top of STACK C On e x i t , the s t r i n g s have been popped; on top of STACK are C a p a i r of chars (ORD values) from the r e s p e c t i v e s t r i n g s ; C e i t h e r the f i r s t p a i r of unequal chars from corresponding C s t r i n g p o s i t i o n s , or the f i n a l char i n each s t r i n g C INTEGER LENGTH, BEGPOS, POS, SR1POS, SR2P0S INTEGER STACK(5000), TOP COMMON STACK, TOP C BEGPOS = TOP - 2*LENGTH + 1 POS = 1 SR1POS = BEGPOS SR2POS = BEGPOS + LENGTH 1 IF (POS.EQ.LENGTH .OR. STACK(SR1POS).NE.STACK(SR2POS)) GOTO 2 POS = POS +1 SRIPOS = SR1POS + 1 SR2POS = SR2POS + 1 GOTO 1 C 2 STACK(BEGPOS) = STACK(SR1POS) STACK(BEGPOS+1) = STACK(SR2POS) TOP = BEGPOS + 1 RETURN END C C ============================================================== C SUBROUTINE STSIMP C C Store the simple value which i s on the top of STACK C i n the l o c a t i o n whose address i s s t o r e d j u s t below i t , C and then pop both the value and the address C INTEGER ADDR INTEGER STACK(5000), TOP COMMON STACK, TOP C ADDR = STACK(TOP-1) STACK(ADDR) = STACK(TOP) TOP = TOP - 2 RETURN END C C ============================================================== c SUBROUTINE STSRUC (LENGTH) Appendix C : LISTING OF THE RUN-TIME LIBRARY 69 C Store the s t r u c t u r e d value of l e n g t h LENGTH which i s on the C top of STACK i n the region whose s t a r t i n g address i s s t o r e d C j u s t below i t , and then pop both the value and the address C INTEGER LENGTH, ADRPOS INTEGER STACK(5000), TOP COMMON STACK, TOP C ADRPOS = TOP - LENGTH CALL COPY(LENGTH, ADRPOS +1 , STACK(ADRPOS)) TOP = ADRPOS - 1 RETURN END C c ============================================================ c SUBROUTINE COPY (LENGTH, SRCADR, DSTADR) C C Copy LENGTH e n t r i e s from address SRCADR to address DSTADR C INTEGER LENGTH, SRCADR, DSTADR, POS, SRCPOS, DSTPOS INTEGER STACK(5000) COMMON STACK C DO 1 POS = 1, LENGTH SRCPOS = SRCADR - 1 + POS DSTPOS = DSTADR - 1 + POS 1 STACK(DSTPOS) = STACK(SRCPOS) RETURN END C c ============================================================ c SUBROUTINE RECBAS (LEVEL) C C Swap the contents of BASE(LEVEL) and STACK(TOP) C INTEGER LEVEL, OLDBSL INTEGER STACK(5000), TOP, BASE(30) COMMON STACK, TOP, BASE C OLDBSL BASE(LEVEL) STACK(TOP) RETURN END C C ============ c SUBROUTINE RSTBAS (LEVEL) = BASE(LEVEL) = STACK(TOP) = OLDBSL Appendix C : LISTING OF THE RUN-TIME LIBRARY 70 C Restore BASE(LEVEL) from STACK(TOP); pop STACK C INTEGER LEVEL INTEGER STACK(5000), TOP, BASE(30) COMMON STACK, TOP, BASE C BASE(LEVEL) = STACK(TOP) TOP = TOP " 1 RETURN END C C ============================================================= c SUBROUTINE ARRCMP (MINORD, COMPSZ) C C Compute the address of an ar r a y component, from C STACK(TOP-I) : address of s t a r t of arr a y C STACK(TOP) : value of index e x p r e s s i o n C MINORD : index of f i r s t a r r a y component C COMPSZ : s i z e of each a r r a y component C Pop STACK, and s t o r e the r e s u l t i n (new) STACK(TOP) C INTEGER MINORD, COMPSZ INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP-1) = STACK(TOP-1) + (STACK(TOP) - MINORD) * COMPSZ TOP =. TOP - 1 RETURN END C c ============================================================= c SUBROUTINE RECFLD (FLDOFS) C C Compute the address of a re c o r d f i e l d , from C STACK(TOP) : address of s t a r t of reco r d C FLDOFS : f i e l d o f f s e t w i t h i n r e c o r d C Store the r e s u l t i n STACK(TOP) C INTEGER FLDOFS INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP) = STACK(TOP) + FLDOFS RETURN END C C ============================================================= c SUBROUTINE ADD C Appendix C : LISTING OF THE RUN-TIME LIBRARY 71 C Store (STACK(TOP-1) + STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP-1) = STACK(TOP-1) + STACK(TOP) TOP = TOP - 1 RETURN END C C ============================================================== c SUBROUTINE SUB C C Store (STACK(TOP-1) - STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP-1) = STACK(TOP-1) - STACK(TOP) TOP = TOP - 1 RETURN END C c ============================================================== c SUBROUTINE MUL C C Store (STACK(TOP-1) * STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP-1) = STACK(TOP-1) * STACK(TOP) TOP = TOP - 1 RETURN END C C ============================================================== C SUBROUTINE DIV C C Store (STACK(TOP-1) d i v STACK(TOP))in STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C IF (STACK(TOP) .EQ. 0) CALL RUNERR(10) STACK(TOP-1) = STACK(TOP-1) / STACK(TOP) TOP = TOP - 1 RETURN END Appendix C : LISTING OF THE RUN-TIME LIBRARY 72 C C ============================================================== C SUBROUTINE MOD C C Store (STACK(TOP-1) mod STACK(TOP))in STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C IF (STACK(TOP) .LE. 0) CALL RUNERR(11) STACK(TOP-1) = MOD(STACK(TOP-1), STACK(TOP)) IF (STACK(TOP-1).LT.O) STACK(TOP -1) = STACK(TOP-1)+STACK(TOP) TOP = TOP " 1 RETURN END C c ============================================================== c SUBROUTINE NOT C C Store (not STACK(TOP)) i n STACK(TOP) C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP) = 1 - STACK(TOP) RETURN END C C ============================================================== C SUBROUTINE AND C C Store (STACK(TOP-1) and STACK(TOP))in STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP-1) = STACK(TOP-1) * STACK(TOP) TOP = TOP - 1 RETURN END C C ============================================================== c SUBROUTINE OR C C Store (STACK(TOP-1) or STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP Appendix C : LISTING OF THE RUN-TIME LIBRARY 73 COMMON STACK, TOP C STACK(TOP-1) = MINO(STACK(TOP-1) + STACK(TOP), 1) TOP = TOP - 1 RETURN END C C =========================================================== c SUBROUTINE UNION C C Replace the top two se t s on STACK by t h e i r union C INTEGER USET1(256), USET2(256), RESULT(256), ELTPOS C CALL UPKSET(USET2) CALL UPKSET(USET1) DO 1 ELTPOS = 1, 256 1 RESULT(ELTPOS) = MINO(USET1(ELTPOS) + USET2(ELTPOS), 1) CALL PKSET(RESULT) RETURN END C c =========================================================== C SUBROUTINE INTER C C Replace the top two set s on STACK by t h e i r i n t e r s e c t i o n C INTEGER USET1(256), USET2(256), RESULT(256), ELTPOS C CALL UPKSET(USET2) CALL UPKSET(USET1 ) DO 1 ELTPOS = 1, 256 1 RESULT(ELTPOS) = USET1(ELTPOS) * USET2(ELTPOS) CALL PKSET(RESULT) RETURN END C C =========================================================== c SUBROUTINE DIFF C C Replace the top two set s on STACK by t h e i r d i f f e r e n c e C (next-to-top set) - (top set) C INTEGER USET1(256), USET2(256), RESULT(256), ELTPOS C CALL UPKSET(USET2) CALL UPKSET(USET1) DO 1 ELTPOS = 1, 256 1 RESULT(ELTPOS) = MAXO(USET1(ELTPOS) - USET2(ELTPOS), 0) Appendix C : LISTING OF THE RUN-TIME LIBRARY 74 CALL PKSET(RESULT) RETURN END C c ====================================================== c SUBROUTINE IN C C Determine i f the set on top of STACK c o n t a i n s the C element s t o r e d j u s t below i t ; pop set and element C INTEGER E L T , RESULT, WDPOS, BITPOS, UWORD(32) INTEGER S T A C K ( 5 0 0 0 ) , TOP COMMON STACK, TOP C E L T = STACK(TOP-8 ) I F ( E L T .GE. 0 .AND. E L T .LE . 255) GOTO 1 RESULT = 0 GOTO 2 1 CONTINUE WDPOS = TOP - 8 + CELT / 32) + 1 CALL UPKSWD(STACK(WDPOS), UWORD) BITPOS = MOD(ELT, 32) + 1 RESULT = UWORD(BITPOS) 2 TOP = TOP - 8 STACK(TOP) = RESULT RETURN END C C ===================================================== C SUBROUTINE MKSET (ELTCNT) C C Replace the top ELTCNT STACK e n t r i e s , C each 0 or 1, by the corresponding set C INTEGER ELTCNT, U S E T ( 2 5 6 ) , UPOS, BEGPOS, STKPOS, E L T INTEGER S T A C K ( 5 0 0 0 ) , TOP COMMON STACK, TOP C DO 1 UPOS = 1, 256 1 USET(UPOS) = 0 I F (ELTCNT .EQ. 0) GOTO 3 BEGPOS = TOP - ELTCNT + 1 DO 2 STKPOS = BEGPOS, TOP EL T = STACK(STKPOS) 2 U S E T ( E L T+ 1 ) = 1 TOP = TOP - ELTCNT C 3 CALL PKSET(USET) RETURN END Appendix C : LISTING OF THE RUN-TIME LIBRARY 75 C c ============================================================== c SUBROUTINE PKSET (USET) C C Pack the elements of USET, each 0 or 1, C i n t o a s e t , and load t h i s onto STACK C INTEGER USET(256), WORD, STKPOS INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL UPTOP(8) DO 1 WORD = 1 , 8 STKPOS = TOP - 8 + WORD 1 CALL PKSWD(USET(32*W0RD-31), STACK(STKPOS)) RETURN END C c ============================================================== c SUBROUTINE UPKSET (USET) C C Unpack the set on top of STACK i n t o USET, popping the set C INTEGER USET(256), WORD, STKPOS INTEGER STACK(5000), TOP COMMON STACK, TOP C DO 1 WORD = 1 , 8 STKPOS = TOP - 8 + WORD 1 CALL UPKSWD(STACK(STKPOS), USET(3 2 *WORD-31)) TOP = TOP - 8 RETURN END C C ============================================================= c SUBROUTINE EQ C C Store (STACK(TOP-1) = STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL MKRELN(STACK(TOP-1) .EQ. STACK(TOP)) RETURN END C c ============================================================= c SUBROUTINE NE Appendix C : LISTING OF THE RUN-TIME LIBRARY 76 C Store (STACK(TOP-1) <> STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL MKRELN(STACK(TOP-1) .NE. STACK(TOP)) RETURN END C C = = = = = = = = = = == = = = = = = = = === = = = = = = = = = = = = = === = = = = = = = = = = = = = = = = = = c SUBROUTINE LT C C Store (STACK(TOP-1 ) < STACK(TOP)) i n STACK(TOP-1 ) ; pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL MKRELN(STACK(TOP-1) .LT. STACK(TOP)) RETURN END C C ============================================================== C SUBROUTINE LE C C Store (STACK(TOP-1) <= STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL MKRELN(STACK(TOP-1) .LE. STACK(TOP)) RETURN END C c ============================================================== c SUBROUTINE GT C C Store (STACK(TOP-1) > STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL MKRELN(STACK(TOP-1) .GT. STACK(TOP)) RETURN END C C ============================================================== c SUBROUTINE GE Appendix C : LISTING OF THE RUN-TIME LIBRARY 77 C Store (STACK(TOP-1) >= STACK(TOP)) i n STACK(TOP-1); pop STACK C INTEGER STACK(5000), TOP COMMON STACK, TOP C CALL MKRELN(STACK(TOP-1) .GE. STACK(TOP)) RETURN END C C = = = = == = = = === = = = = = = = = = = = = === = = = = == = = = = = = = = = = = = = = = = = = = = = C SUBROUTINE MKRELN (RELN) C C Pop STACK, and st o r e ORD(RELN) i n (new) STACK(TOP) C LOGICAL RELN INTEGER STACK(5000), TOP COMMON STACK, TOP C TOP = TOP " 1 IF (RELN) GOTO 1 STACK(TOP) = 0 GOTO 2 1 CONTINUE STACK(TOP) = 1 2 RETURN END C C ============================================================== C SUBROUTINE PRED C C Store STACK(TOP)-1 i n STACK(TOP) C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP) = STACK(TOP) - 1 RETURN END C C ============================================================== C SUBROUTINE SUCC C C Store STACK(TOP)+1 i n STACK(TOP) C INTEGER STACK(5000), TOP COMMON STACK, TOP C STACK(TOP) = STACK(TOP) + 1 Appendix C : LISTING OF THE RUN-TIME LIBRARY 78 C RETURN END SUBROUTINE EOF (FILNUM) C C Load onto STACK the value of EOF(FILNUM) C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C IF (FILSTS(FILNUM) .EQ. U) CALL RUNERR(12) CALL LDVALU(ENDFIL(FILNUM)) RETURN END SUBROUTINE EOLN (FILNUM) C C Load onto STACK the value of EOLN(FILNUM) C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C IF (FILSTS(FILNUM) .EQ. U) CALL RUNERR(12) IF (ENDFIL(FILNUM) .EQ. T) CALL RUNERR(12) CALL LDVALU(ENDLIN(FILNUM)) RETURN END LOGICAL FUNCTION FALSE (NOPARM) C C Return STACK(TOP) .EQ. 0; pop STACK C INTEGER NOPARM INTEGER STACK(5000), TOP COMMON STACK, TOP C FALSE = (STACK(TOP) .EQ. 0) TOP = TOP - 1 Appendix C : LISTING OF THE RUN-TIME LIBRARY 79 RETURN END C C c c c c c c c c c c c c c c c c c c c SUBROUTINE UNLOAD (VALUE) Store the value of STACK(TOP) i n VALUE; pop STACK INTEGER VALUE INTEGER STACK(5000), TOP COMMON STACK, TOP VALUE = STACK(TOP) TOP = TOP - 1 RETURN END SUBROUTINE PREFOR (STEP, DECLEV, OFFSET, NOLOOP) Prepare to execute a FOR loop On e n t r y , STACK(TOP-I) and STACK(TOP) c o n t a i n the FOR loop's e v a l u a t e d " i n i t i a l - v a l u e " and " f i n a l - v a l u e " , r e s p e c t i v e l y . If the range between these two values i s empty, then set NOLOOP to .TRUE. pop these top two values e l s e set NOLOOP to .FALSE. set the c o n t r o l v a r i a b l e to " i n i t i a l - v a l u e " , l e a v i n g i t s address i n STACK(TOP) INTEGER STEP, DECLEV, OFFSET, INLVAL, FNLVAL, ADDR LOGICAL NOLOOP INTEGER STACK(5000), TOP COMMON STACK, TOP INLVAL FNLVAL NOLOOP IF STACK(TOP-1) STACK(TOP) (STEP .EQ. +1 (STEP .EQ. -1 .AND, .AND. INLVAL .GT. FNLVAL) .OR. INLVAL .LT. FNLVAL) (NOLOOP) GOTO 1 CALL LDADDR(DECLEV, OFFSET) ADDR = STACK(TOP) STACK(ADDR) = INLVAL GOTO 2 CONTINUE TOP = TOP - 2 RETURN END Appendix C : LISTING OF THE RUN-TIME LIBRARY 80 C C = = = == = = = = = = = = = = = = === === = = = = = = = = = = = = === = = = = = c SUBROUTINE TESTEP (MORE, STEP) C C Test / Step the c o n t r o l v a r i a b l e of a FOR loop C On ent r y , STACK(TOP-2), STACK(TOP-I) and STACK(TOP) C c o n t a i n the FOR loop's " i n i t i a l - v a l u e " , " f i n a l - v a l u e " , C and c o n t r o l v a r i a b l e ' s address, r e s p e c t i v e l y . C I f the c o n t r o l v a r i a b l e ' s value equals " f i n a l - v a l u e " , then C set MORE to .FALSE. C pop the address, " f i n a l - v a l u e " and " i n i t i a l - v a l u e " C e l s e C set MORE to .TRUE. C a l t e r the c o n t r o l v a r i a b l e ' s value by STEP C LOGICAL MORE INTEGER STEP, ADDR INTEGER STACK(5000), TOP COMMON STACK, TOP C ADDR = STACK(TOP) MORE = (STACK(ADDR) .NE. STACK(TOP-1)) C IF (MORE) GOTO 1 TOP = TOP - 3 GOTO 2 1 CONTINUE STACK(ADDR) = STACK(ADDR) + STEP 2 RETURN END C C ============================================================== C SUBROUTINE SETFLS C C I n i t i a l i z e FILSTS to U and WINDOW to ORDSPC f o r each f i l e C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORD0, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORD0,ORD9,MXDV10,MXMD10 C DO 1 FILNUM = 1 , 6 FILSTS(FILNUM) = U 1 WINDOW(FILNUM) = ORDSPC RETURN END C Appendix C : LISTING OF THE RUN-TIME LIBRARY 81 C SUBROUTINE CLSFLS C C Issue a c l o s i n g WRITELN, where needed, f o r each output f i l e C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDP0SN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDS PC,ORDPLS,ORDMNS,ORD 0,ORD 9,MXDV10,MXMD10 C DO 1 FILNUM = 1 , 6 1 CALL CLSFIL(FILNUM) RETURN END C C = = = = = = = = = = ==== = = = = = = = = = = = = = = = = = = == = = = = = = = = = = = = = == = = = c SUBROUTINE CLSFIL (FILNUM) C C Issue a c l o s i n g WRITELN, i f needed, f o r output f i l e FILNUM C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C IF (FILSTS(FILNUM) .NE. W) GOTO 1 IF (LINLEN(FILNUM) .GT. 0) CALL WRLN(FILNUM) 1 RETURN END C C ============================================================== c SUBROUTINE RESET (FILNUM) C C Implements the P a s c a l procedure RESET C Prepare f i l e FILNUM f o r reading by p o s i t i o n i n g to i t s s t a r t C and p l a c i n g i t s f i r s t component to the b u f f e r WINDOW(FILNUM) C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C CALL CLSFIL(FILNUM) CALL OPENRD(FILNUM) Appendix C : LISTING OF THE RUN-TIME LIBRARY 82 FILSTS(FILNUM) = R ENDFIL(FILNUM) = F ENDLIN(FILNUM) = T CALL GET(FILNUM) RETURN END C C = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = == = = = C SUBROUTINE GET (FILNUM) C C Implements the P a s c a l procedure GET C Advance t o next component of f i l e FILNUM; p l a c e i t i n b u f f e r C WINDOW(FILNUM); a l s o set ENDFIL(FILNUM) and ENDLIN(FILNUM) C INTEGER FILNUM, INDEX INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 IF (FILSTS(FILNUM) .NE. R) CALL RUNERR(2) IF (ENDFIL(FILNUM) • EQ. T) CALL RUNERR(3) IF (ENDLIN(FILNUM) • EQ. F) GOTO 1 CALL GETLN(FILNUM, ENDFIL(FILNUM), + .LINLEN(FILNUM), LINE(1,FILNUM)) IF (ENDFIL (FILNUM) '.EQ. T) GOTO 3 IF (LINLEN(FILNUM) .GT. 254) CALL RUNERR(4) RDPOSN(FILNUM) = 0 1 IF (RDPOSN(FILNUM) .LT. LINLEN(FILNUM)) GOTO 2 ENDLIN(FILNUM) = T WINDOW(FILNUM) = ORDSPC GOTO 3 2 CONTINUE ENDLIN(FILNUM) = F RDPOSN(FILNUM) = RDPOSN(FILNUM) + 1 INDEX = RDPOSN(FILNUM) WINDOW(FILNUM) = LINE(INDEX, FILNUM) 3 RETURN END C C ================================================== C SUBROUTINE RDCH (FILNUM) C C Read from f i l e FILNUM a char, and st o r e C i t s ORD value i n STACK(STACK(TOP)); pop STACK C INTEGER FILNUM, ADDR INTEGER STACK(5000), TOP Appendix C : LISTING OF THE RUN-TIME LIBRARY 83 INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON STACK, TOP COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WlNDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C ADDR = STACK(TOP) TOP = TOP - 1 STACK(ADDR) = WINDOW(FILNUM) CALL GET(FILNUM) RETURN END C c ====================================== c SUBROUTINE RDINT (FILNUM) C C Read from f i l e FILNUM an i n t e g e r , and s t o r e C i t s value i n STACK(STACK(TOP)); pop STACK C INTEGER FILNUM, INT, DGTVAL, ADDR LOGICAL NEGATV, ISDGT INTEGER STACK(5000), TOP INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON STACK, TOP COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WlNDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C IF (FILSTS(FILNUM) .NE. R) CALL RUNERR(2) C 1 IF (WINDOW(FILNUM) .NE. ORDSPC) GOTO 2 CALL GET(FILNUM) GOTO 1 2 NEGATV = (WINDOW(FILNUM) .EQ. ORDMNS) IF (NEGATV .OR. WlNDOW(FlLNUM).EQ.ORDPLS) CALL GET(FILNUM) CALL DGTEST(WlNDOW(FlLNUM), ISDGT, DGTVAL) IF (.NOT. ISDGT) CALL RUNERR(5) C INT = 0 3 CONTINUE IF (INT.GT.MXDV10 .OR. + INT.EQ.MXDV10 .AND. DGTVAL.GT.MXMD10) CALL RUNERR(6) INT = 10 * INT + DGTVAL CALL GET(FILNUM) CALL DGTEST(WlNDOW(FlLNUM), ISDGT, DGTVAL) IF (ISDGT) GOTO 3 IF (NEGATV) INT = -INT C ADDR = STACK(TOP) Appendix C : LISTING OF THE RUN-TIME LIBRARY 84 TOP = TOP - 1 STACK(ADDR) = INT RETURN END C C = = = = = === = = = = = = = = = = = = = == = = = = = = = = = = = == = == = = = = = = = = = = c SUBROUTINE DGTEST (TSTORD, ISDGT, DGTVAL) C C Test i f a given char r e p r e s e n t s a decimal d i g i t , C and i f so, r e t u r n the numeric value of the d i g i t C INTEGER TSTORD, DGTVAL LOGICAL ISDGT INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C ISDGT = (TSTORD.GE.ORDO .AND. TSTORD.LE.ORD9) IF (ISDGT) DGTVAL = TSTORD - ORDO RETURN END C C ============================================================== c SUBROUTINE RDLN (FILNUM) C C Implements the (single-parameter) P a s c a l procedure READLN C Skip to the s t a r t of the next l i n e , or EOF, on f i l e FILNUM C INTEGER FILNUM INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C ENDLIN(FILNUM) = T CALL GET(FILNUM) RETURN END C c ============================================================== c SUBROUTINE REWRIT (FILNUM) C C Implements the Pascal procedure REWRITE C D i s c a r d c u r r e n t value of f i l e FILNUM; prepare i t f o r w r i t i n g C INTEGER FILNUM Appendix C : LISTING OF THE RUN-TIME LIBRARY 85 INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FlLSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C CALL CLSFIL(FILNUM) CALL OPENWR(FILNUM) FILSTS(FILNUM) = W ENDFIL(FILNUM) = T LINLEN(FILNUM) = 0 RETURN END C C ===================================== c SUBROUTINE PUT (FILNUM) C C Implements the Pas c a l procedure PUT C Append the b u f f e r WINDOW(FILNUM) to f i l e FILNUM C INTEGER FILNUM, INDEX INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WlNDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C IF (FILSTS(FILNUM) .NE. W) CALL RUNERR(7) IF (LINLEN(FILNUM) .EQ. 254) CALL RUNERR(8) C LINLEN(FILNUM) = LINLEN(FILNUM) + 1 INDEX = LINLEN(FILNUM) LINE(INDEX, FILNUM) = WINDOW(FILNUM) RETURN END C C ============================================================== C SUBROUTINE WRCH (FILNUM) C C Write onto f i l e FILNUM the char (ORD value) i n STACK(TOP-1), C using the f i e l d - w i d t h i n STACK(TOP); pop the top two e n t r i e s C INTEGER FILNUM, ORDCH, WIDTH, SPACES, SPCCNT INTEGER STACK(5000), TOP INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON STACK, TOP COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WlNDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 Appendix C LISTING OF THE RUN-TIME LIBRARY 86 C WIDTH = STACK(TOP) ORDCH = STACK(TOP-1) TOP = TOP - 2 C IF (WIDTH .LE. 0) CALL RUNERR(9) IF (WIDTH .EQ. 1) GOTO 2 SPACES = WIDTH - 1 DO 1 SPCCNT = 1, SPACES WINDOW(FILNUM) = ORDSPC 1 CALL PUT(FILNUM) C 2 WINDOW(FILNUM) = ORDCH CALL PUT(FILNUM) RETURN END C C ================================================ c SUBROUTINE WRINT (FILNUM) C C Write onto f i l e FILNUM the i n t e g e r i n STACK(TOP-1), us i n g C the f i e l d - w i d t h i n STACK(TOP); pop the top two e n t r i e s C INTEGER FILNUM, INT, WIDTH, ABSINT, ABSLEN, INTLEN, + SPACES, SPCCNT, DGTCNT INTEGER STACK(5000), TOP INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON STACK, TOP COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C WIDTH = STACK(TOP) INT = STACK(TOP-1) TOP = TOP - 2 C IF (WIDTH .LE. 0) CALL RUNERR(9) ABSINT = IABS(INT) ABSLEN = 1 1 IF (ABSINT .LT. 10) GOTO 2 ABSLEN = ABSLEN + 1 ABSINT = ABSINT / 10 GOTO 1 C 2 IF (INT .GE. 0) INTLEN = ABSLEN IF (INT .LT. 0) INTLEN = ABSLEN + 1 IF (WIDTH .LE. INTLEN) GOTO 4 SPACES = WIDTH - INTLEN DO 3 SPCCNT = 1, SPACES WINDOW(FILNUM) = ORDSPC Appendix C : LISTING OF THE RUN-TIME LIBRARY 87 3 CALL PUT(FILNUM) C 4 IF (INT .GE. 0) GOTO 5 WINDOW(FILNUM) = ORDMNS CALL PUT(FILNUM) 5 ABSINT = IABS(INT) DO 6 DGTCNT = 1, ABSLEN WINDOW(FILNUM) = ORD0+MOD(ABSINT/(10**(ABSLEN-DGTCNT)),10) 6 CALL PUT(FILNUM) RETURN END C SUBROUTINE WRBOOL (FILNUM) C C Write onto f i l e FILNUM the Boolean i n STACK(TOP-1), using C the f i e l d - w i d t h in STACK(TOP); pop the top two e n t r i e s C INTEGER FILNUM, BOOL, WIDTH, STRLEN. INTEGER STACK(5000), TOP COMMON STACK, TOP C WIDTH = STACK(TOP) BOOL = STACK(TOP-1) TOP = TOP - 2 C IF (BOOL .EQ. 1) GOTO 1 CALL LDSTR(2, 5, 8HFALSE ) STRLEN = 5 GOTO 2 1 CONTINUE CALL LDSTR(1, 4, 4HTRUE) STRLEN = 4 2 CALL LDVALU(WIDTH) CALL WRSTR(STRLEN, FILNUM) RETURN END C INTEGER FUNCTION DFLTBW (NOPARM) C C Returns the d e f a u l t f i e l d - w i d t h f o r the Boolean i n STACK(TOP) C INTEGER NOPARM INTEGER STACK(5000), TOP COMMON STACK, TOP C •DFLTBW = 5 - STACK(TOP) RETURN END Appendix C : LISTING OF THE RUN-TIME LIBRARY 88 C C = = = = = = = = = = = = = == = = = = = = = = = = ====== = = = = = = = = = = === = = = C SUBROUTINE WRSTR (STRLEN, FILNUM) C C Write onto f i l e FILNUM the char s t r i n g of l e n g t h STRLEN, C s t o r e d i n STACK f i n i s h i n g at p o s i t i o n TOP-1, using the C f i e l d - w i d t h i n STACK(TOP); pop the s t r i n g and f i e l d - w i d t h C INTEGER STRLEN,FILNUM,WIDTH,SPACES,SPCCNT,LOPOS,HIPOS,STKPOS INTEGER STACK(5000), TOP INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON STACK, TOP COMMON/FILCOM/LINE,FILSTS,LlNLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C WIDTH = STACK(TOP) LOPOS = TOP - STRLEN C IF (WIDTH .LE. 0) CALL RUNERR(9) C IF (WIDTH .LE. STRLEN) GOTO 2 SPACES = WIDTH - STRLEN DO 1 SPCCNT = 1, SPACES WINDOW(FILNUM) = ORDSPC 1 CALL PUT(FILNUM) C 2 HIPOS = LOPOS - 1 + MINO(STRLEN, WIDTH) DO 3 STKPOS = LOPOS, HIPOS WINDOW(FILNUM) = STACK(STKPOS) 3 CALL PUT(FILNUM) C TOP = TOP - 1 - STRLEN RETURN END C c ============================================================== c SUBROUTINE WRLN (FILNUM) C C Implements the (single-parameter) P a s c a l procedure WRITELN C Output a l i n e onto f i l e FILNUM and empty the l i n e b u f f e r C INTEGER FILNUM, WRLEN, WRPOSN, WRORD INTEGER LINE(254,6), FILSTS(6), LINLEN(6), RDPOSN(6), + WINDOW(6), ENDFIL(6), ENDLIN(6), R, W, U, F, T, + CHR(256), ORDSPC, ORDPLS, ORDMNS, ORDO, ORD9, MXDV10, MXMD10 COMMON/FILCOM/LINE,FILSTS,LINLEN,RDPOSN,WINDOW,ENDFIL,ENDLIN, + R,W,U,F,T,CHR,ORDSPC,ORDPLS,ORDMNS,ORDO,ORD9,MXDV10,MXMD10 C Appendix C : LISTING OF THE RUN-TIME LIBRARY 89 IF (FILSTS(FILNUM) .NE. W) CALL RUNERR(7) C WRLEN = LINLEN(FILNUM) IF (WRLEN .GT. 0) GOTO 1 CALL WRNULN(FILNUM) GOTO 3 1 CONTINUE DO 2 WRPOSN = 1, WRLEN WRORD = LINE(WRPOSN, FILNUM) 2 LINE(WRPOSN, FILNUM) = CHR(WRORD + 1 ) WRITE(FILNUM,4) (LINE(WRPOSN, FILNUM), WRPOSN = 1, WRLEN) LINLEN(FILNUM) = 0 3 RETURN 4 FORMAT(254A1) END C C ====================================== C SUBROUTINE RUNERR (ERRNUM) C C Issue run-time e r r o r ERRNUM and h a l t e x e c u t i o n C C C C INTEGER ERRNUM INTEGER LINNUM COMMON /LINCOM/ LINNUM CALL CLSFLS WRITE(6,100) LINNUM 100 FORMAT(/ 27H ***** Run E r r o r at l i n e , 15) GOTO (1,2,3,4,5,6,7,8,9,10,11,12,13,998), ERRNUM 1 WRITE(6,101) 101 FORMAT(23H ***** Stack overflow /) GOTO 999 2 WRITE(6,102) 102 FORMAT(40H ***** GET/READ attempted before RESET /) GOTO 999 3 WRITE(6,103) 103 FORMAT(41H ***** Attempt to read past e n d - o f - f i l e /) GOTO 999 4 WRITE(6,104) 104 FORMAT(28H ***** Input l i n e too long /) GOTO 999 5 WRITE(6,105) 105 FORMAT(32H ***** D i g i t expected on input /) GOTO 999 6 WRITE(6,106) 106 FORMAT(32H ***** Input i n t e g e r too l a r g e /) GOTO 999 7 WRITE(6,107) 107 FORMAT(43H ***** PUT/WRITE attempted before REWRITE /) Appendix C : LISTING OF THE RUN-TIME LIBRARY 90 GOTO 99 8 WRITE(6 108 FORMAT( GOTO 99 9 WRITE(6 109 FORMAT( GOTO 99 10 WRITE(6 110 FORMAT( GOTO 99 11 WRITE(6 111 FORMAT( GOTO 99 12 WRITE(6 112 FORMAT( GOTO 99 13 WRITE(6 113 FORMAT( GOTO 99 9 , 1 0 8 ) 2 9 H * * * * * 9 , 1 0 9 ) 4OH * * * * * 9 , 1 1 0 ) 3 8 H * * * * * 9 , 1 1 1 ) 4 1H * * * * * 9 , 1 1 2 ) 3 0 H * * * * * 9 , 1 1 3 ) 3 2 H * * * * * 9 Output l i n e too long /) Output f i e l d - w i d t h n o n - p o s i t i v e /) Second operand of DIV i s zero /) Second operand of MOD i s <= zero /) EOF or EOLN undefined /) CASE index out of range /) 999 STOP 998 RETURN END C C c c c PROGRAM MAIN The Main Program INTEGER BASNUM INTEGER STACK(5000), TOP, BASE(30), SAVESZ, LINKSZ, BASEXC COMMON STACK, TOP, BASE, SAVESZ, LINKSZ, BASEXC SAVESZ = 19 LINKSZ = SAVESZ + 3 DO 1 BASNUM = 1 ,20 BASE(BASNUM) = -1 BASEXC = -1 TOP = 0 CALL SETFLS CALL MKLINK CALL CALLUP(1,1,0) CALL CLSFLS STOP END 

Cite

Citation Scheme:

        

Citations by CSL (citeproc-js)

Usage Statistics

Share

Embed

Customize your widget with the following options, then copy and paste the code below into the HTML of your page to embed this item in your website.
                        
                            <div id="ubcOpenCollectionsWidgetDisplay">
                            <script id="ubcOpenCollectionsWidget"
                            src="{[{embed.src}]}"
                            data-item="{[{embed.item}]}"
                            data-collection="{[{embed.collection}]}"
                            data-metadata="{[{embed.showMetadata}]}"
                            data-width="{[{embed.width}]}"
                            data-media="{[{embed.selectedMedia}]}"
                            async >
                            </script>
                            </div>
                        
                    
IIIF logo Our image viewer uses the IIIF 2.0 standard. To load this item in other compatible viewers, use this url:
https://iiif.library.ubc.ca/presentation/dsp.831.1-0051835/manifest

Comment

Related Items