Merge from trunk.
This commit is contained in:
commit
fd10cf7ac2
|
@ -7,5 +7,6 @@ IndentCaseLabels: 'true'
|
|||
PointerAlignment: Left
|
||||
TabWidth: '4'
|
||||
UseTab: ForIndentation
|
||||
SortIncludes: false
|
||||
|
||||
...
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
- os: osx
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ed
|
||||
- openbios-ppc
|
||||
- qemu-user
|
||||
|
||||
git:
|
||||
depth: 10
|
||||
|
|
4
Makefile
4
Makefile
|
@ -63,7 +63,7 @@ PLATDEP = $(INSDIR)/lib/ack
|
|||
|
||||
.NOTPARALLEL:
|
||||
|
||||
MAKECMDGOALS ?= +ack
|
||||
MAKECMDGOALS ?= +ack +tests
|
||||
BUILD_FILES = $(shell find * -name '*.lua')
|
||||
|
||||
ifneq ($(shell which ninja),)
|
||||
|
@ -88,6 +88,7 @@ $(BUILDDIR)/build.$(BUILDSYSTEM): first/ackbuilder.lua Makefile $(BUILD_FILES) $
|
|||
@$(LUA) first/ackbuilder.lua \
|
||||
first/build.lua build.lua \
|
||||
--$(BUILDSYSTEM) \
|
||||
DEFAULT_PLATFORM=$(DEFAULT_PLATFORM) \
|
||||
OBJDIR=$(OBJDIR) \
|
||||
BINDIR=$(BINDIR) \
|
||||
LIBDIR=$(LIBDIR) \
|
||||
|
@ -95,6 +96,7 @@ $(BUILDDIR)/build.$(BUILDSYSTEM): first/ackbuilder.lua Makefile $(BUILD_FILES) $
|
|||
INSDIR=$(INSDIR) \
|
||||
PLATIND=$(PLATIND) \
|
||||
PLATDEP=$(PLATDEP) \
|
||||
PREFIX=$(PREFIX) \
|
||||
AR=$(AR) \
|
||||
CC=$(CC) \
|
||||
> $(BUILDDIR)/build.$(BUILDSYSTEM)
|
||||
|
|
26
README
26
README
|
@ -2,7 +2,7 @@
|
|||
===================================
|
||||
|
||||
© 1987-2005 Vrije Universiteit, Amsterdam
|
||||
2016-08-02
|
||||
2017-01-07
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
|
@ -19,22 +19,25 @@ probably broken. However, what's there should be sufficient to get things
|
|||
done and to evaluate how the full 6.1 release should work.
|
||||
|
||||
|
||||
|
||||
SUPPORT
|
||||
=======
|
||||
|
||||
Languages:
|
||||
|
||||
ANSI C, Pascal, Modula 2, Basic. K&R is supported via the ANSI C compiler.
|
||||
ANSI C, B, Pascal, Modula 2, Basic. K&R is supported via the ANSI C compiler.
|
||||
|
||||
Platforms:
|
||||
|
||||
pc86 produces bootable floppy disk images for 8086 PCs
|
||||
linux386 produces ELF executables for PC Linux systems
|
||||
linux68k produces ELF executables for m68020 Linux systems
|
||||
linuxppc produces ELF executables for PowerPC Linux systems
|
||||
cpm produces i80 CP/M .COM files
|
||||
rpi produces Raspberry Pi GPU binaries
|
||||
|
||||
|
||||
|
||||
INSTALLATION
|
||||
============
|
||||
|
||||
|
@ -55,6 +58,11 @@ Requirements:
|
|||
- (optionally) ninja; if you've got this, this will be autodetected and give
|
||||
you faster builds.
|
||||
|
||||
- (optionally) the qemu suite: if you have this installed, the build system
|
||||
will detect it automatically and run the test suites for the supported
|
||||
architectures. Get both the qemu-system-* platform emulators and the qemu-*
|
||||
userland emulators (only works on Linux).
|
||||
|
||||
- about 40MB free in /tmp (or some other temporary directory).
|
||||
|
||||
- about 6MB in the target directory.
|
||||
|
@ -89,6 +97,7 @@ Instructions:
|
|||
The ACK should now be ready to use.
|
||||
|
||||
|
||||
|
||||
USAGE
|
||||
=====
|
||||
|
||||
|
@ -111,7 +120,8 @@ Some useful options include:
|
|||
ack figures out which language to use from the file extension:
|
||||
|
||||
.c C (ANSI or K&R)
|
||||
.b Basic
|
||||
.b the PDP-11 dialect of B
|
||||
.bas Basic
|
||||
.mod Modula-2
|
||||
.ocm Occam 1
|
||||
.p Pascal
|
||||
|
@ -150,11 +160,17 @@ There are some things you should be aware of.
|
|||
- The ACK uses its own .o format. You won't be able to mix the ACK's object
|
||||
files and another compiler's.
|
||||
|
||||
- When compiling together multiple B source files, you need to do some extra
|
||||
work to initialise them properly otherwise your program will crash on
|
||||
startup; see the ack(1) and abmodules(1) man pages.
|
||||
|
||||
- The distribution contains *everything*, including the weird, ancient,
|
||||
archaic stuff that doesn't work any more and never will, such as the int EM
|
||||
interpreter and the assembler-linkers. Only some of it builds. Look for
|
||||
build.lua files.
|
||||
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
==========
|
||||
|
||||
|
@ -177,6 +193,6 @@ You can find the mailing list on the project's web site:
|
|||
|
||||
Please enjoy.
|
||||
|
||||
David Given (dtrg on Sourceforge)
|
||||
David Given (davidgiven on Github)
|
||||
dg@cowlark.com
|
||||
2016-08-02
|
||||
2016-11-26
|
||||
|
|
22
build.lua
22
build.lua
|
@ -9,12 +9,17 @@ vars.plats = {
|
|||
"linux386",
|
||||
"linux68k",
|
||||
"linuxppc",
|
||||
"osx386",
|
||||
"osxppc",
|
||||
"qemuppc",
|
||||
"pc86",
|
||||
"rpi",
|
||||
}
|
||||
vars.plats_with_tests = {
|
||||
"linux386",
|
||||
"linuxppc",
|
||||
"qemuppc",
|
||||
"pc86",
|
||||
}
|
||||
|
||||
local plat_packages = {}
|
||||
|
@ -33,6 +38,7 @@ installable {
|
|||
"lang/cem/cemcom.ansi+pkg",
|
||||
"lang/m2/comp+pkg",
|
||||
"lang/pc/comp+pkg",
|
||||
"lang/b/compiler+pkg",
|
||||
"util/ack+pkg",
|
||||
"util/amisc+pkg",
|
||||
"util/arch+pkg",
|
||||
|
@ -43,8 +49,18 @@ installable {
|
|||
"examples+pkg",
|
||||
plat_packages
|
||||
},
|
||||
deps = {
|
||||
test_packages
|
||||
}
|
||||
}
|
||||
|
||||
normalrule {
|
||||
name = "tests",
|
||||
ins = {
|
||||
"first/testsummary.sh",
|
||||
test_packages
|
||||
},
|
||||
outleaves = {
|
||||
"stamp"
|
||||
},
|
||||
commands = {
|
||||
"%{ins}"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ local conly = {
|
|||
|
||||
local sourcefiles = filenamesof(
|
||||
"./hilo.b",
|
||||
"./hilo.bas",
|
||||
"./hilo.c",
|
||||
"./hilo.mod",
|
||||
"./hilo.p",
|
||||
|
|
137
examples/hilo.b
137
examples/hilo.b
|
@ -1,39 +1,108 @@
|
|||
1 ' $Source$
|
||||
2 ' $State$
|
||||
3 ' $Revision$
|
||||
#
|
||||
|
||||
10 print "Hi there! I'm written in Basic. Before we start, what is your name?"
|
||||
20 input "> ", PlayerName$
|
||||
30 print
|
||||
40 print "Hello, "; PlayerName$; "!"
|
||||
buffer[6];
|
||||
PlayerName[6];
|
||||
|
||||
100 gosub 1000
|
||||
110 print
|
||||
120 print "Would you like another go?"
|
||||
130 input "> ", s$
|
||||
140 s$ = left$(s$, 1)
|
||||
150 if s$ = "n" or s$ = "N" then goto 200
|
||||
160 print
|
||||
170 print "Excellent! ";
|
||||
180 goto 100
|
||||
200 print
|
||||
210 print "Thanks for playing --- goodbye!"
|
||||
220 end
|
||||
/* Taken intact from the B reference manual. */
|
||||
strcopy(sl ,s2)
|
||||
{
|
||||
auto i;
|
||||
|
||||
1000 print "See if you can guess my number."
|
||||
1010 Number% = rnd(1) mod 100
|
||||
1020 Attempts% = 1
|
||||
i = 0;
|
||||
while (lchar(sl, i, char(s2, i)) != '*e')
|
||||
i++;
|
||||
}
|
||||
|
||||
1030 print
|
||||
1040 input "> ", guess%
|
||||
1050 if guess% < Number% then print: print "Try a bit higher."
|
||||
1060 if guess% > Number% then print: print "Try a bit lower."
|
||||
1070 if guess% = Number% then goto 1100
|
||||
1080 Attempts% = Attempts% + 1
|
||||
1090 goto 1030
|
||||
1100 print
|
||||
1110 print "You got it right in only"; Attempts%;
|
||||
1120 if Attempts% = 1 then print "go"; else print "goes";
|
||||
1130 print "!"
|
||||
1140 return
|
||||
reads()
|
||||
{
|
||||
extrn buffer;
|
||||
|
||||
putstr("> ");
|
||||
flush();
|
||||
getstr(buffer);
|
||||
}
|
||||
|
||||
atoi(s)
|
||||
{
|
||||
auto value, sign, i, c;
|
||||
|
||||
i = 0;
|
||||
if (char(s, i) == '-')
|
||||
{
|
||||
sign = -1;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
sign = 1;
|
||||
|
||||
value = 0;
|
||||
while ((c = char(s, i++)) != '*e')
|
||||
value = value*10 + (c - '0');
|
||||
|
||||
return(value * sign);
|
||||
}
|
||||
|
||||
rand()
|
||||
{
|
||||
/* Genuinely random; retrieved from random.org */
|
||||
return(57);
|
||||
}
|
||||
|
||||
game()
|
||||
{
|
||||
extrn buffer;
|
||||
auto Number, Attempts;
|
||||
auto guess;
|
||||
|
||||
printf("See if you can guess my number.*n");
|
||||
|
||||
Number = rand() % 100;
|
||||
Attempts = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
reads();
|
||||
guess = atoi(buffer);
|
||||
|
||||
if (guess == Number)
|
||||
{
|
||||
printf("*nYou got it right in only %d %s!*n", Attempts,
|
||||
(Attempts == 1) ? "go" : "goes");
|
||||
return;
|
||||
}
|
||||
|
||||
if (guess < Number)
|
||||
printf("*nTry a bit higher.*n");
|
||||
if (guess > Number)
|
||||
printf("*nTry a bit lower.*n");
|
||||
Attempts++;
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
extrn buffer, PlayerName;
|
||||
|
||||
printf("*nHi there! I'm written in B. Before we start, what is your name?*n");
|
||||
reads();
|
||||
strcopy(PlayerName, buffer);
|
||||
printf("*nHello, %s! ", PlayerName);
|
||||
|
||||
while (1)
|
||||
{
|
||||
game();
|
||||
printf("*nWould you like another go?*n");
|
||||
reads();
|
||||
|
||||
if ((char(buffer, 0) == 'n') | (char(buffer, 0) == 'N'))
|
||||
{
|
||||
printf("*nThanks for playing --- goodbye!*n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("*nExcellent! ");
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
39
examples/hilo.bas
Normal file
39
examples/hilo.bas
Normal file
|
@ -0,0 +1,39 @@
|
|||
1 ' $Source$
|
||||
2 ' $State$
|
||||
3 ' $Revision$
|
||||
|
||||
10 print "Hi there! I'm written in Basic. Before we start, what is your name?"
|
||||
20 input "> ", PlayerName$
|
||||
30 print
|
||||
40 print "Hello, "; PlayerName$; "!"
|
||||
|
||||
100 gosub 1000
|
||||
110 print
|
||||
120 print "Would you like another go?"
|
||||
130 input "> ", s$
|
||||
140 s$ = left$(s$, 1)
|
||||
150 if s$ = "n" or s$ = "N" then goto 200
|
||||
160 print
|
||||
170 print "Excellent! ";
|
||||
180 goto 100
|
||||
200 print
|
||||
210 print "Thanks for playing --- goodbye!"
|
||||
220 end
|
||||
|
||||
1000 print "See if you can guess my number."
|
||||
1010 Number% = rnd(1) mod 100
|
||||
1020 Attempts% = 1
|
||||
|
||||
1030 print
|
||||
1040 input "> ", guess%
|
||||
1050 if guess% < Number% then print: print "Try a bit higher."
|
||||
1060 if guess% > Number% then print: print "Try a bit lower."
|
||||
1070 if guess% = Number% then goto 1100
|
||||
1080 Attempts% = Attempts% + 1
|
||||
1090 goto 1030
|
||||
1100 print
|
||||
1110 print "You got it right in only"; Attempts%;
|
||||
1120 if Attempts% = 1 then print "go"; else print "goes";
|
||||
1130 print "!"
|
||||
1140 return
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
This is a public domain adventure and may not be sold for profit */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MOXIE 13
|
||||
|
@ -32,7 +33,9 @@ int plato_clone=3;
|
|||
int blast_door=0;
|
||||
int killer_count=0;
|
||||
|
||||
char get_char()
|
||||
void character(void);
|
||||
|
||||
char get_char(void)
|
||||
{
|
||||
char c;
|
||||
fflush(stdout);
|
||||
|
@ -41,7 +44,7 @@ char get_char()
|
|||
return c;
|
||||
}
|
||||
|
||||
more()
|
||||
void more(void)
|
||||
{
|
||||
printf("---------- More ----------");
|
||||
#ifdef DEBUG
|
||||
|
@ -55,8 +58,7 @@ more()
|
|||
};
|
||||
}
|
||||
|
||||
new_clone(resume)
|
||||
int resume;
|
||||
int new_clone(int resume)
|
||||
{
|
||||
printf("\nClone %d just died.\n",clone);
|
||||
if (++clone>6)
|
||||
|
@ -75,15 +77,14 @@ int resume;
|
|||
}
|
||||
}
|
||||
|
||||
dice_roll(number,faces)
|
||||
int number, faces;
|
||||
int dice_roll(int number, int faces)
|
||||
{
|
||||
int i,total=0;
|
||||
for(i=number;i>0;i--) total+= rand()%faces+1;
|
||||
return total;
|
||||
}
|
||||
|
||||
instructions()
|
||||
void instructions(void)
|
||||
{
|
||||
printf("\n\n\n\nWelcome to Paranoia!\n\n");
|
||||
printf("HOW TO PLAY:\n\n");
|
||||
|
@ -104,7 +105,7 @@ instructions()
|
|||
printf(" If not, you can try again later.\n");
|
||||
}
|
||||
|
||||
character()
|
||||
void character(void)
|
||||
{
|
||||
printf("===============================================================================\n");
|
||||
printf("The Character : Philo-R-DMD %d\n", clone);
|
||||
|
@ -130,9 +131,7 @@ character()
|
|||
printf("===============================================================================\n");
|
||||
}
|
||||
|
||||
choose(a,aptr,b,bptr)
|
||||
int a,b;
|
||||
char *aptr, *bptr;
|
||||
int choose(int a, char* aptr, int b, char* bptr)
|
||||
{
|
||||
printf("\nSelect \'a\' or \'b\' :\n");
|
||||
printf(" a - %s.\n b - %s.\n", aptr, bptr);
|
||||
|
@ -140,7 +139,7 @@ char *aptr, *bptr;
|
|||
else return b;
|
||||
}
|
||||
|
||||
page1()
|
||||
int page1(void)
|
||||
{
|
||||
printf(" You wake up face down on the red and pink checked E-Z-Kleen linoleum floor.\n");
|
||||
printf(" You recognise the pattern, it\'s the type preferred in the internal security\nbriefing cells. When you finally look around you, you see that you are alone\n");
|
||||
|
@ -148,7 +147,7 @@ page1()
|
|||
return 57;
|
||||
}
|
||||
|
||||
page2()
|
||||
int page2(void)
|
||||
{
|
||||
printf("\"Greetings,\" says the kindly Internal Security self incrimination expert who\n");
|
||||
printf("meets you at the door, \"How are we doing today?\" He offers you a doughnut\n");
|
||||
|
@ -166,7 +165,7 @@ page2()
|
|||
else return new_clone(32);
|
||||
}
|
||||
|
||||
page3()
|
||||
int page3(void)
|
||||
{
|
||||
printf("You walk to the nearest Computer terminal and request more information about\n");
|
||||
printf("Christmas. The Computer says, \"That is an A-1 ULTRAVIOLET ONLY IMMEDIATE\n");
|
||||
|
@ -174,7 +173,7 @@ page3()
|
|||
return choose(4,"You give your correct clearance",5,"You lie and claim Ultraviolet clearance");
|
||||
}
|
||||
|
||||
page4()
|
||||
int page4(void)
|
||||
{
|
||||
printf("\"That is classified information, Troubleshooter, thank you for your inquiry.\n");
|
||||
printf(" Please report to an Internal Security self incrimination station as soon as\n");
|
||||
|
@ -182,7 +181,7 @@ page4()
|
|||
return 9;
|
||||
}
|
||||
|
||||
page5()
|
||||
int page5(void)
|
||||
{
|
||||
printf("The computer says, \"Troubleshooter, you are not wearing the correct colour\n");
|
||||
printf("uniform. You must put on an Ultraviolet uniform immediately. I have seen to\n");
|
||||
|
@ -193,7 +192,7 @@ page5()
|
|||
return choose(6, "You open the package and put on the uniform", 7, "You finally come to your senses and run for it");
|
||||
}
|
||||
|
||||
page6()
|
||||
int page6(void)
|
||||
{
|
||||
printf("The uniform definitely makes you look snappy and pert. It really looks\n");
|
||||
printf("impressive, and even has the new lopsided lapel fashion that you admire so\n");
|
||||
|
@ -205,7 +204,7 @@ page6()
|
|||
return 8;
|
||||
}
|
||||
|
||||
page7()
|
||||
int page7(void)
|
||||
{
|
||||
printf("The corridor lights dim and are replaced by red battle lamps as the Security\n");
|
||||
printf("Breach alarms howl all around you. You run headlong down the corridor and\n");
|
||||
|
@ -232,7 +231,7 @@ page7()
|
|||
return 8;
|
||||
}
|
||||
|
||||
page8()
|
||||
int page8(void)
|
||||
{
|
||||
printf("\"Now, about your question, citizen. Christmas was an old world marketing ploy\n");
|
||||
printf("to induce lower clearance citizens to purchase vast quantities of goods, thus\n");
|
||||
|
@ -249,7 +248,7 @@ page8()
|
|||
return 10;
|
||||
}
|
||||
|
||||
page9()
|
||||
int page9(void)
|
||||
{
|
||||
int choice;
|
||||
printf("As you walk toward the tubecar that will take you to GDH7-beta, you pass one\n");
|
||||
|
@ -262,7 +261,7 @@ page9()
|
|||
return choice;
|
||||
}
|
||||
|
||||
page10()
|
||||
int page10(void)
|
||||
{
|
||||
int choice;
|
||||
printf("You stroll briskly down the corridor, up a ladder, across an unrailed catwalk,\n");
|
||||
|
@ -290,7 +289,7 @@ page10()
|
|||
}
|
||||
}
|
||||
|
||||
page11()
|
||||
int page11(void)
|
||||
{
|
||||
printf("The printing on the folder says \"Experimental Self Briefing.\"\n");
|
||||
printf("You open it and begin to read the following:\n");
|
||||
|
@ -321,7 +320,7 @@ page11()
|
|||
return choose(3,"You wish to ask The Computer for more information about Christmas",10,"You have decided to go directly to Goods Distribution Hall 7-beta");
|
||||
}
|
||||
|
||||
page12()
|
||||
int page12(void)
|
||||
{
|
||||
printf("You walk up to the door and push the button labelled \"push to exit.\"\n");
|
||||
printf("Within seconds a surly looking guard shoves his face into the small plexiglass\n");
|
||||
|
@ -333,7 +332,7 @@ page12()
|
|||
return choose(11,"You sit down at the table and read the Orange packet",57,"You stare around the room some more");
|
||||
}
|
||||
|
||||
page13()
|
||||
int page13(void)
|
||||
{
|
||||
printf("You step into the shiny plasteel tubecar, wondering why the shape has always\n");
|
||||
printf("reminded you of bullets. The car shoots forward the instant your feet touch\n");
|
||||
|
@ -346,7 +345,7 @@ page13()
|
|||
return 14;
|
||||
}
|
||||
|
||||
page14()
|
||||
int page14(void)
|
||||
{
|
||||
printf("You manage to pull yourself out of the tubecar and look around. Before you is\n");
|
||||
printf("one of the most confusing things you have ever seen, a hallway that is\n");
|
||||
|
@ -360,7 +359,7 @@ page14()
|
|||
return 22;
|
||||
}
|
||||
|
||||
page15()
|
||||
int page15(void)
|
||||
{
|
||||
printf("You are set upon by a runty robot with a queer looking face and two pointy\n");
|
||||
printf("rubber ears poking from beneath a tattered cap. \"Hey mister,\" it says,\n");
|
||||
|
@ -384,7 +383,7 @@ page15()
|
|||
}
|
||||
}
|
||||
|
||||
page16()
|
||||
int page16(void)
|
||||
{
|
||||
printf("The doll is a good buy for fifty credits; it will make a fine Christmas present\n");
|
||||
printf("for one of your friends. After the sale the robot rolls away. You can use\n");
|
||||
|
@ -395,7 +394,7 @@ page16()
|
|||
return 22;
|
||||
}
|
||||
|
||||
page17()
|
||||
int page17(void)
|
||||
{
|
||||
int i, robot_hp=15;
|
||||
printf("You whip out your laser and shoot the robot, but not before it squeezes the\n");
|
||||
|
@ -432,7 +431,7 @@ page17()
|
|||
return 22;
|
||||
}
|
||||
|
||||
page18()
|
||||
int page18(void)
|
||||
{
|
||||
printf("You walk to the centre of the hall, ogling like an infrared fresh from the\n");
|
||||
printf("clone vats. Towering before you is the most unearthly thing you have ever\n");
|
||||
|
@ -448,7 +447,7 @@ page18()
|
|||
else return 20;
|
||||
}
|
||||
|
||||
page19()
|
||||
int page19(void)
|
||||
{
|
||||
printf("Quickly you regain your balance, whirl and fire your laser into the Ultraviolet\n");
|
||||
printf("citizen behind you. For a moment your heart leaps to your throat, then you\n");
|
||||
|
@ -461,7 +460,7 @@ page19()
|
|||
return choose(34,"You search the body, keeping an eye open for Internal Security",22,"You run away like the cowardly dog you are");
|
||||
}
|
||||
|
||||
page20()
|
||||
int page20(void)
|
||||
{
|
||||
printf("Oh no! you can\'t keep your balance. You\'re falling, falling head first into\n");
|
||||
printf("the Christmas beast\'s gaping maw. It\'s a valiant struggle; you think you are\n");
|
||||
|
@ -473,7 +472,7 @@ page20()
|
|||
return 22;
|
||||
}
|
||||
|
||||
page21()
|
||||
int page21(void)
|
||||
{
|
||||
printf("You have been wasting the leading citizens of Alpha Complex at a prodigious\n");
|
||||
printf("rate. This has not gone unnoticed by the Internal Security squad at GDH7-beta.\n");
|
||||
|
@ -482,7 +481,7 @@ page21()
|
|||
return new_clone(45);
|
||||
}
|
||||
|
||||
page22()
|
||||
int page22(void)
|
||||
{
|
||||
printf("You are searching Goods Distribution Hall 7-beta.\n");
|
||||
switch(dice_roll(1,4))
|
||||
|
@ -494,7 +493,7 @@ page22()
|
|||
}
|
||||
}
|
||||
|
||||
page23()
|
||||
int page23(void)
|
||||
{
|
||||
printf("You go to the nearest computer terminal and declare yourself a mutant.\n");
|
||||
printf("\"A mutant, he\'s a mutant,\" yells a previously unnoticed infrared who had\n");
|
||||
|
@ -503,7 +502,7 @@ page23()
|
|||
return choose(28,"You tell them that it was really only a bad joke",24,"You want to fight it out, one against twelve");
|
||||
}
|
||||
|
||||
page24()
|
||||
int page24(void)
|
||||
{
|
||||
printf("Golly, I never expected someone to pick this. I haven\'t even designed\n");
|
||||
printf("the 12 citizens who are going to make a sponge out of you. Tell you what,\n");
|
||||
|
@ -511,7 +510,7 @@ page24()
|
|||
return choose(28,"You change your mind and say it was only a bad joke",25,"You REALLY want to shoot it out");
|
||||
}
|
||||
|
||||
page25()
|
||||
int page25(void)
|
||||
{
|
||||
printf("Boy, you really can\'t take a hint!\n");
|
||||
printf("They\'re closing in. Their trigger fingers are twitching, they\'re about to\n");
|
||||
|
@ -519,7 +518,7 @@ page25()
|
|||
return choose(28,"You tell them it was all just a bad joke",26,"You are going to shoot");
|
||||
}
|
||||
|
||||
page26()
|
||||
int page26(void)
|
||||
{
|
||||
printf("You can read the cold, sober hatred in their eyes (They really didn\'t think\n");
|
||||
printf("it was funny), as they tighten the circle around you. One of them shoves a\n");
|
||||
|
@ -529,19 +528,19 @@ page26()
|
|||
return new_clone(32);
|
||||
}
|
||||
|
||||
page27()
|
||||
int page27(void)
|
||||
{
|
||||
/* doesn't exist. Can't happen with computer version.
|
||||
designed to catch dice cheats */
|
||||
}
|
||||
|
||||
page28()
|
||||
int page28(void)
|
||||
{
|
||||
printf("They don\'t think it\'s funny.\n");
|
||||
return 26;
|
||||
}
|
||||
|
||||
page29()
|
||||
int page29(void)
|
||||
{
|
||||
printf("\"Psst, hey citizen, come here. Pssfft,\" you hear. When you peer around\n");
|
||||
printf("you can see someone\'s dim outline in the shadows. \"I got some information\n");
|
||||
|
@ -559,7 +558,7 @@ page29()
|
|||
}
|
||||
}
|
||||
|
||||
page30()
|
||||
int page30(void)
|
||||
{
|
||||
printf("You step into the shadows and offer the man a thirty credit bill. \"Just drop\n");
|
||||
printf("it on the floor,\" he says. \"So you\'re looking for the Master Retailer, pssfft?\n");
|
||||
|
@ -586,7 +585,7 @@ page30()
|
|||
}
|
||||
}
|
||||
|
||||
page31()
|
||||
int page31(void)
|
||||
{
|
||||
printf("Like any good troubleshooter you make the least expensive decision and threaten\n");
|
||||
printf("him for information. With lightning like reflexes you whip out your laser and\n");
|
||||
|
@ -599,7 +598,7 @@ page31()
|
|||
return choose(30,"You pay the 30 credits",22,"You pssfft go away stupid");
|
||||
}
|
||||
|
||||
page32()
|
||||
int page32(void)
|
||||
{
|
||||
printf("Finally it\'s your big chance to prove that you\'re as good a troubleshooter\n");
|
||||
printf("as your previous clone. You walk briskly to mission briefing and pick up your\n");
|
||||
|
@ -609,7 +608,7 @@ page32()
|
|||
return 22;
|
||||
}
|
||||
|
||||
page33()
|
||||
int page33(void)
|
||||
{
|
||||
blast_door=1;
|
||||
printf("You release the megabolts on the blast door, then strain against it with your\n");
|
||||
|
@ -622,7 +621,7 @@ page33()
|
|||
else return 36;
|
||||
}
|
||||
|
||||
page34()
|
||||
int page34(void)
|
||||
{
|
||||
printf("You have found a sealed envelope on the body. You open it and read:\n");
|
||||
printf("\"WARNING: Ultraviolet Clearance ONLY. DO NOT READ.\n");
|
||||
|
@ -650,7 +649,7 @@ page34()
|
|||
return choose(46,"You rush off to the nearest computer terminal to expose the commies",22,"You wander off to look for more evidence");
|
||||
}
|
||||
|
||||
page35()
|
||||
int page35(void)
|
||||
{
|
||||
printf("\"Oh master,\" you hear through the gun barrel, \"where have you been? It is\n");
|
||||
printf("time for the great Christmas gifting ceremony. You had better hurry and get\n");
|
||||
|
@ -669,7 +668,7 @@ page35()
|
|||
return new_clone(32);
|
||||
}
|
||||
|
||||
page36()
|
||||
int page36(void)
|
||||
{
|
||||
printf("\"Congratulations, troubleshooter, you have successfully found the lair of the\n");
|
||||
printf("Master Retailer and completed the Troubleshooter Training Course test mission,\"\n");
|
||||
|
@ -692,7 +691,7 @@ page36()
|
|||
}
|
||||
}
|
||||
|
||||
page37()
|
||||
int page37(void)
|
||||
{
|
||||
printf("\"Come with me please, Troubleshooter,\" says the Green clearance technician\n");
|
||||
printf("after he has dislodged your head from the cannon. \"You have been participating\n");
|
||||
|
@ -708,7 +707,7 @@ page37()
|
|||
return 38;
|
||||
}
|
||||
|
||||
page38()
|
||||
int page38(void)
|
||||
{
|
||||
printf("\"I am Plato-B-PHI%d, head of mutant propaganda here at the training course.\n",plato_clone);
|
||||
printf("If you have any questions about mutants please come to me. Today I will be\n");
|
||||
|
@ -725,7 +724,7 @@ page38()
|
|||
return choose(39,"You volunteer for the test",40,"You duck behind a chair and hope the instructor doesn\'t notice you");
|
||||
}
|
||||
|
||||
page39()
|
||||
int page39(void)
|
||||
{
|
||||
printf("You bravely volunteer to test the mutant detection gun. You stand up and walk\n");
|
||||
printf("down the steps to the podium, passing a very relieved Troubleshooter along the\n");
|
||||
|
@ -743,7 +742,7 @@ page39()
|
|||
return 41;
|
||||
}
|
||||
|
||||
page40()
|
||||
int page40(void)
|
||||
{
|
||||
printf("You breathe a sigh of relief as Plato-B-PHI picks on the other Troubleshooter.\n");
|
||||
printf("\"You down here in the front,\" says the instructor pointing at the other\n");
|
||||
|
@ -775,7 +774,7 @@ page40()
|
|||
}
|
||||
}
|
||||
|
||||
page41()
|
||||
int page41(void)
|
||||
{
|
||||
printf("You stumble down the hallway of the Troubleshooter Training Course looking for\n");
|
||||
printf("your next class. Up ahead you see one of the instructors waving to you. When\n");
|
||||
|
@ -789,7 +788,7 @@ page41()
|
|||
return choose(42,"You respond with the proper Illuminati code phrase, \"Ewige Blumenkraft\"",43,"You ignore this secret society contact");
|
||||
}
|
||||
|
||||
page42()
|
||||
int page42(void)
|
||||
{
|
||||
printf("\"Aha, so you are a member of the elitist Illuminati secret society,\" he says\n");
|
||||
printf("loudly, \"that is most interesting.\" He turns to the large class already\n");
|
||||
|
@ -799,7 +798,7 @@ page42()
|
|||
return choose(51,"You run for it",52,"You wait for the guard");
|
||||
}
|
||||
|
||||
page43()
|
||||
int page43(void)
|
||||
{
|
||||
printf("You sit through a long lecture on how to recognise and infiltrate secret\n");
|
||||
printf("societies, with an emphasis on mimicking secret handshakes. The basic theory,\n");
|
||||
|
@ -815,7 +814,7 @@ page43()
|
|||
return choose(44,"You go looking for a computer terminal",55,"You go to the graduation ceremony immediately");
|
||||
}
|
||||
|
||||
page44()
|
||||
int page44(void)
|
||||
{
|
||||
printf("You walk down to a semi-secluded part of the training course complex and\n");
|
||||
printf("activate a computer terminal. \"AT YOUR SERVICE\" reads the computer screen.\n");
|
||||
|
@ -833,7 +832,7 @@ page44()
|
|||
}
|
||||
}
|
||||
|
||||
page45()
|
||||
int page45(void)
|
||||
{
|
||||
printf("\"Hrank Hrank,\" snorts the alarm in your living quarters. Something is up.\n");
|
||||
printf("You look at the monitor above the bathroom mirror and see the message you have\n");
|
||||
|
@ -847,7 +846,7 @@ page45()
|
|||
return 10;
|
||||
}
|
||||
|
||||
page46()
|
||||
int page46(void)
|
||||
{
|
||||
printf("\"Why do you ask about the communists, Troubleshooter? It is not in the\n");
|
||||
printf("interest of your continued survival to be asking about such topics,\" says\n");
|
||||
|
@ -855,7 +854,7 @@ page46()
|
|||
return choose(53,"You insist on talking about the communists",54,"You change the subject");
|
||||
}
|
||||
|
||||
page47()
|
||||
int page47(void)
|
||||
{
|
||||
printf("The Computer orders the entire Vulture squadron to terminate the Troubleshooter\n");
|
||||
printf("Training Course. Unfortunately you too are terminated for possessing\n");
|
||||
|
@ -867,7 +866,7 @@ page47()
|
|||
return 0;
|
||||
}
|
||||
|
||||
page48()
|
||||
int page48(void)
|
||||
{
|
||||
printf("The tubecar shoots forward as you enter, slamming you back into a pile of\n");
|
||||
printf("garbage. The front end rotates upward and you, the garbage and the garbage\n");
|
||||
|
@ -877,14 +876,14 @@ page48()
|
|||
return new_clone(45);
|
||||
}
|
||||
|
||||
page49()
|
||||
int page49(void)
|
||||
{
|
||||
printf("The instructor drags your inert body into a specimen detainment cage.\n");
|
||||
printf("\"He\'ll make a good subject for tomorrow\'s mutant dissection class,\" you hear.\n");
|
||||
return new_clone(32);
|
||||
}
|
||||
|
||||
page50()
|
||||
int page50(void)
|
||||
{
|
||||
printf("You put down the other Troubleshooter, and then wisely decide to drill a few\n");
|
||||
printf("holes in the instructor as well; the only good witness is a dead witness.\n");
|
||||
|
@ -893,27 +892,27 @@ page50()
|
|||
return 41;
|
||||
}
|
||||
|
||||
page51()
|
||||
int page51(void)
|
||||
{
|
||||
printf("You run for it, but you don\'t run far. Three hundred strange and exotic\n");
|
||||
printf("weapons turn you into a freeze dried cloud of soot.\n");
|
||||
return new_clone(32);
|
||||
}
|
||||
|
||||
page52()
|
||||
int page52(void)
|
||||
{
|
||||
printf("You wisely wait until the instructor returns with a Blue Internal Security\n");
|
||||
printf("guard. The guard leads you to an Internal Security self incrimination station.\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
page53()
|
||||
int page53(void)
|
||||
{
|
||||
printf("You tell The Computer about:\n");
|
||||
return choose(47,"The commies who have infiltrated the Troubleshooter Training Course\n and the impending People\'s Revolution",54,"Something less dangerous");
|
||||
}
|
||||
|
||||
page54()
|
||||
int page54(void)
|
||||
{
|
||||
printf("\"Do not try to change the subject, Troubleshooter,\" says The Computer.\n");
|
||||
printf("\"It is a serious crime to ask about the communists. You will be terminated\n");
|
||||
|
@ -927,7 +926,7 @@ page54()
|
|||
else return new_clone(32);
|
||||
}
|
||||
|
||||
page55()
|
||||
int page55(void)
|
||||
{
|
||||
printf("You and 300 other excited graduates are marched from the lecture hall and into\n");
|
||||
printf("a large auditorium for the graduation exercise. The auditorium is\n");
|
||||
|
@ -955,7 +954,7 @@ page55()
|
|||
return 0;
|
||||
}
|
||||
|
||||
page56()
|
||||
int page56(void)
|
||||
{
|
||||
printf("That familiar strange feeling of deja\'vu envelops you again. It is hard to\n");
|
||||
printf("say, but whatever is on the other side of the door does not seem to be intended\n");
|
||||
|
@ -963,15 +962,14 @@ page56()
|
|||
return choose(33,"You open the door and step through",22,"You go looking for more information");
|
||||
}
|
||||
|
||||
page57()
|
||||
int page57(void)
|
||||
{
|
||||
printf("In the centre of the room is a table and a single chair. There is an Orange\n");
|
||||
printf("folder on the table top, but you can\'t make out the lettering on it.\n");
|
||||
return choose(11,"You sit down and read the folder",12,"You leave the room");
|
||||
}
|
||||
|
||||
next_page(this_page)
|
||||
int this_page;
|
||||
int next_page(int this_page)
|
||||
{
|
||||
printf("\n");
|
||||
switch (this_page)
|
||||
|
@ -1038,10 +1036,11 @@ int this_page;
|
|||
}
|
||||
}
|
||||
|
||||
main()
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
/* srand(time(0)); */
|
||||
instructions(); more();
|
||||
character(); more();
|
||||
while((page=next_page(page))!=0) more();
|
||||
return 0;
|
||||
}
|
||||
|
|
50
first/testsummary.sh
Executable file
50
first/testsummary.sh
Executable file
|
@ -0,0 +1,50 @@
|
|||
#!/bin/sh
|
||||
echo ""
|
||||
|
||||
succeeding="$(find "$@" -size 0)"
|
||||
notsucceeding="$(find "$@" ! -size 0)"
|
||||
if [ "$notsucceeding" != "" ]; then
|
||||
skipped="$(grep -l @@SKIPPED $notsucceeding)"
|
||||
timedout="$(grep -l @@TIMEDOUT $notsucceeding)"
|
||||
failed="$(grep -l @@FAIL $notsucceeding)"
|
||||
else
|
||||
skipped=
|
||||
timedout=
|
||||
failed=
|
||||
fi
|
||||
|
||||
for a in $failed $timedout; do
|
||||
echo "**** $a"
|
||||
cat $a
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "$(echo "$succeeding" | wc -w) tests passed"
|
||||
echo "$(echo "$notsucceeding" | wc -w) tests failed to pass"
|
||||
echo "$(echo "$skipped" | wc -w) were skipped (see build log for details)"
|
||||
echo "$(echo "$timedout" | wc -w) timed out"
|
||||
echo "$(echo "$failed" | wc -w) failed"
|
||||
echo ""
|
||||
|
||||
if [ "$failed" != "" ]; then
|
||||
echo "Failing test logs:"
|
||||
for t in $failed; do
|
||||
echo $t
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
if [ "$failed" != "" -o "$timedout" != "" ]; then
|
||||
echo "Test status: SAD FACE (tests are failing)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$succeeding" = "" ]; then
|
||||
echo "Test status: PUZZLED FACE (all tests were skipped)"
|
||||
exit 0
|
||||
fi
|
||||
if [ "$skipped" != "" ]; then
|
||||
echo "Test status: MILDLY PLEASED FACE (some tests were skipped, but the rest pass)"
|
||||
exit 0
|
||||
fi
|
||||
echo "Test status: HAPPY FACE (all tests are passing)"
|
||||
exit 0
|
||||
|
2
h/out.h
2
h/out.h
|
@ -66,7 +66,7 @@ struct outname {
|
|||
#define RELO2 2 /* 2 bytes */
|
||||
#define RELO4 3 /* 4 bytes */
|
||||
#define RELOPPC 4 /* PowerPC 26-bit address */
|
||||
/* relo 5 is unused */
|
||||
#define RELOLIS 5 /* PowerPC lis */
|
||||
#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */
|
||||
|
||||
#define RELPC 0x2000 /* pc relative */
|
||||
|
|
22
lang/b/LICENSE
Normal file
22
lang/b/LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2016 aap
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
53
lang/b/README.md
Normal file
53
lang/b/README.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
A B Compiler
|
||||
============
|
||||
|
||||
abc is a compiler for the [B Programming Language](http://en.wikipedia.org/wiki/B_(programming_language)) that targets x86\_32 processors. It is currently tested under Linux but should work (or at least be easily ported) to other UNIX-like systems. The code is based on [an early C compiler (last1120c)](http://www.cs.bell-labs.com/who/dmr/primevalC.html) by Dennis Ritchie.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
* [The Programming Language B](http://9p.io/cm/cs/who/dmr/bintro.html)
|
||||
|
||||
* [B Reference by Ken Thompson](http://9p.io/cm/cs/who/dmr/kbman.html) describes a presumably earlier variant of B, which is slightly different from the one described above. The compiler cannot understand it, but I plan to implement a compatibility mode (the differences are minor).
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
Since B was first implemented for machines with word addressing, some hacking was required to make it work on the byte addressed x86. Addresses filled in by the linker are always byte addresses, so pointers to these addresses are collectively stored at the end of the .data section and are then converted to word addresses at runtime, before main() is called.
|
||||
|
||||
The generated assembly is *very* inefficient, not even constant expressions are reduced at compile time. Also I/O is currently not buffered.
|
||||
|
||||
How to use
|
||||
----------
|
||||
|
||||
The installation requires a little configuration:
|
||||
'abc' is a frontend for the actual compiler which feels somewhat like gcc (it also handles assembling and linking). Before you can use it, set it's BDIR variable to the directory of the B compiler.
|
||||
In the Makefile, change the directory of the 'install' rule to wherever you want your 'abc' file to reside.
|
||||
Then type
|
||||
|
||||
make install libs
|
||||
|
||||
which compiles the compiler 'b', installs the 'abc' frontend and compiles the B runtime and library (brt.o and lib.o).
|
||||
|
||||
To compile and link a B program, simply type
|
||||
|
||||
abc -o outfile file1.b [file2.b ...]
|
||||
|
||||
If you want to compile and assemble only:
|
||||
|
||||
abc -c file1.b [file2.b ...]
|
||||
|
||||
or generate only the assembly:
|
||||
|
||||
abc -S file1.b [file2.b ...]
|
||||
|
||||
Examples of B programs are in the 'examples' directory, they are mostly from Brian Kernighan's tutorial.
|
||||
|
||||
Bugs
|
||||
----
|
||||
|
||||
Since command line parameters aren't passed word-aligned, B can't handle them easily. brt.s copies the strings to another location and aligns them, the space is not dynamically allocated however and only 256 bytes are available by default.
|
||||
|
||||
The library is incomplete but has some of the most important functions.
|
||||
|
||||
I have only tested the compiler on an x86\_64 gentoo system.
|
176
lang/b/compiler/b.h
Normal file
176
lang/b/compiler/b.h
Normal file
|
@ -0,0 +1,176 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <em.h>
|
||||
#include "astring.h"
|
||||
|
||||
#define NCPS 8 /* chars per symbol */
|
||||
#define HSHSIZ 400 /* hash table size */
|
||||
#define SWSIZ 230 /* switch table size */
|
||||
#define CMSIZ 40 /* symbol stack size */
|
||||
#define SSIZE 20 /* operator and precedence stack size */
|
||||
#define OSSIZ 300*8 /* space for expression tree */
|
||||
|
||||
#define EOS 04 /* end of string marker */
|
||||
|
||||
/*
|
||||
* Holds a B symbol.
|
||||
* class is one of the storage classes below.
|
||||
* offset is used depending on class.
|
||||
*/
|
||||
struct hshtab {
|
||||
int class;
|
||||
int offset;
|
||||
int dim;
|
||||
struct hshtab *next;
|
||||
char name[NCPS+1];
|
||||
};
|
||||
|
||||
struct tnode {
|
||||
int op;
|
||||
int value;
|
||||
struct tnode *tr1;
|
||||
struct tnode *tr2;
|
||||
};
|
||||
|
||||
struct swtab {
|
||||
int swlab;
|
||||
int swval;
|
||||
};
|
||||
|
||||
extern int wordsize;
|
||||
extern const char* modulename;
|
||||
int paramsize;
|
||||
struct hshtab hshtab[HSHSIZ];
|
||||
int hshused;
|
||||
int eof;
|
||||
int peekc;
|
||||
char ctab[128];
|
||||
struct hshtab *bsym;
|
||||
struct hshtab *paraml, *parame;
|
||||
int cval;
|
||||
int isn;
|
||||
char symbuf[NCPS+1];
|
||||
FILE *sbufp;
|
||||
int stack;
|
||||
struct tnode **cp;
|
||||
int *space;
|
||||
int ospace[OSSIZ];
|
||||
int retlab;
|
||||
int nerror;
|
||||
struct swtab swtab[SWSIZ];
|
||||
struct swtab *swp;
|
||||
int deflab;
|
||||
extern int contlab;
|
||||
extern int brklab;
|
||||
|
||||
extern int opdope[];
|
||||
extern int line;
|
||||
extern int peeksym, peeksym2;
|
||||
|
||||
void error(char *s, ...);
|
||||
void printtoken(int tok, FILE *out);
|
||||
struct tnode * block(int op, int value, struct tnode *tr1, struct tnode *tr2);
|
||||
void rcexpr(struct tnode *tr);
|
||||
void cbranch(struct tnode *t, int lab);
|
||||
void jump(int lab);
|
||||
void fnlabel(int l);
|
||||
void tonativeaddr(void);
|
||||
void fromnativeaddr(void);
|
||||
char* manglename(char* name, char prefix);
|
||||
|
||||
#define EOFC 0
|
||||
#define SEMI 1
|
||||
#define LBRACE 2
|
||||
#define RBRACE 3
|
||||
#define LBRACK 4
|
||||
#define RBRACK 5
|
||||
#define LPARN 6
|
||||
#define RPARN 7
|
||||
#define COLON 8
|
||||
#define COMMA 9
|
||||
#define HASH 10
|
||||
|
||||
#define MCALL 15
|
||||
#define CALL 16
|
||||
#define DECBEF 17
|
||||
#define INCBEF 18
|
||||
#define DECAFT 19
|
||||
#define INCAFT 20
|
||||
#define EXCLA 21
|
||||
#define NEG 22
|
||||
#define AMPER 23
|
||||
#define STAR 24
|
||||
#define QUEST 25
|
||||
#define NOT 26
|
||||
|
||||
#define PLUS 30
|
||||
#define MINUS 31
|
||||
#define MOD 32
|
||||
#define TIMES 33
|
||||
#define DIVIDE 34
|
||||
#define OR 35
|
||||
#define AND 36
|
||||
#define LSHIFT 37
|
||||
#define RSHIFT 38
|
||||
#define EQUAL 39
|
||||
#define NEQUAL 40
|
||||
#define LESSEQ 41
|
||||
#define LESS 42
|
||||
#define GREATEQ 43
|
||||
#define GREAT 44
|
||||
#define EOR 45
|
||||
|
||||
#define ASSIGN 49
|
||||
#define ASPLUS 50
|
||||
#define ASMINUS 51
|
||||
#define ASMOD 52
|
||||
#define ASTIMES 53
|
||||
#define ASDIV 54
|
||||
#define ASOR 55
|
||||
#define ASAND 56
|
||||
#define ASLSH 57
|
||||
#define ASRSH 58
|
||||
#define ASEQUAL 59
|
||||
#define ASNEQL 60
|
||||
#define ASLEQ 61
|
||||
#define ASLESS 62
|
||||
#define ASGTQ 63
|
||||
#define ASGREAT 64
|
||||
#define ASEOR 65
|
||||
|
||||
#define CON 70
|
||||
#define STRING 71
|
||||
#define NAME 72
|
||||
#define KEYW 73
|
||||
|
||||
#define SQUOTE 121
|
||||
#define DQUOTE 122
|
||||
#define NEWLN 123
|
||||
#define SPACE 124
|
||||
#define LETTER 125
|
||||
#define DIGIT 126
|
||||
#define UNKN 127
|
||||
|
||||
#define SEOF 200
|
||||
|
||||
/* storage classes */
|
||||
#define AUTO 1
|
||||
#define EXTERN 2
|
||||
#define INTERN 3
|
||||
#define ARG 4
|
||||
#define KEYWF 5
|
||||
|
||||
/* keywords */
|
||||
#define CASE 3
|
||||
#define IF 4
|
||||
#define ELSE 5
|
||||
#define WHILE 6
|
||||
#define SWITCH 7
|
||||
#define GOTO 8
|
||||
#define RETURN 9
|
||||
#define DEFAULT 10
|
||||
#define BREAK 11
|
||||
|
1383
lang/b/compiler/b0.c
Normal file
1383
lang/b/compiler/b0.c
Normal file
File diff suppressed because it is too large
Load diff
403
lang/b/compiler/b1.c
Normal file
403
lang/b/compiler/b1.c
Normal file
|
@ -0,0 +1,403 @@
|
|||
#include "b.h"
|
||||
|
||||
/*
|
||||
* Code generation (EM)
|
||||
*/
|
||||
|
||||
static int
|
||||
shiftsize(void)
|
||||
{
|
||||
switch (wordsize) {
|
||||
case 1: return 0;
|
||||
case 2: return 1;
|
||||
case 4: return 2;
|
||||
case 8: return 3;
|
||||
default:
|
||||
error("unsupported word size");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tonativeaddr(void)
|
||||
{
|
||||
C_loc(shiftsize());
|
||||
C_slu(wordsize);
|
||||
}
|
||||
|
||||
void
|
||||
fromnativeaddr(void)
|
||||
{
|
||||
C_loc(shiftsize());
|
||||
C_sru(wordsize);
|
||||
}
|
||||
|
||||
char*
|
||||
manglename(char* name, char prefix)
|
||||
{
|
||||
static char buffer[NCPS+3];
|
||||
buffer[0] = prefix;
|
||||
buffer[1] = '_';
|
||||
strcpy(buffer+2, name);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
binary(struct tnode *tr)
|
||||
{
|
||||
rcexpr(tr->tr1);
|
||||
rcexpr(tr->tr2);
|
||||
}
|
||||
|
||||
int
|
||||
pushargs(struct tnode *tr)
|
||||
{
|
||||
int stk;
|
||||
|
||||
if (tr == NULL)
|
||||
return 0;
|
||||
if (tr->op == COMMA) {
|
||||
rcexpr(tr->tr2);
|
||||
stk = pushargs(tr->tr1);
|
||||
return stk+wordsize;
|
||||
}
|
||||
rcexpr(tr);
|
||||
return wordsize;
|
||||
}
|
||||
|
||||
void
|
||||
lvalexp(struct tnode *tr)
|
||||
{
|
||||
struct hshtab *bs;
|
||||
char memloc[64];
|
||||
|
||||
switch (tr->op) {
|
||||
|
||||
case DECBEF:
|
||||
case INCBEF:
|
||||
case DECAFT:
|
||||
case INCAFT:
|
||||
if (tr->tr1->op == STAR) {
|
||||
rcexpr(tr->tr1->tr1);
|
||||
tonativeaddr();
|
||||
|
||||
if ((tr->op == DECBEF) || (tr->op == INCBEF)) {
|
||||
C_dup(wordsize); /* ( addr addr -- ) */
|
||||
C_loi(wordsize); /* ( addr val -- ) */
|
||||
if (tr->op == DECBEF)
|
||||
C_dec(); /* ( addr newval -- ) */
|
||||
else
|
||||
C_inc(); /* ( addr newval -- ) */
|
||||
C_exg(wordsize); /* ( newval addr -- ) */
|
||||
C_dup(wordsize*2); /* ( newval addr newval addr -- ) */
|
||||
C_sti(wordsize); /* ( newval addr -- ) */
|
||||
C_asp(wordsize); /* ( newval -- ) */
|
||||
} else {
|
||||
C_dup(wordsize); /* ( addr addr -- ) */
|
||||
C_loi(wordsize); /* ( addr val -- ) */
|
||||
C_dup(wordsize*2); /* ( addr val addr val -- ) */
|
||||
if (tr->op == DECAFT)
|
||||
C_dec(); /* ( addr val addr newval -- ) */
|
||||
else
|
||||
C_inc(); /* ( addr val addr newval -- ) */
|
||||
C_exg(wordsize); /* ( addr val newval addr -- ) */
|
||||
C_sti(wordsize); /* ( addr val -- ) */
|
||||
C_exg(wordsize); /* ( val addr -- ) */
|
||||
C_asp(wordsize); /* ( val -- ) */
|
||||
}
|
||||
} else { /* NAME, checked in "build" */
|
||||
bs = (struct hshtab *) tr->tr1->tr1;
|
||||
if (bs->class == EXTERN) {
|
||||
switch (tr->op) {
|
||||
case INCBEF:
|
||||
C_ine_dnam(manglename(bs->name, 'b'), 0);
|
||||
C_loe_dnam(manglename(bs->name, 'b'), 0);
|
||||
break;
|
||||
|
||||
case DECBEF:
|
||||
C_dee_dnam(manglename(bs->name, 'b'), 0);
|
||||
C_loe_dnam(manglename(bs->name, 'b'), 0);
|
||||
break;
|
||||
|
||||
case INCAFT:
|
||||
C_loe_dnam(manglename(bs->name, 'b'), 0);
|
||||
C_ine_dnam(manglename(bs->name, 'b'), 0);
|
||||
break;
|
||||
|
||||
case DECAFT:
|
||||
C_loe_dnam(manglename(bs->name, 'b'), 0);
|
||||
C_dee_dnam(manglename(bs->name, 'b'), 0);
|
||||
break;
|
||||
}
|
||||
} else if (bs->class == AUTO) {
|
||||
switch (tr->op) {
|
||||
case INCBEF:
|
||||
C_inl(bs->offset);
|
||||
C_lol(bs->offset);
|
||||
break;
|
||||
|
||||
case DECBEF:
|
||||
C_del(bs->offset);
|
||||
C_lol(bs->offset);
|
||||
break;
|
||||
|
||||
case INCAFT:
|
||||
C_lol(bs->offset);
|
||||
C_inl(bs->offset);
|
||||
break;
|
||||
|
||||
case DECAFT:
|
||||
C_lol(bs->offset);
|
||||
C_del(bs->offset);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
goto classerror;
|
||||
}
|
||||
return;
|
||||
|
||||
case ASSIGN:
|
||||
rcexpr(tr->tr2);
|
||||
C_dup(wordsize);
|
||||
if (tr->tr1->op == STAR) {
|
||||
rcexpr(tr->tr1->tr1);
|
||||
tonativeaddr();
|
||||
C_sti(wordsize);
|
||||
} else { /* NAME */
|
||||
bs = (struct hshtab *) tr->tr1->tr1;
|
||||
if (bs->class == EXTERN) {
|
||||
C_ste_dnam(manglename(bs->name, 'b'), 0);
|
||||
} else if (bs->class == AUTO) {
|
||||
C_stl(bs->offset);
|
||||
} else
|
||||
goto classerror;
|
||||
}
|
||||
return;
|
||||
|
||||
case ASPLUS:
|
||||
case ASMINUS:
|
||||
case ASMOD:
|
||||
case ASTIMES:
|
||||
case ASDIV:
|
||||
case ASOR:
|
||||
case ASAND:
|
||||
case ASLSH:
|
||||
case ASRSH:
|
||||
case ASEQUAL:
|
||||
case ASNEQL:
|
||||
case ASLEQ:
|
||||
case ASLESS:
|
||||
case ASGTQ:
|
||||
case ASGREAT:
|
||||
case ASEOR:
|
||||
tr->op -= ASPLUS-PLUS;
|
||||
rcexpr(block(ASSIGN,0,tr->tr1,tr));
|
||||
return;
|
||||
}
|
||||
|
||||
classerror:
|
||||
error("Storage class");
|
||||
}
|
||||
|
||||
void
|
||||
rcexpr(struct tnode *tr)
|
||||
{
|
||||
int o1, o2;
|
||||
int stk;
|
||||
struct hshtab *bs;
|
||||
|
||||
if (tr == NULL)
|
||||
return;
|
||||
|
||||
if (opdope[tr->op]&02) {
|
||||
lvalexp(tr);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (tr->op) {
|
||||
|
||||
case CON:
|
||||
C_loc(tr->value);
|
||||
return;
|
||||
|
||||
case STRING:
|
||||
C_lae_dlb(tr->value, 0);
|
||||
fromnativeaddr();
|
||||
return;
|
||||
|
||||
case NAME: /* only rvalue */
|
||||
bs = (struct hshtab *) tr->tr1;
|
||||
if (bs->class == EXTERN)
|
||||
C_loe_dnam(manglename(bs->name, 'b'), 0);
|
||||
else if (bs->class == AUTO)
|
||||
C_lol(bs->offset);
|
||||
else
|
||||
goto classerror;
|
||||
return;
|
||||
|
||||
case CALL:
|
||||
stk = pushargs(tr->tr2);
|
||||
rcexpr(tr->tr1);
|
||||
tonativeaddr();
|
||||
C_cai();
|
||||
if (stk)
|
||||
C_asp(stk);
|
||||
C_lfr(wordsize);
|
||||
return;
|
||||
|
||||
case AMPER:
|
||||
bs = (struct hshtab *) tr->tr1->tr1;
|
||||
if (bs->class == EXTERN) {
|
||||
C_lae_dnam(manglename(bs->name, 'b'), 0);
|
||||
} else if (bs->class == AUTO) {
|
||||
C_lal(bs->offset);
|
||||
} else
|
||||
goto classerror;
|
||||
fromnativeaddr();
|
||||
return;
|
||||
|
||||
case STAR: /* only rvalue */
|
||||
rcexpr(tr->tr1);
|
||||
tonativeaddr();
|
||||
C_loi(wordsize);
|
||||
return;
|
||||
|
||||
case PLUS:
|
||||
binary(tr);
|
||||
C_adi(wordsize);
|
||||
return;
|
||||
|
||||
case MINUS:
|
||||
binary(tr);
|
||||
C_sbi(wordsize);
|
||||
return;
|
||||
|
||||
case TIMES:
|
||||
binary(tr);
|
||||
C_mli(wordsize);
|
||||
return;
|
||||
|
||||
case DIVIDE:
|
||||
binary(tr);
|
||||
C_dvi(wordsize);
|
||||
return;
|
||||
|
||||
case MOD:
|
||||
binary(tr);
|
||||
C_rmi(wordsize);
|
||||
return;
|
||||
|
||||
case AND:
|
||||
binary(tr);
|
||||
C_and(wordsize);
|
||||
return;
|
||||
|
||||
case OR:
|
||||
binary(tr);
|
||||
C_ior(wordsize);
|
||||
return;
|
||||
|
||||
case EOR:
|
||||
binary(tr);
|
||||
C_xor(wordsize);
|
||||
return;
|
||||
|
||||
case LSHIFT:
|
||||
binary(tr);
|
||||
C_sli(wordsize);
|
||||
return;
|
||||
|
||||
case RSHIFT:
|
||||
binary(tr);
|
||||
C_sri(wordsize);
|
||||
return;
|
||||
|
||||
case EQUAL:
|
||||
case NEQUAL:
|
||||
case LESS:
|
||||
case LESSEQ:
|
||||
case GREAT:
|
||||
case GREATEQ:
|
||||
binary(tr);
|
||||
C_cmi(wordsize);
|
||||
switch (tr->op) {
|
||||
case EQUAL:
|
||||
C_teq();
|
||||
break;
|
||||
case NEQUAL:
|
||||
C_tne();
|
||||
break;
|
||||
case LESS:
|
||||
C_tlt();
|
||||
break;
|
||||
case LESSEQ:
|
||||
C_tle();
|
||||
break;
|
||||
case GREAT:
|
||||
C_tgt();
|
||||
break;
|
||||
case GREATEQ:
|
||||
C_tge();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
case EXCLA:
|
||||
rcexpr(tr->tr1);
|
||||
C_teq();
|
||||
return;
|
||||
|
||||
case NEG:
|
||||
rcexpr(tr->tr1);
|
||||
C_ngi(wordsize);
|
||||
return;
|
||||
|
||||
case NOT:
|
||||
rcexpr(tr->tr1);
|
||||
C_com(wordsize);
|
||||
return;
|
||||
|
||||
case QUEST:
|
||||
cbranch(tr->tr1, o1=isn++);
|
||||
rcexpr(tr->tr2->tr1);
|
||||
jump(o2 = isn++);
|
||||
fnlabel(o1);
|
||||
rcexpr(tr->tr2->tr2);
|
||||
fnlabel(o2);
|
||||
return;
|
||||
|
||||
default:
|
||||
error("Can't print tree (op: %d)", tr->op);
|
||||
}
|
||||
|
||||
classerror:
|
||||
error("Storage class");
|
||||
}
|
||||
|
||||
/* Prints the tree in RPN, for debugging */
|
||||
/*
|
||||
void
|
||||
rcexpr(struct tnode *tr)
|
||||
{
|
||||
struct hshtab *bs;
|
||||
|
||||
if (tr == NULL)
|
||||
printf("(NULL) ");
|
||||
else if (tr->op == CON)
|
||||
printf("%d ", tr->value);
|
||||
else if (tr->op == STRING)
|
||||
printf("s(L%d) ", tr->value);
|
||||
else if (tr->op == NAME) {
|
||||
bs = (struct hshtab *)tr->tr1;
|
||||
if (bs->class == AUTO)
|
||||
printf("%s(%d) ", bs->name, bs->offset);
|
||||
else
|
||||
printf("%s ", bs->name);
|
||||
} else {
|
||||
rcexpr(tr->tr1);
|
||||
if (opdope[tr->op]&01)
|
||||
rcexpr(tr->tr2);
|
||||
printtoken(tr->op, stdout);
|
||||
}
|
||||
}
|
||||
*/
|
28
lang/b/compiler/build.lua
Normal file
28
lang/b/compiler/build.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
cprogram {
|
||||
name = "em_b",
|
||||
srcs = {
|
||||
"./*.c",
|
||||
},
|
||||
deps = {
|
||||
"./*.h",
|
||||
"modules+headers",
|
||||
"modules/src/alloc+lib",
|
||||
"modules/src/data+lib",
|
||||
"modules/src/em_code+lib_k",
|
||||
"modules/src/em_data+lib",
|
||||
"modules/src/em_mes+lib",
|
||||
"modules/src/print+lib",
|
||||
"modules/src/string+lib",
|
||||
"modules/src/system+lib",
|
||||
}
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = {
|
||||
["$(PLATDEP)/em_b"] = "+em_b",
|
||||
["$(INSDIR)/share/man/man6/em_b.6"] = "./em_b.6"
|
||||
}
|
||||
}
|
||||
|
53
lang/b/compiler/em_b.6
Normal file
53
lang/b/compiler/em_b.6
Normal file
|
@ -0,0 +1,53 @@
|
|||
.TH EM_B 6 2017-01-18
|
||||
.ad
|
||||
.SH NAME
|
||||
em_b \- ACK B compiler
|
||||
.SH SYNOPSIS
|
||||
.B ~em/lib/ack/em_b
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.I em_b
|
||||
is a port of the ABC B compiler to the ACK.
|
||||
Interested parties will be
|
||||
interested in the upstream distribution here:
|
||||
.nf
|
||||
.sp
|
||||
https://github.com/aap/abc
|
||||
.fi
|
||||
.PP
|
||||
However, the version here has been heavily modified \(em bug reports should be
|
||||
filed with the ACK, not with the upstream compiler.
|
||||
.PP
|
||||
Since B was designed for machines with word addressing, some hacking is
|
||||
required to make it work on modern, byte addressed machines.
|
||||
The generated
|
||||
code expects B variables to contain word addresses, and then generates
|
||||
code to transform these into native addresses before use (which,
|
||||
unfortunately, impacts performance).
|
||||
However, the ACK's linker doesn't know
|
||||
how to emit word addresses into the program's data sections, and so a
|
||||
separate fixup stage has to happen at runtime, just before \fBmain()\fP,
|
||||
to convert the byte addresses into word addresses.
|
||||
.PP
|
||||
The end result is that using multiple source files with B is somewhat
|
||||
unwieldy, requiring each module to be explicitly named and then an extra
|
||||
stage to generate the fixup code.
|
||||
See the \fBack\fP(1) and \fBabmodules\fP(1) for details.
|
||||
.SH OPTIONS
|
||||
.I em_b
|
||||
accepts the following flags:
|
||||
.IP \-w\ \fIsize\fP
|
||||
Sets the word size, used for scaling addresses.
|
||||
Usually either 2 or 4.
|
||||
.IP \-B\ \fIname\fP
|
||||
Sets the name of the module currently being compiled (used to generate the
|
||||
fixup table symbol name).
|
||||
Defaults to \fImain\fP if not specified.
|
||||
.IP \-i\ \fIfilename\fP
|
||||
The source B file.
|
||||
.IP \-o\ \fIfilename\fP
|
||||
The output compact EM bytecode file.
|
||||
.SH SEE ALSO
|
||||
\fIack\fR(1), \fIabmodules\fR(1)
|
||||
.SH REMARKS
|
||||
It is very unlikely the \fIem_b\fP will ever be useful for anything.
|
15
lang/b/distr/Makefile
Normal file
15
lang/b/distr/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
CFLAGS=-Wall -Wextra
|
||||
b: b0.o b1.o
|
||||
cc b0.o b1.o -o b
|
||||
b0.o: b0.c b.h
|
||||
b1.o: b1.c b.h
|
||||
|
||||
libs:
|
||||
./abc -c brt.s lib.b
|
||||
|
||||
install: b abc
|
||||
cp abc $(HOME)/bin
|
||||
|
||||
%.o: %.s
|
||||
as --32 $^ -o $@
|
||||
|
95
lang/b/distr/abc
Executable file
95
lang/b/distr/abc
Executable file
|
@ -0,0 +1,95 @@
|
|||
#!/bin/sh
|
||||
BDIR="$HOME/abc"
|
||||
objs="$BDIR/brt.o $BDIR/lib.o"
|
||||
BC="$BDIR/b"
|
||||
|
||||
# compile in.b [out.s]
|
||||
compile() {
|
||||
if [ "${1##*.}" != "b" ]; then
|
||||
echo "Error: can only compile b files" >&2
|
||||
exit 1
|
||||
fi
|
||||
cout=$2
|
||||
[ "$cout" != "" ] || cout=${1%b}s
|
||||
tmp1=`mktemp`; tmp2=`mktemp`
|
||||
$BC $1 $tmp2 $tmp1
|
||||
retval=$?
|
||||
cat $tmp1 $tmp2 > $cout
|
||||
rm $tmp1 $tmp2
|
||||
[ $retval -eq 0 ] || rm $cout && return $retval
|
||||
echo $cout
|
||||
return $retval
|
||||
}
|
||||
|
||||
# assemble in.{sb} [out.o]
|
||||
assemble() {
|
||||
atmp=""
|
||||
ain=$1
|
||||
aout=$2;
|
||||
if [ "${1##*.}" = "b" ]; then
|
||||
[ "$aout" != "" ] || aout=${ain%b}o
|
||||
ain=`mktemp --suffix=.s`
|
||||
compile $1 $ain >/dev/null || return 1
|
||||
atmp="foo"
|
||||
elif [ "${1##*.}" = "s" ]; then
|
||||
[ "$aout" != "" ] || aout=${ain%s}o
|
||||
else
|
||||
echo "Error: can only compile b and s files" >&2
|
||||
exit 1
|
||||
fi
|
||||
as --32 -g $ain -o $aout
|
||||
[ "$atmp" != "" ] && rm $ain
|
||||
echo $aout
|
||||
}
|
||||
|
||||
out=""
|
||||
action="link"
|
||||
while getopts "o:Sc" o
|
||||
do case "$o" in
|
||||
o) out="$OPTARG";;
|
||||
S) action=compile;;
|
||||
c) action=assemble;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
# ignore -o option if more than one file given and not linking objs
|
||||
if [ $# -gt 1 ]; then
|
||||
if [ "$action" != "link" ]; then
|
||||
out=""
|
||||
fi
|
||||
fi
|
||||
|
||||
[ $# -ne 1 ] && havelist=yes
|
||||
tmpobjs=""
|
||||
for i in $@; do
|
||||
if [ "$action" != "link" ]; then
|
||||
[ "$havelist" = "yes" ] && echo $i:
|
||||
$action $i $out >/dev/null
|
||||
[ $? -eq 0 ] || break=1
|
||||
else
|
||||
if [ "${i##*.}" = "o" ]; then
|
||||
objs="$objs $i"
|
||||
else
|
||||
[ "$havelist" = "yes" ] && echo $i:
|
||||
ltmp=`mktemp --suffix=.o`
|
||||
tmpobjs="$tmpobjs $ltmp"
|
||||
assemble $i $ltmp >/dev/null
|
||||
[ $? -eq 0 ] || break=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ $break ]; then
|
||||
[ "$tmpobjs" = "" ] || rm $tmpobjs
|
||||
echo "Error" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$action" = "link" ]; then
|
||||
if [ "$out" = "" ]; then
|
||||
out="-o a.out"
|
||||
else
|
||||
out="-o $out"
|
||||
fi
|
||||
ld -m elf_i386 -T $BDIR/link.ld $out $objs $tmpobjs
|
||||
rm $tmpobjs
|
||||
fi
|
151
lang/b/distr/brt.s
Normal file
151
lang/b/distr/brt.s
Normal file
|
@ -0,0 +1,151 @@
|
|||
.globl _argv
|
||||
.data
|
||||
.align 4
|
||||
.comm argstr,256,4
|
||||
_argv: .long 0
|
||||
|
||||
.text
|
||||
.globl start
|
||||
start:
|
||||
# clear bss (could be done better)
|
||||
# is it actually necessary?
|
||||
mov $__bss,%eax
|
||||
1:
|
||||
movb $0,(%eax)
|
||||
inc %eax
|
||||
cmp $__ebss,%eax
|
||||
jbe 1b
|
||||
|
||||
# copy command line args (can't use them directly, not aligned)
|
||||
mov %esp,%eax
|
||||
shr $2,%eax
|
||||
mov %eax,_argv
|
||||
mov (%esp),%ecx # number of arguments
|
||||
mov $argstr,%edi
|
||||
1:
|
||||
mov (%esp,%ecx,4),%esi
|
||||
mov %edi,%eax
|
||||
shr $2,%eax
|
||||
mov %eax,(%esp,%ecx,4)
|
||||
call cpystr
|
||||
loop 1b
|
||||
|
||||
call bsymbs
|
||||
mov _main,%eax
|
||||
shl $2,%eax
|
||||
call *%eax
|
||||
mov %eax,%ebx
|
||||
mov $1,%eax
|
||||
int $0x80
|
||||
|
||||
# copy string from esi to edi and convert '\0' to B's '*e', align edi
|
||||
cpystr:
|
||||
mov (%esi),%al
|
||||
test %al,%al
|
||||
jz 1f
|
||||
mov %al,(%edi)
|
||||
inc %edi
|
||||
inc %esi
|
||||
jmp cpystr
|
||||
1:
|
||||
movb $04,(%edi)
|
||||
inc %edi
|
||||
add $3,%edi
|
||||
and $~3,%edi
|
||||
ret
|
||||
|
||||
# shift addresses filled in by the linker 2 bits to the right
|
||||
# so B only ever sees word addresses
|
||||
bsymbs:
|
||||
mov $__bsymb,%eax
|
||||
1:
|
||||
cmp $__ebsymb,%eax
|
||||
jge 1f
|
||||
mov (%eax),%ebx
|
||||
mov (%ebx),%ecx
|
||||
shr $2,%ecx
|
||||
mov %ecx,(%ebx)
|
||||
add $4,%eax
|
||||
jmp 1b
|
||||
1:
|
||||
ret
|
||||
|
||||
.globl retrn
|
||||
retrn:
|
||||
mov %ebp,%esp
|
||||
pop %ebp
|
||||
ret
|
||||
|
||||
# handle switch table:
|
||||
# eax has the value, ebx the address of the switch table
|
||||
.globl bswitch
|
||||
bswitch:
|
||||
xor %ecx,%ecx
|
||||
1:
|
||||
mov (%ebx,%ecx,8),%edx
|
||||
mov 4(%ebx,%ecx,8),%edi
|
||||
test %edi,%edi
|
||||
jz 1f # default (last in table)
|
||||
cmp %eax,%edx
|
||||
je 2f
|
||||
inc %ecx
|
||||
jmp 1b
|
||||
1:
|
||||
jmp *%edx
|
||||
2:
|
||||
jmp *%edi
|
||||
|
||||
#
|
||||
# Library functions in assembly
|
||||
#
|
||||
.globl _exit
|
||||
.data
|
||||
.align 4
|
||||
.section .bsymb; .long _exit; .data
|
||||
_exit: .long 1f
|
||||
.text
|
||||
.align 4
|
||||
1: mov $1,%eax
|
||||
mov $0,%ebx
|
||||
int $0x80
|
||||
|
||||
.globl _write
|
||||
.data
|
||||
.align 4
|
||||
.section .bsymb; .long _write; .data
|
||||
_write: .long 1f
|
||||
.text
|
||||
.align 4
|
||||
1: mov 4(%esp),%ebx
|
||||
mov 8(%esp),%ecx
|
||||
shl $2,%ecx
|
||||
mov 12(%esp),%edx
|
||||
mov $4,%eax
|
||||
int $0x80
|
||||
ret
|
||||
|
||||
.globl _read
|
||||
.data
|
||||
.align 4
|
||||
.section .bsymb; .long _read; .data
|
||||
_read: .long 1f
|
||||
.text
|
||||
.align 4
|
||||
1: mov 4(%esp),%ebx
|
||||
mov 8(%esp),%ecx
|
||||
shl $2,%ecx
|
||||
mov 12(%esp),%edx
|
||||
mov $3,%eax
|
||||
int $0x80
|
||||
ret
|
||||
|
||||
.globl _inv
|
||||
.data
|
||||
.align 4
|
||||
.section .bsymb; .long _inv; .data
|
||||
_inv: .long 1f
|
||||
.text
|
||||
.align 4
|
||||
1: mov 4(%esp),%eax
|
||||
not %eax
|
||||
ret
|
7
lang/b/distr/examples/1_var.b
Normal file
7
lang/b/distr/examples/1_var.b
Normal file
|
@ -0,0 +1,7 @@
|
|||
main() {
|
||||
auto a, b, c, sum;
|
||||
|
||||
a = 1; b = 2; c = 3;
|
||||
sum = a+b+c;
|
||||
putnumb(sum);
|
||||
}
|
9
lang/b/distr/examples/2_ext.b
Normal file
9
lang/b/distr/examples/2_ext.b
Normal file
|
@ -0,0 +1,9 @@
|
|||
main() {
|
||||
extrn a, b, c;
|
||||
putchar(a); putchar(b); putchar(c); putchar('!*n');
|
||||
}
|
||||
|
||||
a 'hell';
|
||||
b 'o, w';
|
||||
c 'orld';
|
||||
|
13
lang/b/distr/examples/3_fun.b
Normal file
13
lang/b/distr/examples/3_fun.b
Normal file
|
@ -0,0 +1,13 @@
|
|||
main() {
|
||||
extrn a, b, c, d;
|
||||
put2char(a,b);
|
||||
put2char(c,d);
|
||||
}
|
||||
|
||||
put2char(x,y) {
|
||||
putchar(x);
|
||||
putchar(y);
|
||||
}
|
||||
|
||||
a 'hell'; b 'o, w'; c 'orld'; d '!*n';
|
||||
|
7
lang/b/distr/examples/4_goto.b
Normal file
7
lang/b/distr/examples/4_goto.b
Normal file
|
@ -0,0 +1,7 @@
|
|||
main() {
|
||||
auto c;
|
||||
read:
|
||||
c= getchar();
|
||||
putchar(c);
|
||||
if(c != '*n') goto read;
|
||||
}
|
10
lang/b/distr/examples/5_while.b
Normal file
10
lang/b/distr/examples/5_while.b
Normal file
|
@ -0,0 +1,10 @@
|
|||
main() {
|
||||
auto c;
|
||||
while (1) {
|
||||
while ( (c=getchar()) != ' ')
|
||||
if (putchar(c) == '*n') exit();
|
||||
putchar( '*n' );
|
||||
while ( (c=getchar()) == ' '); /* skip blanks */
|
||||
if (putchar(c)=='*n') exit();
|
||||
}
|
||||
}
|
10
lang/b/distr/examples/printargs.b
Normal file
10
lang/b/distr/examples/printargs.b
Normal file
|
@ -0,0 +1,10 @@
|
|||
main() {
|
||||
extrn argv;
|
||||
auto i;
|
||||
|
||||
i = 1;
|
||||
printf("%d args:*n", argv[0]);
|
||||
while (i <= argv[0])
|
||||
printf("%s*n", argv[i++]);
|
||||
return(0);
|
||||
}
|
111
lang/b/distr/lib.b
Normal file
111
lang/b/distr/lib.b
Normal file
|
@ -0,0 +1,111 @@
|
|||
char(s, n)
|
||||
return((s[n/4]>>8*(n%4))&0377); /* s[n/4] */
|
||||
|
||||
lchar(s, n, char) {
|
||||
auto i;
|
||||
i = 8*(n%4);
|
||||
char = (char&0377)<<i;
|
||||
i = inv(0377<<i);
|
||||
s[(n/4)*4] = s[n/4]&i | char;
|
||||
}
|
||||
|
||||
putchar(char) {
|
||||
auto c, i;
|
||||
|
||||
c = char;
|
||||
i = 4;
|
||||
while ((c&0377) != '*e' & (c&0377) != '*0' & i != 0) {
|
||||
i--;
|
||||
c =>> 8;
|
||||
}
|
||||
write(1, &char, 4-i);
|
||||
return(char);
|
||||
}
|
||||
|
||||
getchar() {
|
||||
auto char;
|
||||
|
||||
char = 0;
|
||||
read(1, &char, 1);
|
||||
return(char);
|
||||
}
|
||||
|
||||
printn(n,b) {
|
||||
extrn putchar;
|
||||
auto a;
|
||||
|
||||
if (a = n/b)
|
||||
printn(a, b);
|
||||
putchar(char("0123456789ABCDEF", n%b));
|
||||
}
|
||||
|
||||
putnumb(n) {
|
||||
printn(n,10);
|
||||
putchar('*n');
|
||||
}
|
||||
|
||||
putstr(s) {
|
||||
auto c, i;
|
||||
|
||||
i = 0;
|
||||
while ((c = char(s,i++)) != '*e')
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
getstr(s) {
|
||||
auto c, i;
|
||||
|
||||
while ((c = getchar()) != '*n')
|
||||
lchar(s,i++,c);
|
||||
lchar(s,i,'*e');
|
||||
return(s);
|
||||
}
|
||||
|
||||
printf(fmt, x1,x2,x3,x4,x5,x6,x7,x8,x9) {
|
||||
extrn printn, char, putchar;
|
||||
auto adx, x, c, i, j;
|
||||
|
||||
i = 0;
|
||||
adx = &x1;
|
||||
loop:
|
||||
while((c=char(fmt,i++)) != '%') {
|
||||
if(c == '*e')
|
||||
return;
|
||||
putchar(c);
|
||||
}
|
||||
x = *adx++;
|
||||
switch (c = char(fmt,i++)) {
|
||||
|
||||
case 'd':
|
||||
case 'o':
|
||||
if(x < 0) {
|
||||
x = -x;
|
||||
putchar('-');
|
||||
}
|
||||
printn(x, c=='o'?8:10);
|
||||
goto loop;
|
||||
|
||||
case 'x':
|
||||
if(x < 0) {
|
||||
x = -x;
|
||||
putchar('-');
|
||||
}
|
||||
printn(x, 16);
|
||||
goto loop;
|
||||
|
||||
case 'c':
|
||||
putchar(x);
|
||||
goto loop;
|
||||
|
||||
case 's':
|
||||
j = 0;
|
||||
while((c=char(x,j++)) != '*e')
|
||||
putchar(c);
|
||||
goto loop;
|
||||
}
|
||||
putchar('%');
|
||||
i--;
|
||||
adx--;
|
||||
goto loop;
|
||||
}
|
||||
|
21
lang/b/distr/link.ld
Normal file
21
lang/b/distr/link.ld
Normal file
|
@ -0,0 +1,21 @@
|
|||
OUTPUT_FORMAT("elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x400000;
|
||||
.text : { *(.text) }
|
||||
. = 0x8000000;
|
||||
.data : {
|
||||
*(.data)
|
||||
__bsymb = .;
|
||||
*(.bsymb)
|
||||
__ebsymb = .;
|
||||
}
|
||||
. = ALIGN(16);
|
||||
__bss = .;
|
||||
.bss : { *(.bss) }
|
||||
__ebss = .;
|
||||
}
|
28
lang/b/lib/b.h
Normal file
28
lang/b/lib/b.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef B_H
|
||||
#define B_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if EM_PSIZE == 2
|
||||
#define SHIFT 1
|
||||
#elif EM_PSIZE == 4
|
||||
#define SHIFT 2
|
||||
#elif EM_PSIZE == 8
|
||||
#define SHIFT 3
|
||||
#else
|
||||
#error Unsupported EM_PSIZE
|
||||
#endif
|
||||
|
||||
extern FILE* input_unit;
|
||||
extern FILE* output_unit;
|
||||
|
||||
#define END 4
|
||||
|
||||
extern uintptr_t* bmodule_main[];
|
||||
|
||||
extern void patch_addresses(uintptr_t** p);
|
||||
|
||||
extern void binit(void);
|
||||
|
||||
#endif
|
27
lang/b/lib/build.lua
Normal file
27
lang/b/lib/build.lua
Normal file
|
@ -0,0 +1,27 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
for _, plat in ipairs(vars.plats) do
|
||||
acklibrary {
|
||||
name = "lib_"..plat,
|
||||
srcs = {
|
||||
"./*.c",
|
||||
"./*.e",
|
||||
},
|
||||
hdrs = {}, -- must be empty
|
||||
deps = {
|
||||
"./*.h",
|
||||
"h+emheaders",
|
||||
"lang/cem/libcc.ansi/headers+pkg",
|
||||
"plat/"..plat.."/include+pkg",
|
||||
},
|
||||
vars = { plat = plat }
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg_"..plat,
|
||||
map = {
|
||||
["$(PLATIND)/"..plat.."/libb.a"] = "+lib_"..plat,
|
||||
}
|
||||
}
|
||||
end
|
||||
|
10
lang/b/lib/init.c
Normal file
10
lang/b/lib/init.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "b.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
void binit(void)
|
||||
{
|
||||
patch_addresses(bmodule_main);
|
||||
}
|
||||
|
186
lang/b/lib/main.c
Normal file
186
lang/b/lib/main.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include "b.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
extern intptr_t i_main(intptr_t argc, const char* argv[]);
|
||||
|
||||
FILE* input_unit;
|
||||
FILE* output_unit;
|
||||
|
||||
static intptr_t i_char(intptr_t s, intptr_t n)
|
||||
{
|
||||
const char* p = (const char*)(s<<SHIFT);
|
||||
return p[n];
|
||||
}
|
||||
|
||||
static void i_lchar(intptr_t s, intptr_t n, intptr_t c)
|
||||
{
|
||||
char* p = (char*)(s<<SHIFT);
|
||||
p[n] = c;
|
||||
}
|
||||
|
||||
static intptr_t i_getchar(void)
|
||||
{
|
||||
return fgetc(input_unit);
|
||||
}
|
||||
|
||||
static intptr_t i_putchar(intptr_t c)
|
||||
{
|
||||
fputc(c, output_unit);
|
||||
return c;
|
||||
}
|
||||
|
||||
static intptr_t i_putstr(intptr_t s)
|
||||
{
|
||||
char* p = (char*)(s<<SHIFT);
|
||||
char c;
|
||||
|
||||
while ((c = *p++) != END)
|
||||
fputc(c, output_unit);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static intptr_t i_getstr(intptr_t s)
|
||||
{
|
||||
char* p = (char*)(s<<SHIFT);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int c = fgetc(input_unit);
|
||||
if ((c == -1) || (c == '\n'))
|
||||
break;
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
*p++ = END;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void i_flush(void)
|
||||
{
|
||||
fflush(output_unit);
|
||||
}
|
||||
|
||||
static int tochar(int n)
|
||||
{
|
||||
if (n <= 9)
|
||||
return n + '0';
|
||||
return n - 10 + 'a';
|
||||
}
|
||||
|
||||
static void putnum(intptr_t value, int base)
|
||||
{
|
||||
int i;
|
||||
char s[32];
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
fputc('-', output_unit);
|
||||
value = -value;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do
|
||||
s[i++] = tochar(value % base);
|
||||
while ((value /= base) > 0);
|
||||
|
||||
do
|
||||
fputc(s[--i], output_unit);
|
||||
while (i > 0);
|
||||
}
|
||||
|
||||
static void i_printf(intptr_t s, ...)
|
||||
{
|
||||
char* p = (char*)(s<<SHIFT);
|
||||
char c;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, s);
|
||||
|
||||
while ((c = *p++) != END)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
intptr_t ss = va_arg(ap, intptr_t);
|
||||
|
||||
switch ((c = *p++))
|
||||
{
|
||||
case 's':
|
||||
i_putstr(ss);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
putnum(ss, 10);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
putnum(ss, 8);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
putnum(ss, 16);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
fputc(ss, output_unit);
|
||||
break;
|
||||
|
||||
default:
|
||||
fputc('?', output_unit);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
fputc(c, output_unit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
uintptr_t b_char = (uintptr_t)i_char;
|
||||
uintptr_t b_lchar = (uintptr_t)i_lchar;
|
||||
uintptr_t b_getchar = (uintptr_t)i_getchar;
|
||||
uintptr_t b_putchar = (uintptr_t)i_putchar;
|
||||
uintptr_t b_putstr = (uintptr_t)i_putstr;
|
||||
uintptr_t b_getstr = (uintptr_t)i_getstr;
|
||||
uintptr_t b_flush = (uintptr_t)i_flush;
|
||||
uintptr_t b_printf = (uintptr_t)i_printf;
|
||||
|
||||
static uintptr_t* bmodule_stdlib[] =
|
||||
{
|
||||
&b_char,
|
||||
&b_lchar,
|
||||
&b_getchar,
|
||||
&b_putchar,
|
||||
&b_putstr,
|
||||
&b_getstr,
|
||||
&b_flush,
|
||||
&b_printf,
|
||||
0
|
||||
};
|
||||
|
||||
void patch_addresses(uintptr_t** p)
|
||||
{
|
||||
while (*p)
|
||||
{
|
||||
uintptr_t* q = *p++;
|
||||
*q >>= SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
patch_addresses(bmodule_stdlib);
|
||||
binit();
|
||||
input_unit = stdin;
|
||||
output_unit = stdout;
|
||||
return i_main(argc, NULL);
|
||||
}
|
|
@ -10,8 +10,8 @@ for _, plat in ipairs(vars.plats) do
|
|||
hdrs = {}, -- must be empty
|
||||
deps = {
|
||||
"h+emheaders",
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/"..plat.."/include+headers",
|
||||
"lang/cem/libcc.ansi/headers+pkg",
|
||||
"plat/"..plat.."/include+pkg",
|
||||
},
|
||||
vars = { plat = plat }
|
||||
}
|
||||
|
|
|
@ -522,7 +522,7 @@ scanstring()
|
|||
yylval.integer= genemlabel();
|
||||
C_rom_dlb((label)i,(arith)0);
|
||||
C_rom_icon("9999",(arith)BEMINTSIZE);
|
||||
C_rom_icon(itoa(length),(arith)BEMINTSIZE);
|
||||
C_rom_icon(myitoa(length),(arith)BEMINTSIZE);
|
||||
}
|
||||
#ifdef YYDEBUG
|
||||
if (yydebug) print("STRVALUE found\n");
|
||||
|
|
|
@ -72,5 +72,5 @@ extern int dataused;
|
|||
extern Linerecord *currline;
|
||||
|
||||
|
||||
extern char *itoa();
|
||||
extern char *myitoa();
|
||||
extern char *salloc();
|
||||
|
|
|
@ -670,7 +670,7 @@ gendata()
|
|||
C_df_dnam("datfdes");
|
||||
C_rom_dnam("datfname",(arith)0);
|
||||
C_rom_cst((arith)1);
|
||||
C_rom_cst((arith)(itoa(strlen(datfname))));
|
||||
C_rom_cst((arith)(myitoa(strlen(datfname))));
|
||||
C_df_dnam("dattdes");
|
||||
C_rom_dnam("dattyp",(arith)0);
|
||||
C_rom_cst((arith)1);
|
||||
|
|
|
@ -69,7 +69,7 @@ illegalcmd()
|
|||
|
||||
|
||||
|
||||
char *itoa(i)
|
||||
char *myitoa(i)
|
||||
int i;
|
||||
{
|
||||
static char buf[30];
|
||||
|
|
|
@ -51,8 +51,8 @@ for _, plat in ipairs(vars.plats) do
|
|||
},
|
||||
hdrs = {}, -- must be empty
|
||||
deps = {
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/"..plat.."/include+headers",
|
||||
"lang/cem/libcc.ansi/headers+pkg",
|
||||
"plat/"..plat.."/include+pkg",
|
||||
"./malloc/malloc.h",
|
||||
"./math/localmath.h",
|
||||
"./stdio/loc_incl.h",
|
||||
|
|
|
@ -113,6 +113,7 @@ cprogram {
|
|||
"h+emheaders",
|
||||
"modules+headers",
|
||||
"modules/src/alloc+lib",
|
||||
"modules/src/data+lib",
|
||||
"modules/src/em_code+lib_k",
|
||||
"modules/src/em_data+lib",
|
||||
"modules/src/em_mes+lib",
|
||||
|
|
|
@ -9,26 +9,27 @@
|
|||
|
||||
/* $Id$ */
|
||||
|
||||
#include "parameters.h"
|
||||
#include "debug.h"
|
||||
#include "parameters.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <alloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <astring.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "def.h"
|
||||
#include "f_info.h"
|
||||
#include "idf.h"
|
||||
#include "input.h"
|
||||
#include "scope.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "Lpars.h"
|
||||
#include "f_info.h"
|
||||
#include "main.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
#include "misc.h"
|
||||
#include "node.h"
|
||||
#include "scope.h"
|
||||
#include "type.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
long sys_filesize();
|
||||
|
@ -37,18 +38,19 @@ long sys_filesize();
|
|||
t_idf* DefId;
|
||||
|
||||
char*
|
||||
getwdir(fn)
|
||||
register char *fn;
|
||||
getwdir(fn) register char* fn;
|
||||
{
|
||||
register char* p;
|
||||
char* strrchr();
|
||||
|
||||
while ((p = strrchr(fn,'/')) && *(p + 1) == '\0') {
|
||||
while ((p = strrchr(fn, '/')) && *(p + 1) == '\0')
|
||||
{
|
||||
/* remove trailing /'s */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (p) {
|
||||
if (p)
|
||||
{
|
||||
*p = '\0';
|
||||
fn = Salloc(fn, (unsigned)(p - &fn[0] + 1));
|
||||
*p = '/';
|
||||
|
@ -58,20 +60,15 @@ getwdir(fn)
|
|||
}
|
||||
|
||||
STATIC
|
||||
GetFile(name)
|
||||
char *name;
|
||||
GetFile(name) char* name;
|
||||
{
|
||||
/* Try to find a file with basename "name" and extension ".def",
|
||||
in the directories mentioned in "DEFPATH".
|
||||
*/
|
||||
char buf[15];
|
||||
char *strncpy(), *strcat();
|
||||
|
||||
strncpy(buf, name, 10);
|
||||
buf[10] = '\0'; /* maximum length */
|
||||
strcat(buf, ".def");
|
||||
char* buf = aprintf("%s.def", name);
|
||||
DEFPATH[0] = WorkingDir;
|
||||
if (! InsertFile(buf, DEFPATH, &(FileName))) {
|
||||
if (!InsertFile(buf, DEFPATH, &(FileName)))
|
||||
{
|
||||
error("could not find a DEFINITION MODULE for \"%s\"", name);
|
||||
return 0;
|
||||
}
|
||||
|
@ -82,8 +79,7 @@ GetFile(name)
|
|||
}
|
||||
|
||||
t_def*
|
||||
GetDefinitionModule(id, incr)
|
||||
register t_idf *id;
|
||||
GetDefinitionModule(id, incr) register t_idf* id;
|
||||
{
|
||||
/* Return a pointer to the "def" structure of the definition
|
||||
module indicated by "id".
|
||||
|
@ -99,7 +95,8 @@ GetDefinitionModule(id, incr)
|
|||
|
||||
level += incr;
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
if (!df) {
|
||||
if (!df)
|
||||
{
|
||||
/* Read definition module. Make an exception for SYSTEM.
|
||||
*/
|
||||
extern int ForeignFlag;
|
||||
|
@ -110,18 +107,21 @@ GetDefinitionModule(id, incr)
|
|||
newsc = CurrentScope;
|
||||
vis = CurrVis;
|
||||
newsc->sc_defmodule = incr;
|
||||
if (!strcmp(id->id_text, "SYSTEM")) {
|
||||
if (!strcmp(id->id_text, "SYSTEM"))
|
||||
{
|
||||
do_SYSTEM();
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
}
|
||||
else {
|
||||
if (!is_anon_idf(id) && GetFile(id->id_text)) {
|
||||
else
|
||||
{
|
||||
if (!is_anon_idf(id) && GetFile(id->id_text))
|
||||
{
|
||||
|
||||
char* f = FileName;
|
||||
DefModule();
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
if (level == 1 &&
|
||||
(df && !(df->df_flags & D_FOREIGN))) {
|
||||
if (level == 1 && (df && !(df->df_flags & D_FOREIGN)))
|
||||
{
|
||||
/* The module is directly imported by
|
||||
the currently defined module, and
|
||||
is not foreign, so we have to
|
||||
|
@ -134,29 +134,35 @@ GetDefinitionModule(id, incr)
|
|||
|
||||
n = dot2leaf(Def);
|
||||
n->nd_def = newsc->sc_definedby;
|
||||
if (nd_end) nd_end->nd_NEXT = n;
|
||||
else Modules = n;
|
||||
if (nd_end)
|
||||
nd_end->nd_NEXT = n;
|
||||
else
|
||||
Modules = n;
|
||||
nd_end = n;
|
||||
}
|
||||
free(f);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
newsc->sc_name = id->id_text;
|
||||
}
|
||||
}
|
||||
close_scope(SC_CHKFORW);
|
||||
if (! df) {
|
||||
if (!df)
|
||||
{
|
||||
df = MkDef(id, GlobalScope, D_ERROR);
|
||||
df->mod_vis = vis;
|
||||
newsc->sc_definedby = df;
|
||||
}
|
||||
}
|
||||
else if (df->df_flags & D_BUSY) {
|
||||
else if (df->df_flags & D_BUSY)
|
||||
{
|
||||
error("definition module \"%s\" depends on itself",
|
||||
id->id_text);
|
||||
}
|
||||
else if (df == Defined && level == 1) {
|
||||
else if (df == Defined && level == 1)
|
||||
{
|
||||
error("cannot import from current module \"%s\"", id->id_text);
|
||||
df->df_kind = D_ERROR;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.TH EM_M2 6 "$Revision$"
|
||||
.TH EM_M2 6 2017-01-18
|
||||
.ad
|
||||
.SH NAME
|
||||
em_m2 \- ACK Modula\-2 compiler
|
||||
|
@ -17,7 +17,7 @@ The input is taken from
|
|||
while the
|
||||
EM code is written on
|
||||
.IR destination .
|
||||
.br
|
||||
.PP
|
||||
.I Option
|
||||
is a, possibly empty, sequence of the following combinations:
|
||||
.IP \fB\-I\fIdirname\fR
|
||||
|
@ -65,7 +65,8 @@ make all procedure names global, so that \fIadb\fR(1) understands them.
|
|||
.IP \fB\-g\fR
|
||||
produce a DBX-style symbol table.
|
||||
.IP \fB\-l\fR
|
||||
enable local extensions. Currently, there are two local extensions:
|
||||
enable local extensions.
|
||||
Currently, there are two local extensions:
|
||||
procedure constants, and the type LONGCARD.
|
||||
.IP \fB\-s\fR
|
||||
make INTEGER ranges symmetric, t.i., MIN(INTEGER) = - MAX(INTEGER).
|
||||
|
@ -77,11 +78,11 @@ disable all range checks.
|
|||
enable extra array bound checks, for machines that do not implement the
|
||||
EM ones.
|
||||
.IP \fB-U\fR
|
||||
allow for underscores within identifiers. Identifiers may not start with
|
||||
allow for underscores within identifiers.
|
||||
Identifiers may not start with
|
||||
an underscore, even if this flag is given.
|
||||
.IP \fB-3\fR
|
||||
only accept Modula-2 programs that strictly conform to [1].
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
\fIack\fR(1), \fImodula-2\fR(1)
|
||||
.IP [1]
|
||||
|
|
|
@ -19,11 +19,6 @@ Implementation modules and program modules must reside in files having a
|
|||
.PP
|
||||
The name of the file in which a definition module is stored must be the same as
|
||||
the module-name, apart from the extension.
|
||||
Also, in most Unix systems filenames are only 14 characters long.
|
||||
So, given an IMPORT declaration for a module called "LongModulName",
|
||||
the compiler will try to open a file called "LongModulN.def".
|
||||
The requirement does not hold for implementation or program modules,
|
||||
but is certainly recommended.
|
||||
.SH CALLING THE COMPILER
|
||||
The easiest way to do this is to let the \fIack\fR(1) program do it.
|
||||
So, to compile a program module "prog.mod", just call
|
||||
|
|
|
@ -76,7 +76,8 @@ void DoAssign();
|
|||
|
||||
int
|
||||
LblWalkNode(lbl, nd, exit, reach)
|
||||
label lbl, exit;
|
||||
label lbl,
|
||||
exit;
|
||||
t_node* nd;
|
||||
{
|
||||
/* Generate code for node "nd", after generating instruction
|
||||
|
@ -96,7 +97,8 @@ DoPriority()
|
|||
/* For the time being (???), handle priorities by calls to
|
||||
the runtime system
|
||||
*/
|
||||
if (priority) {
|
||||
if (priority)
|
||||
{
|
||||
tmpprio = NewInt();
|
||||
C_loc(priority->nd_INT);
|
||||
CAL("stackprio", (int)word_size);
|
||||
|
@ -108,7 +110,8 @@ DoPriority()
|
|||
STATIC
|
||||
EndPriority()
|
||||
{
|
||||
if (priority) {
|
||||
if (priority)
|
||||
{
|
||||
C_lol(tmpprio);
|
||||
CAL("unstackprio", (int)word_size);
|
||||
FreeInt(tmpprio);
|
||||
|
@ -124,8 +127,7 @@ def_ilb(l)
|
|||
oldlineno = 0;
|
||||
}
|
||||
|
||||
DoLineno(nd)
|
||||
register t_node *nd;
|
||||
DoLineno(nd) register t_node* nd;
|
||||
{
|
||||
/* Generate line number information, if necessary.
|
||||
*/
|
||||
|
@ -133,16 +135,19 @@ DoLineno(nd)
|
|||
#ifdef DBSYMTAB
|
||||
|| options['g']
|
||||
#endif /* DBSYMTAB */
|
||||
) &&
|
||||
nd->nd_lineno &&
|
||||
nd->nd_lineno != oldlineno) {
|
||||
)
|
||||
&& nd->nd_lineno && nd->nd_lineno != oldlineno)
|
||||
{
|
||||
oldlineno = nd->nd_lineno;
|
||||
if (! options['L']) C_lin((arith) nd->nd_lineno);
|
||||
if (!options['L'])
|
||||
C_lin((arith)nd->nd_lineno);
|
||||
#ifdef DBSYMTAB
|
||||
if ( options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
static int ms_lineno;
|
||||
|
||||
if (ms_lineno != nd->nd_lineno) {
|
||||
if (ms_lineno != nd->nd_lineno)
|
||||
{
|
||||
ms_lineno = nd->nd_lineno;
|
||||
C_ms_std((char*)0, N_SLINE, ms_lineno);
|
||||
}
|
||||
|
@ -161,9 +166,11 @@ DoFilename(needed)
|
|||
static label filename_label = 0;
|
||||
|
||||
oldlineno = 0; /* always invalidate remembered line number */
|
||||
if (needed && ! options['L']) {
|
||||
if (needed && !options['L'])
|
||||
{
|
||||
|
||||
if (! filename_label) {
|
||||
if (!filename_label)
|
||||
{
|
||||
filename_label = 1;
|
||||
C_df_dlb((label)1);
|
||||
C_rom_scon(FileName, (arith)(strlen(FileName) + 1));
|
||||
|
@ -173,8 +180,7 @@ DoFilename(needed)
|
|||
}
|
||||
}
|
||||
|
||||
WalkModule(module)
|
||||
register t_def *module;
|
||||
WalkModule(module) register t_def* module;
|
||||
{
|
||||
/* Walk through a module, and all its local definitions.
|
||||
Also generate code for its body.
|
||||
|
@ -200,10 +206,12 @@ WalkModule(module)
|
|||
TmpOpen(sc); /* Initialize for temporaries */
|
||||
C_pro_narg(sc->sc_name);
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
stb_string(module, D_MODULE);
|
||||
WalkDefList(sc->sc_def, stabdef);
|
||||
if (state == PROGRAM && module == Defined) {
|
||||
if (state == PROGRAM && module == Defined)
|
||||
{
|
||||
C_ms_stb_cst(module->df_idf->id_text,
|
||||
N_MAIN,
|
||||
0,
|
||||
|
@ -213,14 +221,16 @@ WalkModule(module)
|
|||
}
|
||||
#endif
|
||||
DoPriority();
|
||||
if (module == Defined) {
|
||||
if (module == Defined)
|
||||
{
|
||||
/* Body of implementation or program module.
|
||||
Call initialization routines of imported modules.
|
||||
Also prevent recursive calls of this one.
|
||||
*/
|
||||
register t_node* nd = Modules;
|
||||
|
||||
if (state == IMPLEMENTATION) {
|
||||
if (state == IMPLEMENTATION)
|
||||
{
|
||||
/* We don't actually prevent recursive calls,
|
||||
but do nothing if called recursively
|
||||
*/
|
||||
|
@ -233,14 +243,16 @@ WalkModule(module)
|
|||
C_zne(RETURN_LABEL);
|
||||
C_ine_dlb(data_label, (arith)0);
|
||||
}
|
||||
else if (! options['R']) {
|
||||
else if (!options['R'])
|
||||
{
|
||||
/* put funny value in BSS, in an attempt to detect
|
||||
uninitialized variables
|
||||
*/
|
||||
C_cal("killbss");
|
||||
}
|
||||
|
||||
for (; nd; nd = nd->nd_NEXT) {
|
||||
for (; nd; nd = nd->nd_NEXT)
|
||||
{
|
||||
C_cal(nd->nd_def->mod_vis->sc_scope->sc_name);
|
||||
}
|
||||
DoFilename(1);
|
||||
|
@ -248,7 +260,8 @@ WalkModule(module)
|
|||
WalkDefList(sc->sc_def, MkCalls);
|
||||
proclevel++;
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel);
|
||||
}
|
||||
#endif /* DBSYMTAB */
|
||||
|
@ -258,7 +271,8 @@ WalkModule(module)
|
|||
EndPriority();
|
||||
C_ret((arith)0);
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
C_ms_std((char*)0, N_RBRAC, gdb_flag ? 0 : proclevel);
|
||||
}
|
||||
#endif /* DBSYMTAB */
|
||||
|
@ -270,8 +284,7 @@ WalkModule(module)
|
|||
WalkDefList(sc->sc_def, UseWarnings);
|
||||
}
|
||||
|
||||
WalkProcedure(procedure)
|
||||
register t_def *procedure;
|
||||
WalkProcedure(procedure) register t_def* procedure;
|
||||
{
|
||||
/* Walk through the definition of a procedure and all its
|
||||
local definitions, checking and generating code.
|
||||
|
@ -301,9 +314,11 @@ WalkProcedure(procedure)
|
|||
|
||||
func_type = tp = RemoveEqual(ResultType(procedure->df_type));
|
||||
|
||||
if (tp) {
|
||||
if (tp)
|
||||
{
|
||||
func_res_size = WA(tp->tp_size);
|
||||
if (TooBigForReturnArea(tp)) {
|
||||
if (TooBigForReturnArea(tp))
|
||||
{
|
||||
#ifdef BIG_RESULT_ON_STACK
|
||||
/* The result type of this procedure is too big.
|
||||
The caller will have reserved space on its stack,
|
||||
|
@ -334,7 +349,8 @@ WalkProcedure(procedure)
|
|||
#else
|
||||
C_pro_narg(procedure->prc_name);
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
stb_string(procedure, D_PROCEDURE);
|
||||
WalkDefList(procscope->sc_def, stabdef);
|
||||
stb_string(procedure, D_PEND);
|
||||
|
@ -360,14 +376,18 @@ WalkProcedure(procedure)
|
|||
/* Check if we must save the stack pointer */
|
||||
for (param = ParamList(procedure->df_type);
|
||||
param;
|
||||
param = param->par_next) {
|
||||
if (! IsVarParam(param)) {
|
||||
param = param->par_next)
|
||||
{
|
||||
if (!IsVarParam(param))
|
||||
{
|
||||
tp = TypeOfParam(param);
|
||||
|
||||
if ( IsConformantArray(tp)) {
|
||||
if (IsConformantArray(tp))
|
||||
{
|
||||
/* First time we get here
|
||||
*/
|
||||
if (func_type && !too_big) {
|
||||
if (func_type && !too_big)
|
||||
{
|
||||
/* Some local space, only
|
||||
needed if the value itself
|
||||
is returned
|
||||
|
@ -390,8 +410,10 @@ WalkProcedure(procedure)
|
|||
def_ilb(cd_body);
|
||||
#endif
|
||||
|
||||
if ((WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG) & REACH_FLAG)) {
|
||||
if (func_res_size) {
|
||||
if ((WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG) & REACH_FLAG))
|
||||
{
|
||||
if (func_res_size)
|
||||
{
|
||||
node_warning(procscope->sc_end,
|
||||
W_ORDINARY,
|
||||
"function procedure \"%s\" does not always return a value",
|
||||
|
@ -422,13 +444,16 @@ WalkProcedure(procedure)
|
|||
*/
|
||||
for (param = ParamList(procedure->df_type);
|
||||
param;
|
||||
param = param->par_next) {
|
||||
if (! IsVarParam(param)) {
|
||||
param = param->par_next)
|
||||
{
|
||||
if (!IsVarParam(param))
|
||||
{
|
||||
tp = TypeOfParam(param);
|
||||
|
||||
if (! IsConformantArray(tp)) {
|
||||
if (tp->tp_size < word_size &&
|
||||
(int) word_size % (int) tp->tp_size == 0) {
|
||||
if (!IsConformantArray(tp))
|
||||
{
|
||||
if (tp->tp_size < word_size && (int)word_size % (int)tp->tp_size == 0)
|
||||
{
|
||||
C_lol(param->par_def->var_off);
|
||||
STL(param->par_def->var_off,
|
||||
tp->tp_size);
|
||||
|
@ -464,7 +489,8 @@ WalkProcedure(procedure)
|
|||
#endif
|
||||
DO_DEBUG(options['X'], PrNode(procedure->prc_body, 0));
|
||||
def_ilb(RETURN_LABEL); /* label at end */
|
||||
if (too_big) {
|
||||
if (too_big)
|
||||
{
|
||||
/* Fill the data area reserved for the function result
|
||||
with the result
|
||||
*/
|
||||
|
@ -474,7 +500,8 @@ WalkProcedure(procedure)
|
|||
c_lae_dlb(too_big);
|
||||
#endif /* BIG_RESULT_ON_STACK */
|
||||
C_sti(func_res_size);
|
||||
if (StackAdjustment) {
|
||||
if (StackAdjustment)
|
||||
{
|
||||
/* Remove copies of conformant arrays
|
||||
*/
|
||||
LOL(StackAdjustment, pointer_size);
|
||||
|
@ -487,17 +514,20 @@ WalkProcedure(procedure)
|
|||
func_res_size = pointer_size;
|
||||
#endif /* BIG_RESULT_ON_STACK */
|
||||
}
|
||||
else if (StackAdjustment) {
|
||||
else if (StackAdjustment)
|
||||
{
|
||||
/* First save the function result in a safe place.
|
||||
Then remove copies of conformant arrays,
|
||||
and put function result back on the stack
|
||||
*/
|
||||
if (func_type) {
|
||||
if (func_type)
|
||||
{
|
||||
STL(retsav, func_res_size);
|
||||
}
|
||||
LOL(StackAdjustment, pointer_size);
|
||||
C_str((arith)1);
|
||||
if (func_type) {
|
||||
if (func_type)
|
||||
{
|
||||
LOL(retsav, func_res_size);
|
||||
}
|
||||
}
|
||||
|
@ -507,7 +537,8 @@ WalkProcedure(procedure)
|
|||
C_beginpart(partno2);
|
||||
C_pro(procedure->prc_name, -procscope->sc_off);
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
stb_string(procedure, D_PROCEDURE);
|
||||
WalkDefList(procscope->sc_def, stabdef);
|
||||
stb_string(procedure, D_PEND);
|
||||
|
@ -520,17 +551,20 @@ WalkProcedure(procedure)
|
|||
#endif
|
||||
);
|
||||
#endif
|
||||
if (! options['n']) WalkDefList(procscope->sc_def, RegisterMessage);
|
||||
if (!options['n'])
|
||||
WalkDefList(procscope->sc_def, RegisterMessage);
|
||||
#ifdef USE_INSERT
|
||||
C_endpart(partno2);
|
||||
#endif
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
if (options['g'])
|
||||
{
|
||||
C_ms_std((char*)0, N_RBRAC, gdb_flag ? 0 : proclevel);
|
||||
}
|
||||
#endif /* DBSYMTAB */
|
||||
C_end(-procscope->sc_off);
|
||||
if (! fit(procscope->sc_off, (int) word_size)) {
|
||||
if (!fit(procscope->sc_off, (int)word_size))
|
||||
{
|
||||
node_error(procedure->prc_body,
|
||||
"maximum local byte count exceeded");
|
||||
}
|
||||
|
@ -540,14 +574,13 @@ WalkProcedure(procedure)
|
|||
WalkDefList(procscope->sc_def, UseWarnings);
|
||||
}
|
||||
|
||||
static
|
||||
WalkDef(df)
|
||||
register t_def *df;
|
||||
static WalkDef(df) register t_def* df;
|
||||
{
|
||||
/* Walk through a list of definitions
|
||||
*/
|
||||
|
||||
switch(df->df_kind) {
|
||||
switch (df->df_kind)
|
||||
{
|
||||
case D_MODULE:
|
||||
WalkModule(df);
|
||||
break;
|
||||
|
@ -555,7 +588,8 @@ WalkDef(df)
|
|||
WalkProcedure(df);
|
||||
break;
|
||||
case D_VARIABLE:
|
||||
if (!proclevel && !(df->df_flags & D_ADDRGIVEN)) {
|
||||
if (!proclevel && !(df->df_flags & D_ADDRGIVEN))
|
||||
{
|
||||
C_df_dnam(df->var_name);
|
||||
C_bss_cst(
|
||||
WA(df->df_type->tp_size),
|
||||
|
@ -568,21 +602,19 @@ WalkDef(df)
|
|||
}
|
||||
}
|
||||
|
||||
static
|
||||
MkCalls(df)
|
||||
register t_def *df;
|
||||
static MkCalls(df) register t_def* df;
|
||||
{
|
||||
/* Generate calls to initialization routines of modules
|
||||
*/
|
||||
|
||||
if (df->df_kind == D_MODULE) {
|
||||
if (df->df_kind == D_MODULE)
|
||||
{
|
||||
C_lxl((arith)0);
|
||||
CAL(df->mod_vis->sc_scope->sc_name, (int)pointer_size);
|
||||
}
|
||||
}
|
||||
|
||||
WalkLink(nd, exit_label, end_reached)
|
||||
register t_node *nd;
|
||||
WalkLink(nd, exit_label, end_reached) register t_node* nd;
|
||||
label exit_label;
|
||||
{
|
||||
/* Walk node "nd", which is a link.
|
||||
|
@ -591,7 +623,8 @@ WalkLink(nd, exit_label, end_reached)
|
|||
and whether an EXIT statement was seen (EXIT_FLAG).
|
||||
*/
|
||||
|
||||
while (nd && nd->nd_class == Link) { /* statement list */
|
||||
while (nd && nd->nd_class == Link)
|
||||
{ /* statement list */
|
||||
end_reached = WalkNode(nd->nd_LEFT, exit_label, end_reached);
|
||||
nd = nd->nd_RIGHT;
|
||||
}
|
||||
|
@ -600,8 +633,7 @@ WalkLink(nd, exit_label, end_reached)
|
|||
}
|
||||
|
||||
STATIC
|
||||
ForLoopVarExpr(nd)
|
||||
register t_node *nd;
|
||||
ForLoopVarExpr(nd) register t_node* nd;
|
||||
{
|
||||
register t_type* tp = nd->nd_type;
|
||||
|
||||
|
@ -610,8 +642,7 @@ ForLoopVarExpr(nd)
|
|||
}
|
||||
|
||||
int
|
||||
WalkStat(nd, exit_label, end_reached)
|
||||
register t_node *nd;
|
||||
WalkStat(nd, exit_label, end_reached) register t_node* nd;
|
||||
label exit_label;
|
||||
{
|
||||
/* Walk through a statement, generating code for it.
|
||||
|
@ -621,25 +652,32 @@ WalkStat(nd, exit_label, end_reached)
|
|||
|
||||
assert(nd->nd_class == Stat);
|
||||
|
||||
if (nd->nd_symb == ';') return 1;
|
||||
if (nd->nd_symb == ';')
|
||||
return 1;
|
||||
|
||||
if (! end_reached & REACH_FLAG) {
|
||||
if (!end_reached & REACH_FLAG)
|
||||
{
|
||||
node_warning(nd, W_ORDINARY, "statement not reached");
|
||||
}
|
||||
if (nd->nd_symb != WHILE ||
|
||||
nd->nd_lineno != left->nd_lineno) {
|
||||
if (nd->nd_symb != WHILE || nd->nd_lineno != left->nd_lineno)
|
||||
{
|
||||
/* Avoid double linenumber generation in while statements */
|
||||
DoLineno(nd);
|
||||
}
|
||||
options['R'] = (nd->nd_flags & ROPTION);
|
||||
options['A'] = (nd->nd_flags & AOPTION);
|
||||
switch(nd->nd_symb) {
|
||||
case '(': {
|
||||
switch (nd->nd_symb)
|
||||
{
|
||||
case '(':
|
||||
{
|
||||
t_node* nd1 = nd;
|
||||
if (ChkCall(&nd1)) {
|
||||
if (ChkCall(&nd1))
|
||||
{
|
||||
assert(nd == nd1);
|
||||
if (nd->nd_type != 0) {
|
||||
node_error(nd, "procedure call expected instead of function call");
|
||||
if (nd->nd_type != 0)
|
||||
{
|
||||
node_error(nd, "only proper procedures can be called from top-level "
|
||||
"statement; this is a function procedure");
|
||||
break;
|
||||
}
|
||||
CodeCall(nd);
|
||||
|
@ -652,21 +690,24 @@ WalkStat(nd, exit_label, end_reached)
|
|||
break;
|
||||
|
||||
case IF:
|
||||
{ label l1 = ++text_label, l3 = ++text_label;
|
||||
{
|
||||
label l1 = ++text_label, l3 = ++text_label;
|
||||
int end_r;
|
||||
|
||||
ExpectBool(&(nd->nd_LEFT), l3, l1);
|
||||
assert(right->nd_symb == THEN);
|
||||
end_r = LblWalkNode(l3, right->nd_LEFT, exit_label, end_reached);
|
||||
|
||||
if (right->nd_RIGHT) { /* ELSE part */
|
||||
if (right->nd_RIGHT)
|
||||
{ /* ELSE part */
|
||||
label l2 = ++text_label;
|
||||
|
||||
c_bra(l2);
|
||||
end_reached = end_r | LblWalkNode(l1, right->nd_RIGHT, exit_label, end_reached);
|
||||
l1 = l2;
|
||||
}
|
||||
else end_reached |= end_r;
|
||||
else
|
||||
end_reached |= end_r;
|
||||
def_ilb(l1);
|
||||
break;
|
||||
}
|
||||
|
@ -676,7 +717,8 @@ WalkStat(nd, exit_label, end_reached)
|
|||
break;
|
||||
|
||||
case WHILE:
|
||||
{ label loop = ++text_label,
|
||||
{
|
||||
label loop = ++text_label,
|
||||
exit = ++text_label,
|
||||
dummy = ++text_label;
|
||||
|
||||
|
@ -689,7 +731,8 @@ WalkStat(nd, exit_label, end_reached)
|
|||
}
|
||||
|
||||
case REPEAT:
|
||||
{ label loop = ++text_label, exit = ++text_label;
|
||||
{
|
||||
label loop = ++text_label, exit = ++text_label;
|
||||
|
||||
end_reached = LblWalkNode(loop, left, exit_label, end_reached);
|
||||
ExpectBool(&(nd->nd_RIGHT), exit, loop);
|
||||
|
@ -698,12 +741,15 @@ WalkStat(nd, exit_label, end_reached)
|
|||
}
|
||||
|
||||
case LOOP:
|
||||
{ label loop = ++text_label, exit = ++text_label;
|
||||
{
|
||||
label loop = ++text_label, exit = ++text_label;
|
||||
|
||||
if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG) {
|
||||
if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG)
|
||||
{
|
||||
end_reached &= REACH_FLAG;
|
||||
}
|
||||
else end_reached = 0;
|
||||
else
|
||||
end_reached = 0;
|
||||
c_bra(loop);
|
||||
def_ilb(exit);
|
||||
break;
|
||||
|
@ -723,12 +769,14 @@ WalkStat(nd, exit_label, end_reached)
|
|||
|
||||
good_forvar = DoForInit(left);
|
||||
loopid = left->nd_LEFT;
|
||||
if ((stepsize = right->nd_LEFT->nd_INT) == 0) {
|
||||
if ((stepsize = right->nd_LEFT->nd_INT) == 0)
|
||||
{
|
||||
node_warning(right->nd_LEFT,
|
||||
W_ORDINARY,
|
||||
"zero stepsize in FOR loop");
|
||||
}
|
||||
if (good_forvar) {
|
||||
if (good_forvar)
|
||||
{
|
||||
bstp = BaseType(loopid->nd_type);
|
||||
uns = bstp->tp_fund != T_INTEGER;
|
||||
CodePExpr(left->nd_RIGHT->nd_RIGHT);
|
||||
|
@ -737,37 +785,46 @@ WalkStat(nd, exit_label, end_reached)
|
|||
C_dup(int_size);
|
||||
C_stl(tmp2);
|
||||
C_lol(tmp);
|
||||
if (uns) C_cmu(int_size);
|
||||
else C_cmi(int_size);
|
||||
if (stepsize >= 0) C_zgt(l2);
|
||||
else C_zlt(l2);
|
||||
if (uns)
|
||||
C_cmu(int_size);
|
||||
else
|
||||
C_cmi(int_size);
|
||||
if (stepsize >= 0)
|
||||
C_zgt(l2);
|
||||
else
|
||||
C_zlt(l2);
|
||||
C_lol(tmp2);
|
||||
RangeCheck(loopid->nd_type,
|
||||
left->nd_RIGHT->nd_LEFT->nd_type);
|
||||
CodeDStore(loopid);
|
||||
if (stepsize >= 0) {
|
||||
if (stepsize >= 0)
|
||||
{
|
||||
C_lol(tmp);
|
||||
ForLoopVarExpr(loopid);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
stepsize = -stepsize;
|
||||
ForLoopVarExpr(loopid);
|
||||
C_lol(tmp);
|
||||
}
|
||||
C_sbu(int_size);
|
||||
if (stepsize) {
|
||||
if (stepsize)
|
||||
{
|
||||
C_loc(stepsize);
|
||||
C_dvu(int_size);
|
||||
}
|
||||
C_stl(tmp);
|
||||
loopid->nd_def->df_flags |= D_FORLOOP;
|
||||
def_ilb(l1);
|
||||
if (! options['R']) {
|
||||
if (!options['R'])
|
||||
{
|
||||
ForLoopVarExpr(loopid);
|
||||
C_stl(tmp2);
|
||||
}
|
||||
end_reached |= WalkNode(right->nd_RIGHT, exit_label, end_reached);
|
||||
if (! options['R']) {
|
||||
if (!options['R'])
|
||||
{
|
||||
label x = ++text_label;
|
||||
C_lol(tmp2);
|
||||
ForLoopVarExpr(loopid);
|
||||
|
@ -778,7 +835,8 @@ WalkStat(nd, exit_label, end_reached)
|
|||
}
|
||||
loopid->nd_def->df_flags &= ~D_FORLOOP;
|
||||
FreeInt(tmp2);
|
||||
if (stepsize) {
|
||||
if (stepsize)
|
||||
{
|
||||
C_lol(tmp);
|
||||
C_zeq(l2);
|
||||
C_lol(tmp);
|
||||
|
@ -792,7 +850,8 @@ WalkStat(nd, exit_label, end_reached)
|
|||
CodeDStore(loopid);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
end_reached |= WalkNode(right->nd_RIGHT, exit_label, end_reached);
|
||||
loopid->nd_def->df_flags &= ~D_FORLOOP;
|
||||
}
|
||||
|
@ -808,9 +867,11 @@ WalkStat(nd, exit_label, end_reached)
|
|||
struct withdesig wds;
|
||||
t_desig ds;
|
||||
|
||||
if (! WalkDesignator(&(nd->nd_LEFT), &ds, D_USED)) break;
|
||||
if (!WalkDesignator(&(nd->nd_LEFT), &ds, D_USED))
|
||||
break;
|
||||
left = nd->nd_LEFT;
|
||||
if (left->nd_type->tp_fund != T_RECORD) {
|
||||
if (left->nd_type->tp_fund != T_RECORD)
|
||||
{
|
||||
node_error(left, "record variable expected");
|
||||
break;
|
||||
}
|
||||
|
@ -843,26 +904,32 @@ WalkStat(nd, exit_label, end_reached)
|
|||
case EXIT:
|
||||
assert(exit_label != 0);
|
||||
|
||||
if (end_reached & REACH_FLAG) end_reached = EXIT_FLAG;
|
||||
if (end_reached & REACH_FLAG)
|
||||
end_reached = EXIT_FLAG;
|
||||
c_bra(exit_label);
|
||||
break;
|
||||
|
||||
case RETURN:
|
||||
end_reached &= ~REACH_FLAG;
|
||||
if (right) {
|
||||
if (! ChkExpression(&(nd->nd_RIGHT))) break;
|
||||
if (right)
|
||||
{
|
||||
if (!ChkExpression(&(nd->nd_RIGHT)))
|
||||
break;
|
||||
/* The type of the return-expression must be
|
||||
assignment compatible with the result type of the
|
||||
function procedure (See Rep. 9.11).
|
||||
*/
|
||||
if (!ChkAssCompat(&(nd->nd_RIGHT), func_type, "RETURN")) {
|
||||
if (!ChkAssCompat(&(nd->nd_RIGHT), func_type, "RETURN"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
right = nd->nd_RIGHT;
|
||||
if (right->nd_type->tp_fund == T_STRING) {
|
||||
if (right->nd_type->tp_fund == T_STRING)
|
||||
{
|
||||
CodePString(right, func_type);
|
||||
}
|
||||
else CodePExpr(right);
|
||||
else
|
||||
CodePExpr(right);
|
||||
}
|
||||
c_bra(RETURN_LABEL);
|
||||
break;
|
||||
|
@ -893,8 +960,7 @@ int (*WalkTable[])() = {
|
|||
|
||||
extern t_desig null_desig;
|
||||
|
||||
ExpectBool(pnd, true_label, false_label)
|
||||
register t_node **pnd;
|
||||
ExpectBool(pnd, true_label, false_label) register t_node** pnd;
|
||||
label true_label, false_label;
|
||||
{
|
||||
/* "pnd" must indicate a boolean expression. Check this and
|
||||
|
@ -903,9 +969,10 @@ ExpectBool(pnd, true_label, false_label)
|
|||
t_desig ds;
|
||||
|
||||
ds = null_desig;
|
||||
if (ChkExpression(pnd)) {
|
||||
if ((*pnd)->nd_type != bool_type &&
|
||||
(*pnd)->nd_type != error_type) {
|
||||
if (ChkExpression(pnd))
|
||||
{
|
||||
if ((*pnd)->nd_type != bool_type && (*pnd)->nd_type != error_type)
|
||||
{
|
||||
node_error(*pnd, "boolean expression expected");
|
||||
}
|
||||
|
||||
|
@ -921,7 +988,8 @@ WalkDesignator(pnd, ds, flags)
|
|||
/* Check designator and generate code for it
|
||||
*/
|
||||
|
||||
if (! ChkVariable(pnd, flags)) return 0;
|
||||
if (!ChkVariable(pnd, flags))
|
||||
return 0;
|
||||
|
||||
*ds = null_desig;
|
||||
CodeDesig(*pnd, ds);
|
||||
|
@ -940,36 +1008,43 @@ DoForInit(nd)
|
|||
r = ChkVariable(&(nd->nd_LEFT), D_USED | D_DEFINED);
|
||||
r &= ChkExpression(&(right->nd_LEFT));
|
||||
r &= ChkExpression(&(right->nd_RIGHT));
|
||||
if (!r) return 0;
|
||||
if (!r)
|
||||
return 0;
|
||||
|
||||
df = nd->nd_LEFT->nd_def;
|
||||
if (df->df_kind == D_FIELD) {
|
||||
if (df->df_kind == D_FIELD)
|
||||
{
|
||||
node_error(nd,
|
||||
"FOR-loop variable may not be a field of a record");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!df->var_name && df->var_off >= 0) {
|
||||
if (!df->var_name && df->var_off >= 0)
|
||||
{
|
||||
node_error(nd, "FOR-loop variable may not be a parameter");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (df->df_scope != CurrentScope) {
|
||||
if (df->df_scope != CurrentScope)
|
||||
{
|
||||
register t_scopelist* sc = CurrVis;
|
||||
|
||||
for (;;) {
|
||||
if (!sc) {
|
||||
for (;;)
|
||||
{
|
||||
if (!sc)
|
||||
{
|
||||
node_error(nd,
|
||||
"FOR-loop variable may not be imported");
|
||||
return 1;
|
||||
}
|
||||
if (sc->sc_scope == df->df_scope) break;
|
||||
if (sc->sc_scope == df->df_scope)
|
||||
break;
|
||||
sc = nextvisible(sc);
|
||||
}
|
||||
}
|
||||
|
||||
if (df->df_type->tp_size > word_size ||
|
||||
!(df->df_type->tp_fund & T_DISCRETE)) {
|
||||
if (df->df_type->tp_size > word_size || !(df->df_type->tp_fund & T_DISCRETE))
|
||||
{
|
||||
node_error(nd, "illegal type of FOR loop variable");
|
||||
return 1;
|
||||
}
|
||||
|
@ -978,19 +1053,21 @@ DoForInit(nd)
|
|||
tpl = right->nd_LEFT->nd_type;
|
||||
tpr = right->nd_RIGHT->nd_type;
|
||||
#ifndef STRICT_3RD_ED
|
||||
if (! options['3']) {
|
||||
if (!ChkAssCompat(&(right->nd_LEFT), base_tp, "FOR statement") ||
|
||||
!ChkAssCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) {
|
||||
if (!options['3'])
|
||||
{
|
||||
if (!ChkAssCompat(&(right->nd_LEFT), base_tp, "FOR statement") || !ChkAssCompat(&(right->nd_RIGHT), base_tp, "FOR statement"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!TstCompat(df->df_type, tpl) ||
|
||||
!TstCompat(df->df_type, tpr)) {
|
||||
if (!TstCompat(df->df_type, tpl) || !TstCompat(df->df_type, tpr))
|
||||
{
|
||||
node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement");
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!ChkCompat(&(right->nd_LEFT), base_tp, "FOR statement") ||
|
||||
!ChkCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) {
|
||||
if (!ChkCompat(&(right->nd_LEFT), base_tp, "FOR statement") || !ChkCompat(&(right->nd_RIGHT), base_tp, "FOR statement"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -998,8 +1075,7 @@ node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement");
|
|||
}
|
||||
|
||||
void
|
||||
DoAssign(nd)
|
||||
register t_node *nd;
|
||||
DoAssign(nd) register t_node* nd;
|
||||
{
|
||||
/* May we do it in this order (expression first) ???
|
||||
The reference manual sais nothing about it, but the book does:
|
||||
|
@ -1009,11 +1085,12 @@ DoAssign(nd)
|
|||
t_desig dsr;
|
||||
register t_type* tp;
|
||||
|
||||
if (! (ChkExpression(&(nd->nd_RIGHT)) &
|
||||
ChkVariable(&(nd->nd_LEFT), D_DEFINED))) return;
|
||||
if (!(ChkExpression(&(nd->nd_RIGHT)) & ChkVariable(&(nd->nd_LEFT), D_DEFINED)))
|
||||
return;
|
||||
tp = nd->nd_LEFT->nd_type;
|
||||
|
||||
if (! ChkAssCompat(&(nd->nd_RIGHT), tp, "assignment")) {
|
||||
if (!ChkAssCompat(&(nd->nd_RIGHT), tp, "assignment"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
dsr = null_desig;
|
||||
|
@ -1022,38 +1099,41 @@ DoAssign(nd)
|
|||
|| (ds).dsg_kind == DSG_INDEXED)
|
||||
CodeExpr(nd->nd_RIGHT, &dsr, NO_LABEL, NO_LABEL);
|
||||
tp = nd->nd_RIGHT->nd_type;
|
||||
if (complex(tp)) {
|
||||
if (StackNeededFor(dsr)) CodeAddress(&dsr);
|
||||
if (complex(tp))
|
||||
{
|
||||
if (StackNeededFor(dsr))
|
||||
CodeAddress(&dsr);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
CodeValue(&dsr, tp);
|
||||
}
|
||||
CodeMove(&dsr, nd->nd_LEFT, tp);
|
||||
}
|
||||
|
||||
static
|
||||
RegisterMessage(df)
|
||||
register t_def *df;
|
||||
static RegisterMessage(df) register t_def* df;
|
||||
{
|
||||
register t_type* tp;
|
||||
|
||||
if (df->df_kind == D_VARIABLE) {
|
||||
if ( !(df->df_flags & D_NOREG)) {
|
||||
if (df->df_kind == D_VARIABLE)
|
||||
{
|
||||
if (!(df->df_flags & D_NOREG))
|
||||
{
|
||||
/* Examine type and size
|
||||
*/
|
||||
tp = BaseType(df->df_type);
|
||||
if ((df->df_flags & D_VARPAR) ||
|
||||
(tp->tp_fund&(T_POINTER|T_HIDDEN|T_EQUAL))) {
|
||||
if ((df->df_flags & D_VARPAR) || (tp->tp_fund & (T_POINTER | T_HIDDEN | T_EQUAL)))
|
||||
{
|
||||
C_ms_reg(df->var_off,
|
||||
pointer_size,
|
||||
reg_pointer,
|
||||
0);
|
||||
}
|
||||
else if (tp->tp_fund & T_NUMERIC) {
|
||||
else if (tp->tp_fund & T_NUMERIC)
|
||||
{
|
||||
C_ms_reg(df->var_off,
|
||||
tp->tp_size,
|
||||
tp->tp_fund == T_REAL ?
|
||||
reg_float : reg_any,
|
||||
tp->tp_fund == T_REAL ? reg_float : reg_any,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
@ -1066,55 +1146,53 @@ df_warning(nd, df, warning)
|
|||
t_def* df;
|
||||
char* warning;
|
||||
{
|
||||
if (! (df->df_kind & (D_VARIABLE|D_PROCEDURE|D_TYPE|D_CONST|D_PROCHEAD))) {
|
||||
if (!(df->df_kind & (D_VARIABLE | D_PROCEDURE | D_TYPE | D_CONST | D_PROCHEAD)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (warning) {
|
||||
if (warning)
|
||||
{
|
||||
node_warning(nd,
|
||||
W_ORDINARY,
|
||||
"%s \"%s\" %s",
|
||||
(df->df_flags & D_VALPAR) ? "value parameter" :
|
||||
(df->df_flags & D_VARPAR) ? "variable parameter" :
|
||||
(df->df_kind == D_VARIABLE) ? "variable" :
|
||||
(df->df_kind == D_TYPE) ? "type" :
|
||||
(df->df_kind == D_CONST) ? "constant" :
|
||||
"procedure",
|
||||
(df->df_flags & D_VALPAR) ? "value parameter" : (df->df_flags & D_VARPAR) ? "variable parameter" : (df->df_kind == D_VARIABLE) ? "variable" : (df->df_kind == D_TYPE) ? "type" : (df->df_kind == D_CONST) ? "constant" : "procedure",
|
||||
df->df_idf->id_text, warning);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UseWarnings(df)
|
||||
register t_def *df;
|
||||
UseWarnings(df) register t_def* df;
|
||||
{
|
||||
t_node* nd = df->df_scope->sc_end;
|
||||
|
||||
if (is_anon_idf(df->df_idf) ||
|
||||
!(df->df_kind&(D_IMPORTED|D_VARIABLE|D_PROCEDURE|D_CONST|D_TYPE)) ||
|
||||
(df->df_flags&(D_EXPORTED|D_QEXPORTED))) {
|
||||
if (is_anon_idf(df->df_idf) || !(df->df_kind & (D_IMPORTED | D_VARIABLE | D_PROCEDURE | D_CONST | D_TYPE)) || (df->df_flags & (D_EXPORTED | D_QEXPORTED)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (df->df_kind & D_IMPORTED) {
|
||||
if (df->df_kind & D_IMPORTED)
|
||||
{
|
||||
register t_def* df1 = df->imp_def;
|
||||
|
||||
df1->df_flags |= df->df_flags & (D_USED | D_DEFINED);
|
||||
if (df->df_kind == D_INUSE) return;
|
||||
if ( !(df->df_flags & D_IMP_BY_EXP)) {
|
||||
if (df->df_flags & (D_USED | D_DEFINED)) {
|
||||
if (df->df_kind == D_INUSE)
|
||||
return;
|
||||
if (!(df->df_flags & D_IMP_BY_EXP))
|
||||
{
|
||||
if (df->df_flags & (D_USED | D_DEFINED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
df_warning(nd,
|
||||
df1,
|
||||
df1->df_kind == D_VARIABLE ?
|
||||
"imported but not used/assigned" :
|
||||
"imported but not used");
|
||||
df1->df_kind == D_VARIABLE ? "imported but not used/assigned" : "imported but not used");
|
||||
return;
|
||||
}
|
||||
df = df1;
|
||||
nd = df->df_scope->sc_end;
|
||||
}
|
||||
switch(df->df_flags & (D_USED|D_DEFINED|D_VALPAR|D_VARPAR)) {
|
||||
switch (df->df_flags & (D_USED | D_DEFINED | D_VALPAR | D_VARPAR))
|
||||
{
|
||||
case 0:
|
||||
case D_VARPAR:
|
||||
df_warning(nd, df, "never used/assigned");
|
||||
|
@ -1130,11 +1208,11 @@ UseWarnings(df)
|
|||
}
|
||||
}
|
||||
|
||||
WalkDefList(df, proc)
|
||||
register t_def *df;
|
||||
WalkDefList(df, proc) register t_def* df;
|
||||
int (*proc)();
|
||||
{
|
||||
for (; df; df = df->df_nextinscope) {
|
||||
for (; df; df = df->df_nextinscope)
|
||||
{
|
||||
(*proc)(df);
|
||||
}
|
||||
}
|
||||
|
@ -1144,7 +1222,8 @@ static int
|
|||
stabdef(df)
|
||||
t_def* df;
|
||||
{
|
||||
switch(df->df_kind) {
|
||||
switch (df->df_kind)
|
||||
{
|
||||
case D_CONST:
|
||||
case D_VARIABLE:
|
||||
stb_string(df, df->df_kind);
|
||||
|
|
|
@ -29,8 +29,8 @@ for _, plat in ipairs(vars.plats) do
|
|||
},
|
||||
hdrs = {}, -- must be empty
|
||||
deps = {
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/"..plat.."/include+headers",
|
||||
"lang/cem/libcc.ansi/headers+pkg",
|
||||
"plat/"..plat.."/include+pkg",
|
||||
"h+emheaders",
|
||||
},
|
||||
vars = { plat = plat }
|
||||
|
|
|
@ -355,7 +355,7 @@ void zgt(lab) int lab; { C_zgt((label) lab); }
|
|||
void zlt(lab) int lab; { C_zlt((label) lab); }
|
||||
void zne(lab) int lab; { C_zne((label) lab); }
|
||||
|
||||
char *itoa(i) long i;
|
||||
char *myitoa(i) long i;
|
||||
{
|
||||
static char a[sizeof(long)*3];
|
||||
sprint(a, "%ld", i);
|
||||
|
@ -364,7 +364,7 @@ char *itoa(i) long i;
|
|||
|
||||
void rom(size, c) int size; long c;
|
||||
{
|
||||
C_rom_icon(itoa(c), (arith) size);
|
||||
C_rom_icon(myitoa(c), (arith) size);
|
||||
}
|
||||
|
||||
void lin()
|
||||
|
|
|
@ -168,10 +168,6 @@ register int delim;
|
|||
str->s_str = p = Malloc((unsigned int) ISTRSIZE);
|
||||
for( ; ; ) {
|
||||
LoadChar(ch);
|
||||
if( ch & 0200 ) {
|
||||
fatal("non-ascii '\\%03o' read", ch & 0377);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
if( class(ch) == STNL ) {
|
||||
lexerror("newline in string");
|
||||
LineNumber++;
|
||||
|
@ -310,11 +306,6 @@ again:
|
|||
LoadChar(ch);
|
||||
if( !options['C'] ) /* -C : cases are different */
|
||||
TO_LOWER(ch);
|
||||
|
||||
if( (ch & 0200) && ch != EOI ) {
|
||||
fatal("non-ascii '\\%03o' read", ch & 0377);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
switch( class(ch) ) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue