Trip down memory lane: book on p-Code based UCSD Pascal
Posted by jpluimers on 2025/05/06
Last week I wrote on File scoped namespaces – C# 10.0 draft specifications | Microsoft Learn, promising to write more on p-Code and UCSD Pascal. That’s now (:
I started with [Wayback/Archive] “java byte code” “ucsd” “p-code” – Google Search as I was looking for really old material on this (Java 1.0 versions became available in the 1994-1995 time frame, and a lot of material back then either did not make it to the World Wide Web (which slowly gained popularity around that time, see History of the World Wide Web) or has vanished due to link rot.
The cool thing is that many “new” people are not even aware of p-Code, as the 2019 thread [Wayback/Archive] What do you think about something like Pascal bytecode? shows.
I learned a thing or two from it as well, for instance that there has been a “recent” book on UCSD Pascal:
The p-code was invented by Urs Amman, a student of Niklas Wirth in the mid 70th.
Kenneth Bowles at the University San Diego California put Pascal and p-code together and developed UCSD Pascal, also known as Apple Pascal or UCSD Power Pascal.Because only 15% of the OS are machine dependent UCSD Pascal became wide spread and was implemented on over different 80 machine types. The most work was to rewrite the system.interpreter in the Assembler dialect of ther machine. Later the interpreter was rewritten in C by Knowledge Software GB. The Java byte code is based on the p-code.
…
A short book about the UCSD Pascal Compiler and the p-system.
From 1982.
Chapter 10 is about p-code.https://homepages.cwi.nl/~steven/pascal/book/pascalimplementation.html
…
The book is not totally correct, but close. I started with UCSD pascal on an Apple 11e. (so, after the language originated)
The idea from the P-code originated with Wirth. The implementation of which is done by his student.
This is quite common in University circles.…
Can I conclude that the idea of string [complex type] was invented at UCSD Pascal, but Borland Turbo Pascal 1.0 in 1983 was the first one to really implement the String [simple] type?
…
Yes, that is the correct history.
UCSD was inteded for educational reasons – to learn Pascal, to learn how to build a compiler and was very puristic with the syntax and the types. Anyway – there were a lot of programms for buisiness use made with UCSD. And it came free with Apple II and Clones.
Turbo came some years later and came from the practical side: you could make sound, you could write a working terminal program (with pascal extension port), the compiler was optimized – as Anders Heilsberg said – not along the rules but with some hacks to speed it up. And you should not forget: A compiler in these days had a price of 1000.- $ and more. Turbo was sold in US for 99 $ and in Germany for 299.- DM (German Marks).
With Turbo you could play around with the hardware so you could get a serial RS 232 with 115.000 Baud – which was not due to the specifications but it worked. Later they sold this as “Poor mens network” with a serial (crossed) cable and some software (Kischbaum Link). You could connect 2 PCs and use neighbours disk C: as drive D: (or higher).
With UCSD you could not do such hardware hacks because it was machine independent. Then they recognized this and inserted unitread and unitwrite, but they tried to keep it secret before the students.
…
I vaguely remembered the first part about Pascal (and was happy about the refresher: I knew it was not Niklaus Wirth himself, now I know the name of the student at the ETH Zürich), but unlike [Wayback/Archive] ETH Zurich / N. Wirth / Books / PASCAL – User Manual, this book by Steven Pemberton and Martin Daniels was totally new for me!
The “Pascal Implementation” book: 20 years of work?!
Probably not 20 years of continuous work, but the copyright goes from 1982 to 2002, annotating the source code for the Pascal P4 Compiler.
It is at [Wayback/Archive] Pascal Implementation:
The full text of Pascal Implementation has been scanned from the original book, and OCR’d, before being updated. This initial release should therefore be considered a DRAFT. As a service to the community, you are therefore asked to communicate any errors, problems, or suggestions back to the authors at the email address below. Thanks!If you understand this is a draft, and will endeavour to communicate errors you find back to the author, then [Wayback/Archive] please proceed.
Then continues at [Wayback/Archive] Pascal Implementation; I added the archive links to the table of contents.
The P4 Compiler and Interpreter
by [Wayback/Archive] Steven Pemberton, [Wayback/Archive] Amsterdam, and [Wayback/Archive] Martin DanielsPart 1: The Compiler
[Wayback/Archive] Chapter 1: Input and Lexical Analysis
[Wayback/Archive] Chapter 2: Syntax Analysis
[Wayback/Archive] Chapter 3: Semantic Analysis
[Wayback/Archive] Chapter 4: Code Generation
[Wayback/Archive] Chapter 5: Compiling Expressions
[Wayback/Archive] Chapter 6: Compiling Procedures and Functions
[Wayback/Archive] Chapter 7: Compiling Statements
[Wayback/Archive] Chapter 8: Compiling Declarations
[Wayback/Archive] Chapter 9: Compiling the ProgramPart 2: The Interpreter
[Wayback/Archive] Chapter 10: The P-code Machine
[Wayback/Archive] Chapter 11: The Assembler
[Wayback/Archive] Chapter 12: The InterpreterAppendices
Copyright © 1982, 2002 Steven Pemberton and Martin Daniels, all rights reserved.
The compiler and interpreter themselves start at at another page named [Wayback/Archive] Pascal Implementation
Pascal Implementation: A Book and Sources
Included here is the Pascal source of a public-domain Pascal compiler and interpreter, the P4 compiler and interpreter. It is coded entirely in Pascal, and produces a high-level so-called intermediate code as output. The program ‘pint’ is an assembler and interpreter for this language.
The entire compiler and interpreter is documented in the book:
[Wayback/Archive] Pascal Implementation: The P4 Compiler and Interpreter, by [Wayback/Archive] Steven Pemberton and [Wayback/Archive] Martin Daniels, Ellis Horwood, ISBN: [W/Archive] 0-13-653-0311 (also available in [Wayback/Archive] Japanese).
It was distributed by John Wiley in other countries, but now that Prentice Hall has taken over Ellis Horwood, that will have changed.
Steven Pemberton is contactable by email as Steven.Pemberton@cwi.nl. He did not write the compiler, only documented it in the book.
What you have to do to use this compiler
- Compile
pcom.pandpint.pwith a Pascal compiler. You obviously have to have a Pascal compiler already. This gives you a Pascal compiler (pcom) that produces P4 code, and an interpreter (pint) that runs P4 code.- To use the compiler, run pcom with the Pascal program as standard input. This produces any diagnostics on standard output, and its code on a Pascal file that is called
prr. Check with your Pascal compiler how this gets assigned to a file in the filestore. You may have to change the lines ‘rewrite(prr)‘ inpcom.pandpint.pand ‘reset(prd)‘ inpint.pfor your compiler, for instance to “rewrite(prr, 'prr')” etc.- To run the resulting code, run
pintwith theprroutput produced bypcomas input for the file ‘prd‘, and input for the compiled pascal program on standard input.For instance, do this once:
pc -o pcom pcom.ppc -o pint pint.pand for each program:
pcom < test.p # produces file prr containing the p4 codemv prr prdpint < inputYou have to supply input to pint, even if the program doesn’t read from it, for instance:
pint < /dev/nullIf you intend to compile
pcomwith itself, there are two lines that have to be commented out when you do; search for the word ‘comment‘ in thepcomsource. There is no reason why you should want to compilepint.pwithpcom.What If You Haven’t Got a Pascal Compiler?
- Find a friend who does, and ask them to compile it for you.
- Use the [Wayback] C Translation of the Pascal Compiler (gzipped tar file), and compile that with a C compiler (as above).
- Get a copy of the [Wayback/Archive] pcode of the Pascal Compiler as compiled by itself, translate
pint.p, the interpreter, by hand into something else, and interpret the compiler.Differences with the Book
The code here is slightly different from that in the book, but the line numbers have been kept the same. The changes were to allow modern Pascal compilers to compile the source (there were some laxities in the original code).
[Wayback/Archive] The Compiler Source
Source files themselves
- [Wayback/Archive] https://homepages.cwi.nl/~steven/pascal/pcom.p
- [Wayback/Archive] https://homepages.cwi.nl/~steven/pascal/pint.p
- [Wayback/Archive] https://homepages.cwi.nl/~steven/pascal/differences.txt
- [Wayback/Archive] https://homepages.cwi.nl/~steven/pascal/pcom-code4.txt
- [Wayback] https://homepages.cwi.nl/~steven/pascal/p4c.tar.gz: a gzip (
.gz) compressedtarfiles of which I saved the individual files to [Wayback/Archive] P4C files by I.J.A.vanGeel@twi.tudelft.nl from https://homepages.cwi.nl/~steven/pascal/p4c.tar.gz (P2C translated C version of the P4 Pascal compiler, originally for UNIX and OS/2; requires GCC)
Source files in HTML form
Two of the above files are also on Steven’s web site in HTML form:
- [Wayback/Archive] https://homepages.cwi.nl/~steven/pascal/book/pcom.html
1 (*$c+,t-,d-,l-*) 2 (*********************************************** 3 * * 4 * Portable Pascal compiler * 5 * ************************ * 6 * * 7 * Pascal P4 * 8 * * 9 * Authors: * 10 * Urs Ammann * 11 * Kesav Nori * 12 * Christian Jacobi * 13 * Address: * 14 * Institut Fuer Informatik * 15 * Eidg. Technische Hochschule * 16 * CH-8096 Zuerich * 17 * * 18 * This code is fully documented in the book * 19 * "Pascal Implementation" * 20 * by Steven Pemberton and Martin Daniels * 21 * published by Ellis Horwood, Chichester, UK * 22 * ISBN: 0-13-653-0311 * 23 * (also available in Japanese) * 24 * * 25 * Steven Pemberton, CWI, Amsterdam * 26 * http://www.cwi.nl/~steven/ * 27 * Steven.Pemberton@cwi.nl * 28 * * 29 ***********************************************)
- [Wayback/Archive] https://homepages.cwi.nl/~steven/pascal/book/pint.html
1 (*Assembler and interpreter of Pascal code*) 2 (*K. Jensen, N. Wirth, Ch. Jacobi, ETH May 76*) 3 4 program pcode(input,output,prd,prr); 5 6 (* Note for the implementation. 7 =========================== 8 This interpreter is written for the case where all the fundamental types 9 take one storage unit. 10 In an actual implementation, the handling of the sp pointer has to take 11 into account the fact that the types may have lengths different from one: 12 in push and pop operations the sp has to be increased and decreased not 13 by 1, but by a number depending on the type concerned. 14 However, where the number of units of storage has been computed by the 15 compiler, the value must not be corrected, since the lengths of the types 16 involved have already been taken into account. 17 *)
Page 2 of the “Pascal bytecode?” thread
I learned a few more things from [Wayback/Archive] What do you think about something like Pascal bytecode? (Page 2)
Well, [Wayback/Archive] https://sourceforge.net/projects/pascalp5/ is a pascal bytecode compiler(it is actually used in the tests to test ISO conformance in {$mode iso})
And the author sometimes visits this forum. Freepascal – at least 3.2.0 and trunk- can compile this compiler…
Scott Franco, the author, is a bit of a ISO standards guru, at least to me.His website also contains the original pascal-s and some previous efforts.
…
Perhaps more to the point, having a compiler emit a bytecode sequence as a well-documented intermediate representation is “very 1980s”. With all respect to Scott, Bernd and the other maintainers of historic compilers, the way it’s done these days is for the frontend to generate a parse tree which might- or might not- be published and documented: and if OP wants to help document some of the FPC arcana I’m sure his help would be appreciated :-)
Noting that Bernd’s port of P4 http://bernd-oppolzer.de/job9.htm runs on at least some of the classic mainframe OSes, I’d add that poor understanding of FPC’s internal operation was one of the reasons that FPC didn’t get ported to those platforms.
…
Why did he port that? The original author already did that: Scott Franco (a.k.a. Scott Moore). Better use the source, the source and not some vague ports.
…
IIRC P4 originated at ETH, was built for portability by Wirth’s team in the seventies. and was indeed ported to many platforms. Stanford Pascal was one of those ports, for IBM mainframes. Scott Moore was not the original author, but he did (much later in time!) quite a remarkable job digging up the original source code and publishing it. And made a ‘P5’ out of it. All compiler-interpreters with p-code (not bytecode!)
…
Afaik, ETH’s P4 was meant as bootstrap compiler because the small bytecode interpreter would be easily portable.
Since the compiler didn’t use the full ISO dialect, neither did P4.That’s why Scott made P5, which is P4 expanded to support the full ISO dialect.
Hopefully more on that in a future blog post.
--jeroen
Gist with P4C source files from https://homepages.cwi.nl/~steven/pascal/p4c.tar.gz
[Wayback/Archive] P4C files by I.J.A.vanGeel@twi.tudelft.nl from https://homepages.cwi.nl/~steven/pascal/p4c.tar.gz (P2C translated C version of the P4 Pascal compiler, originally for UNIX and OS/2; requires GCC)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| README for P4 compiler/interpreter | |
| Included are the sources to the P4 Pascal -> P-code compiler and to the | |
| P-code interpreter. The original source-code was written in Pascal, which | |
| was transformed to C-code, using p2c. | |
| (Details of the conversion can be found in the headers of the C-files) | |
| You can redistribute all the source code freely, the p2c library source | |
| and the code generated by it are NOT subject to the GNU general public | |
| license. The original Pascal source-code is public domain. | |
| Makefiles are included to compile the programs using gcc and Unix or | |
| gcc (emx) and OS/2. | |
| To make just enter: | |
| make | |
| or | |
| make -f makefile.os2 | |
| Enjoy | |
| Send reactions to | |
| I.J.A.vanGeel@twi.tudelft.nl | |
| Date: august 22 1996 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # UNIX Makefile | |
| # Makefile for the P4 pascal compiler and interpreter | |
| CC = gcc | |
| CFLAGS = -O3 -fomit-frame-pointer -funroll-loops | |
| #CFLAGS = -Wall -g | |
| .c.o: | |
| $(CC) -I. $(CFLAGS) -c $< | |
| all: pcom pint | |
| pcom: libp2c.a pcom.o | |
| $(CC) pcom.o -o pcom -L. -lp2c | |
| pcom.o: pcom.c p2c.h | |
| pint: libp2c.a pint.o | |
| $(CC) pint.o -o pint -L. -lp2c -lm | |
| pint.o: pint.c p2c.h | |
| libp2c.a: p2clib.o | |
| ar rv libp2c.a p2clib.o | |
| ranlib libp2c.a | |
| p2clib.o: p2clib.c p2c.h | |
| clean: | |
| $(RM) *% *.o *.a pint pcom core prr prd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # OS/2 Makefile | |
| # Makefile for the P4 pascal compiler and interpreter | |
| CC = gcc | |
| CFLAGS = -O3 -fomit-frame-pointer -funroll-loops | |
| #CFLAGS = -Wall -g | |
| RM = del | |
| .c.o: | |
| $(CC) -I. $(CFLAGS) -c $< | |
| all: pcom.exe pint.exe | |
| pcom.exe: p2c.a pcom.o | |
| $(CC) pcom.o -o pcom.exe -L. -lp2c | |
| pcom.o: pcom.c p2c.h | |
| pint.exe: p2c.a pint.o | |
| $(CC) pint.o -o pint.exe -L. -lp2c -lm | |
| pint.o: pint.c p2c.h | |
| p2c.a: p2clib.o | |
| ar rv p2c.a p2clib.o | |
| p2clib.o: p2clib.c p2c.h | |
| clean: | |
| $(RM) *.o *.a pint.exe pcom.exe core prr prd | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # UNIX Makefile | |
| # Makefile for the P4 pascal compiler and interpreter | |
| CC = gcc | |
| CFLAGS = -O3 -fomit-frame-pointer -funroll-loops | |
| #CFLAGS = -Wall -g | |
| .c.o: | |
| $(CC) -I. $(CFLAGS) -c $< | |
| all: pcom pint | |
| pcom: libp2c.a pcom.o | |
| $(CC) pcom.o -o pcom -L. -lp2c | |
| pcom.o: pcom.c p2c.h | |
| pint: libp2c.a pint.o | |
| $(CC) pint.o -o pint -L. -lp2c -lm | |
| pint.o: pint.c p2c.h | |
| libp2c.a: p2clib.o | |
| ar rv libp2c.a p2clib.o | |
| ranlib libp2c.a | |
| p2clib.o: p2clib.c p2c.h | |
| clean: | |
| $(RM) *% *.o *.a pint pcom core prr prd |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef P2C_H | |
| #define P2C_H | |
| /* Header file for code generated by "p2c", the Pascal-to-C translator */ | |
| /* "p2c" Copyright (C) 1989, 1990, 1991 Free Software Foundation. | |
| * By Dave Gillespie, daveg@csvax.cs.caltech.edu. Version 1.20. | |
| * This file may be copied, modified, etc. in any way. It is not restricted | |
| * by the licence agreement accompanying p2c itself. | |
| */ | |
| #include <stdio.h> | |
| /* If the following heuristic fails, compile -DBSD=0 for non-BSD systems, | |
| or -DBSD=1 for BSD systems. */ | |
| #ifdef M_XENIX | |
| # define BSD 0 | |
| #endif | |
| #ifdef vms | |
| # define BSD 0 | |
| # ifndef __STDC__ | |
| # define __STDC__ 1 | |
| # endif | |
| #endif | |
| #ifdef __TURBOC__ | |
| # define MSDOS 1 | |
| #endif | |
| #ifdef MSDOS | |
| # define BSD 0 | |
| #endif | |
| #ifdef FILE /* a #define in BSD, a typedef in SYSV (hp-ux, at least) */ | |
| # ifndef BSD /* (a convenient, but horrible kludge!) */ | |
| # define BSD 1 | |
| # endif | |
| #endif | |
| #ifdef BSD | |
| # if !BSD | |
| # undef BSD | |
| # endif | |
| #endif | |
| #if (defined(__STDC__) && !defined(M_XENIX)) || defined(__TURBOC__) | |
| # include <stddef.h> | |
| # include <stdlib.h> | |
| # define HAS_STDLIB | |
| # if defined(vms) || defined(__TURBOC__) | |
| # define __ID__(a)a | |
| # endif | |
| #else | |
| # ifndef BSD | |
| # ifndef __TURBOC__ | |
| # include <memory.h> | |
| # endif | |
| # endif | |
| # ifdef hpux | |
| # ifdef _INCLUDE__STDC__ | |
| # include <stddef.h> | |
| # include <stdlib.h> | |
| # endif | |
| # endif | |
| # include <sys/types.h> | |
| # if !defined(MSDOS) || defined(__TURBOC__) | |
| # define __ID__(a)a | |
| # endif | |
| #endif | |
| #ifdef __ID__ | |
| # define __CAT__(a,b)__ID__(a)b | |
| #else | |
| # define __CAT__(a,b)a##b | |
| #endif | |
| #ifdef BSD | |
| # include <strings.h> | |
| # define memcpy(a,b,n) (bcopy(b,a,n),a) | |
| # define memcmp(a,b,n) bcmp(a,b,n) | |
| # define strchr(s,c) index(s,c) | |
| # define strrchr(s,c) rindex(s,c) | |
| #else | |
| # include <string.h> | |
| #endif | |
| #include <ctype.h> | |
| #include <math.h> | |
| #include <setjmp.h> | |
| #include <assert.h> | |
| #define NO_LACK | |
| #ifndef NO_LACK | |
| #ifdef vms | |
| #define LACK_LABS | |
| #define LACK_MEMMOVE | |
| #define LACK_MEMCPY | |
| #else | |
| #define LACK_LABS /* Undefine these if your library has these */ | |
| #define LACK_MEMMOVE | |
| #endif | |
| #endif | |
| typedef struct __p2c_jmp_buf { | |
| struct __p2c_jmp_buf *next; | |
| jmp_buf jbuf; | |
| } __p2c_jmp_buf; | |
| /* Warning: The following will not work if setjmp is used simultaneously. | |
| This also violates the ANSI restriction about using vars after longjmp, | |
| but a typical implementation of longjmp will get it right anyway. */ | |
| #ifndef FAKE_TRY | |
| # define TRY(x) do { __p2c_jmp_buf __try_jb; \ | |
| __try_jb.next = __top_jb; \ | |
| if (!setjmp((__top_jb = &__try_jb)->jbuf)) { | |
| # define RECOVER(x) __top_jb = __try_jb.next; } else { | |
| # define RECOVER2(x,L) __top_jb = __try_jb.next; } else { \ | |
| if (0) { L: __top_jb = __try_jb.next; } | |
| # define ENDTRY(x) } } while (0) | |
| #else | |
| # define TRY(x) if (1) { | |
| # define RECOVER(x) } else do { | |
| # define RECOVER2(x,L) } else do { L: ; | |
| # define ENDTRY(x) } while (0) | |
| #endif | |
| #ifdef M_XENIX /* avoid compiler bug */ | |
| # define SHORT_MAX (32767) | |
| # define SHORT_MIN (-32768) | |
| #endif | |
| /* The following definitions work only on twos-complement machines */ | |
| #ifndef SHORT_MAX | |
| # define SHORT_MAX ((short)(((unsigned short) -1) >> 1)) | |
| # define SHORT_MIN (~SHORT_MAX) | |
| #endif | |
| #ifndef INT_MAX | |
| # define INT_MAX ((int)(((unsigned int) -1) >> 1)) | |
| # define INT_MIN (~INT_MAX) | |
| #endif | |
| #ifndef LONG_MAX | |
| # define LONG_MAX ((long)(((unsigned long) -1) >> 1)) | |
| # define LONG_MIN (~LONG_MAX) | |
| #endif | |
| #ifndef SEEK_SET | |
| # define SEEK_SET 0 | |
| # define SEEK_CUR 1 | |
| # define SEEK_END 2 | |
| #endif | |
| #ifndef EXIT_SUCCESS | |
| # ifdef vms | |
| # define EXIT_SUCCESS 1 | |
| # define EXIT_FAILURE (02000000000L) | |
| # else | |
| # define EXIT_SUCCESS 0 | |
| # define EXIT_FAILURE 1 | |
| # endif | |
| #endif | |
| #define SETBITS 32 | |
| #if defined(__STDC__) || defined(__TURBOC__) | |
| # if !defined(vms) && !defined(M_LINT) | |
| # define Signed signed | |
| # else | |
| # define Signed | |
| # endif | |
| # define Void void /* Void f() = procedure */ | |
| # ifndef Const | |
| # define Const const | |
| # endif | |
| # ifndef Volatile | |
| # define Volatile volatile | |
| # endif | |
| # ifdef M_LINT | |
| # define PP(x) () | |
| # define PV() () | |
| typedef char *Anyptr; | |
| # else | |
| # define PP(x) x /* function prototype */ | |
| # define PV() (void) /* null function prototype */ | |
| typedef void *Anyptr; | |
| # endif | |
| #else | |
| # define Signed | |
| # define Void void | |
| # ifndef Const | |
| # define Const | |
| # endif | |
| # ifndef Volatile | |
| # define Volatile | |
| # endif | |
| # define PP(x) () | |
| # define PV() () | |
| typedef char *Anyptr; | |
| #endif | |
| #ifdef __GNUC__ | |
| # define Inline inline | |
| #else | |
| # define Inline | |
| #endif | |
| #define Register register /* Register variables */ | |
| #define Char char /* Characters (not bytes) */ | |
| #ifndef Static | |
| # define Static static /* Private global funcs and vars */ | |
| #endif | |
| #ifndef Local | |
| # define Local static /* Nested functions */ | |
| #endif | |
| typedef Signed char schar; | |
| typedef unsigned char uchar; | |
| typedef unsigned char boolean; | |
| #ifndef true | |
| # define true 1 | |
| # define false 0 | |
| #endif | |
| #ifndef TRUE | |
| # define TRUE 1 | |
| # define FALSE 0 | |
| #endif | |
| typedef struct { | |
| Anyptr proc, link; | |
| } _PROCEDURE; | |
| #ifndef _FNSIZE | |
| # define _FNSIZE 120 | |
| #endif | |
| extern Void PASCAL_MAIN PP( (int, Char **) ); | |
| extern Char **P_argv; | |
| extern int P_argc; | |
| extern short P_escapecode; | |
| extern int P_ioresult; | |
| extern __p2c_jmp_buf *__top_jb; | |
| #ifdef P2C_H_PROTO /* if you have Ansi C but non-prototyped header files */ | |
| extern Char *strcat PP( (Char *, Const Char *) ); | |
| extern Char *strchr PP( (Const Char *, int) ); | |
| extern int strcmp PP( (Const Char *, Const Char *) ); | |
| extern Char *strcpy PP( (Char *, Const Char *) ); | |
| extern size_t strlen PP( (Const Char *) ); | |
| extern Char *strncat PP( (Char *, Const Char *, size_t) ); | |
| extern int strncmp PP( (Const Char *, Const Char *, size_t) ); | |
| extern Char *strncpy PP( (Char *, Const Char *, size_t) ); | |
| extern Char *strrchr PP( (Const Char *, int) ); | |
| extern Anyptr memchr PP( (Const Anyptr, int, size_t) ); | |
| extern Anyptr memmove PP( (Anyptr, Const Anyptr, size_t) ); | |
| extern Anyptr memset PP( (Anyptr, int, size_t) ); | |
| #ifndef memcpy | |
| extern Anyptr memcpy PP( (Anyptr, Const Anyptr, size_t) ); | |
| extern int memcmp PP( (Const Anyptr, Const Anyptr, size_t) ); | |
| #endif | |
| extern int atoi PP( (Const Char *) ); | |
| extern double atof PP( (Const Char *) ); | |
| extern long atol PP( (Const Char *) ); | |
| extern double strtod PP( (Const Char *, Char **) ); | |
| extern long strtol PP( (Const Char *, Char **, int) ); | |
| #endif /*P2C_H_PROTO*/ | |
| #ifndef HAS_STDLIB | |
| extern Anyptr malloc PP( (size_t) ); | |
| extern Void free PP( (Anyptr) ); | |
| #endif | |
| extern int _OutMem PV(); | |
| extern int _CaseCheck PV(); | |
| extern int _NilCheck PV(); | |
| extern int _Escape PP( (int) ); | |
| extern int _EscIO PP( (int) ); | |
| extern long ipow PP( (long, long) ); | |
| extern Char *strsub PP( (Char *, Char *, int, int) ); | |
| extern Char *strltrim PP( (Char *) ); | |
| extern Char *strrtrim PP( (Char *) ); | |
| extern Char *strrpt PP( (Char *, Char *, int) ); | |
| extern Char *strpad PP( (Char *, Char *, int, int) ); | |
| extern int strpos2 PP( (Char *, Char *, int) ); | |
| extern long memavail PV(); | |
| extern int P_peek PP( (FILE *) ); | |
| extern int P_eof PP( (FILE *) ); | |
| extern int P_eoln PP( (FILE *) ); | |
| extern Void P_readpaoc PP( (FILE *, Char *, int) ); | |
| extern Void P_readlnpaoc PP( (FILE *, Char *, int) ); | |
| extern long P_maxpos PP( (FILE *) ); | |
| extern Char *P_trimname PP( (Char *, int) ); | |
| extern long *P_setunion PP( (long *, long *, long *) ); | |
| extern long *P_setint PP( (long *, long *, long *) ); | |
| extern long *P_setdiff PP( (long *, long *, long *) ); | |
| extern long *P_setxor PP( (long *, long *, long *) ); | |
| extern int P_inset PP( (unsigned, long *) ); | |
| extern int P_setequal PP( (long *, long *) ); | |
| extern int P_subset PP( (long *, long *) ); | |
| extern long *P_addset PP( (long *, unsigned) ); | |
| extern long *P_addsetr PP( (long *, unsigned, unsigned) ); | |
| extern long *P_remset PP( (long *, unsigned) ); | |
| extern long *P_setcpy PP( (long *, long *) ); | |
| extern long *P_expset PP( (long *, long) ); | |
| extern long P_packset PP( (long *) ); | |
| extern int P_getcmdline PP( (int, int, Char *) ); | |
| extern Void TimeStamp PP( (int *, int *, int *, | |
| int *, int *, int *) ); | |
| extern Void P_sun_argv PP( (char *, int, int) ); | |
| /* I/O error handling */ | |
| #define _CHKIO(cond,ior,val,def) ((cond) ? P_ioresult=0,(val) \ | |
| : P_ioresult=(ior),(def)) | |
| #define _SETIO(cond,ior) (P_ioresult = (cond) ? 0 : (ior)) | |
| /* Following defines are suitable for the HP Pascal operating system */ | |
| #define FileNotFound 10 | |
| #define FileNotOpen 13 | |
| #define FileWriteError 38 | |
| #define BadInputFormat 14 | |
| #define EndOfFile 30 | |
| #define FILENOTFOUND 10 | |
| #define FILENOTOPEN 13 | |
| #define FILEWRITEERROR 38 | |
| #define BADINPUTFORMAT 14 | |
| #define ENDOFFILE 30 | |
| /* Creating temporary files */ | |
| #if (defined(BSD) || defined(NO_TMPFILE)) && !defined(HAVE_TMPFILE) | |
| # define tmpfile() (fopen(tmpnam(NULL), "w+")) | |
| #endif | |
| /* File buffers */ | |
| #define FILEBUF(f,sc,type) sc int __CAT__(f,_BFLAGS); \ | |
| sc type __CAT__(f,_BUFFER) | |
| #define FILEBUFNC(f,type) int __CAT__(f,_BFLAGS); \ | |
| type __CAT__(f,_BUFFER) | |
| #define RESETBUF(f,type) (__CAT__(f,_BFLAGS) = 1) | |
| #define SETUPBUF(f,type) (__CAT__(f,_BFLAGS) = 0) | |
| #define GETFBUF(f,type) (*((__CAT__(f,_BFLAGS) == 1 && \ | |
| ((__CAT__(f,_BFLAGS) = 2), \ | |
| fread(&__CAT__(f,_BUFFER), \ | |
| sizeof(type),1,(f)))),\ | |
| &__CAT__(f,_BUFFER))) | |
| #define AGETFBUF(f,type) ((__CAT__(f,_BFLAGS) == 1 && \ | |
| ((__CAT__(f,_BFLAGS) = 2), \ | |
| fread(__CAT__(f,_BUFFER), \ | |
| sizeof(type),1,(f)))),\ | |
| __CAT__(f,_BUFFER)) | |
| #define PUTFBUF(f,type,v) (GETFBUF(f,type) = (v)) | |
| #define CPUTFBUF(f,v) (PUTFBUF(f,char,v)) | |
| #define APUTFBUF(f,type,v) (memcpy(AGETFBUF(f,type), (v), \ | |
| sizeof(__CAT__(f,_BUFFER)))) | |
| #define GET(f,type) (__CAT__(f,_BFLAGS) == 1 ? \ | |
| fread(&__CAT__(f,_BUFFER),sizeof(type),1,(f)) : \ | |
| (__CAT__(f,_BFLAGS) = 1)) | |
| #define PUT(f,type) (fwrite(&__CAT__(f,_BUFFER),sizeof(type),1,(f)), \ | |
| (__CAT__(f,_BFLAGS) = 0)) | |
| #define CPUT(f) (PUT(f,char)) | |
| #define BUFEOF(f) (__CAT__(f,_BFLAGS) != 2 && P_eof(f)) | |
| #define BUFFPOS(f) (ftell(f) – (__CAT__(f,_BFLAGS) == 2)) | |
| typedef struct { | |
| FILE *f; | |
| FILEBUFNC(f,Char); | |
| Char name[_FNSIZE]; | |
| } _TEXT; | |
| /* Memory allocation */ | |
| #ifdef __GCC__ | |
| # define Malloc(n) (malloc(n) ?: (Anyptr)_OutMem()) | |
| #else | |
| extern Anyptr __MallocTemp__; | |
| # define Malloc(n) ((__MallocTemp__ = malloc(n)) ? __MallocTemp__ : (Anyptr)_OutMem()) | |
| #endif | |
| #define FreeR(p) (free((Anyptr)(p))) /* used if arg is an rvalue */ | |
| #define Free(p) (free((Anyptr)(p)), (p)=NULL) | |
| /* sign extension */ | |
| #define SEXT(x,n) ((x) | -(((x) & (1L<<((n)-1))) << 1)) | |
| /* packed arrays */ /* BEWARE: these are untested! */ | |
| #define P_getbits_UB(a,i,n,L) ((int)((a)[(i)>>(L)-(n)] >> \ | |
| (((~(i))&((1<<(L)-(n))-1)) << (n)) & \ | |
| (1<<(1<<(n)))-1)) | |
| #define P_getbits_SB(a,i,n,L) ((int)((a)[(i)>>(L)-(n)] << \ | |
| (16 – ((((~(i))&((1<<(L)-(n))-1))+1) <<\ | |
| (n)) >> (16-(1<<(n)))))) | |
| #define P_putbits_UB(a,i,x,n,L) ((a)[(i)>>(L)-(n)] |= \ | |
| (x) << (((~(i))&((1<<(L)-(n))-1)) << (n))) | |
| #define P_putbits_SB(a,i,x,n,L) ((a)[(i)>>(L)-(n)] |= \ | |
| ((x) & (1<<(1<<(n)))-1) << \ | |
| (((~(i))&((1<<(L)-(n))-1)) << (n))) | |
| #define P_clrbits_B(a,i,n,L) ((a)[(i)>>(L)-(n)] &= \ | |
| ~( ((1<<(1<<(n)))-1) << \ | |
| (((~(i))&((1<<(L)-(n))-1)) << (n))) ) | |
| /* small packed arrays */ | |
| #define P_getbits_US(v,i,n) ((int)((v) >> ((i)<<(n)) & (1<<(1<<(n)))-1)) | |
| #define P_getbits_SS(v,i,n) ((int)((long)(v) << (SETBITS – (((i)+1) << (n))) >> (SETBITS-(1<<(n))))) | |
| #define P_putbits_US(v,i,x,n) ((v) |= (x) << ((i) << (n))) | |
| #define P_putbits_SS(v,i,x,n) ((v) |= ((x) & (1<<(1<<(n)))-1) << ((i)<<(n))) | |
| #define P_clrbits_S(v,i,n) ((v) &= ~( ((1<<(1<<(n)))-1) << ((i)<<(n)) )) | |
| #define P_max(a,b) ((a) > (b) ? (a) : (b)) | |
| #define P_min(a,b) ((a) < (b) ? (a) : (b)) | |
| /* Fix ANSI-isms */ | |
| #ifdef LACK_LABS | |
| # ifndef labs | |
| # define labs my_labs | |
| extern long my_labs PP( (long) ); | |
| # endif | |
| #endif | |
| #ifdef LACK_MEMMOVE | |
| # ifndef memmove | |
| # define memmove my_memmove | |
| extern Anyptr my_memmove PP( (Anyptr, Const Anyptr, size_t) ); | |
| # endif | |
| #endif | |
| #ifdef LACK_MEMCPY | |
| # ifndef memcpy | |
| # define memcpy my_memcpy | |
| extern Anyptr my_memcpy PP( (Anyptr, Const Anyptr, size_t) ); | |
| # endif | |
| # ifndef memcmp | |
| # define memcmp my_memcmp | |
| extern int my_memcmp PP( (Const Anyptr, Const Anyptr, size_t) ); | |
| # endif | |
| # ifndef memset | |
| # define memset my_memset | |
| extern Anyptr my_memset PP( (Anyptr, int, size_t) ); | |
| # endif | |
| #endif | |
| #endif /* P2C_H */ | |
| /* End. */ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Run-time library for use with "p2c", the Pascal to C translator */ | |
| /* "p2c" Copyright (C) 1989, 1990, 1991 Free Software Foundation. | |
| * By Dave Gillespie, daveg@csvax.cs.caltech.edu. Version –VERSION–. | |
| * This file may be copied, modified, etc. in any way. It is not restricted | |
| * by the licence agreement accompanying p2c itself. | |
| */ | |
| #include "p2c.h" | |
| #ifndef NO_TIME | |
| # include <time.h> | |
| #endif | |
| #define Isspace(c) isspace(c) /* or "((c) == ' ')" if preferred */ | |
| int P_argc; | |
| char **P_argv; | |
| short P_escapecode; | |
| int P_ioresult; | |
| long EXCP_LINE; /* Used by Pascal workstation system */ | |
| Anyptr __MallocTemp__; | |
| __p2c_jmp_buf *__top_jb; | |
| void PASCAL_MAIN(argc, argv) | |
| int argc; | |
| char **argv; | |
| { | |
| P_argc = argc; | |
| P_argv = argv; | |
| __top_jb = NULL; | |
| #ifdef LOCAL_INIT | |
| LOCAL_INIT(); | |
| #endif | |
| } | |
| /* In case your system lacks these… */ | |
| long my_labs(x) | |
| long x; | |
| { | |
| return((x > 0) ? x : -x); | |
| } | |
| #ifdef __STDC__ | |
| Anyptr my_memmove(Anyptr d, Const Anyptr s, size_t n) | |
| #else | |
| Anyptr my_memmove(d, s, n) | |
| Anyptr d, s; | |
| register int n; | |
| #endif | |
| { | |
| register char *dd = (char *)d, *ss = (char *)s; | |
| if (dd < ss || dd – ss >= n) { | |
| memcpy(dd, ss, n); | |
| } else if (n > 0) { | |
| dd += n; | |
| ss += n; | |
| while (n– > 0) | |
| *–dd = *–ss; | |
| } | |
| return d; | |
| } | |
| #ifdef __STDC__ | |
| Anyptr my_memcpy(Anyptr d, Const Anyptr s, size_t n) | |
| #else | |
| Anyptr my_memcpy(d, s, n) | |
| Anyptr d, s; | |
| register int n; | |
| #endif | |
| { | |
| register char *ss = (char *)s, *dd = (char *)d; | |
| while (n– > 0) | |
| *dd++ = *ss++; | |
| return d; | |
| } | |
| #ifdef __STDC__ | |
| int my_memcmp(Const Anyptr s1, Const Anyptr s2, size_t n) | |
| #else | |
| int my_memcmp(s1, s2, n) | |
| Anyptr s1, s2; | |
| register int n; | |
| #endif | |
| { | |
| register char *a = (char *)s1, *b = (char *)s2; | |
| register int i; | |
| while (n– > 0) | |
| if ((i = (*a++) – (*b++)) != 0) | |
| return i; | |
| return 0; | |
| } | |
| #ifdef __STDC__ | |
| Anyptr my_memset(Anyptr d, int c, size_t n) | |
| #else | |
| Anyptr my_memset(d, c, n) | |
| Anyptr d; | |
| register int c; | |
| register int n; | |
| #endif | |
| { | |
| register char *dd = (char *)d; | |
| while (n– > 0) | |
| *dd++ = c; | |
| return d; | |
| } | |
| int my_toupper(c) | |
| int c; | |
| { | |
| if (islower(c)) | |
| return _toupper(c); | |
| else | |
| return c; | |
| } | |
| int my_tolower(c) | |
| int c; | |
| { | |
| if (isupper(c)) | |
| return _tolower(c); | |
| else | |
| return c; | |
| } | |
| long ipow(a, b) | |
| long a, b; | |
| { | |
| long v; | |
| if (a == 0 || a == 1) | |
| return a; | |
| if (a == -1) | |
| return (b & 1) ? -1 : 1; | |
| if (b < 0) | |
| return 0; | |
| if (a == 2) | |
| return 1L << b; | |
| v = (b & 1) ? a : 1; | |
| while ((b >>= 1) > 0) { | |
| a *= a; | |
| if (b & 1) | |
| v *= a; | |
| } | |
| return v; | |
| } | |
| /* Common string functions: */ | |
| /* Store in "ret" the substring of length "len" starting from "pos" (1-based). | |
| Store a shorter or null string if out-of-range. Return "ret". */ | |
| char *strsub(ret, s, pos, len) | |
| register char *ret, *s; | |
| register int pos, len; | |
| { | |
| register char *s2; | |
| if (–pos < 0 || len <= 0) { | |
| *ret = 0; | |
| return ret; | |
| } | |
| while (pos > 0) { | |
| if (!*s++) { | |
| *ret = 0; | |
| return ret; | |
| } | |
| pos–; | |
| } | |
| s2 = ret; | |
| while (–len >= 0) { | |
| if (!(*s2++ = *s++)) | |
| return ret; | |
| } | |
| *s2 = 0; | |
| return ret; | |
| } | |
| /* Return the index of the first occurrence of "pat" as a substring of "s", | |
| starting at index "pos" (1-based). Result is 1-based, 0 if not found. */ | |
| int strpos2(s, pat, pos) | |
| char *s; | |
| register char *pat; | |
| register int pos; | |
| { | |
| register char *cp, ch; | |
| register int slen; | |
| if (–pos < 0) | |
| return 0; | |
| slen = strlen(s) – pos; | |
| cp = s + pos; | |
| if (!(ch = *pat++)) | |
| return 0; | |
| pos = strlen(pat); | |
| slen -= pos; | |
| while (–slen >= 0) { | |
| if (*cp++ == ch && !strncmp(cp, pat, pos)) | |
| return cp – s; | |
| } | |
| return 0; | |
| } | |
| /* Case-insensitive version of strcmp. */ | |
| int strcicmp(s1, s2) | |
| register char *s1, *s2; | |
| { | |
| register unsigned char c1, c2; | |
| while (*s1) { | |
| if (*s1++ != *s2++) { | |
| if (!s2[-1]) | |
| return 1; | |
| c1 = toupper(s1[-1]); | |
| c2 = toupper(s2[-1]); | |
| if (c1 != c2) | |
| return c1 – c2; | |
| } | |
| } | |
| if (*s2) | |
| return -1; | |
| return 0; | |
| } | |
| /* HP and Turbo Pascal string functions: */ | |
| /* Trim blanks at left end of string. */ | |
| char *strltrim(s) | |
| register char *s; | |
| { | |
| while (Isspace(*s++)) ; | |
| return s – 1; | |
| } | |
| /* Trim blanks at right end of string. */ | |
| char *strrtrim(s) | |
| register char *s; | |
| { | |
| register char *s2 = s; | |
| if (!*s) | |
| return s; | |
| while (*++s2) ; | |
| while (s2 > s && Isspace(*–s2)) | |
| *s2 = 0; | |
| return s; | |
| } | |
| /* Store in "ret" "num" copies of string "s". Return "ret". */ | |
| char *strrpt(ret, s, num) | |
| char *ret; | |
| register char *s; | |
| register int num; | |
| { | |
| register char *s2 = ret; | |
| register char *s1; | |
| while (–num >= 0) { | |
| s1 = s; | |
| while ((*s2++ = *s1++)) ; | |
| s2–; | |
| } | |
| return ret; | |
| } | |
| /* Store in "ret" string "s" with enough pad chars added to reach "size". */ | |
| char *strpad(ret, s, padchar, num) | |
| char *ret; | |
| register char *s; | |
| register int padchar, num; | |
| { | |
| register char *d = ret; | |
| if (s == d) { | |
| while (*d++) ; | |
| } else { | |
| while ((*d++ = *s++)) ; | |
| } | |
| num -= (–d – ret); | |
| while (–num >= 0) | |
| *d++ = padchar; | |
| *d = 0; | |
| return ret; | |
| } | |
| /* Copy the substring of length "len" from index "spos" of "s" (1-based) | |
| to index "dpos" of "d", lengthening "d" if necessary. Length and | |
| indices must be in-range. */ | |
| void strmove(len, s, spos, d, dpos) | |
| register char *s, *d; | |
| register int len, spos, dpos; | |
| { | |
| s += spos – 1; | |
| d += dpos – 1; | |
| while (*d && –len >= 0) | |
| *d++ = *s++; | |
| if (len > 0) { | |
| while (–len >= 0) | |
| *d++ = *s++; | |
| *d = 0; | |
| } | |
| } | |
| /* Delete the substring of length "len" at index "pos" from "s". | |
| Delete less if out-of-range. */ | |
| void strdelete(s, pos, len) | |
| register char *s; | |
| register int pos, len; | |
| { | |
| register int slen; | |
| if (–pos < 0) | |
| return; | |
| slen = strlen(s) – pos; | |
| if (slen <= 0) | |
| return; | |
| s += pos; | |
| if (slen <= len) { | |
| *s = 0; | |
| return; | |
| } | |
| while ((*s = s[len])) s++; | |
| } | |
| /* Insert string "src" at index "pos" of "dst". */ | |
| void strinsert(src, dst, pos) | |
| register char *src, *dst; | |
| register int pos; | |
| { | |
| register int slen, dlen; | |
| if (–pos < 0) | |
| return; | |
| dlen = strlen(dst); | |
| dst += dlen; | |
| dlen -= pos; | |
| if (dlen <= 0) { | |
| strcpy(dst, src); | |
| return; | |
| } | |
| slen = strlen(src); | |
| do { | |
| dst[slen] = *dst; | |
| –dst; | |
| } while (–dlen >= 0); | |
| dst++; | |
| while (–slen >= 0) | |
| *dst++ = *src++; | |
| } | |
| /* File functions */ | |
| /* Peek at next character of input stream; return EOF at end-of-file. */ | |
| int P_peek(f) | |
| FILE *f; | |
| { | |
| int ch; | |
| ch = fgetc(f); | |
| if (ch == EOF) | |
| return EOF; | |
| ungetc(ch, f); | |
| return (ch == '\n') ? ' ' : ch; | |
| } | |
| /* Check if at end of file, using Pascal "eof" semantics. End-of-file for | |
| stdin is broken; remove the special case for it to be broken in a | |
| different way. */ | |
| int P_eof(f) | |
| FILE *f; | |
| { | |
| register int ch; | |
| if (feof(f)) | |
| return 1; | |
| ch = fgetc(f); | |
| if (ch == EOF) | |
| return 1; | |
| ungetc(ch, f); | |
| return 0; | |
| } | |
| /* Check if at end of line (or end of entire file). */ | |
| int P_eoln(f) | |
| FILE *f; | |
| { | |
| register int ch; | |
| ch = fgetc(f); | |
| if (ch == EOF) | |
| return 1; | |
| ungetc(ch, f); | |
| return (ch == '\n'); | |
| } | |
| /* Read a packed array of characters from a file. */ | |
| Void P_readpaoc(f, s, len) | |
| FILE *f; | |
| char *s; | |
| int len; | |
| { | |
| int ch; | |
| for (;;) { | |
| if (len <= 0) | |
| return; | |
| ch = fgetc(f); | |
| if (ch == EOF || ch == '\n') | |
| break; | |
| *s++ = ch; | |
| –len; | |
| } | |
| while (–len >= 0) | |
| *s++ = ' '; | |
| if (ch != EOF) | |
| ungetc(ch, f); | |
| } | |
| Void P_readlnpaoc(f, s, len) | |
| FILE *f; | |
| char *s; | |
| int len; | |
| { | |
| int ch; | |
| for (;;) { | |
| ch = fgetc(f); | |
| if (ch == EOF || ch == '\n') | |
| break; | |
| if (len > 0) { | |
| *s++ = ch; | |
| –len; | |
| } | |
| } | |
| while (–len >= 0) | |
| *s++ = ' '; | |
| } | |
| /* Compute maximum legal "seek" index in file (0-based). */ | |
| long P_maxpos(f) | |
| FILE *f; | |
| { | |
| long savepos = ftell(f); | |
| long val; | |
| if (fseek(f, 0L, SEEK_END)) | |
| return -1; | |
| val = ftell(f); | |
| if (fseek(f, savepos, SEEK_SET)) | |
| return -1; | |
| return val; | |
| } | |
| /* Use packed array of char for a file name. */ | |
| Char *P_trimname(fn, len) | |
| register Char *fn; | |
| register int len; | |
| { | |
| static Char fnbuf[256]; | |
| register Char *cp = fnbuf; | |
| while (–len >= 0 && *fn && !isspace(*fn)) | |
| *cp++ = *fn++; | |
| *cp = 0; | |
| return fnbuf; | |
| } | |
| /* Pascal's "memavail" doesn't make much sense in Unix with virtual memory. | |
| We fix memory size as 10Meg as a reasonable compromise. */ | |
| long memavail() | |
| { | |
| return 10000000; /* worry about this later! */ | |
| } | |
| long maxavail() | |
| { | |
| return memavail(); | |
| } | |
| /* Sets are stored as an array of longs. S[0] is the size of the set; | |
| S[N] is the N'th 32-bit chunk of the set. S[0] equals the maximum | |
| I such that S[I] is nonzero. S[0] is zero for an empty set. Within | |
| each long, bits are packed from lsb to msb. The first bit of the | |
| set is the element with ordinal value 0. (Thus, for a "set of 5..99", | |
| the lowest five bits of the first long are unused and always zero.) */ | |
| /* (Sets with 32 or fewer elements are normally stored as plain longs.) */ | |
| long *P_setunion(d, s1, s2) /* d := s1 + s2 */ | |
| register long *d, *s1, *s2; | |
| { | |
| long *dbase = d++; | |
| register int sz1 = *s1++, sz2 = *s2++; | |
| while (sz1 > 0 && sz2 > 0) { | |
| *d++ = *s1++ | *s2++; | |
| sz1–, sz2–; | |
| } | |
| while (–sz1 >= 0) | |
| *d++ = *s1++; | |
| while (–sz2 >= 0) | |
| *d++ = *s2++; | |
| *dbase = d – dbase – 1; | |
| return dbase; | |
| } | |
| long *P_setint(d, s1, s2) /* d := s1 * s2 */ | |
| register long *d, *s1, *s2; | |
| { | |
| long *dbase = d++; | |
| register int sz1 = *s1++, sz2 = *s2++; | |
| while (–sz1 >= 0 && –sz2 >= 0) | |
| *d++ = *s1++ & *s2++; | |
| while (–d > dbase && !*d) ; | |
| *dbase = d – dbase; | |
| return dbase; | |
| } | |
| long *P_setdiff(d, s1, s2) /* d := s1 – s2 */ | |
| register long *d, *s1, *s2; | |
| { | |
| long *dbase = d++; | |
| register int sz1 = *s1++, sz2 = *s2++; | |
| while (–sz1 >= 0 && –sz2 >= 0) | |
| *d++ = *s1++ & ~*s2++; | |
| if (sz1 >= 0) { | |
| while (sz1– >= 0) | |
| *d++ = *s1++; | |
| } | |
| while (–d > dbase && !*d) ; | |
| *dbase = d – dbase; | |
| return dbase; | |
| } | |
| long *P_setxor(d, s1, s2) /* d := s1 / s2 */ | |
| register long *d, *s1, *s2; | |
| { | |
| long *dbase = d++; | |
| register int sz1 = *s1++, sz2 = *s2++; | |
| while (sz1 > 0 && sz2 > 0) { | |
| *d++ = *s1++ ^ *s2++; | |
| sz1–, sz2–; | |
| } | |
| while (–sz1 >= 0) | |
| *d++ = *s1++; | |
| while (–sz2 >= 0) | |
| *d++ = *s2++; | |
| while (–d > dbase && !*d) ; | |
| *dbase = d – dbase; | |
| return dbase; | |
| } | |
| int P_inset(val, s) /* val IN s */ | |
| register unsigned val; | |
| register long *s; | |
| { | |
| register int bit; | |
| bit = val % SETBITS; | |
| val /= SETBITS; | |
| if (val < *s++ && ((1L<<bit) & s[val])) | |
| return 1; | |
| return 0; | |
| } | |
| long *P_addset(s, val) /* s := s + [val] */ | |
| register long *s; | |
| register unsigned val; | |
| { | |
| register long *sbase = s; | |
| register int bit, size; | |
| bit = val % SETBITS; | |
| val /= SETBITS; | |
| size = *s; | |
| if (++val > size) { | |
| s += size; | |
| while (val > size) | |
| *++s = 0, size++; | |
| *sbase = size; | |
| } else | |
| s += val; | |
| *s |= 1L<<bit; | |
| return sbase; | |
| } | |
| long *P_addsetr(s, v1, v2) /* s := s + [v1..v2] */ | |
| register long *s; | |
| register unsigned v1, v2; | |
| { | |
| register long *sbase = s; | |
| register int b1, b2, size; | |
| if ((int)v1 > (int)v2) | |
| return sbase; | |
| b1 = v1 % SETBITS; | |
| v1 /= SETBITS; | |
| b2 = v2 % SETBITS; | |
| v2 /= SETBITS; | |
| size = *s; | |
| v1++; | |
| if (++v2 > size) { | |
| while (v2 > size) | |
| s[++size] = 0; | |
| s[v2] = 0; | |
| *s = v2; | |
| } | |
| s += v1; | |
| if (v1 == v2) { | |
| *s |= (~((-2L)<<(b2-b1))) << b1; | |
| } else { | |
| *s++ |= (-1L) << b1; | |
| while (++v1 < v2) | |
| *s++ = -1; | |
| *s |= ~((-2L) << b2); | |
| } | |
| return sbase; | |
| } | |
| long *P_remset(s, val) /* s := s – [val] */ | |
| register long *s; | |
| register unsigned val; | |
| { | |
| register int bit; | |
| bit = val % SETBITS; | |
| val /= SETBITS; | |
| if (++val <= *s) { | |
| if (!(s[val] &= ~(1L<<bit))) | |
| while (*s && !s[*s]) | |
| (*s)–; | |
| } | |
| return s; | |
| } | |
| int P_setequal(s1, s2) /* s1 = s2 */ | |
| register long *s1, *s2; | |
| { | |
| register int size = *s1++; | |
| if (*s2++ != size) | |
| return 0; | |
| while (–size >= 0) { | |
| if (*s1++ != *s2++) | |
| return 0; | |
| } | |
| return 1; | |
| } | |
| int P_subset(s1, s2) /* s1 <= s2 */ | |
| register long *s1, *s2; | |
| { | |
| register int sz1 = *s1++, sz2 = *s2++; | |
| if (sz1 > sz2) | |
| return 0; | |
| while (–sz1 >= 0) { | |
| if (*s1++ & ~*s2++) | |
| return 0; | |
| } | |
| return 1; | |
| } | |
| long *P_setcpy(d, s) /* d := s */ | |
| register long *d, *s; | |
| { | |
| register long *save_d = d; | |
| #ifdef SETCPY_MEMCPY | |
| memcpy(d, s, (*s + 1) * sizeof(long)); | |
| #else | |
| register int i = *s + 1; | |
| while (–i >= 0) | |
| *d++ = *s++; | |
| #endif | |
| return save_d; | |
| } | |
| /* s is a "smallset", i.e., a 32-bit or less set stored | |
| directly in a long. */ | |
| long *P_expset(d, s) /* d := s */ | |
| register long *d; | |
| register long s; | |
| { | |
| if (s) { | |
| d[1] = s; | |
| *d = 1; | |
| } else | |
| *d = 0; | |
| return d; | |
| } | |
| long P_packset(s) /* convert s to a small-set */ | |
| register long *s; | |
| { | |
| if (*s++) | |
| return *s; | |
| else | |
| return 0; | |
| } | |
| /* Oregon Software Pascal extensions, courtesy of William Bader */ | |
| int P_getcmdline(l, h, line) | |
| int l, h; | |
| Char *line; | |
| { | |
| int i, len; | |
| char *s; | |
| h = h – l + 1; | |
| len = 0; | |
| for(i = 1; i < P_argc; i++) { | |
| s = P_argv[i]; | |
| while (*s) { | |
| if (len >= h) return len; | |
| line[len++] = *s++; | |
| } | |
| if (len >= h) return len; | |
| line[len++] = ' '; | |
| } | |
| return len; | |
| } | |
| Void TimeStamp(Day, Month, Year, Hour, Min, Sec) | |
| int *Day, *Month, *Year, *Hour, *Min, *Sec; | |
| { | |
| #ifndef NO_TIME | |
| struct tm *tm; | |
| long clock; | |
| time(&clock); | |
| tm = localtime(&clock); | |
| *Day = tm->tm_mday; | |
| *Month = tm->tm_mon + 1; /* Jan = 0 */ | |
| *Year = tm->tm_year; | |
| if (*Year < 1900) | |
| *Year += 1900; /* year since 1900 */ | |
| *Hour = tm->tm_hour; | |
| *Min = tm->tm_min; | |
| *Sec = tm->tm_sec; | |
| #endif | |
| } | |
| Void VAXdate(s) | |
| char *s; | |
| { | |
| long clock; | |
| char *c; | |
| int i; | |
| static int where[] = {8, 9, 0, 4, 5, 6, 0, 20, 21, 22, 23}; | |
| time(&clock); | |
| c = ctime(&clock); | |
| for (i = 0; i < 11; i++) | |
| s[i] = my_toupper(c[where[i]]); | |
| s[2] = '-'; | |
| s[6] = '-'; | |
| } | |
| Void VAXtime(s) | |
| char *s; | |
| { | |
| long clock; | |
| char *c; | |
| int i; | |
| time(&clock); | |
| c = ctime(&clock); | |
| for (i = 0; i < 8; i++) | |
| s[i] = c[i+11]; | |
| s[8] = '.'; | |
| s[9] = '0'; | |
| s[10] = '0'; | |
| } | |
| /* SUN Berkeley Pascal extensions */ | |
| Void P_sun_argv(s, len, n) | |
| register char *s; | |
| register int len, n; | |
| { | |
| register char *cp; | |
| if ((unsigned)n < P_argc) | |
| cp = P_argv[n]; | |
| else | |
| cp = ""; | |
| while (*cp && –len >= 0) | |
| *s++ = *cp++; | |
| while (–len >= 0) | |
| *s++ = ' '; | |
| } | |
| int _OutMem() | |
| { | |
| return _Escape(-2); | |
| } | |
| int _CaseCheck() | |
| { | |
| return _Escape(-9); | |
| } | |
| int _NilCheck() | |
| { | |
| return _Escape(-3); | |
| } | |
| /* The following is suitable for the HP Pascal operating system. | |
| It might want to be revised when emulating another system. */ | |
| char *_ShowEscape(buf, code, ior, prefix) | |
| char *buf, *prefix; | |
| int code, ior; | |
| { | |
| char *bufp; | |
| if (prefix && *prefix) { | |
| strcpy(buf, prefix); | |
| strcat(buf, ": "); | |
| bufp = buf + strlen(buf); | |
| } else { | |
| bufp = buf; | |
| } | |
| if (code == -10) { | |
| sprintf(bufp, "Pascal system I/O error %d", ior); | |
| switch (ior) { | |
| case 3: | |
| strcat(buf, " (illegal I/O request)"); | |
| break; | |
| case 7: | |
| strcat(buf, " (bad file name)"); | |
| break; | |
| case FileNotFound: /*10*/ | |
| strcat(buf, " (file not found)"); | |
| break; | |
| case FileNotOpen: /*13*/ | |
| strcat(buf, " (file not open)"); | |
| break; | |
| case BadInputFormat: /*14*/ | |
| strcat(buf, " (bad input format)"); | |
| break; | |
| case 24: | |
| strcat(buf, " (not open for reading)"); | |
| break; | |
| case 25: | |
| strcat(buf, " (not open for writing)"); | |
| break; | |
| case 26: | |
| strcat(buf, " (not open for direct access)"); | |
| break; | |
| case 28: | |
| strcat(buf, " (string subscript out of range)"); | |
| break; | |
| case EndOfFile: /*30*/ | |
| strcat(buf, " (end-of-file)"); | |
| break; | |
| case FileWriteError: /*38*/ | |
| strcat(buf, " (file write error)"); | |
| break; | |
| } | |
| } else { | |
| sprintf(bufp, "Pascal system error %d", code); | |
| switch (code) { | |
| case -2: | |
| strcat(buf, " (out of memory)"); | |
| break; | |
| case -3: | |
| strcat(buf, " (reference to NIL pointer)"); | |
| break; | |
| case -4: | |
| strcat(buf, " (integer overflow)"); | |
| break; | |
| case -5: | |
| strcat(buf, " (divide by zero)"); | |
| break; | |
| case -6: | |
| strcat(buf, " (real math overflow)"); | |
| break; | |
| case -8: | |
| strcat(buf, " (value range error)"); | |
| break; | |
| case -9: | |
| strcat(buf, " (CASE value range error)"); | |
| break; | |
| case -12: | |
| strcat(buf, " (bus error)"); | |
| break; | |
| case -20: | |
| strcat(buf, " (stopped by user)"); | |
| break; | |
| } | |
| } | |
| return buf; | |
| } | |
| int _Escape(code) | |
| int code; | |
| { | |
| char buf[100]; | |
| P_escapecode = code; | |
| if (__top_jb) { | |
| __p2c_jmp_buf *jb = __top_jb; | |
| __top_jb = jb->next; | |
| longjmp(jb->jbuf, 1); | |
| } | |
| if (code == 0) | |
| exit(EXIT_SUCCESS); | |
| if (code == -1) | |
| exit(EXIT_FAILURE); | |
| fprintf(stderr, "%s\n", _ShowEscape(buf, P_escapecode, P_ioresult, "")); | |
| exit(EXIT_FAILURE); | |
| } | |
| int _EscIO(code) | |
| int code; | |
| { | |
| P_ioresult = code; | |
| return _Escape(-10); | |
| } | |
| /* End. */ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/csh -fb | |
| if ($#argv == 0) then | |
| echo "No filename given !" | |
| exit | |
| endif | |
| if ($#argv > 1) then | |
| echo "Too many parameters !" | |
| exit | |
| endif | |
| rm -f $1.pc prr prd | |
| pcom < $1.p && cp -f prr $1.pc && mv -f prr prd && pint && mv -f prr $1.out | |
| rm -f prd prr |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @echo off | |
| if "%1" == "" goto error | |
| del %1.pc %1.out prr prd > NUL: 2>&1 | |
| pcom < %1.p && copy prr %1.pc > NUL: 2>&1 && move prr prd > NUL: 2>&1 && pint && move prr %1.out > NUL: 2>&1 | |
| del prd prr > NUL: 2>&1 | |
| goto end | |
| :error | |
| echo No filename given ! | |
| :end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Output from p2c, the Pascal-to-C translator */ | |
| /* From input file "pcom.p" */ | |
| /* P2c command-line options: -M0 (due to bug in p2c) */ | |
| /* P2c options: | |
| Language BERK | |
| StructFiles 1 */ | |
| /* P2c produced macro calls "BUFEOF(stdin)", | |
| which were edited to "P_eof(stdin)" */ | |
| /* Translation and editing done by I.J.A. van Geel | |
| e-mail: I.J.A.vanGeel@twi.tudelft.nl */ | |
| /* Date: august 22 1996 */ | |
| /*$c+,t-,d-,l-*/ | |
| /************************************************ | |
| * * | |
| * Portable Pascal compiler * | |
| * ************************ * | |
| * * | |
| *Pascal P4 * | |
| * * | |
| * Authors: * | |
| * Urs Ammann * | |
| * Kesav Nori * | |
| * Christian Jacobi * | |
| * Address: * | |
| * Institut Fuer Informatik * | |
| * Eidg. Technische Hochschule * | |
| * CH-8096 Zuerich * | |
| * * | |
| * This code is fully documented in the book * | |
| * "Pascal Implementation" * | |
| * by Steven Pemberton and Martin Daniels * | |
| * published by Ellis Horwood, Chichester, UK * | |
| * ISBN: 0-13-653-0311 * | |
| * (also available in Japanese) * | |
| * * | |
| * Steven Pemberton, CWI/AA, * | |
| * Kruislaan 413, 1098 SJ Amsterdam, NL * | |
| * Steven.Pemberton@cwi.nl * | |
| * * | |
| ************************************************/ | |
| #include "p2c.h" | |
| #define displimit 20 | |
| #define maxlevel 10 | |
| #define intsize 1 | |
| #define intal 1 | |
| #define realsize 1 | |
| #define realal 1 | |
| #define charsize 1 | |
| #define charal 1 | |
| #define charmax 1 | |
| #define boolsize 1 | |
| #define boolal 1 | |
| #define ptrsize 1 | |
| #define adral 1 | |
| #define setsize 1 | |
| #define setal 1 | |
| #define stackal 1 | |
| #define stackelsize 1 | |
| #define strglgth 16 | |
| #define sethigh 47 | |
| #define setlow 0 | |
| #define ordmaxchar 63 | |
| #define ordminchar 0 | |
| #define maxint 32767 | |
| #define lcaftermarkstack 5 | |
| #define fileal charal | |
| /* stackelsize = minimum size for 1 stackelement | |
| = k*stackal | |
| stackal = scm(all other al-constants) | |
| charmax = scm(charsize,charal) | |
| scm = smallest common multiple | |
| lcaftermarkstack >= 4*ptrsize+max(x-size) | |
| = k1*stackelsize */ | |
| #define maxstack 1 | |
| #define parmal stackal | |
| #define parmsize stackelsize | |
| #define recal stackal | |
| #define filebuffer 4 | |
| #define maxaddr maxint | |
| /*describing:*/ | |
| /*************/ | |
| /*basic symbols*/ | |
| /***************/ | |
| typedef enum { | |
| ident, intconst, realconst, stringconst, notsy, mulop, addop, relop, | |
| lparent, rparent, lbrack, rbrack, comma, semicolon, period, arrow, colon, | |
| becomes, labelsy, constsy, typesy, varsy, funcsy, progsy, procsy, setsy, | |
| packedsy, arraysy, recordsy, filesy, forwardsy, beginsy, ifsy, casesy, | |
| repeatsy, whilesy, forsy, withsy, gotosy, endsy, elsesy, untilsy, ofsy, | |
| dosy, tosy, downtosy, thensy, othersy | |
| } symbol; | |
| typedef enum { | |
| mul, rdiv, andop, idiv, imod, plus, minus, orop, ltop, leop, geop, gtop, | |
| neop, eqop, inop, noop | |
| } operator_; | |
| typedef long setofsys[3]; | |
| typedef enum { | |
| letter, number, special, illegal, chstrquo, chcolon, chperiod, chlt, chgt, | |
| chlparen, chspace | |
| } chtp; | |
| /*constants*/ | |
| /***********/ | |
| typedef long setty[sethigh / 32 + 2]; | |
| typedef enum { | |
| reel, pset, strg | |
| } cstclass; | |
| typedef struct constant { | |
| cstclass cclass; | |
| union { | |
| Char rval[strglgth]; | |
| setty pval; | |
| struct { | |
| char slgth; | |
| Char sval[strglgth]; | |
| } U2; | |
| } UU; | |
| } constant; | |
| typedef struct valu { | |
| /*intval never set nor tested*/ | |
| boolean intval; | |
| union { | |
| long ival; | |
| constant *valp; | |
| } UU; | |
| } valu; | |
| /*data structures*/ | |
| /*****************/ | |
| typedef char levrange; | |
| typedef short addrrange; | |
| typedef enum { | |
| scalar, subrange, pointer, power, arrays, records, files, tagfld, variant | |
| } structform; | |
| typedef enum { | |
| standard, declared | |
| } declkind; | |
| typedef struct structure { | |
| unsigned marked : 1; /*for test phase only*/ | |
| unsigned size : 15; | |
| /* p2c: pcom.p, line 121: Note: | |
| * Field width for form assumes enum structform has 9 elements [105] */ | |
| unsigned form : 4; | |
| union { | |
| struct { | |
| /* p2c: pcom.p, line 122: Note: | |
| * Field width for scalkind assumes enum declkind has 2 elements [105] */ | |
| unsigned scalkind : 1; | |
| union { | |
| struct identifier *fconst; | |
| } UU; | |
| } U0; | |
| struct { | |
| struct structure *rangetype; | |
| valu min, max; | |
| } U1; | |
| struct structure *eltype; | |
| struct structure *elset; | |
| struct { | |
| struct structure *aeltype, *inxtype; | |
| } U4; | |
| struct { | |
| struct identifier *fstfld; | |
| struct structure *recvar; | |
| } U5; | |
| struct structure *filtype; | |
| struct { | |
| struct identifier *tagfieldp; | |
| struct structure *fstvar; | |
| } U7; | |
| struct { | |
| struct structure *nxtvar, *subvar; | |
| valu varval; | |
| } U8; | |
| } UU; | |
| } structure; | |
| /*names*/ | |
| /*******/ | |
| typedef enum { | |
| types, konst, vars, field, proc, func | |
| } idclass; | |
| typedef long setofids; | |
| typedef enum { | |
| actual, formal | |
| } idkind; | |
| typedef Char alpha[8]; | |
| typedef struct identifier { | |
| alpha name; | |
| struct identifier *llink, *rlink; | |
| structure *idtype; | |
| struct identifier *next; | |
| /* p2c: pcom.p, line 145: | |
| * Note: Field width for klass assumes enum idclass has 6 elements [105] */ | |
| unsigned klass : 3; | |
| union { | |
| valu values; | |
| struct { | |
| unsigned vkind : 1; | |
| /* p2c: pcom.p, line 148: | |
| * Note: Field width for vkind assumes enum idkind has 2 elements [105] */ | |
| unsigned vlev : 4, vaddr : 15; | |
| } U2; | |
| unsigned fldaddr; | |
| struct { | |
| /* p2c: pcom.p, line 150: Note: | |
| * Field width for pfdeckind assumes enum declkind has 2 elements [105] */ | |
| unsigned pfdeckind : 1; | |
| union { | |
| unsigned key; | |
| struct { | |
| unsigned pflev : 4; | |
| long pfname; | |
| /* p2c: pcom.p, line 153: | |
| * Note: Field width for pfkind assumes enum idkind has 2 elements [105] */ | |
| unsigned pfkind : 1; | |
| union { | |
| struct { | |
| unsigned forwdecl : 1, externl : 1; | |
| } U0; | |
| } UU; | |
| } U1; | |
| } UU; | |
| } U4; | |
| } UU; | |
| } identifier; | |
| typedef char disprange; | |
| typedef enum { | |
| blck, crec, vrec, rec | |
| } where; | |
| /*expressions*/ | |
| /*************/ | |
| typedef enum { | |
| cst, varbl, expr | |
| } attrkind; | |
| typedef enum { | |
| drct, indrct, inxd | |
| } vaccess; | |
| typedef struct attr { | |
| structure *typtr; | |
| attrkind kind; | |
| union { | |
| valu cval; | |
| struct { | |
| vaccess access; | |
| union { | |
| struct { | |
| levrange vlevel; | |
| addrrange dplmt; | |
| } U0; | |
| addrrange idplmt; | |
| } UU; | |
| } U1; | |
| } UU; | |
| } attr; | |
| typedef struct testpointer { | |
| structure *elt1, *elt2; | |
| struct testpointer *lasttestp; | |
| } testpointer; | |
| /*labels*/ | |
| /********/ | |
| typedef struct labl { | |
| struct labl *nextlab; | |
| boolean defined_; | |
| long labval, labname; | |
| } labl; | |
| typedef struct filerec { | |
| alpha filename; | |
| struct filerec *nextfile; | |
| } filerec; | |
| /*————————————————————————-*/ | |
| typedef struct _REC_display { | |
| /*=blck: id is variable id*/ | |
| identifier *fname; | |
| labl *flabel; /*=crec: id is field id in record with*/ | |
| /* p2c: pcom.p, line 254: | |
| * Note: Field width for occur assumes enum where has 4 elements [105] */ | |
| /* constant address*/ | |
| unsigned occur : 2; | |
| union { | |
| struct { | |
| levrange clev; /*=vrec: id is field id in record with*/ | |
| addrrange cdspl; /* variable address*/ | |
| } U1; | |
| addrrange vdspl; | |
| } UU; | |
| } _REC_display; | |
| typedef struct _REC_errlist { | |
| long pos; | |
| unsigned nmr : 9; | |
| } _REC_errlist; | |
| Static _TEXT prr; /* comment this out when compiling with pcom */ | |
| /*returned by source program scanner | |
| insymbol: | |
| **********/ | |
| Static symbol sy; /*last symbol*/ | |
| Static operator_ op; /*classification of last symbol*/ | |
| Static valu val; /*value of last constant*/ | |
| Static long lgth; /*length of last string constant*/ | |
| Static alpha id; /*last identifier (possibly truncated)*/ | |
| Static char kk; /*nr of chars in last identifier*/ | |
| Static Char ch; /*last character*/ | |
| Static boolean eol; /*end of line flag*/ | |
| /*counters:*/ | |
| /***********/ | |
| Static long chcnt; /*character counter*/ | |
| Static addrrange lc, ic; /*data location and instruction counter*/ | |
| Static long linecount; | |
| /*switches:*/ | |
| /***********/ | |
| Static boolean dp; /*declaration part*/ | |
| Static boolean prterr; | |
| /*to allow forward references in pointer type | |
| declaration by suppressing error message*/ | |
| Static boolean list, prcode, prtables; | |
| /*output options for | |
| — source program listing | |
| — printing symbolic code | |
| — displaying ident and struct tables | |
| –> procedure option*/ | |
| Static boolean debug; | |
| /*pointers:*/ | |
| /***********/ | |
| Static structure *parmptr, *intptr, *realptr, *charptr, *boolptr, *nilptr, | |
| *textptr; | |
| /*pointers to entries of standard ids*/ | |
| Static identifier *utypptr, *ucstptr, *uvarptr, *ufldptr, *uprcptr, *ufctptr; | |
| /*pointers to entries for undeclared ids*/ | |
| Static identifier *fwptr; /*head of chain of forw decl type ids*/ | |
| Static filerec *fextfilep; /*head of chain of external files*/ | |
| Static testpointer *globtestp; /*last testpointer*/ | |
| /*bookkeeping of declaration levels:*/ | |
| /************************************/ | |
| Static levrange level; /*current static level*/ | |
| Static disprange disx; /*level of last id searched by searchid*/ | |
| Static disprange top; /*top of display*/ | |
| /*where: means:*/ | |
| Static _REC_display display[displimit + 1]; /* –> procedure withstatement*/ | |
| /*error messages:*/ | |
| /*****************/ | |
| Static char errinx; /*nr of errors in current source line*/ | |
| Static _REC_errlist errlist[10]; | |
| Static boolean input_ok = true; | |
| /*expression compilation:*/ | |
| /*************************/ | |
| Static attr gattr; /*describes the expr currently compiled*/ | |
| /*structured constants:*/ | |
| /***********************/ | |
| Static setofsys constbegsys, simptypebegsys, typebegsys, blockbegsys, | |
| selectsys, facbegsys, statbegsys, typedels; | |
| Static chtp chartp[256]; | |
| /*nr. of res. words*/ | |
| Static alpha rw[35]; | |
| /*nr. of res. words + 1*/ | |
| Static char frw[9]; | |
| /*nr. of res. words*/ | |
| Static symbol rsy[35]; | |
| Static symbol ssy[256]; | |
| /*nr. of res. words*/ | |
| Static operator_ rop[35]; | |
| Static operator_ sop[256]; | |
| Static alpha na[35]; | |
| Static Char mn[61][4]; | |
| Static Char sna[23][4]; | |
| Static schar cdx[61]; | |
| Static schar pdx[23]; | |
| Static long ordint[256]; | |
| Static long intlabel, mxint10, digmax; | |
| /*————————————————————————-*/ | |
| Static void mark_(long **p) | |
| { | |
| } | |
| Static void release_(long *p) | |
| { | |
| } | |
| Static void endofline(void) | |
| { | |
| long lastpos, freepos, currpos, currnmr, f, k, FORLIM; | |
| _REC_errlist *WITH; | |
| /*endofline*/ | |
| if (errinx > 0) { /*output error messages*/ | |
| printf("%6ld%9s", linecount, " **** "); | |
| lastpos = 0; | |
| freepos = 1; | |
| FORLIM = errinx; | |
| for (k = 0; k < FORLIM; k++) { | |
| WITH = &errlist[k]; | |
| currpos = WITH->pos; | |
| currnmr = WITH->nmr; | |
| if (currpos == lastpos) | |
| putchar(','); | |
| else { | |
| while (freepos < currpos) { | |
| putchar(' '); | |
| freepos++; | |
| } | |
| putchar('^'); | |
| lastpos = currpos; | |
| } | |
| if (currnmr < 10) | |
| f = 1; | |
| else if (currnmr < 100) | |
| f = 2; | |
| else | |
| f = 3; | |
| printf("%*ld", (int)f, currnmr); | |
| freepos += f + 1; | |
| } | |
| putchar('\n'); | |
| errinx = 0; | |
| } | |
| linecount++; | |
| if (list & (!P_eof(stdin))) { | |
| printf("%6ld%2s", linecount, " "); | |
| if (dp) | |
| printf("%7d", lc); | |
| else | |
| printf("%7d", ic); | |
| putchar(' '); | |
| } | |
| chcnt = 0; | |
| } | |
| Static void error(long ferrnr) | |
| { | |
| /*error*/ | |
| if (errinx >= 9) { | |
| errlist[9].nmr = 255; | |
| errinx = 10; | |
| } else { | |
| errinx++; | |
| errlist[errinx – 1].nmr = ferrnr; | |
| } | |
| errlist[errinx – 1].pos = chcnt; | |
| input_ok = false; | |
| } | |
| /* Local variables for insymbol: */ | |
| struct LOC_insymbol { | |
| boolean test; | |
| } ; | |
| Local void nextch(struct LOC_insymbol *LINK) | |
| { | |
| if (eol) { | |
| if (list) | |
| putchar('\n'); | |
| endofline(); | |
| } | |
| if (P_eof(stdin)) { | |
| printf(" *** eof encountered\n"); | |
| LINK->test = false; | |
| return; | |
| } | |
| eol = P_eoln(stdin); | |
| ch = fgetc (stdin); | |
| if (ch == '\n') | |
| ch = ' '; | |
| else | |
| if (isupper (ch)) | |
| ch = tolower (ch); | |
| if (list) | |
| putchar(ch); | |
| chcnt++; | |
| } | |
| Local void options(struct LOC_insymbol *LINK) | |
| { | |
| /*options*/ | |
| do { | |
| nextch(LINK); | |
| if (ch != '*') { | |
| if (ch == 't') { | |
| nextch(LINK); | |
| prtables = (ch == '+'); | |
| } else { | |
| if (ch == 'l') { | |
| nextch(LINK); | |
| list = (ch == '+'); | |
| if (!list) | |
| putchar('\n'); | |
| } else { | |
| if (ch == 'd') { | |
| nextch(LINK); | |
| debug = (ch == '+'); | |
| } else { | |
| if (ch == 'c') { | |
| nextch(LINK); | |
| prcode = (ch == '+'); | |
| } | |
| } | |
| } | |
| } | |
| nextch(LINK); | |
| } | |
| } while (ch == ','); | |
| } | |
| Static void insymbol(void) | |
| { | |
| /*read next basic symbol of source program and return its | |
| description in the global variables sy, op, id, val and lgth*/ | |
| struct LOC_insymbol V; | |
| long i, k; | |
| Char digit[strglgth]; | |
| Char string[strglgth]; | |
| constant *lvp; | |
| long FORLIM; | |
| /*insymbol*/ | |
| _L1: | |
| do { | |
| while ((ch == ' ' || ch == '\t') && !eol) | |
| nextch(&V); | |
| V.test = eol; | |
| if (V.test) | |
| nextch(&V); | |
| } while (V.test); | |
| /* | |
| if (P_eof (stdin)) { | |
| sy = othersy; | |
| op = noop; | |
| error(399); | |
| return; | |
| } | |
| */ | |
| if (chartp[ch] == illegal) { | |
| sy = othersy; | |
| op = noop; | |
| error(399); | |
| nextch(&V); | |
| return; | |
| } | |
| switch (chartp[ch]) { | |
| case letter: | |
| k = 0; | |
| do { | |
| if (k < 8) { | |
| k++; | |
| id[k – 1] = ch; | |
| } | |
| nextch(&V); | |
| } while (((1L << ((long)chartp[ch])) & ((1L << ((long)special)) | | |
| (1L << ((long)illegal)) | (1L << ((long)chstrquo)) | | |
| (1L << ((long)chcolon)) | (1L << ((long)chperiod)) | | |
| (1L << ((long)chlt)) | (1L << ((long)chgt)) | | |
| (1L << ((long)chlparen)) | (1L << ((long)chspace)))) == 0); | |
| if (k >= kk) | |
| kk = k; | |
| else { | |
| do { | |
| id[kk – 1] = ' '; | |
| kk–; | |
| } while (kk != k); | |
| } | |
| FORLIM = frw[k] – 2; | |
| for (i = frw[k – 1] – 1; i <= FORLIM; i++) { | |
| if (!strncmp(rw[i], id, sizeof(alpha))) { | |
| sy = rsy[i]; | |
| op = rop[i]; | |
| goto _L2; | |
| } | |
| } | |
| sy = ident; | |
| op = noop; | |
| _L2: ; | |
| break; | |
| case number: | |
| op = noop; | |
| i = 0; | |
| do { | |
| i++; | |
| if (i <= digmax) | |
| digit[i – 1] = ch; | |
| nextch(&V); | |
| } while (chartp[ch] == number); | |
| if (((ch == '.') & (P_peek(stdin) != '.')) || ch == 'e') { | |
| k = i; | |
| if (ch == '.') { | |
| k++; | |
| if (k <= digmax) | |
| digit[k – 1] = ch; | |
| nextch(&V); /*if ch = '.' then begin ch := ':'; goto 3 end;*/ | |
| if (chartp[ch] != number) | |
| error(201); | |
| else { | |
| do { | |
| k++; | |
| if (k <= digmax) | |
| digit[k – 1] = ch; | |
| nextch(&V); | |
| } while (chartp[ch] == number); | |
| } | |
| } | |
| if (ch == 'e') { | |
| k++; | |
| if (k <= digmax) | |
| digit[k – 1] = ch; | |
| nextch(&V); | |
| if (ch == '+' || ch == '-') { | |
| k++; | |
| if (k <= digmax) | |
| digit[k – 1] = ch; | |
| nextch(&V); | |
| } | |
| if (chartp[ch] != number) | |
| error(201); | |
| else { | |
| do { | |
| k++; | |
| if (k <= digmax) | |
| digit[k – 1] = ch; | |
| nextch(&V); | |
| } while (chartp[ch] == number); | |
| } | |
| } | |
| /* p2c: pcom.p, line 454: | |
| * Note: No SpecialMalloc form known for CONSTANT.REEL [187] */ | |
| lvp = Malloc(sizeof(constant)); | |
| sy = realconst; | |
| lvp->cclass = reel; | |
| for (i = 0; i < strglgth; i++) | |
| lvp->UU.rval[i] = ' '; | |
| if (k <= digmax) { | |
| for (i = 2; i <= k + 1; i++) | |
| lvp->UU.rval[i – 1] = digit[i – 2]; | |
| } else { | |
| error(203); | |
| lvp->UU.rval[1] = '0'; | |
| lvp->UU.rval[2] = '.'; | |
| lvp->UU.rval[3] = '0'; | |
| } | |
| val.UU.valp = lvp; | |
| } else { | |
| if (i > digmax) { | |
| error(203); | |
| val.UU.ival = 0; | |
| } else { | |
| val.UU.ival = 0; | |
| for (k = 0; k < i; k++) { | |
| if (val.UU.ival <= mxint10) | |
| val.UU.ival = val.UU.ival * 10 + ordint[digit[k]]; | |
| else { | |
| error(203); | |
| val.UU.ival = 0; | |
| } | |
| } | |
| sy = intconst; | |
| } | |
| } | |
| break; | |
| case chstrquo: | |
| lgth = 0; | |
| sy = stringconst; | |
| op = noop; | |
| do { | |
| do { | |
| nextch(&V); | |
| lgth++; | |
| if (lgth <= strglgth) | |
| string[lgth – 1] = ch; | |
| } while (!(eol || ch == '\'')); | |
| if (eol) | |
| error(202); | |
| else | |
| nextch(&V); | |
| } while (ch == '\''); | |
| lgth–; /*now lgth = nr of chars in string*/ | |
| if (lgth == 0) | |
| error(205); | |
| else { | |
| if (lgth == 1) | |
| val.UU.ival = string[0]; | |
| else { | |
| lvp = Malloc(sizeof(constant)); | |
| lvp->cclass = strg; | |
| if (lgth > strglgth) { | |
| error(399); | |
| lgth = strglgth; | |
| } | |
| lvp->UU.U2.slgth = lgth; | |
| FORLIM = lgth; | |
| for (i = 0; i < FORLIM; i++) | |
| lvp->UU.U2.sval[i] = string[i]; | |
| val.UU.valp = lvp; | |
| } | |
| } | |
| break; | |
| case chcolon: | |
| op = noop; | |
| nextch(&V); | |
| if (ch == '=') { | |
| sy = becomes; | |
| nextch(&V); | |
| } else | |
| sy = colon; | |
| break; | |
| case chperiod: | |
| op = noop; | |
| nextch(&V); | |
| if (ch == '.') { | |
| sy = colon; | |
| nextch(&V); | |
| } else | |
| sy = period; | |
| break; | |
| case chlt: | |
| nextch(&V); | |
| sy = relop; | |
| if (ch == '=') { | |
| op = leop; | |
| nextch(&V); | |
| } else { | |
| if (ch == '>') { | |
| op = neop; | |
| nextch(&V); | |
| } else | |
| op = ltop; | |
| } | |
| break; | |
| case chgt: | |
| nextch(&V); | |
| sy = relop; | |
| if (ch == '=') { | |
| op = geop; | |
| nextch(&V); | |
| } else | |
| op = gtop; | |
| break; | |
| case chlparen: | |
| nextch(&V); | |
| if (ch == '*') { | |
| nextch(&V); | |
| if (ch == '$') | |
| options(&V); | |
| do { | |
| while ((ch != '*') & (!P_eof(stdin))) | |
| nextch(&V); | |
| nextch(&V); | |
| } while (!((ch == ')') | P_eof(stdin))); | |
| nextch(&V); | |
| goto _L1; | |
| } | |
| sy = lparent; | |
| op = noop; | |
| break; | |
| case special: | |
| sy = ssy[ch]; | |
| op = sop[ch]; | |
| nextch(&V); | |
| break; | |
| case chspace: | |
| sy = othersy; | |
| break; | |
| }/*case*/ | |
| /* p2c: pcom.p, line 493: | |
| * Note: No SpecialMalloc form known for CONSTANT.STRG [187] */ | |
| } | |
| Static void enterid(identifier *fcp) | |
| { | |
| /*enter id pointed at by fcp into the name-table, | |
| which on each declaration level is organised as | |
| an unbalanced binary tree*/ | |
| alpha nam; | |
| identifier *lcp, *lcp1; | |
| boolean lleft; | |
| /*enterid*/ | |
| memcpy(nam, fcp->name, sizeof(alpha)); | |
| lcp = display[top].fname; | |
| if (lcp == NULL) | |
| display[top].fname = fcp; | |
| else { | |
| do { | |
| lcp1 = lcp; | |
| if (!strncmp(lcp->name, nam, sizeof(alpha))) | |
| { /*name conflict, follow right link*/ | |
| error(101); | |
| lcp = lcp->rlink; | |
| lleft = false; | |
| } else { | |
| if (strncmp(lcp->name, nam, sizeof(alpha)) < 0) { | |
| lcp = lcp->rlink; | |
| lleft = false; | |
| } else { | |
| lcp = lcp->llink; | |
| lleft = true; | |
| } | |
| } | |
| } while (lcp != NULL); | |
| if (lleft) | |
| lcp1->llink = fcp; | |
| else | |
| lcp1->rlink = fcp; | |
| } | |
| fcp->llink = NULL; | |
| fcp->rlink = NULL; | |
| } | |
| Static void searchsection(identifier *fcp, identifier **fcp1) | |
| { | |
| /*to find record fields and forward declared procedure id's | |
| –> procedure proceduredeclaration | |
| –> procedure selector*/ | |
| /*searchsection*/ | |
| while (fcp != NULL) { | |
| if (!strncmp(fcp->name, id, sizeof(alpha))) | |
| goto _L1; | |
| if (strncmp(fcp->name, id, sizeof(alpha)) < 0) | |
| fcp = fcp->rlink; | |
| else | |
| fcp = fcp->llink; | |
| } | |
| _L1: | |
| *fcp1 = fcp; | |
| } | |
| Static void searchid(setofids fidcls, identifier **fcp) | |
| { | |
| identifier *lcp; | |
| /*searchid*/ | |
| for (disx = top; disx >= 0; disx–) { | |
| lcp = display[disx].fname; | |
| while (lcp != NULL) { | |
| if (strncmp(lcp->name, id, sizeof(alpha))) { | |
| if (strncmp(lcp->name, id, sizeof(alpha)) < 0) | |
| lcp = lcp->rlink; | |
| else | |
| lcp = lcp->llink; | |
| continue; | |
| } | |
| if (((1L << lcp->klass) & fidcls) != 0) | |
| goto _L1; | |
| if (prterr) | |
| error(103); | |
| lcp = lcp->rlink; | |
| } | |
| } | |
| /*search not successful; suppress error message in case | |
| of forward referenced type id in pointer type definition | |
| –> procedure simpletype*/ | |
| if (prterr) { | |
| error(104); | |
| /*to avoid returning nil, reference an entry | |
| for an undeclared id of appropriate class | |
| –> procedure enterundecl*/ | |
| if (((1L << ((long)types)) & fidcls) != 0) | |
| lcp = utypptr; | |
| else { | |
| if (((1L << ((long)vars)) & fidcls) != 0) | |
| lcp = uvarptr; | |
| else { | |
| if (((1L << ((long)field)) & fidcls) != 0) | |
| lcp = ufldptr; | |
| else { | |
| if (((1L << ((long)konst)) & fidcls) != 0) | |
| lcp = ucstptr; | |
| else { | |
| if (((1L << ((long)proc)) & fidcls) != 0) | |
| lcp = uprcptr; | |
| else | |
| lcp = ufctptr; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| _L1: | |
| *fcp = lcp; | |
| } | |
| Static void getbounds(structure *fsp, long *fmin, long *fmax) | |
| { | |
| /*get internal bounds of subrange or scalar type*/ | |
| /*assume fsp<>intptr and fsp<>realptr*/ | |
| /*getbounds*/ | |
| *fmin = 0; | |
| *fmax = 0; | |
| if (fsp == NULL) | |
| return; | |
| if ((structform)fsp->form == subrange) { | |
| *fmin = fsp->UU.U1.min.UU.ival; | |
| *fmax = fsp->UU.U1.max.UU.ival; | |
| return; | |
| } | |
| if (fsp == charptr) { | |
| *fmin = ordminchar; | |
| *fmax = ordmaxchar; | |
| } else { | |
| if (fsp->UU.U0.UU.fconst != NULL) | |
| *fmax = fsp->UU.U0.UU.fconst->UU.values.UU.ival; | |
| } | |
| } | |
| Static long alignquot(structure *fsp) | |
| { | |
| long Result; | |
| /*alignquot*/ | |
| Result = 1; | |
| if (fsp == NULL) | |
| return Result; | |
| switch ((structform)fsp->form) { | |
| case scalar: | |
| if (fsp == intptr) | |
| Result = intal; | |
| else if (fsp == boolptr) | |
| Result = boolal; | |
| else if ((declkind)fsp->UU.U0.scalkind == declared) | |
| Result = intal; | |
| else if (fsp == charptr) | |
| Result = charal; | |
| else if (fsp == realptr) | |
| Result = realal; | |
| else | |
| Result = parmal; | |
| break; | |
| case subrange: | |
| Result = alignquot(fsp->UU.U1.rangetype); | |
| break; | |
| case pointer: | |
| Result = adral; | |
| break; | |
| case power: | |
| Result = setal; | |
| break; | |
| case files: | |
| Result = fileal; | |
| break; | |
| case arrays: | |
| Result = alignquot(fsp->UU.U4.aeltype); | |
| break; | |
| case records: | |
| Result = recal; | |
| break; | |
| case variant: | |
| case tagfld: | |
| error(501); | |
| break; | |
| } | |
| return Result; | |
| /*parmptr*/ | |
| } | |
| Static void align(structure *fsp, addrrange *flc) | |
| { | |
| long k, l; | |
| /*align*/ | |
| k = alignquot(fsp); | |
| l = *flc – 1; | |
| *flc = l + k – (k + l) % k; | |
| } | |
| /* Local variables for printtables: */ | |
| struct LOC_printtables { | |
| disprange lim; | |
| } ; | |
| Local void followctp(identifier *fp, struct LOC_printtables *LINK); | |
| Local void markctp(identifier *fp); | |
| Local void markstp(structure *fp) | |
| { | |
| /*mark data structures, prevent cycles*/ | |
| /*markstp*/ | |
| if (fp == NULL) | |
| return; | |
| fp->marked = true; | |
| switch ((structform)fp->form) { /*with*/ | |
| case scalar: | |
| /* blank case */ | |
| break; | |
| case subrange: | |
| markstp(fp->UU.U1.rangetype); | |
| break; | |
| case pointer: | |
| /* blank case */ | |
| break; | |
| /*don't mark eltype: cycle possible; will be marked | |
| anyway, if fp = true*/ | |
| case power: | |
| markstp(fp->UU.elset); | |
| break; | |
| case arrays: | |
| markstp(fp->UU.U4.aeltype); | |
| markstp(fp->UU.U4.inxtype); | |
| break; | |
| case records: | |
| markctp(fp->UU.U5.fstfld); | |
| markstp(fp->UU.U5.recvar); | |
| break; | |
| case files: | |
| markstp(fp->UU.filtype); | |
| break; | |
| case tagfld: | |
| markstp(fp->UU.U7.fstvar); | |
| break; | |
| case variant: | |
| markstp(fp->UU.U8.nxtvar); | |
| markstp(fp->UU.U8.subvar); | |
| break; | |
| }/*case*/ | |
| } | |
| Local void markctp(identifier *fp) | |
| { | |
| /*markctp*/ | |
| if (fp == NULL) | |
| return; | |
| markctp(fp->llink); | |
| markctp(fp->rlink); | |
| markstp(fp->idtype); | |
| } | |
| Local void marker(struct LOC_printtables *LINK) | |
| { | |
| /*mark data structure entries to avoid multiple printout*/ | |
| long i, FORLIM; | |
| /*marker*/ | |
| FORLIM = LINK->lim; | |
| for (i = top; i >= FORLIM; i–) | |
| markctp(display[i].fname); | |
| } | |
| Local void followstp(structure *fp, struct LOC_printtables *LINK) | |
| { | |
| /*followstp*/ | |
| if (fp == NULL) | |
| return; | |
| if (!fp->marked) { | |
| return; | |
| } /*if marked*/ | |
| fp->marked = false; | |
| printf("%4c%6ld%10d", ' ', (long)fp, fp->size); | |
| switch ((structform)fp->form) { | |
| case scalar: | |
| printf("%10s", "scalar"); | |
| if ((declkind)fp->UU.U0.scalkind == standard) | |
| printf("%10s", "standard"); | |
| else | |
| printf("%10s%4c%6ld", "declared", ' ', (long)fp->UU.U0.UU.fconst); | |
| putchar('\n'); | |
| break; | |
| case subrange: | |
| printf("%10s%4c%6ld", "subrange", ' ', (long)fp->UU.U1.rangetype); | |
| if (fp->UU.U1.rangetype != realptr) | |
| printf("%12ld%12ld", fp->UU.U1.min.UU.ival, fp->UU.U1.max.UU.ival); | |
| else { | |
| if (fp->UU.U1.min.UU.valp != NULL && fp->UU.U1.max.UU.valp != NULL) | |
| printf(" %.9s %.9s", | |
| fp->UU.U1.min.UU.valp->UU.rval, | |
| fp->UU.U1.max.UU.valp->UU.rval); | |
| /* p2c: pcom.p, line 742: Note: | |
| * Format for packed-array-of-char will work only if width < length [321] */ | |
| /* p2c: pcom.p, line 743: Note: | |
| * Format for packed-array-of-char will work only if width < length [321] */ | |
| } | |
| putchar('\n'); | |
| followstp(fp->UU.U1.rangetype, LINK); | |
| break; | |
| case pointer: | |
| printf("%10s%4c%6ld\n", "pointer", ' ', (long)fp->UU.eltype); | |
| break; | |
| case power: | |
| printf("%10s%4c%6ld\n", "set", ' ', (long)fp->UU.elset); | |
| followstp(fp->UU.elset, LINK); | |
| break; | |
| case arrays: | |
| printf("%10s%4c%6ld%4c%6ld\n", | |
| "array", ' ', (long)fp->UU.U4.aeltype, ' ', | |
| (long)fp->UU.U4.inxtype); | |
| followstp(fp->UU.U4.aeltype, LINK); | |
| followstp(fp->UU.U4.inxtype, LINK); | |
| break; | |
| case records: | |
| printf("%10s%4c%6ld%4c%6ld\n", | |
| "record", ' ', (long)fp->UU.U5.fstfld, ' ', | |
| (long)fp->UU.U5.recvar); | |
| followctp(fp->UU.U5.fstfld, LINK); | |
| followstp(fp->UU.U5.recvar, LINK); | |
| break; | |
| case files: | |
| printf("%10s%4c%6ld", "file", ' ', (long)fp->UU.filtype); | |
| followstp(fp->UU.filtype, LINK); | |
| break; | |
| case tagfld: | |
| printf("%10s%4c%6ld%4c%6ld\n", | |
| "tagfld", ' ', (long)fp->UU.U7.tagfieldp, ' ', | |
| (long)fp->UU.U7.fstvar); | |
| followstp(fp->UU.U7.fstvar, LINK); | |
| break; | |
| case variant: | |
| printf("%10s%4c%6ld%4c%6ld%12ld\n", | |
| "variant", ' ', (long)fp->UU.U8.nxtvar, ' ', | |
| (long)fp->UU.U8.subvar, fp->UU.U8.varval.UU.ival); | |
| followstp(fp->UU.U8.nxtvar, LINK); | |
| followstp(fp->UU.U8.subvar, LINK); | |
| break; | |
| }/*case*/ | |
| } | |
| Local void followctp(identifier *fp, struct LOC_printtables *LINK) | |
| { | |
| long i; | |
| constant *WITH1; | |
| long FORLIM; | |
| /*followctp*/ | |
| if (fp == NULL) | |
| return; | |
| printf("%4c%6ld %.8s%4c%6ld%4c%6ld%4c%6ld", | |
| ' ', (long)fp, fp->name, ' ', (long)fp->llink, ' ', (long)fp->rlink, | |
| ' ', (long)fp->idtype); | |
| switch ((idclass)fp->klass) { /*case*/ | |
| case types: | |
| printf("%10s", "type"); | |
| break; | |
| case konst: | |
| printf("%10s%4c%6ld", "constant", ' ', (long)fp->next); | |
| if (fp->idtype != NULL) { | |
| if (fp->idtype == realptr) { | |
| if (fp->UU.values.UU.valp != NULL) | |
| printf(" %.9s", fp->UU.values.UU.valp->UU.rval); | |
| /* p2c: pcom.p, line 789: Note: | |
| * Format for packed-array-of-char will work only if width < length [321] */ | |
| } else { | |
| if ((structform)fp->idtype->form == arrays) { /*stringconst*/ | |
| if (fp->UU.values.UU.valp != NULL) { | |
| putchar(' '); | |
| WITH1 = fp->UU.values.UU.valp; | |
| FORLIM = WITH1->UU.U2.slgth; | |
| for (i = 0; i < FORLIM; i++) | |
| putchar(WITH1->UU.U2.sval[i]); | |
| } | |
| } else | |
| printf("%12ld", fp->UU.values.UU.ival); | |
| } | |
| } | |
| break; | |
| case vars: | |
| printf("%10s", "variable"); | |
| if ((idkind)fp->UU.U2.vkind == actual) | |
| printf("%10s", "actual"); | |
| else | |
| printf("%10s", "formal"); | |
| printf("%4c%6ld%12d%4c%6d", | |
| ' ', (long)fp->next, fp->UU.U2.vlev, ' ', fp->UU.U2.vaddr); | |
| break; | |
| case field: | |
| printf("%10s%4c%6ld%4c%6d", | |
| "field", ' ', (long)fp->next, ' ', fp->UU.fldaddr); | |
| break; | |
| case proc: | |
| case func: | |
| if ((idclass)fp->klass == proc) | |
| printf("%10s", "procedure"); | |
| else | |
| printf("%10s", "function"); | |
| if ((declkind)fp->UU.U4.pfdeckind == standard) | |
| printf("%10s%10d", "standard", fp->UU.U4.UU.key); | |
| else { | |
| printf("%10s%4c%6ld", "declared", ' ', (long)fp->next); | |
| printf("%12d%4c%6ld", | |
| fp->UU.U4.UU.U1.pflev, ' ', fp->UU.U4.UU.U1.pfname); | |
| if ((idkind)fp->UU.U4.UU.U1.pfkind == actual) { | |
| printf("%10s", "actual"); | |
| if (fp->UU.U4.UU.U1.UU.U0.forwdecl) | |
| printf("%10s", "forward"); | |
| else | |
| printf("%10s", "notforward"); | |
| if (fp->UU.U4.UU.U1.UU.U0.externl) | |
| printf("%10s", "extern"); | |
| else | |
| printf("%10s", "not extern"); | |
| } else | |
| printf("%10s", "formal"); | |
| } | |
| break; | |
| } | |
| putchar('\n'); | |
| followctp(fp->llink, LINK); | |
| followctp(fp->rlink, LINK); | |
| followstp(fp->idtype, LINK); /*with*/ | |
| } | |
| Static void printtables(boolean fb) | |
| { | |
| /*print data structure and name table*/ | |
| struct LOC_printtables V; | |
| disprange i, FORLIM; | |
| /*printtables*/ | |
| printf("\n\n\n"); | |
| if (fb) | |
| V.lim = 0; | |
| else { | |
| V.lim = top; | |
| printf(" local"); | |
| } | |
| printf(" tables \n\n"); | |
| marker(&V); | |
| FORLIM = V.lim; | |
| for (i = top; i >= FORLIM; i–) | |
| followctp(display[i].fname, &V); | |
| putchar('\n'); | |
| if (!eol) | |
| printf("%*c", (int)(chcnt + 16), ' '); | |
| } | |
| Static void genlabel(long *nxtlab) | |
| { | |
| /*genlabel*/ | |
| intlabel++; | |
| *nxtlab = intlabel; | |
| } | |
| Static void block(long *fsys, symbol fsy, identifier *fprocp); | |
| #define cstoccmax 65 | |
| #define cixmax 1000 | |
| typedef char oprange; | |
| typedef struct caseinfo { | |
| struct caseinfo *next; | |
| long csstart, cslab; | |
| } caseinfo; | |
| /* Local variables for block: */ | |
| struct LOC_block { | |
| setofsys fsys; | |
| identifier *fprocp; | |
| boolean test; | |
| } ; | |
| Local void typ(long *fsys, structure **fsp, addrrange *fsize, | |
| struct LOC_block *LINK); | |
| Local void skip(long *fsys, struct LOC_block *LINK) | |
| { | |
| /*skip input string until relevant symbol found*/ | |
| /*skip*/ | |
| if (P_eof(stdin)) | |
| return; | |
| while ((!P_inset(sy, fsys)) & (!P_eof(stdin))) | |
| insymbol(); | |
| if (!P_inset(sy, fsys)) | |
| insymbol(); | |
| } | |
| Local void constant_(long *fsys, structure **fsp, valu *fvalu, | |
| struct LOC_block *LINK) | |
| { | |
| structure *lsp; | |
| identifier *lcp; | |
| enum { | |
| none, pos_, neg | |
| } sign; | |
| constant *lvp; | |
| char i; | |
| setofsys SET; | |
| /*constant*/ | |
| lsp = NULL; | |
| fvalu->UU.ival = 0; | |
| if (!P_inset(sy, constbegsys)) { | |
| error(50); | |
| skip(P_setunion(SET, fsys, constbegsys), LINK); | |
| } | |
| if (P_inset(sy, constbegsys)) { | |
| if (sy == stringconst) { | |
| if (lgth == 1) | |
| lsp = charptr; | |
| else { | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.U4.aeltype = charptr; | |
| lsp->UU.U4.inxtype = NULL; | |
| lsp->size = lgth; | |
| (structform)lsp->form = arrays; | |
| } | |
| *fvalu = val; | |
| insymbol(); | |
| } else { | |
| sign = none; | |
| if (sy == addop && | |
| ((1L << ((long)op)) & ((1L << ((long)plus)) | (1L << ((long)minus)))) != | |
| 0) { | |
| if (op == plus) | |
| sign = pos_; | |
| else | |
| sign = neg; | |
| insymbol(); | |
| } | |
| if (sy == ident) { | |
| searchid(1L << ((long)konst), &lcp); | |
| lsp = lcp->idtype; | |
| *fvalu = lcp->UU.values; | |
| if (sign != none) { | |
| if (lsp == intptr) { | |
| if (sign == neg) | |
| fvalu->UU.ival = -fvalu->UU.ival; | |
| } else { | |
| if (lsp == realptr) { | |
| if (sign == neg) { | |
| lvp = Malloc(sizeof(constant)); | |
| if (fvalu->UU.valp->UU.rval[0] == '-') | |
| lvp->UU.rval[0] = '+'; | |
| else | |
| lvp->UU.rval[0] = '-'; | |
| for (i = 1; i < strglgth; i++) | |
| lvp->UU.rval[i] = fvalu->UU.valp->UU.rval[i]; | |
| fvalu->UU.valp = lvp; | |
| } | |
| /* p2c: pcom.p, line 903: | |
| * Note: No SpecialMalloc form known for CONSTANT.REEL [187] */ | |
| } else | |
| error(105); | |
| } | |
| } | |
| insymbol(); | |
| } else { | |
| if (sy == intconst) { | |
| if (sign == neg) | |
| val.UU.ival = -val.UU.ival; | |
| lsp = intptr; | |
| *fvalu = val; | |
| insymbol(); | |
| } else { | |
| if (sy == realconst) { | |
| if (sign == neg) | |
| val.UU.valp->UU.rval[0] = '-'; | |
| lsp = realptr; | |
| *fvalu = val; | |
| insymbol(); | |
| } else { | |
| error(106); | |
| skip(fsys, LINK); | |
| } | |
| } | |
| } | |
| } | |
| if (!P_inset(sy, fsys)) { | |
| error(6); | |
| skip(fsys, LINK); | |
| } | |
| } | |
| *fsp = lsp; | |
| /* p2c: pcom.p, line 877: | |
| * Note: No SpecialMalloc form known for STRUCTURE.ARRAYS [187] */ | |
| } | |
| Local boolean equalbounds(structure *fsp1, structure *fsp2, | |
| struct LOC_block *LINK) | |
| { | |
| long lmin1, lmin2, lmax1, lmax2; | |
| /*equalbounds*/ | |
| if (fsp1 == NULL || fsp2 == NULL) | |
| return true; | |
| else { | |
| getbounds(fsp1, &lmin1, &lmax1); | |
| getbounds(fsp2, &lmin2, &lmax2); | |
| return (lmin1 == lmin2 && lmax1 == lmax2); | |
| } | |
| } | |
| Local boolean comptypes(structure *fsp1, structure *fsp2, | |
| struct LOC_block *LINK) | |
| { | |
| /*decide whether structures pointed at by fsp1 and fsp2 are compatible*/ | |
| boolean Result; | |
| identifier *nxt1, *nxt2; | |
| boolean comp; | |
| testpointer *ltestp1, *ltestp2, *WITH; | |
| /*comptypes*/ | |
| if (fsp1 == fsp2) | |
| return true; | |
| else { | |
| if (fsp1 != NULL && fsp2 != NULL) { | |
| if ((structform)fsp1->form == (structform)fsp2->form) { | |
| switch ((structform)fsp1->form) { | |
| case scalar: | |
| Result = false; | |
| break; | |
| /* identical scalars declared on different levels are | |
| not recognized to be compatible*/ | |
| case subrange: | |
| Result = comptypes(fsp1->UU.U1.rangetype, fsp2->UU.U1.rangetype, | |
| LINK); | |
| break; | |
| case pointer: | |
| comp = false; | |
| ltestp1 = globtestp; | |
| ltestp2 = globtestp; | |
| while (ltestp1 != NULL) { | |
| WITH = ltestp1; | |
| if (WITH->elt1 == fsp1->UU.eltype && WITH->elt2 == fsp2->UU.eltype) | |
| comp = true; | |
| ltestp1 = WITH->lasttestp; | |
| } | |
| if (!comp) { | |
| ltestp1 = Malloc(sizeof(testpointer)); | |
| ltestp1->elt1 = fsp1->UU.eltype; | |
| ltestp1->elt2 = fsp2->UU.eltype; | |
| ltestp1->lasttestp = globtestp; | |
| globtestp = ltestp1; | |
| comp = comptypes(fsp1->UU.eltype, fsp2->UU.eltype, LINK); | |
| } | |
| Result = comp; | |
| globtestp = ltestp2; | |
| break; | |
| case power: | |
| Result = comptypes(fsp1->UU.elset, fsp2->UU.elset, LINK); | |
| break; | |
| case arrays: | |
| comp = comptypes(fsp1->UU.U4.aeltype, fsp2->UU.U4.aeltype, LINK) & | |
| comptypes(fsp1->UU.U4.inxtype, fsp2->UU.U4.inxtype, LINK); | |
| Result = (comp && fsp1->size == fsp2->size) & equalbounds( | |
| fsp1->UU.U4.inxtype, fsp2->UU.U4.inxtype, LINK); | |
| break; | |
| case records: | |
| nxt1 = fsp1->UU.U5.fstfld; | |
| nxt2 = fsp2->UU.U5.fstfld; | |
| comp = true; | |
| while (nxt1 != NULL && nxt2 != NULL) { | |
| comp &= comptypes(nxt1->idtype, nxt2->idtype, LINK); | |
| nxt1 = nxt1->next; | |
| nxt2 = nxt2->next; | |
| } | |
| Result = (comp && nxt1 == NULL && nxt2 == NULL && | |
| fsp1->UU.U5.recvar == NULL && fsp2->UU.U5.recvar == NULL); | |
| break; | |
| /*identical records are recognized to be compatible | |
| iff no variants occur*/ | |
| case files: | |
| Result = comptypes(fsp1->UU.filtype, fsp2->UU.filtype, LINK); | |
| break; | |
| }/*case*/ | |
| return Result; | |
| } else { /*fsp1^.form <> fsp2^.form*/ | |
| if ((structform)fsp1->form == subrange) | |
| return (comptypes(fsp1->UU.U1.rangetype, fsp2, LINK)); | |
| else { | |
| if ((structform)fsp2->form == subrange) | |
| return (comptypes(fsp1, fsp2->UU.U1.rangetype, LINK)); | |
| else | |
| return false; | |
| } | |
| } | |
| } else | |
| return true; | |
| } | |
| return Result; | |
| } | |
| Local boolean string(structure *fsp, struct LOC_block *LINK) | |
| { | |
| boolean Result; | |
| /*string*/ | |
| Result = false; | |
| if (fsp == NULL) | |
| return Result; | |
| if ((structform)fsp->form == arrays) { | |
| if (comptypes(fsp->UU.U4.aeltype, charptr, LINK)) | |
| return true; | |
| } | |
| return Result; | |
| } | |
| /* Local variables for typ: */ | |
| struct LOC_typ { | |
| struct LOC_block *LINK; | |
| addrrange displ; | |
| } ; | |
| Local void simpletype(long *fsys, structure **fsp, addrrange *fsize, | |
| struct LOC_typ *LINK) | |
| { | |
| structure *lsp, *lsp1; | |
| identifier *lcp, *lcp1; | |
| disprange ttop; | |
| long lcnt; | |
| valu lvalu; | |
| setofsys SET, SET1, SET2, SET3; | |
| /*simpletype*/ | |
| *fsize = 1; | |
| if (!P_inset(sy, simptypebegsys)) { | |
| error(1); | |
| skip(P_setunion(SET, fsys, simptypebegsys), LINK->LINK); | |
| } | |
| if (!P_inset(sy, simptypebegsys)) { | |
| *fsp = NULL; | |
| return; | |
| } | |
| if (sy == lparent) { | |
| ttop = top; /*decl. consts local to innermost block*/ | |
| while ((where)display[top].occur != blck) | |
| top–; | |
| /* p2c: pcom.p, line 1040: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SCALAR.DECLARED [187] */ | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->size = intsize; | |
| (structform)lsp->form = scalar; | |
| (declkind)lsp->UU.U0.scalkind = declared; | |
| lcp1 = NULL; | |
| lcnt = 0; | |
| do { | |
| insymbol(); | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = lsp; | |
| lcp->next = lcp1; | |
| lcp->UU.values.UU.ival = lcnt; | |
| (idclass)lcp->klass = konst; | |
| enterid(lcp); | |
| lcnt++; | |
| lcp1 = lcp; | |
| insymbol(); | |
| } else | |
| error(2); | |
| /* p2c: pcom.p, line 1048: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.KONST [187] */ | |
| if (!P_inset(sy, P_setunion(SET1, fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))))) { | |
| error(6); | |
| skip(P_setunion(SET3, fsys, P_expset(SET2, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| } | |
| } while (sy == comma); | |
| lsp->UU.U0.UU.fconst = lcp1; | |
| top = ttop; | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| } else { | |
| if (sy == ident) { | |
| searchid((1L << ((long)types)) | (1L << ((long)konst)), &lcp); | |
| insymbol(); | |
| if ((idclass)lcp->klass == konst) { | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.U1.rangetype = lcp->idtype; | |
| (structform)lsp->form = subrange; | |
| if (string(lsp->UU.U1.rangetype, LINK->LINK)) { | |
| error(148); | |
| lsp->UU.U1.rangetype = NULL; | |
| } | |
| lsp->UU.U1.min = lcp->UU.values; | |
| lsp->size = intsize; | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| constant_(fsys, &lsp1, &lvalu, LINK->LINK); | |
| lsp->UU.U1.max = lvalu; | |
| if (lsp->UU.U1.rangetype != lsp1) | |
| error(107); | |
| } else { | |
| lsp = lcp->idtype; | |
| if (lsp != NULL) | |
| *fsize = lsp->size; | |
| } | |
| /* p2c: pcom.p, line 1070: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SUBRANGE [187] */ | |
| } /*sy = ident*/ | |
| else { | |
| lsp = Malloc(sizeof(structure)); | |
| (structform)lsp->form = subrange; | |
| constant_(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)colon))), | |
| &lsp1, &lvalu, LINK->LINK); | |
| if (string(lsp1, LINK->LINK)) { | |
| error(148); | |
| lsp1 = NULL; | |
| } | |
| lsp->UU.U1.rangetype = lsp1; | |
| lsp->UU.U1.min = lvalu; | |
| lsp->size = intsize; | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| constant_(fsys, &lsp1, &lvalu, LINK->LINK); | |
| lsp->UU.U1.max = lvalu; | |
| if (lsp->UU.U1.rangetype != lsp1) | |
| error(107); | |
| } | |
| if (lsp != NULL) { | |
| if ((structform)lsp->form == subrange) { | |
| if (lsp->UU.U1.rangetype != NULL) { | |
| if (lsp->UU.U1.rangetype == realptr) | |
| error(399); | |
| else { | |
| if (lsp->UU.U1.min.UU.ival > lsp->UU.U1.max.UU.ival) | |
| error(102); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| *fsp = lsp; | |
| if (!P_inset(sy, fsys)) { | |
| error(6); | |
| skip(fsys, LINK->LINK); | |
| } | |
| /* p2c: pcom.p, line 1088: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SUBRANGE [187] */ | |
| } | |
| Local void fieldlist(long *fsys, structure **frecvar, struct LOC_typ *LINK) | |
| { | |
| identifier *lcp, *lcp1, *nxt, *nxt1; | |
| structure *lsp, *lsp1, *lsp2, *lsp3, *lsp4; | |
| addrrange minsize, maxsize, lsize; | |
| valu lvalu; | |
| long SET[(long)casesy / 32 + 2]; | |
| setofsys SET1; | |
| long SET2[(long)casesy / 32 + 2]; | |
| setofsys SET3; | |
| identifier *WITH; | |
| structure *WITH1; | |
| long SET4[(long)ofsy / 32 + 2]; | |
| setofsys SET5, SET6, SET7, SET8; | |
| /*fieldlist*/ | |
| nxt1 = NULL; | |
| lsp = NULL; | |
| P_addset(P_expset(SET, 0), (long)ident); | |
| if (!P_inset(sy, P_setunion(SET1, fsys, P_addset(SET, (long)casesy)))) { | |
| error(19); | |
| P_addset(P_expset(SET2, 0), (long)ident); | |
| skip(P_setunion(SET3, fsys, P_addset(SET2, (long)casesy)), LINK->LINK); | |
| } | |
| while (sy == ident) { /*while*/ | |
| nxt = nxt1; | |
| do { | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| lcp->next = nxt; | |
| (idclass)lcp->klass = field; | |
| nxt = lcp; | |
| enterid(lcp); | |
| insymbol(); | |
| } else | |
| error(2); | |
| /* p2c: pcom.p, line 1124: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.FIELD [187] */ | |
| if ((unsigned long)sy >= 32 || | |
| ((1L << ((long)sy)) & ((1L << ((long)comma)) | (1L << ((long)colon)))) == | |
| 0) { | |
| error(6); | |
| P_addset(P_expset(SET, 0), (long)comma); | |
| P_addset(SET, (long)colon); | |
| P_addset(SET, (long)semicolon); | |
| skip(P_setunion(SET1, fsys, P_addset(SET, (long)casesy)), LINK->LINK); | |
| } | |
| LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->test); | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| P_addset(P_expset(SET, 0), (long)casesy); | |
| typ(P_setunion(SET1, fsys, P_addset(SET, (long)semicolon)), &lsp, &lsize, | |
| LINK->LINK); | |
| while (nxt != nxt1) { | |
| WITH = nxt; | |
| align(lsp, &LINK->displ); | |
| WITH->idtype = lsp; | |
| WITH->UU.fldaddr = LINK->displ; | |
| nxt = WITH->next; | |
| LINK->displ += lsize; | |
| } | |
| nxt1 = lcp; | |
| while (sy == semicolon) { | |
| insymbol(); | |
| P_addset(P_expset(SET, 0), (long)ident); | |
| P_addset(SET, (long)casesy); | |
| if (!P_inset(sy, P_setunion(SET1, fsys, P_addset(SET, (long)semicolon)))) { | |
| error(19); | |
| P_addset(P_expset(SET2, 0), (long)ident); | |
| skip(P_setunion(SET3, fsys, P_addset(SET2, (long)casesy)), LINK->LINK); | |
| } | |
| } | |
| } | |
| nxt = NULL; | |
| while (nxt1 != NULL) { | |
| WITH = nxt1; | |
| lcp = WITH->next; | |
| WITH->next = nxt; | |
| nxt = nxt1; | |
| nxt1 = lcp; | |
| } | |
| if (sy != casesy) { | |
| *frecvar = NULL; | |
| return; | |
| } | |
| /* p2c: pcom.p, line 1160: | |
| * Note: No SpecialMalloc form known for STRUCTURE.TAGFLD [187] */ | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.U7.tagfieldp = NULL; | |
| lsp->UU.U7.fstvar = NULL; | |
| (structform)lsp->form = tagfld; | |
| *frecvar = lsp; | |
| insymbol(); | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| (idclass)lcp->klass = field; | |
| lcp->next = NULL; | |
| lcp->UU.fldaddr = LINK->displ; | |
| enterid(lcp); | |
| insymbol(); | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| if (sy == ident) { | |
| searchid(1L << ((long)types), &lcp1); | |
| lsp1 = lcp1->idtype; | |
| if (lsp1 != NULL) { | |
| align(lsp1, &LINK->displ); | |
| lcp->UU.fldaddr = LINK->displ; | |
| LINK->displ += lsp1->size; | |
| if (((structform)lsp1->form <= subrange) | string(lsp1, LINK->LINK)) { | |
| if (comptypes(realptr, lsp1, LINK->LINK)) | |
| error(109); | |
| else if (string(lsp1, LINK->LINK)) | |
| error(399); | |
| lcp->idtype = lsp1; | |
| lsp->UU.U7.tagfieldp = lcp; | |
| } else | |
| error(110); | |
| } | |
| insymbol(); | |
| } else { | |
| error(2); | |
| P_addset(P_expset(SET4, 0), (long)ofsy); | |
| skip(P_setunion(SET1, fsys, P_addset(SET4, (long)lparent)), LINK->LINK); | |
| } | |
| } else { | |
| error(2); | |
| P_addset(P_expset(SET4, 0), (long)ofsy); | |
| skip(P_setunion(SET1, fsys, P_addset(SET4, (long)lparent)), LINK->LINK); | |
| } | |
| /* p2c: pcom.p, line 1166: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.FIELD [187] */ | |
| lsp->size = LINK->displ; | |
| if (sy == ofsy) | |
| insymbol(); | |
| else | |
| error(8); | |
| lsp1 = NULL; | |
| minsize = LINK->displ; | |
| maxsize = LINK->displ; | |
| do { | |
| lsp2 = NULL; | |
| if (!P_inset(sy, P_setunion(SET3, fsys, | |
| P_expset(SET1, 1L << ((long)semicolon))))) { | |
| do { | |
| constant_(P_setunion(SET6, fsys, P_expset(SET5, | |
| (1L << ((long)comma)) | (1L << ((long)colon)) | | |
| (1L << ((long)lparent)))), &lsp3, &lvalu, | |
| LINK->LINK); | |
| if (lsp->UU.U7.tagfieldp != NULL) { | |
| if (!comptypes(lsp->UU.U7.tagfieldp->idtype, lsp3, LINK->LINK)) | |
| error(111); | |
| } | |
| /* p2c: pcom.p, line 1202: | |
| * Note: No SpecialMalloc form known for STRUCTURE.VARIANT [187] */ | |
| lsp3 = Malloc(sizeof(structure)); | |
| lsp3->UU.U8.nxtvar = lsp1; | |
| lsp3->UU.U8.subvar = lsp2; | |
| lsp3->UU.U8.varval = lvalu; | |
| (structform)lsp3->form = variant; | |
| lsp4 = lsp1; | |
| while (lsp4 != NULL) { | |
| WITH1 = lsp4; | |
| if (WITH1->UU.U8.varval.UU.ival == lvalu.UU.ival) | |
| error(178); | |
| lsp4 = WITH1->UU.U8.nxtvar; | |
| } | |
| lsp1 = lsp3; | |
| lsp2 = lsp3; | |
| LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->test); | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| if (sy == lparent) | |
| insymbol(); | |
| else | |
| error(9); | |
| fieldlist(P_setunion(SET6, fsys, P_expset(SET5, | |
| (1L << ((long)rparent)) | (1L << ((long)semicolon)))), | |
| &lsp2, LINK); | |
| if (LINK->displ > maxsize) | |
| maxsize = LINK->displ; | |
| while (lsp3 != NULL) { | |
| lsp4 = lsp3->UU.U8.subvar; | |
| lsp3->UU.U8.subvar = lsp2; | |
| lsp3->size = LINK->displ; | |
| lsp3 = lsp4; | |
| } | |
| if (sy == rparent) { | |
| insymbol(); | |
| if (!P_inset(sy, | |
| P_setunion(SET6, fsys, | |
| P_expset(SET5, 1L << ((long)semicolon))))) { | |
| error(6); | |
| skip(P_setunion(SET8, fsys, P_expset(SET7, 1L << ((long)semicolon))), | |
| LINK->LINK); | |
| } | |
| } else | |
| error(4); | |
| } | |
| LINK->LINK->test = (sy != semicolon); | |
| if (!LINK->LINK->test) { | |
| LINK->displ = minsize; | |
| insymbol(); | |
| } | |
| } while (!LINK->LINK->test); | |
| LINK->displ = maxsize; | |
| lsp->UU.U7.fstvar = lsp1; | |
| } | |
| Local void typ(long *fsys, structure **fsp, addrrange *fsize, | |
| struct LOC_block *LINK) | |
| { | |
| struct LOC_typ V; | |
| structure *lsp, *lsp1, *lsp2; | |
| disprange oldtop; | |
| identifier *lcp; | |
| addrrange lsize; | |
| long lmin, lmax; | |
| setofsys SET; | |
| _REC_display *WITH; | |
| long SET1[(long)ofsy / 32 + 2]; | |
| setofsys SET2; | |
| long SET3[(long)endsy / 32 + 2]; | |
| setofsys SET4; | |
| V.LINK = LINK; | |
| /*typ*/ | |
| if (!P_inset(sy, typebegsys)) { | |
| error(10); | |
| skip(P_setunion(SET, fsys, typebegsys), LINK); | |
| } | |
| if (P_inset(sy, typebegsys)) { | |
| if (P_inset(sy, simptypebegsys)) | |
| simpletype(fsys, fsp, fsize, &V); | |
| else { | |
| /*^*/ | |
| if (sy == arrow) { | |
| lsp = Malloc(sizeof(structure)); | |
| *fsp = lsp; | |
| lsp->UU.eltype = NULL; | |
| lsp->size = ptrsize; | |
| (structform)lsp->form = pointer; | |
| insymbol(); | |
| if (sy == ident) { | |
| prterr = false; /*no error if search not successful*/ | |
| searchid(1L << ((long)types), &lcp); | |
| prterr = true; | |
| if (lcp == NULL) { /*forward referenced type id*/ | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = lsp; | |
| lcp->next = fwptr; | |
| (idclass)lcp->klass = types; | |
| fwptr = lcp; | |
| } else { | |
| if (lcp->idtype != NULL) { | |
| if ((structform)lcp->idtype->form == files) | |
| error(108); | |
| else | |
| lsp->UU.eltype = lcp->idtype; | |
| } | |
| } | |
| /* p2c: pcom.p, line 1262: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| insymbol(); | |
| } else | |
| error(2); | |
| } else { | |
| if (sy == packedsy) { | |
| insymbol(); | |
| if (!P_inset(sy, typedels)) { | |
| error(10); | |
| skip(P_setunion(SET, fsys, typedels), LINK); | |
| } | |
| } | |
| /*array*/ | |
| if (sy == arraysy) { | |
| insymbol(); | |
| if (sy == lbrack) | |
| insymbol(); | |
| else | |
| error(11); | |
| lsp1 = NULL; | |
| do { | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.U4.aeltype = lsp1; | |
| lsp->UU.U4.inxtype = NULL; | |
| (structform)lsp->form = arrays; | |
| lsp1 = lsp; | |
| P_addset(P_expset(SET1, 0), (long)comma); | |
| P_addset(SET1, (long)rbrack); | |
| simpletype(P_setunion(SET, fsys, P_addset(SET1, (long)ofsy)), | |
| &lsp2, &lsize, &V); | |
| lsp1->size = lsize; | |
| if (lsp2 != NULL) { | |
| if ((structform)lsp2->form <= subrange) { | |
| if (lsp2 == realptr) { | |
| error(109); | |
| lsp2 = NULL; | |
| } else { | |
| if (lsp2 == intptr) { | |
| error(149); | |
| lsp2 = NULL; | |
| } | |
| } | |
| lsp->UU.U4.inxtype = lsp2; | |
| } else { | |
| error(113); | |
| lsp2 = NULL; | |
| } | |
| } | |
| LINK->test = (sy != comma); | |
| if (!LINK->test) | |
| insymbol(); | |
| } while (!LINK->test); | |
| /* p2c: pcom.p, line 1292: | |
| * Note: No SpecialMalloc form known for STRUCTURE.ARRAYS [187] */ | |
| if (sy == rbrack) | |
| insymbol(); | |
| else | |
| error(12); | |
| if (sy == ofsy) | |
| insymbol(); | |
| else | |
| error(8); | |
| typ(fsys, &lsp, &lsize, LINK); | |
| do { | |
| lsp2 = lsp1->UU.U4.aeltype; | |
| lsp1->UU.U4.aeltype = lsp; | |
| if (lsp1->UU.U4.inxtype != NULL) { | |
| getbounds(lsp1->UU.U4.inxtype, &lmin, &lmax); | |
| align(lsp, &lsize); | |
| lsize *= lmax – lmin + 1; | |
| lsp1->size = lsize; | |
| } | |
| lsp = lsp1; | |
| lsp1 = lsp2; | |
| } while (lsp1 != NULL); | |
| } else { | |
| /*record*/ | |
| if (sy == recordsy) { | |
| insymbol(); | |
| oldtop = top; | |
| if (top < displimit) { | |
| top++; | |
| WITH = &display[top]; | |
| WITH->fname = NULL; | |
| WITH->flabel = NULL; | |
| (where)WITH->occur = rec; | |
| } else | |
| error(250); | |
| V.displ = 0; | |
| fieldlist(P_setunion(SET4, | |
| P_setdiff(SET2, fsys, P_expset(SET, 1L << ((long)semicolon))), | |
| P_addset(P_expset(SET3, 0), (long)endsy)), &lsp1, &V); | |
| /* p2c: pcom.p, line 1343: | |
| * Note: No SpecialMalloc form known for STRUCTURE.RECORDS [187] */ | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.U5.fstfld = display[top].fname; | |
| lsp->UU.U5.recvar = lsp1; | |
| lsp->size = V.displ; | |
| (structform)lsp->form = records; | |
| top = oldtop; | |
| if (sy == endsy) | |
| insymbol(); | |
| else | |
| error(13); | |
| } else { | |
| /*set*/ | |
| if (sy == setsy) { | |
| insymbol(); | |
| if (sy == ofsy) | |
| insymbol(); | |
| else | |
| error(8); | |
| simpletype(fsys, &lsp1, &lsize, &V); | |
| if (lsp1 != NULL) { | |
| if ((structform)lsp1->form > subrange) { | |
| error(115); | |
| lsp1 = NULL; | |
| } else { | |
| if (lsp1 == realptr) { | |
| error(114); | |
| lsp1 = NULL; | |
| } else if (lsp1 == intptr) { | |
| error(169); | |
| lsp1 = NULL; | |
| } else { | |
| getbounds(lsp1, &lmin, &lmax); | |
| if (lmin < setlow || lmax > sethigh) | |
| error(169); | |
| } | |
| } | |
| } | |
| /* p2c: pcom.p, line 1369: | |
| * Note: No SpecialMalloc form known for STRUCTURE.POWER [187] */ | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.elset = lsp1; | |
| lsp->size = setsize; | |
| (structform)lsp->form = power; | |
| } else { | |
| /*file*/ | |
| if (sy == filesy) { | |
| insymbol(); | |
| error(399); | |
| skip(fsys, LINK); | |
| lsp = NULL; | |
| } | |
| } | |
| } | |
| } | |
| *fsp = lsp; | |
| } | |
| /* p2c: pcom.p, line 1254: | |
| * Note: No SpecialMalloc form known for STRUCTURE.POINTER [187] */ | |
| } | |
| if (!P_inset(sy, fsys)) { | |
| error(6); | |
| skip(fsys, LINK); | |
| } | |
| } else | |
| *fsp = NULL; | |
| if (*fsp == NULL) | |
| *fsize = 1; | |
| else | |
| *fsize = (*fsp)->size; | |
| } | |
| Local void labeldeclaration(struct LOC_block *LINK) | |
| { | |
| labl *llp; | |
| boolean redef; | |
| long lbname; | |
| _REC_display *WITH; | |
| setofsys SET, SET1, SET2, SET3; | |
| /* labeldeclaration */ | |
| do { | |
| if (sy == intconst) { | |
| WITH = &display[top]; | |
| llp = WITH->flabel; | |
| redef = false; | |
| while (llp != NULL && !redef) { | |
| if (llp->labval != val.UU.ival) | |
| llp = llp->nextlab; | |
| else { | |
| redef = true; | |
| error(166); | |
| } | |
| } | |
| if (!redef) { | |
| llp = Malloc(sizeof(labl)); | |
| llp->labval = val.UU.ival; | |
| genlabel(&lbname); | |
| llp->defined_ = false; | |
| llp->nextlab = WITH->flabel; | |
| llp->labname = lbname; | |
| WITH->flabel = llp; | |
| } | |
| insymbol(); | |
| } else | |
| error(15); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)semicolon)))))) { | |
| error(6); | |
| skip(P_setunion(SET3, LINK->fsys, P_expset(SET2, | |
| (1L << ((long)comma)) | (1L << ((long)semicolon)))), | |
| LINK); | |
| } | |
| LINK->test = (sy != comma); | |
| if (!LINK->test) | |
| insymbol(); | |
| } while (!LINK->test); | |
| if (sy == semicolon) | |
| insymbol(); | |
| else | |
| error(14); | |
| } | |
| Local void constdeclaration(struct LOC_block *LINK) | |
| { | |
| identifier *lcp; | |
| structure *lsp; | |
| valu lvalu; | |
| setofsys SET, SET1, SET2, SET3; | |
| /*constdeclaration*/ | |
| if (sy != ident) { | |
| error(2); | |
| skip(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)ident))), | |
| LINK); | |
| } | |
| while (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| lcp->next = NULL; | |
| (idclass)lcp->klass = konst; | |
| insymbol(); | |
| if (sy == relop && op == eqop) | |
| insymbol(); | |
| else | |
| error(16); | |
| constant_(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)semicolon))), &lsp, | |
| &lvalu, LINK); | |
| enterid(lcp); | |
| lcp->idtype = lsp; | |
| lcp->UU.values = lvalu; | |
| if (sy == semicolon) { | |
| insymbol(); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)ident))))) { | |
| error(6); | |
| skip(P_setunion(SET3, LINK->fsys, P_expset(SET2, 1L << ((long)ident))), | |
| LINK); | |
| } | |
| } else | |
| error(14); | |
| } | |
| /* p2c: pcom.p, line 1423: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.KONST [187] */ | |
| } | |
| Local void typedeclaration(struct LOC_block *LINK) | |
| { | |
| identifier *lcp, *lcp1, *lcp2; | |
| structure *lsp; | |
| addrrange lsize; | |
| setofsys SET, SET1, SET2, SET3; | |
| /*typedeclaration*/ | |
| if (sy != ident) { | |
| error(2); | |
| skip(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)ident))), | |
| LINK); | |
| } | |
| while (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| (idclass)lcp->klass = types; | |
| insymbol(); | |
| if (sy == relop && op == eqop) | |
| insymbol(); | |
| else | |
| error(16); | |
| typ(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)semicolon))), | |
| &lsp, &lsize, LINK); | |
| enterid(lcp); | |
| lcp->idtype = lsp; | |
| /*has any forward reference been satisfied:*/ | |
| lcp1 = fwptr; | |
| while (lcp1 != NULL) { | |
| if (!strncmp(lcp1->name, lcp->name, sizeof(alpha))) { | |
| lcp1->idtype->UU.eltype = lcp->idtype; | |
| if (lcp1 != fwptr) | |
| lcp2->next = lcp1->next; | |
| else | |
| fwptr = lcp1->next; | |
| } else | |
| lcp2 = lcp1; | |
| lcp1 = lcp1->next; | |
| } | |
| if (sy == semicolon) { | |
| insymbol(); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)ident))))) { | |
| error(6); | |
| skip(P_setunion(SET3, LINK->fsys, P_expset(SET2, 1L << ((long)ident))), | |
| LINK); | |
| } | |
| } else | |
| error(14); | |
| } | |
| /* p2c: pcom.p, line 1446: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| if (fwptr == NULL) | |
| return; | |
| error(117); | |
| putchar('\n'); | |
| do { | |
| printf(" type-id %.8s\n", fwptr->name); | |
| fwptr = fwptr->next; | |
| } while (fwptr != NULL); | |
| if (!eol) | |
| printf("%*c", (int)(chcnt + 16), ' '); | |
| } | |
| Local void vardeclaration(struct LOC_block *LINK) | |
| { | |
| identifier *lcp, *nxt; | |
| structure *lsp; | |
| addrrange lsize; | |
| identifier *WITH; | |
| setofsys SET, SET1, SET2, SET3, SET4, SET5; | |
| /*vardeclaration*/ | |
| nxt = NULL; | |
| do { | |
| do { | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->next = nxt; | |
| (idclass)lcp->klass = vars; | |
| lcp->idtype = NULL; | |
| (idkind)lcp->UU.U2.vkind = actual; | |
| lcp->UU.U2.vlev = level; | |
| enterid(lcp); | |
| nxt = lcp; | |
| insymbol(); | |
| } else | |
| error(2); | |
| /* p2c: pcom.p, line 1489: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.VARS [187] */ | |
| if (!P_inset(sy, P_setunion(SET2, P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)colon)))), | |
| typedels))) { | |
| error(6); | |
| skip(P_setunion(SET5, P_setunion(SET4, LINK->fsys, P_expset(SET3, | |
| (1L << ((long)comma)) | (1L << ((long)colon)) | | |
| (1L << ((long)semicolon)))), typedels), LINK); | |
| } | |
| LINK->test = (sy != comma); | |
| if (!LINK->test) | |
| insymbol(); | |
| } while (!LINK->test); | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| typ(P_setunion(SET2, P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)semicolon))), | |
| typedels), &lsp, &lsize, LINK); | |
| while (nxt != NULL) { | |
| WITH = nxt; | |
| align(lsp, &lc); | |
| WITH->idtype = lsp; | |
| WITH->UU.U2.vaddr = lc; | |
| lc += lsize; | |
| nxt = WITH->next; | |
| } | |
| if (sy == semicolon) { | |
| insymbol(); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)ident))))) { | |
| error(6); | |
| skip(P_setunion(SET3, LINK->fsys, P_expset(SET2, 1L << ((long)ident))), | |
| LINK); | |
| } | |
| } else | |
| error(14); | |
| } while (!((sy != ident) & (!P_inset(sy, typedels)))); | |
| if (fwptr == NULL) | |
| return; | |
| error(117); | |
| putchar('\n'); | |
| do { | |
| printf(" type-id %.8s\n", fwptr->name); | |
| fwptr = fwptr->next; | |
| } while (fwptr != NULL); | |
| if (!eol) | |
| printf("%*c", (int)(chcnt + 16), ' '); | |
| } | |
| /* Local variables for procdeclaration: */ | |
| struct LOC_procdeclaration { | |
| struct LOC_block *LINK; | |
| boolean forw; | |
| } ; | |
| Local void parameterlist(long *fsy, identifier **fpar, | |
| struct LOC_procdeclaration *LINK) | |
| { | |
| identifier *lcp, *lcp1, *lcp2, *lcp3; | |
| structure *lsp; | |
| idkind lkind; | |
| addrrange llc, lsize; | |
| long count; | |
| setofsys SET, SET1, SET2, SET3, SET4; | |
| identifier *WITH; | |
| /*parameterlist*/ | |
| lcp1 = NULL; | |
| if (!P_inset(sy, | |
| P_setunion(SET1, fsy, P_expset(SET, 1L << ((long)lparent))))) { | |
| error(7); | |
| skip(P_setunion(SET4, P_setunion(SET2, LINK->LINK->fsys, fsy), | |
| P_expset(SET3, 1L << ((long)lparent))), LINK->LINK); | |
| } | |
| if (sy != lparent) { | |
| *fpar = NULL; | |
| return; | |
| } | |
| if (LINK->forw) | |
| error(119); | |
| insymbol(); | |
| if ((unsigned long)sy >= 32 || | |
| ((1L << ((long)sy)) & ((1L << ((long)ident)) | (1L << ((long)varsy)) | | |
| (1L << ((long)procsy)) | (1L << ((long)funcsy)))) == 0) { | |
| error(7); | |
| skip(P_setunion(SET1, LINK->LINK->fsys, | |
| P_expset(SET, (1L << ((long)ident)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| } | |
| while ((unsigned long)sy < 32 && | |
| ((1L << ((long)sy)) & ((1L << ((long)ident)) | (1L << ((long)varsy)) | | |
| (1L << ((long)procsy)) | (1L << ((long)funcsy)))) != 0) | |
| { /*while*/ | |
| if (sy == procsy) { | |
| error(399); | |
| do { | |
| insymbol(); | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| lcp->next = lcp1; | |
| lcp->UU.U4.UU.U1.pflev = level; /*beware of parameter procedures*/ | |
| (idclass)lcp->klass = proc; | |
| (declkind)lcp->UU.U4.pfdeckind = declared; | |
| (idkind)lcp->UU.U4.UU.U1.pfkind = formal; | |
| enterid(lcp); | |
| lcp1 = lcp; | |
| align(parmptr, &lc); | |
| /*lc := lc + some size */ | |
| insymbol(); | |
| } else | |
| error(2); | |
| /* p2c: pcom.p, line 1550: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.PROC.DECLARED.FORMAL [187] */ | |
| if (!P_inset(sy, P_setunion(SET1, LINK->LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)semicolon)) | | |
| (1L << ((long)rparent)))))) { | |
| error(7); | |
| skip(P_setunion(SET3, LINK->LINK->fsys, | |
| P_expset(SET2, | |
| (1L << ((long)comma)) | (1L << ((long)semicolon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| } | |
| } while (sy == comma); | |
| } else { | |
| if (sy == funcsy) { | |
| error(399); | |
| lcp2 = NULL; | |
| do { | |
| insymbol(); | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| lcp->next = lcp2; | |
| lcp->UU.U4.UU.U1.pflev = level; /*beware param funcs*/ | |
| (idclass)lcp->klass = func; | |
| (declkind)lcp->UU.U4.pfdeckind = declared; | |
| (idkind)lcp->UU.U4.UU.U1.pfkind = formal; | |
| enterid(lcp); | |
| lcp2 = lcp; | |
| align(parmptr, &lc); | |
| /*lc := lc + some size*/ | |
| insymbol(); | |
| } | |
| /* p2c: pcom.p, line 1573: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.FUNC.DECLARED.FORMAL [187] */ | |
| if (!P_inset(sy, P_setunion(SET1, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)colon))), | |
| LINK->LINK->fsys))) { | |
| error(7); | |
| skip(P_setunion(SET3, LINK->LINK->fsys, P_expset(SET2, | |
| (1L << ((long)comma)) | (1L << ((long)semicolon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| } | |
| } while (sy == comma); | |
| if (sy == colon) { | |
| insymbol(); | |
| if (sy == ident) { | |
| searchid(1L << ((long)types), &lcp); | |
| lsp = lcp->idtype; | |
| if (lsp != NULL) { | |
| if (((1L << lsp->form) & ((1L << ((long)scalar)) | | |
| (1L << ((long)subrange)) | (1L << ((long)pointer)))) == 0) { | |
| error(120); | |
| lsp = NULL; | |
| } | |
| } | |
| lcp3 = lcp2; | |
| while (lcp2 != NULL) { | |
| lcp2->idtype = lsp; | |
| lcp = lcp2; | |
| lcp2 = lcp2->next; | |
| } | |
| lcp->next = lcp1; | |
| lcp1 = lcp3; | |
| insymbol(); | |
| } else | |
| error(2); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->LINK->fsys, P_expset(SET, | |
| (1L << ((long)semicolon)) | (1L << ((long)rparent)))))) { | |
| error(7); | |
| skip(P_setunion(SET3, LINK->LINK->fsys, P_expset(SET2, | |
| (1L << ((long)semicolon)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| } | |
| } else | |
| error(5); | |
| } else { | |
| if (sy == varsy) { | |
| lkind = formal; | |
| insymbol(); | |
| } else | |
| lkind = actual; | |
| lcp2 = NULL; | |
| count = 0; | |
| do { | |
| if (sy == ident) { | |
| lcp = Malloc(sizeof(identifier)); | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| (idclass)lcp->klass = vars; | |
| (idkind)lcp->UU.U2.vkind = lkind; | |
| lcp->next = lcp2; | |
| lcp->UU.U2.vlev = level; | |
| enterid(lcp); | |
| lcp2 = lcp; | |
| count++; | |
| insymbol(); | |
| } | |
| /* p2c: pcom.p, line 1621: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.VARS [187] */ | |
| if (!P_inset(sy, P_setunion(SET1, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)colon))), | |
| LINK->LINK->fsys))) { | |
| error(7); | |
| skip(P_setunion(SET3, LINK->LINK->fsys, P_expset(SET2, | |
| (1L << ((long)comma)) | (1L << ((long)semicolon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| } | |
| LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->test); | |
| if (sy == colon) { | |
| insymbol(); | |
| if (sy == ident) { | |
| searchid(1L << ((long)types), &lcp); | |
| lsp = lcp->idtype; | |
| lsize = ptrsize; | |
| if (lsp != NULL) { | |
| if (lkind == actual) { | |
| if ((structform)lsp->form <= power) | |
| lsize = lsp->size; | |
| else if ((structform)lsp->form == files) | |
| error(121); | |
| } | |
| } | |
| align(parmptr, &lsize); | |
| lcp3 = lcp2; | |
| align(parmptr, &lc); | |
| lc += count * lsize; | |
| llc = lc; | |
| while (lcp2 != NULL) { | |
| lcp = lcp2; | |
| lcp2->idtype = lsp; | |
| llc -= lsize; | |
| lcp2->UU.U2.vaddr = llc; | |
| lcp2 = lcp2->next; | |
| } | |
| lcp->next = lcp1; | |
| lcp1 = lcp3; | |
| insymbol(); | |
| } else | |
| error(2); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->LINK->fsys, P_expset(SET, | |
| (1L << ((long)semicolon)) | (1L << ((long)rparent)))))) { | |
| error(7); | |
| skip(P_setunion(SET3, LINK->LINK->fsys, P_expset(SET2, | |
| (1L << ((long)semicolon)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| } | |
| } else | |
| error(5); | |
| } | |
| } | |
| if (sy == semicolon) { | |
| insymbol(); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->LINK->fsys, P_expset(SET, | |
| (1L << ((long)ident)) | (1L << ((long)varsy)) | | |
| (1L << ((long)procsy)) | (1L << ((long)funcsy)))))) { | |
| error(7); | |
| skip(P_setunion(SET3, LINK->LINK->fsys, P_expset(SET2, | |
| (1L << ((long)ident)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| } | |
| } | |
| } | |
| if (sy == rparent) { | |
| insymbol(); | |
| if (!P_inset(sy, P_setunion(SET, fsy, LINK->LINK->fsys))) { | |
| error(6); | |
| skip(P_setunion(SET1, fsy, LINK->LINK->fsys), LINK->LINK); | |
| } | |
| } else | |
| error(4); | |
| lcp3 = NULL; | |
| /*reverse pointers and reserve local cells for copies of multiple | |
| values*/ | |
| while (lcp1 != NULL) { | |
| WITH = lcp1; | |
| lcp2 = WITH->next; | |
| WITH->next = lcp3; | |
| if ((idclass)WITH->klass == vars) { | |
| if (WITH->idtype != NULL) { | |
| if ((idkind)WITH->UU.U2.vkind == actual && | |
| (structform)WITH->idtype->form > power) { | |
| align(WITH->idtype, &lc); | |
| WITH->UU.U2.vaddr = lc; | |
| lc += WITH->idtype->size; | |
| } | |
| } | |
| } | |
| lcp3 = lcp1; | |
| lcp1 = lcp2; | |
| } | |
| *fpar = lcp3; | |
| } | |
| Local void procdeclaration(symbol fsy, struct LOC_block *LINK) | |
| { | |
| struct LOC_procdeclaration V; | |
| char oldlev; | |
| identifier *lcp, *lcp1; | |
| structure *lsp; | |
| disprange oldtop; | |
| addrrange llc, lcm; | |
| long lbname, *markp; | |
| _REC_display *WITH; | |
| setofsys SET, SET1; | |
| V.LINK = LINK; | |
| /*procdeclaration*/ | |
| llc = lc; | |
| lc = lcaftermarkstack; | |
| V.forw = false; | |
| if (sy == ident) { | |
| searchsection(display[top].fname, &lcp); /*decide whether forw.*/ | |
| if (lcp != NULL) { | |
| if ((idclass)lcp->klass == proc) | |
| V.forw = (lcp->UU.U4.UU.U1.UU.U0.forwdecl && fsy == procsy && | |
| (idkind)lcp->UU.U4.UU.U1.pfkind == actual); | |
| else { | |
| if ((idclass)lcp->klass == func) | |
| V.forw = (lcp->UU.U4.UU.U1.UU.U0.forwdecl && fsy == funcsy && | |
| (idkind)lcp->UU.U4.UU.U1.pfkind == actual); | |
| else | |
| V.forw = false; | |
| } | |
| if (!V.forw) | |
| error(160); | |
| } | |
| if (!V.forw) { | |
| if (fsy == procsy) | |
| lcp = Malloc(sizeof(identifier)); | |
| else | |
| lcp = Malloc(sizeof(identifier)); | |
| /* p2c: pcom.p, line 1719: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.PROC.DECLARED.ACTUAL [187] */ | |
| memcpy(lcp->name, id, sizeof(alpha)); | |
| lcp->idtype = NULL; | |
| lcp->UU.U4.UU.U1.UU.U0.externl = false; | |
| lcp->UU.U4.UU.U1.pflev = level; | |
| genlabel(&lbname); | |
| (declkind)lcp->UU.U4.pfdeckind = declared; | |
| (idkind)lcp->UU.U4.UU.U1.pfkind = actual; | |
| lcp->UU.U4.UU.U1.pfname = lbname; | |
| if (fsy == procsy) | |
| (idclass)lcp->klass = proc; | |
| else | |
| (idclass)lcp->klass = func; | |
| enterid(lcp); | |
| } else { | |
| lcp1 = lcp->next; | |
| while (lcp1 != NULL) { | |
| if ((idclass)lcp1->klass == vars) { | |
| if (lcp1->idtype != NULL) { | |
| lcm = lcp1->UU.U2.vaddr + lcp1->idtype->size; | |
| if (lcm > lc) | |
| lc = lcm; | |
| } | |
| } | |
| lcp1 = lcp1->next; | |
| } | |
| } | |
| insymbol(); | |
| } else { | |
| error(2); | |
| lcp = ufctptr; | |
| } | |
| oldlev = level; | |
| oldtop = top; | |
| if (level < maxlevel) | |
| level++; | |
| else | |
| error(251); | |
| if (top < displimit) { | |
| top++; | |
| WITH = &display[top]; | |
| if (V.forw) | |
| WITH->fname = lcp->next; | |
| else | |
| WITH->fname = NULL; | |
| WITH->flabel = NULL; | |
| (where)WITH->occur = blck; | |
| } else | |
| error(250); | |
| if (fsy == procsy) { | |
| parameterlist(P_expset(SET, 1L << ((long)semicolon)), &lcp1, &V); | |
| if (!V.forw) | |
| lcp->next = lcp1; | |
| } else { | |
| parameterlist(P_expset(SET, | |
| (1L << ((long)semicolon)) | (1L << ((long)colon))), | |
| &lcp1, &V); | |
| if (!V.forw) | |
| lcp->next = lcp1; | |
| if (sy == colon) { | |
| insymbol(); | |
| if (sy == ident) { | |
| if (V.forw) | |
| error(122); | |
| searchid(1L << ((long)types), &lcp1); | |
| lsp = lcp1->idtype; | |
| lcp->idtype = lsp; | |
| if (lsp != NULL) { | |
| if (((1L << lsp->form) & ((1L << ((long)scalar)) | | |
| (1L << ((long)subrange)) | (1L << ((long)pointer)))) == 0) { | |
| error(120); | |
| lcp->idtype = NULL; | |
| } | |
| } | |
| insymbol(); | |
| } else { | |
| error(2); | |
| skip(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)semicolon))), LINK); | |
| } | |
| } else { | |
| if (!V.forw) | |
| error(123); | |
| } | |
| } | |
| if (sy == semicolon) | |
| insymbol(); | |
| else | |
| error(14); | |
| if (sy == forwardsy) { | |
| if (V.forw) | |
| error(161); | |
| else | |
| lcp->UU.U4.UU.U1.UU.U0.forwdecl = true; | |
| insymbol(); | |
| if (sy == semicolon) | |
| insymbol(); | |
| else | |
| error(14); | |
| if (!P_inset(sy, LINK->fsys)) { | |
| error(6); | |
| skip(LINK->fsys, LINK); | |
| } | |
| } else { | |
| lcp->UU.U4.UU.U1.UU.U0.forwdecl = false; | |
| mark_(&markp); | |
| do { | |
| block(LINK->fsys, semicolon, lcp); | |
| if (sy == semicolon) { | |
| if (prtables) | |
| printtables(false); | |
| insymbol(); | |
| if ((unsigned long)sy >= 32 || | |
| ((1L << ((long)sy)) & ((1L << ((long)beginsy)) | | |
| (1L << ((long)procsy)) | (1L << ((long)funcsy)))) == 0) { | |
| error(6); | |
| skip(LINK->fsys, LINK); | |
| } | |
| } else | |
| error(14); | |
| } while (!(((unsigned long)sy < 32 && | |
| ((1L << ((long)sy)) & ((1L << ((long)beginsy)) | | |
| (1L << ((long)procsy)) | (1L << ((long)funcsy)))) != | |
| 0) | P_eof(stdin))); | |
| release_(markp); /* return local entries on runtime heap */ | |
| } | |
| level = oldlev; | |
| top = oldtop; | |
| lc = llc; | |
| /* p2c: pcom.p, line 1719: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.FUNC.DECLARED.ACTUAL [187] */ | |
| } | |
| /* Local variables for body: */ | |
| struct LOC_body { | |
| struct LOC_block *LINK; | |
| constant *cstptr[cstoccmax]; | |
| char cstptrix; | |
| long topnew, topmax; | |
| addrrange lcmax; | |
| } ; | |
| Local void statement(long *fsys, struct LOC_body *LINK); | |
| Local void mes(long i, struct LOC_body *LINK) | |
| { | |
| LINK->topnew += cdx[i]; | |
| if (LINK->topnew > LINK->topmax) | |
| LINK->topmax = LINK->topnew; | |
| } | |
| Local void putic(struct LOC_body *LINK) | |
| { | |
| if (ic % 10 == 0) | |
| fprintf(prr.f, "i%5d\n", ic); | |
| } | |
| Local void gen0(oprange fop, struct LOC_body *LINK) | |
| { | |
| /*gen0*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s\n", mn[fop]); | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void gen1(oprange fop, long fp2, struct LOC_body *LINK) | |
| { | |
| long k; | |
| constant *WITH; | |
| long FORLIM; | |
| /*gen1*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s", mn[fop]); | |
| if (fop == 30) { | |
| fprintf(prr.f, " %.4s\n", sna[fp2 – 1]); | |
| LINK->topnew += pdx[fp2 – 1]; | |
| if (LINK->topnew > LINK->topmax) | |
| LINK->topmax = LINK->topnew; | |
| } else { | |
| if (fop == 38) { | |
| putc('\'', prr.f); | |
| WITH = LINK->cstptr[fp2 – 1]; | |
| FORLIM = WITH->UU.U2.slgth; | |
| for (k = 0; k < FORLIM; k++) | |
| putc(WITH->UU.U2.sval[k], prr.f); | |
| for (k = WITH->UU.U2.slgth + 1; k <= strglgth; k++) | |
| putc(' ', prr.f); | |
| fprintf(prr.f, "'\n"); | |
| } else if (fop == 42) | |
| fprintf(prr.f, "%c\n", (Char)fp2); | |
| else | |
| fprintf(prr.f, "%12ld\n", fp2); | |
| mes(fop, LINK); | |
| } | |
| } | |
| ic++; | |
| } | |
| Local void gen2(oprange fop, long fp1, long fp2, struct LOC_body *LINK) | |
| { | |
| long k; | |
| constant *WITH; | |
| /*gen2*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s", mn[fop]); | |
| switch (fop) { | |
| case 45: | |
| case 50: | |
| case 54: | |
| case 56: | |
| fprintf(prr.f, " %3ld%8ld\n", fp1, fp2); | |
| break; | |
| case 47: | |
| case 48: | |
| case 49: | |
| case 52: | |
| case 53: | |
| case 55: | |
| putc((Char)fp1, prr.f); | |
| if (fp1 == 'm') | |
| fprintf(prr.f, "%11ld", fp2); | |
| putc('\n', prr.f); | |
| break; | |
| case 51: | |
| switch (fp1) { | |
| case 1: | |
| fprintf(prr.f, "i %12ld\n", fp2); | |
| break; | |
| case 2: | |
| fprintf(prr.f, "r "); | |
| WITH = LINK->cstptr[fp2 – 1]; | |
| for (k = 0; k < strglgth; k++) | |
| putc(WITH->UU.rval[k], prr.f); | |
| putc('\n', prr.f); | |
| break; | |
| case 3: | |
| fprintf(prr.f, "b %12ld\n", fp2); | |
| break; | |
| case 4: | |
| fprintf(prr.f, "n\n"); | |
| break; | |
| case 6: | |
| fprintf(prr.f, "%3s%c'\n", "c '", (Char)fp2); | |
| break; | |
| case 5: | |
| putc('(', prr.f); | |
| WITH = LINK->cstptr[fp2 – 1]; | |
| for (k = setlow; k <= sethigh; k++) { | |
| if (P_inset(k, WITH->UU.pval)) | |
| fprintf(prr.f, "%3ld", k); | |
| } | |
| fprintf(prr.f, ")\n"); | |
| break; | |
| } | |
| break; | |
| } | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void gentypindicator(structure *fsp, struct LOC_body *LINK) | |
| { | |
| /*typindicator*/ | |
| if (fsp == NULL) | |
| return; | |
| switch ((structform)fsp->form) { | |
| case scalar: | |
| if (fsp == intptr) | |
| putc('i', prr.f); | |
| else { | |
| if (fsp == boolptr) | |
| putc('b', prr.f); | |
| else { | |
| if (fsp == charptr) | |
| putc('c', prr.f); | |
| else { | |
| if ((declkind)fsp->UU.U0.scalkind == declared) | |
| putc('i', prr.f); | |
| else | |
| putc('r', prr.f); | |
| } | |
| } | |
| } | |
| break; | |
| case subrange: | |
| gentypindicator(fsp->UU.U1.rangetype, LINK); | |
| break; | |
| case pointer: | |
| putc('a', prr.f); | |
| break; | |
| case power: | |
| putc('s', prr.f); | |
| break; | |
| case records: | |
| case arrays: | |
| putc('m', prr.f); | |
| break; | |
| case files: | |
| case tagfld: | |
| case variant: | |
| error(500); | |
| break; | |
| } | |
| } | |
| Local void gen0t(oprange fop, structure *fsp, struct LOC_body *LINK) | |
| { | |
| /*gen0t*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s", mn[fop]); | |
| gentypindicator(fsp, LINK); | |
| putc('\n', prr.f); | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void gen1t(oprange fop, long fp2, structure *fsp, struct LOC_body *LINK) | |
| { | |
| /*gen1t*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s", mn[fop]); | |
| gentypindicator(fsp, LINK); | |
| fprintf(prr.f, "%11ld\n", fp2); | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void gen2t(oprange fop, long fp1, long fp2, structure *fsp, | |
| struct LOC_body *LINK) | |
| { | |
| /*gen2t*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s", mn[fop]); | |
| gentypindicator(fsp, LINK); | |
| fprintf(prr.f, "%*ld%8ld\n", (labs(fp1) > 99) * 5 + 3, fp1, fp2); | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void load(struct LOC_body *LINK) | |
| { | |
| /*load*/ | |
| if (gattr.typtr == NULL) | |
| return; | |
| switch (gattr.kind) { | |
| case cst: | |
| if ((structform)gattr.typtr->form == scalar && gattr.typtr != realptr) { | |
| if (gattr.typtr == boolptr) /*ldc*/ | |
| gen2(51, 3, gattr.UU.cval.UU.ival, LINK); | |
| else { | |
| if (gattr.typtr == charptr) /*ldc*/ | |
| gen2(51, 6, gattr.UU.cval.UU.ival, LINK); | |
| else /*ldc*/ | |
| gen2(51, 1, gattr.UU.cval.UU.ival, LINK); | |
| } | |
| } else { | |
| if (gattr.typtr == nilptr) /*ldc*/ | |
| gen2(51, 4, 0, LINK); | |
| else { | |
| if (LINK->cstptrix >= cstoccmax) | |
| error(254); | |
| else { | |
| LINK->cstptrix++; | |
| LINK->cstptr[LINK->cstptrix – 1] = gattr.UU.cval.UU.valp; | |
| if (gattr.typtr == realptr) /*ldc*/ | |
| gen2(51, 2, LINK->cstptrix, LINK); | |
| else /*ldc*/ | |
| gen2(51, 5, LINK->cstptrix, LINK); | |
| } | |
| } | |
| } | |
| break; | |
| case varbl: | |
| switch (gattr.UU.U1.access) { | |
| case drct: | |
| if (gattr.UU.U1.UU.U0.vlevel <= 1) /*ldo*/ | |
| gen1t(39, gattr.UU.U1.UU.U0.dplmt, gattr.typtr, LINK); | |
| else /*lod*/ | |
| gen2t(54, level – gattr.UU.U1.UU.U0.vlevel, gattr.UU.U1.UU.U0.dplmt, | |
| gattr.typtr, LINK); | |
| break; | |
| case indrct: /*ind*/ | |
| gen1t(35, gattr.UU.U1.UU.idplmt, gattr.typtr, LINK); | |
| break; | |
| case inxd: | |
| error(400); | |
| break; | |
| } | |
| break; | |
| case expr: | |
| /* blank case */ | |
| break; | |
| } | |
| gattr.kind = expr; | |
| } | |
| Local void store(attr *fattr, struct LOC_body *LINK) | |
| { | |
| /*store*/ | |
| if (fattr->typtr == NULL) | |
| return; | |
| switch (fattr->UU.U1.access) { | |
| case drct: | |
| if (fattr->UU.U1.UU.U0.vlevel <= 1) /*sro*/ | |
| gen1t(43, fattr->UU.U1.UU.U0.dplmt, fattr->typtr, LINK); | |
| else /*str*/ | |
| gen2t(56, level – fattr->UU.U1.UU.U0.vlevel, fattr->UU.U1.UU.U0.dplmt, | |
| fattr->typtr, LINK); | |
| break; | |
| case indrct: | |
| if (fattr->UU.U1.UU.idplmt != 0) | |
| error(400); | |
| else /*sto*/ | |
| gen0t(26, fattr->typtr, LINK); | |
| break; | |
| case inxd: | |
| error(400); | |
| break; | |
| } | |
| } | |
| Local void loadaddress(struct LOC_body *LINK) | |
| { | |
| /*loadaddress*/ | |
| if (gattr.typtr == NULL) | |
| return; | |
| switch (gattr.kind) { | |
| case cst: | |
| if (string(gattr.typtr, LINK->LINK)) { | |
| if (LINK->cstptrix >= cstoccmax) | |
| error(254); | |
| else { | |
| LINK->cstptrix++; | |
| LINK->cstptr[LINK->cstptrix – 1] = gattr.UU.cval.UU.valp; /*lca*/ | |
| gen1(38, LINK->cstptrix, LINK); | |
| } | |
| } else | |
| error(400); | |
| break; | |
| case varbl: | |
| switch (gattr.UU.U1.access) { | |
| case drct: | |
| if (gattr.UU.U1.UU.U0.vlevel <= 1) /*lao*/ | |
| gen1(37, gattr.UU.U1.UU.U0.dplmt, LINK); | |
| else /*lda*/ | |
| gen2(50, level – gattr.UU.U1.UU.U0.vlevel, gattr.UU.U1.UU.U0.dplmt, | |
| LINK); | |
| break; | |
| case indrct: | |
| if (gattr.UU.U1.UU.idplmt != 0) /*inc*/ | |
| gen1t(34, gattr.UU.U1.UU.idplmt, nilptr, LINK); | |
| break; | |
| case inxd: | |
| error(400); | |
| break; | |
| } | |
| break; | |
| case expr: | |
| error(400); | |
| break; | |
| } | |
| gattr.kind = varbl; | |
| gattr.UU.U1.access = indrct; | |
| gattr.UU.U1.UU.idplmt = 0; | |
| } | |
| Local void genfjp(long faddr, struct LOC_body *LINK) | |
| { | |
| /*genfjp*/ | |
| load(LINK); | |
| if (gattr.typtr != NULL) { | |
| if (gattr.typtr != boolptr) | |
| error(144); | |
| } | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s%8s%4ld\n", mn[33], " l", faddr); | |
| } | |
| ic++; | |
| mes(33, LINK); | |
| } | |
| Local void genujpxjp(oprange fop, long fp2, struct LOC_body *LINK) | |
| { | |
| /*genujpxjp*/ | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s%8s%4ld\n", mn[fop], " l", fp2); | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void gencupent(oprange fop, long fp1, long fp2, struct LOC_body *LINK) | |
| { | |
| if (prcode) { | |
| putic(LINK); | |
| fprintf(prr.f, "%.4s%4ld%4c%4ld\n", mn[fop], fp1, 'l', fp2); | |
| } | |
| ic++; | |
| mes(fop, LINK); | |
| } | |
| Local void checkbnds(structure *fsp, struct LOC_body *LINK) | |
| { | |
| long lmin, lmax; | |
| /*checkbnds*/ | |
| if (fsp == NULL) | |
| return; | |
| if (fsp == intptr) | |
| return; | |
| if (fsp == realptr) | |
| return; | |
| if ((structform)fsp->form <= subrange) { | |
| getbounds(fsp, &lmin, &lmax); /*chk*/ | |
| gen2t(45, lmin, lmax, fsp, LINK); | |
| } | |
| } | |
| Local void putlabel(long labname, struct LOC_body *LINK) | |
| { | |
| /*putlabel*/ | |
| if (prcode) | |
| fprintf(prr.f, "l%4ld\n", labname); | |
| } | |
| /* Local variables for statement: */ | |
| struct LOC_statement { | |
| struct LOC_body *LINK; | |
| setofsys fsys; | |
| identifier *lcp; | |
| } ; | |
| Local void expression(long *fsys, struct LOC_statement *LINK); | |
| Local void selector(long *fsys, identifier *fcp, struct LOC_statement *LINK) | |
| { | |
| attr lattr; | |
| identifier *lcp; | |
| addrrange lsize; | |
| long lmin, lmax; | |
| structure *WITH; | |
| _REC_display *WITH1; | |
| setofsys SET, SET1; | |
| /*selector*/ | |
| gattr.typtr = fcp->idtype; | |
| gattr.kind = varbl; | |
| switch ((idclass)fcp->klass) { /*with*/ | |
| case vars: | |
| if ((idkind)fcp->UU.U2.vkind == actual) { | |
| gattr.UU.U1.access = drct; | |
| gattr.UU.U1.UU.U0.vlevel = fcp->UU.U2.vlev; | |
| gattr.UU.U1.UU.U0.dplmt = fcp->UU.U2.vaddr; | |
| } else { /*lod*/ | |
| gen2t(54, level – fcp->UU.U2.vlev, fcp->UU.U2.vaddr, nilptr, LINK->LINK); | |
| gattr.UU.U1.access = indrct; | |
| gattr.UU.U1.UU.idplmt = 0; | |
| } | |
| break; | |
| case field: | |
| WITH1 = &display[disx]; | |
| if ((where)WITH1->occur == crec) { | |
| gattr.UU.U1.access = drct; | |
| gattr.UU.U1.UU.U0.vlevel = WITH1->UU.U1.clev; | |
| gattr.UU.U1.UU.U0.dplmt = WITH1->UU.U1.cdspl + fcp->UU.fldaddr; | |
| } else { | |
| if (level == 1) /*ldo*/ | |
| gen1t(39, WITH1->UU.vdspl, nilptr, LINK->LINK); | |
| else /*lod*/ | |
| gen2t(54, 0, WITH1->UU.vdspl, nilptr, LINK->LINK); | |
| gattr.UU.U1.access = indrct; | |
| gattr.UU.U1.UU.idplmt = fcp->UU.fldaddr; | |
| } | |
| break; | |
| case func: | |
| if ((declkind)fcp->UU.U4.pfdeckind == standard) { | |
| error(150); | |
| gattr.typtr = NULL; | |
| } else { | |
| if ((idkind)fcp->UU.U4.UU.U1.pfkind == formal) | |
| error(151); | |
| else { | |
| if (fcp->UU.U4.UU.U1.pflev + 1 != level || | |
| LINK->LINK->LINK->fprocp != fcp) | |
| error(177); | |
| } | |
| gattr.UU.U1.access = drct; | |
| gattr.UU.U1.UU.U0.vlevel = fcp->UU.U4.UU.U1.pflev + 1; | |
| gattr.UU.U1.UU.U0.dplmt = 0; /*impl. relat. addr. of fct. result*/ | |
| } | |
| break; | |
| }/*case*/ | |
| if (!P_inset(sy, P_setunion(SET, selectsys, fsys))) { | |
| error(59); | |
| skip(P_setunion(SET1, selectsys, fsys), LINK->LINK->LINK); | |
| } | |
| while (P_inset(sy, selectsys)) { | |
| /*[*/ | |
| if (sy == lbrack) { | |
| do { | |
| lattr = gattr; | |
| if (lattr.typtr != NULL) { | |
| if ((structform)lattr.typtr->form != arrays) { | |
| error(138); | |
| lattr.typtr = NULL; | |
| } | |
| } | |
| loadaddress(LINK->LINK); | |
| insymbol(); | |
| expression(P_setunion(SET1, fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rbrack)))), | |
| LINK); | |
| load(LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != scalar) | |
| error(113); | |
| else if (!comptypes(gattr.typtr, intptr, LINK->LINK->LINK)) | |
| gen0t(58, gattr.typtr, LINK->LINK); | |
| } | |
| if (lattr.typtr != NULL) { | |
| WITH = lattr.typtr; | |
| if (comptypes(WITH->UU.U4.inxtype, gattr.typtr, LINK->LINK->LINK)) { | |
| if (WITH->UU.U4.inxtype != NULL) { | |
| getbounds(WITH->UU.U4.inxtype, &lmin, &lmax); | |
| if (debug) /*chk*/ | |
| gen2t(45, lmin, lmax, intptr, LINK->LINK); | |
| if (lmin > 0) /*dec*/ | |
| gen1t(31, lmin, intptr, LINK->LINK); | |
| else if (lmin < 0) | |
| gen1t(34, -lmin, intptr, LINK->LINK); | |
| /*or simply gen1(31,lmin)*/ | |
| } | |
| } else | |
| error(139); | |
| gattr.typtr = WITH->UU.U4.aeltype; | |
| gattr.kind = varbl; | |
| gattr.UU.U1.access = indrct; | |
| gattr.UU.U1.UU.idplmt = 0; | |
| if (gattr.typtr != NULL) { | |
| lsize = gattr.typtr->size; | |
| align(gattr.typtr, &lsize); /*ixa*/ | |
| gen1(36, lsize, LINK->LINK); | |
| } | |
| } | |
| } while (sy == comma); | |
| if (sy == rbrack) | |
| insymbol(); | |
| else | |
| error(12); | |
| } /*if sy = lbrack*/ | |
| else { | |
| /*.*/ | |
| if (sy == period) { | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != records) { | |
| error(140); | |
| gattr.typtr = NULL; | |
| } | |
| } | |
| insymbol(); | |
| if (sy == ident) { /*with gattr*/ | |
| if (gattr.typtr != NULL) { | |
| searchsection(gattr.typtr->UU.U5.fstfld, &lcp); | |
| if (lcp == NULL) { | |
| error(152); | |
| gattr.typtr = NULL; | |
| } else { | |
| gattr.typtr = lcp->idtype; | |
| switch (gattr.UU.U1.access) { | |
| case drct: | |
| gattr.UU.U1.UU.U0.dplmt += lcp->UU.fldaddr; | |
| break; | |
| case indrct: | |
| gattr.UU.U1.UU.idplmt += lcp->UU.fldaddr; | |
| break; | |
| case inxd: | |
| error(400); | |
| break; | |
| } | |
| } | |
| } | |
| insymbol(); | |
| } /*sy = ident*/ | |
| else | |
| error(2); | |
| } /*if sy = period*/ | |
| else { | |
| /*^*/ | |
| if (gattr.typtr != NULL) { | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == pointer) { | |
| load(LINK->LINK); | |
| gattr.typtr = WITH->UU.eltype; | |
| if (debug) /*chk*/ | |
| gen2t(45, 1, maxaddr, nilptr, LINK->LINK); | |
| gattr.kind = varbl; | |
| gattr.UU.U1.access = indrct; | |
| gattr.UU.U1.UU.idplmt = 0; | |
| } else { | |
| if ((structform)WITH->form == files) | |
| gattr.typtr = WITH->UU.filtype; | |
| else | |
| error(141); | |
| } | |
| } | |
| insymbol(); | |
| } | |
| } | |
| if (!P_inset(sy, P_setunion(SET, fsys, selectsys))) { | |
| error(6); | |
| skip(P_setunion(SET1, fsys, selectsys), LINK->LINK->LINK); | |
| } | |
| } /*while*/ | |
| /*ord*/ | |
| /*inc*/ | |
| } | |
| /* Local variables for call: */ | |
| struct LOC_call { | |
| struct LOC_statement *LINK; | |
| setofsys fsys; | |
| identifier *fcp; | |
| char lkey; | |
| } ; | |
| Local void variable(long *fsys, struct LOC_call *LINK) | |
| { | |
| identifier *lcp; | |
| /*variable*/ | |
| if (sy == ident) { | |
| searchid((1L << ((long)vars)) | (1L << ((long)field)), &lcp); | |
| insymbol(); | |
| } else { | |
| error(2); | |
| lcp = uvarptr; | |
| } | |
| selector(fsys, lcp, LINK->LINK); | |
| } | |
| Local void getputresetrewrite(struct LOC_call *LINK) | |
| { | |
| setofsys SET, SET1; | |
| /*getputresetrewrite*/ | |
| variable(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)rparent))), | |
| LINK); | |
| loadaddress(LINK->LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != files) | |
| error(116); | |
| } | |
| if (LINK->lkey <= 2) /*csp*/ | |
| gen1(30, LINK->lkey, LINK->LINK->LINK); | |
| else | |
| error(399); | |
| /*get,put*/ | |
| } | |
| Local void read(struct LOC_call *LINK) | |
| { | |
| levrange llev; | |
| addrrange laddr; | |
| structure *lsp; | |
| setofsys SET, SET1; | |
| /*read*/ | |
| llev = 1; | |
| laddr = lcaftermarkstack; | |
| if (sy == lparent) { | |
| insymbol(); | |
| variable(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| lsp = gattr.typtr; | |
| LINK->LINK->LINK->LINK->test = false; | |
| if (lsp != NULL) { | |
| if ((structform)lsp->form == files) { | |
| if (lsp->UU.filtype == charptr) { | |
| llev = gattr.UU.U1.UU.U0.vlevel; | |
| laddr = gattr.UU.U1.UU.U0.dplmt; | |
| } else | |
| error(399); | |
| if (sy == rparent) { | |
| if (LINK->lkey == 5) | |
| error(116); | |
| LINK->LINK->LINK->LINK->test = true; | |
| } else { | |
| if (sy != comma) { | |
| error(116); | |
| skip(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK->LINK->LINK); | |
| } | |
| } | |
| if (sy == comma) { | |
| insymbol(); | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| } else | |
| LINK->LINK->LINK->LINK->test = true; | |
| } | |
| } | |
| if (!LINK->LINK->LINK->LINK->test) { | |
| do { | |
| loadaddress(LINK->LINK->LINK); /*lda*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form <= subrange) { | |
| if (comptypes(intptr, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| /*csp*/ | |
| gen1(30, 3, LINK->LINK->LINK); | |
| else { | |
| if (comptypes(realptr, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| /*csp*/ | |
| gen1(30, 4, LINK->LINK->LINK); | |
| else { | |
| if (comptypes(charptr, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| /*csp*/ | |
| gen1(30, 5, LINK->LINK->LINK); | |
| else | |
| error(399); | |
| /*rdc*/ | |
| } | |
| /*rdr*/ | |
| } | |
| /*rdi*/ | |
| } else | |
| error(116); | |
| } | |
| LINK->LINK->LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->LINK->LINK->test) { | |
| insymbol(); | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| } | |
| } while (!LINK->LINK->LINK->LINK->test); | |
| } | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| } else if (LINK->lkey == 5) | |
| error(116); | |
| if (LINK->lkey == 11) { /*lda*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); /*csp*/ | |
| /*rln*/ | |
| gen1(30, 21, LINK->LINK->LINK); | |
| } | |
| } | |
| Local void write(struct LOC_call *LINK) | |
| { | |
| structure *lsp; | |
| boolean default_; | |
| char llkey; | |
| levrange llev; | |
| addrrange laddr, len; | |
| setofsys SET, SET1; | |
| /*write*/ | |
| llkey = LINK->lkey; | |
| llev = 1; | |
| laddr = lcaftermarkstack + charmax; | |
| if (sy == lparent) { | |
| insymbol(); | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)colon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| lsp = gattr.typtr; | |
| LINK->LINK->LINK->LINK->test = false; | |
| if (lsp != NULL) { | |
| if ((structform)lsp->form == files) { | |
| if (lsp->UU.filtype == charptr) { | |
| llev = gattr.UU.U1.UU.U0.vlevel; | |
| laddr = gattr.UU.U1.UU.U0.dplmt; | |
| } else | |
| error(399); | |
| if (sy == rparent) { | |
| if (llkey == 6) | |
| error(116); | |
| LINK->LINK->LINK->LINK->test = true; | |
| } else { | |
| if (sy != comma) { | |
| error(116); | |
| skip(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK->LINK->LINK); | |
| } | |
| } | |
| if (sy == comma) { | |
| insymbol(); | |
| expression(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)colon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| } else | |
| LINK->LINK->LINK->LINK->test = true; | |
| } | |
| } | |
| if (!LINK->LINK->LINK->LINK->test) { | |
| do { | |
| lsp = gattr.typtr; | |
| if (lsp != NULL) { | |
| if ((structform)lsp->form <= subrange) | |
| load(LINK->LINK->LINK); | |
| else | |
| loadaddress(LINK->LINK->LINK); | |
| } | |
| if (sy == colon) { | |
| insymbol(); | |
| expression(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)colon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if (gattr.typtr != intptr) | |
| error(116); | |
| } | |
| load(LINK->LINK->LINK); | |
| default_ = false; | |
| } else | |
| default_ = true; | |
| if (sy == colon) { | |
| insymbol(); | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if (gattr.typtr != intptr) | |
| error(116); | |
| } | |
| if (lsp != realptr) | |
| error(124); | |
| load(LINK->LINK->LINK); | |
| error(399); | |
| } else { | |
| if (lsp == intptr) { | |
| if (default_) /*ldc*/ | |
| gen2(51, 1, 10, LINK->LINK->LINK); | |
| /*lda*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); /*csp*/ | |
| /*wri*/ | |
| gen1(30, 6, LINK->LINK->LINK); | |
| } else { | |
| if (lsp == realptr) { | |
| if (default_) /*ldc*/ | |
| gen2(51, 1, 20, LINK->LINK->LINK); | |
| /*lda*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); /*csp*/ | |
| /*wrr*/ | |
| gen1(30, 8, LINK->LINK->LINK); | |
| } else { | |
| if (lsp == charptr) { | |
| if (default_) /*ldc*/ | |
| gen2(51, 1, 1, LINK->LINK->LINK); | |
| /*lda*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); /*csp*/ | |
| /*wrc*/ | |
| gen1(30, 9, LINK->LINK->LINK); | |
| } else { | |
| if (lsp != NULL) { | |
| if ((structform)lsp->form == scalar) | |
| error(399); | |
| else { | |
| if (string(lsp, LINK->LINK->LINK->LINK)) { | |
| len = lsp->size; | |
| if (default_) /*ldc*/ | |
| gen2(51, 1, len, LINK->LINK->LINK); | |
| /*ldc*/ | |
| gen2(51, 1, len, LINK->LINK->LINK); /*lda*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); | |
| /*csp*/ | |
| /*wrs*/ | |
| gen1(30, 10, LINK->LINK->LINK); | |
| } else | |
| error(116); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| LINK->LINK->LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->LINK->LINK->test) { | |
| insymbol(); | |
| expression(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)colon)) | | |
| (1L << ((long)rparent)))), LINK->LINK); | |
| } | |
| } while (!LINK->LINK->LINK->LINK->test); | |
| } | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| } else if (LINK->lkey == 6) | |
| error(116); | |
| if (llkey == 12) { /*writeln*/ | |
| gen2(50, level – llev, laddr, LINK->LINK->LINK); /*csp*/ | |
| /*wln*/ | |
| gen1(30, 22, LINK->LINK->LINK); | |
| } | |
| /*lda*/ | |
| } | |
| Local void pack(struct LOC_call *LINK) | |
| { | |
| structure *lsp, *lsp1; | |
| setofsys SET, SET1; | |
| structure *WITH; | |
| /*pack*/ | |
| error(399); | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| lsp = NULL; | |
| lsp1 = NULL; | |
| if (gattr.typtr != NULL) { | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == arrays) { | |
| lsp = WITH->UU.U4.inxtype; | |
| lsp1 = WITH->UU.U4.aeltype; | |
| } else | |
| error(116); | |
| } | |
| if (sy == comma) | |
| insymbol(); | |
| else | |
| error(20); | |
| expression(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != scalar) | |
| error(116); | |
| else { | |
| if (!comptypes(lsp, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| error(116); | |
| } | |
| } | |
| if (sy == comma) | |
| insymbol(); | |
| else | |
| error(20); | |
| variable(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)rparent))), | |
| LINK); | |
| if (gattr.typtr == NULL) | |
| return; | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == arrays) { | |
| if ((!comptypes(WITH->UU.U4.aeltype, lsp1, LINK->LINK->LINK->LINK)) | | |
| (!comptypes(WITH->UU.U4.inxtype, lsp, LINK->LINK->LINK->LINK))) | |
| error(116); | |
| } else | |
| error(116); | |
| } | |
| Local void unpack(struct LOC_call *LINK) | |
| { | |
| structure *lsp, *lsp1; | |
| setofsys SET, SET1; | |
| structure *WITH; | |
| /*unpack*/ | |
| error(399); | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| lsp = NULL; | |
| lsp1 = NULL; | |
| if (gattr.typtr != NULL) { | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == arrays) { | |
| lsp = WITH->UU.U4.inxtype; | |
| lsp1 = WITH->UU.U4.aeltype; | |
| } else | |
| error(116); | |
| } | |
| if (sy == comma) | |
| insymbol(); | |
| else | |
| error(20); | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| if (gattr.typtr != NULL) { | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == arrays) { | |
| if ((!comptypes(WITH->UU.U4.aeltype, lsp1, LINK->LINK->LINK->LINK)) | | |
| (!comptypes(WITH->UU.U4.inxtype, lsp, LINK->LINK->LINK->LINK))) | |
| error(116); | |
| } else | |
| error(116); | |
| } | |
| if (sy == comma) | |
| insymbol(); | |
| else | |
| error(20); | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)rparent))), LINK->LINK); | |
| if (gattr.typtr == NULL) | |
| return; | |
| if ((structform)gattr.typtr->form != scalar) | |
| error(116); | |
| else { | |
| if (!comptypes(lsp, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| error(116); | |
| } | |
| } | |
| Local void new_(struct LOC_call *LINK) | |
| { | |
| structure *lsp, *lsp1; | |
| long varts; | |
| addrrange lsize; | |
| valu lval; | |
| setofsys SET, SET1; | |
| structure *WITH; | |
| /*new*/ | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK); | |
| loadaddress(LINK->LINK->LINK); | |
| lsp = NULL; | |
| varts = 0; | |
| lsize = 0; | |
| if (gattr.typtr != NULL) { | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == pointer) { | |
| if (WITH->UU.eltype != NULL) { | |
| lsize = WITH->UU.eltype->size; | |
| if ((structform)WITH->UU.eltype->form == records) | |
| lsp = WITH->UU.eltype->UU.U5.recvar; | |
| } | |
| } else | |
| error(116); | |
| } | |
| while (sy == comma) { /*while*/ | |
| insymbol(); | |
| constant_(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| &lsp1, &lval, LINK->LINK->LINK->LINK); | |
| varts++; | |
| /*check to insert here: is constant in tagfieldtype range*/ | |
| if (lsp == NULL) | |
| error(158); | |
| else { | |
| if ((structform)lsp->form != tagfld) | |
| error(162); | |
| else { | |
| if (lsp->UU.U7.tagfieldp != NULL) { | |
| if (string(lsp1, LINK->LINK->LINK->LINK) || lsp1 == realptr) | |
| error(159); | |
| else { | |
| if (comptypes(lsp->UU.U7.tagfieldp->idtype, lsp1, | |
| LINK->LINK->LINK->LINK)) { | |
| lsp1 = lsp->UU.U7.fstvar; | |
| while (lsp1 != NULL) { | |
| WITH = lsp1; | |
| if (WITH->UU.U8.varval.UU.ival == lval.UU.ival) { | |
| lsize = WITH->size; | |
| lsp = WITH->UU.U8.subvar; | |
| goto _L1; | |
| } | |
| lsp1 = WITH->UU.U8.nxtvar; | |
| } | |
| lsize = lsp->size; | |
| lsp = NULL; | |
| } else | |
| error(116); | |
| } | |
| } | |
| } | |
| } | |
| _L1: ; | |
| } | |
| /*ldc*/ | |
| gen2(51, 1, lsize, LINK->LINK->LINK); /*csp*/ | |
| /*new*/ | |
| gen1(30, 12, LINK->LINK->LINK); | |
| } | |
| Local void mark__(struct LOC_call *LINK) | |
| { | |
| setofsys SET, SET1; | |
| /*mark*/ | |
| variable(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)rparent))), | |
| LINK); | |
| if (gattr.typtr == NULL) | |
| return; | |
| if ((structform)gattr.typtr->form == pointer) { | |
| loadaddress(LINK->LINK->LINK); /*csp*/ | |
| /*sav*/ | |
| gen1(30, 23, LINK->LINK->LINK); | |
| } else | |
| error(116); | |
| } | |
| Local void release__(struct LOC_call *LINK) | |
| { | |
| setofsys SET, SET1; | |
| /*release*/ | |
| variable(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)rparent))), | |
| LINK); | |
| if (gattr.typtr == NULL) | |
| return; | |
| if ((structform)gattr.typtr->form == pointer) { | |
| load(LINK->LINK->LINK); /*csp*/ | |
| /*rst*/ | |
| gen1(30, 13, LINK->LINK->LINK); | |
| } else | |
| error(116); | |
| } | |
| Local void abs_(struct LOC_call *LINK) | |
| { | |
| /*abs*/ | |
| if (gattr.typtr == NULL) | |
| return; | |
| if (gattr.typtr == intptr) { /*abi*/ | |
| gen0(0, LINK->LINK->LINK); | |
| return; | |
| } | |
| if (gattr.typtr == realptr) /*abr*/ | |
| gen0(1, LINK->LINK->LINK); | |
| else { | |
| error(125); | |
| gattr.typtr = intptr; | |
| } | |
| } | |
| Local void sqr_(struct LOC_call *LINK) | |
| { | |
| /*sqr*/ | |
| if (gattr.typtr == NULL) | |
| return; | |
| if (gattr.typtr == intptr) { /*sqi*/ | |
| gen0(24, LINK->LINK->LINK); | |
| return; | |
| } | |
| if (gattr.typtr == realptr) /*sqr*/ | |
| gen0(25, LINK->LINK->LINK); | |
| else { | |
| error(125); | |
| gattr.typtr = intptr; | |
| } | |
| } | |
| Local void trunc_(struct LOC_call *LINK) | |
| { | |
| /*trunc*/ | |
| if (gattr.typtr != NULL) { /*trc*/ | |
| if (gattr.typtr != realptr) | |
| error(125); | |
| } | |
| gen0(27, LINK->LINK->LINK); | |
| gattr.typtr = intptr; | |
| } | |
| Local void odd_(struct LOC_call *LINK) | |
| { | |
| /*odd*/ | |
| if (gattr.typtr != NULL) { /*odd*/ | |
| if (gattr.typtr != intptr) | |
| error(125); | |
| } | |
| gen0(20, LINK->LINK->LINK); | |
| gattr.typtr = boolptr; | |
| } | |
| Local void ord_(struct LOC_call *LINK) | |
| { | |
| /*ord*/ | |
| if (gattr.typtr != NULL) { /*ord*/ | |
| if ((structform)gattr.typtr->form >= power) | |
| error(125); | |
| } | |
| gen0t(58, gattr.typtr, LINK->LINK->LINK); | |
| gattr.typtr = intptr; | |
| } | |
| Local void chr_(struct LOC_call *LINK) | |
| { | |
| /*chr*/ | |
| if (gattr.typtr != NULL) { /*chr*/ | |
| if (gattr.typtr != intptr) | |
| error(125); | |
| } | |
| gen0(59, LINK->LINK->LINK); | |
| gattr.typtr = charptr; | |
| } | |
| Local void predsucc(struct LOC_call *LINK) | |
| { | |
| /*predsucc*/ | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != scalar) | |
| error(125); | |
| } | |
| if (LINK->lkey == 7) /*dec*/ | |
| gen1t(31, 1, gattr.typtr, LINK->LINK->LINK); | |
| else /*inc*/ | |
| gen1t(34, 1, gattr.typtr, LINK->LINK->LINK); | |
| } | |
| Local void eof_(struct LOC_call *LINK) | |
| { | |
| setofsys SET, SET1; | |
| /*eof*/ | |
| if (sy == lparent) { | |
| insymbol(); | |
| variable(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, 1L << ((long)rparent))), LINK); | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| } else { | |
| gattr.typtr = textptr; | |
| gattr.kind = varbl; | |
| gattr.UU.U1.access = drct; | |
| gattr.UU.U1.UU.U0.vlevel = 1; | |
| gattr.UU.U1.UU.U0.dplmt = lcaftermarkstack; | |
| } | |
| loadaddress(LINK->LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != files) | |
| error(125); | |
| } | |
| if (LINK->lkey == 9) /*eof*/ | |
| gen0(8, LINK->LINK->LINK); | |
| else /*csp*/ | |
| gen1(30, 14, LINK->LINK->LINK); | |
| gattr.typtr = boolptr; | |
| /*eln*/ | |
| } | |
| Local void callnonstandard(struct LOC_call *LINK) | |
| { | |
| identifier *nxt, *lcp; | |
| structure *lsp; | |
| idkind lkind; | |
| boolean lb; | |
| addrrange locpar, llc; | |
| identifier *WITH; | |
| setofsys SET, SET1, SET2, SET3; | |
| /*callnonstandard*/ | |
| locpar = 0; | |
| WITH = LINK->fcp; | |
| nxt = WITH->next; | |
| lkind = (idkind)WITH->UU.U4.UU.U1.pfkind; | |
| if (!WITH->UU.U4.UU.U1.UU.U0.externl) /*mst*/ | |
| gen1(41, level – WITH->UU.U4.UU.U1.pflev, LINK->LINK->LINK); | |
| if (sy == lparent) { /*if lparent*/ | |
| llc = lc; | |
| do { | |
| lb = false; /*decide whether proc/func must be passed*/ | |
| if (lkind == actual) { | |
| if (nxt == NULL) | |
| error(126); | |
| else | |
| lb = (((1L << nxt->klass) & | |
| ((1L << ((long)proc)) | (1L << ((long)func)))) != 0); | |
| } else | |
| error(399); | |
| /*For formal proc/func, lb is false and expression | |
| will be called, which will always interpret a proc/func id | |
| at its beginning as a call rather than a parameter passing. | |
| In this implementation, parameter procedures/functions | |
| are therefore not allowed to have procedure/function | |
| parameters*/ | |
| insymbol(); | |
| if (lb) { /*pass function or procedure*/ | |
| error(399); | |
| if (sy != ident) { | |
| error(2); | |
| skip(P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK->LINK->LINK); | |
| } else { | |
| if ((idclass)nxt->klass == proc) | |
| searchid(1L << ((long)proc), &lcp); | |
| else { | |
| searchid(1L << ((long)func), &lcp); | |
| if (!comptypes(lcp->idtype, nxt->idtype, LINK->LINK->LINK->LINK)) | |
| error(128); | |
| } | |
| insymbol(); | |
| if (!P_inset(sy, P_setunion(SET1, LINK->fsys, P_expset(SET, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))))) { | |
| error(6); | |
| skip(P_setunion(SET3, LINK->fsys, | |
| P_expset(SET2, | |
| (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK->LINK->LINK); | |
| } | |
| } | |
| } /*if lb*/ | |
| else { | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rparent)))), | |
| LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if (lkind == actual) { | |
| if (nxt != NULL) { | |
| lsp = nxt->idtype; | |
| if (lsp != NULL) { | |
| if ((idkind)nxt->UU.U2.vkind == actual) { | |
| if ((structform)lsp->form <= power) { | |
| load(LINK->LINK->LINK); | |
| if (debug) | |
| checkbnds(lsp, LINK->LINK->LINK); | |
| if (comptypes(realptr, lsp, LINK->LINK->LINK->LINK) && | |
| gattr.typtr == intptr) | |
| { /*flt*/ | |
| gen0(10, LINK->LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| locpar += lsp->size; | |
| align(parmptr, &locpar); | |
| } else { | |
| loadaddress(LINK->LINK->LINK); | |
| locpar += ptrsize; | |
| align(parmptr, &locpar); | |
| } | |
| } else { | |
| if (gattr.kind == varbl) { | |
| loadaddress(LINK->LINK->LINK); | |
| locpar += ptrsize; | |
| align(parmptr, &locpar); | |
| } else | |
| error(154); | |
| } | |
| if (!comptypes(lsp, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| error(142); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (lkind == actual && nxt != NULL) | |
| nxt = nxt->next; | |
| } while (sy == comma); | |
| lc = llc; | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| } | |
| if (lkind == actual) { | |
| if (nxt != NULL) | |
| error(126); | |
| WITH = LINK->fcp; | |
| if (WITH->UU.U4.UU.U1.UU.U0.externl) /*csp*/ | |
| gen1(30, WITH->UU.U4.UU.U1.pfname, LINK->LINK->LINK); | |
| else /*cup*/ | |
| gencupent(46, locpar, WITH->UU.U4.UU.U1.pfname, LINK->LINK->LINK); | |
| } | |
| gattr.typtr = LINK->fcp->idtype; | |
| /*lkind = formal*/ | |
| /*pass formal param*/ | |
| } | |
| Local void call(long *fsys_, identifier *fcp_, struct LOC_statement *LINK) | |
| { | |
| struct LOC_call V; | |
| setofsys SET, SET1; | |
| V.LINK = LINK; | |
| /*call*/ | |
| P_setcpy(V.fsys, fsys_); | |
| V.fcp = fcp_; | |
| if ((declkind)V.fcp->UU.U4.pfdeckind != standard) { | |
| callnonstandard(&V); | |
| return; | |
| } /*standard procedures and functions*/ | |
| V.lkey = V.fcp->UU.U4.UU.key; | |
| if ((idclass)V.fcp->klass == proc) { | |
| if (((1L << V.lkey) & 0x1860) == 0) { | |
| if (sy == lparent) | |
| insymbol(); | |
| else | |
| error(9); | |
| } | |
| switch (V.lkey) { | |
| case 1: | |
| case 2: | |
| case 3: | |
| case 4: | |
| getputresetrewrite(&V); | |
| break; | |
| case 5: | |
| case 11: | |
| read(&V); | |
| break; | |
| case 6: | |
| case 12: | |
| write(&V); | |
| break; | |
| case 7: | |
| pack(&V); | |
| break; | |
| case 8: | |
| unpack(&V); | |
| break; | |
| case 9: | |
| new_(&V); | |
| break; | |
| case 10: | |
| release__(&V); | |
| break; | |
| case 13: | |
| mark__(&V); | |
| break; | |
| } | |
| if (((1L << V.lkey) & 0x1860) != 0) | |
| return; | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| return; | |
| } | |
| if (V.lkey <= 8) { | |
| if (sy == lparent) | |
| insymbol(); | |
| else | |
| error(9); | |
| expression(P_setunion(SET1, V.fsys, P_expset(SET, 1L << ((long)rparent))), | |
| LINK); | |
| load(LINK->LINK); | |
| } | |
| switch (V.lkey) { | |
| case 1: | |
| abs_(&V); | |
| break; | |
| case 2: | |
| sqr_(&V); | |
| break; | |
| case 3: | |
| trunc_(&V); | |
| break; | |
| case 4: | |
| odd_(&V); | |
| break; | |
| case 5: | |
| ord_(&V); | |
| break; | |
| case 6: | |
| chr_(&V); | |
| break; | |
| case 7: | |
| case 8: | |
| predsucc(&V); | |
| break; | |
| case 9: | |
| case 10: | |
| eof_(&V); | |
| break; | |
| } | |
| if (V.lkey > 8) | |
| return; | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| } | |
| /* Local variables for expression: */ | |
| struct LOC_expression { | |
| struct LOC_statement *LINK; | |
| } ; | |
| /* Local variables for simpleexpression: */ | |
| struct LOC_simpleexpression { | |
| struct LOC_expression *LINK; | |
| } ; | |
| /* Local variables for term: */ | |
| struct LOC_term { | |
| struct LOC_simpleexpression *LINK; | |
| } ; | |
| Local void factor(long *fsys, struct LOC_term *LINK) | |
| { | |
| identifier *lcp; | |
| constant *lvp; | |
| boolean varpart; | |
| setty cstpart; | |
| structure *lsp; | |
| setofsys SET; | |
| structure *WITH; | |
| setofsys SET1; | |
| /*factor*/ | |
| if (!P_inset(sy, facbegsys)) { | |
| error(58); | |
| skip(P_setunion(SET, fsys, facbegsys), LINK->LINK->LINK->LINK->LINK->LINK); | |
| gattr.typtr = NULL; | |
| } | |
| while (P_inset(sy, facbegsys)) { | |
| switch (sy) { /*case*/ | |
| /*id*/ | |
| case ident: | |
| searchid((1L << ((long)konst)) | (1L << ((long)vars)) | | |
| (1L << ((long)field)) | (1L << ((long)func)), &lcp); | |
| insymbol(); | |
| if ((idclass)lcp->klass == func) { | |
| call(fsys, lcp, LINK->LINK->LINK->LINK); | |
| gattr.kind = expr; | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form == subrange) | |
| gattr.typtr = gattr.typtr->UU.U1.rangetype; | |
| } | |
| } else { | |
| if ((idclass)lcp->klass == konst) { | |
| gattr.typtr = lcp->idtype; | |
| gattr.kind = cst; | |
| gattr.UU.cval = lcp->UU.values; | |
| } else { | |
| selector(fsys, lcp, LINK->LINK->LINK->LINK); | |
| if (gattr.typtr != NULL) { /*elim.subr.types to*/ | |
| WITH = gattr.typtr; | |
| if ((structform)WITH->form == subrange) | |
| gattr.typtr = WITH->UU.U1.rangetype; | |
| } | |
| /*simplify later tests*/ | |
| } | |
| } | |
| break; | |
| /*cst*/ | |
| case intconst: | |
| gattr.typtr = intptr; | |
| gattr.kind = cst; | |
| gattr.UU.cval = val; | |
| insymbol(); | |
| break; | |
| case realconst: | |
| gattr.typtr = realptr; | |
| gattr.kind = cst; | |
| gattr.UU.cval = val; | |
| insymbol(); | |
| break; | |
| case stringconst: | |
| if (lgth == 1) | |
| gattr.typtr = charptr; | |
| else { | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.U4.aeltype = charptr; | |
| (structform)lsp->form = arrays; | |
| lsp->UU.U4.inxtype = NULL; | |
| lsp->size = lgth; | |
| gattr.typtr = lsp; | |
| } | |
| gattr.kind = cst; | |
| gattr.UU.cval = val; | |
| insymbol(); | |
| break; | |
| /* ( */ | |
| case lparent: | |
| insymbol(); | |
| expression(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)rparent))), | |
| LINK->LINK->LINK->LINK); | |
| if (sy == rparent) | |
| insymbol(); | |
| else | |
| error(4); | |
| break; | |
| /*not*/ | |
| case notsy: | |
| insymbol(); | |
| factor(fsys, LINK); | |
| load(LINK->LINK->LINK->LINK->LINK); /*not*/ | |
| gen0(19, LINK->LINK->LINK->LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if (gattr.typtr != boolptr) { | |
| error(135); | |
| gattr.typtr = NULL; | |
| } | |
| } | |
| break; | |
| /*[*/ | |
| case lbrack: | |
| insymbol(); | |
| P_expset(cstpart, 0); | |
| varpart = false; | |
| /* p2c: pcom.p, line 2831: | |
| * Note: No SpecialMalloc form known for STRUCTURE.POWER [187] */ | |
| lsp = Malloc(sizeof(structure)); | |
| lsp->UU.elset = NULL; | |
| lsp->size = setsize; | |
| (structform)lsp->form = power; | |
| if (sy == rbrack) { | |
| gattr.typtr = lsp; | |
| gattr.kind = cst; | |
| insymbol(); | |
| } else { | |
| do { | |
| expression(P_setunion(SET1, fsys, | |
| P_expset(SET, (1L << ((long)comma)) | (1L << ((long)rbrack)))), | |
| LINK->LINK->LINK->LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != scalar) { | |
| error(136); | |
| gattr.typtr = NULL; | |
| } else { | |
| if (comptypes(lsp->UU.elset, gattr.typtr, | |
| LINK->LINK->LINK->LINK->LINK->LINK)) { | |
| if (gattr.kind == cst) { | |
| if ((unsigned long)gattr.UU.cval.UU.ival > sethigh) | |
| error(304); | |
| else | |
| P_addset(cstpart, gattr.UU.cval.UU.ival); | |
| } else { | |
| load(LINK->LINK->LINK->LINK->LINK); | |
| if (!comptypes(gattr.typtr, intptr, | |
| LINK->LINK->LINK->LINK->LINK->LINK)) | |
| /*ord*/ | |
| gen0t(58, gattr.typtr, LINK->LINK->LINK->LINK->LINK); | |
| /*sgs*/ | |
| gen0(23, LINK->LINK->LINK->LINK->LINK); | |
| if (varpart) /*uni*/ | |
| gen0(28, LINK->LINK->LINK->LINK->LINK); | |
| else | |
| varpart = true; | |
| } | |
| lsp->UU.elset = gattr.typtr; | |
| gattr.typtr = lsp; | |
| } else | |
| error(137); | |
| } | |
| } | |
| LINK->LINK->LINK->LINK->LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->LINK->LINK->LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->LINK->LINK->LINK->LINK->test); | |
| if (sy == rbrack) | |
| insymbol(); | |
| else | |
| error(12); | |
| } | |
| if (varpart) { | |
| if (*cstpart != 0) { | |
| lvp = Malloc(sizeof(constant)); | |
| P_setcpy(lvp->UU.pval, cstpart); | |
| lvp->cclass = pset; | |
| if (LINK->LINK->LINK->LINK->LINK->cstptrix == cstoccmax) | |
| error(254); | |
| else { | |
| LINK->LINK->LINK->LINK->LINK->cstptrix++; | |
| LINK->LINK->LINK->LINK->LINK->cstptr[LINK->LINK->LINK->LINK-> | |
| LINK->cstptrix – 1] = lvp; | |
| /*ldc*/ | |
| gen2(51, 5, LINK->LINK->LINK->LINK->LINK->cstptrix, | |
| LINK->LINK->LINK->LINK->LINK); | |
| /*uni*/ | |
| gen0(28, LINK->LINK->LINK->LINK->LINK); | |
| gattr.kind = expr; | |
| } | |
| } | |
| /* p2c: pcom.p, line 2875: | |
| * Note: No SpecialMalloc form known for CONSTANT.PSET [187] */ | |
| } else { | |
| lvp = Malloc(sizeof(constant)); | |
| P_setcpy(lvp->UU.pval, cstpart); | |
| lvp->cclass = pset; | |
| gattr.UU.cval.UU.valp = lvp; | |
| } | |
| break; | |
| } | |
| if (!P_inset(sy, fsys)) { | |
| error(6); | |
| skip(P_setunion(SET, fsys, facbegsys), | |
| LINK->LINK->LINK->LINK->LINK->LINK); | |
| } | |
| } /*while*/ | |
| /* p2c: pcom.p, line 2807: | |
| * Note: No SpecialMalloc form known for STRUCTURE.ARRAYS [187] */ | |
| /* p2c: pcom.p, line 2887: | |
| * Note: No SpecialMalloc form known for CONSTANT.PSET [187] */ | |
| } | |
| Local void term(long *fsys, struct LOC_simpleexpression *LINK) | |
| { | |
| struct LOC_term V; | |
| attr lattr; | |
| operator_ lop; | |
| setofsys SET, SET1; | |
| V.LINK = LINK; | |
| /*term*/ | |
| factor(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)mulop))), &V); | |
| while (sy == mulop) { | |
| load(LINK->LINK->LINK->LINK); | |
| lattr = gattr; | |
| lop = op; | |
| insymbol(); | |
| factor(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)mulop))), &V); | |
| load(LINK->LINK->LINK->LINK); | |
| if (lattr.typtr == NULL || gattr.typtr == NULL) { | |
| gattr.typtr = NULL; | |
| continue; | |
| } | |
| switch (lop) { | |
| /***/ | |
| case mul: | |
| if (lattr.typtr == intptr && gattr.typtr == intptr) /*mpi*/ | |
| gen0(15, LINK->LINK->LINK->LINK); | |
| else { | |
| if (lattr.typtr == intptr) { /*flo*/ | |
| gen0(9, LINK->LINK->LINK->LINK); | |
| lattr.typtr = realptr; | |
| } else { | |
| if (gattr.typtr == intptr) { /*flt*/ | |
| gen0(10, LINK->LINK->LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| } | |
| if (lattr.typtr == realptr && gattr.typtr == realptr) /*mpr*/ | |
| gen0(16, LINK->LINK->LINK->LINK); | |
| else { | |
| if (((structform)lattr.typtr->form == power) & comptypes(lattr.typtr, | |
| gattr.typtr, LINK->LINK->LINK->LINK->LINK)) | |
| /*int*/ | |
| gen0(12, LINK->LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| } | |
| } | |
| break; | |
| /* / */ | |
| case rdiv: | |
| if (gattr.typtr == intptr) { /*flt*/ | |
| gen0(10, LINK->LINK->LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| if (lattr.typtr == intptr) { /*flo*/ | |
| gen0(9, LINK->LINK->LINK->LINK); | |
| lattr.typtr = realptr; | |
| } | |
| if (lattr.typtr == realptr && gattr.typtr == realptr) /*dvr*/ | |
| gen0(7, LINK->LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| break; | |
| /*div*/ | |
| case idiv: | |
| if (lattr.typtr == intptr && gattr.typtr == intptr) /*dvi*/ | |
| gen0(6, LINK->LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| break; | |
| /*mod*/ | |
| case imod: | |
| if (lattr.typtr == intptr && gattr.typtr == intptr) /*mod*/ | |
| gen0(14, LINK->LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| break; | |
| /*and*/ | |
| case andop: | |
| if (lattr.typtr == boolptr && gattr.typtr == boolptr) /*and*/ | |
| gen0(4, LINK->LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| break; | |
| }/*case*/ | |
| } /*while*/ | |
| } | |
| Local void simpleexpression(long *fsys, struct LOC_expression *LINK) | |
| { | |
| struct LOC_simpleexpression V; | |
| attr lattr; | |
| operator_ lop; | |
| boolean signed_; | |
| setofsys SET, SET1; | |
| V.LINK = LINK; | |
| /*simpleexpression*/ | |
| signed_ = false; | |
| if (sy == addop && | |
| ((1L << ((long)op)) & ((1L << ((long)plus)) | (1L << ((long)minus)))) != 0) { | |
| signed_ = (op == minus); | |
| insymbol(); | |
| } | |
| term(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)addop))), &V); | |
| if (signed_) { | |
| load(LINK->LINK->LINK); | |
| if (gattr.typtr == intptr) /*ngi*/ | |
| gen0(17, LINK->LINK->LINK); | |
| else { | |
| if (gattr.typtr == realptr) /*ngr*/ | |
| gen0(18, LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| } | |
| } | |
| while (sy == addop) { | |
| load(LINK->LINK->LINK); | |
| lattr = gattr; | |
| lop = op; | |
| insymbol(); | |
| term(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)addop))), &V); | |
| load(LINK->LINK->LINK); | |
| if (lattr.typtr == NULL || gattr.typtr == NULL) { | |
| gattr.typtr = NULL; | |
| continue; | |
| } | |
| switch (lop) { | |
| /*+*/ | |
| case plus: | |
| if (lattr.typtr == intptr && gattr.typtr == intptr) /*adi*/ | |
| gen0(2, LINK->LINK->LINK); | |
| else { | |
| if (lattr.typtr == intptr) { /*flo*/ | |
| gen0(9, LINK->LINK->LINK); | |
| lattr.typtr = realptr; | |
| } else { | |
| if (gattr.typtr == intptr) { /*flt*/ | |
| gen0(10, LINK->LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| } | |
| if (lattr.typtr == realptr && gattr.typtr == realptr) /*adr*/ | |
| gen0(3, LINK->LINK->LINK); | |
| else if (((structform)lattr.typtr->form == power) & | |
| comptypes(lattr.typtr, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| gen0(28, LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| } | |
| break; | |
| /*-*/ | |
| case minus: | |
| if (lattr.typtr == intptr && gattr.typtr == intptr) /*sbi*/ | |
| gen0(21, LINK->LINK->LINK); | |
| else { | |
| if (lattr.typtr == intptr) { /*flo*/ | |
| gen0(9, LINK->LINK->LINK); | |
| lattr.typtr = realptr; | |
| } else { | |
| if (gattr.typtr == intptr) { /*flt*/ | |
| gen0(10, LINK->LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| } | |
| if (lattr.typtr == realptr && gattr.typtr == realptr) /*sbr*/ | |
| gen0(22, LINK->LINK->LINK); | |
| else { | |
| if (((structform)lattr.typtr->form == power) & | |
| comptypes(lattr.typtr, gattr.typtr, LINK->LINK->LINK->LINK)) | |
| /*dif*/ | |
| gen0(5, LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| } | |
| } | |
| break; | |
| /*or*/ | |
| case orop: | |
| if (lattr.typtr == boolptr && gattr.typtr == boolptr) /*ior*/ | |
| gen0(13, LINK->LINK->LINK); | |
| else { | |
| error(134); | |
| gattr.typtr = NULL; | |
| } | |
| break; | |
| }/*case*/ | |
| } /*while*/ | |
| /*uni*/ | |
| } | |
| Local void expression(long *fsys, struct LOC_statement *LINK) | |
| { | |
| struct LOC_expression V; | |
| attr lattr; | |
| operator_ lop; | |
| Char typind; | |
| addrrange lsize; | |
| setofsys SET, SET1; | |
| V.LINK = LINK; | |
| /*expression*/ | |
| simpleexpression(P_setunion(SET1, fsys, P_expset(SET, 1L << ((long)relop))), | |
| &V); | |
| if (sy != relop) { | |
| return; | |
| } /*sy = relop*/ | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form <= power) | |
| load(LINK->LINK); | |
| else | |
| loadaddress(LINK->LINK); | |
| } | |
| lattr = gattr; | |
| lop = op; | |
| if (lop == inop) { | |
| if (!comptypes(gattr.typtr, intptr, LINK->LINK->LINK)) /*ord*/ | |
| gen0t(58, gattr.typtr, LINK->LINK); | |
| } | |
| insymbol(); | |
| simpleexpression(fsys, &V); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form <= power) | |
| load(LINK->LINK); | |
| else | |
| loadaddress(LINK->LINK); | |
| } | |
| if (lattr.typtr != NULL && gattr.typtr != NULL) { | |
| if (lop == inop) { | |
| if ((structform)gattr.typtr->form == power) { | |
| if (comptypes(lattr.typtr, gattr.typtr->UU.elset, LINK->LINK->LINK)) | |
| /*inn*/ | |
| gen0(11, LINK->LINK); | |
| else { | |
| error(129); | |
| gattr.typtr = NULL; | |
| } | |
| } else { | |
| error(130); | |
| gattr.typtr = NULL; | |
| } | |
| } else { | |
| if (lattr.typtr != gattr.typtr) { | |
| if (lattr.typtr == intptr) { /*flo*/ | |
| gen0(9, LINK->LINK); | |
| lattr.typtr = realptr; | |
| } else { | |
| if (gattr.typtr == intptr) { /*flt*/ | |
| gen0(10, LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| } | |
| } | |
| if (comptypes(lattr.typtr, gattr.typtr, LINK->LINK->LINK)) { | |
| lsize = lattr.typtr->size; | |
| switch ((structform)lattr.typtr->form) { | |
| case scalar: | |
| if (lattr.typtr == realptr) | |
| typind = 'r'; | |
| else { | |
| if (lattr.typtr == boolptr) | |
| typind = 'b'; | |
| else { | |
| if (lattr.typtr == charptr) | |
| typind = 'c'; | |
| else | |
| typind = 'i'; | |
| } | |
| } | |
| break; | |
| case pointer: | |
| if (((1L << ((long)lop)) & ((1L << ((long)ltop)) | (1L << ((long)leop)) | | |
| (1L << ((long)gtop)) | (1L << ((long)geop)))) != 0) | |
| error(131); | |
| typind = 'a'; | |
| break; | |
| case power: | |
| if (((1L << ((long)lop)) & | |
| ((1L << ((long)ltop)) | (1L << ((long)gtop)))) != 0) | |
| error(132); | |
| typind = 's'; | |
| break; | |
| case arrays: | |
| if (!string(lattr.typtr, LINK->LINK->LINK)) | |
| error(134); | |
| typind = 'm'; | |
| break; | |
| case records: | |
| error(134); | |
| typind = 'm'; | |
| break; | |
| case files: | |
| error(133); | |
| typind = 'f'; | |
| break; | |
| } | |
| switch (lop) { | |
| case ltop: /*les*/ | |
| gen2(53, typind, lsize, LINK->LINK); | |
| break; | |
| case leop: /*leq*/ | |
| gen2(52, typind, lsize, LINK->LINK); | |
| break; | |
| case gtop: /*grt*/ | |
| gen2(49, typind, lsize, LINK->LINK); | |
| break; | |
| case geop: /*geq*/ | |
| gen2(48, typind, lsize, LINK->LINK); | |
| break; | |
| case neop: /*neq*/ | |
| gen2(55, typind, lsize, LINK->LINK); | |
| break; | |
| case eqop: /*equ*/ | |
| gen2(47, typind, lsize, LINK->LINK); | |
| break; | |
| } | |
| } else | |
| error(129); | |
| } | |
| } | |
| gattr.typtr = boolptr; | |
| gattr.kind = expr; | |
| } | |
| Local void assignment(identifier *fcp, struct LOC_statement *LINK) | |
| { | |
| attr lattr; | |
| setofsys SET, SET1; | |
| /*assignment*/ | |
| selector(P_setunion(SET1, LINK->fsys, P_expset(SET, 1L << ((long)becomes))), | |
| fcp, LINK); | |
| if (sy != becomes) { | |
| error(51); | |
| return; | |
| } /*sy = becomes*/ | |
| if (gattr.typtr != NULL) { | |
| if (gattr.UU.U1.access != drct || (structform)gattr.typtr->form > power) | |
| loadaddress(LINK->LINK); | |
| } | |
| lattr = gattr; | |
| insymbol(); | |
| expression(LINK->fsys, LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form <= power) | |
| load(LINK->LINK); | |
| else | |
| loadaddress(LINK->LINK); | |
| } | |
| if (lattr.typtr == NULL || gattr.typtr == NULL) | |
| return; | |
| if (comptypes(realptr, lattr.typtr, LINK->LINK->LINK) && | |
| gattr.typtr == intptr) | |
| { /*flt*/ | |
| gen0(10, LINK->LINK); | |
| gattr.typtr = realptr; | |
| } | |
| if (!comptypes(lattr.typtr, gattr.typtr, LINK->LINK->LINK)) { | |
| error(129); | |
| return; | |
| } | |
| switch ((structform)lattr.typtr->form) { | |
| case scalar: | |
| case subrange: | |
| if (debug) | |
| checkbnds(lattr.typtr, LINK->LINK); | |
| store(&lattr, LINK->LINK); | |
| break; | |
| case pointer: | |
| if (debug) /*chk*/ | |
| gen2t(45, 0, maxaddr, nilptr, LINK->LINK); | |
| store(&lattr, LINK->LINK); | |
| break; | |
| case power: | |
| store(&lattr, LINK->LINK); | |
| break; | |
| case arrays: | |
| case records: /*mov*/ | |
| gen1(40, lattr.typtr->size, LINK->LINK); | |
| break; | |
| case files: | |
| error(146); | |
| break; | |
| } | |
| } | |
| Local void gotostatement(struct LOC_statement *LINK) | |
| { | |
| labl *llp; | |
| boolean found; | |
| disprange ttop, ttop1; | |
| labl *WITH; | |
| /*gotostatement*/ | |
| if (sy != intconst) { | |
| error(15); | |
| return; | |
| } | |
| found = false; | |
| ttop = top; | |
| while ((where)display[ttop].occur != blck) | |
| ttop–; | |
| ttop1 = ttop; | |
| do { | |
| llp = display[ttop].flabel; | |
| while (llp != NULL && !found) { | |
| WITH = llp; | |
| if (WITH->labval == val.UU.ival) { | |
| found = true; | |
| if (ttop == ttop1) /*ujp*/ | |
| genujpxjp(57, WITH->labname, LINK->LINK); | |
| else /*goto leads out of procedure*/ | |
| error(399); | |
| } else | |
| llp = WITH->nextlab; | |
| } | |
| ttop–; | |
| } while (!(found || ttop == 0)); | |
| if (!found) | |
| error(167); | |
| insymbol(); | |
| } | |
| Local void compoundstatement(struct LOC_statement *LINK) | |
| { | |
| long SET[(long)endsy / 32 + 2]; | |
| setofsys SET1; | |
| /*compoundstatemenet*/ | |
| do { | |
| do { | |
| P_addset(P_expset(SET, 0), (long)semicolon); | |
| statement(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)endsy)), | |
| LINK->LINK); | |
| } while (P_inset(sy, statbegsys)); | |
| LINK->LINK->LINK->test = (sy != semicolon); | |
| if (!LINK->LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->LINK->test); | |
| if (sy == endsy) | |
| insymbol(); | |
| else | |
| error(13); | |
| } | |
| Local void ifstatement(struct LOC_statement *LINK) | |
| { | |
| long lcix1, lcix2; | |
| long SET[(long)thensy / 32 + 2]; | |
| setofsys SET1; | |
| long SET2[(long)elsesy / 32 + 2]; | |
| /*ifstatement*/ | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_addset(P_expset(SET, 0), (long)thensy)), LINK); | |
| genlabel(&lcix1); | |
| genfjp(lcix1, LINK->LINK); | |
| if (sy == thensy) | |
| insymbol(); | |
| else | |
| error(52); | |
| statement(P_setunion(SET1, LINK->fsys, | |
| P_addset(P_expset(SET2, 0), (long)elsesy)), | |
| LINK->LINK); | |
| if (sy != elsesy) { | |
| putlabel(lcix1, LINK->LINK); | |
| return; | |
| } | |
| genlabel(&lcix2); /*ujp*/ | |
| genujpxjp(57, lcix2, LINK->LINK); | |
| putlabel(lcix1, LINK->LINK); | |
| insymbol(); | |
| statement(LINK->fsys, LINK->LINK); | |
| putlabel(lcix2, LINK->LINK); | |
| } | |
| Local void casestatement(struct LOC_statement *LINK) | |
| { | |
| structure *lsp, *lsp1; | |
| caseinfo *fstptr, *lpt1, *lpt2, *lpt3; | |
| valu lval; | |
| long laddr, lcix, lcix1, lmin, lmax; | |
| long SET[(long)ofsy / 32 + 2]; | |
| setofsys SET1, SET2; | |
| caseinfo *WITH; | |
| setofsys SET3, SET4; | |
| /*casestatement*/ | |
| P_addset(P_expset(SET, 0), (long)ofsy); | |
| P_addset(SET, (long)comma); | |
| expression(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)colon)), LINK); | |
| load(LINK->LINK); | |
| genlabel(&lcix); | |
| lsp = gattr.typtr; | |
| if (lsp != NULL) { /*ujp*/ | |
| if ((structform)lsp->form != scalar || lsp == realptr) { | |
| error(144); | |
| lsp = NULL; | |
| } else if (!comptypes(lsp, intptr, LINK->LINK->LINK)) | |
| gen0t(58, lsp, LINK->LINK); | |
| } | |
| genujpxjp(57, lcix, LINK->LINK); | |
| if (sy == ofsy) | |
| insymbol(); | |
| else | |
| error(8); | |
| fstptr = NULL; | |
| genlabel(&laddr); | |
| do { | |
| lpt3 = NULL; | |
| genlabel(&lcix1); | |
| if (sy != (long)endsy && sy != (long)semicolon) { | |
| do { | |
| constant_(P_setunion(SET2, LINK->fsys, | |
| P_expset(SET1, (1L << ((long)comma)) | (1L << ((long)colon)))), | |
| &lsp1, &lval, LINK->LINK->LINK); | |
| if (lsp != NULL) { | |
| if (comptypes(lsp, lsp1, LINK->LINK->LINK)) { | |
| lpt1 = fstptr; | |
| lpt2 = NULL; | |
| while (lpt1 != NULL) { | |
| WITH = lpt1; | |
| if (WITH->cslab <= lval.UU.ival) { | |
| if (WITH->cslab == lval.UU.ival) | |
| error(156); | |
| goto _L1; | |
| } | |
| lpt2 = lpt1; | |
| lpt1 = WITH->next; | |
| } | |
| _L1: | |
| lpt3 = Malloc(sizeof(caseinfo)); | |
| lpt3->next = lpt1; | |
| lpt3->cslab = lval.UU.ival; | |
| lpt3->csstart = lcix1; | |
| if (lpt2 == NULL) | |
| fstptr = lpt3; | |
| else | |
| lpt2->next = lpt3; | |
| } else | |
| error(147); | |
| } | |
| LINK->LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->LINK->test); | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| putlabel(lcix1, LINK->LINK); | |
| do { | |
| statement(P_setunion(SET4, LINK->fsys, | |
| P_expset(SET3, 1L << ((long)semicolon))), | |
| LINK->LINK); | |
| } while (P_inset(sy, statbegsys)); | |
| if (lpt3 != NULL) /*ujp*/ | |
| genujpxjp(57, laddr, LINK->LINK); | |
| } | |
| LINK->LINK->LINK->test = (sy != semicolon); | |
| if (!LINK->LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->LINK->test); | |
| putlabel(lcix, LINK->LINK); | |
| if (fstptr != NULL) { | |
| lmax = fstptr->cslab; | |
| /*reverse pointers*/ | |
| lpt1 = fstptr; | |
| fstptr = NULL; | |
| do { | |
| lpt2 = lpt1->next; | |
| lpt1->next = fstptr; | |
| fstptr = lpt1; | |
| lpt1 = lpt2; | |
| } while (lpt1 != NULL); | |
| lmin = fstptr->cslab; | |
| if (lmax – lmin < cixmax) { /*chk*/ | |
| gen2t(45, lmin, lmax, intptr, LINK->LINK); /*ldc*/ | |
| gen2(51, 1, lmin, LINK->LINK); /*sbi*/ | |
| gen0(21, LINK->LINK); | |
| genlabel(&lcix); /*xjp*/ | |
| genujpxjp(44, lcix, LINK->LINK); | |
| putlabel(lcix, LINK->LINK); | |
| do { | |
| WITH = fstptr; | |
| while (WITH->cslab > lmin) { /*ujc error*/ | |
| gen0(60, LINK->LINK); | |
| lmin++; | |
| } | |
| /*ujp*/ | |
| genujpxjp(57, WITH->csstart, LINK->LINK); | |
| fstptr = WITH->next; | |
| lmin++; | |
| } while (fstptr != NULL); | |
| putlabel(laddr, LINK->LINK); | |
| } else | |
| error(157); | |
| } | |
| if (sy == endsy) | |
| insymbol(); | |
| else | |
| error(13); | |
| /*ord*/ | |
| } | |
| Local void repeatstatement(struct LOC_statement *LINK) | |
| { | |
| long laddr; | |
| long SET[(long)untilsy / 32 + 2]; | |
| setofsys SET1; | |
| /*repeatstatement*/ | |
| genlabel(&laddr); | |
| putlabel(laddr, LINK->LINK); | |
| do { | |
| P_addset(P_expset(SET, 0), (long)semicolon); | |
| statement(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)untilsy)), | |
| LINK->LINK); | |
| if (P_inset(sy, statbegsys)) | |
| error(14); | |
| } while (P_inset(sy, statbegsys)); | |
| while (sy == semicolon) { | |
| insymbol(); | |
| do { | |
| P_addset(P_expset(SET, 0), (long)semicolon); | |
| statement(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)untilsy)), | |
| LINK->LINK); | |
| if (P_inset(sy, statbegsys)) | |
| error(14); | |
| } while (P_inset(sy, statbegsys)); | |
| } | |
| if (sy != untilsy) { | |
| error(53); | |
| return; | |
| } | |
| insymbol(); | |
| expression(LINK->fsys, LINK); | |
| genfjp(laddr, LINK->LINK); | |
| } | |
| Local void whilestatement(struct LOC_statement *LINK) | |
| { | |
| long laddr, lcix; | |
| long SET[(long)dosy / 32 + 2]; | |
| setofsys SET1; | |
| /*whilestatement*/ | |
| genlabel(&laddr); | |
| putlabel(laddr, LINK->LINK); | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_addset(P_expset(SET, 0), (long)dosy)), LINK); | |
| genlabel(&lcix); | |
| genfjp(lcix, LINK->LINK); | |
| if (sy == dosy) | |
| insymbol(); | |
| else | |
| error(54); | |
| statement(LINK->fsys, LINK->LINK); /*ujp*/ | |
| genujpxjp(57, laddr, LINK->LINK); | |
| putlabel(lcix, LINK->LINK); | |
| } | |
| Local void forstatement(struct LOC_statement *LINK) | |
| { | |
| attr lattr; | |
| symbol lsy; | |
| long lcix, laddr; | |
| addrrange llc; | |
| identifier *WITH; | |
| long SET[(long)downtosy / 32 + 2]; | |
| setofsys SET1; | |
| long SET2[(long)dosy / 32 + 2]; | |
| /*forstatement*/ | |
| llc = lc; | |
| lattr.typtr = NULL; | |
| lattr.kind = varbl; | |
| lattr.UU.U1.access = drct; | |
| lattr.UU.U1.UU.U0.vlevel = level; | |
| lattr.UU.U1.UU.U0.dplmt = 0; | |
| if (sy == ident) { | |
| searchid(1L << ((long)vars), &LINK->lcp); | |
| WITH = LINK->lcp; | |
| lattr.typtr = WITH->idtype; | |
| lattr.kind = varbl; | |
| if ((idkind)WITH->UU.U2.vkind == actual) { | |
| lattr.UU.U1.access = drct; | |
| lattr.UU.U1.UU.U0.vlevel = WITH->UU.U2.vlev; | |
| lattr.UU.U1.UU.U0.dplmt = WITH->UU.U2.vaddr; | |
| } else { | |
| error(155); | |
| lattr.typtr = NULL; | |
| } | |
| if (lattr.typtr != NULL) { | |
| if (((structform)lattr.typtr->form > subrange) | comptypes(realptr, | |
| lattr.typtr, LINK->LINK->LINK)) { | |
| error(143); | |
| lattr.typtr = NULL; | |
| } | |
| } | |
| insymbol(); | |
| } else { | |
| error(2); | |
| P_addset(P_expset(SET, 0), (long)becomes); | |
| P_addset(SET, (long)tosy); | |
| P_addset(SET, (long)downtosy); | |
| skip(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)dosy)), | |
| LINK->LINK->LINK); | |
| } | |
| if (sy == becomes) { | |
| insymbol(); | |
| P_addset(P_expset(SET, 0), (long)tosy); | |
| P_addset(SET, (long)downtosy); | |
| expression(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)dosy)), LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != scalar) | |
| error(144); | |
| else { | |
| if (comptypes(lattr.typtr, gattr.typtr, LINK->LINK->LINK)) { | |
| load(LINK->LINK); | |
| store(&lattr, LINK->LINK); | |
| } else | |
| error(145); | |
| } | |
| } | |
| } else { | |
| error(51); | |
| P_addset(P_expset(SET, 0), (long)tosy); | |
| P_addset(SET, (long)downtosy); | |
| skip(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)dosy)), | |
| LINK->LINK->LINK); | |
| } | |
| if (sy == (long)downtosy || sy == (long)tosy) { | |
| lsy = sy; | |
| insymbol(); | |
| expression(P_setunion(SET1, LINK->fsys, | |
| P_addset(P_expset(SET2, 0), (long)dosy)), LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form != scalar) | |
| error(144); | |
| else { | |
| if (comptypes(lattr.typtr, gattr.typtr, LINK->LINK->LINK)) { | |
| load(LINK->LINK); | |
| if (!comptypes(lattr.typtr, intptr, LINK->LINK->LINK)) /*ord*/ | |
| gen0t(58, gattr.typtr, LINK->LINK); | |
| align(intptr, &lc); /*str*/ | |
| gen2t(56, 0, lc, intptr, LINK->LINK); | |
| genlabel(&laddr); | |
| putlabel(laddr, LINK->LINK); | |
| gattr = lattr; | |
| load(LINK->LINK); | |
| if (!comptypes(gattr.typtr, intptr, LINK->LINK->LINK)) /*ord*/ | |
| gen0t(58, gattr.typtr, LINK->LINK); | |
| /*lod*/ | |
| gen2t(54, 0, lc, intptr, LINK->LINK); | |
| lc += intsize; | |
| if (lc > LINK->LINK->lcmax) | |
| LINK->LINK->lcmax = lc; | |
| if (lsy == tosy) /*leq*/ | |
| gen2(52, 'i', 1, LINK->LINK); | |
| else /*geq*/ | |
| gen2(48, 'i', 1, LINK->LINK); | |
| } else | |
| error(145); | |
| } | |
| } | |
| } else { | |
| error(55); | |
| skip(P_setunion(SET1, LINK->fsys, P_addset(P_expset(SET2, 0), (long)dosy)), | |
| LINK->LINK->LINK); | |
| } | |
| genlabel(&lcix); /*fjp*/ | |
| genujpxjp(33, lcix, LINK->LINK); | |
| if (sy == dosy) | |
| insymbol(); | |
| else | |
| error(54); | |
| statement(LINK->fsys, LINK->LINK); | |
| gattr = lattr; | |
| load(LINK->LINK); | |
| if (lsy == tosy) /*inc*/ | |
| gen1t(34, 1, gattr.typtr, LINK->LINK); | |
| else /*dec*/ | |
| gen1t(31, 1, gattr.typtr, LINK->LINK); | |
| store(&lattr, LINK->LINK); /*ujp*/ | |
| genujpxjp(57, laddr, LINK->LINK); | |
| putlabel(lcix, LINK->LINK); | |
| lc = llc; | |
| } | |
| Local void withstatement(struct LOC_statement *LINK) | |
| { | |
| identifier *lcp; | |
| disprange lcnt1; | |
| addrrange llc; | |
| long SET[(long)dosy / 32 + 2]; | |
| setofsys SET1; | |
| _REC_display *WITH; | |
| /*withstatement*/ | |
| lcnt1 = 0; | |
| llc = lc; | |
| do { | |
| if (sy == ident) { | |
| searchid((1L << ((long)vars)) | (1L << ((long)field)), &lcp); | |
| insymbol(); | |
| } else { | |
| error(2); | |
| lcp = uvarptr; | |
| } | |
| P_addset(P_expset(SET, 0), (long)comma); | |
| selector(P_setunion(SET1, LINK->fsys, P_addset(SET, (long)dosy)), lcp, | |
| LINK); | |
| if (gattr.typtr != NULL) { | |
| if ((structform)gattr.typtr->form == records) { | |
| if (top < displimit) { | |
| top++; | |
| lcnt1++; | |
| WITH = &display[top]; | |
| WITH->fname = gattr.typtr->UU.U5.fstfld; | |
| WITH->flabel = NULL; | |
| if (gattr.UU.U1.access == drct) { | |
| WITH = &display[top]; | |
| (where)WITH->occur = crec; | |
| WITH->UU.U1.clev = gattr.UU.U1.UU.U0.vlevel; | |
| WITH->UU.U1.cdspl = gattr.UU.U1.UU.U0.dplmt; | |
| } else { | |
| loadaddress(LINK->LINK); | |
| align(nilptr, &lc); /*str*/ | |
| gen2t(56, 0, lc, nilptr, LINK->LINK); | |
| WITH = &display[top]; | |
| (where)WITH->occur = vrec; | |
| WITH->UU.vdspl = lc; | |
| lc += ptrsize; | |
| if (lc > LINK->LINK->lcmax) | |
| LINK->LINK->lcmax = lc; | |
| } | |
| } else | |
| error(250); | |
| } else | |
| error(140); | |
| } | |
| LINK->LINK->LINK->test = (sy != comma); | |
| if (!LINK->LINK->LINK->test) | |
| insymbol(); | |
| } while (!LINK->LINK->LINK->test); | |
| if (sy == dosy) | |
| insymbol(); | |
| else | |
| error(54); | |
| statement(LINK->fsys, LINK->LINK); | |
| top -= lcnt1; | |
| lc = llc; | |
| } | |
| Local void statement(long *fsys_, struct LOC_body *LINK) | |
| { | |
| struct LOC_statement V; | |
| labl *llp, *WITH; | |
| setofsys SET, SET1; | |
| V.LINK = LINK; | |
| /*statement*/ | |
| P_setcpy(V.fsys, fsys_); | |
| if (sy == intconst) { /*label*/ | |
| llp = display[level].flabel; | |
| while (llp != NULL) { | |
| WITH = llp; | |
| if (WITH->labval == val.UU.ival) { | |
| if (WITH->defined_) | |
| error(165); | |
| putlabel(WITH->labname, LINK); | |
| WITH->defined_ = true; | |
| goto _L1; | |
| } else { | |
| llp = WITH->nextlab; | |
| continue; | |
| } | |
| } | |
| error(167); | |
| _L1: | |
| insymbol(); | |
| if (sy == colon) | |
| insymbol(); | |
| else | |
| error(5); | |
| } | |
| if (!P_inset(sy, P_setunion(SET1, V.fsys, | |
| P_expset(SET, 1L << ((long)ident))))) { | |
| error(6); | |
| skip(V.fsys, LINK->LINK); | |
| } | |
| if (!P_inset(sy, P_setunion(SET1, statbegsys, | |
| P_expset(SET, 1L << ((long)ident))))) | |
| return; | |
| switch (sy) { | |
| case ident: | |
| searchid((1L << ((long)vars)) | (1L << ((long)field)) | | |
| (1L << ((long)func)) | (1L << ((long)proc)), &V.lcp); | |
| insymbol(); | |
| if ((idclass)V.lcp->klass == proc) | |
| call(V.fsys, V.lcp, &V); | |
| else | |
| assignment(V.lcp, &V); | |
| break; | |
| case beginsy: | |
| insymbol(); | |
| compoundstatement(&V); | |
| break; | |
| case gotosy: | |
| insymbol(); | |
| gotostatement(&V); | |
| break; | |
| case ifsy: | |
| insymbol(); | |
| ifstatement(&V); | |
| break; | |
| case casesy: | |
| insymbol(); | |
| casestatement(&V); | |
| break; | |
| case whilesy: | |
| insymbol(); | |
| whilestatement(&V); | |
| break; | |
| case repeatsy: | |
| insymbol(); | |
| repeatstatement(&V); | |
| break; | |
| case forsy: | |
| insymbol(); | |
| forstatement(&V); | |
| break; | |
| case withsy: | |
| insymbol(); | |
| withstatement(&V); | |
| break; | |
| } | |
| if (sy != (long)untilsy && sy != (long)elsesy && sy != (long)endsy && | |
| sy != (long)semicolon) { | |
| error(6); | |
| skip(V.fsys, LINK->LINK); | |
| } | |
| } | |
| Local void body(long *fsys, struct LOC_block *LINK) | |
| { | |
| struct LOC_body V; | |
| identifier *llcp; | |
| alpha saveid; | |
| /*allows referencing of noninteger constants by an index | |
| (instead of a pointer), which can be stored in the p2-field | |
| of the instruction record until writeout. | |
| –> procedure load, procedure writeout*/ | |
| long entname, segsize, stacktop; | |
| addrrange llc1; | |
| identifier *lcp; | |
| labl *llp; | |
| identifier *WITH; | |
| long SET[(long)endsy / 32 + 2]; | |
| setofsys SET1; | |
| labl *WITH1; | |
| filerec *WITH2; | |
| V.LINK = LINK; | |
| /*body*/ | |
| if (LINK->fprocp != NULL) | |
| entname = LINK->fprocp->UU.U4.UU.U1.pfname; | |
| else | |
| genlabel(&entname); | |
| V.cstptrix = 0; | |
| V.topnew = lcaftermarkstack; | |
| V.topmax = lcaftermarkstack; | |
| putlabel(entname, &V); | |
| genlabel(&segsize); | |
| genlabel(&stacktop); /*ent1*/ | |
| gencupent(32, 1, segsize, &V); /*ent2*/ | |
| gencupent(32, 2, stacktop, &V); | |
| if (LINK->fprocp != NULL) { /*copy multiple values into local cells*/ | |
| llc1 = lcaftermarkstack; | |
| lcp = LINK->fprocp->next; | |
| while (lcp != NULL) { | |
| WITH = lcp; | |
| align(parmptr, &llc1); | |
| if ((idclass)WITH->klass == vars) { | |
| if (WITH->idtype != NULL) { | |
| if ((structform)WITH->idtype->form > power) { | |
| if ((idkind)WITH->UU.U2.vkind == actual) { /*lda*/ | |
| gen2(50, 0, WITH->UU.U2.vaddr, &V); /*lod*/ | |
| gen2t(54, 0, llc1, nilptr, &V); /*mov*/ | |
| gen1(40, WITH->idtype->size, &V); | |
| } | |
| llc1 += ptrsize; | |
| } else | |
| llc1 += WITH->idtype->size; | |
| } | |
| } | |
| lcp = lcp->next; | |
| } | |
| } | |
| V.lcmax = lc; | |
| do { | |
| do { | |
| P_addset(P_expset(SET, 0), (long)semicolon); | |
| statement(P_setunion(SET1, fsys, P_addset(SET, (long)endsy)), &V); | |
| } while (P_inset(sy, statbegsys)); | |
| LINK->test = (sy != semicolon); | |
| if (!LINK->test) | |
| insymbol(); | |
| } while (!LINK->test); | |
| if (sy == endsy) | |
| insymbol(); | |
| else | |
| error(13); | |
| llp = display[top].flabel; /*test for undefined labels*/ | |
| while (llp != NULL) { | |
| WITH1 = llp; | |
| if (!WITH1->defined_) { | |
| error(168); | |
| printf("\n label %12ld\n", WITH1->labval); | |
| printf("%*c", (int)(chcnt + 16), ' '); | |
| } | |
| llp = WITH1->nextlab; | |
| } | |
| if (LINK->fprocp != NULL) { | |
| if (LINK->fprocp->idtype == NULL) /*ret*/ | |
| gen1(42, 'p', &V); | |
| else /*ret*/ | |
| gen0t(42, LINK->fprocp->idtype, &V); | |
| align(parmptr, &V.lcmax); | |
| if (prcode) { | |
| fprintf(prr.f, "l%4ld=%12d\n", segsize, V.lcmax); | |
| fprintf(prr.f, "l%4ld=%12ld\n", stacktop, V.topmax); | |
| } | |
| return; | |
| } | |
| gen1(42, 'p', &V); | |
| align(parmptr, &V.lcmax); | |
| if (prcode) { | |
| fprintf(prr.f, "l%4ld=%12d\n", segsize, V.lcmax); | |
| fprintf(prr.f, "l%4ld=%12ld\n", stacktop, V.topmax); | |
| fprintf(prr.f, "q\n"); | |
| } | |
| ic = 0; /*mst*/ | |
| /*generate call of main program; note that this call must be loaded | |
| at absolute address zero*/ | |
| gen1(41, 0, &V); /*cup*/ | |
| gencupent(46, 0, entname, &V); /*stp*/ | |
| gen0(29, &V); | |
| if (prcode) | |
| fprintf(prr.f, "q\n"); | |
| memcpy(saveid, id, sizeof(alpha)); | |
| while (fextfilep != NULL) { | |
| WITH2 = fextfilep; | |
| if (strncmp(WITH2->filename, "input ", sizeof(alpha)) && | |
| strncmp(WITH2->filename, "output ", sizeof(alpha)) && | |
| strncmp(WITH2->filename, "prd ", sizeof(alpha)) && | |
| strncmp(WITH2->filename, "prr ", sizeof(alpha))) { | |
| memcpy(id, WITH2->filename, sizeof(alpha)); | |
| searchid(1L << ((long)vars), &llcp); | |
| if (llcp->idtype != NULL) { | |
| if ((structform)llcp->idtype->form != files) { | |
| printf("\n%8cundeclared external file%.8s\n", | |
| ' ', fextfilep->filename); | |
| printf("%*c", (int)(chcnt + 16), ' '); | |
| } | |
| } | |
| } | |
| fextfilep = fextfilep->nextfile; | |
| } | |
| memcpy(id, saveid, sizeof(alpha)); | |
| if (prtables) { | |
| putchar('\n'); | |
| printtables(true); | |
| } | |
| /*ret*/ | |
| } | |
| #undef cstoccmax | |
| #undef cixmax | |
| Static void block(long *fsys_, symbol fsy, identifier *fprocp_) | |
| { | |
| struct LOC_block V; | |
| symbol lsy; | |
| long SET[(long)casesy / 32 + 2]; | |
| setofsys SET1; | |
| /*block*/ | |
| P_setcpy(V.fsys, fsys_); | |
| V.fprocp = fprocp_; | |
| dp = true; | |
| do { | |
| if (sy == labelsy) { | |
| insymbol(); | |
| labeldeclaration(&V); | |
| } | |
| if (sy == constsy) { | |
| insymbol(); | |
| constdeclaration(&V); | |
| } | |
| if (sy == typesy) { | |
| insymbol(); | |
| typedeclaration(&V); | |
| } | |
| if (sy == varsy) { | |
| insymbol(); | |
| vardeclaration(&V); | |
| } | |
| while ((unsigned long)sy < 32 && | |
| ((1L << ((long)sy)) & | |
| ((1L << ((long)procsy)) | (1L << ((long)funcsy)))) != 0) { | |
| lsy = sy; | |
| insymbol(); | |
| procdeclaration(lsy, &V); | |
| } | |
| if (sy != beginsy) { | |
| error(18); | |
| skip(V.fsys, &V); | |
| } | |
| } while (!(P_inset(sy, statbegsys) | P_eof(stdin))); | |
| dp = false; | |
| if (sy == beginsy) | |
| insymbol(); | |
| else | |
| error(17); | |
| do { | |
| body(P_setunion(SET1, V.fsys, P_addset(P_expset(SET, 0), (long)casesy)), | |
| &V); | |
| if (sy != fsy) { | |
| error(6); | |
| skip(V.fsys, &V); | |
| } | |
| } while (!((sy == fsy) | P_inset(sy, blockbegsys) | P_eof(stdin))); | |
| } | |
| Static void programme(long *fsys) | |
| { | |
| filerec *extfp; | |
| /*programme*/ | |
| if (sy == progsy) { | |
| insymbol(); | |
| if (sy != ident) | |
| error(2); | |
| insymbol(); | |
| if ((unsigned long)sy >= 32 || | |
| ((1L << ((long)sy)) & | |
| ((1L << ((long)lparent)) | (1L << ((long)semicolon)))) == 0) | |
| error(14); | |
| if (sy == lparent) { | |
| do { | |
| insymbol(); | |
| if (sy == ident) { | |
| extfp = Malloc(sizeof(filerec)); | |
| memcpy(extfp->filename, id, sizeof(alpha)); | |
| extfp->nextfile = fextfilep; | |
| fextfilep = extfp; | |
| insymbol(); | |
| if ((unsigned long)sy >= 32 || | |
| ((1L << ((long)sy)) & | |
| ((1L << ((long)comma)) | (1L << ((long)rparent)))) == 0) | |
| error(20); | |
| } else | |
| error(2); | |
| } while (sy == comma); | |
| if (sy != rparent) | |
| error(4); | |
| insymbol(); | |
| } | |
| if (sy != semicolon) | |
| error(14); | |
| else | |
| insymbol(); | |
| } | |
| do { | |
| block(fsys, period, NULL); | |
| if (sy != period) | |
| error(21); | |
| } while (!((sy == period) | P_eof(stdin))); | |
| if (list) | |
| putchar('\n'); | |
| if (errinx != 0) { | |
| list = false; | |
| endofline(); | |
| } | |
| } | |
| Static void stdnames(void) | |
| { | |
| /*stdnames*/ | |
| memcpy(na[0], "false ", sizeof(alpha)); | |
| memcpy(na[1], "true ", sizeof(alpha)); | |
| memcpy(na[2], "input ", sizeof(alpha)); | |
| memcpy(na[3], "output ", sizeof(alpha)); | |
| memcpy(na[4], "get ", sizeof(alpha)); | |
| memcpy(na[5], "put ", sizeof(alpha)); | |
| memcpy(na[6], "reset ", sizeof(alpha)); | |
| memcpy(na[7], "rewrite ", sizeof(alpha)); | |
| memcpy(na[8], "read ", sizeof(alpha)); | |
| memcpy(na[9], "write ", sizeof(alpha)); | |
| memcpy(na[10], "pack ", sizeof(alpha)); | |
| memcpy(na[11], "unpack ", sizeof(alpha)); | |
| memcpy(na[12], "new ", sizeof(alpha)); | |
| memcpy(na[13], "release ", sizeof(alpha)); | |
| memcpy(na[14], "readln ", sizeof(alpha)); | |
| memcpy(na[15], "writeln ", sizeof(alpha)); | |
| memcpy(na[16], "abs ", sizeof(alpha)); | |
| memcpy(na[17], "sqr ", sizeof(alpha)); | |
| memcpy(na[18], "trunc ", sizeof(alpha)); | |
| memcpy(na[19], "odd ", sizeof(alpha)); | |
| memcpy(na[20], "ord ", sizeof(alpha)); | |
| memcpy(na[21], "chr ", sizeof(alpha)); | |
| memcpy(na[22], "pred ", sizeof(alpha)); | |
| memcpy(na[23], "succ ", sizeof(alpha)); | |
| memcpy(na[24], "eof ", sizeof(alpha)); | |
| memcpy(na[25], "eoln ", sizeof(alpha)); | |
| memcpy(na[26], "sin ", sizeof(alpha)); | |
| memcpy(na[27], "cos ", sizeof(alpha)); | |
| memcpy(na[28], "exp ", sizeof(alpha)); | |
| memcpy(na[29], "sqrt ", sizeof(alpha)); | |
| memcpy(na[30], "ln ", sizeof(alpha)); | |
| memcpy(na[31], "arctan ", sizeof(alpha)); | |
| memcpy(na[32], "prd ", sizeof(alpha)); | |
| memcpy(na[33], "prr ", sizeof(alpha)); | |
| memcpy(na[34], "mark ", sizeof(alpha)); | |
| } | |
| Static void enterstdtypes(void) | |
| { /*type underlying:*/ | |
| structure *WITH; | |
| /******************/ | |
| /* p2c: pcom.p, line 3646: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SCALAR.STANDARD [187] */ | |
| /*enterstdtypes*/ | |
| intptr = Malloc(sizeof(structure)); /*integer*/ | |
| WITH = intptr; | |
| /* p2c: pcom.p, line 3649: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SCALAR.STANDARD [187] */ | |
| WITH->size = intsize; | |
| (structform)WITH->form = scalar; | |
| (declkind)WITH->UU.U0.scalkind = standard; | |
| realptr = Malloc(sizeof(structure)); /*real*/ | |
| WITH = realptr; | |
| /* p2c: pcom.p, line 3652: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SCALAR.STANDARD [187] */ | |
| WITH->size = realsize; | |
| (structform)WITH->form = scalar; | |
| (declkind)WITH->UU.U0.scalkind = standard; | |
| charptr = Malloc(sizeof(structure)); /*char*/ | |
| WITH = charptr; | |
| /* p2c: pcom.p, line 3655: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SCALAR.DECLARED [187] */ | |
| WITH->size = charsize; | |
| (structform)WITH->form = scalar; | |
| (declkind)WITH->UU.U0.scalkind = standard; | |
| boolptr = Malloc(sizeof(structure)); /*boolean*/ | |
| WITH = boolptr; | |
| /* p2c: pcom.p, line 3658: | |
| * Note: No SpecialMalloc form known for STRUCTURE.POINTER [187] */ | |
| WITH->size = boolsize; | |
| (structform)WITH->form = scalar; | |
| (declkind)WITH->UU.U0.scalkind = declared; | |
| nilptr = Malloc(sizeof(structure)); /*nil*/ | |
| WITH = nilptr; | |
| /* p2c: pcom.p, line 3661: | |
| * Note: No SpecialMalloc form known for STRUCTURE.SCALAR.STANDARD [187] */ | |
| WITH->UU.eltype = NULL; | |
| WITH->size = ptrsize; | |
| (structform)WITH->form = pointer; | |
| parmptr = Malloc(sizeof(structure)); /*for alignment of parameters*/ | |
| WITH = parmptr; | |
| /* p2c: pcom.p, line 3664: | |
| * Note: No SpecialMalloc form known for STRUCTURE.FILES [187] */ | |
| WITH->size = parmsize; | |
| (structform)WITH->form = scalar; | |
| (declkind)WITH->UU.U0.scalkind = standard; | |
| textptr = Malloc(sizeof(structure)); /*text*/ | |
| WITH = textptr; | |
| WITH->UU.filtype = charptr; | |
| WITH->size = charsize; | |
| (structform)WITH->form = files; | |
| } | |
| Static void entstdnames(void) | |
| { /*name:*/ | |
| identifier *cp, *cp1; | |
| long i; | |
| /*******/ | |
| /* p2c: pcom.p, line 3674: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| /*entstdnames*/ | |
| cp = Malloc(sizeof(identifier)); /*integer*/ | |
| memcpy(cp->name, "integer ", sizeof(alpha)); | |
| cp->idtype = intptr; | |
| (idclass)cp->klass = types; | |
| enterid(cp); | |
| /* p2c: pcom.p, line 3678: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| cp = Malloc(sizeof(identifier)); /*real*/ | |
| memcpy(cp->name, "real ", sizeof(alpha)); | |
| cp->idtype = realptr; | |
| (idclass)cp->klass = types; | |
| enterid(cp); | |
| /* p2c: pcom.p, line 3682: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| cp = Malloc(sizeof(identifier)); /*char*/ | |
| memcpy(cp->name, "char ", sizeof(alpha)); | |
| cp->idtype = charptr; | |
| (idclass)cp->klass = types; | |
| enterid(cp); | |
| /* p2c: pcom.p, line 3686: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| cp = Malloc(sizeof(identifier)); /*boolean*/ | |
| memcpy(cp->name, "boolean ", sizeof(alpha)); | |
| cp->idtype = boolptr; | |
| (idclass)cp->klass = types; | |
| enterid(cp); | |
| cp1 = NULL; | |
| for (i = 0; i <= 1; i++) { | |
| cp = Malloc(sizeof(identifier)); /*false,true*/ | |
| memcpy(cp->name, na[i], sizeof(alpha)); | |
| cp->idtype = boolptr; | |
| cp->next = cp1; | |
| cp->UU.values.UU.ival = i; | |
| (idclass)cp->klass = konst; | |
| enterid(cp); | |
| cp1 = cp; | |
| } | |
| /* p2c: pcom.p, line 3692: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.KONST [187] */ | |
| boolptr->UU.U0.UU.fconst = cp; | |
| /* p2c: pcom.p, line 3700: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.KONST [187] */ | |
| cp = Malloc(sizeof(identifier)); /*nil*/ | |
| memcpy(cp->name, "nil ", sizeof(alpha)); | |
| cp->idtype = nilptr; | |
| cp->next = NULL; | |
| cp->UU.values.UU.ival = 0; | |
| (idclass)cp->klass = konst; | |
| enterid(cp); | |
| for (i = 3; i <= 4; i++) { | |
| cp = Malloc(sizeof(identifier)); /*input,output*/ | |
| memcpy(cp->name, na[i – 1], sizeof(alpha)); | |
| cp->idtype = textptr; | |
| (idclass)cp->klass = vars; | |
| (idkind)cp->UU.U2.vkind = actual; | |
| cp->next = NULL; | |
| cp->UU.U2.vlev = 1; | |
| cp->UU.U2.vaddr = lcaftermarkstack + i – 3; | |
| enterid(cp); | |
| } | |
| /* p2c: pcom.p, line 3707: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.VARS [187] */ | |
| for (i = 33; i <= 34; i++) { | |
| cp = Malloc(sizeof(identifier)); /*prd,prr files*/ | |
| memcpy(cp->name, na[i – 1], sizeof(alpha)); | |
| cp->idtype = textptr; | |
| (idclass)cp->klass = vars; | |
| (idkind)cp->UU.U2.vkind = actual; | |
| cp->next = NULL; | |
| cp->UU.U2.vlev = 1; | |
| cp->UU.U2.vaddr = lcaftermarkstack + i – 31; | |
| enterid(cp); | |
| } | |
| /* p2c: pcom.p, line 3716: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.VARS [187] */ | |
| for (i = 5; i <= 16; i++) { | |
| cp = Malloc(sizeof(identifier)); /*get,put,reset*/ | |
| /*rewrite,read*/ | |
| memcpy(cp->name, na[i – 1], sizeof(alpha)); | |
| cp->idtype = NULL; /*write,pack*/ | |
| cp->next = NULL; | |
| cp->UU.U4.UU.key = i – 4; /*unpack,pack*/ | |
| (idclass)cp->klass = proc; | |
| (declkind)cp->UU.U4.pfdeckind = standard; | |
| enterid(cp); | |
| } | |
| /* p2c: pcom.p, line 3725: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.PROC.STANDARD [187] */ | |
| /* p2c: pcom.p, line 3733: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.PROC.STANDARD [187] */ | |
| cp = Malloc(sizeof(identifier)); | |
| memcpy(cp->name, na[34], sizeof(alpha)); | |
| cp->idtype = NULL; | |
| cp->next = NULL; | |
| cp->UU.U4.UU.key = 13; | |
| (idclass)cp->klass = proc; | |
| (declkind)cp->UU.U4.pfdeckind = standard; | |
| enterid(cp); | |
| for (i = 17; i <= 26; i++) { | |
| cp = Malloc(sizeof(identifier)); /*abs,sqr,trunc*/ | |
| /*odd,ord,chr*/ | |
| memcpy(cp->name, na[i – 1], sizeof(alpha)); | |
| cp->idtype = NULL; /*pred,succ,eof*/ | |
| cp->next = NULL; | |
| cp->UU.U4.UU.key = i – 16; | |
| (idclass)cp->klass = func; | |
| (declkind)cp->UU.U4.pfdeckind = standard; | |
| enterid(cp); | |
| } | |
| /* p2c: pcom.p, line 3740: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.FUNC.STANDARD [187] */ | |
| /* p2c: pcom.p, line 3748: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.VARS [187] */ | |
| cp = Malloc(sizeof(identifier)); /*parameter of predeclared functions*/ | |
| memcpy(cp->name, " ", sizeof(alpha)); | |
| cp->idtype = realptr; | |
| (idclass)cp->klass = vars; | |
| (idkind)cp->UU.U2.vkind = actual; | |
| cp->next = NULL; | |
| cp->UU.U2.vlev = 1; | |
| cp->UU.U2.vaddr = 0; | |
| for (i = 27; i <= 32; i++) { | |
| cp1 = Malloc(sizeof(identifier)); /*sin,cos,exp*/ | |
| /*sqrt,ln,arctan*/ | |
| memcpy(cp1->name, na[i – 1], sizeof(alpha)); | |
| cp1->idtype = realptr; | |
| cp1->next = cp; | |
| cp1->UU.U4.UU.U1.UU.U0.forwdecl = false; | |
| cp1->UU.U4.UU.U1.UU.U0.externl = true; | |
| cp1->UU.U4.UU.U1.pflev = 0; | |
| cp1->UU.U4.UU.U1.pfname = i – 12; | |
| (idclass)cp1->klass = func; | |
| (declkind)cp1->UU.U4.pfdeckind = declared; | |
| (idkind)cp1->UU.U4.UU.U1.pfkind = actual; | |
| enterid(cp1); | |
| } | |
| /* p2c: pcom.p, line 3754: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.FUNC.DECLARED.ACTUAL [187] */ | |
| } | |
| Static void enterundecl(void) | |
| { | |
| identifier *WITH; | |
| /* p2c: pcom.p, line 3766: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.TYPES [187] */ | |
| /*enterundecl*/ | |
| utypptr = Malloc(sizeof(identifier)); | |
| WITH = utypptr; | |
| /* p2c: pcom.p, line 3769: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.KONST [187] */ | |
| memcpy(WITH->name, " ", sizeof(alpha)); | |
| WITH->idtype = NULL; | |
| (idclass)WITH->klass = types; | |
| ucstptr = Malloc(sizeof(identifier)); | |
| WITH = ucstptr; | |
| /* p2c: pcom.p, line 3774: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.VARS [187] */ | |
| memcpy(WITH->name, " ", sizeof(alpha)); | |
| WITH->idtype = NULL; | |
| WITH->next = NULL; | |
| WITH->UU.values.UU.ival = 0; | |
| (idclass)WITH->klass = konst; | |
| uvarptr = Malloc(sizeof(identifier)); | |
| WITH = uvarptr; | |
| /* p2c: pcom.p, line 3779: | |
| * Note: No SpecialMalloc form known for IDENTIFIER.FIELD [187] */ | |
| memcpy(WITH->name, " ", sizeof(alpha)); | |
| WITH->idtype = NULL; | |
| (idkind)WITH->UU.U2.vkind = actual; | |
| WITH->next = NULL; | |
| WITH->UU.U2.vlev = 0; | |
| WITH->UU.U2.vaddr = 0; | |
| (idclass)WITH->klass = vars; | |
| ufldptr = Malloc(sizeof(identifier)); | |
| WITH = ufldptr; | |
| /* p2c: pcom.p, line 3784: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.PROC.DECLARED.ACTUAL [187] */ | |
| memcpy(WITH->name, " ", sizeof(alpha)); | |
| WITH->idtype = NULL; | |
| WITH->next = NULL; | |
| WITH->UU.fldaddr = 0; | |
| (idclass)WITH->klass = field; | |
| uprcptr = Malloc(sizeof(identifier)); | |
| WITH = uprcptr; | |
| /* p2c: pcom.p, line 3790: Note: | |
| * No SpecialMalloc form known for IDENTIFIER.FUNC.DECLARED.ACTUAL [187] */ | |
| memcpy(WITH->name, " ", sizeof(alpha)); | |
| WITH->idtype = NULL; | |
| WITH->UU.U4.UU.U1.UU.U0.forwdecl = false; | |
| WITH->next = NULL; | |
| WITH->UU.U4.UU.U1.UU.U0.externl = false; | |
| WITH->UU.U4.UU.U1.pflev = 0; | |
| genlabel(&WITH->UU.U4.UU.U1.pfname); | |
| (idclass)WITH->klass = proc; | |
| (declkind)WITH->UU.U4.pfdeckind = declared; | |
| (idkind)WITH->UU.U4.UU.U1.pfkind = actual; | |
| ufctptr = Malloc(sizeof(identifier)); | |
| WITH = ufctptr; | |
| memcpy(WITH->name, " ", sizeof(alpha)); | |
| WITH->idtype = NULL; | |
| WITH->next = NULL; | |
| WITH->UU.U4.UU.U1.UU.U0.forwdecl = false; | |
| WITH->UU.U4.UU.U1.UU.U0.externl = false; | |
| WITH->UU.U4.UU.U1.pflev = 0; | |
| genlabel(&WITH->UU.U4.UU.U1.pfname); | |
| (idclass)WITH->klass = func; | |
| (declkind)WITH->UU.U4.pfdeckind = declared; | |
| (idkind)WITH->UU.U4.UU.U1.pfkind = actual; | |
| } | |
| Static void initscalars(void) | |
| { | |
| /*initscalars*/ | |
| fwptr = NULL; | |
| prtables = false; | |
| list = true; | |
| prcode = true; | |
| debug = true; | |
| dp = true; | |
| prterr = true; | |
| errinx = 0; | |
| intlabel = 0; | |
| kk = 8; | |
| fextfilep = NULL; | |
| lc = lcaftermarkstack + filebuffer; | |
| /* note in the above reservation of buffer store for 2 text files */ | |
| ic = 3; | |
| eol = true; | |
| linecount = 0; | |
| ch = ' '; | |
| chcnt = 0; | |
| globtestp = NULL; | |
| mxint10 = maxint / 10; | |
| digmax = strglgth – 1; | |
| } | |
| Static void initsets(void) | |
| { | |
| setofsys SET; | |
| /*initsets*/ | |
| P_expset(constbegsys, (1L << ((long)addop)) | (1L << ((long)intconst)) | | |
| (1L << ((long)realconst)) | | |
| (1L << ((long)stringconst)) | (1L << ((long)ident))); | |
| P_setunion(simptypebegsys, P_expset(SET, 1L << ((long)lparent)), | |
| constbegsys); | |
| P_setunion(typebegsys, | |
| P_expset(SET, (1L << ((long)arrow)) | (1L << ((long)packedsy)) | | |
| (1L << ((long)arraysy)) | (1L << ((long)recordsy)) | | |
| (1L << ((long)setsy)) | (1L << ((long)filesy))), | |
| simptypebegsys); | |
| P_expset(typedels, (1L << ((long)arraysy)) | (1L << ((long)recordsy)) | | |
| (1L << ((long)setsy)) | (1L << ((long)filesy))); | |
| P_expset(blockbegsys, | |
| (1L << ((long)labelsy)) | (1L << ((long)constsy)) | | |
| (1L << ((long)typesy)) | (1L << ((long)varsy)) | (1L << ((long)procsy)) | | |
| (1L << ((long)funcsy)) | (1L << ((long)beginsy))); | |
| P_expset(selectsys, | |
| (1L << ((long)arrow)) | (1L << ((long)period)) | (1L << ((long)lbrack))); | |
| P_expset(facbegsys, | |
| (1L << ((long)intconst)) | (1L << ((long)realconst)) | | |
| (1L << ((long)stringconst)) | (1L << ((long)ident)) | | |
| (1L << ((long)lparent)) | (1L << ((long)lbrack)) | (1L << ((long)notsy))); | |
| P_addset(P_expset(statbegsys, 0), (long)beginsy); | |
| P_addset(statbegsys, (long)gotosy); | |
| P_addset(statbegsys, (long)ifsy); | |
| P_addset(statbegsys, (long)whilesy); | |
| P_addset(statbegsys, (long)repeatsy); | |
| P_addset(statbegsys, (long)forsy); | |
| P_addset(statbegsys, (long)withsy); | |
| P_addset(statbegsys, (long)casesy); | |
| } | |
| Local void reswords(void) | |
| { | |
| /*reswords*/ | |
| memcpy(rw[0], "if ", sizeof(alpha)); | |
| memcpy(rw[1], "do ", sizeof(alpha)); | |
| memcpy(rw[2], "of ", sizeof(alpha)); | |
| memcpy(rw[3], "to ", sizeof(alpha)); | |
| memcpy(rw[4], "in ", sizeof(alpha)); | |
| memcpy(rw[5], "or ", sizeof(alpha)); | |
| memcpy(rw[6], "end ", sizeof(alpha)); | |
| memcpy(rw[7], "for ", sizeof(alpha)); | |
| memcpy(rw[8], "var ", sizeof(alpha)); | |
| memcpy(rw[9], "div ", sizeof(alpha)); | |
| memcpy(rw[10], "mod ", sizeof(alpha)); | |
| memcpy(rw[11], "set ", sizeof(alpha)); | |
| memcpy(rw[12], "and ", sizeof(alpha)); | |
| memcpy(rw[13], "not ", sizeof(alpha)); | |
| memcpy(rw[14], "then ", sizeof(alpha)); | |
| memcpy(rw[15], "else ", sizeof(alpha)); | |
| memcpy(rw[16], "with ", sizeof(alpha)); | |
| memcpy(rw[17], "goto ", sizeof(alpha)); | |
| memcpy(rw[18], "case ", sizeof(alpha)); | |
| memcpy(rw[19], "type ", sizeof(alpha)); | |
| memcpy(rw[20], "file ", sizeof(alpha)); | |
| memcpy(rw[21], "begin ", sizeof(alpha)); | |
| memcpy(rw[22], "until ", sizeof(alpha)); | |
| memcpy(rw[23], "while ", sizeof(alpha)); | |
| memcpy(rw[24], "array ", sizeof(alpha)); | |
| memcpy(rw[25], "const ", sizeof(alpha)); | |
| memcpy(rw[26], "label ", sizeof(alpha)); | |
| memcpy(rw[27], "repeat ", sizeof(alpha)); | |
| memcpy(rw[28], "record ", sizeof(alpha)); | |
| memcpy(rw[29], "downto ", sizeof(alpha)); | |
| memcpy(rw[30], "packed ", sizeof(alpha)); | |
| memcpy(rw[31], "forward ", sizeof(alpha)); | |
| memcpy(rw[32], "program ", sizeof(alpha)); | |
| memcpy(rw[33], "function", sizeof(alpha)); | |
| memcpy(rw[34], "procedur", sizeof(alpha)); | |
| frw[0] = 1; | |
| frw[1] = 1; | |
| frw[2] = 7; | |
| frw[3] = 15; | |
| frw[4] = 22; | |
| frw[5] = 28; | |
| frw[6] = 32; | |
| frw[7] = 34; | |
| frw[8] = 36; | |
| } | |
| Local void symbols(void) | |
| { | |
| /*symbols*/ | |
| rsy[0] = ifsy; | |
| rsy[1] = dosy; | |
| rsy[2] = ofsy; | |
| rsy[3] = tosy; | |
| rsy[4] = relop; | |
| rsy[5] = addop; | |
| rsy[6] = endsy; | |
| rsy[7] = forsy; | |
| rsy[8] = varsy; | |
| rsy[9] = mulop; | |
| rsy[10] = mulop; | |
| rsy[11] = setsy; | |
| rsy[12] = mulop; | |
| rsy[13] = notsy; | |
| rsy[14] = thensy; | |
| rsy[15] = elsesy; | |
| rsy[16] = withsy; | |
| rsy[17] = gotosy; | |
| rsy[18] = casesy; | |
| rsy[19] = typesy; | |
| rsy[20] = filesy; | |
| rsy[21] = beginsy; | |
| rsy[22] = untilsy; | |
| rsy[23] = whilesy; | |
| rsy[24] = arraysy; | |
| rsy[25] = constsy; | |
| rsy[26] = labelsy; | |
| rsy[27] = repeatsy; | |
| rsy[28] = recordsy; | |
| rsy[29] = downtosy; | |
| rsy[30] = packedsy; | |
| rsy[31] = forwardsy; | |
| rsy[32] = progsy; | |
| rsy[33] = funcsy; | |
| rsy[34] = procsy; | |
| ssy['+'] = addop; | |
| ssy['-'] = addop; | |
| ssy['*'] = mulop; | |
| ssy['/'] = mulop; | |
| ssy['('] = lparent; | |
| ssy[')'] = rparent; | |
| ssy['$'] = othersy; | |
| ssy['='] = relop; | |
| ssy[' '] = othersy; | |
| ssy[','] = comma; | |
| ssy['.'] = period; | |
| ssy['\''] = othersy; | |
| ssy['['] = lbrack; | |
| ssy[']'] = rbrack; | |
| ssy[':'] = colon; | |
| ssy['^'] = arrow; | |
| ssy['<'] = relop; | |
| ssy['>'] = relop; | |
| ssy[';'] = semicolon; | |
| } | |
| Local void rators(void) | |
| { | |
| long i; | |
| /*rators*/ | |
| for (i = 0; i <= 34; i++) /*nr of res words*/ | |
| rop[i] = noop; | |
| rop[4] = inop; | |
| rop[9] = idiv; | |
| rop[10] = imod; | |
| rop[5] = orop; | |
| rop[12] = andop; | |
| for (i = ordminchar; i <= ordmaxchar; i++) | |
| sop[(Char)i] = noop; | |
| sop['+'] = plus; | |
| sop['-'] = minus; | |
| sop['*'] = mul; | |
| sop['/'] = rdiv; | |
| sop['='] = eqop; | |
| sop['<'] = ltop; | |
| sop['>'] = gtop; | |
| } | |
| Local void procmnemonics(void) | |
| { | |
| /*procmnemonics*/ | |
| memcpy(sna[0], " get", 4); | |
| memcpy(sna[1], " put", 4); | |
| memcpy(sna[2], " rdi", 4); | |
| memcpy(sna[3], " rdr", 4); | |
| memcpy(sna[4], " rdc", 4); | |
| memcpy(sna[5], " wri", 4); | |
| memcpy(sna[6], " wro", 4); | |
| memcpy(sna[7], " wrr", 4); | |
| memcpy(sna[8], " wrc", 4); | |
| memcpy(sna[9], " wrs", 4); | |
| memcpy(sna[10], " pak", 4); | |
| memcpy(sna[11], " new", 4); | |
| memcpy(sna[12], " rst", 4); | |
| memcpy(sna[13], " eln", 4); | |
| memcpy(sna[14], " sin", 4); | |
| memcpy(sna[15], " cos", 4); | |
| memcpy(sna[16], " exp", 4); | |
| memcpy(sna[17], " sqt", 4); | |
| memcpy(sna[18], " log", 4); | |
| memcpy(sna[19], " atn", 4); | |
| memcpy(sna[20], " rln", 4); | |
| memcpy(sna[21], " wln", 4); | |
| memcpy(sna[22], " sav", 4); | |
| } | |
| Local void instrmnemonics(void) | |
| { | |
| /*instrmnemonics*/ | |
| memcpy(mn[0], " abi", 4); | |
| memcpy(mn[1], " abr", 4); | |
| memcpy(mn[2], " adi", 4); | |
| memcpy(mn[3], " adr", 4); | |
| memcpy(mn[4], " and", 4); | |
| memcpy(mn[5], " dif", 4); | |
| memcpy(mn[6], " dvi", 4); | |
| memcpy(mn[7], " dvr", 4); | |
| memcpy(mn[8], " eof", 4); | |
| memcpy(mn[9], " flo", 4); | |
| memcpy(mn[10], " flt", 4); | |
| memcpy(mn[11], " inn", 4); | |
| memcpy(mn[12], " int", 4); | |
| memcpy(mn[13], " ior", 4); | |
| memcpy(mn[14], " mod", 4); | |
| memcpy(mn[15], " mpi", 4); | |
| memcpy(mn[16], " mpr", 4); | |
| memcpy(mn[17], " ngi", 4); | |
| memcpy(mn[18], " ngr", 4); | |
| memcpy(mn[19], " not", 4); | |
| memcpy(mn[20], " odd", 4); | |
| memcpy(mn[21], " sbi", 4); | |
| memcpy(mn[22], " sbr", 4); | |
| memcpy(mn[23], " sgs", 4); | |
| memcpy(mn[24], " sqi", 4); | |
| memcpy(mn[25], " sqr", 4); | |
| memcpy(mn[26], " sto", 4); | |
| memcpy(mn[27], " trc", 4); | |
| memcpy(mn[28], " uni", 4); | |
| memcpy(mn[29], " stp", 4); | |
| memcpy(mn[30], " csp", 4); | |
| memcpy(mn[31], " dec", 4); | |
| memcpy(mn[32], " ent", 4); | |
| memcpy(mn[33], " fjp", 4); | |
| memcpy(mn[34], " inc", 4); | |
| memcpy(mn[35], " ind", 4); | |
| memcpy(mn[36], " ixa", 4); | |
| memcpy(mn[37], " lao", 4); | |
| memcpy(mn[38], " lca", 4); | |
| memcpy(mn[39], " ldo", 4); | |
| memcpy(mn[40], " mov", 4); | |
| memcpy(mn[41], " mst", 4); | |
| memcpy(mn[42], " ret", 4); | |
| memcpy(mn[43], " sro", 4); | |
| memcpy(mn[44], " xjp", 4); | |
| memcpy(mn[45], " chk", 4); | |
| memcpy(mn[46], " cup", 4); | |
| memcpy(mn[47], " equ", 4); | |
| memcpy(mn[48], " geq", 4); | |
| memcpy(mn[49], " grt", 4); | |
| memcpy(mn[50], " lda", 4); | |
| memcpy(mn[51], " ldc", 4); | |
| memcpy(mn[52], " leq", 4); | |
| memcpy(mn[53], " les", 4); | |
| memcpy(mn[54], " lod", 4); | |
| memcpy(mn[55], " neq", 4); | |
| memcpy(mn[56], " str", 4); | |
| memcpy(mn[57], " ujp", 4); | |
| memcpy(mn[58], " ord", 4); | |
| memcpy(mn[59], " chr", 4); | |
| memcpy(mn[60], " ujc", 4); | |
| } | |
| Local void chartypes(void) | |
| { | |
| long i; | |
| for (i = ordminchar; i <= ordmaxchar; i++) | |
| chartp[(Char)i] = illegal; | |
| chartp['a'] = letter; | |
| chartp['b'] = letter; | |
| chartp['c'] = letter; | |
| chartp['d'] = letter; | |
| chartp['e'] = letter; | |
| chartp['f'] = letter; | |
| chartp['g'] = letter; | |
| chartp['h'] = letter; | |
| chartp['i'] = letter; | |
| chartp['j'] = letter; | |
| chartp['k'] = letter; | |
| chartp['l'] = letter; | |
| chartp['m'] = letter; | |
| chartp['n'] = letter; | |
| chartp['o'] = letter; | |
| chartp['p'] = letter; | |
| chartp['q'] = letter; | |
| chartp['r'] = letter; | |
| chartp['s'] = letter; | |
| chartp['t'] = letter; | |
| chartp['u'] = letter; | |
| chartp['v'] = letter; | |
| chartp['w'] = letter; | |
| chartp['x'] = letter; | |
| chartp['y'] = letter; | |
| chartp['z'] = letter; | |
| chartp['0'] = number; | |
| chartp['1'] = number; | |
| chartp['2'] = number; | |
| chartp['3'] = number; | |
| chartp['4'] = number; | |
| chartp['5'] = number; | |
| chartp['6'] = number; | |
| chartp['7'] = number; | |
| chartp['8'] = number; | |
| chartp['9'] = number; | |
| chartp['+'] = special; | |
| chartp['-'] = special; | |
| chartp['*'] = special; | |
| chartp['/'] = special; | |
| chartp['('] = chlparen; | |
| chartp[')'] = special; | |
| chartp['$'] = special; | |
| chartp['='] = special; | |
| chartp[' '] = chspace; | |
| chartp[','] = special; | |
| chartp['.'] = chperiod; | |
| chartp['\''] = chstrquo; | |
| chartp['['] = special; | |
| chartp[']'] = special; | |
| chartp[':'] = chcolon; | |
| chartp['^'] = special; | |
| chartp[';'] = special; | |
| chartp['<'] = chlt; | |
| chartp['>'] = chgt; | |
| ordint['0'] = 0; | |
| ordint['1'] = 1; | |
| ordint['2'] = 2; | |
| ordint['3'] = 3; | |
| ordint['4'] = 4; | |
| ordint['5'] = 5; | |
| ordint['6'] = 6; | |
| ordint['7'] = 7; | |
| ordint['8'] = 8; | |
| ordint['9'] = 9; | |
| } | |
| Local void initdx(void) | |
| { | |
| cdx[0] = 0; | |
| cdx[1] = 0; | |
| cdx[2] = -1; | |
| cdx[3] = -1; | |
| cdx[4] = -1; | |
| cdx[5] = -1; | |
| cdx[6] = -1; | |
| cdx[7] = -1; | |
| cdx[8] = 0; | |
| cdx[9] = 0; | |
| cdx[10] = 0; | |
| cdx[11] = -1; | |
| cdx[12] = -1; | |
| cdx[13] = -1; | |
| cdx[14] = -1; | |
| cdx[15] = -1; | |
| cdx[16] = -1; | |
| cdx[17] = 0; | |
| cdx[18] = 0; | |
| cdx[19] = 0; | |
| cdx[20] = 0; | |
| cdx[21] = -1; | |
| cdx[22] = -1; | |
| cdx[23] = 0; | |
| cdx[24] = 0; | |
| cdx[25] = 0; | |
| cdx[26] = -2; | |
| cdx[27] = 0; | |
| cdx[28] = -1; | |
| cdx[29] = 0; | |
| cdx[30] = 0; | |
| cdx[31] = 0; | |
| cdx[32] = 0; | |
| cdx[33] = -1; | |
| cdx[34] = 0; | |
| cdx[35] = 0; | |
| cdx[36] = -1; | |
| cdx[37] = 1; | |
| cdx[38] = 1; | |
| cdx[39] = 1; | |
| cdx[40] = -2; | |
| cdx[41] = 0; | |
| cdx[42] = 0; | |
| cdx[43] = -1; | |
| cdx[44] = -1; | |
| cdx[45] = 0; | |
| cdx[46] = 0; | |
| cdx[47] = -1; | |
| cdx[48] = -1; | |
| cdx[49] = -1; | |
| cdx[50] = 1; | |
| cdx[51] = 1; | |
| cdx[52] = -1; | |
| cdx[53] = -1; | |
| cdx[54] = 1; | |
| cdx[55] = -1; | |
| cdx[56] = -1; | |
| cdx[57] = 0; | |
| cdx[58] = 0; | |
| cdx[59] = 0; | |
| cdx[60] = 0; | |
| pdx[0] = -1; | |
| pdx[1] = -1; | |
| pdx[2] = -2; | |
| pdx[3] = -2; | |
| pdx[4] = -2; | |
| pdx[5] = -3; | |
| pdx[6] = -3; | |
| pdx[7] = -3; | |
| pdx[8] = -3; | |
| pdx[9] = -4; | |
| pdx[10] = 0; | |
| pdx[11] = -2; | |
| pdx[12] = -1; | |
| pdx[13] = 0; | |
| pdx[14] = 0; | |
| pdx[15] = 0; | |
| pdx[16] = 0; | |
| pdx[17] = 0; | |
| pdx[18] = 0; | |
| pdx[19] = 0; | |
| pdx[20] = -1; | |
| pdx[21] = -1; | |
| pdx[22] = -1; | |
| } | |
| Static void inittables(void) | |
| { | |
| /*inittables*/ | |
| reswords(); | |
| symbols(); | |
| rators(); | |
| instrmnemonics(); | |
| procmnemonics(); | |
| chartypes(); | |
| initdx(); | |
| } | |
| int main(int argc, Char *argv[]) | |
| { | |
| _REC_display *WITH; | |
| setofsys SET; | |
| long SET1[(long)casesy / 32 + 2]; | |
| setofsys SET2; | |
| PASCAL_MAIN(argc, argv); | |
| prr.f = NULL; | |
| strcpy(prr.name, "prr"); | |
| /*initialize*/ | |
| /************/ | |
| initscalars(); | |
| initsets(); | |
| inittables(); | |
| /*enter standard names and standard types:*/ | |
| /******************************************/ | |
| level = 0; | |
| top = 0; | |
| WITH = display; | |
| WITH->fname = NULL; | |
| WITH->flabel = NULL; | |
| (where)WITH->occur = blck; | |
| enterstdtypes(); | |
| stdnames(); | |
| entstdnames(); | |
| enterundecl(); | |
| top = 1; | |
| level = 1; | |
| WITH = &display[1]; | |
| /*compile:*/ | |
| WITH->fname = NULL; | |
| WITH->flabel = NULL; | |
| (where)WITH->occur = blck; | |
| if (*prr.name != '\0') { | |
| if (prr.f != NULL) | |
| prr.f = freopen(prr.name, "w", prr.f); | |
| else | |
| prr.f = fopen(prr.name, "w"); | |
| } else { | |
| if (prr.f != NULL) | |
| rewind(prr.f); | |
| else | |
| prr.f = tmpfile(); | |
| } | |
| if (prr.f == NULL) | |
| _EscIO(FileNotFound); | |
| SETUPBUF(prr.f, Char); | |
| /*comment this out when compiling with pcom */ | |
| /**********/ | |
| insymbol(); | |
| programme(P_setdiff(SET2, P_setunion(SET, blockbegsys, statbegsys), | |
| P_addset(P_expset(SET1, 0), (long)casesy))); | |
| if (prr.f != NULL) | |
| fclose(prr.f); | |
| if (input_ok == true) | |
| return 0; | |
| else | |
| return 1; | |
| } | |
| /* End. */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (*$c+,t-,d-,l-*) | |
| (*********************************************** | |
| * * | |
| * Portable Pascal compiler * | |
| * ************************ * | |
| * * | |
| * Pascal P4 * | |
| * * | |
| * Authors: * | |
| * Urs Ammann * | |
| * Kesav Nori * | |
| * Christian Jacobi * | |
| * Address: * | |
| * Institut Fuer Informatik * | |
| * Eidg. Technische Hochschule * | |
| * CH-8096 Zuerich * | |
| * * | |
| * This code is fully documented in the book * | |
| * "Pascal Implementation" * | |
| * by Steven Pemberton and Martin Daniels * | |
| * published by Ellis Horwood, Chichester, UK * | |
| * ISBN: 0-13-653-0311 * | |
| * (also available in Japanese) * | |
| * * | |
| * Steven Pemberton, CWI/AA, * | |
| * Kruislaan 413, 1098 SJ Amsterdam, NL * | |
| * Steven.Pemberton@cwi.nl * | |
| * * | |
| ***********************************************) | |
| program pascalcompiler(input,output,prr); | |
| const displimit = 20; maxlevel = 10; | |
| intsize = 1; | |
| intal = 1; | |
| realsize = 1; | |
| realal = 1; | |
| charsize = 1; | |
| charal = 1; | |
| charmax = 1; | |
| boolsize = 1; | |
| boolal = 1; | |
| ptrsize = 1; | |
| adral = 1; | |
| setsize = 1; | |
| setal = 1; | |
| stackal = 1; | |
| stackelsize = 1; | |
| strglgth = 16; | |
| sethigh = 47; | |
| setlow = 0; | |
| ordmaxchar = 63; | |
| ordminchar = 0; | |
| maxint = 32767; | |
| lcaftermarkstack = 5; | |
| fileal = charal; | |
| (* stackelsize = minimum size for 1 stackelement | |
| = k*stackal | |
| stackal = scm(all other al-constants) | |
| charmax = scm(charsize,charal) | |
| scm = smallest common multiple | |
| lcaftermarkstack >= 4*ptrsize+max(x-size) | |
| = k1*stackelsize *) | |
| maxstack = 1; | |
| parmal = stackal; | |
| parmsize = stackelsize; | |
| recal = stackal; | |
| filebuffer = 4; | |
| maxaddr = maxint; | |
| type (*describing:*) | |
| (*************) | |
| marktype= ^integer; | |
| (*basic symbols*) | |
| (***************) | |
| symbol = (ident,intconst,realconst,stringconst,notsy,mulop,addop,relop, | |
| lparent,rparent,lbrack,rbrack,comma,semicolon,period,arrow, | |
| colon,becomes,labelsy,constsy,typesy,varsy,funcsy,progsy, | |
| procsy,setsy,packedsy,arraysy,recordsy,filesy,forwardsy, | |
| beginsy,ifsy,casesy,repeatsy,whilesy,forsy,withsy, | |
| gotosy,endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy, | |
| thensy,othersy); | |
| operator = (mul,rdiv,andop,idiv,imod,plus,minus,orop,ltop,leop,geop,gtop, | |
| neop,eqop,inop,noop); | |
| setofsys = set of symbol; | |
| chtp = (letter,number,special,illegal, | |
| chstrquo,chcolon,chperiod,chlt,chgt,chlparen,chspace); | |
| (*constants*) | |
| (***********) | |
| setty = set of setlow..sethigh; | |
| cstclass = (reel,pset,strg); | |
| csp = ^ constant; | |
| constant = record case cclass: cstclass of | |
| reel: (rval: packed array [1..strglgth] of char); | |
| pset: (pval: setty); | |
| strg: (slgth: 0..strglgth; | |
| sval: packed array [1..strglgth] of char) | |
| end; | |
| valu = record case intval: boolean of (*intval never set nor tested*) | |
| true: (ival: integer); | |
| false: (valp: csp) | |
| end; | |
| (*data structures*) | |
| (*****************) | |
| levrange = 0..maxlevel; addrrange = 0..maxaddr; | |
| structform = (scalar,subrange,pointer,power,arrays,records,files, | |
| tagfld,variant); | |
| declkind = (standard,declared); | |
| stp = ^ structure; ctp = ^ identifier; | |
| structure = packed record | |
| marked: boolean; (*for test phase only*) | |
| size: addrrange; | |
| case form: structform of | |
| scalar: (case scalkind: declkind of | |
| declared: (fconst: ctp); standard: ()); | |
| subrange: (rangetype: stp; min,max: valu); | |
| pointer: (eltype: stp); | |
| power: (elset: stp); | |
| arrays: (aeltype,inxtype: stp); | |
| records: (fstfld: ctp; recvar: stp); | |
| files: (filtype: stp); | |
| tagfld: (tagfieldp: ctp; fstvar: stp); | |
| variant: (nxtvar,subvar: stp; varval: valu) | |
| end; | |
| (*names*) | |
| (*******) | |
| idclass = (types,konst,vars,field,proc,func); | |
| setofids = set of idclass; | |
| idkind = (actual,formal); | |
| alpha = packed array [1..8] of char; | |
| identifier = packed record | |
| name: alpha; llink, rlink: ctp; | |
| idtype: stp; next: ctp; | |
| case klass: idclass of | |
| types: (); | |
| konst: (values: valu); | |
| vars: (vkind: idkind; vlev: levrange; vaddr: addrrange); | |
| field: (fldaddr: addrrange); | |
| proc, func: (case pfdeckind: declkind of | |
| standard: (key: 1..15); | |
| declared: (pflev: levrange; pfname: integer; | |
| case pfkind: idkind of | |
| actual: (forwdecl, externl: boolean); | |
| formal: ())) | |
| end; | |
| disprange = 0..displimit; | |
| where = (blck,crec,vrec,rec); | |
| (*expressions*) | |
| (*************) | |
| attrkind = (cst,varbl,expr); | |
| vaccess = (drct,indrct,inxd); | |
| attr = record typtr: stp; | |
| case kind: attrkind of | |
| cst: (cval: valu); | |
| varbl: (case access: vaccess of | |
| drct: (vlevel: levrange; dplmt: addrrange); | |
| indrct: (idplmt: addrrange)) | |
| end; | |
| testp = ^ testpointer; | |
| testpointer = packed record | |
| elt1,elt2 : stp; | |
| lasttestp : testp | |
| end; | |
| (*labels*) | |
| (********) | |
| lbp = ^ labl; | |
| labl = record nextlab: lbp; defined: boolean; | |
| labval, labname: integer | |
| end; | |
| extfilep = ^filerec; | |
| filerec = record filename:alpha; nextfile:extfilep end; | |
| (*————————————————————————-*) | |
| var | |
| prr: text; (* comment this out when compiling with pcom *) | |
| (*returned by source program scanner | |
| insymbol: | |
| **********) | |
| sy: symbol; (*last symbol*) | |
| op: operator; (*classification of last symbol*) | |
| val: valu; (*value of last constant*) | |
| lgth: integer; (*length of last string constant*) | |
| id: alpha; (*last identifier (possibly truncated)*) | |
| kk: 1..8; (*nr of chars in last identifier*) | |
| ch: char; (*last character*) | |
| eol: boolean; (*end of line flag*) | |
| (*counters:*) | |
| (***********) | |
| chcnt: integer; (*character counter*) | |
| lc,ic: addrrange; (*data location and instruction counter*) | |
| linecount: integer; | |
| (*switches:*) | |
| (***********) | |
| dp, (*declaration part*) | |
| prterr, (*to allow forward references in pointer type | |
| declaration by suppressing error message*) | |
| list,prcode,prtables: boolean; (*output options for | |
| — source program listing | |
| — printing symbolic code | |
| — displaying ident and struct tables | |
| –> procedure option*) | |
| debug: boolean; | |
| (*pointers:*) | |
| (***********) | |
| parmptr, | |
| intptr,realptr,charptr, | |
| boolptr,nilptr,textptr: stp; (*pointers to entries of standard ids*) | |
| utypptr,ucstptr,uvarptr, | |
| ufldptr,uprcptr,ufctptr, (*pointers to entries for undeclared ids*) | |
| fwptr: ctp; (*head of chain of forw decl type ids*) | |
| fextfilep: extfilep; (*head of chain of external files*) | |
| globtestp: testp; (*last testpointer*) | |
| (*bookkeeping of declaration levels:*) | |
| (************************************) | |
| level: levrange; (*current static level*) | |
| disx, (*level of last id searched by searchid*) | |
| top: disprange; (*top of display*) | |
| display: (*where: means:*) | |
| array [disprange] of | |
| packed record (*=blck: id is variable id*) | |
| fname: ctp; flabel: lbp; (*=crec: id is field id in record with*) | |
| case occur: where of (* constant address*) | |
| crec: (clev: levrange; (*=vrec: id is field id in record with*) | |
| cdspl: addrrange);(* variable address*) | |
| vrec: (vdspl: addrrange) | |
| end; (* –> procedure withstatement*) | |
| (*error messages:*) | |
| (*****************) | |
| errinx: 0..10; (*nr of errors in current source line*) | |
| errlist: | |
| array [1..10] of | |
| packed record pos: integer; | |
| nmr: 1..400 | |
| end; | |
| (*expression compilation:*) | |
| (*************************) | |
| gattr: attr; (*describes the expr currently compiled*) | |
| (*structured constants:*) | |
| (***********************) | |
| constbegsys,simptypebegsys,typebegsys,blockbegsys,selectsys,facbegsys, | |
| statbegsys,typedels: setofsys; | |
| chartp : array[char] of chtp; | |
| rw: array [1..35(*nr. of res. words*)] of alpha; | |
| frw: array [1..9] of 1..36(*nr. of res. words + 1*); | |
| rsy: array [1..35(*nr. of res. words*)] of symbol; | |
| ssy: array [char] of symbol; | |
| rop: array [1..35(*nr. of res. words*)] of operator; | |
| sop: array [char] of operator; | |
| na: array [1..35] of alpha; | |
| mn: array [0..60] of packed array [1..4] of char; | |
| sna: array [1..23] of packed array [1..4] of char; | |
| cdx: array [0..60] of -4..+4; | |
| pdx: array [1..23] of -7..+7; | |
| ordint: array [char] of integer; | |
| intlabel,mxint10,digmax: integer; | |
| (*————————————————————————-*) | |
| procedure mark(var p: marktype); begin end; | |
| procedure release(p: marktype); begin end; | |
| procedure endofline; | |
| var lastpos,freepos,currpos,currnmr,f,k: integer; | |
| begin | |
| if errinx > 0 then (*output error messages*) | |
| begin write(output,linecount:6,' **** ':9); | |
| lastpos := 0; freepos := 1; | |
| for k := 1 to errinx do | |
| begin | |
| with errlist[k] do | |
| begin currpos := pos; currnmr := nmr end; | |
| if currpos = lastpos then write(output,',') | |
| else | |
| begin | |
| while freepos < currpos do | |
| begin write(output,' '); freepos := freepos + 1 end; | |
| write(output,'^'); | |
| lastpos := currpos | |
| end; | |
| if currnmr < 10 then f := 1 | |
| else if currnmr < 100 then f := 2 | |
| else f := 3; | |
| write(output,currnmr:f); | |
| freepos := freepos + f + 1 | |
| end; | |
| writeln(output); errinx := 0 | |
| end; | |
| linecount := linecount + 1; | |
| if list and (not eof(input)) then | |
| begin write(output,linecount:6,' ':2); | |
| if dp then write(output,lc:7) else write(output,ic:7); | |
| write(output,' ') | |
| end; | |
| chcnt := 0 | |
| end (*endofline*) ; | |
| procedure error(ferrnr: integer); | |
| begin | |
| if errinx >= 9 then | |
| begin errlist[10].nmr := 255; errinx := 10 end | |
| else | |
| begin errinx := errinx + 1; | |
| errlist[errinx].nmr := ferrnr | |
| end; | |
| errlist[errinx].pos := chcnt | |
| end (*error*) ; | |
| procedure insymbol; | |
| (*read next basic symbol of source program and return its | |
| description in the global variables sy, op, id, val and lgth*) | |
| label 1,2,3; | |
| var i,k: integer; | |
| digit: packed array [1..strglgth] of char; | |
| string: packed array [1..strglgth] of char; | |
| lvp: csp; test: boolean; | |
| procedure nextch; | |
| begin if eol then | |
| begin if list then writeln(output); endofline | |
| end; | |
| if not eof(input) then | |
| begin eol := eoln(input); read(input,ch); | |
| if list then write(output,ch); | |
| chcnt := chcnt + 1 | |
| end | |
| else | |
| begin writeln(output,' *** eof ','encountered'); | |
| test := false | |
| end | |
| end; | |
| procedure options; | |
| begin | |
| repeat nextch; | |
| if ch <> '*' then | |
| begin | |
| if ch = 't' then | |
| begin nextch; prtables := ch = '+' end | |
| else | |
| if ch = 'l' then | |
| begin nextch; list := ch = '+'; | |
| if not list then writeln(output) | |
| end | |
| else | |
| if ch = 'd' then | |
| begin nextch; debug := ch = '+' end | |
| else | |
| if ch = 'c' then | |
| begin nextch; prcode := ch = '+' end; | |
| nextch | |
| end | |
| until ch <> ',' | |
| end (*options*) ; | |
| begin (*insymbol*) | |
| 1: | |
| repeat while ((ch = ' ') or (ch = ' ')) and not eol do nextch; | |
| test := eol; | |
| if test then nextch | |
| until not test; | |
| if chartp[ch] = illegal then | |
| begin sy := othersy; op := noop; | |
| error(399); nextch | |
| end | |
| else | |
| case chartp[ch] of | |
| letter: | |
| begin k := 0; | |
| repeat | |
| if k < 8 then | |
| begin k := k + 1; id[k] := ch end ; | |
| nextch | |
| until chartp[ch] in [special,illegal,chstrquo,chcolon, | |
| chperiod,chlt,chgt,chlparen,chspace]; | |
| if k >= kk then kk := k | |
| else | |
| repeat id[kk] := ' '; kk := kk – 1 | |
| until kk = k; | |
| for i := frw[k] to frw[k+1] – 1 do | |
| if rw[i] = id then | |
| begin sy := rsy[i]; op := rop[i]; goto 2 end; | |
| sy := ident; op := noop; | |
| 2: end; | |
| number: | |
| begin op := noop; i := 0; | |
| repeat i := i+1; if i<= digmax then digit[i] := ch; nextch | |
| until chartp[ch] <> number; | |
| if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then | |
| begin | |
| k := i; | |
| if ch = '.' then | |
| begin k := k+1; if k <= digmax then digit[k] := ch; | |
| nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*) | |
| if chartp[ch] <> number then error(201) | |
| else | |
| repeat k := k + 1; | |
| if k <= digmax then digit[k] := ch; nextch | |
| until chartp[ch] <> number | |
| end; | |
| if ch = 'e' then | |
| begin k := k+1; if k <= digmax then digit[k] := ch; | |
| nextch; | |
| if (ch = '+') or (ch ='-') then | |
| begin k := k+1; if k <= digmax then digit[k] := ch; | |
| nextch | |
| end; | |
| if chartp[ch] <> number then error(201) | |
| else | |
| repeat k := k+1; | |
| if k <= digmax then digit[k] := ch; nextch | |
| until chartp[ch] <> number | |
| end; | |
| new(lvp,reel); sy:= realconst; lvp^.cclass := reel; | |
| with lvp^ do | |
| begin for i := 1 to strglgth do rval[i] := ' '; | |
| if k <= digmax then | |
| for i := 2 to k + 1 do rval[i] := digit[i-1] | |
| else begin error(203); rval[2] := '0'; | |
| rval[3] := '.'; rval[4] := '0' | |
| end | |
| end; | |
| val.valp := lvp | |
| end | |
| else | |
| 3: begin | |
| if i > digmax then begin error(203); val.ival := 0 end | |
| else | |
| with val do | |
| begin ival := 0; | |
| for k := 1 to i do | |
| begin | |
| if ival <= mxint10 then | |
| ival := ival*10+ordint[digit[k]] | |
| else begin error(203); ival := 0 end | |
| end; | |
| sy := intconst | |
| end | |
| end | |
| end; | |
| chstrquo: | |
| begin lgth := 0; sy := stringconst; op := noop; | |
| repeat | |
| repeat nextch; lgth := lgth + 1; | |
| if lgth <= strglgth then string[lgth] := ch | |
| until (eol) or (ch = ''''); | |
| if eol then error(202) else nextch | |
| until ch <> ''''; | |
| lgth := lgth – 1; (*now lgth = nr of chars in string*) | |
| if lgth = 0 then error(205) else | |
| if lgth = 1 then val.ival := ord(string[1]) | |
| else | |
| begin new(lvp,strg); lvp^.cclass:=strg; | |
| if lgth > strglgth then | |
| begin error(399); lgth := strglgth end; | |
| with lvp^ do | |
| begin slgth := lgth; | |
| for i := 1 to lgth do sval[i] := string[i] | |
| end; | |
| val.valp := lvp | |
| end | |
| end; | |
| chcolon: | |
| begin op := noop; nextch; | |
| if ch = '=' then | |
| begin sy := becomes; nextch end | |
| else sy := colon | |
| end; | |
| chperiod: | |
| begin op := noop; nextch; | |
| if ch = '.' then | |
| begin sy := colon; nextch end | |
| else sy := period | |
| end; | |
| chlt: | |
| begin nextch; sy := relop; | |
| if ch = '=' then | |
| begin op := leop; nextch end | |
| else | |
| if ch = '>' then | |
| begin op := neop; nextch end | |
| else op := ltop | |
| end; | |
| chgt: | |
| begin nextch; sy := relop; | |
| if ch = '=' then | |
| begin op := geop; nextch end | |
| else op := gtop | |
| end; | |
| chlparen: | |
| begin nextch; | |
| if ch = '*' then | |
| begin nextch; | |
| if ch = '$' then options; | |
| repeat | |
| while (ch <> '*') and not eof(input) do nextch; | |
| nextch | |
| until (ch = ')') or eof(input); | |
| nextch; goto 1 | |
| end; | |
| sy := lparent; op := noop | |
| end; | |
| special: | |
| begin sy := ssy[ch]; op := sop[ch]; | |
| nextch | |
| end; | |
| chspace: sy := othersy | |
| end (*case*) | |
| end (*insymbol*) ; | |
| procedure enterid(fcp: ctp); | |
| (*enter id pointed at by fcp into the name-table, | |
| which on each declaration level is organised as | |
| an unbalanced binary tree*) | |
| var nam: alpha; lcp, lcp1: ctp; lleft: boolean; | |
| begin nam := fcp^.name; | |
| lcp := display[top].fname; | |
| if lcp = nil then | |
| display[top].fname := fcp | |
| else | |
| begin | |
| repeat lcp1 := lcp; | |
| if lcp^.name = nam then (*name conflict, follow right link*) | |
| begin error(101); lcp := lcp^.rlink; lleft := false end | |
| else | |
| if lcp^.name < nam then | |
| begin lcp := lcp^.rlink; lleft := false end | |
| else begin lcp := lcp^.llink; lleft := true end | |
| until lcp = nil; | |
| if lleft then lcp1^.llink := fcp else lcp1^.rlink := fcp | |
| end; | |
| fcp^.llink := nil; fcp^.rlink := nil | |
| end (*enterid*) ; | |
| procedure searchsection(fcp: ctp; var fcp1: ctp); | |
| (*to find record fields and forward declared procedure id's | |
| –> procedure proceduredeclaration | |
| –> procedure selector*) | |
| label 1; | |
| begin | |
| while fcp <> nil do | |
| if fcp^.name = id then goto 1 | |
| else if fcp^.name < id then fcp := fcp^.rlink | |
| else fcp := fcp^.llink; | |
| 1: fcp1 := fcp | |
| end (*searchsection*) ; | |
| procedure searchid(fidcls: setofids; var fcp: ctp); | |
| label 1; | |
| var lcp: ctp; | |
| begin | |
| for disx := top downto 0 do | |
| begin lcp := display[disx].fname; | |
| while lcp <> nil do | |
| if lcp^.name = id then | |
| if lcp^.klass in fidcls then goto 1 | |
| else | |
| begin if prterr then error(103); | |
| lcp := lcp^.rlink | |
| end | |
| else | |
| if lcp^.name < id then | |
| lcp := lcp^.rlink | |
| else lcp := lcp^.llink | |
| end; | |
| (*search not successful; suppress error message in case | |
| of forward referenced type id in pointer type definition | |
| –> procedure simpletype*) | |
| if prterr then | |
| begin error(104); | |
| (*to avoid returning nil, reference an entry | |
| for an undeclared id of appropriate class | |
| –> procedure enterundecl*) | |
| if types in fidcls then lcp := utypptr | |
| else | |
| if vars in fidcls then lcp := uvarptr | |
| else | |
| if field in fidcls then lcp := ufldptr | |
| else | |
| if konst in fidcls then lcp := ucstptr | |
| else | |
| if proc in fidcls then lcp := uprcptr | |
| else lcp := ufctptr; | |
| end; | |
| 1: fcp := lcp | |
| end (*searchid*) ; | |
| procedure getbounds(fsp: stp; var fmin,fmax: integer); | |
| (*get internal bounds of subrange or scalar type*) | |
| (*assume fsp<>intptr and fsp<>realptr*) | |
| begin | |
| fmin := 0; fmax := 0; | |
| if fsp <> nil then | |
| with fsp^ do | |
| if form = subrange then | |
| begin fmin := min.ival; fmax := max.ival end | |
| else | |
| if fsp = charptr then | |
| begin fmin := ordminchar; fmax := ordmaxchar | |
| end | |
| else | |
| if fconst <> nil then | |
| fmax := fconst^.values.ival | |
| end (*getbounds*) ; | |
| function alignquot(fsp: stp): integer; | |
| begin | |
| alignquot := 1; | |
| if fsp <> nil then | |
| with fsp^ do | |
| case form of | |
| scalar: if fsp=intptr then alignquot := intal | |
| else if fsp=boolptr then alignquot := boolal | |
| else if scalkind=declared then alignquot := intal | |
| else if fsp=charptr then alignquot := charal | |
| else if fsp=realptr then alignquot := realal | |
| else (*parmptr*) alignquot := parmal; | |
| subrange: alignquot := alignquot(rangetype); | |
| pointer: alignquot := adral; | |
| power: alignquot := setal; | |
| files: alignquot := fileal; | |
| arrays: alignquot := alignquot(aeltype); | |
| records: alignquot := recal; | |
| variant,tagfld: error(501) | |
| end | |
| end (*alignquot*); | |
| procedure align(fsp: stp; var flc: addrrange); | |
| var k,l: integer; | |
| begin | |
| k := alignquot(fsp); | |
| l := flc-1; | |
| flc := l + k – (k+l) mod k | |
| end (*align*); | |
| procedure printtables(fb: boolean); | |
| (*print data structure and name table*) | |
| var i, lim: disprange; | |
| procedure marker; | |
| (*mark data structure entries to avoid multiple printout*) | |
| var i: integer; | |
| procedure markctp(fp: ctp); forward; | |
| procedure markstp(fp: stp); | |
| (*mark data structures, prevent cycles*) | |
| begin | |
| if fp <> nil then | |
| with fp^ do | |
| begin marked := true; | |
| case form of | |
| scalar: ; | |
| subrange: markstp(rangetype); | |
| pointer: (*don't mark eltype: cycle possible; will be marked | |
| anyway, if fp = true*) ; | |
| power: markstp(elset) ; | |
| arrays: begin markstp(aeltype); markstp(inxtype) end; | |
| records: begin markctp(fstfld); markstp(recvar) end; | |
| files: markstp(filtype); | |
| tagfld: markstp(fstvar); | |
| variant: begin markstp(nxtvar); markstp(subvar) end | |
| end (*case*) | |
| end (*with*) | |
| end (*markstp*); | |
| procedure markctp; | |
| begin | |
| if fp <> nil then | |
| with fp^ do | |
| begin markctp(llink); markctp(rlink); | |
| markstp(idtype) | |
| end | |
| end (*markctp*); | |
| begin (*marker*) | |
| for i := top downto lim do | |
| markctp(display[i].fname) | |
| end (*marker*); | |
| procedure followctp(fp: ctp); forward; | |
| procedure followstp(fp: stp); | |
| begin | |
| if fp <> nil then | |
| with fp^ do | |
| if marked then | |
| begin marked := false; write(output,' ':4,ord(fp):6,size:10); | |
| case form of | |
| scalar: begin write(output,'scalar':10); | |
| if scalkind = standard then | |
| write(output,'standard':10) | |
| else write(output,'declared':10,' ':4,ord(fconst):6); | |
| writeln(output) | |
| end; | |
| subrange: begin | |
| write(output,'subrange':10,' ':4,ord(rangetype):6); | |
| if rangetype <> realptr then | |
| write(output,min.ival,max.ival) | |
| else | |
| if (min.valp <> nil) and (max.valp <> nil) then | |
| write(output,' ',min.valp^.rval:9, | |
| ' ',max.valp^.rval:9); | |
| writeln(output); followstp(rangetype); | |
| end; | |
| pointer: writeln(output,'pointer':10,' ':4,ord(eltype):6); | |
| power: begin writeln(output,'set':10,' ':4,ord(elset):6); | |
| followstp(elset) | |
| end; | |
| arrays: begin | |
| writeln(output,'array':10,' ':4,ord(aeltype):6,' ':4, | |
| ord(inxtype):6); | |
| followstp(aeltype); followstp(inxtype) | |
| end; | |
| records: begin | |
| writeln(output,'record':10,' ':4,ord(fstfld):6,' ':4, | |
| ord(recvar):6); followctp(fstfld); | |
| followstp(recvar) | |
| end; | |
| files: begin write(output,'file':10,' ':4,ord(filtype):6); | |
| followstp(filtype) | |
| end; | |
| tagfld: begin writeln(output,'tagfld':10,' ':4,ord(tagfieldp):6, | |
| ' ':4,ord(fstvar):6); | |
| followstp(fstvar) | |
| end; | |
| variant: begin writeln(output,'variant':10,' ':4,ord(nxtvar):6, | |
| ' ':4,ord(subvar):6,varval.ival); | |
| followstp(nxtvar); followstp(subvar) | |
| end | |
| end (*case*) | |
| end (*if marked*) | |
| end (*followstp*); | |
| procedure followctp; | |
| var i: integer; | |
| begin | |
| if fp <> nil then | |
| with fp^ do | |
| begin write(output,' ':4,ord(fp):6,' ',name:9,' ':4,ord(llink):6, | |
| ' ':4,ord(rlink):6,' ':4,ord(idtype):6); | |
| case klass of | |
| types: write(output,'type':10); | |
| konst: begin write(output,'constant':10,' ':4,ord(next):6); | |
| if idtype <> nil then | |
| if idtype = realptr then | |
| begin | |
| if values.valp <> nil then | |
| write(output,' ',values.valp^.rval:9) | |
| end | |
| else | |
| if idtype^.form = arrays then (*stringconst*) | |
| begin | |
| if values.valp <> nil then | |
| begin write(output,' '); | |
| with values.valp^ do | |
| for i := 1 to slgth do | |
| write(output,sval[i]) | |
| end | |
| end | |
| else write(output,values.ival) | |
| end; | |
| vars: begin write(output,'variable':10); | |
| if vkind = actual then write(output,'actual':10) | |
| else write(output,'formal':10); | |
| write(output,' ':4,ord(next):6,vlev,' ':4,vaddr:6 ); | |
| end; | |
| field: write(output,'field':10,' ':4,ord(next):6,' ':4,fldaddr:6); | |
| proc, | |
| func: begin | |
| if klass = proc then write(output,'procedure':10) | |
| else write(output,'function':10); | |
| if pfdeckind = standard then | |
| write(output,'standard':10, key:10) | |
| else | |
| begin write(output,'declared':10,' ':4,ord(next):6); | |
| write(output,pflev,' ':4,pfname:6); | |
| if pfkind = actual then | |
| begin write(output,'actual':10); | |
| if forwdecl then write(output,'forward':10) | |
| else write(output,'notforward':10); | |
| if externl then write(output,'extern':10) | |
| else write(output,'not extern':10); | |
| end | |
| else write(output,'formal':10) | |
| end | |
| end | |
| end (*case*); | |
| writeln(output); | |
| followctp(llink); followctp(rlink); | |
| followstp(idtype) | |
| end (*with*) | |
| end (*followctp*); | |
| begin (*printtables*) | |
| writeln(output); writeln(output); writeln(output); | |
| if fb then lim := 0 | |
| else begin lim := top; write(output,' local') end; | |
| writeln(output,' tables '); writeln(output); | |
| marker; | |
| for i := top downto lim do | |
| followctp(display[i].fname); | |
| writeln(output); | |
| if not eol then write(output,' ':chcnt+16) | |
| end (*printtables*); | |
| procedure genlabel(var nxtlab: integer); | |
| begin intlabel := intlabel + 1; | |
| nxtlab := intlabel | |
| end (*genlabel*); | |
| procedure block(fsys: setofsys; fsy: symbol; fprocp: ctp); | |
| var lsy: symbol; test: boolean; | |
| procedure skip(fsys: setofsys); | |
| (*skip input string until relevant symbol found*) | |
| begin | |
| if not eof(input) then | |
| begin while not(sy in fsys) and (not eof(input)) do insymbol; | |
| if not (sy in fsys) then insymbol | |
| end | |
| end (*skip*) ; | |
| procedure constant(fsys: setofsys; var fsp: stp; var fvalu: valu); | |
| var lsp: stp; lcp: ctp; sign: (none,pos,neg); | |
| lvp: csp; i: 2..strglgth; | |
| begin lsp := nil; fvalu.ival := 0; | |
| if not(sy in constbegsys) then | |
| begin error(50); skip(fsys+constbegsys) end; | |
| if sy in constbegsys then | |
| begin | |
| if sy = stringconst then | |
| begin | |
| if lgth = 1 then lsp := charptr | |
| else | |
| begin | |
| new(lsp,arrays); | |
| with lsp^ do | |
| begin aeltype := charptr; inxtype := nil; | |
| size := lgth*charsize; form := arrays | |
| end | |
| end; | |
| fvalu := val; insymbol | |
| end | |
| else | |
| begin | |
| sign := none; | |
| if (sy = addop) and (op in [plus,minus]) then | |
| begin if op = plus then sign := pos else sign := neg; | |
| insymbol | |
| end; | |
| if sy = ident then | |
| begin searchid([konst],lcp); | |
| with lcp^ do | |
| begin lsp := idtype; fvalu := values end; | |
| if sign <> none then | |
| if lsp = intptr then | |
| begin if sign = neg then fvalu.ival := -fvalu.ival end | |
| else | |
| if lsp = realptr then | |
| begin | |
| if sign = neg then | |
| begin new(lvp,reel); | |
| if fvalu.valp^.rval[1] = '-' then | |
| lvp^.rval[1] := '+' | |
| else lvp^.rval[1] := '-'; | |
| for i := 2 to strglgth do | |
| lvp^.rval[i] := fvalu.valp^.rval[i]; | |
| fvalu.valp := lvp; | |
| end | |
| end | |
| else error(105); | |
| insymbol; | |
| end | |
| else | |
| if sy = intconst then | |
| begin if sign = neg then val.ival := -val.ival; | |
| lsp := intptr; fvalu := val; insymbol | |
| end | |
| else | |
| if sy = realconst then | |
| begin if sign = neg then val.valp^.rval[1] := '-'; | |
| lsp := realptr; fvalu := val; insymbol | |
| end | |
| else | |
| begin error(106); skip(fsys) end | |
| end; | |
| if not (sy in fsys) then | |
| begin error(6); skip(fsys) end | |
| end; | |
| fsp := lsp | |
| end (*constant*) ; | |
| function equalbounds(fsp1,fsp2: stp): boolean; | |
| var lmin1,lmin2,lmax1,lmax2: integer; | |
| begin | |
| if (fsp1=nil) or (fsp2=nil) then equalbounds := true | |
| else | |
| begin | |
| getbounds(fsp1,lmin1,lmax1); | |
| getbounds(fsp2,lmin2,lmax2); | |
| equalbounds := (lmin1=lmin2) and (lmax1=lmax2) | |
| end | |
| end (*equalbounds*) ; | |
| function comptypes(fsp1,fsp2: stp) : boolean; | |
| (*decide whether structures pointed at by fsp1 and fsp2 are compatible*) | |
| var nxt1,nxt2: ctp; comp: boolean; | |
| ltestp1,ltestp2 : testp; | |
| begin | |
| if fsp1 = fsp2 then comptypes := true | |
| else | |
| if (fsp1 <> nil) and (fsp2 <> nil) then | |
| if fsp1^.form = fsp2^.form then | |
| case fsp1^.form of | |
| scalar: | |
| comptypes := false; | |
| (* identical scalars declared on different levels are | |
| not recognized to be compatible*) | |
| subrange: | |
| comptypes := comptypes(fsp1^.rangetype,fsp2^.rangetype); | |
| pointer: | |
| begin | |
| comp := false; ltestp1 := globtestp; | |
| ltestp2 := globtestp; | |
| while ltestp1 <> nil do | |
| with ltestp1^ do | |
| begin | |
| if (elt1 = fsp1^.eltype) and | |
| (elt2 = fsp2^.eltype) then comp := true; | |
| ltestp1 := lasttestp | |
| end; | |
| if not comp then | |
| begin new(ltestp1); | |
| with ltestp1^ do | |
| begin elt1 := fsp1^.eltype; | |
| elt2 := fsp2^.eltype; | |
| lasttestp := globtestp | |
| end; | |
| globtestp := ltestp1; | |
| comp := comptypes(fsp1^.eltype,fsp2^.eltype) | |
| end; | |
| comptypes := comp; globtestp := ltestp2 | |
| end; | |
| power: | |
| comptypes := comptypes(fsp1^.elset,fsp2^.elset); | |
| arrays: | |
| begin | |
| comp := comptypes(fsp1^.aeltype,fsp2^.aeltype) | |
| and comptypes(fsp1^.inxtype,fsp2^.inxtype); | |
| comptypes := comp and (fsp1^.size = fsp2^.size) and | |
| equalbounds(fsp1^.inxtype,fsp2^.inxtype) | |
| end; | |
| records: | |
| begin nxt1 := fsp1^.fstfld; nxt2 := fsp2^.fstfld; comp:=true; | |
| while (nxt1 <> nil) and (nxt2 <> nil) do | |
| begin comp:=comp and comptypes(nxt1^.idtype,nxt2^.idtype); | |
| nxt1 := nxt1^.next; nxt2 := nxt2^.next | |
| end; | |
| comptypes := comp and (nxt1 = nil) and (nxt2 = nil) | |
| and(fsp1^.recvar = nil)and(fsp2^.recvar = nil) | |
| end; | |
| (*identical records are recognized to be compatible | |
| iff no variants occur*) | |
| files: | |
| comptypes := comptypes(fsp1^.filtype,fsp2^.filtype) | |
| end (*case*) | |
| else (*fsp1^.form <> fsp2^.form*) | |
| if fsp1^.form = subrange then | |
| comptypes := comptypes(fsp1^.rangetype,fsp2) | |
| else | |
| if fsp2^.form = subrange then | |
| comptypes := comptypes(fsp1,fsp2^.rangetype) | |
| else comptypes := false | |
| else comptypes := true | |
| end (*comptypes*) ; | |
| function string(fsp: stp) : boolean; | |
| begin string := false; | |
| if fsp <> nil then | |
| if fsp^.form = arrays then | |
| if comptypes(fsp^.aeltype,charptr) then string := true | |
| end (*string*) ; | |
| procedure typ(fsys: setofsys; var fsp: stp; var fsize: addrrange); | |
| var lsp,lsp1,lsp2: stp; oldtop: disprange; lcp: ctp; | |
| lsize,displ: addrrange; lmin,lmax: integer; | |
| procedure simpletype(fsys:setofsys; var fsp:stp; var fsize:addrrange); | |
| var lsp,lsp1: stp; lcp,lcp1: ctp; ttop: disprange; | |
| lcnt: integer; lvalu: valu; | |
| begin fsize := 1; | |
| if not (sy in simptypebegsys) then | |
| begin error(1); skip(fsys + simptypebegsys) end; | |
| if sy in simptypebegsys then | |
| begin | |
| if sy = lparent then | |
| begin ttop := top; (*decl. consts local to innermost block*) | |
| while display[top].occur <> blck do top := top – 1; | |
| new(lsp,scalar,declared); | |
| with lsp^ do | |
| begin size := intsize; form := scalar; | |
| scalkind := declared | |
| end; | |
| lcp1 := nil; lcnt := 0; | |
| repeat insymbol; | |
| if sy = ident then | |
| begin new(lcp,konst); | |
| with lcp^ do | |
| begin name := id; idtype := lsp; next := lcp1; | |
| values.ival := lcnt; klass := konst | |
| end; | |
| enterid(lcp); | |
| lcnt := lcnt + 1; | |
| lcp1 := lcp; insymbol | |
| end | |
| else error(2); | |
| if not (sy in fsys + [comma,rparent]) then | |
| begin error(6); skip(fsys + [comma,rparent]) end | |
| until sy <> comma; | |
| lsp^.fconst := lcp1; top := ttop; | |
| if sy = rparent then insymbol else error(4) | |
| end | |
| else | |
| begin | |
| if sy = ident then | |
| begin searchid([types,konst],lcp); | |
| insymbol; | |
| if lcp^.klass = konst then | |
| begin new(lsp,subrange); | |
| with lsp^, lcp^ do | |
| begin rangetype := idtype; form := subrange; | |
| if string(rangetype) then | |
| begin error(148); rangetype := nil end; | |
| min := values; size := intsize | |
| end; | |
| if sy = colon then insymbol else error(5); | |
| constant(fsys,lsp1,lvalu); | |
| lsp^.max := lvalu; | |
| if lsp^.rangetype <> lsp1 then error(107) | |
| end | |
| else | |
| begin lsp := lcp^.idtype; | |
| if lsp <> nil then fsize := lsp^.size | |
| end | |
| end (*sy = ident*) | |
| else | |
| begin new(lsp,subrange); lsp^.form := subrange; | |
| constant(fsys + [colon],lsp1,lvalu); | |
| if string(lsp1) then | |
| begin error(148); lsp1 := nil end; | |
| with lsp^ do | |
| begin rangetype:=lsp1; min:=lvalu; size:=intsize end; | |
| if sy = colon then insymbol else error(5); | |
| constant(fsys,lsp1,lvalu); | |
| lsp^.max := lvalu; | |
| if lsp^.rangetype <> lsp1 then error(107) | |
| end; | |
| if lsp <> nil then | |
| with lsp^ do | |
| if form = subrange then | |
| if rangetype <> nil then | |
| if rangetype = realptr then error(399) | |
| else | |
| if min.ival > max.ival then error(102) | |
| end; | |
| fsp := lsp; | |
| if not (sy in fsys) then | |
| begin error(6); skip(fsys) end | |
| end | |
| else fsp := nil | |
| end (*simpletype*) ; | |
| procedure fieldlist(fsys: setofsys; var frecvar: stp); | |
| var lcp,lcp1,nxt,nxt1: ctp; lsp,lsp1,lsp2,lsp3,lsp4: stp; | |
| minsize,maxsize,lsize: addrrange; lvalu: valu; | |
| begin nxt1 := nil; lsp := nil; | |
| if not (sy in (fsys+[ident,casesy])) then | |
| begin error(19); skip(fsys + [ident,casesy]) end; | |
| while sy = ident do | |
| begin nxt := nxt1; | |
| repeat | |
| if sy = ident then | |
| begin new(lcp,field); | |
| with lcp^ do | |
| begin name := id; idtype := nil; next := nxt; | |
| klass := field | |
| end; | |
| nxt := lcp; | |
| enterid(lcp); | |
| insymbol | |
| end | |
| else error(2); | |
| if not (sy in [comma,colon]) then | |
| begin error(6); skip(fsys + [comma,colon,semicolon,casesy]) | |
| end; | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = colon then insymbol else error(5); | |
| typ(fsys + [casesy,semicolon],lsp,lsize); | |
| while nxt <> nxt1 do | |
| with nxt^ do | |
| begin align(lsp,displ); | |
| idtype := lsp; fldaddr := displ; | |
| nxt := next; displ := displ + lsize | |
| end; | |
| nxt1 := lcp; | |
| while sy = semicolon do | |
| begin insymbol; | |
| if not (sy in fsys + [ident,casesy,semicolon]) then | |
| begin error(19); skip(fsys + [ident,casesy]) end | |
| end | |
| end (*while*); | |
| nxt := nil; | |
| while nxt1 <> nil do | |
| with nxt1^ do | |
| begin lcp := next; next := nxt; nxt := nxt1; nxt1 := lcp end; | |
| if sy = casesy then | |
| begin new(lsp,tagfld); | |
| with lsp^ do | |
| begin tagfieldp := nil; fstvar := nil; form:=tagfld end; | |
| frecvar := lsp; | |
| insymbol; | |
| if sy = ident then | |
| begin new(lcp,field); | |
| with lcp^ do | |
| begin name := id; idtype := nil; klass:=field; | |
| next := nil; fldaddr := displ | |
| end; | |
| enterid(lcp); | |
| insymbol; | |
| if sy = colon then insymbol else error(5); | |
| if sy = ident then | |
| begin searchid([types],lcp1); | |
| lsp1 := lcp1^.idtype; | |
| if lsp1 <> nil then | |
| begin align(lsp1,displ); | |
| lcp^.fldaddr := displ; | |
| displ := displ+lsp1^.size; | |
| if (lsp1^.form <= subrange) or string(lsp1) then | |
| begin if comptypes(realptr,lsp1) then error(109) | |
| else if string(lsp1) then error(399); | |
| lcp^.idtype := lsp1; lsp^.tagfieldp := lcp; | |
| end | |
| else error(110); | |
| end; | |
| insymbol; | |
| end | |
| else begin error(2); skip(fsys + [ofsy,lparent]) end | |
| end | |
| else begin error(2); skip(fsys + [ofsy,lparent]) end; | |
| lsp^.size := displ; | |
| if sy = ofsy then insymbol else error(8); | |
| lsp1 := nil; minsize := displ; maxsize := displ; | |
| repeat lsp2 := nil; | |
| if not (sy in fsys + [semicolon]) then | |
| begin | |
| repeat constant(fsys + [comma,colon,lparent],lsp3,lvalu); | |
| if lsp^.tagfieldp <> nil then | |
| if not comptypes(lsp^.tagfieldp^.idtype,lsp3)then error(111); | |
| new(lsp3,variant); | |
| with lsp3^ do | |
| begin nxtvar := lsp1; subvar := lsp2; varval := lvalu; | |
| form := variant | |
| end; | |
| lsp4 := lsp1; | |
| while lsp4 <> nil do | |
| with lsp4^ do | |
| begin | |
| if varval.ival = lvalu.ival then error(178); | |
| lsp4 := nxtvar | |
| end; | |
| lsp1 := lsp3; lsp2 := lsp3; | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = colon then insymbol else error(5); | |
| if sy = lparent then insymbol else error(9); | |
| fieldlist(fsys + [rparent,semicolon],lsp2); | |
| if displ > maxsize then maxsize := displ; | |
| while lsp3 <> nil do | |
| begin lsp4 := lsp3^.subvar; lsp3^.subvar := lsp2; | |
| lsp3^.size := displ; | |
| lsp3 := lsp4 | |
| end; | |
| if sy = rparent then | |
| begin insymbol; | |
| if not (sy in fsys + [semicolon]) then | |
| begin error(6); skip(fsys + [semicolon]) end | |
| end | |
| else error(4); | |
| end; | |
| test := sy <> semicolon; | |
| if not test then | |
| begin displ := minsize; | |
| insymbol | |
| end | |
| until test; | |
| displ := maxsize; | |
| lsp^.fstvar := lsp1; | |
| end | |
| else frecvar := nil | |
| end (*fieldlist*) ; | |
| begin (*typ*) | |
| if not (sy in typebegsys) then | |
| begin error(10); skip(fsys + typebegsys) end; | |
| if sy in typebegsys then | |
| begin | |
| if sy in simptypebegsys then simpletype(fsys,fsp,fsize) | |
| else | |
| (*^*) if sy = arrow then | |
| begin new(lsp,pointer); fsp := lsp; | |
| with lsp^ do | |
| begin eltype := nil; size := ptrsize; form:=pointer end; | |
| insymbol; | |
| if sy = ident then | |
| begin prterr := false; (*no error if search not successful*) | |
| searchid([types],lcp); prterr := true; | |
| if lcp = nil then (*forward referenced type id*) | |
| begin new(lcp,types); | |
| with lcp^ do | |
| begin name := id; idtype := lsp; | |
| next := fwptr; klass := types | |
| end; | |
| fwptr := lcp | |
| end | |
| else | |
| begin | |
| if lcp^.idtype <> nil then | |
| if lcp^.idtype^.form = files then error(108) | |
| else lsp^.eltype := lcp^.idtype | |
| end; | |
| insymbol; | |
| end | |
| else error(2); | |
| end | |
| else | |
| begin | |
| if sy = packedsy then | |
| begin insymbol; | |
| if not (sy in typedels) then | |
| begin | |
| error(10); skip(fsys + typedels) | |
| end | |
| end; | |
| (*array*) if sy = arraysy then | |
| begin insymbol; | |
| if sy = lbrack then insymbol else error(11); | |
| lsp1 := nil; | |
| repeat new(lsp,arrays); | |
| with lsp^ do | |
| begin aeltype := lsp1; inxtype := nil; form:=arrays end; | |
| lsp1 := lsp; | |
| simpletype(fsys + [comma,rbrack,ofsy],lsp2,lsize); | |
| lsp1^.size := lsize; | |
| if lsp2 <> nil then | |
| if lsp2^.form <= subrange then | |
| begin | |
| if lsp2 = realptr then | |
| begin error(109); lsp2 := nil end | |
| else | |
| if lsp2 = intptr then | |
| begin error(149); lsp2 := nil end; | |
| lsp^.inxtype := lsp2 | |
| end | |
| else begin error(113); lsp2 := nil end; | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = rbrack then insymbol else error(12); | |
| if sy = ofsy then insymbol else error(8); | |
| typ(fsys,lsp,lsize); | |
| repeat | |
| with lsp1^ do | |
| begin lsp2 := aeltype; aeltype := lsp; | |
| if inxtype <> nil then | |
| begin getbounds(inxtype,lmin,lmax); | |
| align(lsp,lsize); | |
| lsize := lsize*(lmax – lmin + 1); | |
| size := lsize | |
| end | |
| end; | |
| lsp := lsp1; lsp1 := lsp2 | |
| until lsp1 = nil | |
| end | |
| else | |
| (*record*) if sy = recordsy then | |
| begin insymbol; | |
| oldtop := top; | |
| if top < displimit then | |
| begin top := top + 1; | |
| with display[top] do | |
| begin fname := nil; | |
| flabel := nil; | |
| occur := rec | |
| end | |
| end | |
| else error(250); | |
| displ := 0; | |
| fieldlist(fsys-[semicolon]+[endsy],lsp1); | |
| new(lsp,records); | |
| with lsp^ do | |
| begin fstfld := display[top].fname; | |
| recvar := lsp1; size := displ; form := records | |
| end; | |
| top := oldtop; | |
| if sy = endsy then insymbol else error(13) | |
| end | |
| else | |
| (*set*) if sy = setsy then | |
| begin insymbol; | |
| if sy = ofsy then insymbol else error(8); | |
| simpletype(fsys,lsp1,lsize); | |
| if lsp1 <> nil then | |
| if lsp1^.form > subrange then | |
| begin error(115); lsp1 := nil end | |
| else | |
| if lsp1 = realptr then | |
| begin error(114); lsp1 := nil end | |
| else if lsp1 = intptr then | |
| begin error(169); lsp1 := nil end | |
| else | |
| begin getbounds(lsp1,lmin,lmax); | |
| if (lmin < setlow) or (lmax > sethigh) | |
| then error(169); | |
| end; | |
| new(lsp,power); | |
| with lsp^ do | |
| begin elset:=lsp1; size:=setsize; form:=power end; | |
| end | |
| else | |
| (*file*) if sy = filesy then | |
| begin insymbol; | |
| error(399); skip(fsys); lsp := nil | |
| end; | |
| fsp := lsp | |
| end; | |
| if not (sy in fsys) then | |
| begin error(6); skip(fsys) end | |
| end | |
| else fsp := nil; | |
| if fsp = nil then fsize := 1 else fsize := fsp^.size | |
| end (*typ*) ; | |
| procedure labeldeclaration; | |
| var llp: lbp; redef: boolean; lbname: integer; | |
| begin | |
| repeat | |
| if sy = intconst then | |
| with display[top] do | |
| begin llp := flabel; redef := false; | |
| while (llp <> nil) and not redef do | |
| if llp^.labval <> val.ival then | |
| llp := llp^.nextlab | |
| else begin redef := true; error(166) end; | |
| if not redef then | |
| begin new(llp); | |
| with llp^ do | |
| begin labval := val.ival; genlabel(lbname); | |
| defined := false; nextlab := flabel; labname := lbname | |
| end; | |
| flabel := llp | |
| end; | |
| insymbol | |
| end | |
| else error(15); | |
| if not ( sy in fsys + [comma, semicolon] ) then | |
| begin error(6); skip(fsys+[comma,semicolon]) end; | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = semicolon then insymbol else error(14) | |
| end (* labeldeclaration *) ; | |
| procedure constdeclaration; | |
| var lcp: ctp; lsp: stp; lvalu: valu; | |
| begin | |
| if sy <> ident then | |
| begin error(2); skip(fsys + [ident]) end; | |
| while sy = ident do | |
| begin new(lcp,konst); | |
| with lcp^ do | |
| begin name := id; idtype := nil; next := nil; klass:=konst end; | |
| insymbol; | |
| if (sy = relop) and (op = eqop) then insymbol else error(16); | |
| constant(fsys + [semicolon],lsp,lvalu); | |
| enterid(lcp); | |
| lcp^.idtype := lsp; lcp^.values := lvalu; | |
| if sy = semicolon then | |
| begin insymbol; | |
| if not (sy in fsys + [ident]) then | |
| begin error(6); skip(fsys + [ident]) end | |
| end | |
| else error(14) | |
| end | |
| end (*constdeclaration*) ; | |
| procedure typedeclaration; | |
| var lcp,lcp1,lcp2: ctp; lsp: stp; lsize: addrrange; | |
| begin | |
| if sy <> ident then | |
| begin error(2); skip(fsys + [ident]) end; | |
| while sy = ident do | |
| begin new(lcp,types); | |
| with lcp^ do | |
| begin name := id; idtype := nil; klass := types end; | |
| insymbol; | |
| if (sy = relop) and (op = eqop) then insymbol else error(16); | |
| typ(fsys + [semicolon],lsp,lsize); | |
| enterid(lcp); | |
| lcp^.idtype := lsp; | |
| (*has any forward reference been satisfied:*) | |
| lcp1 := fwptr; | |
| while lcp1 <> nil do | |
| begin | |
| if lcp1^.name = lcp^.name then | |
| begin lcp1^.idtype^.eltype := lcp^.idtype; | |
| if lcp1 <> fwptr then | |
| lcp2^.next := lcp1^.next | |
| else fwptr := lcp1^.next; | |
| end | |
| else lcp2 := lcp1; | |
| lcp1 := lcp1^.next | |
| end; | |
| if sy = semicolon then | |
| begin insymbol; | |
| if not (sy in fsys + [ident]) then | |
| begin error(6); skip(fsys + [ident]) end | |
| end | |
| else error(14) | |
| end; | |
| if fwptr <> nil then | |
| begin error(117); writeln(output); | |
| repeat writeln(output,' type-id ',fwptr^.name); | |
| fwptr := fwptr^.next | |
| until fwptr = nil; | |
| if not eol then write(output,' ': chcnt+16) | |
| end | |
| end (*typedeclaration*) ; | |
| procedure vardeclaration; | |
| var lcp,nxt: ctp; lsp: stp; lsize: addrrange; | |
| begin nxt := nil; | |
| repeat | |
| repeat | |
| if sy = ident then | |
| begin new(lcp,vars); | |
| with lcp^ do | |
| begin name := id; next := nxt; klass := vars; | |
| idtype := nil; vkind := actual; vlev := level | |
| end; | |
| enterid(lcp); | |
| nxt := lcp; | |
| insymbol; | |
| end | |
| else error(2); | |
| if not (sy in fsys + [comma,colon] + typedels) then | |
| begin error(6); skip(fsys+[comma,colon,semicolon]+typedels) end; | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = colon then insymbol else error(5); | |
| typ(fsys + [semicolon] + typedels,lsp,lsize); | |
| while nxt <> nil do | |
| with nxt^ do | |
| begin align(lsp,lc); | |
| idtype := lsp; vaddr := lc; | |
| lc := lc + lsize; nxt := next | |
| end; | |
| if sy = semicolon then | |
| begin insymbol; | |
| if not (sy in fsys + [ident]) then | |
| begin error(6); skip(fsys + [ident]) end | |
| end | |
| else error(14) | |
| until (sy <> ident) and not (sy in typedels); | |
| if fwptr <> nil then | |
| begin error(117); writeln(output); | |
| repeat writeln(output,' type-id ',fwptr^.name); | |
| fwptr := fwptr^.next | |
| until fwptr = nil; | |
| if not eol then write(output,' ': chcnt+16) | |
| end | |
| end (*vardeclaration*) ; | |
| procedure procdeclaration(fsy: symbol); | |
| var oldlev: 0..maxlevel; lcp,lcp1: ctp; lsp: stp; | |
| forw: boolean; oldtop: disprange; | |
| llc,lcm: addrrange; lbname: integer; markp: marktype; | |
| procedure parameterlist(fsy: setofsys; var fpar: ctp); | |
| var lcp,lcp1,lcp2,lcp3: ctp; lsp: stp; lkind: idkind; | |
| llc,lsize: addrrange; count: integer; | |
| begin lcp1 := nil; | |
| if not (sy in fsy + [lparent]) then | |
| begin error(7); skip(fsys + fsy + [lparent]) end; | |
| if sy = lparent then | |
| begin if forw then error(119); | |
| insymbol; | |
| if not (sy in [ident,varsy,procsy,funcsy]) then | |
| begin error(7); skip(fsys + [ident,rparent]) end; | |
| while sy in [ident,varsy,procsy,funcsy] do | |
| begin | |
| if sy = procsy then | |
| begin error(399); | |
| repeat insymbol; | |
| if sy = ident then | |
| begin new(lcp,proc,declared,formal); | |
| with lcp^ do | |
| begin name := id; idtype := nil; next := lcp1; | |
| pflev := level (*beware of parameter procedures*); | |
| klass:=proc;pfdeckind:=declared;pfkind:=formal | |
| end; | |
| enterid(lcp); | |
| lcp1 := lcp; | |
| align(parmptr,lc); | |
| (*lc := lc + some size *) | |
| insymbol | |
| end | |
| else error(2); | |
| if not (sy in fsys + [comma,semicolon,rparent]) then | |
| begin error(7);skip(fsys+[comma,semicolon,rparent])end | |
| until sy <> comma | |
| end | |
| else | |
| begin | |
| if sy = funcsy then | |
| begin error(399); lcp2 := nil; | |
| repeat insymbol; | |
| if sy = ident then | |
| begin new(lcp,func,declared,formal); | |
| with lcp^ do | |
| begin name := id; idtype := nil; next := lcp2; | |
| pflev := level (*beware param funcs*); | |
| klass:=func;pfdeckind:=declared; | |
| pfkind:=formal | |
| end; | |
| enterid(lcp); | |
| lcp2 := lcp; | |
| align(parmptr,lc); | |
| (*lc := lc + some size*) | |
| insymbol; | |
| end; | |
| if not (sy in [comma,colon] + fsys) then | |
| begin error(7);skip(fsys+[comma,semicolon,rparent]) | |
| end | |
| until sy <> comma; | |
| if sy = colon then | |
| begin insymbol; | |
| if sy = ident then | |
| begin searchid([types],lcp); | |
| lsp := lcp^.idtype; | |
| if lsp <> nil then | |
| if not(lsp^.form in[scalar,subrange,pointer]) | |
| then begin error(120); lsp := nil end; | |
| lcp3 := lcp2; | |
| while lcp2 <> nil do | |
| begin lcp2^.idtype := lsp; lcp := lcp2; | |
| lcp2 := lcp2^.next | |
| end; | |
| lcp^.next := lcp1; lcp1 := lcp3; | |
| insymbol | |
| end | |
| else error(2); | |
| if not (sy in fsys + [semicolon,rparent]) then | |
| begin error(7);skip(fsys+[semicolon,rparent])end | |
| end | |
| else error(5) | |
| end | |
| else | |
| begin | |
| if sy = varsy then | |
| begin lkind := formal; insymbol end | |
| else lkind := actual; | |
| lcp2 := nil; | |
| count := 0; | |
| repeat | |
| if sy = ident then | |
| begin new(lcp,vars); | |
| with lcp^ do | |
| begin name:=id; idtype:=nil; klass:=vars; | |
| vkind := lkind; next := lcp2; vlev := level; | |
| end; | |
| enterid(lcp); | |
| lcp2 := lcp; count := count+1; | |
| insymbol; | |
| end; | |
| if not (sy in [comma,colon] + fsys) then | |
| begin error(7);skip(fsys+[comma,semicolon,rparent]) | |
| end; | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = colon then | |
| begin insymbol; | |
| if sy = ident then | |
| begin searchid([types],lcp); | |
| lsp := lcp^.idtype; | |
| lsize := ptrsize; | |
| if lsp <> nil then | |
| if lkind=actual then | |
| if lsp^.form<=power then lsize := lsp^.size | |
| else if lsp^.form=files then error(121); | |
| align(parmptr,lsize); | |
| lcp3 := lcp2; | |
| align(parmptr,lc); | |
| lc := lc+count*lsize; | |
| llc := lc; | |
| while lcp2 <> nil do | |
| begin lcp := lcp2; | |
| with lcp2^ do | |
| begin idtype := lsp; | |
| llc := llc-lsize; | |
| vaddr := llc; | |
| end; | |
| lcp2 := lcp2^.next | |
| end; | |
| lcp^.next := lcp1; lcp1 := lcp3; | |
| insymbol | |
| end | |
| else error(2); | |
| if not (sy in fsys + [semicolon,rparent]) then | |
| begin error(7);skip(fsys+[semicolon,rparent])end | |
| end | |
| else error(5); | |
| end; | |
| end; | |
| if sy = semicolon then | |
| begin insymbol; | |
| if not (sy in fsys + [ident,varsy,procsy,funcsy]) then | |
| begin error(7); skip(fsys + [ident,rparent]) end | |
| end | |
| end (*while*) ; | |
| if sy = rparent then | |
| begin insymbol; | |
| if not (sy in fsy + fsys) then | |
| begin error(6); skip(fsy + fsys) end | |
| end | |
| else error(4); | |
| lcp3 := nil; | |
| (*reverse pointers and reserve local cells for copies of multiple | |
| values*) | |
| while lcp1 <> nil do | |
| with lcp1^ do | |
| begin lcp2 := next; next := lcp3; | |
| if klass = vars then | |
| if idtype <> nil then | |
| if (vkind=actual)and(idtype^.form>power) then | |
| begin align(idtype,lc); | |
| vaddr := lc; | |
| lc := lc+idtype^.size; | |
| end; | |
| lcp3 := lcp1; lcp1 := lcp2 | |
| end; | |
| fpar := lcp3 | |
| end | |
| else fpar := nil | |
| end (*parameterlist*) ; | |
| begin (*procdeclaration*) | |
| llc := lc; lc := lcaftermarkstack; forw := false; | |
| if sy = ident then | |
| begin searchsection(display[top].fname,lcp); (*decide whether forw.*) | |
| if lcp <> nil then | |
| begin | |
| if lcp^.klass = proc then | |
| forw := lcp^.forwdecl and(fsy=procsy)and(lcp^.pfkind=actual) | |
| else | |
| if lcp^.klass = func then | |
| forw:=lcp^.forwdecl and(fsy=funcsy)and(lcp^.pfkind=actual) | |
| else forw := false; | |
| if not forw then error(160) | |
| end; | |
| if not forw then | |
| begin | |
| if fsy = procsy then new(lcp,proc,declared,actual) | |
| else new(lcp,func,declared,actual); | |
| with lcp^ do | |
| begin name := id; idtype := nil; | |
| externl := false; pflev := level; genlabel(lbname); | |
| pfdeckind := declared; pfkind := actual; pfname := lbname; | |
| if fsy = procsy then klass := proc | |
| else klass := func | |
| end; | |
| enterid(lcp) | |
| end | |
| else | |
| begin lcp1 := lcp^.next; | |
| while lcp1 <> nil do | |
| begin | |
| with lcp1^ do | |
| if klass = vars then | |
| if idtype <> nil then | |
| begin lcm := vaddr + idtype^.size; | |
| if lcm > lc then lc := lcm | |
| end; | |
| lcp1 := lcp1^.next | |
| end | |
| end; | |
| insymbol | |
| end | |
| else | |
| begin error(2); lcp := ufctptr end; | |
| oldlev := level; oldtop := top; | |
| if level < maxlevel then level := level + 1 else error(251); | |
| if top < displimit then | |
| begin top := top + 1; | |
| with display[top] do | |
| begin | |
| if forw then fname := lcp^.next | |
| else fname := nil; | |
| flabel := nil; | |
| occur := blck | |
| end | |
| end | |
| else error(250); | |
| if fsy = procsy then | |
| begin parameterlist([semicolon],lcp1); | |
| if not forw then lcp^.next := lcp1 | |
| end | |
| else | |
| begin parameterlist([semicolon,colon],lcp1); | |
| if not forw then lcp^.next := lcp1; | |
| if sy = colon then | |
| begin insymbol; | |
| if sy = ident then | |
| begin if forw then error(122); | |
| searchid([types],lcp1); | |
| lsp := lcp1^.idtype; | |
| lcp^.idtype := lsp; | |
| if lsp <> nil then | |
| if not (lsp^.form in [scalar,subrange,pointer]) then | |
| begin error(120); lcp^.idtype := nil end; | |
| insymbol | |
| end | |
| else begin error(2); skip(fsys + [semicolon]) end | |
| end | |
| else | |
| if not forw then error(123) | |
| end; | |
| if sy = semicolon then insymbol else error(14); | |
| if sy = forwardsy then | |
| begin | |
| if forw then error(161) | |
| else lcp^.forwdecl := true; | |
| insymbol; | |
| if sy = semicolon then insymbol else error(14); | |
| if not (sy in fsys) then | |
| begin error(6); skip(fsys) end | |
| end | |
| else | |
| begin lcp^.forwdecl := false; mark(markp); | |
| repeat block(fsys,semicolon,lcp); | |
| if sy = semicolon then | |
| begin if prtables then printtables(false); insymbol; | |
| if not (sy in [beginsy,procsy,funcsy]) then | |
| begin error(6); skip(fsys) end | |
| end | |
| else error(14) | |
| until (sy in [beginsy,procsy,funcsy]) or eof(input); | |
| release(markp); (* return local entries on runtime heap *) | |
| end; | |
| level := oldlev; top := oldtop; lc := llc; | |
| end (*procdeclaration*) ; | |
| procedure body(fsys: setofsys); | |
| const cstoccmax=65; cixmax=1000; | |
| type oprange = 0..63; | |
| var | |
| llcp:ctp; saveid:alpha; | |
| cstptr: array [1..cstoccmax] of csp; | |
| cstptrix: 0..cstoccmax; | |
| (*allows referencing of noninteger constants by an index | |
| (instead of a pointer), which can be stored in the p2-field | |
| of the instruction record until writeout. | |
| –> procedure load, procedure writeout*) | |
| entname, segsize: integer; | |
| stacktop, topnew, topmax: integer; | |
| lcmax,llc1: addrrange; lcp: ctp; | |
| llp: lbp; | |
| procedure mes(i: integer); | |
| begin topnew := topnew + cdx[i]*maxstack; | |
| if topnew > topmax then topmax := topnew | |
| end; | |
| procedure putic; | |
| begin if ic mod 10 = 0 then writeln(prr,'i',ic:5) end; | |
| procedure gen0(fop: oprange); | |
| begin | |
| if prcode then begin putic; writeln(prr,mn[fop]:4) end; | |
| ic := ic + 1; mes(fop) | |
| end (*gen0*) ; | |
| procedure gen1(fop: oprange; fp2: integer); | |
| var k: integer; | |
| begin | |
| if prcode then | |
| begin putic; write(prr,mn[fop]:4); | |
| if fop = 30 then | |
| begin writeln(prr,sna[fp2]:12); | |
| topnew := topnew + pdx[fp2]*maxstack; | |
| if topnew > topmax then topmax := topnew | |
| end | |
| else | |
| begin | |
| if fop = 38 then | |
| begin write(prr,''''); | |
| with cstptr[fp2]^ do | |
| begin | |
| for k := 1 to slgth do write(prr,sval[k]:1); | |
| for k := slgth+1 to strglgth do write(prr,' '); | |
| end; | |
| writeln(prr,'''') | |
| end | |
| else if fop = 42 then writeln(prr,chr(fp2)) | |
| else writeln(prr,fp2:12); | |
| mes(fop) | |
| end | |
| end; | |
| ic := ic + 1 | |
| end (*gen1*) ; | |
| procedure gen2(fop: oprange; fp1,fp2: integer); | |
| var k : integer; | |
| begin | |
| if prcode then | |
| begin putic; write(prr,mn[fop]:4); | |
| case fop of | |
| 45,50,54,56: | |
| writeln(prr,' ',fp1:3,fp2:8); | |
| 47,48,49,52,53,55: | |
| begin write(prr,chr(fp1)); | |
| if chr(fp1) = 'm' then write(prr,fp2:11); | |
| writeln(prr) | |
| end; | |
| 51: | |
| case fp1 of | |
| 1: writeln(prr,'i ',fp2); | |
| 2: begin write(prr,'r '); | |
| with cstptr[fp2]^ do | |
| for k := 1 to strglgth do write(prr,rval[k]); | |
| writeln(prr) | |
| end; | |
| 3: writeln(prr,'b ',fp2); | |
| 4: writeln(prr,'n'); | |
| 6: writeln(prr,'c ''':3,chr(fp2),''''); | |
| 5: begin write(prr,'('); | |
| with cstptr[fp2]^ do | |
| for k := setlow to sethigh do | |
| if k in pval then write(prr,k:3); | |
| writeln(prr,')') | |
| end | |
| end | |
| end; | |
| end; | |
| ic := ic + 1; mes(fop) | |
| end (*gen2*) ; | |
| procedure gentypindicator(fsp: stp); | |
| begin | |
| if fsp<>nil then | |
| with fsp^ do | |
| case form of | |
| scalar: if fsp=intptr then write(prr,'i') | |
| else | |
| if fsp=boolptr then write(prr,'b') | |
| else | |
| if fsp=charptr then write(prr,'c') | |
| else | |
| if scalkind = declared then write(prr,'i') | |
| else write(prr,'r'); | |
| subrange: gentypindicator(rangetype); | |
| pointer: write(prr,'a'); | |
| power: write(prr,'s'); | |
| records,arrays: write(prr,'m'); | |
| files,tagfld,variant: error(500) | |
| end | |
| end (*typindicator*); | |
| procedure gen0t(fop: oprange; fsp: stp); | |
| begin | |
| if prcode then | |
| begin putic; | |
| write(prr,mn[fop]:4); | |
| gentypindicator(fsp); | |
| writeln(prr); | |
| end; | |
| ic := ic + 1; mes(fop) | |
| end (*gen0t*); | |
| procedure gen1t(fop: oprange; fp2: integer; fsp: stp); | |
| begin | |
| if prcode then | |
| begin putic; | |
| write(prr,mn[fop]:4); | |
| gentypindicator(fsp); | |
| writeln(prr,fp2:11) | |
| end; | |
| ic := ic + 1; mes(fop) | |
| end (*gen1t*); | |
| procedure gen2t(fop: oprange; fp1,fp2: integer; fsp: stp); | |
| begin | |
| if prcode then | |
| begin putic; | |
| write(prr,mn[fop]: 4); | |
| gentypindicator(fsp); | |
| writeln(prr,fp1:3+5*ord(abs(fp1)>99),fp2:8); | |
| end; | |
| ic := ic + 1; mes(fop) | |
| end (*gen2t*); | |
| procedure load; | |
| begin | |
| with gattr do | |
| if typtr <> nil then | |
| begin | |
| case kind of | |
| cst: if (typtr^.form = scalar) and (typtr <> realptr) then | |
| if typtr = boolptr then gen2(51(*ldc*),3,cval.ival) | |
| else | |
| if typtr=charptr then | |
| gen2(51(*ldc*),6,cval.ival) | |
| else gen2(51(*ldc*),1,cval.ival) | |
| else | |
| if typtr = nilptr then gen2(51(*ldc*),4,0) | |
| else | |
| if cstptrix >= cstoccmax then error(254) | |
| else | |
| begin cstptrix := cstptrix + 1; | |
| cstptr[cstptrix] := cval.valp; | |
| if typtr = realptr then | |
| gen2(51(*ldc*),2,cstptrix) | |
| else | |
| gen2(51(*ldc*),5,cstptrix) | |
| end; | |
| varbl: case access of | |
| drct: if vlevel<=1 then | |
| gen1t(39(*ldo*),dplmt,typtr) | |
| else gen2t(54(*lod*),level-vlevel,dplmt,typtr); | |
| indrct: gen1t(35(*ind*),idplmt,typtr); | |
| inxd: error(400) | |
| end; | |
| expr: | |
| end; | |
| kind := expr | |
| end | |
| end (*load*) ; | |
| procedure store(var fattr: attr); | |
| begin | |
| with fattr do | |
| if typtr <> nil then | |
| case access of | |
| drct: if vlevel <= 1 then gen1t(43(*sro*),dplmt,typtr) | |
| else gen2t(56(*str*),level-vlevel,dplmt,typtr); | |
| indrct: if idplmt <> 0 then error(400) | |
| else gen0t(26(*sto*),typtr); | |
| inxd: error(400) | |
| end | |
| end (*store*) ; | |
| procedure loadaddress; | |
| begin | |
| with gattr do | |
| if typtr <> nil then | |
| begin | |
| case kind of | |
| cst: if string(typtr) then | |
| if cstptrix >= cstoccmax then error(254) | |
| else | |
| begin cstptrix := cstptrix + 1; | |
| cstptr[cstptrix] := cval.valp; | |
| gen1(38(*lca*),cstptrix) | |
| end | |
| else error(400); | |
| varbl: case access of | |
| drct: if vlevel <= 1 then gen1(37(*lao*),dplmt) | |
| else gen2(50(*lda*),level-vlevel,dplmt); | |
| indrct: if idplmt <> 0 then | |
| gen1t(34(*inc*),idplmt,nilptr); | |
| inxd: error(400) | |
| end; | |
| expr: error(400) | |
| end; | |
| kind := varbl; access := indrct; idplmt := 0 | |
| end | |
| end (*loadaddress*) ; | |
| procedure genfjp(faddr: integer); | |
| begin load; | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> boolptr then error(144); | |
| if prcode then begin putic; writeln(prr,mn[33]:4,' l':8,faddr:4) end; | |
| ic := ic + 1; mes(33) | |
| end (*genfjp*) ; | |
| procedure genujpxjp(fop: oprange; fp2: integer); | |
| begin | |
| if prcode then | |
| begin putic; writeln(prr, mn[fop]:4, ' l':8,fp2:4) end; | |
| ic := ic + 1; mes(fop) | |
| end (*genujpxjp*); | |
| procedure gencupent(fop: oprange; fp1,fp2: integer); | |
| begin | |
| if prcode then | |
| begin putic; | |
| writeln(prr,mn[fop]:4,fp1:4,'l':4,fp2:4) | |
| end; | |
| ic := ic + 1; mes(fop) | |
| end; | |
| procedure checkbnds(fsp: stp); | |
| var lmin,lmax: integer; | |
| begin | |
| if fsp <> nil then | |
| if fsp <> intptr then | |
| if fsp <> realptr then | |
| if fsp^.form <= subrange then | |
| begin | |
| getbounds(fsp,lmin,lmax); | |
| gen2t(45(*chk*),lmin,lmax,fsp) | |
| end | |
| end (*checkbnds*); | |
| procedure putlabel(labname: integer); | |
| begin if prcode then writeln(prr, 'l', labname:4) | |
| end (*putlabel*); | |
| procedure statement(fsys: setofsys); | |
| label 1; | |
| var lcp: ctp; llp: lbp; | |
| procedure expression(fsys: setofsys); forward; | |
| procedure selector(fsys: setofsys; fcp: ctp); | |
| var lattr: attr; lcp: ctp; lsize: addrrange; lmin,lmax: integer; | |
| begin | |
| with fcp^, gattr do | |
| begin typtr := idtype; kind := varbl; | |
| case klass of | |
| vars: | |
| if vkind = actual then | |
| begin access := drct; vlevel := vlev; | |
| dplmt := vaddr | |
| end | |
| else | |
| begin gen2t(54(*lod*),level-vlev,vaddr,nilptr); | |
| access := indrct; idplmt := 0 | |
| end; | |
| field: | |
| with display[disx] do | |
| if occur = crec then | |
| begin access := drct; vlevel := clev; | |
| dplmt := cdspl + fldaddr | |
| end | |
| else | |
| begin | |
| if level = 1 then gen1t(39(*ldo*),vdspl,nilptr) | |
| else gen2t(54(*lod*),0,vdspl,nilptr); | |
| access := indrct; idplmt := fldaddr | |
| end; | |
| func: | |
| if pfdeckind = standard then | |
| begin error(150); typtr := nil end | |
| else | |
| begin | |
| if pfkind = formal then error(151) | |
| else | |
| if (pflev+1<>level)or(fprocp<>fcp) then error(177); | |
| begin access := drct; vlevel := pflev + 1; | |
| dplmt := 0 (*impl. relat. addr. of fct. result*) | |
| end | |
| end | |
| end (*case*) | |
| end (*with*); | |
| if not (sy in selectsys + fsys) then | |
| begin error(59); skip(selectsys + fsys) end; | |
| while sy in selectsys do | |
| begin | |
| (*[*) if sy = lbrack then | |
| begin | |
| repeat lattr := gattr; | |
| with lattr do | |
| if typtr <> nil then | |
| if typtr^.form <> arrays then | |
| begin error(138); typtr := nil end; | |
| loadaddress; | |
| insymbol; expression(fsys + [comma,rbrack]); | |
| load; | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form<>scalar then error(113) | |
| else if not comptypes(gattr.typtr,intptr) then | |
| gen0t(58(*ord*),gattr.typtr); | |
| if lattr.typtr <> nil then | |
| with lattr.typtr^ do | |
| begin | |
| if comptypes(inxtype,gattr.typtr) then | |
| begin | |
| if inxtype <> nil then | |
| begin getbounds(inxtype,lmin,lmax); | |
| if debug then | |
| gen2t(45(*chk*),lmin,lmax,intptr); | |
| if lmin>0 then gen1t(31(*dec*),lmin,intptr) | |
| else if lmin<0 then | |
| gen1t(34(*inc*),-lmin,intptr); | |
| (*or simply gen1(31,lmin)*) | |
| end | |
| end | |
| else error(139); | |
| with gattr do | |
| begin typtr := aeltype; kind := varbl; | |
| access := indrct; idplmt := 0 | |
| end; | |
| if gattr.typtr <> nil then | |
| begin | |
| lsize := gattr.typtr^.size; | |
| align(gattr.typtr,lsize); | |
| gen1(36(*ixa*),lsize) | |
| end | |
| end | |
| until sy <> comma; | |
| if sy = rbrack then insymbol else error(12) | |
| end (*if sy = lbrack*) | |
| else | |
| (*.*) if sy = period then | |
| begin | |
| with gattr do | |
| begin | |
| if typtr <> nil then | |
| if typtr^.form <> records then | |
| begin error(140); typtr := nil end; | |
| insymbol; | |
| if sy = ident then | |
| begin | |
| if typtr <> nil then | |
| begin searchsection(typtr^.fstfld,lcp); | |
| if lcp = nil then | |
| begin error(152); typtr := nil end | |
| else | |
| with lcp^ do | |
| begin typtr := idtype; | |
| case access of | |
| drct: dplmt := dplmt + fldaddr; | |
| indrct: idplmt := idplmt + fldaddr; | |
| inxd: error(400) | |
| end | |
| end | |
| end; | |
| insymbol | |
| end (*sy = ident*) | |
| else error(2) | |
| end (*with gattr*) | |
| end (*if sy = period*) | |
| else | |
| (*^*) begin | |
| if gattr.typtr <> nil then | |
| with gattr,typtr^ do | |
| if form = pointer then | |
| begin load; typtr := eltype; | |
| if debug then gen2t(45(*chk*),1,maxaddr,nilptr); | |
| with gattr do | |
| begin kind := varbl; access := indrct; | |
| idplmt := 0 | |
| end | |
| end | |
| else | |
| if form = files then typtr := filtype | |
| else error(141); | |
| insymbol | |
| end; | |
| if not (sy in fsys + selectsys) then | |
| begin error(6); skip(fsys + selectsys) end | |
| end (*while*) | |
| end (*selector*) ; | |
| procedure call(fsys: setofsys; fcp: ctp); | |
| var lkey: 1..15; | |
| procedure variable(fsys: setofsys); | |
| var lcp: ctp; | |
| begin | |
| if sy = ident then | |
| begin searchid([vars,field],lcp); insymbol end | |
| else begin error(2); lcp := uvarptr end; | |
| selector(fsys,lcp) | |
| end (*variable*) ; | |
| procedure getputresetrewrite; | |
| begin variable(fsys + [rparent]); loadaddress; | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> files then error(116); | |
| if lkey <= 2 then gen1(30(*csp*),lkey(*get,put*)) | |
| else error(399) | |
| end (*getputresetrewrite*) ; | |
| procedure read; | |
| var llev:levrange; laddr:addrrange; | |
| lsp : stp; | |
| begin | |
| llev := 1; laddr := lcaftermarkstack; | |
| if sy = lparent then | |
| begin insymbol; | |
| variable(fsys + [comma,rparent]); | |
| lsp := gattr.typtr; test := false; | |
| if lsp <> nil then | |
| if lsp^.form = files then | |
| with gattr, lsp^ do | |
| begin | |
| if filtype = charptr then | |
| begin llev := vlevel; laddr := dplmt end | |
| else error(399); | |
| if sy = rparent then | |
| begin if lkey = 5 then error(116); | |
| test := true | |
| end | |
| else | |
| if sy <> comma then | |
| begin error(116); skip(fsys + [comma,rparent]) end; | |
| if sy = comma then | |
| begin insymbol; variable(fsys + [comma,rparent]) | |
| end | |
| else test := true | |
| end; | |
| if not test then | |
| repeat loadaddress; | |
| gen2(50(*lda*),level-llev,laddr); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <= subrange then | |
| if comptypes(intptr,gattr.typtr) then | |
| gen1(30(*csp*),3(*rdi*)) | |
| else | |
| if comptypes(realptr,gattr.typtr) then | |
| gen1(30(*csp*),4(*rdr*)) | |
| else | |
| if comptypes(charptr,gattr.typtr) then | |
| gen1(30(*csp*),5(*rdc*)) | |
| else error(399) | |
| else error(116); | |
| test := sy <> comma; | |
| if not test then | |
| begin insymbol; variable(fsys + [comma,rparent]) | |
| end | |
| until test; | |
| if sy = rparent then insymbol else error(4) | |
| end | |
| else if lkey = 5 then error(116); | |
| if lkey = 11 then | |
| begin gen2(50(*lda*),level-llev,laddr); | |
| gen1(30(*csp*),21(*rln*)) | |
| end | |
| end (*read*) ; | |
| procedure write; | |
| var lsp: stp; default : boolean; llkey: 1..15; | |
| llev:levrange; laddr,len:addrrange; | |
| begin llkey := lkey; | |
| llev := 1; laddr := lcaftermarkstack + charmax; | |
| if sy = lparent then | |
| begin insymbol; | |
| expression(fsys + [comma,colon,rparent]); | |
| lsp := gattr.typtr; test := false; | |
| if lsp <> nil then | |
| if lsp^.form = files then | |
| with gattr, lsp^ do | |
| begin | |
| if filtype = charptr then | |
| begin llev := vlevel; laddr := dplmt end | |
| else error(399); | |
| if sy = rparent then | |
| begin if llkey = 6 then error(116); | |
| test := true | |
| end | |
| else | |
| if sy <> comma then | |
| begin error(116); skip(fsys+[comma,rparent]) end; | |
| if sy = comma then | |
| begin insymbol; expression(fsys+[comma,colon,rparent]) | |
| end | |
| else test := true | |
| end; | |
| if not test then | |
| repeat | |
| lsp := gattr.typtr; | |
| if lsp <> nil then | |
| if lsp^.form <= subrange then load else loadaddress; | |
| if sy = colon then | |
| begin insymbol; expression(fsys + [comma,colon,rparent]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> intptr then error(116); | |
| load; default := false | |
| end | |
| else default := true; | |
| if sy = colon then | |
| begin insymbol; expression(fsys + [comma,rparent]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> intptr then error(116); | |
| if lsp <> realptr then error(124); | |
| load; error(399); | |
| end | |
| else | |
| if lsp = intptr then | |
| begin if default then gen2(51(*ldc*),1,10); | |
| gen2(50(*lda*),level-llev,laddr); | |
| gen1(30(*csp*),6(*wri*)) | |
| end | |
| else | |
| if lsp = realptr then | |
| begin if default then gen2(51(*ldc*),1,20); | |
| gen2(50(*lda*),level-llev,laddr); | |
| gen1(30(*csp*),8(*wrr*)) | |
| end | |
| else | |
| if lsp = charptr then | |
| begin if default then gen2(51(*ldc*),1,1); | |
| gen2(50(*lda*),level-llev,laddr); | |
| gen1(30(*csp*),9(*wrc*)) | |
| end | |
| else | |
| if lsp <> nil then | |
| begin | |
| if lsp^.form = scalar then error(399) | |
| else | |
| if string(lsp) then | |
| begin len := lsp^.size div charmax; | |
| if default then | |
| gen2(51(*ldc*),1,len); | |
| gen2(51(*ldc*),1,len); | |
| gen2(50(*lda*),level-llev,laddr); | |
| gen1(30(*csp*),10(*wrs*)) | |
| end | |
| else error(116) | |
| end; | |
| test := sy <> comma; | |
| if not test then | |
| begin insymbol; expression(fsys + [comma,colon,rparent]) | |
| end | |
| until test; | |
| if sy = rparent then insymbol else error(4) | |
| end | |
| else if lkey = 6 then error(116); | |
| if llkey = 12 then (*writeln*) | |
| begin gen2(50(*lda*),level-llev,laddr); | |
| gen1(30(*csp*),22(*wln*)) | |
| end | |
| end (*write*) ; | |
| procedure pack; | |
| var lsp,lsp1: stp; | |
| begin error(399); variable(fsys + [comma,rparent]); | |
| lsp := nil; lsp1 := nil; | |
| if gattr.typtr <> nil then | |
| with gattr.typtr^ do | |
| if form = arrays then | |
| begin lsp := inxtype; lsp1 := aeltype end | |
| else error(116); | |
| if sy = comma then insymbol else error(20); | |
| expression(fsys + [comma,rparent]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> scalar then error(116) | |
| else | |
| if not comptypes(lsp,gattr.typtr) then error(116); | |
| if sy = comma then insymbol else error(20); | |
| variable(fsys + [rparent]); | |
| if gattr.typtr <> nil then | |
| with gattr.typtr^ do | |
| if form = arrays then | |
| begin | |
| if not comptypes(aeltype,lsp1) | |
| or not comptypes(inxtype,lsp) then | |
| error(116) | |
| end | |
| else error(116) | |
| end (*pack*) ; | |
| procedure unpack; | |
| var lsp,lsp1: stp; | |
| begin error(399); variable(fsys + [comma,rparent]); | |
| lsp := nil; lsp1 := nil; | |
| if gattr.typtr <> nil then | |
| with gattr.typtr^ do | |
| if form = arrays then | |
| begin lsp := inxtype; lsp1 := aeltype end | |
| else error(116); | |
| if sy = comma then insymbol else error(20); | |
| variable(fsys + [comma,rparent]); | |
| if gattr.typtr <> nil then | |
| with gattr.typtr^ do | |
| if form = arrays then | |
| begin | |
| if not comptypes(aeltype,lsp1) | |
| or not comptypes(inxtype,lsp) then | |
| error(116) | |
| end | |
| else error(116); | |
| if sy = comma then insymbol else error(20); | |
| expression(fsys + [rparent]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> scalar then error(116) | |
| else | |
| if not comptypes(lsp,gattr.typtr) then error(116); | |
| end (*unpack*) ; | |
| procedure new; | |
| label 1; | |
| var lsp,lsp1: stp; varts: integer; | |
| lsize: addrrange; lval: valu; | |
| begin variable(fsys + [comma,rparent]); loadaddress; | |
| lsp := nil; varts := 0; lsize := 0; | |
| if gattr.typtr <> nil then | |
| with gattr.typtr^ do | |
| if form = pointer then | |
| begin | |
| if eltype <> nil then | |
| begin lsize := eltype^.size; | |
| if eltype^.form = records then lsp := eltype^.recvar | |
| end | |
| end | |
| else error(116); | |
| while sy = comma do | |
| begin insymbol;constant(fsys + [comma,rparent],lsp1,lval); | |
| varts := varts + 1; | |
| (*check to insert here: is constant in tagfieldtype range*) | |
| if lsp = nil then error(158) | |
| else | |
| if lsp^.form <> tagfld then error(162) | |
| else | |
| if lsp^.tagfieldp <> nil then | |
| if string(lsp1) or (lsp1 = realptr) then error(159) | |
| else | |
| if comptypes(lsp^.tagfieldp^.idtype,lsp1) then | |
| begin | |
| lsp1 := lsp^.fstvar; | |
| while lsp1 <> nil do | |
| with lsp1^ do | |
| if varval.ival = lval.ival then | |
| begin lsize := size; lsp := subvar; | |
| goto 1 | |
| end | |
| else lsp1 := nxtvar; | |
| lsize := lsp^.size; lsp := nil; | |
| end | |
| else error(116); | |
| 1: end (*while*) ; | |
| gen2(51(*ldc*),1,lsize); | |
| gen1(30(*csp*),12(*new*)); | |
| end (*new*) ; | |
| procedure mark; | |
| begin variable(fsys+[rparent]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form = pointer then | |
| begin loadaddress; gen1(30(*csp*),23(*sav*)) end | |
| else error(116) | |
| end(*mark*); | |
| procedure release; | |
| begin variable(fsys+[rparent]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form = pointer then | |
| begin load; gen1(30(*csp*),13(*rst*)) end | |
| else error(116) | |
| end (*release*); | |
| procedure abs; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr = intptr then gen0(0(*abi*)) | |
| else | |
| if gattr.typtr = realptr then gen0(1(*abr*)) | |
| else begin error(125); gattr.typtr := intptr end | |
| end (*abs*) ; | |
| procedure sqr; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr = intptr then gen0(24(*sqi*)) | |
| else | |
| if gattr.typtr = realptr then gen0(25(*sqr*)) | |
| else begin error(125); gattr.typtr := intptr end | |
| end (*sqr*) ; | |
| procedure trunc; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> realptr then error(125); | |
| gen0(27(*trc*)); | |
| gattr.typtr := intptr | |
| end (*trunc*) ; | |
| procedure odd; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> intptr then error(125); | |
| gen0(20(*odd*)); | |
| gattr.typtr := boolptr | |
| end (*odd*) ; | |
| procedure ord; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form >= power then error(125); | |
| gen0t(58(*ord*),gattr.typtr); | |
| gattr.typtr := intptr | |
| end (*ord*) ; | |
| procedure chr; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> intptr then error(125); | |
| gen0(59(*chr*)); | |
| gattr.typtr := charptr | |
| end (*chr*) ; | |
| procedure predsucc; | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> scalar then error(125); | |
| if lkey = 7 then gen1t(31(*dec*),1,gattr.typtr) | |
| else gen1t(34(*inc*),1,gattr.typtr) | |
| end (*predsucc*) ; | |
| procedure eof; | |
| begin | |
| if sy = lparent then | |
| begin insymbol; variable(fsys + [rparent]); | |
| if sy = rparent then insymbol else error(4) | |
| end | |
| else | |
| with gattr do | |
| begin typtr := textptr; kind := varbl; access := drct; | |
| vlevel := 1; dplmt := lcaftermarkstack | |
| end; | |
| loadaddress; | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> files then error(125); | |
| if lkey = 9 then gen0(8(*eof*)) else gen1(30(*csp*),14(*eln*)); | |
| gattr.typtr := boolptr | |
| end (*eof*) ; | |
| procedure callnonstandard; | |
| var nxt,lcp: ctp; lsp: stp; lkind: idkind; lb: boolean; | |
| locpar, llc: addrrange; | |
| begin locpar := 0; | |
| with fcp^ do | |
| begin nxt := next; lkind := pfkind; | |
| if not externl then gen1(41(*mst*),level-pflev) | |
| end; | |
| if sy = lparent then | |
| begin llc := lc; | |
| repeat lb := false; (*decide whether proc/func must be passed*) | |
| if lkind = actual then | |
| begin | |
| if nxt = nil then error(126) | |
| else lb := nxt^.klass in [proc,func] | |
| end else error(399); | |
| (*For formal proc/func, lb is false and expression | |
| will be called, which will always interpret a proc/func id | |
| at its beginning as a call rather than a parameter passing. | |
| In this implementation, parameter procedures/functions | |
| are therefore not allowed to have procedure/function | |
| parameters*) | |
| insymbol; | |
| if lb then (*pass function or procedure*) | |
| begin error(399); | |
| if sy <> ident then | |
| begin error(2); skip(fsys + [comma,rparent]) end | |
| else | |
| begin | |
| if nxt^.klass = proc then searchid([proc],lcp) | |
| else | |
| begin searchid([func],lcp); | |
| if not comptypes(lcp^.idtype,nxt^.idtype) then | |
| error(128) | |
| end; | |
| insymbol; | |
| if not (sy in fsys + [comma,rparent]) then | |
| begin error(6); skip(fsys + [comma,rparent]) end | |
| end | |
| end (*if lb*) | |
| else | |
| begin expression(fsys + [comma,rparent]); | |
| if gattr.typtr <> nil then | |
| if lkind = actual then | |
| begin | |
| if nxt <> nil then | |
| begin lsp := nxt^.idtype; | |
| if lsp <> nil then | |
| begin | |
| if (nxt^.vkind = actual) then | |
| if lsp^.form <= power then | |
| begin load; | |
| if debug then checkbnds(lsp); | |
| if comptypes(realptr,lsp) | |
| and (gattr.typtr = intptr) then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| locpar := locpar+lsp^.size; | |
| align(parmptr,locpar); | |
| end | |
| else | |
| begin | |
| loadaddress; | |
| locpar := locpar+ptrsize; | |
| align(parmptr,locpar) | |
| end | |
| else | |
| if gattr.kind = varbl then | |
| begin loadaddress; | |
| locpar := locpar+ptrsize; | |
| align(parmptr,locpar); | |
| end | |
| else error(154); | |
| if not comptypes(lsp,gattr.typtr) then | |
| error(142) | |
| end | |
| end | |
| end | |
| else (*lkind = formal*) | |
| begin (*pass formal param*) | |
| end | |
| end; | |
| if (lkind = actual) and (nxt <> nil) then nxt := nxt^.next | |
| until sy <> comma; | |
| lc := llc; | |
| if sy = rparent then insymbol else error(4) | |
| end (*if lparent*); | |
| if lkind = actual then | |
| begin if nxt <> nil then error(126); | |
| with fcp^ do | |
| begin | |
| if externl then gen1(30(*csp*),pfname) | |
| else gencupent(46(*cup*),locpar,pfname); | |
| end | |
| end; | |
| gattr.typtr := fcp^.idtype | |
| end (*callnonstandard*) ; | |
| begin (*call*) | |
| if fcp^.pfdeckind = standard then | |
| begin lkey := fcp^.key; | |
| if fcp^.klass = proc then | |
| begin | |
| if not(lkey in [5,6,11,12]) then | |
| if sy = lparent then insymbol else error(9); | |
| case lkey of | |
| 1,2, | |
| 3,4: getputresetrewrite; | |
| 5,11: read; | |
| 6,12: write; | |
| 7: pack; | |
| 8: unpack; | |
| 9: new; | |
| 10: release; | |
| 13: mark | |
| end; | |
| if not(lkey in [5,6,11,12]) then | |
| if sy = rparent then insymbol else error(4) | |
| end | |
| else | |
| begin | |
| if lkey <= 8 then | |
| begin | |
| if sy = lparent then insymbol else error(9); | |
| expression(fsys+[rparent]); load | |
| end; | |
| case lkey of | |
| 1: abs; | |
| 2: sqr; | |
| 3: trunc; | |
| 4: odd; | |
| 5: ord; | |
| 6: chr; | |
| 7,8: predsucc; | |
| 9,10: eof | |
| end; | |
| if lkey <= 8 then | |
| if sy = rparent then insymbol else error(4) | |
| end; | |
| end (*standard procedures and functions*) | |
| else callnonstandard | |
| end (*call*) ; | |
| procedure expression; | |
| var lattr: attr; lop: operator; typind: char; lsize: addrrange; | |
| procedure simpleexpression(fsys: setofsys); | |
| var lattr: attr; lop: operator; signed: boolean; | |
| procedure term(fsys: setofsys); | |
| var lattr: attr; lop: operator; | |
| procedure factor(fsys: setofsys); | |
| var lcp: ctp; lvp: csp; varpart: boolean; | |
| cstpart: setty; lsp: stp; | |
| begin | |
| if not (sy in facbegsys) then | |
| begin error(58); skip(fsys + facbegsys); | |
| gattr.typtr := nil | |
| end; | |
| while sy in facbegsys do | |
| begin | |
| case sy of | |
| (*id*) ident: | |
| begin searchid([konst,vars,field,func],lcp); | |
| insymbol; | |
| if lcp^.klass = func then | |
| begin call(fsys,lcp); | |
| with gattr do | |
| begin kind := expr; | |
| if typtr <> nil then | |
| if typtr^.form=subrange then | |
| typtr := typtr^.rangetype | |
| end | |
| end | |
| else | |
| if lcp^.klass = konst then | |
| with gattr, lcp^ do | |
| begin typtr := idtype; kind := cst; | |
| cval := values | |
| end | |
| else | |
| begin selector(fsys,lcp); | |
| if gattr.typtr<>nil then(*elim.subr.types to*) | |
| with gattr,typtr^ do(*simplify later tests*) | |
| if form = subrange then | |
| typtr := rangetype | |
| end | |
| end; | |
| (*cst*) intconst: | |
| begin | |
| with gattr do | |
| begin typtr := intptr; kind := cst; | |
| cval := val | |
| end; | |
| insymbol | |
| end; | |
| realconst: | |
| begin | |
| with gattr do | |
| begin typtr := realptr; kind := cst; | |
| cval := val | |
| end; | |
| insymbol | |
| end; | |
| stringconst: | |
| begin | |
| with gattr do | |
| begin | |
| if lgth = 1 then typtr := charptr | |
| else | |
| begin new(lsp,arrays); | |
| with lsp^ do | |
| begin aeltype := charptr; form:=arrays; | |
| inxtype := nil; size := lgth*charsize | |
| end; | |
| typtr := lsp | |
| end; | |
| kind := cst; cval := val | |
| end; | |
| insymbol | |
| end; | |
| (* ( *) lparent: | |
| begin insymbol; expression(fsys + [rparent]); | |
| if sy = rparent then insymbol else error(4) | |
| end; | |
| (*not*) notsy: | |
| begin insymbol; factor(fsys); | |
| load; gen0(19(*not*)); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr <> boolptr then | |
| begin error(135); gattr.typtr := nil end; | |
| end; | |
| (*[*) lbrack: | |
| begin insymbol; cstpart := [ ]; varpart := false; | |
| new(lsp,power); | |
| with lsp^ do | |
| begin elset:=nil;size:=setsize;form:=power end; | |
| if sy = rbrack then | |
| begin | |
| with gattr do | |
| begin typtr := lsp; kind := cst end; | |
| insymbol | |
| end | |
| else | |
| begin | |
| repeat expression(fsys + [comma,rbrack]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> scalar then | |
| begin error(136); gattr.typtr := nil end | |
| else | |
| if comptypes(lsp^.elset,gattr.typtr) then | |
| begin | |
| if gattr.kind = cst then | |
| if (gattr.cval.ival < setlow) or | |
| (gattr.cval.ival > sethigh) then | |
| error(304) | |
| else | |
| cstpart := cstpart+[gattr.cval.ival] | |
| else | |
| begin load; | |
| if not comptypes(gattr.typtr,intptr) | |
| then gen0t(58(*ord*),gattr.typtr); | |
| gen0(23(*sgs*)); | |
| if varpart then gen0(28(*uni*)) | |
| else varpart := true | |
| end; | |
| lsp^.elset := gattr.typtr; | |
| gattr.typtr := lsp | |
| end | |
| else error(137); | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = rbrack then insymbol else error(12) | |
| end; | |
| if varpart then | |
| begin | |
| if cstpart <> [ ] then | |
| begin new(lvp,pset); lvp^.pval := cstpart; | |
| lvp^.cclass := pset; | |
| if cstptrix = cstoccmax then error(254) | |
| else | |
| begin cstptrix := cstptrix + 1; | |
| cstptr[cstptrix] := lvp; | |
| gen2(51(*ldc*),5,cstptrix); | |
| gen0(28(*uni*)); gattr.kind := expr | |
| end | |
| end | |
| end | |
| else | |
| begin new(lvp,pset); lvp^.pval := cstpart; | |
| lvp^.cclass := pset; | |
| gattr.cval.valp := lvp | |
| end | |
| end | |
| end (*case*) ; | |
| if not (sy in fsys) then | |
| begin error(6); skip(fsys + facbegsys) end | |
| end (*while*) | |
| end (*factor*) ; | |
| begin (*term*) | |
| factor(fsys + [mulop]); | |
| while sy = mulop do | |
| begin load; lattr := gattr; lop := op; | |
| insymbol; factor(fsys + [mulop]); load; | |
| if (lattr.typtr <> nil) and (gattr.typtr <> nil) then | |
| case lop of | |
| (***) mul: if (lattr.typtr=intptr)and(gattr.typtr=intptr) | |
| then gen0(15(*mpi*)) | |
| else | |
| begin | |
| if lattr.typtr = intptr then | |
| begin gen0(9(*flo*)); | |
| lattr.typtr := realptr | |
| end | |
| else | |
| if gattr.typtr = intptr then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| if (lattr.typtr = realptr) | |
| and(gattr.typtr=realptr)then gen0(16(*mpr*)) | |
| else | |
| if(lattr.typtr^.form=power) | |
| and comptypes(lattr.typtr,gattr.typtr)then | |
| gen0(12(*int*)) | |
| else begin error(134); gattr.typtr:=nil end | |
| end; | |
| (* / *) rdiv: begin | |
| if gattr.typtr = intptr then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| if lattr.typtr = intptr then | |
| begin gen0(9(*flo*)); | |
| lattr.typtr := realptr | |
| end; | |
| if (lattr.typtr = realptr) | |
| and (gattr.typtr=realptr)then gen0(7(*dvr*)) | |
| else begin error(134); gattr.typtr := nil end | |
| end; | |
| (*div*) idiv: if (lattr.typtr = intptr) | |
| and (gattr.typtr = intptr) then gen0(6(*dvi*)) | |
| else begin error(134); gattr.typtr := nil end; | |
| (*mod*) imod: if (lattr.typtr = intptr) | |
| and (gattr.typtr = intptr) then gen0(14(*mod*)) | |
| else begin error(134); gattr.typtr := nil end; | |
| (*and*) andop:if (lattr.typtr = boolptr) | |
| and (gattr.typtr = boolptr) then gen0(4(*and*)) | |
| else begin error(134); gattr.typtr := nil end | |
| end (*case*) | |
| else gattr.typtr := nil | |
| end (*while*) | |
| end (*term*) ; | |
| begin (*simpleexpression*) | |
| signed := false; | |
| if (sy = addop) and (op in [plus,minus]) then | |
| begin signed := op = minus; insymbol end; | |
| term(fsys + [addop]); | |
| if signed then | |
| begin load; | |
| if gattr.typtr = intptr then gen0(17(*ngi*)) | |
| else | |
| if gattr.typtr = realptr then gen0(18(*ngr*)) | |
| else begin error(134); gattr.typtr := nil end | |
| end; | |
| while sy = addop do | |
| begin load; lattr := gattr; lop := op; | |
| insymbol; term(fsys + [addop]); load; | |
| if (lattr.typtr <> nil) and (gattr.typtr <> nil) then | |
| case lop of | |
| (*+*) plus: | |
| if (lattr.typtr = intptr)and(gattr.typtr = intptr) then | |
| gen0(2(*adi*)) | |
| else | |
| begin | |
| if lattr.typtr = intptr then | |
| begin gen0(9(*flo*)); | |
| lattr.typtr := realptr | |
| end | |
| else | |
| if gattr.typtr = intptr then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| if (lattr.typtr = realptr)and(gattr.typtr = realptr) | |
| then gen0(3(*adr*)) | |
| else if(lattr.typtr^.form=power) | |
| and comptypes(lattr.typtr,gattr.typtr) then | |
| gen0(28(*uni*)) | |
| else begin error(134); gattr.typtr:=nil end | |
| end; | |
| (*-*) minus: | |
| if (lattr.typtr = intptr)and(gattr.typtr = intptr) then | |
| gen0(21(*sbi*)) | |
| else | |
| begin | |
| if lattr.typtr = intptr then | |
| begin gen0(9(*flo*)); | |
| lattr.typtr := realptr | |
| end | |
| else | |
| if gattr.typtr = intptr then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| if (lattr.typtr = realptr)and(gattr.typtr = realptr) | |
| then gen0(22(*sbr*)) | |
| else | |
| if (lattr.typtr^.form = power) | |
| and comptypes(lattr.typtr,gattr.typtr) then | |
| gen0(5(*dif*)) | |
| else begin error(134); gattr.typtr := nil end | |
| end; | |
| (*or*) orop: | |
| if(lattr.typtr=boolptr)and(gattr.typtr=boolptr)then | |
| gen0(13(*ior*)) | |
| else begin error(134); gattr.typtr := nil end | |
| end (*case*) | |
| else gattr.typtr := nil | |
| end (*while*) | |
| end (*simpleexpression*) ; | |
| begin (*expression*) | |
| simpleexpression(fsys + [relop]); | |
| if sy = relop then | |
| begin | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <= power then load | |
| else loadaddress; | |
| lattr := gattr; lop := op; | |
| if lop = inop then | |
| if not comptypes(gattr.typtr,intptr) then | |
| gen0t(58(*ord*),gattr.typtr); | |
| insymbol; simpleexpression(fsys); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <= power then load | |
| else loadaddress; | |
| if (lattr.typtr <> nil) and (gattr.typtr <> nil) then | |
| if lop = inop then | |
| if gattr.typtr^.form = power then | |
| if comptypes(lattr.typtr,gattr.typtr^.elset) then | |
| gen0(11(*inn*)) | |
| else begin error(129); gattr.typtr := nil end | |
| else begin error(130); gattr.typtr := nil end | |
| else | |
| begin | |
| if lattr.typtr <> gattr.typtr then | |
| if lattr.typtr = intptr then | |
| begin gen0(9(*flo*)); | |
| lattr.typtr := realptr | |
| end | |
| else | |
| if gattr.typtr = intptr then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| if comptypes(lattr.typtr,gattr.typtr) then | |
| begin lsize := lattr.typtr^.size; | |
| case lattr.typtr^.form of | |
| scalar: | |
| if lattr.typtr = realptr then typind := 'r' | |
| else | |
| if lattr.typtr = boolptr then typind := 'b' | |
| else | |
| if lattr.typtr = charptr then typind := 'c' | |
| else typind := 'i'; | |
| pointer: | |
| begin | |
| if lop in [ltop,leop,gtop,geop] then error(131); | |
| typind := 'a' | |
| end; | |
| power: | |
| begin if lop in [ltop,gtop] then error(132); | |
| typind := 's' | |
| end; | |
| arrays: | |
| begin | |
| if not string(lattr.typtr) | |
| then error(134); | |
| typind := 'm' | |
| end; | |
| records: | |
| begin | |
| error(134); | |
| typind := 'm' | |
| end; | |
| files: | |
| begin error(133); typind := 'f' end | |
| end; | |
| case lop of | |
| ltop: gen2(53(*les*),ord(typind),lsize); | |
| leop: gen2(52(*leq*),ord(typind),lsize); | |
| gtop: gen2(49(*grt*),ord(typind),lsize); | |
| geop: gen2(48(*geq*),ord(typind),lsize); | |
| neop: gen2(55(*neq*),ord(typind),lsize); | |
| eqop: gen2(47(*equ*),ord(typind),lsize) | |
| end | |
| end | |
| else error(129) | |
| end; | |
| gattr.typtr := boolptr; gattr.kind := expr | |
| end (*sy = relop*) | |
| end (*expression*) ; | |
| procedure assignment(fcp: ctp); | |
| var lattr: attr; | |
| begin selector(fsys + [becomes],fcp); | |
| if sy = becomes then | |
| begin | |
| if gattr.typtr <> nil then | |
| if (gattr.access<>drct) or (gattr.typtr^.form>power) then | |
| loadaddress; | |
| lattr := gattr; | |
| insymbol; expression(fsys); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <= power then load | |
| else loadaddress; | |
| if (lattr.typtr <> nil) and (gattr.typtr <> nil) then | |
| begin | |
| if comptypes(realptr,lattr.typtr)and(gattr.typtr=intptr)then | |
| begin gen0(10(*flt*)); | |
| gattr.typtr := realptr | |
| end; | |
| if comptypes(lattr.typtr,gattr.typtr) then | |
| case lattr.typtr^.form of | |
| scalar, | |
| subrange: begin | |
| if debug then checkbnds(lattr.typtr); | |
| store(lattr) | |
| end; | |
| pointer: begin | |
| if debug then | |
| gen2t(45(*chk*),0,maxaddr,nilptr); | |
| store(lattr) | |
| end; | |
| power: store(lattr); | |
| arrays, | |
| records: gen1(40(*mov*),lattr.typtr^.size); | |
| files: error(146) | |
| end | |
| else error(129) | |
| end | |
| end (*sy = becomes*) | |
| else error(51) | |
| end (*assignment*) ; | |
| procedure gotostatement; | |
| var llp: lbp; found: boolean; ttop,ttop1: disprange; | |
| begin | |
| if sy = intconst then | |
| begin | |
| found := false; | |
| ttop := top; | |
| while display[ttop].occur <> blck do ttop := ttop – 1; | |
| ttop1 := ttop; | |
| repeat | |
| llp := display[ttop].flabel; | |
| while (llp <> nil) and not found do | |
| with llp^ do | |
| if labval = val.ival then | |
| begin found := true; | |
| if ttop = ttop1 then | |
| genujpxjp(57(*ujp*),labname) | |
| else (*goto leads out of procedure*) error(399) | |
| end | |
| else llp := nextlab; | |
| ttop := ttop – 1 | |
| until found or (ttop = 0); | |
| if not found then error(167); | |
| insymbol | |
| end | |
| else error(15) | |
| end (*gotostatement*) ; | |
| procedure compoundstatement; | |
| begin | |
| repeat | |
| repeat statement(fsys + [semicolon,endsy]) | |
| until not (sy in statbegsys); | |
| test := sy <> semicolon; | |
| if not test then insymbol | |
| until test; | |
| if sy = endsy then insymbol else error(13) | |
| end (*compoundstatemenet*) ; | |
| procedure ifstatement; | |
| var lcix1,lcix2: integer; | |
| begin expression(fsys + [thensy]); | |
| genlabel(lcix1); genfjp(lcix1); | |
| if sy = thensy then insymbol else error(52); | |
| statement(fsys + [elsesy]); | |
| if sy = elsesy then | |
| begin genlabel(lcix2); genujpxjp(57(*ujp*),lcix2); | |
| putlabel(lcix1); | |
| insymbol; statement(fsys); | |
| putlabel(lcix2) | |
| end | |
| else putlabel(lcix1) | |
| end (*ifstatement*) ; | |
| procedure casestatement; | |
| label 1; | |
| type cip = ^caseinfo; | |
| caseinfo = packed | |
| record next: cip; | |
| csstart: integer; | |
| cslab: integer | |
| end; | |
| var lsp,lsp1: stp; fstptr,lpt1,lpt2,lpt3: cip; lval: valu; | |
| laddr, lcix, lcix1, lmin, lmax: integer; | |
| begin expression(fsys + [ofsy,comma,colon]); | |
| load; genlabel(lcix); | |
| lsp := gattr.typtr; | |
| if lsp <> nil then | |
| if (lsp^.form <> scalar) or (lsp = realptr) then | |
| begin error(144); lsp := nil end | |
| else if not comptypes(lsp,intptr) then gen0t(58(*ord*),lsp); | |
| genujpxjp(57(*ujp*),lcix); | |
| if sy = ofsy then insymbol else error(8); | |
| fstptr := nil; genlabel(laddr); | |
| repeat | |
| lpt3 := nil; genlabel(lcix1); | |
| if not(sy in [semicolon,endsy]) then | |
| begin | |
| repeat constant(fsys + [comma,colon],lsp1,lval); | |
| if lsp <> nil then | |
| if comptypes(lsp,lsp1) then | |
| begin lpt1 := fstptr; lpt2 := nil; | |
| while lpt1 <> nil do | |
| with lpt1^ do | |
| begin | |
| if cslab <= lval.ival then | |
| begin if cslab = lval.ival then error(156); | |
| goto 1 | |
| end; | |
| lpt2 := lpt1; lpt1 := next | |
| end; | |
| 1: new(lpt3); | |
| with lpt3^ do | |
| begin next := lpt1; cslab := lval.ival; | |
| csstart := lcix1 | |
| end; | |
| if lpt2 = nil then fstptr := lpt3 | |
| else lpt2^.next := lpt3 | |
| end | |
| else error(147); | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = colon then insymbol else error(5); | |
| putlabel(lcix1); | |
| repeat statement(fsys + [semicolon]) | |
| until not (sy in statbegsys); | |
| if lpt3 <> nil then | |
| genujpxjp(57(*ujp*),laddr); | |
| end; | |
| test := sy <> semicolon; | |
| if not test then insymbol | |
| until test; | |
| putlabel(lcix); | |
| if fstptr <> nil then | |
| begin lmax := fstptr^.cslab; | |
| (*reverse pointers*) | |
| lpt1 := fstptr; fstptr := nil; | |
| repeat lpt2 := lpt1^.next; lpt1^.next := fstptr; | |
| fstptr := lpt1; lpt1 := lpt2 | |
| until lpt1 = nil; | |
| lmin := fstptr^.cslab; | |
| if lmax – lmin < cixmax then | |
| begin | |
| gen2t(45(*chk*),lmin,lmax,intptr); | |
| gen2(51(*ldc*),1,lmin); gen0(21(*sbi*)); genlabel(lcix); | |
| genujpxjp(44(*xjp*),lcix); putlabel(lcix); | |
| repeat | |
| with fstptr^ do | |
| begin | |
| while cslab > lmin do | |
| begin gen0(60(*ujc error*)); | |
| lmin := lmin+1 | |
| end; | |
| genujpxjp(57(*ujp*),csstart); | |
| fstptr := next; lmin := lmin + 1 | |
| end | |
| until fstptr = nil; | |
| putlabel(laddr) | |
| end | |
| else error(157) | |
| end; | |
| if sy = endsy then insymbol else error(13) | |
| end (*casestatement*) ; | |
| procedure repeatstatement; | |
| var laddr: integer; | |
| begin genlabel(laddr); putlabel(laddr); | |
| repeat statement(fsys + [semicolon,untilsy]); | |
| if sy in statbegsys then error(14) | |
| until not(sy in statbegsys); | |
| while sy = semicolon do | |
| begin insymbol; | |
| repeat statement(fsys + [semicolon,untilsy]); | |
| if sy in statbegsys then error(14) | |
| until not (sy in statbegsys); | |
| end; | |
| if sy = untilsy then | |
| begin insymbol; expression(fsys); genfjp(laddr) | |
| end | |
| else error(53) | |
| end (*repeatstatement*) ; | |
| procedure whilestatement; | |
| var laddr, lcix: integer; | |
| begin genlabel(laddr); putlabel(laddr); | |
| expression(fsys + [dosy]); genlabel(lcix); genfjp(lcix); | |
| if sy = dosy then insymbol else error(54); | |
| statement(fsys); genujpxjp(57(*ujp*),laddr); putlabel(lcix) | |
| end (*whilestatement*) ; | |
| procedure forstatement; | |
| var lattr: attr; lsy: symbol; | |
| lcix, laddr: integer; | |
| llc: addrrange; | |
| begin llc := lc; | |
| with lattr do | |
| begin typtr := nil; kind := varbl; | |
| access := drct; vlevel := level; dplmt := 0 | |
| end; | |
| if sy = ident then | |
| begin searchid([vars],lcp); | |
| with lcp^, lattr do | |
| begin typtr := idtype; kind := varbl; | |
| if vkind = actual then | |
| begin access := drct; vlevel := vlev; | |
| dplmt := vaddr | |
| end | |
| else begin error(155); typtr := nil end | |
| end; | |
| if lattr.typtr <> nil then | |
| if (lattr.typtr^.form > subrange) | |
| or comptypes(realptr,lattr.typtr) then | |
| begin error(143); lattr.typtr := nil end; | |
| insymbol | |
| end | |
| else | |
| begin error(2); skip(fsys + [becomes,tosy,downtosy,dosy]) end; | |
| if sy = becomes then | |
| begin insymbol; expression(fsys + [tosy,downtosy,dosy]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> scalar then error(144) | |
| else | |
| if comptypes(lattr.typtr,gattr.typtr) then | |
| begin load; store(lattr) end | |
| else error(145) | |
| end | |
| else | |
| begin error(51); skip(fsys + [tosy,downtosy,dosy]) end; | |
| if sy in [tosy,downtosy] then | |
| begin lsy := sy; insymbol; expression(fsys + [dosy]); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form <> scalar then error(144) | |
| else | |
| if comptypes(lattr.typtr,gattr.typtr) then | |
| begin load; | |
| if not comptypes(lattr.typtr,intptr) then | |
| gen0t(58(*ord*),gattr.typtr); | |
| align(intptr,lc); | |
| gen2t(56(*str*),0,lc,intptr); | |
| genlabel(laddr); putlabel(laddr); | |
| gattr := lattr; load; | |
| if not comptypes(gattr.typtr,intptr) then | |
| gen0t(58(*ord*),gattr.typtr); | |
| gen2t(54(*lod*),0,lc,intptr); | |
| lc := lc + intsize; | |
| if lc > lcmax then lcmax := lc; | |
| if lsy = tosy then gen2(52(*leq*),ord('i'),1) | |
| else gen2(48(*geq*),ord('i'),1); | |
| end | |
| else error(145) | |
| end | |
| else begin error(55); skip(fsys + [dosy]) end; | |
| genlabel(lcix); genujpxjp(33(*fjp*),lcix); | |
| if sy = dosy then insymbol else error(54); | |
| statement(fsys); | |
| gattr := lattr; load; | |
| if lsy=tosy then gen1t(34(*inc*),1,gattr.typtr) | |
| else gen1t(31(*dec*),1,gattr.typtr); | |
| store(lattr); genujpxjp(57(*ujp*),laddr); putlabel(lcix); | |
| lc := llc; | |
| end (*forstatement*) ; | |
| procedure withstatement; | |
| var lcp: ctp; lcnt1: disprange; llc: addrrange; | |
| begin lcnt1 := 0; llc := lc; | |
| repeat | |
| if sy = ident then | |
| begin searchid([vars,field],lcp); insymbol end | |
| else begin error(2); lcp := uvarptr end; | |
| selector(fsys + [comma,dosy],lcp); | |
| if gattr.typtr <> nil then | |
| if gattr.typtr^.form = records then | |
| if top < displimit then | |
| begin top := top + 1; lcnt1 := lcnt1 + 1; | |
| with display[top] do | |
| begin fname := gattr.typtr^.fstfld; | |
| flabel := nil | |
| end; | |
| if gattr.access = drct then | |
| with display[top] do | |
| begin occur := crec; clev := gattr.vlevel; | |
| cdspl := gattr.dplmt | |
| end | |
| else | |
| begin loadaddress; | |
| align(nilptr,lc); | |
| gen2t(56(*str*),0,lc,nilptr); | |
| with display[top] do | |
| begin occur := vrec; vdspl := lc end; | |
| lc := lc+ptrsize; | |
| if lc > lcmax then lcmax := lc | |
| end | |
| end | |
| else error(250) | |
| else error(140); | |
| test := sy <> comma; | |
| if not test then insymbol | |
| until test; | |
| if sy = dosy then insymbol else error(54); | |
| statement(fsys); | |
| top := top-lcnt1; lc := llc; | |
| end (*withstatement*) ; | |
| begin (*statement*) | |
| if sy = intconst then (*label*) | |
| begin llp := display[level].flabel; | |
| while llp <> nil do | |
| with llp^ do | |
| if labval = val.ival then | |
| begin if defined then error(165); | |
| putlabel(labname); defined := true; | |
| goto 1 | |
| end | |
| else llp := nextlab; | |
| error(167); | |
| 1: insymbol; | |
| if sy = colon then insymbol else error(5) | |
| end; | |
| if not (sy in fsys + [ident]) then | |
| begin error(6); skip(fsys) end; | |
| if sy in statbegsys + [ident] then | |
| begin | |
| case sy of | |
| ident: begin searchid([vars,field,func,proc],lcp); insymbol; | |
| if lcp^.klass = proc then call(fsys,lcp) | |
| else assignment(lcp) | |
| end; | |
| beginsy: begin insymbol; compoundstatement end; | |
| gotosy: begin insymbol; gotostatement end; | |
| ifsy: begin insymbol; ifstatement end; | |
| casesy: begin insymbol; casestatement end; | |
| whilesy: begin insymbol; whilestatement end; | |
| repeatsy: begin insymbol; repeatstatement end; | |
| forsy: begin insymbol; forstatement end; | |
| withsy: begin insymbol; withstatement end | |
| end; | |
| if not (sy in [semicolon,endsy,elsesy,untilsy]) then | |
| begin error(6); skip(fsys) end | |
| end | |
| end (*statement*) ; | |
| begin (*body*) | |
| if fprocp <> nil then entname := fprocp^.pfname | |
| else genlabel(entname); | |
| cstptrix := 0; topnew := lcaftermarkstack; topmax := lcaftermarkstack; | |
| putlabel(entname); genlabel(segsize); genlabel(stacktop); | |
| gencupent(32(*ent1*),1,segsize); gencupent(32(*ent2*),2,stacktop); | |
| if fprocp <> nil then (*copy multiple values into local cells*) | |
| begin llc1 := lcaftermarkstack; | |
| lcp := fprocp^.next; | |
| while lcp <> nil do | |
| with lcp^ do | |
| begin | |
| align(parmptr,llc1); | |
| if klass = vars then | |
| if idtype <> nil then | |
| if idtype^.form > power then | |
| begin | |
| if vkind = actual then | |
| begin | |
| gen2(50(*lda*),0,vaddr); | |
| gen2t(54(*lod*),0,llc1,nilptr); | |
| gen1(40(*mov*),idtype^.size); | |
| end; | |
| llc1 := llc1 + ptrsize | |
| end | |
| else llc1 := llc1 + idtype^.size; | |
| lcp := lcp^.next; | |
| end; | |
| end; | |
| lcmax := lc; | |
| repeat | |
| repeat statement(fsys + [semicolon,endsy]) | |
| until not (sy in statbegsys); | |
| test := sy <> semicolon; | |
| if not test then insymbol | |
| until test; | |
| if sy = endsy then insymbol else error(13); | |
| llp := display[top].flabel; (*test for undefined labels*) | |
| while llp <> nil do | |
| with llp^ do | |
| begin | |
| if not defined then | |
| begin error(168); | |
| writeln(output); writeln(output,' label ',labval); | |
| write(output,' ':chcnt+16) | |
| end; | |
| llp := nextlab | |
| end; | |
| if fprocp <> nil then | |
| begin | |
| if fprocp^.idtype = nil then gen1(42(*ret*),ord('p')) | |
| else gen0t(42(*ret*),fprocp^.idtype); | |
| align(parmptr,lcmax); | |
| if prcode then | |
| begin writeln(prr,'l',segsize:4,'=',lcmax); | |
| writeln(prr,'l',stacktop:4,'=',topmax) | |
| end | |
| end | |
| else | |
| begin gen1(42(*ret*),ord('p')); | |
| align(parmptr,lcmax); | |
| if prcode then | |
| begin writeln(prr,'l',segsize:4,'=',lcmax); | |
| writeln(prr,'l',stacktop:4,'=',topmax); | |
| writeln(prr,'q') | |
| end; | |
| ic := 0; | |
| (*generate call of main program; note that this call must be loaded | |
| at absolute address zero*) | |
| gen1(41(*mst*),0); gencupent(46(*cup*),0,entname); gen0(29(*stp*)); | |
| if prcode then | |
| writeln(prr,'q'); | |
| saveid := id; | |
| while fextfilep <> nil do | |
| begin | |
| with fextfilep^ do | |
| if not ((filename = 'input ') or (filename = 'output ') or | |
| (filename = 'prd ') or (filename = 'prr ')) | |
| then begin id := filename; | |
| searchid([vars],llcp); | |
| if llcp^.idtype<>nil then | |
| if llcp^.idtype^.form<>files then | |
| begin writeln(output); | |
| writeln(output,' ':8,'undeclared ','external ', | |
| 'file',fextfilep^.filename:8); | |
| write(output,' ':chcnt+16) | |
| end | |
| end; | |
| fextfilep := fextfilep^.nextfile | |
| end; | |
| id := saveid; | |
| if prtables then | |
| begin writeln(output); printtables(true) | |
| end | |
| end; | |
| end (*body*) ; | |
| begin (*block*) | |
| dp := true; | |
| repeat | |
| if sy = labelsy then | |
| begin insymbol; labeldeclaration end; | |
| if sy = constsy then | |
| begin insymbol; constdeclaration end; | |
| if sy = typesy then | |
| begin insymbol; typedeclaration end; | |
| if sy = varsy then | |
| begin insymbol; vardeclaration end; | |
| while sy in [procsy,funcsy] do | |
| begin lsy := sy; insymbol; procdeclaration(lsy) end; | |
| if sy <> beginsy then | |
| begin error(18); skip(fsys) end | |
| until (sy in statbegsys) or eof(input); | |
| dp := false; | |
| if sy = beginsy then insymbol else error(17); | |
| repeat body(fsys + [casesy]); | |
| if sy <> fsy then | |
| begin error(6); skip(fsys) end | |
| until ((sy = fsy) or (sy in blockbegsys)) or eof(input); | |
| end (*block*) ; | |
| procedure programme(fsys:setofsys); | |
| var extfp:extfilep; | |
| begin | |
| if sy = progsy then | |
| begin insymbol; if sy <> ident then error(2); insymbol; | |
| if not (sy in [lparent,semicolon]) then error(14); | |
| if sy = lparent then | |
| begin | |
| repeat insymbol; | |
| if sy = ident then | |
| begin new(extfp); | |
| with extfp^ do | |
| begin filename := id; nextfile := fextfilep end; | |
| fextfilep := extfp; | |
| insymbol; | |
| if not ( sy in [comma,rparent] ) then error(20) | |
| end | |
| else error(2) | |
| until sy <> comma; | |
| if sy <> rparent then error(4); | |
| insymbol | |
| end; | |
| if sy <> semicolon then error(14) | |
| else insymbol; | |
| end; | |
| repeat block(fsys,period,nil); | |
| if sy <> period then error(21) | |
| until (sy = period) or eof(input); | |
| if list then writeln(output); | |
| if errinx <> 0 then | |
| begin list := false; endofline end | |
| end (*programme*) ; | |
| procedure stdnames; | |
| begin | |
| na[ 1] := 'false '; na[ 2] := 'true '; na[ 3] := 'input '; | |
| na[ 4] := 'output '; na[ 5] := 'get '; na[ 6] := 'put '; | |
| na[ 7] := 'reset '; na[ 8] := 'rewrite '; na[ 9] := 'read '; | |
| na[10] := 'write '; na[11] := 'pack '; na[12] := 'unpack '; | |
| na[13] := 'new '; na[14] := 'release '; na[15] := 'readln '; | |
| na[16] := 'writeln '; | |
| na[17] := 'abs '; na[18] := 'sqr '; na[19] := 'trunc '; | |
| na[20] := 'odd '; na[21] := 'ord '; na[22] := 'chr '; | |
| na[23] := 'pred '; na[24] := 'succ '; na[25] := 'eof '; | |
| na[26] := 'eoln '; | |
| na[27] := 'sin '; na[28] := 'cos '; na[29] := 'exp '; | |
| na[30] := 'sqrt '; na[31] := 'ln '; na[32] := 'arctan '; | |
| na[33] := 'prd '; na[34] := 'prr '; na[35] := 'mark '; | |
| end (*stdnames*) ; | |
| procedure enterstdtypes; | |
| begin (*type underlying:*) | |
| (******************) | |
| new(intptr,scalar,standard); (*integer*) | |
| with intptr^ do | |
| begin size := intsize; form := scalar; scalkind := standard end; | |
| new(realptr,scalar,standard); (*real*) | |
| with realptr^ do | |
| begin size := realsize; form := scalar; scalkind := standard end; | |
| new(charptr,scalar,standard); (*char*) | |
| with charptr^ do | |
| begin size := charsize; form := scalar; scalkind := standard end; | |
| new(boolptr,scalar,declared); (*boolean*) | |
| with boolptr^ do | |
| begin size := boolsize; form := scalar; scalkind := declared end; | |
| new(nilptr,pointer); (*nil*) | |
| with nilptr^ do | |
| begin eltype := nil; size := ptrsize; form := pointer end; | |
| new(parmptr,scalar,standard); (*for alignment of parameters*) | |
| with parmptr^ do | |
| begin size := parmsize; form := scalar; scalkind := standard end ; | |
| new(textptr,files); (*text*) | |
| with textptr^ do | |
| begin filtype := charptr; size := charsize; form := files end | |
| end (*enterstdtypes*) ; | |
| procedure entstdnames; | |
| var cp,cp1: ctp; i: integer; | |
| begin (*name:*) | |
| (*******) | |
| new(cp,types); (*integer*) | |
| with cp^ do | |
| begin name := 'integer '; idtype := intptr; klass := types end; | |
| enterid(cp); | |
| new(cp,types); (*real*) | |
| with cp^ do | |
| begin name := 'real '; idtype := realptr; klass := types end; | |
| enterid(cp); | |
| new(cp,types); (*char*) | |
| with cp^ do | |
| begin name := 'char '; idtype := charptr; klass := types end; | |
| enterid(cp); | |
| new(cp,types); (*boolean*) | |
| with cp^ do | |
| begin name := 'boolean '; idtype := boolptr; klass := types end; | |
| enterid(cp); | |
| cp1 := nil; | |
| for i := 1 to 2 do | |
| begin new(cp,konst); (*false,true*) | |
| with cp^ do | |
| begin name := na[i]; idtype := boolptr; | |
| next := cp1; values.ival := i – 1; klass := konst | |
| end; | |
| enterid(cp); cp1 := cp | |
| end; | |
| boolptr^.fconst := cp; | |
| new(cp,konst); (*nil*) | |
| with cp^ do | |
| begin name := 'nil '; idtype := nilptr; | |
| next := nil; values.ival := 0; klass := konst | |
| end; | |
| enterid(cp); | |
| for i := 3 to 4 do | |
| begin new(cp,vars); (*input,output*) | |
| with cp^ do | |
| begin name := na[i]; idtype := textptr; klass := vars; | |
| vkind := actual; next := nil; vlev := 1; | |
| vaddr := lcaftermarkstack+(i-3)*charmax; | |
| end; | |
| enterid(cp) | |
| end; | |
| for i:=33 to 34 do | |
| begin new(cp,vars); (*prd,prr files*) | |
| with cp^ do | |
| begin name := na[i]; idtype := textptr; klass := vars; | |
| vkind := actual; next := nil; vlev := 1; | |
| vaddr := lcaftermarkstack+(i-31)*charmax; | |
| end; | |
| enterid(cp) | |
| end; | |
| for i := 5 to 16 do | |
| begin new(cp,proc,standard); (*get,put,reset*) | |
| with cp^ do (*rewrite,read*) | |
| begin name := na[i]; idtype := nil; (*write,pack*) | |
| next := nil; key := i – 4; (*unpack,pack*) | |
| klass := proc; pfdeckind := standard | |
| end; | |
| enterid(cp) | |
| end; | |
| new(cp,proc,standard); | |
| with cp^ do | |
| begin name:=na[35]; idtype:=nil; | |
| next:= nil; key:=13; | |
| klass:=proc; pfdeckind:= standard | |
| end; enterid(cp); | |
| for i := 17 to 26 do | |
| begin new(cp,func,standard); (*abs,sqr,trunc*) | |
| with cp^ do (*odd,ord,chr*) | |
| begin name := na[i]; idtype := nil; (*pred,succ,eof*) | |
| next := nil; key := i – 16; | |
| klass := func; pfdeckind := standard | |
| end; | |
| enterid(cp) | |
| end; | |
| new(cp,vars); (*parameter of predeclared functions*) | |
| with cp^ do | |
| begin name := ' '; idtype := realptr; klass := vars; | |
| vkind := actual; next := nil; vlev := 1; vaddr := 0 | |
| end; | |
| for i := 27 to 32 do | |
| begin new(cp1,func,declared,actual); (*sin,cos,exp*) | |
| with cp1^ do (*sqrt,ln,arctan*) | |
| begin name := na[i]; idtype := realptr; next := cp; | |
| forwdecl := false; externl := true; pflev := 0; pfname := i – 12; | |
| klass := func; pfdeckind := declared; pfkind := actual | |
| end; | |
| enterid(cp1) | |
| end | |
| end (*entstdnames*) ; | |
| procedure enterundecl; | |
| begin | |
| new(utypptr,types); | |
| with utypptr^ do | |
| begin name := ' '; idtype := nil; klass := types end; | |
| new(ucstptr,konst); | |
| with ucstptr^ do | |
| begin name := ' '; idtype := nil; next := nil; | |
| values.ival := 0; klass := konst | |
| end; | |
| new(uvarptr,vars); | |
| with uvarptr^ do | |
| begin name := ' '; idtype := nil; vkind := actual; | |
| next := nil; vlev := 0; vaddr := 0; klass := vars | |
| end; | |
| new(ufldptr,field); | |
| with ufldptr^ do | |
| begin name := ' '; idtype := nil; next := nil; fldaddr := 0; | |
| klass := field | |
| end; | |
| new(uprcptr,proc,declared,actual); | |
| with uprcptr^ do | |
| begin name := ' '; idtype := nil; forwdecl := false; | |
| next := nil; externl := false; pflev := 0; genlabel(pfname); | |
| klass := proc; pfdeckind := declared; pfkind := actual | |
| end; | |
| new(ufctptr,func,declared,actual); | |
| with ufctptr^ do | |
| begin name := ' '; idtype := nil; next := nil; | |
| forwdecl := false; externl := false; pflev := 0; genlabel(pfname); | |
| klass := func; pfdeckind := declared; pfkind := actual | |
| end | |
| end (*enterundecl*) ; | |
| procedure initscalars; | |
| begin fwptr := nil; | |
| prtables := false; list := true; prcode := true; debug := true; | |
| dp := true; prterr := true; errinx := 0; | |
| intlabel := 0; kk := 8; fextfilep := nil; | |
| lc := lcaftermarkstack+filebuffer*charmax; | |
| (* note in the above reservation of buffer store for 2 text files *) | |
| ic := 3; eol := true; linecount := 0; | |
| ch := ' '; chcnt := 0; | |
| globtestp := nil; | |
| mxint10 := maxint div 10; digmax := strglgth – 1; | |
| end (*initscalars*) ; | |
| procedure initsets; | |
| begin | |
| constbegsys := [addop,intconst,realconst,stringconst,ident]; | |
| simptypebegsys := [lparent] + constbegsys; | |
| typebegsys:=[arrow,packedsy,arraysy,recordsy,setsy,filesy]+simptypebegsys; | |
| typedels := [arraysy,recordsy,setsy,filesy]; | |
| blockbegsys := [labelsy,constsy,typesy,varsy,procsy,funcsy,beginsy]; | |
| selectsys := [arrow,period,lbrack]; | |
| facbegsys := [intconst,realconst,stringconst,ident,lparent,lbrack,notsy]; | |
| statbegsys := [beginsy,gotosy,ifsy,whilesy,repeatsy,forsy,withsy,casesy]; | |
| end (*initsets*) ; | |
| procedure inittables; | |
| procedure reswords; | |
| begin | |
| rw[ 1] := 'if '; rw[ 2] := 'do '; rw[ 3] := 'of '; | |
| rw[ 4] := 'to '; rw[ 5] := 'in '; rw[ 6] := 'or '; | |
| rw[ 7] := 'end '; rw[ 8] := 'for '; rw[ 9] := 'var '; | |
| rw[10] := 'div '; rw[11] := 'mod '; rw[12] := 'set '; | |
| rw[13] := 'and '; rw[14] := 'not '; rw[15] := 'then '; | |
| rw[16] := 'else '; rw[17] := 'with '; rw[18] := 'goto '; | |
| rw[19] := 'case '; rw[20] := 'type '; | |
| rw[21] := 'file '; rw[22] := 'begin '; | |
| rw[23] := 'until '; rw[24] := 'while '; rw[25] := 'array '; | |
| rw[26] := 'const '; rw[27] := 'label '; | |
| rw[28] := 'repeat '; rw[29] := 'record '; rw[30] := 'downto '; | |
| rw[31] := 'packed '; rw[32] := 'forward '; rw[33] := 'program '; | |
| rw[34] := 'function'; rw[35] := 'procedur'; | |
| frw[1] := 1; frw[2] := 1; frw[3] := 7; frw[4] := 15; frw[5] := 22; | |
| frw[6] := 28; frw[7] := 32; frw[8] := 34; frw[9] := 36; | |
| end (*reswords*) ; | |
| procedure symbols; | |
| begin | |
| rsy[ 1] := ifsy; rsy[ 2] := dosy; rsy[ 3] := ofsy; | |
| rsy[ 4] := tosy; rsy[ 5] := relop; rsy[ 6] := addop; | |
| rsy[ 7] := endsy; rsy[ 8] := forsy; rsy[ 9] := varsy; | |
| rsy[10] := mulop; rsy[11] := mulop; rsy[12] := setsy; | |
| rsy[13] := mulop; rsy[14] := notsy; rsy[15] := thensy; | |
| rsy[16] := elsesy; rsy[17] := withsy; rsy[18] := gotosy; | |
| rsy[19] := casesy; rsy[20] := typesy; | |
| rsy[21] := filesy; rsy[22] := beginsy; | |
| rsy[23] := untilsy; rsy[24] := whilesy; rsy[25] := arraysy; | |
| rsy[26] := constsy; rsy[27] := labelsy; | |
| rsy[28] := repeatsy; rsy[29] := recordsy; rsy[30] := downtosy; | |
| rsy[31] := packedsy; rsy[32] := forwardsy; rsy[33] := progsy; | |
| rsy[34] := funcsy; rsy[35] := procsy; | |
| ssy['+'] := addop ; ssy['-'] := addop; ssy['*'] := mulop; | |
| ssy['/'] := mulop ; ssy['('] := lparent; ssy[')'] := rparent; | |
| ssy['$'] := othersy ; ssy['='] := relop; ssy[' '] := othersy; | |
| ssy[','] := comma ; ssy['.'] := period; ssy['''']:= othersy; | |
| ssy['['] := lbrack ; ssy[']'] := rbrack; ssy[':'] := colon; | |
| ssy['^'] := arrow ; ssy['<'] := relop; ssy['>'] := relop; | |
| ssy[';'] := semicolon; | |
| end (*symbols*) ; | |
| procedure rators; | |
| var i: integer; | |
| begin | |
| for i := 1 to 35 (*nr of res words*) do rop[i] := noop; | |
| rop[5] := inop; rop[10] := idiv; rop[11] := imod; | |
| rop[6] := orop; rop[13] := andop; | |
| for i := ordminchar to ordmaxchar do sop[chr(i)] := noop; | |
| sop['+'] := plus; sop['-'] := minus; sop['*'] := mul; sop['/'] := rdiv; | |
| sop['='] := eqop; sop['<'] := ltop; sop['>'] := gtop; | |
| end (*rators*) ; | |
| procedure procmnemonics; | |
| begin | |
| sna[ 1] :=' get'; sna[ 2] :=' put'; sna[ 3] :=' rdi'; sna[ 4] :=' rdr'; | |
| sna[ 5] :=' rdc'; sna[ 6] :=' wri'; sna[ 7] :=' wro'; sna[ 8] :=' wrr'; | |
| sna[ 9] :=' wrc'; sna[10] :=' wrs'; sna[11] :=' pak'; sna[12] :=' new'; | |
| sna[13] :=' rst'; sna[14] :=' eln'; sna[15] :=' sin'; sna[16] :=' cos'; | |
| sna[17] :=' exp'; sna[18] :=' sqt'; sna[19] :=' log'; sna[20] :=' atn'; | |
| sna[21] :=' rln'; sna[22] :=' wln'; sna[23] :=' sav'; | |
| end (*procmnemonics*) ; | |
| procedure instrmnemonics; | |
| begin | |
| mn[ 0] :=' abi'; mn[ 1] :=' abr'; mn[ 2] :=' adi'; mn[ 3] :=' adr'; | |
| mn[ 4] :=' and'; mn[ 5] :=' dif'; mn[ 6] :=' dvi'; mn[ 7] :=' dvr'; | |
| mn[ 8] :=' eof'; mn[ 9] :=' flo'; mn[10] :=' flt'; mn[11] :=' inn'; | |
| mn[12] :=' int'; mn[13] :=' ior'; mn[14] :=' mod'; mn[15] :=' mpi'; | |
| mn[16] :=' mpr'; mn[17] :=' ngi'; mn[18] :=' ngr'; mn[19] :=' not'; | |
| mn[20] :=' odd'; mn[21] :=' sbi'; mn[22] :=' sbr'; mn[23] :=' sgs'; | |
| mn[24] :=' sqi'; mn[25] :=' sqr'; mn[26] :=' sto'; mn[27] :=' trc'; | |
| mn[28] :=' uni'; mn[29] :=' stp'; mn[30] :=' csp'; mn[31] :=' dec'; | |
| mn[32] :=' ent'; mn[33] :=' fjp'; mn[34] :=' inc'; mn[35] :=' ind'; | |
| mn[36] :=' ixa'; mn[37] :=' lao'; mn[38] :=' lca'; mn[39] :=' ldo'; | |
| mn[40] :=' mov'; mn[41] :=' mst'; mn[42] :=' ret'; mn[43] :=' sro'; | |
| mn[44] :=' xjp'; mn[45] :=' chk'; mn[46] :=' cup'; mn[47] :=' equ'; | |
| mn[48] :=' geq'; mn[49] :=' grt'; mn[50] :=' lda'; mn[51] :=' ldc'; | |
| mn[52] :=' leq'; mn[53] :=' les'; mn[54] :=' lod'; mn[55] :=' neq'; | |
| mn[56] :=' str'; mn[57] :=' ujp'; mn[58] :=' ord'; mn[59] :=' chr'; | |
| mn[60] :=' ujc'; | |
| end (*instrmnemonics*) ; | |
| procedure chartypes; | |
| var i : integer; | |
| begin | |
| for i := ordminchar to ordmaxchar do chartp[chr(i)] := illegal; | |
| chartp['a'] := letter ; | |
| chartp['b'] := letter ; chartp['c'] := letter ; | |
| chartp['d'] := letter ; chartp['e'] := letter ; | |
| chartp['f'] := letter ; chartp['g'] := letter ; | |
| chartp['h'] := letter ; chartp['i'] := letter ; | |
| chartp['j'] := letter ; chartp['k'] := letter ; | |
| chartp['l'] := letter ; chartp['m'] := letter ; | |
| chartp['n'] := letter ; chartp['o'] := letter ; | |
| chartp['p'] := letter ; chartp['q'] := letter ; | |
| chartp['r'] := letter ; chartp['s'] := letter ; | |
| chartp['t'] := letter ; chartp['u'] := letter ; | |
| chartp['v'] := letter ; chartp['w'] := letter ; | |
| chartp['x'] := letter ; chartp['y'] := letter ; | |
| chartp['z'] := letter ; chartp['0'] := number ; | |
| chartp['1'] := number ; chartp['2'] := number ; | |
| chartp['3'] := number ; chartp['4'] := number ; | |
| chartp['5'] := number ; chartp['6'] := number ; | |
| chartp['7'] := number ; chartp['8'] := number ; | |
| chartp['9'] := number ; chartp['+'] := special ; | |
| chartp['-'] := special ; chartp['*'] := special ; | |
| chartp['/'] := special ; chartp['('] := chlparen; | |
| chartp[')'] := special ; chartp['$'] := special ; | |
| chartp['='] := special ; chartp[' '] := chspace ; | |
| chartp[','] := special ; chartp['.'] := chperiod; | |
| chartp['''']:= chstrquo; chartp['['] := special ; | |
| chartp[']'] := special ; chartp[':'] := chcolon ; | |
| chartp['^'] := special ; chartp[';'] := special ; | |
| chartp['<'] := chlt ; chartp['>'] := chgt ; | |
| ordint['0'] := 0; ordint['1'] := 1; ordint['2'] := 2; | |
| ordint['3'] := 3; ordint['4'] := 4; ordint['5'] := 5; | |
| ordint['6'] := 6; ordint['7'] := 7; ordint['8'] := 8; | |
| ordint['9'] := 9; | |
| end; | |
| procedure initdx; | |
| begin | |
| cdx[ 0] := 0; cdx[ 1] := 0; cdx[ 2] := -1; cdx[ 3] := -1; | |
| cdx[ 4] := -1; cdx[ 5] := -1; cdx[ 6] := -1; cdx[ 7] := -1; | |
| cdx[ 8] := 0; cdx[ 9] := 0; cdx[10] := 0; cdx[11] := -1; | |
| cdx[12] := -1; cdx[13] := -1; cdx[14] := -1; cdx[15] := -1; | |
| cdx[16] := -1; cdx[17] := 0; cdx[18] := 0; cdx[19] := 0; | |
| cdx[20] := 0; cdx[21] := -1; cdx[22] := -1; cdx[23] := 0; | |
| cdx[24] := 0; cdx[25] := 0; cdx[26] := -2; cdx[27] := 0; | |
| cdx[28] := -1; cdx[29] := 0; cdx[30] := 0; cdx[31] := 0; | |
| cdx[32] := 0; cdx[33] := -1; cdx[34] := 0; cdx[35] := 0; | |
| cdx[36] := -1; cdx[37] := +1; cdx[38] := +1; cdx[39] := +1; | |
| cdx[40] := -2; cdx[41] := 0; cdx[42] := 0; cdx[43] := -1; | |
| cdx[44] := -1; cdx[45] := 0; cdx[46] := 0; cdx[47] := -1; | |
| cdx[48] := -1; cdx[49] := -1; cdx[50] := +1; cdx[51] := +1; | |
| cdx[52] := -1; cdx[53] := -1; cdx[54] := +1; cdx[55] := -1; | |
| cdx[56] := -1; cdx[57] := 0; cdx[58] := 0; cdx[59] := 0; | |
| cdx[60] := 0; | |
| pdx[ 1] := -1; pdx[ 2] := -1; pdx[ 3] := -2; pdx[ 4] := -2; | |
| pdx[ 5] := -2; pdx[ 6] := -3; pdx[ 7] := -3; pdx[ 8] := -3; | |
| pdx[ 9] := -3; pdx[10] := -4; pdx[11] := 0; pdx[12] := -2; | |
| pdx[13] := -1; pdx[14] := 0; pdx[15] := 0; pdx[16] := 0; | |
| pdx[17] := 0; pdx[18] := 0; pdx[19] := 0; pdx[20] := 0; | |
| pdx[21] := -1; pdx[22] := -1; pdx[23] := -1; | |
| end; | |
| begin (*inittables*) | |
| reswords; symbols; rators; | |
| instrmnemonics; procmnemonics; | |
| chartypes; initdx; | |
| end (*inittables*) ; | |
| begin | |
| (*initialize*) | |
| (************) | |
| initscalars; initsets; inittables; | |
| (*enter standard names and standard types:*) | |
| (******************************************) | |
| level := 0; top := 0; | |
| with display[0] do | |
| begin fname := nil; flabel := nil; occur := blck end; | |
| enterstdtypes; stdnames; entstdnames; enterundecl; | |
| top := 1; level := 1; | |
| with display[1] do | |
| begin fname := nil; flabel := nil; occur := blck end; | |
| (*compile:*) rewrite(prr); (*comment this out when compiling with pcom *) | |
| (**********) | |
| insymbol; | |
| programme(blockbegsys+statbegsys-[casesy]); | |
| end. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Output from p2c, the Pascal-to-C translator */ | |
| /* From input file "pint.p" */ | |
| /* P2c options: | |
| Language BERK | |
| StructFiles 1 */ | |
| /* P2c produced macro calls "BUFEOF(stdin)", | |
| which were edited to "P_eof(stdin)" */ | |
| /* Translation and editing done by I.J.A. van Geel | |
| e-mail: I.J.A.vanGeel@twi.tudelft.nl */ | |
| /* Date: august 22 1996 */ | |
| /*Assembler and interpreter of Pascal code*/ | |
| /*K. Jensen, N. Wirth, Ch. Jacobi, ETH May 76*/ | |
| #include "p2c.h" | |
| #include <math.h> | |
| /* Note for the implementation. | |
| =========================== | |
| This interpreter is written for the case where all the fundamental types | |
| take one storage unit. | |
| In an actual implementation, the handling of the sp pointer has to take | |
| into account the fact that the types may have lengths different from one: | |
| in push and pop operations the sp has to be increased and decreased not | |
| by 1, but by a number depending on the type concerned. | |
| However, where the number of units of storage has been computed by the | |
| compiler, the value must not be corrected, since the lengths of the types | |
| involved have already been taken into account. | |
| */ | |
| #define codemax 8650 | |
| #define pcmax 17500 | |
| #define maxstk 13650 /* size of variable store */ | |
| #define overi 13655 /* size of integer constant table = 5 */ | |
| #define overr 13660 /* size of real constant table = 5 */ | |
| #define overs 13730 /* size of set constant table = 70 */ | |
| #define overb 13820 | |
| #define overm 18000 | |
| #define maxstr 18001 | |
| #define largeint 26144 | |
| #define begincode 3 | |
| #define inputadr 5 | |
| #define outputadr 6 | |
| #define prdadr 7 | |
| #define prradr 8 | |
| #define duminst 62 | |
| typedef char bit4; | |
| typedef char bit6; | |
| typedef short bit20; | |
| typedef enum { | |
| undef, int_, reel, bool, sett, adr, mark_, car | |
| } datatype; | |
| typedef short address; | |
| typedef Char beta[25]; /*error message*/ | |
| typedef long settype[3]; | |
| typedef Char alfa_[10]; | |
| typedef struct _REC_code { | |
| /* the program */ | |
| unsigned op1 : 7, p1 : 4; | |
| signed int q1 : 16; | |
| unsigned op2 : 7, p2 : 4; | |
| short q2; | |
| } _REC_code; | |
| typedef union _REC_store { | |
| long vi; | |
| double vr; | |
| boolean vb; | |
| settype vs; | |
| Char vc; | |
| address va; | |
| /*address in store*/ | |
| long vm; | |
| } _REC_store; | |
| Static _REC_code code[codemax + 1]; | |
| Static short pc; /*program address register*/ | |
| Static bit6 op; | |
| Static bit4 p; | |
| Static bit20 q; /*instruction register*/ | |
| Static _REC_store store[overm + 1]; | |
| Static address mp, sp, np, ep; /* address registers */ | |
| /*mp points to beginning of a data segment | |
| sp points to top of the stack | |
| ep points to the maximum extent of the stack | |
| np points to top of the dynamically allocated area*/ | |
| Static boolean interpreting; | |
| Static _TEXT prd, prr; /*prd for read only, prr for write only */ | |
| Static alfa_ instr[128]; /* mnemonic instruction codes */ | |
| Static long cop[128]; | |
| Static alfa_ sptable[21]; /*standard functions and procedures*/ | |
| /*locally used for interpreting one instruction*/ | |
| Static address ad; | |
| Static boolean b; | |
| Static long i, i1, i2; | |
| #define maxlabel 1850 | |
| typedef enum { | |
| entered, defined_ | |
| } labelst; /*label situation*/ | |
| typedef short labelrg; | |
| /*label range*/ | |
| typedef struct labelrec { | |
| address val; | |
| labelst st; | |
| } labelrec; | |
| /* Local variables for load: */ | |
| struct LOC_load { | |
| address icp, rcp, scp, bcp, mcp; /*pointers to next free position*/ | |
| Char word[10]; | |
| Char ch; | |
| labelrec labeltab[maxlabel + 1]; | |
| address labelvalue; | |
| } ; | |
| Local void assemble(struct LOC_load *LINK); | |
| Local void init(struct LOC_load *LINK) | |
| { | |
| long i; | |
| labelrec *WITH; | |
| memcpy(instr[0], "lod ", sizeof(alfa_)); | |
| memcpy(instr[1], "ldo ", sizeof(alfa_)); | |
| memcpy(instr[2], "str ", sizeof(alfa_)); | |
| memcpy(instr[3], "sro ", sizeof(alfa_)); | |
| memcpy(instr[4], "lda ", sizeof(alfa_)); | |
| memcpy(instr[5], "lao ", sizeof(alfa_)); | |
| memcpy(instr[6], "sto ", sizeof(alfa_)); | |
| memcpy(instr[7], "ldc ", sizeof(alfa_)); | |
| memcpy(instr[8], "… ", sizeof(alfa_)); | |
| memcpy(instr[9], "ind ", sizeof(alfa_)); | |
| memcpy(instr[10], "inc ", sizeof(alfa_)); | |
| memcpy(instr[11], "mst ", sizeof(alfa_)); | |
| memcpy(instr[12], "cup ", sizeof(alfa_)); | |
| memcpy(instr[13], "ent ", sizeof(alfa_)); | |
| memcpy(instr[14], "ret ", sizeof(alfa_)); | |
| memcpy(instr[15], "csp ", sizeof(alfa_)); | |
| memcpy(instr[16], "ixa ", sizeof(alfa_)); | |
| memcpy(instr[17], "equ ", sizeof(alfa_)); | |
| memcpy(instr[18], "neq ", sizeof(alfa_)); | |
| memcpy(instr[19], "geq ", sizeof(alfa_)); | |
| memcpy(instr[20], "grt ", sizeof(alfa_)); | |
| memcpy(instr[21], "leq ", sizeof(alfa_)); | |
| memcpy(instr[22], "les ", sizeof(alfa_)); | |
| memcpy(instr[23], "ujp ", sizeof(alfa_)); | |
| memcpy(instr[24], "fjp ", sizeof(alfa_)); | |
| memcpy(instr[25], "xjp ", sizeof(alfa_)); | |
| memcpy(instr[26], "chk ", sizeof(alfa_)); | |
| memcpy(instr[27], "eof ", sizeof(alfa_)); | |
| memcpy(instr[28], "adi ", sizeof(alfa_)); | |
| memcpy(instr[29], "adr ", sizeof(alfa_)); | |
| memcpy(instr[30], "sbi ", sizeof(alfa_)); | |
| memcpy(instr[31], "sbr ", sizeof(alfa_)); | |
| memcpy(instr[32], "sgs ", sizeof(alfa_)); | |
| memcpy(instr[33], "flt ", sizeof(alfa_)); | |
| memcpy(instr[34], "flo ", sizeof(alfa_)); | |
| memcpy(instr[35], "trc ", sizeof(alfa_)); | |
| memcpy(instr[36], "ngi ", sizeof(alfa_)); | |
| memcpy(instr[37], "ngr ", sizeof(alfa_)); | |
| memcpy(instr[38], "sqi ", sizeof(alfa_)); | |
| memcpy(instr[39], "sqr ", sizeof(alfa_)); | |
| memcpy(instr[40], "abi ", sizeof(alfa_)); | |
| memcpy(instr[41], "abr ", sizeof(alfa_)); | |
| memcpy(instr[42], "not ", sizeof(alfa_)); | |
| memcpy(instr[43], "and ", sizeof(alfa_)); | |
| memcpy(instr[44], "ior ", sizeof(alfa_)); | |
| memcpy(instr[45], "dif ", sizeof(alfa_)); | |
| memcpy(instr[46], "int ", sizeof(alfa_)); | |
| memcpy(instr[47], "uni ", sizeof(alfa_)); | |
| memcpy(instr[48], "inn ", sizeof(alfa_)); | |
| memcpy(instr[49], "mod ", sizeof(alfa_)); | |
| memcpy(instr[50], "odd ", sizeof(alfa_)); | |
| memcpy(instr[51], "mpi ", sizeof(alfa_)); | |
| memcpy(instr[52], "mpr ", sizeof(alfa_)); | |
| memcpy(instr[53], "dvi ", sizeof(alfa_)); | |
| memcpy(instr[54], "dvr ", sizeof(alfa_)); | |
| memcpy(instr[55], "mov ", sizeof(alfa_)); | |
| memcpy(instr[56], "lca ", sizeof(alfa_)); | |
| memcpy(instr[57], "dec ", sizeof(alfa_)); | |
| memcpy(instr[58], "stp ", sizeof(alfa_)); | |
| memcpy(instr[59], "ord ", sizeof(alfa_)); | |
| memcpy(instr[60], "chr ", sizeof(alfa_)); | |
| memcpy(instr[61], "ujc ", sizeof(alfa_)); | |
| memcpy(sptable[0], "get ", sizeof(alfa_)); | |
| memcpy(sptable[1], "put ", sizeof(alfa_)); | |
| memcpy(sptable[2], "rst ", sizeof(alfa_)); | |
| memcpy(sptable[3], "rln ", sizeof(alfa_)); | |
| memcpy(sptable[4], "new ", sizeof(alfa_)); | |
| memcpy(sptable[5], "wln ", sizeof(alfa_)); | |
| memcpy(sptable[6], "wrs ", sizeof(alfa_)); | |
| memcpy(sptable[7], "eln ", sizeof(alfa_)); | |
| memcpy(sptable[8], "wri ", sizeof(alfa_)); | |
| memcpy(sptable[9], "wrr ", sizeof(alfa_)); | |
| memcpy(sptable[10], "wrc ", sizeof(alfa_)); | |
| memcpy(sptable[11], "rdi ", sizeof(alfa_)); | |
| memcpy(sptable[12], "rdr ", sizeof(alfa_)); | |
| memcpy(sptable[13], "rdc ", sizeof(alfa_)); | |
| memcpy(sptable[14], "sin ", sizeof(alfa_)); | |
| memcpy(sptable[15], "cos ", sizeof(alfa_)); | |
| memcpy(sptable[16], "exp ", sizeof(alfa_)); | |
| memcpy(sptable[17], "log ", sizeof(alfa_)); | |
| memcpy(sptable[18], "sqt ", sizeof(alfa_)); | |
| memcpy(sptable[19], "atn ", sizeof(alfa_)); | |
| memcpy(sptable[20], "sav ", sizeof(alfa_)); | |
| cop[0] = 105; | |
| cop[1] = 65; | |
| cop[2] = 70; | |
| cop[3] = 75; | |
| cop[6] = 80; | |
| cop[9] = 85; | |
| cop[10] = 90; | |
| cop[26] = 95; | |
| cop[57] = 100; | |
| pc = begincode; | |
| LINK->icp = maxstk + 1; | |
| LINK->rcp = overi + 1; | |
| LINK->scp = overr + 1; | |
| LINK->bcp = overs + 2; | |
| LINK->mcp = overb + 1; | |
| for (i = 0; i <= 9; i++) | |
| LINK->word[i] = ' '; | |
| for (i = 0; i <= maxlabel; i++) { | |
| WITH = &LINK->labeltab[i]; | |
| WITH->val = -1; | |
| WITH->st = entered; | |
| } | |
| if (*prd.name != '\0') { | |
| if (prd.f != NULL) | |
| prd.f = freopen(prd.name, "r", prd.f); | |
| else | |
| prd.f = fopen(prd.name, "r"); | |
| } else | |
| rewind(prd.f); | |
| if (prd.f == NULL) | |
| _EscIO(FileNotFound); | |
| RESETBUF(prd.f, Char); | |
| } /*init*/ | |
| Local void errorl(Char *string, struct LOC_load *LINK) | |
| { | |
| /*error in loading*/ | |
| printf("\n%.25s", string); | |
| _Escape(0); | |
| } /*errorl*/ | |
| Local void update(labelrg x, struct LOC_load *LINK) | |
| { | |
| /*when a label definition lx is found*/ | |
| short curr, succ; | |
| /*resp. current element and successor element | |
| of a list of future references*/ | |
| boolean endlist; | |
| _REC_code *WITH; | |
| if (LINK->labeltab[x].st == defined_) { | |
| errorl(" duplicated label\t ", LINK); | |
| return; | |
| } | |
| if (LINK->labeltab[x].val != -1) { /*forward reference(s)*/ | |
| curr = LINK->labeltab[x].val; | |
| endlist = false; | |
| while (!endlist) { | |
| WITH = &code[curr / 2]; | |
| if (curr & 1) { | |
| succ = WITH->q2; | |
| WITH->q2 = LINK->labelvalue; | |
| } else { | |
| succ = WITH->q1; | |
| WITH->q1 = LINK->labelvalue; | |
| } | |
| if (succ == -1) | |
| endlist = true; | |
| else | |
| curr = succ; | |
| } | |
| } | |
| LINK->labeltab[x].st = defined_; | |
| LINK->labeltab[x].val = LINK->labelvalue; | |
| } /*update*/ | |
| Local void generate(struct LOC_load *LINK) | |
| { | |
| /*generate segment of code*/ | |
| long x; /* label number */ | |
| boolean again; | |
| again = true; | |
| while (again) { | |
| LINK->ch = getc(prd.f); /* first character of line*/ | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| switch (LINK->ch) { | |
| case 'i': | |
| fscanf(prd.f, "%*[^\n]"); | |
| getc(prd.f); | |
| break; | |
| case 'l': | |
| fscanf(prd.f, "%ld", &x); | |
| if (!P_eoln(prd.f)) { | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| } | |
| if (LINK->ch == '=') | |
| fscanf(prd.f, "%hd", &LINK->labelvalue); | |
| else | |
| LINK->labelvalue = pc; | |
| update(x, LINK); | |
| fscanf(prd.f, "%*[^\n]"); | |
| getc(prd.f); | |
| break; | |
| case 'q': | |
| again = false; | |
| fscanf(prd.f, "%*[^\n]"); | |
| getc(prd.f); | |
| break; | |
| case ' ': | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| assemble(LINK); | |
| break; | |
| } | |
| } | |
| } /*generate*/ | |
| /* Local variables for assemble: */ | |
| struct LOC_assemble { | |
| struct LOC_load *LINK; | |
| /*goto 1 for instructions without code generation*/ | |
| alfa_ name; | |
| } ; | |
| Local void lookup(labelrg x, struct LOC_assemble *LINK) | |
| { | |
| /* search in label table*/ | |
| switch (LINK->LINK->labeltab[x].st) { | |
| case entered: | |
| q = LINK->LINK->labeltab[x].val; | |
| LINK->LINK->labeltab[x].val = pc; | |
| break; | |
| case defined_: | |
| q = LINK->LINK->labeltab[x].val; | |
| break; | |
| }/*case label..*/ | |
| } /*lookup*/ | |
| Local void labelsearch(struct LOC_assemble *LINK) | |
| { | |
| labelrg x; | |
| while ((LINK->LINK->ch != 'l') & (!P_eoln(prd.f))) { | |
| LINK->LINK->ch = getc(prd.f); | |
| if (LINK->LINK->ch == '\n') | |
| LINK->LINK->ch = ' '; | |
| } | |
| fscanf(prd.f, "%hd", &x); | |
| lookup(x, LINK); | |
| } /*labelsearch*/ | |
| Local void getname(struct LOC_assemble *LINK) | |
| { | |
| LINK->LINK->word[0] = LINK->LINK->ch; | |
| LINK->LINK->word[1] = getc(prd.f); | |
| LINK->LINK->word[2] = getc(prd.f); | |
| if (LINK->LINK->word[1] == '\n') | |
| LINK->LINK->word[1] = ' '; | |
| if (LINK->LINK->word[2] == '\n') | |
| LINK->LINK->word[2] = ' '; | |
| if (!P_eoln(prd.f)) { | |
| LINK->LINK->ch = getc(prd.f); /*next character*/ | |
| if (LINK->LINK->ch == '\n') | |
| LINK->LINK->ch = ' '; | |
| } | |
| memcpy(LINK->name, LINK->LINK->word, sizeof(alfa_)); | |
| } /*getname*/ | |
| Local void typesymbol(struct LOC_assemble *LINK) | |
| { | |
| long i; | |
| /*typesymbol*/ | |
| if (LINK->LINK->ch == 'i') | |
| return; | |
| switch (LINK->LINK->ch) { | |
| case 'a': | |
| i = 0; | |
| break; | |
| case 'r': | |
| i = 1; | |
| break; | |
| case 's': | |
| i = 2; | |
| break; | |
| case 'b': | |
| i = 3; | |
| break; | |
| case 'c': | |
| i = 4; | |
| break; | |
| } | |
| op = cop[op] + i; | |
| } | |
| Local void assemble(struct LOC_load *LINK) | |
| { | |
| /*translate symbolic code into machine code and store*/ | |
| struct LOC_assemble V; | |
| double r; | |
| settype s; | |
| long i, s1, lb, ub; | |
| int TEMP; | |
| _REC_code *WITH; | |
| V.LINK = LINK; | |
| p = 0; | |
| q = 0; | |
| op = 0; | |
| getname(&V); | |
| memcpy(instr[duminst], V.name, sizeof(alfa_)); | |
| while (strncmp(instr[op], V.name, sizeof(alfa_))) | |
| op++; | |
| if (op == duminst) | |
| errorl(" illegal instruction ", LINK); | |
| switch (op) { /* get parameters p,q */ | |
| /*equ,neq,geq,grt,leq,les*/ | |
| case 17: | |
| case 18: | |
| case 19: | |
| case 20: | |
| case 21: | |
| case 22: | |
| switch (LINK->ch) { | |
| case 'a': /*p = 0*/ | |
| break; | |
| case 'i': | |
| p = 1; | |
| break; | |
| case 'r': | |
| p = 2; | |
| break; | |
| case 'b': | |
| p = 3; | |
| break; | |
| case 's': | |
| p = 4; | |
| break; | |
| case 'c': | |
| p = 6; | |
| break; | |
| case 'm': | |
| p = 5; | |
| fscanf(prd.f, "%hd", &q); | |
| break; | |
| } | |
| break; | |
| /*lod,str*/ | |
| case 0: | |
| case 2: | |
| typesymbol(&V); | |
| fscanf(prd.f, "%d%hd", &TEMP, &q); | |
| p = TEMP; | |
| break; | |
| case 4: /*lda*/ | |
| fscanf(prd.f, "%d%hd", &TEMP, &q); | |
| p = TEMP; | |
| break; | |
| case 12: /*cup*/ | |
| fscanf(prd.f, "%d", &TEMP); | |
| p = TEMP; | |
| labelsearch(&V); | |
| break; | |
| case 11: /*mst*/ | |
| fscanf(prd.f, "%d", &TEMP); | |
| p = TEMP; | |
| break; | |
| case 14: /*ret*/ | |
| switch (LINK->ch) { | |
| case 'p': | |
| p = 0; | |
| break; | |
| case 'i': | |
| p = 1; | |
| break; | |
| case 'r': | |
| p = 2; | |
| break; | |
| case 'c': | |
| p = 3; | |
| break; | |
| case 'b': | |
| p = 4; | |
| break; | |
| case 'a': | |
| p = 5; | |
| break; | |
| } | |
| break; | |
| /*lao,ixa,mov*/ | |
| case 5: | |
| case 16: | |
| case 55: | |
| fscanf(prd.f, "%hd", &q); | |
| break; | |
| /*ldo,sro,ind,inc,dec*/ | |
| case 1: | |
| case 3: | |
| case 9: | |
| case 10: | |
| case 57: | |
| typesymbol(&V); | |
| fscanf(prd.f, "%hd", &q); | |
| break; | |
| /*ujp,fjp,xjp*/ | |
| case 23: | |
| case 24: | |
| case 25: | |
| labelsearch(&V); | |
| break; | |
| case 13: /*ent*/ | |
| fscanf(prd.f, "%d", &TEMP); | |
| p = TEMP; | |
| labelsearch(&V); | |
| break; | |
| case 15: /*csp*/ | |
| for (i = 1; i <= 9; i++) { | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| } | |
| getname(&V); | |
| while (strncmp(V.name, sptable[q], sizeof(alfa_))) | |
| q++; | |
| break; | |
| case 7: /*ldc*/ | |
| switch (LINK->ch) { /*get q*/ | |
| case 'i': | |
| p = 1; | |
| fscanf(prd.f, "%ld", &i); | |
| if (labs(i) >= largeint) { | |
| op = 8; | |
| store[LINK->icp].vi = i; | |
| q = maxstk; | |
| do { | |
| q++; | |
| } while (store[q].vi != i); | |
| if (q == LINK->icp) { | |
| LINK->icp++; | |
| if (LINK->icp == overi) | |
| errorl(" integer table overflow ", LINK); | |
| } | |
| } else | |
| q = i; | |
| break; | |
| case 'r': | |
| op = 8; | |
| p = 2; | |
| fscanf(prd.f, "%lg", &r); | |
| store[LINK->rcp].vr = r; | |
| q = overi; | |
| do { | |
| q++; | |
| } while (store[q].vr != r); | |
| if (q == LINK->rcp) { | |
| LINK->rcp++; | |
| if (LINK->rcp == overr) | |
| errorl(" real table overflow ", LINK); | |
| } | |
| break; | |
| case 'n': /*p,q = 0*/ | |
| break; | |
| case 'b': | |
| p = 3; | |
| fscanf(prd.f, "%hd", &q); | |
| break; | |
| case 'c': | |
| p = 6; | |
| do { | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| } while (LINK->ch == ' '); | |
| if (LINK->ch != '\'') | |
| errorl(" illegal character ", LINK); | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| q = LINK->ch; | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| if (LINK->ch != '\'') | |
| errorl(" illegal character ", LINK); | |
| break; | |
| case '(': | |
| op = 8; | |
| p = 4; | |
| P_expset(s, 0); | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| while (LINK->ch != ')') { | |
| fscanf(prd.f, "%ld%c", &s1, &LINK->ch); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| P_addset(s, s1); | |
| } | |
| P_setcpy(store[LINK->scp].vs, s); | |
| q = overr; | |
| do { | |
| q++; | |
| } while (!P_setequal(store[q].vs, s)); | |
| if (q == LINK->scp) { | |
| LINK->scp++; | |
| if (LINK->scp == overs) | |
| errorl(" set table overflow ", LINK); | |
| } | |
| break; | |
| }/*case*/ | |
| break; | |
| case 26: /*chk*/ | |
| typesymbol(&V); | |
| fscanf(prd.f, "%ld%ld", &lb, &ub); | |
| if (op == 95) | |
| q = lb; | |
| else { | |
| store[LINK->bcp – 1].vi = lb; | |
| store[LINK->bcp].vi = ub; | |
| q = overs; | |
| do { | |
| q += 2; | |
| } while (store[q – 1].vi != lb || store[q].vi != ub); | |
| if (q == LINK->bcp) { | |
| LINK->bcp += 2; | |
| if (LINK->bcp == overb) | |
| errorl(" boundary table overflow ", LINK); | |
| } | |
| } | |
| break; | |
| case 56: /*lca*/ | |
| if (LINK->mcp + 16 >= overm) | |
| errorl(" multiple table overflow ", LINK); | |
| LINK->mcp += 16; | |
| q = LINK->mcp; | |
| for (i = 0; i <= 15; i++) { /*stringlgth*/ | |
| LINK->ch = getc(prd.f); | |
| if (LINK->ch == '\n') | |
| LINK->ch = ' '; | |
| store[q + i].vc = LINK->ch; | |
| } | |
| break; | |
| case 6: /*sto*/ | |
| typesymbol(&V); | |
| break; | |
| case 27: | |
| case 28: | |
| case 29: | |
| case 30: | |
| case 31: | |
| case 32: | |
| case 33: | |
| case 34: | |
| case 35: | |
| case 36: | |
| case 37: | |
| case 38: | |
| case 39: | |
| case 40: | |
| case 41: | |
| case 42: | |
| case 43: | |
| case 44: | |
| case 45: | |
| case 46: | |
| case 47: | |
| case 48: | |
| case 49: | |
| case 50: | |
| case 51: | |
| case 52: | |
| case 53: | |
| case 54: | |
| case 58: | |
| break; | |
| /*ord,chr*/ | |
| case 59: | |
| case 60: | |
| goto _L1; | |
| break; | |
| case 61: /*ujc*/ | |
| break; | |
| /*must have same length as ujp*/ | |
| }/*case*/ | |
| WITH = &code[pc / 2]; | |
| /* store instruction */ | |
| if (pc & 1) { | |
| WITH->op2 = op; | |
| WITH->p2 = p; | |
| WITH->q2 = q; | |
| } else { | |
| WITH->op1 = op; | |
| WITH->p1 = p; | |
| WITH->q1 = q; | |
| } | |
| pc++; | |
| _L1: | |
| fscanf(prd.f, "%*[^\n]"); | |
| getc(prd.f); | |
| } /*assemble*/ | |
| /*——————————————————————–*/ | |
| Static void load(void) | |
| { | |
| struct LOC_load V; | |
| init(&V); | |
| generate(&V); | |
| pc = 0; | |
| generate(&V); | |
| } /*load*/ | |
| #undef maxlabel | |
| /* Local variables for pmd: */ | |
| struct LOC_pmd { | |
| long s, i; | |
| } ; | |
| Local void pt(struct LOC_pmd *LINK) | |
| { | |
| printf("%6ld", LINK->s); | |
| if (labs(store[LINK->s].vi) < LONG_MAX) | |
| printf("%12ld", store[LINK->s].vi); | |
| else | |
| printf("too big "); | |
| LINK->s–; | |
| LINK->i++; | |
| if (LINK->i == 4) { | |
| putchar('\n'); | |
| LINK->i = 0; | |
| } | |
| } /*pt*/ | |
| /*————————————————————————*/ | |
| Static void pmd(void) | |
| { | |
| struct LOC_pmd V; | |
| printf(" pc =%5d op =%3d sp =%5d mp =%5d np =%5d\n", | |
| pc – 1, op, sp, mp, np); | |
| printf("————————————–\n"); | |
| V.s = sp; | |
| V.i = 0; | |
| while (V.s >= 0) | |
| pt(&V); | |
| V.s = maxstk; | |
| while (V.s >= np) | |
| pt(&V); | |
| } /*pmd*/ | |
| Static jmp_buf _JL1; | |
| Static void errori(Char *string) | |
| { | |
| printf("\n%.25s\n", string); | |
| pmd(); | |
| longjmp(_JL1, 1); | |
| } /*errori*/ | |
| Static address base(long ld) | |
| { | |
| address ad; | |
| ad = mp; | |
| while (ld > 0) { | |
| ad = store[ad + 1].vm; | |
| ld–; | |
| } | |
| return ad; | |
| } /*base*/ | |
| Static void compare(void) | |
| { | |
| /*comparing is only correct if result by comparing integers will be*/ | |
| i1 = store[sp].va; | |
| i2 = store[sp + 1].va; | |
| i = 0; | |
| b = true; | |
| while (b && i != q) { | |
| if (store[i1 + i].vi == store[i2 + i].vi) | |
| i++; | |
| else | |
| b = false; | |
| } | |
| } /*compare*/ | |
| Local void readi(_TEXT *f) | |
| { | |
| address ad; | |
| ad = store[sp – 1].va; | |
| fscanf(f->f, "%ld", &store[ad].vi); | |
| store[store[sp].va].vc = P_peek(f->f); | |
| sp -= 2; | |
| } /*readi*/ | |
| Local void readr(_TEXT *f) | |
| { | |
| address ad; | |
| ad = store[sp – 1].va; | |
| fscanf(f->f, "%lg", &store[ad].vr); | |
| store[store[sp].va].vc = P_peek(f->f); | |
| sp -= 2; | |
| } /*readr*/ | |
| Local void readc(_TEXT *f) | |
| { | |
| Char c; | |
| address ad; | |
| c = getc(f->f); | |
| if (c == '\n') | |
| c = ' '; | |
| ad = store[sp – 1].va; | |
| store[ad].vc = c; | |
| store[store[sp].va].vc = P_peek(f->f); | |
| store[store[sp].va].vi = P_peek(f->f); | |
| sp -= 2; | |
| } /*readc*/ | |
| Local void writestr(_TEXT *f) | |
| { | |
| long i, j, k; | |
| address ad; | |
| long FORLIM; | |
| ad = store[sp – 3].va; | |
| k = store[sp – 2].vi; | |
| j = store[sp – 1].vi; | |
| /* j and k are numbers of characters */ | |
| if (k > j) { | |
| FORLIM = k – j; | |
| for (i = 1; i <= FORLIM; i++) | |
| putc(' ', f->f); | |
| } else | |
| j = k; | |
| for (i = 0; i < j; i++) | |
| putc(store[ad + i].vc, f->f); | |
| sp -= 4; | |
| } /*writestr*/ | |
| Local void getfile(_TEXT *f) | |
| { | |
| address ad; | |
| ad = store[sp].va; | |
| getc(f->f); | |
| store[ad].vc = P_peek(f->f); | |
| sp–; | |
| } /*getfile*/ | |
| Local void putfile(_TEXT *f) | |
| { | |
| address ad; | |
| ad = store[sp].va; | |
| putc(store[ad].vc, f->f); | |
| sp–; | |
| } /*putfile*/ | |
| Static void callsp(void) | |
| { | |
| boolean line; | |
| _TEXT TEMP; | |
| switch (q) { | |
| case 0: /*get*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| TEMP.f = stdin; | |
| *TEMP.name = '\0'; | |
| getfile(&TEMP); | |
| break; | |
| case 6: | |
| errori(" get on output file "); | |
| break; | |
| case 7: | |
| getfile(&prd); | |
| break; | |
| case 8: | |
| errori(" get on prr file\t "); | |
| break; | |
| } | |
| break; | |
| case 1: /*put*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| errori(" put on read file\t "); | |
| break; | |
| case 6: | |
| TEMP.f = stdout; | |
| *TEMP.name = '\0'; | |
| putfile(&TEMP); | |
| break; | |
| case 7: | |
| errori(" put on prd file\t "); | |
| break; | |
| case 8: | |
| putfile(&prr); | |
| break; | |
| } | |
| break; | |
| case 2: /*rst*/ | |
| /*for testphase*/ | |
| np = store[sp].va; | |
| sp–; | |
| break; | |
| case 3: /*rln*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| scanf("%*[^\n]"); | |
| getchar(); | |
| store[inputadr].vc = P_peek(stdin); | |
| break; | |
| case 6: | |
| errori(" readln on output file "); | |
| break; | |
| case 7: | |
| scanf("%*[^\n]"); | |
| getchar(); | |
| store[inputadr].vc = P_peek(stdin); | |
| break; | |
| case 8: | |
| errori(" readln on prr file "); | |
| break; | |
| } | |
| sp–; | |
| break; | |
| case 4: /*new*/ | |
| ad = np – store[sp].va; | |
| /*top of stack gives the length in units of storage */ | |
| if (ad <= ep) | |
| errori(" store overflow\t "); | |
| np = ad; | |
| ad = store[sp – 1].va; | |
| store[ad].va = np; | |
| sp -= 2; | |
| break; | |
| case 5: /*wln*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| errori(" writeln on input file "); | |
| break; | |
| case 6: | |
| putchar('\n'); | |
| break; | |
| case 7: | |
| errori(" writeln on prd file "); | |
| break; | |
| case 8: | |
| putc('\n', prr.f); | |
| break; | |
| } | |
| sp–; | |
| break; | |
| case 6: /*wrs*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| errori(" write on input file "); | |
| break; | |
| case 6: | |
| TEMP.f = stdout; | |
| *TEMP.name = '\0'; | |
| writestr(&TEMP); | |
| break; | |
| case 7: | |
| errori(" write on prd file "); | |
| break; | |
| case 8: | |
| writestr(&prr); | |
| break; | |
| } | |
| break; | |
| case 7: /*eln*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| line = P_eoln(stdin); | |
| break; | |
| case 6: | |
| errori(" eoln output file\t "); | |
| break; | |
| case 7: | |
| line = P_eoln(prd.f); | |
| break; | |
| case 8: | |
| errori(" eoln on prr file\t "); | |
| break; | |
| } | |
| store[sp].vb = line; | |
| break; | |
| case 8: /*wri*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| errori(" write on input file "); | |
| break; | |
| case 6: | |
| printf("%*ld", (int)store[sp – 1].vi, store[sp – 2].vi); | |
| break; | |
| case 7: | |
| errori(" write on prd file "); | |
| break; | |
| case 8: | |
| fprintf(prr.f, "%*ld", (int)store[sp – 1].vi, store[sp – 2].vi); | |
| break; | |
| } | |
| sp -= 3; | |
| break; | |
| case 9: /*wrr*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| errori(" write on input file "); | |
| break; | |
| case 6: | |
| printf("% .*E", P_max((int)store[sp – 1].vi – 7, 1), store[sp – 2].vr); | |
| break; | |
| case 7: | |
| errori(" write on prd file "); | |
| break; | |
| case 8: | |
| fprintf(prr.f, "% .*E", | |
| P_max((int)store[sp – 1].vi – 7, 1), store[sp – 2].vr); | |
| break; | |
| } | |
| sp -= 3; | |
| break; | |
| case 10: /*wrc*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| errori(" write on input file "); | |
| break; | |
| case 6: | |
| printf("%*c", (int)store[sp – 1].vi, store[sp – 2].vc); | |
| break; | |
| case 7: | |
| errori(" write on prd file "); | |
| break; | |
| case 8: | |
| fprintf(prr.f, "%*c", (int)store[sp – 1].vi, (Char)store[sp – 2].vi); | |
| break; | |
| } | |
| sp -= 3; | |
| break; | |
| case 11: /*rdi*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| TEMP.f = stdin; | |
| *TEMP.name = '\0'; | |
| readi(&TEMP); | |
| break; | |
| case 6: | |
| errori(" read on output file "); | |
| break; | |
| case 7: | |
| readi(&prd); | |
| break; | |
| case 8: | |
| errori(" read on prr file\t "); | |
| break; | |
| } | |
| break; | |
| case 12: /*rdr*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| TEMP.f = stdin; | |
| *TEMP.name = '\0'; | |
| readr(&TEMP); | |
| break; | |
| case 6: | |
| errori(" read on output file "); | |
| break; | |
| case 7: | |
| readr(&prd); | |
| break; | |
| case 8: | |
| errori(" read on prr file\t "); | |
| break; | |
| } | |
| break; | |
| case 13: /*rdc*/ | |
| switch (store[sp].va) { | |
| case 5: | |
| TEMP.f = stdin; | |
| *TEMP.name = '\0'; | |
| readc(&TEMP); | |
| break; | |
| case 6: | |
| errori(" read on output file "); | |
| break; | |
| case 7: | |
| readc(&prd); | |
| break; | |
| case 8: | |
| errori(" read on prr file\t "); | |
| break; | |
| } | |
| break; | |
| case 14: /*sin*/ | |
| store[sp].vr = sin(store[sp].vr); | |
| break; | |
| case 15: /*cos*/ | |
| store[sp].vr = cos(store[sp].vr); | |
| break; | |
| case 16: /*exp*/ | |
| store[sp].vr = exp(store[sp].vr); | |
| break; | |
| case 17: /*log*/ | |
| store[sp].vr = log(store[sp].vr); | |
| break; | |
| case 18: /*sqt*/ | |
| store[sp].vr = sqrt(store[sp].vr); | |
| break; | |
| case 19: /*atn*/ | |
| store[sp].vr = atan(store[sp].vr); | |
| break; | |
| case 20: /*sav*/ | |
| ad = store[sp].va; | |
| store[ad].va = np; | |
| sp–; | |
| break; | |
| }/*case q*/ | |
| } /*callsp*/ | |
| int main(int argc, Char *argv[]) | |
| { /* main */ | |
| _REC_code *WITH; | |
| settype SET; | |
| long TEMP; | |
| double TEMP1; | |
| long FORLIM; | |
| PASCAL_MAIN(argc, argv); | |
| if (setjmp(_JL1)) | |
| goto _L1; | |
| prr.f = NULL; | |
| strcpy(prr.name, "prr"); | |
| prd.f = NULL; | |
| strcpy(prd.name, "prd"); | |
| if (*prr.name != '\0') { | |
| if (prr.f != NULL) | |
| prr.f = freopen(prr.name, "w", prr.f); | |
| else | |
| prr.f = fopen(prr.name, "w"); | |
| } else { | |
| if (prr.f != NULL) | |
| rewind(prr.f); | |
| else | |
| prr.f = tmpfile(); | |
| } | |
| if (prr.f == NULL) | |
| _EscIO(FileNotFound); | |
| SETUPBUF(prr.f, Char); | |
| load(); /* assembles and stores code */ | |
| /* writeln(output); for testing */ | |
| pc = 0; | |
| sp = -1; | |
| mp = 0; | |
| np = maxstk + 1; | |
| ep = 5; | |
| /* store[inputadr].vc = P_peek(stdin); */ | |
| store[inputadr].vc = ' '; | |
| store[prdadr].vc = P_peek(prd.f); | |
| interpreting = true; | |
| while (interpreting) { | |
| WITH = &code[pc / 2]; | |
| /*fetch*/ | |
| if (pc & 1) { | |
| op = WITH->op2; | |
| p = WITH->p2; | |
| q = WITH->q2; | |
| } else { | |
| op = WITH->op1; | |
| p = WITH->p1; | |
| q = WITH->q1; | |
| } | |
| pc++; | |
| /*execute*/ | |
| switch (op) { | |
| case 105: | |
| case 106: | |
| case 107: | |
| case 108: | |
| case 109: | |
| case 0: /*lod*/ | |
| ad = base(p) + q; | |
| sp++; | |
| store[sp] = store[ad]; | |
| break; | |
| case 65: | |
| case 66: | |
| case 67: | |
| case 68: | |
| case 69: | |
| case 1: /*ldo*/ | |
| sp++; | |
| store[sp] = store[q]; | |
| break; | |
| case 70: | |
| case 71: | |
| case 72: | |
| case 73: | |
| case 74: | |
| case 2: /*str*/ | |
| store[base(p) + q] = store[sp]; | |
| sp–; | |
| break; | |
| case 75: | |
| case 76: | |
| case 77: | |
| case 78: | |
| case 79: | |
| case 3: /*sro*/ | |
| store[q] = store[sp]; | |
| sp–; | |
| break; | |
| case 4: /*lda*/ | |
| sp++; | |
| store[sp].va = base(p) + q; | |
| break; | |
| case 5: /*lao*/ | |
| sp++; | |
| store[sp].va = q; | |
| break; | |
| case 80: | |
| case 81: | |
| case 82: | |
| case 83: | |
| case 84: | |
| case 6: /*sto*/ | |
| store[store[sp – 1].va] = store[sp]; | |
| sp -= 2; | |
| break; | |
| case 7: /*ldc*/ | |
| sp++; | |
| if (p == 1) | |
| store[sp].vi = q; | |
| else { | |
| if (p == 6) | |
| store[sp].vc = q; | |
| else { | |
| if (p == 3) | |
| store[sp].vb = (q == 1); | |
| else /* load nil */ | |
| store[sp].va = maxstr; | |
| } | |
| } | |
| break; | |
| case 8: /*lci*/ | |
| sp++; | |
| store[sp] = store[q]; | |
| break; | |
| case 85: | |
| case 86: | |
| case 87: | |
| case 88: | |
| case 89: | |
| case 9: /*ind*/ | |
| ad = store[sp].va + q; | |
| /* q is a number of storage units */ | |
| store[sp] = store[ad]; | |
| break; | |
| case 90: | |
| case 91: | |
| case 92: | |
| case 93: | |
| case 94: | |
| case 10: /*inc*/ | |
| store[sp].vi += q; | |
| break; | |
| case 11: /*mst*/ | |
| /*p=level of calling procedure minus level of called | |
| procedure + 1; set dl and sl, increment sp*/ | |
| /* then length of this element is | |
| max(intsize,realsize,boolsize,charsize,ptrsize */ | |
| store[sp + 2].vm = base(p); | |
| /* the length of this element is ptrsize */ | |
| store[sp + 3].vm = mp; | |
| /* idem */ | |
| store[sp + 4].vm = ep; | |
| /* idem */ | |
| sp += 5; | |
| break; | |
| case 12: /*cup*/ | |
| /*p=no of locations for parameters, q=entry point*/ | |
| mp = sp – p – 4; | |
| store[mp + 4].vm = pc; | |
| pc = q; | |
| break; | |
| case 13: /*ent*/ | |
| if (p == 1) { | |
| sp = mp + q; /*q = length of dataseg*/ | |
| if (sp > np) | |
| errori(" store overflow\t "); | |
| } else { | |
| ep = sp + q; | |
| if (ep > np) | |
| errori(" store overflow\t "); | |
| } | |
| break; | |
| /*q = max space required on stack*/ | |
| case 14: /*ret*/ | |
| switch (p) { | |
| case 0: | |
| sp = mp – 1; | |
| break; | |
| case 1: | |
| case 2: | |
| case 3: | |
| case 4: | |
| case 5: | |
| sp = mp; | |
| break; | |
| } | |
| pc = store[mp + 4].vm; | |
| ep = store[mp + 3].vm; | |
| mp = store[mp + 2].vm; | |
| break; | |
| case 15: /*csp*/ | |
| callsp(); | |
| break; | |
| case 16: /*ixa*/ | |
| i = store[sp].vi; | |
| sp–; | |
| store[sp].va += q * i; | |
| break; | |
| case 17: /*equ*/ | |
| sp–; | |
| switch (p) { | |
| case 1: | |
| store[sp].vb = (store[sp].vi == store[sp + 1].vi); | |
| break; | |
| case 0: | |
| store[sp].vb = (store[sp].va == store[sp + 1].va); | |
| break; | |
| case 6: | |
| store[sp].vb = (store[sp].vc == store[sp + 1].vc); | |
| break; | |
| case 2: | |
| store[sp].vb = (store[sp].vr == store[sp + 1].vr); | |
| break; | |
| case 3: | |
| store[sp].vb = (store[sp].vb == store[sp + 1].vb); | |
| break; | |
| case 4: | |
| store[sp].vb = P_setequal(store[sp].vs, store[sp + 1].vs); | |
| break; | |
| case 5: | |
| compare(); | |
| store[sp].vb = b; | |
| break; | |
| }/*case p*/ | |
| break; | |
| case 18: /*neq*/ | |
| sp–; | |
| switch (p) { | |
| case 0: | |
| store[sp].vb = (store[sp].va != store[sp + 1].va); | |
| break; | |
| case 1: | |
| store[sp].vb = (store[sp].vi != store[sp + 1].vi); | |
| break; | |
| case 6: | |
| store[sp].vb = (store[sp].vc != store[sp + 1].vc); | |
| break; | |
| case 2: | |
| store[sp].vb = (store[sp].vr != store[sp + 1].vr); | |
| break; | |
| case 3: | |
| store[sp].vb = (store[sp].vb != store[sp + 1].vb); | |
| break; | |
| case 4: | |
| store[sp].vb = !P_setequal(store[sp].vs, store[sp + 1].vs); | |
| break; | |
| case 5: | |
| compare(); | |
| store[sp].vb = !b; | |
| break; | |
| }/*case p*/ | |
| break; | |
| case 19: /*geq*/ | |
| sp–; | |
| switch (p) { | |
| case 0: | |
| errori(" <,<=,>,>= for address "); | |
| break; | |
| case 1: | |
| store[sp].vb = (store[sp].vi >= store[sp + 1].vi); | |
| break; | |
| case 6: | |
| store[sp].vb = (store[sp].vc >= store[sp + 1].vc); | |
| break; | |
| case 2: | |
| store[sp].vb = (store[sp].vr >= store[sp + 1].vr); | |
| break; | |
| case 3: | |
| store[sp].vb = (store[sp].vb >= store[sp + 1].vb); | |
| break; | |
| case 4: | |
| store[sp].vb = P_subset(store[sp + 1].vs, store[sp].vs); | |
| break; | |
| case 5: | |
| compare(); | |
| store[sp].vb = (b || store[i1 + i].vi >= store[i2 + i].vi); | |
| break; | |
| }/*case p*/ | |
| break; | |
| case 20: /*grt*/ | |
| sp–; | |
| switch (p) { | |
| case 0: | |
| errori(" <,<=,>,>= for address "); | |
| break; | |
| case 1: | |
| store[sp].vb = (store[sp].vi > store[sp + 1].vi); | |
| break; | |
| case 6: | |
| store[sp].vb = (store[sp].vc > store[sp + 1].vc); | |
| break; | |
| case 2: | |
| store[sp].vb = (store[sp].vr > store[sp + 1].vr); | |
| break; | |
| case 3: | |
| store[sp].vb = (store[sp].vb > store[sp + 1].vb); | |
| break; | |
| case 4: | |
| errori(" set inclusion\t "); | |
| break; | |
| case 5: | |
| compare(); | |
| store[sp].vb = (!b && store[i1 + i].vi > store[i2 + i].vi); | |
| break; | |
| }/*case p*/ | |
| break; | |
| case 21: /*leq*/ | |
| sp–; | |
| switch (p) { | |
| case 0: | |
| errori(" <,<=,>,>= for address "); | |
| break; | |
| case 1: | |
| store[sp].vb = (store[sp].vi <= store[sp + 1].vi); | |
| break; | |
| case 6: | |
| store[sp].vb = (store[sp].vc <= store[sp + 1].vc); | |
| break; | |
| case 2: | |
| store[sp].vb = (store[sp].vr <= store[sp + 1].vr); | |
| break; | |
| case 3: | |
| store[sp].vb = (store[sp].vb <= store[sp + 1].vb); | |
| break; | |
| case 4: | |
| store[sp].vb = P_subset(store[sp].vs, store[sp + 1].vs); | |
| break; | |
| case 5: | |
| compare(); | |
| store[sp].vb = (b || store[i1 + i].vi <= store[i2 + i].vi); | |
| break; | |
| }/*case p*/ | |
| break; | |
| case 22: /*les*/ | |
| sp–; | |
| switch (p) { | |
| case 0: | |
| errori(" <,<=,>,>= for address "); | |
| break; | |
| case 1: | |
| store[sp].vb = (store[sp].vi < store[sp + 1].vi); | |
| break; | |
| case 6: | |
| store[sp].vb = (store[sp].vc < store[sp + 1].vc); | |
| break; | |
| case 2: | |
| store[sp].vb = (store[sp].vr < store[sp + 1].vr); | |
| break; | |
| case 3: | |
| store[sp].vb = (store[sp].vb < store[sp + 1].vb); | |
| break; | |
| case 5: | |
| compare(); | |
| store[sp].vb = (!b && store[i1 + i].vi < store[i2 + i].vi); | |
| break; | |
| }/*case p*/ | |
| break; | |
| case 23: /*ujp*/ | |
| pc = q; | |
| break; | |
| case 24: /*fjp*/ | |
| if (!store[sp].vb) | |
| pc = q; | |
| sp–; | |
| break; | |
| case 25: /*xjp*/ | |
| pc = store[sp].vi + q; | |
| sp–; | |
| break; | |
| case 95: /*chka*/ | |
| if (store[sp].va < np || store[sp].va > maxstr – q) | |
| errori(" bad pointer value "); | |
| break; | |
| case 96: | |
| case 97: | |
| case 98: | |
| case 99: | |
| case 26: /*chk*/ | |
| if (store[sp].vi < store[q – 1].vi || store[sp].vi > store[q].vi) | |
| errori(" value out of range "); | |
| break; | |
| case 27: /*eof*/ | |
| i = store[sp].vi; | |
| if (i == inputadr) | |
| store[sp].vb = P_eof(stdin); | |
| else | |
| errori(" code in error\t "); | |
| break; | |
| case 28: /*adi*/ | |
| sp–; | |
| store[sp].vi += store[sp + 1].vi; | |
| break; | |
| case 29: /*adr*/ | |
| sp–; | |
| store[sp].vr += store[sp + 1].vr; | |
| break; | |
| case 30: /*sbi*/ | |
| sp–; | |
| store[sp].vi -= store[sp + 1].vi; | |
| break; | |
| case 31: /*sbr*/ | |
| sp–; | |
| store[sp].vr -= store[sp + 1].vr; | |
| break; | |
| case 32: /*sgs*/ | |
| P_setcpy(store[sp].vs, P_addset(P_expset(SET, 0), store[sp].vi)); | |
| break; | |
| case 33: /*flt*/ | |
| store[sp].vr = store[sp].vi; | |
| break; | |
| case 34: /*flo*/ | |
| store[sp – 1].vr = store[sp – 1].vi; | |
| break; | |
| case 35: /*trc*/ | |
| store[sp].vi = (long)store[sp].vr; | |
| break; | |
| case 36: /*ngi*/ | |
| store[sp].vi = -store[sp].vi; | |
| break; | |
| case 37: /*ngr*/ | |
| store[sp].vr = -store[sp].vr; | |
| break; | |
| case 38: /*sqi*/ | |
| TEMP = store[sp].vi; | |
| store[sp].vi = TEMP * TEMP; | |
| break; | |
| case 39: /*sqr*/ | |
| TEMP1 = store[sp].vr; | |
| store[sp].vr = TEMP1 * TEMP1; | |
| break; | |
| case 40: /*abi*/ | |
| store[sp].vi = labs(store[sp].vi); | |
| break; | |
| case 41: /*abr*/ | |
| store[sp].vr = fabs(store[sp].vr); | |
| break; | |
| case 42: /*not*/ | |
| store[sp].vb = !store[sp].vb; | |
| break; | |
| case 43: /*and*/ | |
| sp–; | |
| store[sp].vb = (store[sp].vb && store[sp + 1].vb); | |
| break; | |
| case 44: /*ior*/ | |
| sp–; | |
| store[sp].vb = (store[sp].vb || store[sp + 1].vb); | |
| break; | |
| case 45: /*dif*/ | |
| sp–; | |
| P_setdiff(store[sp].vs, store[sp].vs, store[sp + 1].vs); | |
| break; | |
| case 46: /*int*/ | |
| sp–; | |
| P_setint(store[sp].vs, store[sp].vs, store[sp + 1].vs); | |
| break; | |
| case 47: /*uni*/ | |
| sp–; | |
| P_setunion(store[sp].vs, store[sp].vs, store[sp + 1].vs); | |
| break; | |
| case 48: /*inn*/ | |
| sp–; | |
| i = store[sp].vi; | |
| store[sp].vb = P_inset(i, store[sp + 1].vs); | |
| break; | |
| case 49: /*mod*/ | |
| sp–; | |
| store[sp].vi %= store[sp + 1].vi; | |
| break; | |
| case 50: /*odd*/ | |
| store[sp].vb = store[sp].vi & 1; | |
| break; | |
| case 51: /*mpi*/ | |
| sp–; | |
| store[sp].vi *= store[sp + 1].vi; | |
| break; | |
| case 52: /*mpr*/ | |
| sp–; | |
| store[sp].vr *= store[sp + 1].vr; | |
| break; | |
| case 53: /*dvi*/ | |
| sp–; | |
| store[sp].vi /= store[sp + 1].vi; | |
| break; | |
| case 54: /*dvr*/ | |
| sp–; | |
| store[sp].vr /= store[sp + 1].vr; | |
| break; | |
| case 55: /*mov*/ | |
| i1 = store[sp – 1].va; | |
| i2 = store[sp].va; | |
| sp -= 2; | |
| FORLIM = q; | |
| for (i = 0; i < FORLIM; i++) { | |
| store[i1 + i] = store[i2 + i]; | |
| /* q is a number of storage units */ | |
| } | |
| break; | |
| case 56: /*lca*/ | |
| sp++; | |
| store[sp].va = q; | |
| break; | |
| case 100: | |
| case 101: | |
| case 102: | |
| case 103: | |
| case 104: | |
| case 57: /*dec*/ | |
| store[sp].vi -= q; | |
| break; | |
| case 58: /*stp*/ | |
| interpreting = false; | |
| break; | |
| case 59: /*ord*/ | |
| break; | |
| /*only used to change the tagfield*/ | |
| case 60: /*chr*/ | |
| break; | |
| case 61: /*ujc*/ | |
| errori(" case – error\t "); | |
| break; | |
| } | |
| } /*while interpreting*/ | |
| _L1: | |
| if (prd.f != NULL) | |
| fclose(prd.f); | |
| if (prr.f != NULL) | |
| fclose(prr.f); | |
| return 0; | |
| } | |
| /* End. */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (*Assembler and interpreter of Pascal code*) | |
| (*K. Jensen, N. Wirth, Ch. Jacobi, ETH May 76*) | |
| program pcode(input,output,prd,prr); | |
| (* Note for the implementation. | |
| =========================== | |
| This interpreter is written for the case where all the fundamental types | |
| take one storage unit. | |
| In an actual implementation, the handling of the sp pointer has to take | |
| into account the fact that the types may have lengths different from one: | |
| in push and pop operations the sp has to be increased and decreased not | |
| by 1, but by a number depending on the type concerned. | |
| However, where the number of units of storage has been computed by the | |
| compiler, the value must not be corrected, since the lengths of the types | |
| involved have already been taken into account. | |
| *) | |
| label 1; | |
| const codemax = 8650; | |
| pcmax = 17500; | |
| maxstk = 13650; (* size of variable store *) | |
| overi = 13655; (* size of integer constant table = 5 *) | |
| overr = 13660; (* size of real constant table = 5 *) | |
| overs = 13730; (* size of set constant table = 70 *) | |
| overb = 13820; | |
| overm = 18000; | |
| maxstr = 18001; | |
| largeint = 26144; | |
| begincode = 3; | |
| inputadr = 5; | |
| outputadr = 6; | |
| prdadr = 7; | |
| prradr = 8; | |
| duminst = 62; | |
| type bit4 = 0..15; | |
| bit6 = 0..127; | |
| bit20 = -26143..26143; | |
| datatype = (undef,int,reel,bool,sett,adr,mark,car); | |
| address = -1..maxstr; | |
| beta = packed array[1..25] of char; (*error message*) | |
| settype = set of 0..58; | |
| alfa = packed array[1..10] of char; | |
| var code : array[0..codemax] of (* the program *) | |
| packed record op1 :bit6; | |
| p1 :bit4; | |
| q1 :bit20; | |
| op2 :bit6; | |
| p2 :bit4; | |
| q2 :bit20 | |
| end; | |
| pc : 0..pcmax; (*program address register*) | |
| op : bit6; p : bit4; q : bit20; (*instruction register*) | |
| store : array [0..overm] of | |
| record case datatype of | |
| int :(vi :integer); | |
| reel :(vr :real); | |
| bool :(vb :boolean); | |
| sett :(vs :settype); | |
| car :(vc :char); | |
| adr :(va :address); | |
| (*address in store*) | |
| mark :(vm :integer) | |
| end; | |
| mp,sp,np,ep : address; (* address registers *) | |
| (*mp points to beginning of a data segment | |
| sp points to top of the stack | |
| ep points to the maximum extent of the stack | |
| np points to top of the dynamically allocated area*) | |
| interpreting: boolean; | |
| prd,prr : text;(*prd for read only, prr for write only *) | |
| instr : array[bit6] of alfa; (* mnemonic instruction codes *) | |
| cop : array[bit6] of integer; | |
| sptable : array[0..20] of alfa; (*standard functions and procedures*) | |
| (*locally used for interpreting one instruction*) | |
| ad,ad1 : address; | |
| b : boolean; | |
| i,j,i1,i2 : integer; | |
| c : char; | |
| (*——————————————————————–*) | |
| procedure load; | |
| const maxlabel = 1850; | |
| type labelst = (entered,defined); (*label situation*) | |
| labelrg = 0..maxlabel; (*label range*) | |
| labelrec = record | |
| val: address; | |
| st: labelst | |
| end; | |
| var icp,rcp,scp,bcp,mcp : address; (*pointers to next free position*) | |
| word : array[1..10] of char; i : integer; ch : char; | |
| labeltab: array[labelrg] of labelrec; | |
| labelvalue: address; | |
| procedure init; | |
| var i: integer; | |
| begin instr[ 0]:='lod '; instr[ 1]:='ldo '; | |
| instr[ 2]:='str '; instr[ 3]:='sro '; | |
| instr[ 4]:='lda '; instr[ 5]:='lao '; | |
| instr[ 6]:='sto '; instr[ 7]:='ldc '; | |
| instr[ 8]:='… '; instr[ 9]:='ind '; | |
| instr[10]:='inc '; instr[11]:='mst '; | |
| instr[12]:='cup '; instr[13]:='ent '; | |
| instr[14]:='ret '; instr[15]:='csp '; | |
| instr[16]:='ixa '; instr[17]:='equ '; | |
| instr[18]:='neq '; instr[19]:='geq '; | |
| instr[20]:='grt '; instr[21]:='leq '; | |
| instr[22]:='les '; instr[23]:='ujp '; | |
| instr[24]:='fjp '; instr[25]:='xjp '; | |
| instr[26]:='chk '; instr[27]:='eof '; | |
| instr[28]:='adi '; instr[29]:='adr '; | |
| instr[30]:='sbi '; instr[31]:='sbr '; | |
| instr[32]:='sgs '; instr[33]:='flt '; | |
| instr[34]:='flo '; instr[35]:='trc '; | |
| instr[36]:='ngi '; instr[37]:='ngr '; | |
| instr[38]:='sqi '; instr[39]:='sqr '; | |
| instr[40]:='abi '; instr[41]:='abr '; | |
| instr[42]:='not '; instr[43]:='and '; | |
| instr[44]:='ior '; instr[45]:='dif '; | |
| instr[46]:='int '; instr[47]:='uni '; | |
| instr[48]:='inn '; instr[49]:='mod '; | |
| instr[50]:='odd '; instr[51]:='mpi '; | |
| instr[52]:='mpr '; instr[53]:='dvi '; | |
| instr[54]:='dvr '; instr[55]:='mov '; | |
| instr[56]:='lca '; instr[57]:='dec '; | |
| instr[58]:='stp '; instr[59]:='ord '; | |
| instr[60]:='chr '; instr[61]:='ujc '; | |
| sptable[ 0]:='get '; sptable[ 1]:='put '; | |
| sptable[ 2]:='rst '; sptable[ 3]:='rln '; | |
| sptable[ 4]:='new '; sptable[ 5]:='wln '; | |
| sptable[ 6]:='wrs '; sptable[ 7]:='eln '; | |
| sptable[ 8]:='wri '; sptable[ 9]:='wrr '; | |
| sptable[10]:='wrc '; sptable[11]:='rdi '; | |
| sptable[12]:='rdr '; sptable[13]:='rdc '; | |
| sptable[14]:='sin '; sptable[15]:='cos '; | |
| sptable[16]:='exp '; sptable[17]:='log '; | |
| sptable[18]:='sqt '; sptable[19]:='atn '; | |
| sptable[20]:='sav '; | |
| cop[ 0] := 105; cop[ 1] := 65; | |
| cop[ 2] := 70; cop[ 3] := 75; | |
| cop[ 6] := 80; cop[ 9] := 85; | |
| cop[10] := 90; cop[26] := 95; | |
| cop[57] := 100; | |
| pc := begincode; | |
| icp := maxstk + 1; | |
| rcp := overi + 1; | |
| scp := overr + 1; | |
| bcp := overs + 2; | |
| mcp := overb + 1; | |
| for i:= 1 to 10 do word[i]:= ' '; | |
| for i:= 0 to maxlabel do | |
| with labeltab[i] do begin val:=-1; st:= entered end; | |
| reset(prd); | |
| end;(*init*) | |
| procedure errorl(string: beta); (*error in loading*) | |
| begin writeln; | |
| write(string); | |
| halt | |
| end; (*errorl*) | |
| procedure update(x: labelrg); (*when a label definition lx is found*) | |
| var curr,succ: -1..pcmax; (*resp. current element and successor element | |
| of a list of future references*) | |
| endlist: boolean; | |
| begin | |
| if labeltab[x].st=defined then errorl(' duplicated label ') | |
| else begin | |
| if labeltab[x].val<>-1 then (*forward reference(s)*) | |
| begin curr:= labeltab[x].val; endlist:= false; | |
| while not endlist do | |
| with code[curr div 2] do | |
| begin | |
| if odd(curr) then begin succ:= q2; | |
| q2:= labelvalue | |
| end | |
| else begin succ:= q1; | |
| q1:= labelvalue | |
| end; | |
| if succ=-1 then endlist:= true | |
| else curr:= succ | |
| end; | |
| end; | |
| labeltab[x].st := defined; | |
| labeltab[x].val:= labelvalue; | |
| end | |
| end;(*update*) | |
| procedure assemble; forward; | |
| procedure generate;(*generate segment of code*) | |
| var x: integer; (* label number *) | |
| again: boolean; | |
| begin | |
| again := true; | |
| while again do | |
| begin read(prd,ch);(* first character of line*) | |
| case ch of | |
| 'i': readln(prd); | |
| 'l': begin read(prd,x); | |
| if not eoln(prd) then read(prd,ch); | |
| if ch='=' then read(prd,labelvalue) | |
| else labelvalue:= pc; | |
| update(x); readln(prd); | |
| end; | |
| 'q': begin again := false; readln(prd) end; | |
| ' ': begin read(prd,ch); assemble end | |
| end; | |
| end | |
| end; (*generate*) | |
| procedure assemble; (*translate symbolic code into machine code and store*) | |
| label 1; (*goto 1 for instructions without code generation*) | |
| var name :alfa; b :boolean; r :real; s :settype; | |
| c1 :char; i,s1,lb,ub :integer; | |
| procedure lookup(x: labelrg); (* search in label table*) | |
| begin case labeltab[x].st of | |
| entered: begin q := labeltab[x].val; | |
| labeltab[x].val := pc | |
| end; | |
| defined: q:= labeltab[x].val | |
| end(*case label..*) | |
| end;(*lookup*) | |
| procedure labelsearch; | |
| var x: labelrg; | |
| begin while (ch<>'l') and not eoln(prd) do read(prd,ch); | |
| read(prd,x); lookup(x) | |
| end;(*labelsearch*) | |
| procedure getname; | |
| begin word[1] := ch; | |
| read(prd,word[2],word[3]); | |
| if not eoln(prd) then read(prd,ch) (*next character*); | |
| pack(word,1,name) | |
| end; (*getname*) | |
| procedure typesymbol; | |
| var i: integer; | |
| begin | |
| if ch <> 'i' then | |
| begin | |
| case ch of | |
| 'a': i := 0; | |
| 'r': i := 1; | |
| 's': i := 2; | |
| 'b': i := 3; | |
| 'c': i := 4; | |
| end; | |
| op := cop[op]+i; | |
| end; | |
| end (*typesymbol*) ; | |
| begin p := 0; q := 0; op := 0; | |
| getname; | |
| instr[duminst] := name; | |
| while instr[op]<>name do op := op+1; | |
| if op = duminst then errorl(' illegal instruction '); | |
| case op of (* get parameters p,q *) | |
| (*equ,neq,geq,grt,leq,les*) | |
| 17,18,19, | |
| 20,21,22: begin case ch of | |
| 'a': ; (*p = 0*) | |
| 'i': p := 1; | |
| 'r': p := 2; | |
| 'b': p := 3; | |
| 's': p := 4; | |
| 'c': p := 6; | |
| 'm': begin p := 5; | |
| read(prd,q) | |
| end | |
| end | |
| end; | |
| (*lod,str*) | |
| 0,2: begin typesymbol; read(prd,p,q) | |
| end; | |
| 4 (*lda*): read(prd,p,q); | |
| 12 (*cup*): begin read(prd,p); labelsearch end; | |
| 11 (*mst*): read(prd,p); | |
| 14 (*ret*): case ch of | |
| 'p': p:=0; | |
| 'i': p:=1; | |
| 'r': p:=2; | |
| 'c': p:=3; | |
| 'b': p:=4; | |
| 'a': p:=5 | |
| end; | |
| (*lao,ixa,mov*) | |
| 5,16,55: read(prd,q); | |
| (*ldo,sro,ind,inc,dec*) | |
| 1,3,9,10,57: begin typesymbol; read(prd,q) | |
| end; | |
| (*ujp,fjp,xjp*) | |
| 23,24,25: labelsearch; | |
| 13 (*ent*): begin read(prd,p); labelsearch end; | |
| 15 (*csp*): begin for i:=1 to 9 do read(prd,ch); getname; | |
| while name<>sptable[q] do q := q+1 | |
| end; | |
| 7 (*ldc*): begin case ch of (*get q*) | |
| 'i': begin p := 1; read(prd,i); | |
| if abs(i)>=largeint then | |
| begin op := 8; | |
| store[icp].vi := i; q := maxstk; | |
| repeat q := q+1 until store[q].vi=i; | |
| if q=icp then | |
| begin icp := icp+1; | |
| if icp=overi then | |
| errorl(' integer table overflow '); | |
| end | |
| end else q := i | |
| end; | |
| 'r': begin op := 8; p := 2; | |
| read(prd,r); | |
| store[rcp].vr := r; q := overi; | |
| repeat q := q+1 until store[q].vr=r; | |
| if q=rcp then | |
| begin rcp := rcp+1; | |
| if rcp = overr then | |
| errorl(' real table overflow '); | |
| end | |
| end; | |
| 'n': ; (*p,q = 0*) | |
| 'b': begin p := 3; read(prd,q) end; | |
| 'c': begin p := 6; | |
| repeat read(prd,ch); until ch <> ' '; | |
| if ch <> '''' then | |
| errorl(' illegal character '); | |
| read(prd,ch); q := ord(ch); | |
| read(prd,ch); | |
| if ch <> '''' then | |
| errorl(' illegal character '); | |
| end; | |
| '(': begin op := 8; p := 4; | |
| s := [ ]; read(prd,ch); | |
| while ch<>')' do | |
| begin read(prd,s1,ch); s := s + [s1] | |
| end; | |
| store[scp].vs := s; q := overr; | |
| repeat q := q+1 until store[q].vs=s; | |
| if q=scp then | |
| begin scp := scp+1; | |
| if scp=overs then | |
| errorl(' set table overflow '); | |
| end | |
| end | |
| end (*case*) | |
| end; | |
| 26 (*chk*): begin typesymbol; | |
| read(prd,lb,ub); | |
| if op = 95 then q := lb | |
| else | |
| begin | |
| store[bcp-1].vi := lb; store[bcp].vi := ub; | |
| q := overs; | |
| repeat q := q+2 | |
| until (store[q-1].vi=lb)and (store[q].vi=ub); | |
| if q=bcp then | |
| begin bcp := bcp+2; | |
| if bcp=overb then | |
| errorl(' boundary table overflow '); | |
| end | |
| end | |
| end; | |
| 56 (*lca*): begin | |
| if mcp + 16 >= overm then | |
| errorl(' multiple table overflow '); | |
| mcp := mcp+16; | |
| q := mcp; | |
| for i := 0 to 15 (*stringlgth*) do | |
| begin read(prd,ch); | |
| store[q+i].vc := ch | |
| end; | |
| end; | |
| 6 (*sto*): typesymbol; | |
| 27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, | |
| 48,49,50,51,52,53,54,58: ; | |
| (*ord,chr*) | |
| 59,60: goto 1; | |
| 61 (*ujc*): ; (*must have same length as ujp*) | |
| end; (*case*) | |
| (* store instruction *) | |
| with code[pc div 2] do | |
| if odd(pc) then | |
| begin op2 := op; p2 := p; q2 := q | |
| end else | |
| begin op1 := op; p1 := p; q1 := q | |
| end; | |
| pc := pc+1; | |
| 1: readln(prd); | |
| end; (*assemble*) | |
| begin (*load*) | |
| init; | |
| generate; | |
| pc := 0; | |
| generate; | |
| end; (*load*) | |
| (*————————————————————————*) | |
| procedure pmd; | |
| var s :integer; i: integer; | |
| procedure pt; | |
| begin write(s:6); | |
| if abs(store[s].vi) < maxint then write(store[s].vi) | |
| else write('too big '); | |
| s := s – 1; | |
| i := i + 1; | |
| if i = 4 then | |
| begin writeln(output); i := 0 end; | |
| end; (*pt*) | |
| begin | |
| write(' pc =',pc-1:5,' op =',op:3,' sp =',sp:5,' mp =',mp:5, | |
| ' np =',np:5); | |
| writeln; writeln('————————————–'); | |
| s := sp; i := 0; | |
| while s>=0 do pt; | |
| s := maxstk; | |
| while s>=np do pt; | |
| end; (*pmd*) | |
| procedure errori(string: beta); | |
| begin writeln; writeln(string); | |
| pmd; goto 1 | |
| end;(*errori*) | |
| function base(ld :integer):address; | |
| var ad :address; | |
| begin ad := mp; | |
| while ld>0 do | |
| begin ad := store[ad+1].vm; ld := ld-1 | |
| end; | |
| base := ad | |
| end; (*base*) | |
| procedure compare; | |
| (*comparing is only correct if result by comparing integers will be*) | |
| begin | |
| i1 := store[sp].va; | |
| i2 := store[sp+1].va; | |
| i := 0; b := true; | |
| while b and (i<>q) do | |
| if store[i1+i].vi = store[i2+i].vi then i := i+1 | |
| else b := false | |
| end; (*compare*) | |
| procedure callsp; | |
| var line: boolean; adptr,adelnt: address; | |
| i: integer; | |
| procedure readi(var f:text); | |
| var ad: address; | |
| begin ad:= store[sp-1].va; | |
| read(f,store[ad].vi); | |
| store[store[sp].va].vc := f^; | |
| sp:= sp-2 | |
| end;(*readi*) | |
| procedure readr(var f: text); | |
| var ad: address; | |
| begin ad:= store[sp-1].va; | |
| read(f,store[ad].vr); | |
| store[store[sp].va].vc := f^; | |
| sp:= sp-2 | |
| end;(*readr*) | |
| procedure readc(var f: text); | |
| var c: char; ad: address; | |
| begin read(f,c); | |
| ad:= store[sp-1].va; | |
| store[ad].vc := c; | |
| store[store[sp].va].vc := f^; | |
| store[store[sp].va].vi := ord(f^); | |
| sp:= sp-2 | |
| end;(*readc*) | |
| procedure writestr(var f: text); | |
| var i,j,k: integer; | |
| ad: address; | |
| begin ad:= store[sp-3].va; | |
| k := store[sp-2].vi; j := store[sp-1].vi; | |
| (* j and k are numbers of characters *) | |
| if k>j then for i:=1 to k-j do write(f,' ') | |
| else j:= k; | |
| for i := 0 to j-1 do write(f,store[ad+i].vc); | |
| sp:= sp-4 | |
| end;(*writestr*) | |
| procedure getfile(var f: text); | |
| var ad: address; | |
| begin ad:=store[sp].va; | |
| get(f); store[ad].vc := f^; | |
| sp:=sp-1 | |
| end;(*getfile*) | |
| procedure putfile(var f: text); | |
| var ad: address; | |
| begin ad:= store[sp].va; | |
| f^:= store[ad].vc; put(f); | |
| sp:= sp-1; | |
| end;(*putfile*) | |
| begin (*callsp*) | |
| case q of | |
| 0 (*get*): case store[sp].va of | |
| 5: getfile(input); | |
| 6: errori(' get on output file '); | |
| 7: getfile(prd); | |
| 8: errori(' get on prr file ') | |
| end; | |
| 1 (*put*): case store[sp].va of | |
| 5: errori(' put on read file '); | |
| 6: putfile(output); | |
| 7: errori(' put on prd file '); | |
| 8: putfile(prr) | |
| end; | |
| 2 (*rst*): begin | |
| (*for testphase*) | |
| np := store[sp].va; sp := sp-1 | |
| end; | |
| 3 (*rln*): begin case store[sp].va of | |
| 5: begin readln(input); | |
| store[inputadr].vc := input^ | |
| end; | |
| 6: errori(' readln on output file '); | |
| 7: begin readln(input); | |
| store[inputadr].vc := input^ | |
| end; | |
| 8: errori(' readln on prr file ') | |
| end; | |
| sp:= sp-1 | |
| end; | |
| 4 (*new*): begin ad:= np-store[sp].va; | |
| (*top of stack gives the length in units of storage *) | |
| if ad <= ep then | |
| errori(' store overflow '); | |
| np:= ad; ad:= store[sp-1].va; | |
| store[ad].va := np; | |
| sp:=sp-2 | |
| end; | |
| 5 (*wln*): begin case store[sp].va of | |
| 5: errori(' writeln on input file '); | |
| 6: writeln(output); | |
| 7: errori(' writeln on prd file '); | |
| 8: writeln(prr) | |
| end; | |
| sp:= sp-1 | |
| end; | |
| 6 (*wrs*): case store[sp].va of | |
| 5: errori(' write on input file '); | |
| 6: writestr(output); | |
| 7: errori(' write on prd file '); | |
| 8: writestr(prr) | |
| end; | |
| 7 (*eln*): begin case store[sp].va of | |
| 5: line:= eoln(input); | |
| 6: errori(' eoln output file '); | |
| 7: line:=eoln(prd); | |
| 8: errori(' eoln on prr file ') | |
| end; | |
| store[sp].vb := line | |
| end; | |
| 8 (*wri*): begin case store[sp].va of | |
| 5: errori(' write on input file '); | |
| 6: write(output, | |
| store[sp-2].vi: store[sp-1].vi); | |
| 7: errori(' write on prd file '); | |
| 8: write(prr, | |
| store[sp-2].vi: store[sp-1].vi) | |
| end; | |
| sp:=sp-3 | |
| end; | |
| 9 (*wrr*): begin case store[sp].va of | |
| 5: errori(' write on input file '); | |
| 6: write(output, | |
| store[sp-2].vr: store[sp-1].vi); | |
| 7: errori(' write on prd file '); | |
| 8: write(prr, | |
| store[sp-2].vr: store[sp-1].vi) | |
| end; | |
| sp:=sp-3 | |
| end; | |
| 10(*wrc*): begin case store[sp].va of | |
| 5: errori(' write on input file '); | |
| 6: write(output,store[sp-2].vc: | |
| store[sp-1].vi); | |
| 7: errori(' write on prd file '); | |
| 8: write(prr,chr(store[sp-2].vi): | |
| store[sp-1].vi); | |
| end; | |
| sp:=sp-3 | |
| end; | |
| 11(*rdi*): case store[sp].va of | |
| 5: readi(input); | |
| 6: errori(' read on output file '); | |
| 7: readi(prd); | |
| 8: errori(' read on prr file ') | |
| end; | |
| 12(*rdr*): case store[sp].va of | |
| 5: readr(input); | |
| 6: errori(' read on output file '); | |
| 7: readr(prd); | |
| 8: errori(' read on prr file ') | |
| end; | |
| 13(*rdc*): case store[sp].va of | |
| 5: readc(input); | |
| 6: errori(' read on output file '); | |
| 7: readc(prd); | |
| 8: errori(' read on prr file ') | |
| end; | |
| 14(*sin*): store[sp].vr:= sin(store[sp].vr); | |
| 15(*cos*): store[sp].vr:= cos(store[sp].vr); | |
| 16(*exp*): store[sp].vr:= exp(store[sp].vr); | |
| 17(*log*): store[sp].vr:= ln(store[sp].vr); | |
| 18(*sqt*): store[sp].vr:= sqrt(store[sp].vr); | |
| 19(*atn*): store[sp].vr:= arctan(store[sp].vr); | |
| 20(*sav*): begin ad:=store[sp].va; | |
| store[ad].va := np; | |
| sp:= sp-1 | |
| end; | |
| end;(*case q*) | |
| end;(*callsp*) | |
| begin (* main *) | |
| rewrite(prr); | |
| load; (* assembles and stores code *) | |
| (* writeln(output); for testing *) | |
| pc := 0; sp := -1; mp := 0; np := maxstk+1; ep := 5; | |
| store[inputadr].vc := input^; | |
| store[prdadr].vc := prd^; | |
| interpreting := true; | |
| while interpreting do | |
| begin | |
| (*fetch*) | |
| with code[pc div 2] do | |
| if odd(pc) then | |
| begin op := op2; p := p2; q := q2 | |
| end else | |
| begin op := op1; p := p1; q := q1 | |
| end; | |
| pc := pc+1; | |
| (*execute*) | |
| case op of | |
| 105,106,107,108,109, | |
| 0 (*lod*): begin ad := base(p) + q; | |
| sp := sp+1; | |
| store[sp] := store[ad] | |
| end; | |
| 65,66,67,68,69, | |
| 1 (*ldo*): begin | |
| sp := sp+1; | |
| store[sp] := store[q] | |
| end; | |
| 70,71,72,73,74, | |
| 2 (*str*): begin store[base(p)+q] := store[sp]; | |
| sp := sp-1 | |
| end; | |
| 75,76,77,78,79, | |
| 3 (*sro*): begin store[q] := store[sp]; | |
| sp := sp-1 | |
| end; | |
| 4 (*lda*): begin sp := sp+1; | |
| store[sp].va := base(p) + q | |
| end; | |
| 5 (*lao*): begin sp := sp+1; | |
| store[sp].va := q | |
| end; | |
| 80,81,82,83,84, | |
| 6 (*sto*): begin | |
| store[store[sp-1].va] := store[sp]; | |
| sp := sp-2; | |
| end; | |
| 7 (*ldc*): begin sp := sp+1; | |
| if p=1 then | |
| begin store[sp].vi := q; | |
| end else | |
| if p = 6 then store[sp].vc := chr(q) | |
| else | |
| if p = 3 then store[sp].vb := q = 1 | |
| else (* load nil *) store[sp].va := maxstr | |
| end; | |
| 8 (*lci*): begin sp := sp+1; | |
| store[sp] := store[q] | |
| end; | |
| 85,86,87,88,89, | |
| 9 (*ind*): begin ad := store[sp].va + q; | |
| (* q is a number of storage units *) | |
| store[sp] := store[ad] | |
| end; | |
| 90,91,92,93,94, | |
| 10 (*inc*): store[sp].vi := store[sp].vi+q; | |
| 11 (*mst*): begin (*p=level of calling procedure minus level of called | |
| procedure + 1; set dl and sl, increment sp*) | |
| (* then length of this element is | |
| max(intsize,realsize,boolsize,charsize,ptrsize *) | |
| store[sp+2].vm := base(p); | |
| (* the length of this element is ptrsize *) | |
| store[sp+3].vm := mp; | |
| (* idem *) | |
| store[sp+4].vm := ep; | |
| (* idem *) | |
| sp := sp+5 | |
| end; | |
| 12 (*cup*): begin (*p=no of locations for parameters, q=entry point*) | |
| mp := sp-(p+4); | |
| store[mp+4].vm := pc; | |
| pc := q | |
| end; | |
| 13 (*ent*): if p = 1 then | |
| begin sp := mp + q; (*q = length of dataseg*) | |
| if sp > np then errori(' store overflow '); | |
| end | |
| else | |
| begin ep := sp+q; | |
| if ep > np then errori(' store overflow '); | |
| end; | |
| (*q = max space required on stack*) | |
| 14 (*ret*): begin case p of | |
| 0: sp:= mp-1; | |
| 1,2,3,4,5: sp:= mp | |
| end; | |
| pc := store[mp+4].vm; | |
| ep := store[mp+3].vm; | |
| mp:= store[mp+2].vm; | |
| end; | |
| 15 (*csp*): callsp; | |
| 16 (*ixa*): begin | |
| i := store[sp].vi; | |
| sp := sp-1; | |
| store[sp].va := q*i+store[sp].va; | |
| end; | |
| 17 (*equ*): begin sp := sp-1; | |
| case p of | |
| 1: store[sp].vb := store[sp].vi = store[sp+1].vi; | |
| 0: store[sp].vb := store[sp].va = store[sp+1].va; | |
| 6: store[sp].vb := store[sp].vc = store[sp+1].vc; | |
| 2: store[sp].vb := store[sp].vr = store[sp+1].vr; | |
| 3: store[sp].vb := store[sp].vb = store[sp+1].vb; | |
| 4: store[sp].vb := store[sp].vs = store[sp+1].vs; | |
| 5: begin compare; | |
| store[sp].vb := b; | |
| end; | |
| end; (*case p*) | |
| end; | |
| 18 (*neq*): begin sp := sp-1; | |
| case p of | |
| 0: store[sp].vb := store[sp].va <> store[sp+1].va; | |
| 1: store[sp].vb := store[sp].vi <> store[sp+1].vi; | |
| 6: store[sp].vb := store[sp].vc <> store[sp+1].vc; | |
| 2: store[sp].vb := store[sp].vr <> store[sp+1].vr; | |
| 3: store[sp].vb := store[sp].vb <> store[sp+1].vb; | |
| 4: store[sp].vb := store[sp].vs <> store[sp+1].vs; | |
| 5: begin compare; | |
| store[sp].vb := not b; | |
| end | |
| end; (*case p*) | |
| end; | |
| 19 (*geq*): begin sp := sp-1; | |
| case p of | |
| 0: errori(' <,<=,>,>= for address '); | |
| 1: store[sp].vb := store[sp].vi >= store[sp+1].vi; | |
| 6: store[sp].vb := store[sp].vc >= store[sp+1].vc; | |
| 2: store[sp].vb := store[sp].vr >= store[sp+1].vr; | |
| 3: store[sp].vb := store[sp].vb >= store[sp+1].vb; | |
| 4: store[sp].vb := store[sp].vs >= store[sp+1].vs; | |
| 5: begin compare; | |
| store[sp].vb := b or | |
| (store[i1+i].vi >= store[i2+i].vi) | |
| end | |
| end; (*case p*) | |
| end; | |
| 20 (*grt*): begin sp := sp-1; | |
| case p of | |
| 0: errori(' <,<=,>,>= for address '); | |
| 1: store[sp].vb := store[sp].vi > store[sp+1].vi; | |
| 6: store[sp].vb := store[sp].vc > store[sp+1].vc; | |
| 2: store[sp].vb := store[sp].vr > store[sp+1].vr; | |
| 3: store[sp].vb := store[sp].vb > store[sp+1].vb; | |
| 4: errori(' set inclusion '); | |
| 5: begin compare; | |
| store[sp].vb := not b and | |
| (store[i1+i].vi > store[i2+i].vi) | |
| end | |
| end; (*case p*) | |
| end; | |
| 21 (*leq*): begin sp := sp-1; | |
| case p of | |
| 0: errori(' <,<=,>,>= for address '); | |
| 1: store[sp].vb := store[sp].vi <= store[sp+1].vi; | |
| 6: store[sp].vb := store[sp].vc <= store[sp+1].vc; | |
| 2: store[sp].vb := store[sp].vr <= store[sp+1].vr; | |
| 3: store[sp].vb := store[sp].vb <= store[sp+1].vb; | |
| 4: store[sp].vb := store[sp].vs <= store[sp+1].vs; | |
| 5: begin compare; | |
| store[sp].vb := b or | |
| (store[i1+i].vi <= store[i2+i].vi) | |
| end; | |
| end; (*case p*) | |
| end; | |
| 22 (*les*): begin sp := sp-1; | |
| case p of | |
| 0: errori(' <,<=,>,>= for address '); | |
| 1: store[sp].vb := store[sp].vi < store[sp+1].vi; | |
| 6: store[sp].vb := store[sp].vc < store[sp+1].vc; | |
| 2: store[sp].vb := store[sp].vr < store[sp+1].vr; | |
| 3: store[sp].vb := store[sp].vb < store[sp+1].vb; | |
| 5: begin compare; | |
| store[sp].vb := not b and | |
| (store[i1+i].vi < store[i2+i].vi) | |
| end | |
| end; (*case p*) | |
| end; | |
| 23 (*ujp*): pc := q; | |
| 24 (*fjp*): begin if not store[sp].vb then pc := q; | |
| sp := sp-1 | |
| end; | |
| 25 (*xjp*): begin | |
| pc := store[sp].vi + q; | |
| sp := sp-1 | |
| end; | |
| 95 (*chka*): if (store[sp].va < np) or | |
| (store[sp].va > (maxstr-q)) then | |
| errori(' bad pointer value '); | |
| 96,97,98,99, | |
| 26 (*chk*): if (store[sp].vi < store[q-1].vi) or | |
| (store[sp].vi > store[q].vi) then | |
| errori(' value out of range '); | |
| 27 (*eof*): begin i := store[sp].vi; | |
| if i=inputadr then | |
| begin store[sp].vb := eof(input); | |
| end else errori(' code in error ') | |
| end; | |
| 28 (*adi*): begin sp := sp-1; | |
| store[sp].vi := store[sp].vi + store[sp+1].vi | |
| end; | |
| 29 (*adr*): begin sp := sp-1; | |
| store[sp].vr := store[sp].vr + store[sp+1].vr | |
| end; | |
| 30 (*sbi*): begin sp := sp-1; | |
| store[sp].vi := store[sp].vi – store[sp+1].vi | |
| end; | |
| 31 (*sbr*): begin sp := sp-1; | |
| store[sp].vr := store[sp].vr – store[sp+1].vr | |
| end; | |
| 32 (*sgs*): store[sp].vs := [store[sp].vi]; | |
| 33 (*flt*): store[sp].vr := store[sp].vi; | |
| 34 (*flo*): store[sp-1].vr := store[sp-1].vi; | |
| 35 (*trc*): store[sp].vi := trunc(store[sp].vr); | |
| 36 (*ngi*): store[sp].vi := -store[sp].vi; | |
| 37 (*ngr*): store[sp].vr := -store[sp].vr; | |
| 38 (*sqi*): store[sp].vi := sqr(store[sp].vi); | |
| 39 (*sqr*): store[sp].vr := sqr(store[sp].vr); | |
| 40 (*abi*): store[sp].vi := abs(store[sp].vi); | |
| 41 (*abr*): store[sp].vr := abs(store[sp].vr); | |
| 42 (*not*): store[sp].vb := not store[sp].vb; | |
| 43 (*and*): begin sp := sp-1; | |
| store[sp].vb := store[sp].vb and store[sp+1].vb | |
| end; | |
| 44 (*ior*): begin sp := sp-1; | |
| store[sp].vb := store[sp].vb or store[sp+1].vb | |
| end; | |
| 45 (*dif*): begin sp := sp-1; | |
| store[sp].vs := store[sp].vs – store[sp+1].vs | |
| end; | |
| 46 (*int*): begin sp := sp-1; | |
| store[sp].vs := store[sp].vs * store[sp+1].vs | |
| end; | |
| 47 (*uni*): begin sp := sp-1; | |
| store[sp].vs := store[sp].vs + store[sp+1].vs | |
| end; | |
| 48 (*inn*): begin | |
| sp := sp – 1; i := store[sp].vi; | |
| store[sp].vb := i in store[sp+1].vs; | |
| end; | |
| 49 (*mod*): begin sp := sp-1; | |
| store[sp].vi := store[sp].vi mod store[sp+1].vi | |
| end; | |
| 50 (*odd*): store[sp].vb := odd(store[sp].vi); | |
| 51 (*mpi*): begin sp := sp-1; | |
| store[sp].vi := store[sp].vi * store[sp+1].vi | |
| end; | |
| 52 (*mpr*): begin sp := sp-1; | |
| store[sp].vr := store[sp].vr * store[sp+1].vr | |
| end; | |
| 53 (*dvi*): begin sp := sp-1; | |
| store[sp].vi := store[sp].vi div store[sp+1].vi | |
| end; | |
| 54 (*dvr*): begin sp := sp-1; | |
| store[sp].vr := store[sp].vr / store[sp+1].vr | |
| end; | |
| 55 (*mov*): begin i1 := store[sp-1].va; | |
| i2 := store[sp].va; sp := sp-2; | |
| for i := 0 to q-1 do store[i1+i] := store[i2+i] | |
| (* q is a number of storage units *) | |
| end; | |
| 56 (*lca*): begin sp := sp+1; | |
| store[sp].va := q; | |
| end; | |
| 100,101,102,103,104, | |
| 57 (*dec*): store[sp].vi := store[sp].vi-q; | |
| 58 (*stp*): interpreting := false; | |
| 59 (*ord*): (*only used to change the tagfield*) | |
| begin | |
| end; | |
| 60 (*chr*): begin | |
| end; | |
| 61 (*ujc*): errori(' case – error '); | |
| end | |
| end; (*while interpreting*) | |
| 1 : | |
| end. |






Leave a comment