mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-27 02:14:19 +00:00
Upload
Digital Research
This commit is contained in:
BIN
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/PLM.ZIP
Normal file
BIN
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/PLM.ZIP
Normal file
Binary file not shown.
BIN
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/PLM2C.ZIP
Normal file
BIN
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/PLM2C.ZIP
Normal file
Binary file not shown.
1
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/README.MD
Normal file
1
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/README.MD
Normal file
@@ -0,0 +1 @@
|
||||
This archive conitains the above PLM2C translator, cleaned up, and buildable on a unix system. It contains PLM2C.ZIP, which is the PLM to C translator, and PLM.ZIP, which is frontend parser for gcc.
|
||||
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/Makefile
Normal file
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
# makefile for tree stuff
|
||||
# vix 24jul87 [stripped down from as makefile]
|
||||
|
||||
CFLAGS = -O
|
||||
|
||||
TRTEST_OBJ = t_trtest.o tree.o
|
||||
|
||||
all : t_trtest
|
||||
|
||||
t_trtest : $(TRTEST_OBJ)
|
||||
cc -o t_trtest $(TRTEST_OBJ)
|
||||
|
||||
clean : FRC
|
||||
rm -f core a.out t_trtest $(TRTEST_OBJ)
|
||||
|
||||
FRC :
|
||||
|
||||
tree.o : tree.c tree.h vixie.h
|
||||
t_trtest.o : t_trtest.c tree.h vixie.h
|
||||
23
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/README
Normal file
23
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/README
Normal file
@@ -0,0 +1,23 @@
|
||||
AVL Trees V1.0
|
||||
24-July-1987
|
||||
Paul Vixie
|
||||
|
||||
This library and test program are useful for creating and using balanced
|
||||
binary trees (AVL trees). The tree is held in memory, using malloc(3) to
|
||||
allocate storage. A better version would allow file-based trees in
|
||||
addition; once memory mapped files hit the UNIX(tm) community, this will
|
||||
be much easier to do. In the meanwhile, these routines have been very
|
||||
useful to be for symbol tables and the like. (Yes, I'm sure hashing is
|
||||
better in some way, but I've used this for symbol tables, just the same.)
|
||||
|
||||
I cannot take credit for the algorithms. See "Algorithms & Data Structures,"
|
||||
Niklaus Wirth, Prentice-Hall 1986, ISBN 0-13-022005-1. This is an update of
|
||||
Wirth's previous book, titled "Algorythms + Data Structures = Programs,"
|
||||
which used Pascal as the language for examples. This later book uses the
|
||||
newer Modula-2 for it's examples; this tree code was created using the
|
||||
Modula-2 examples as guidelines. At the time I typed this stuff in (about
|
||||
a year ago, in July 1987), I understood how it all worked. Today, well...
|
||||
|
||||
This code is hereby placed in the public domain, unless restrictions apply
|
||||
from Prentice-Hall on the algorithms themselves. If you use or redistribute
|
||||
this code, please leave my name (and Wirth's) in the comments.
|
||||
126
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/t_trtest.c
Normal file
126
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/t_trtest.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/* t_trtest - test the tree functions
|
||||
* vix 24jul87 [documented, added savestr for net distribution]
|
||||
*/
|
||||
|
||||
#define MAIN
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vixie.h"
|
||||
#include "tree.h"
|
||||
|
||||
main()
|
||||
{
|
||||
tree *t;
|
||||
char line[100];
|
||||
|
||||
tree_init(&t);
|
||||
while (printf("line (or .): "), gets(line), line[0] != '.')
|
||||
{
|
||||
if (strncmp(line, "~r ", 3)) {
|
||||
trtest(&t, line, 1);
|
||||
}
|
||||
else {
|
||||
FILE *f;
|
||||
|
||||
if (!(f = fopen(&line[3], "r")))
|
||||
perror(&line[3]);
|
||||
else {
|
||||
while (fgets(line, 100, f)) {
|
||||
line[strlen(line)-1] = '\0';
|
||||
printf("(%s)\n", line);
|
||||
trtest(&t, line, 0);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trtest(tt, line, inter)
|
||||
tree **tt;
|
||||
char *line;
|
||||
{
|
||||
char opts[100], *tree_srch(), *pc, *n;
|
||||
int uar_print(), duar(), compar(), opt, status;
|
||||
|
||||
pc = tree_srch(tt, compar, line);
|
||||
printf("tree_srch=%08lx\n", pc);
|
||||
if (pc)
|
||||
{
|
||||
printf(" <%s>\n", pc);
|
||||
|
||||
if (inter) {
|
||||
printf("delete? "); gets(opts); opt = (opts[0]=='y');
|
||||
}
|
||||
else
|
||||
opt = 1;
|
||||
|
||||
if (opt) {
|
||||
status = tree_delete(tt, compar, line, duar);
|
||||
printf("delete=%d\n", status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inter) {
|
||||
printf("add? "); gets(opts); opt = (opts[0]=='y');
|
||||
}
|
||||
else
|
||||
opt = 1;
|
||||
|
||||
if (opt) {
|
||||
char *savestr();
|
||||
|
||||
n = savestr(line);
|
||||
tree_add(tt, compar, n, duar);
|
||||
}
|
||||
}
|
||||
tree_trav1(*tt, 0);
|
||||
}
|
||||
|
||||
duar(pc)
|
||||
char *pc;
|
||||
{
|
||||
printf("duar called, pc=%08X: <%s>\n", pc, pc?pc:"");
|
||||
free(pc);
|
||||
}
|
||||
|
||||
tree_trav1(t, l)
|
||||
tree *t;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!t) return;
|
||||
tree_trav1(t->tree_l, l+1);
|
||||
for (i=0; i<l; i++) printf(" ");
|
||||
printf("%08lx (%s)\n", t->tree_p, t->tree_p);
|
||||
tree_trav1(t->tree_r, l+1);
|
||||
}
|
||||
|
||||
uar_print(pc)
|
||||
char *pc;
|
||||
{
|
||||
printf("uar_print(%08lx)", pc);
|
||||
if (pc)
|
||||
printf(" '%s'", pc);
|
||||
putchar('\n');
|
||||
return 1;
|
||||
}
|
||||
|
||||
compar(l, r)
|
||||
char *l, *r;
|
||||
{
|
||||
printf("compar(%s,%s)=%d\n", l, r, strcmp(l, r));
|
||||
return strcmp(l, r);
|
||||
}
|
||||
|
||||
char *
|
||||
savestr(str)
|
||||
char *str;
|
||||
{
|
||||
char *save;
|
||||
|
||||
save = malloc(strlen(str) + 1);
|
||||
strcpy(save, str);
|
||||
return save;
|
||||
}
|
||||
511
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.c
Normal file
511
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.c
Normal file
@@ -0,0 +1,511 @@
|
||||
/* as_tree - tree library for as
|
||||
* vix 14dec85 [written]
|
||||
* vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
|
||||
* vix 06feb86 [added tree_mung()]
|
||||
* vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
|
||||
* vix 23jun86 [added delete uar to add for replaced nodes]
|
||||
*/
|
||||
|
||||
|
||||
/* This program text was created by Paul Vixie using examples from the book:
|
||||
* "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
|
||||
* 0-13-022005-1. This code and associated documentation is hereby placed
|
||||
* in the public domain.
|
||||
*/
|
||||
|
||||
|
||||
/*#define DEBUG "tree"*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vixie.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define MSG(msg) printf("DEBUG: '%s'\n", msg);
|
||||
#else
|
||||
#define MSG(msg)
|
||||
#endif
|
||||
|
||||
|
||||
void tree_init(ppr_tree)
|
||||
tree **ppr_tree;
|
||||
{
|
||||
ENTER("tree_init")
|
||||
*ppr_tree = NULL;
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
char *tree_srch(ppr_tree, pfi_compare, pc_user)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
{
|
||||
register int i_comp;
|
||||
register tree *pr_new;
|
||||
|
||||
ENTER("tree_srch")
|
||||
|
||||
if (*ppr_tree)
|
||||
{
|
||||
i_comp = (*pfi_compare)(pc_user, (**ppr_tree).tree_p);
|
||||
if (i_comp > 0)
|
||||
EXIT(tree_srch(
|
||||
&(**ppr_tree).tree_r,
|
||||
pfi_compare,
|
||||
pc_user
|
||||
))
|
||||
if (i_comp < 0)
|
||||
EXIT(tree_srch(
|
||||
&(**ppr_tree).tree_l,
|
||||
pfi_compare,
|
||||
pc_user
|
||||
))
|
||||
|
||||
/* not higher, not lower... this must be the one.
|
||||
*/
|
||||
EXIT((**ppr_tree).tree_p)
|
||||
}
|
||||
|
||||
/* grounded. NOT found.
|
||||
*/
|
||||
EXIT(NULL)
|
||||
}
|
||||
|
||||
|
||||
void tree_add(ppr_tree, pfi_compare, pc_user, pfi_delete)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
int (*pfi_delete)();
|
||||
{
|
||||
void sprout();
|
||||
int i_balance = FALSE;
|
||||
|
||||
ENTER("tree_add")
|
||||
sprout(ppr_tree, pc_user, &i_balance, pfi_compare, pfi_delete);
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
static void sprout(ppr, pc_data, pi_balance, pfi_compare, pfi_delete)
|
||||
tree **ppr;
|
||||
char *pc_data;
|
||||
int *pi_balance;
|
||||
int (*pfi_compare)();
|
||||
int (*pfi_delete)();
|
||||
{
|
||||
tree *p1, *p2;
|
||||
int cmp;
|
||||
|
||||
ENTER("sprout")
|
||||
|
||||
/* are we grounded? if so, add the node "here" and set the rebalance
|
||||
* flag, then exit.
|
||||
*/
|
||||
if (!*ppr) {
|
||||
MSG("grounded. adding new node, setting h=true")
|
||||
*ppr = (tree *) malloc(sizeof(tree));
|
||||
(*ppr)->tree_l = NULL;
|
||||
(*ppr)->tree_r = NULL;
|
||||
(*ppr)->tree_b = 0;
|
||||
(*ppr)->tree_p = pc_data;
|
||||
*pi_balance = TRUE;
|
||||
EXITV
|
||||
}
|
||||
|
||||
/* compare the data using routine passed by caller.
|
||||
*/
|
||||
cmp = (*pfi_compare)(pc_data, (*ppr)->tree_p);
|
||||
|
||||
/* if LESS, prepare to move to the left.
|
||||
*/
|
||||
if (cmp < 0) {
|
||||
MSG("LESS. sprouting left.")
|
||||
sprout(&(*ppr)->tree_l, pc_data, pi_balance,
|
||||
pfi_compare, pfi_delete);
|
||||
if (*pi_balance) { /* left branch has grown longer */
|
||||
MSG("LESS: left branch has grown")
|
||||
switch ((*ppr)->tree_b)
|
||||
{
|
||||
case 1: /* right branch WAS longer; balance is ok now */
|
||||
MSG("LESS: case 1.. balnce restored implicitly")
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 0: /* balance WAS okay; now left branch longer */
|
||||
MSG("LESS: case 0.. balnce bad but still ok")
|
||||
(*ppr)->tree_b = -1;
|
||||
break;
|
||||
case -1:
|
||||
/* left branch was already too long. rebalnce */
|
||||
MSG("LESS: case -1: rebalancing")
|
||||
p1 = (*ppr)->tree_l;
|
||||
if (p1->tree_b == -1) { /* LL */
|
||||
MSG("LESS: single LL")
|
||||
(*ppr)->tree_l = p1->tree_r;
|
||||
p1->tree_r = *ppr;
|
||||
(*ppr)->tree_b = 0;
|
||||
*ppr = p1;
|
||||
}
|
||||
else { /* double LR */
|
||||
MSG("LESS: double LR")
|
||||
|
||||
p2 = p1->tree_r;
|
||||
p1->tree_r = p2->tree_l;
|
||||
p2->tree_l = p1;
|
||||
|
||||
(*ppr)->tree_l = p2->tree_r;
|
||||
p2->tree_r = *ppr;
|
||||
|
||||
if (p2->tree_b == -1)
|
||||
(*ppr)->tree_b = 1;
|
||||
else
|
||||
(*ppr)->tree_b = 0;
|
||||
|
||||
if (p2->tree_b == 1)
|
||||
p1->tree_b = -1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
*ppr = p2;
|
||||
} /*else*/
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
} /*switch*/
|
||||
} /*if*/
|
||||
EXITV
|
||||
} /*if*/
|
||||
|
||||
/* if MORE, prepare to move to the right.
|
||||
*/
|
||||
if (cmp > 0) {
|
||||
MSG("MORE: sprouting to the right")
|
||||
sprout(&(*ppr)->tree_r, pc_data, pi_balance,
|
||||
pfi_compare, pfi_delete);
|
||||
if (*pi_balance) { /* right branch has grown longer */
|
||||
MSG("MORE: right branch has grown")
|
||||
|
||||
switch ((*ppr)->tree_b)
|
||||
{
|
||||
case -1:MSG("MORE: balance was off, fixed implicitly")
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 0: MSG("MORE: balance was okay, now off but ok")
|
||||
(*ppr)->tree_b = 1;
|
||||
break;
|
||||
case 1: MSG("MORE: balance was off, need to rebalance")
|
||||
p1 = (*ppr)->tree_r;
|
||||
if (p1->tree_b == 1) { /* RR */
|
||||
MSG("MORE: single RR")
|
||||
(*ppr)->tree_r = p1->tree_l;
|
||||
p1->tree_l = *ppr;
|
||||
(*ppr)->tree_b = 0;
|
||||
*ppr = p1;
|
||||
}
|
||||
else { /* double RL */
|
||||
MSG("MORE: double RL")
|
||||
|
||||
p2 = p1->tree_l;
|
||||
p1->tree_l = p2->tree_r;
|
||||
p2->tree_r = p1;
|
||||
|
||||
(*ppr)->tree_r = p2->tree_l;
|
||||
p2->tree_l = *ppr;
|
||||
|
||||
if (p2->tree_b == 1)
|
||||
(*ppr)->tree_b = -1;
|
||||
else
|
||||
(*ppr)->tree_b = 0;
|
||||
|
||||
if (p2->tree_b == -1)
|
||||
p1->tree_b = 1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
|
||||
*ppr = p2;
|
||||
} /*else*/
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
} /*switch*/
|
||||
} /*if*/
|
||||
EXITV
|
||||
} /*if*/
|
||||
|
||||
/* not less, not more: this is the same key! replace...
|
||||
*/
|
||||
MSG("I found it! Replacing data value")
|
||||
*pi_balance = FALSE;
|
||||
if (pfi_delete)
|
||||
(*pfi_delete)((*ppr)->tree_p);
|
||||
(*ppr)->tree_p = pc_data;
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
int tree_delete(ppr_p, pfi_compare, pc_user, pfi_uar)
|
||||
tree **ppr_p;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
int (*pfi_uar)();
|
||||
{
|
||||
int i_balance = FALSE, i_uar_called = FALSE;
|
||||
|
||||
ENTER("tree_delete");
|
||||
EXIT(delete(ppr_p, pfi_compare, pc_user, pfi_uar,
|
||||
&i_balance, &i_uar_called))
|
||||
}
|
||||
|
||||
|
||||
static int delete(ppr_p, pfi_compare, pc_user, pfi_uar,
|
||||
pi_balance, pi_uar_called)
|
||||
tree **ppr_p;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
int (*pfi_uar)();
|
||||
int *pi_balance;
|
||||
int *pi_uar_called;
|
||||
{
|
||||
void del(), balanceL(), balanceR();
|
||||
tree *pr_q;
|
||||
int i_comp, i_ret;
|
||||
|
||||
ENTER("delete")
|
||||
|
||||
if (*ppr_p == NULL) {
|
||||
MSG("key not in tree")
|
||||
EXIT(FALSE)
|
||||
}
|
||||
|
||||
i_comp = (*pfi_compare)((*ppr_p)->tree_p, pc_user);
|
||||
if (i_comp > 0) {
|
||||
MSG("too high - scan left")
|
||||
i_ret = delete(&(*ppr_p)->tree_l, pfi_compare, pc_user, pfi_uar,
|
||||
pi_balance, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceL(ppr_p, pi_balance);
|
||||
}
|
||||
else if (i_comp < 0) {
|
||||
MSG("too low - scan right")
|
||||
i_ret = delete(&(*ppr_p)->tree_r, pfi_compare, pc_user, pfi_uar,
|
||||
pi_balance, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceR(ppr_p, pi_balance);
|
||||
}
|
||||
else {
|
||||
MSG("equal")
|
||||
pr_q = *ppr_p;
|
||||
if (pr_q->tree_r == NULL) {
|
||||
MSG("right subtree null")
|
||||
*ppr_p = pr_q->tree_l;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
else if (pr_q->tree_l == NULL) {
|
||||
MSG("right subtree non-null, left subtree null")
|
||||
*ppr_p = pr_q->tree_r;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
else {
|
||||
MSG("neither subtree null")
|
||||
del(&pr_q->tree_l, pi_balance, &pr_q, pfi_uar,
|
||||
pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceL(ppr_p, pi_balance);
|
||||
}
|
||||
free(pr_q);
|
||||
if (!*pi_uar_called && *pfi_uar)
|
||||
(*pfi_uar)(pr_q->tree_p);
|
||||
i_ret = TRUE;
|
||||
}
|
||||
EXIT(i_ret)
|
||||
}
|
||||
|
||||
|
||||
static void del(ppr_r, pi_balance, ppr_q, pfi_uar, pi_uar_called)
|
||||
tree **ppr_r;
|
||||
int *pi_balance;
|
||||
tree **ppr_q;
|
||||
int (*pfi_uar)();
|
||||
int *pi_uar_called;
|
||||
{
|
||||
void balanceR();
|
||||
|
||||
ENTER("del")
|
||||
|
||||
if ((*ppr_r)->tree_r != NULL) {
|
||||
del(&(*ppr_r)->tree_r, pi_balance, ppr_q, pfi_uar,
|
||||
pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceR(ppr_r, pi_balance);
|
||||
} else {
|
||||
if (pfi_uar)
|
||||
(*pfi_uar)((*ppr_q)->tree_p);
|
||||
*pi_uar_called = TRUE;
|
||||
(*ppr_q)->tree_p = (*ppr_r)->tree_p;
|
||||
*ppr_q = *ppr_r;
|
||||
*ppr_r = (*ppr_r)->tree_l;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
static void balanceL(ppr_p, pi_balance)
|
||||
tree **ppr_p;
|
||||
int *pi_balance;
|
||||
{
|
||||
tree *p1, *p2;
|
||||
int b1, b2;
|
||||
|
||||
ENTER("balanceL")
|
||||
MSG("left branch has shrunk")
|
||||
|
||||
switch ((*ppr_p)->tree_b)
|
||||
{
|
||||
case -1: MSG("was imbalanced, fixed implicitly")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
break;
|
||||
case 0: MSG("was okay, is now one off")
|
||||
(*ppr_p)->tree_b = 1;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 1: MSG("was already off, this is too much")
|
||||
p1 = (*ppr_p)->tree_r;
|
||||
b1 = p1->tree_b;
|
||||
if (b1 >= 0) {
|
||||
MSG("single RR")
|
||||
(*ppr_p)->tree_r = p1->tree_l;
|
||||
p1->tree_l = *ppr_p;
|
||||
if (b1 == 0) {
|
||||
MSG("b1 == 0")
|
||||
(*ppr_p)->tree_b = 1;
|
||||
p1->tree_b = -1;
|
||||
*pi_balance = FALSE;
|
||||
} else {
|
||||
MSG("b1 != 0")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
p1->tree_b = 0;
|
||||
}
|
||||
*ppr_p = p1;
|
||||
} else {
|
||||
MSG("double RL")
|
||||
p2 = p1->tree_l;
|
||||
b2 = p2->tree_b;
|
||||
p1->tree_l = p2->tree_r;
|
||||
p2->tree_r = p1;
|
||||
(*ppr_p)->tree_r = p2->tree_l;
|
||||
p2->tree_l = *ppr_p;
|
||||
if (b2 == 1)
|
||||
(*ppr_p)->tree_b = -1;
|
||||
else
|
||||
(*ppr_p)->tree_b = 0;
|
||||
if (b2 == -1)
|
||||
p1->tree_b = 1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
*ppr_p = p2;
|
||||
p2->tree_b = 0;
|
||||
}
|
||||
}
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
static void balanceR(ppr_p, pi_balance)
|
||||
tree **ppr_p;
|
||||
int *pi_balance;
|
||||
{
|
||||
tree *p1, *p2;
|
||||
int b1, b2;
|
||||
|
||||
ENTER("balanceR")
|
||||
MSG("right branch has shrunk")
|
||||
switch ((*ppr_p)->tree_b)
|
||||
{
|
||||
case 1: MSG("was imbalanced, fixed implicitly")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
break;
|
||||
case 0: MSG("was okay, is now one off")
|
||||
(*ppr_p)->tree_b = -1;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case -1: MSG("was already off, this is too much")
|
||||
p1 = (*ppr_p)->tree_l;
|
||||
b1 = p1->tree_b;
|
||||
if (b1 <= 0) {
|
||||
MSG("single LL")
|
||||
(*ppr_p)->tree_l = p1->tree_r;
|
||||
p1->tree_r = *ppr_p;
|
||||
if (b1 == 0) {
|
||||
MSG("b1 == 0")
|
||||
(*ppr_p)->tree_b = -1;
|
||||
p1->tree_b = 1;
|
||||
*pi_balance = FALSE;
|
||||
} else {
|
||||
MSG("b1 != 0")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
p1->tree_b = 0;
|
||||
}
|
||||
*ppr_p = p1;
|
||||
} else {
|
||||
MSG("double LR")
|
||||
p2 = p1->tree_r;
|
||||
b2 = p2->tree_b;
|
||||
p1->tree_r = p2->tree_l;
|
||||
p2->tree_l = p1;
|
||||
(*ppr_p)->tree_l = p2->tree_r;
|
||||
p2->tree_r = *ppr_p;
|
||||
if (b2 == -1)
|
||||
(*ppr_p)->tree_b = 1;
|
||||
else
|
||||
(*ppr_p)->tree_b = 0;
|
||||
if (b2 == 1)
|
||||
p1->tree_b = -1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
*ppr_p = p2;
|
||||
p2->tree_b = 0;
|
||||
}
|
||||
}
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
int tree_trav(ppr_tree, pfi_uar)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_uar)();
|
||||
{
|
||||
ENTER("tree_trav")
|
||||
|
||||
if (!*ppr_tree)
|
||||
EXIT(TRUE)
|
||||
|
||||
if (!tree_trav(&(**ppr_tree).tree_l, pfi_uar))
|
||||
EXIT(FALSE)
|
||||
if (!(*pfi_uar)((**ppr_tree).tree_p))
|
||||
EXIT(FALSE)
|
||||
if (!tree_trav(&(**ppr_tree).tree_r, pfi_uar))
|
||||
EXIT(FALSE)
|
||||
EXIT(TRUE)
|
||||
}
|
||||
|
||||
|
||||
void tree_mung(ppr_tree, pfi_uar)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_uar)();
|
||||
{
|
||||
ENTER("tree_mung")
|
||||
if (*ppr_tree)
|
||||
{
|
||||
tree_mung(&(**ppr_tree).tree_l, pfi_uar);
|
||||
tree_mung(&(**ppr_tree).tree_r, pfi_uar);
|
||||
if (pfi_uar)
|
||||
(*pfi_uar)((**ppr_tree).tree_p);
|
||||
free(*ppr_tree);
|
||||
*ppr_tree = NULL;
|
||||
}
|
||||
EXITV
|
||||
}
|
||||
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.h
Normal file
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* tree.h - declare structures used by tree.c
|
||||
* vix 27jun86 [broken out of tree.c]
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _TREE_FLAG
|
||||
#define _TREE_FLAG
|
||||
|
||||
|
||||
typedef struct tree_s
|
||||
{
|
||||
struct tree_s *tree_l, *tree_r;
|
||||
short tree_b;
|
||||
char *tree_p;
|
||||
}
|
||||
tree;
|
||||
|
||||
|
||||
#endif _TREE_FLAG
|
||||
124
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.man3
Normal file
124
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.man3
Normal file
@@ -0,0 +1,124 @@
|
||||
.TH TREE 2 "23 June 1986"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
tree_init, tree_mung, tree_srch, tree_add, tree_delete, tree_trav \- balanced binary tree routines
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.B void
|
||||
.B tree_init(tree)
|
||||
.B int **tree;
|
||||
.PP
|
||||
.B int *
|
||||
.B tree_srch(tree, compare, data)
|
||||
.B int **tree, (*compare)(), *data;
|
||||
.PP
|
||||
.B void
|
||||
.B tree_add(tree, compare, data, del_uar)
|
||||
.B int **tree, (*compare)(), *data, (*del_uar)();
|
||||
.PP
|
||||
.B int
|
||||
.B tree_delete(tree, compare, data, del_uar)
|
||||
.B int **tree, (*compare)(), *data, (*del_uar)();
|
||||
.PP
|
||||
.B int
|
||||
.B tree_trav(tree, trav_uar)
|
||||
.B int **tree, (*trav_uar)();
|
||||
.PP
|
||||
.B void
|
||||
.B tree_mung(tree, del_uar)
|
||||
.B int **tree, (*del_uar)();
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
These functions create and manipulate a balanced binary (AVL) tree. Each node
|
||||
of the tree contains the expected left & right subtree pointers, a short-int
|
||||
balance indicator, and a pointer to the user-data. On a 32-bit system, this
|
||||
means an overhead of 4+4+2+4 bytes per node. There is no key data type
|
||||
enforced by this package; a caller-supplied compare routine is used to compare
|
||||
user-data blocks.
|
||||
.PP
|
||||
.I Tree_init
|
||||
creates an empty tree and binds it to
|
||||
.I tree
|
||||
(which for this and all other routines in this package should be declared as
|
||||
a pointer to integer and passed by reference), which can then be used by other
|
||||
routines in this package. Note that more than one
|
||||
.I tree
|
||||
variable can exist at once; thus multiple trees can be manipulated
|
||||
simultaneously.
|
||||
.PP
|
||||
.I Tree_srch
|
||||
searches a tree for a specific node and returns either
|
||||
.I NULL
|
||||
if no node was found, or the address of the user-data for that node if one was
|
||||
found.
|
||||
.I compare
|
||||
is the address of a function to compare two user-data blocks. This routine
|
||||
should work much the way
|
||||
.IR strcmp 2
|
||||
does; in fact,
|
||||
.I strcmp
|
||||
could be used if the user-data was a null-terminated string.
|
||||
.I data
|
||||
is the address of a user-data block to be used via
|
||||
.I compare
|
||||
as the search criteria. The tree is searched for a node where
|
||||
.I compare
|
||||
returns 0.
|
||||
.PP
|
||||
.I Tree_add
|
||||
inserts or replaces a node in the specified tree. The tree specified by
|
||||
.I tree
|
||||
is searched as in
|
||||
.I tree_srch,
|
||||
and if a node is found to match
|
||||
.I data,
|
||||
then the
|
||||
.I del_uar
|
||||
function is called with the address of the user-data block for the node
|
||||
(this routine should deallocate any dynamic memory which is pointed to
|
||||
exclusively by the node); the user-data pointer for the node is then
|
||||
replaced by the value of
|
||||
.I data.
|
||||
If no node is found to match, a new node is added (which may or may not
|
||||
cause a transparent rebalance operation), with a user-data pointer equal
|
||||
to
|
||||
.I data.
|
||||
.PP
|
||||
.I Tree_delete
|
||||
deletes a node from
|
||||
.I tree.
|
||||
A rebalance may or may not occur, depending on where the node is removed from
|
||||
and what the rest of the tree looks like.
|
||||
.I Tree_delete
|
||||
returns TRUE if a node was deleted, FALSE otherwise.
|
||||
.PP
|
||||
.I Tree_trav
|
||||
traverses all of
|
||||
.I tree,
|
||||
calling
|
||||
.I trav_uar
|
||||
with the address of each user-data block. If
|
||||
.I trav_uar
|
||||
returns FALSE at any time,
|
||||
.I tree_trav
|
||||
will immediately return FALSE to its caller. Otherwise all nodes will be
|
||||
reached and
|
||||
.I tree_trav
|
||||
will return TRUE.
|
||||
.PP
|
||||
.I Tree_mung
|
||||
deletes every node in
|
||||
.I tree,
|
||||
calling
|
||||
.I del_uar
|
||||
with the user-data address from each node (see
|
||||
.I tree_add
|
||||
and
|
||||
.I tree_delete
|
||||
above). The tree is left in the same state that
|
||||
.I tree_init
|
||||
leaves it in \- i.e., empty.
|
||||
.SH AUTHOR
|
||||
Paul Vixie, converted and augumented from Modula-2 examples in
|
||||
.I Algorithms & Data Structures,
|
||||
Niklaus Wirth, Prentice-Hall, ISBN 0-13-022005-1.
|
||||
73
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/vixie.h
Normal file
73
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/vixie.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* vixie.h - include file to define general vixie-type things
|
||||
* v1.0 vix 21jun86 [broken out of as.h]
|
||||
*/
|
||||
|
||||
#ifdef DOCUMENTATION
|
||||
|
||||
There are two macros you can define before including this file which can
|
||||
change the things defined by this file.
|
||||
|
||||
DEBUG: if defined, will cause enter/exit messages to be printed by the
|
||||
ENTER/EXIT/EXITV macros. If not defined, causes ENTER to do nothing,
|
||||
and EXIT/EXITV to generate 'return' without any messages.
|
||||
|
||||
If defined, should be set to the name of the including module.
|
||||
|
||||
MAIN: Should be defined for a program containing a main() function which
|
||||
is linked with other modules which include this file.
|
||||
|
||||
Value is not important, only existence/nonexistence matters.
|
||||
|
||||
#endif DOCUMENTATION
|
||||
|
||||
|
||||
#ifndef _VIXIE_FLAG
|
||||
#define _VIXIE_FLAG
|
||||
|
||||
|
||||
/*--- debugging stuff ---*/
|
||||
#define MAXPROC 256
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ENTER(proc) { \
|
||||
APC_PROCS[I_PROC] = proc; \
|
||||
printf("ENTER(%d:%s.%s)\n", \
|
||||
I_PROC, DEBUG, APC_PROCS[I_PROC]); \
|
||||
I_PROC++; \
|
||||
}
|
||||
#define EXIT(value) { \
|
||||
I_PROC--; \
|
||||
printf("EXIT(%d:%s.%s)\n", \
|
||||
I_PROC, DEBUG, \
|
||||
APC_PROCS[I_PROC]); \
|
||||
return value; \
|
||||
}
|
||||
#define EXITV { \
|
||||
I_PROC--; \
|
||||
printf("EXITV(%d:%s.%s)\n", \
|
||||
I_PROC, DEBUG, \
|
||||
APC_PROCS[I_PROC]); \
|
||||
return value; \
|
||||
}
|
||||
#else
|
||||
#define ENTER(proc)
|
||||
#define EXIT(value) {return value;}
|
||||
#define EXITV return;
|
||||
#endif
|
||||
|
||||
#ifdef MAIN
|
||||
int I_PROC = 0;
|
||||
char *APC_PROCS[MAXPROC];
|
||||
#else
|
||||
extern int I_PROC;
|
||||
extern char *APC_PROCS[MAXPROC];
|
||||
#endif
|
||||
|
||||
|
||||
/*--- why didn't k&r put these into stdio.h? ---*/
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
extern char *malloc(), *calloc();
|
||||
|
||||
|
||||
#endif _VIXIE_FLAG
|
||||
44
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/Makefile
Normal file
44
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/Makefile
Normal file
@@ -0,0 +1,44 @@
|
||||
# $Id: Makefile,v 1.3 1994/02/28 22:28:36 hays Exp $
|
||||
|
||||
LEX=flex
|
||||
LEXFLAGS= -v
|
||||
YACC=bison
|
||||
YACCFLAGS= -y -v -d
|
||||
CFLAGS= -g
|
||||
DIST=README Makefile plm-lex.l plm-manifest.h plm-parse.y scope.c scope.h
|
||||
OBJS= plm-lex.o plm-parse.o scope.o tree.o
|
||||
#NOTE: tree.o and tree.h come from Paul Vixie's PD AVL Tree package,
|
||||
# comp.sources.unix Volume 27, Issue 34.
|
||||
|
||||
.y.c:
|
||||
|
||||
plm: $(OBJS)
|
||||
$(CC) $(CFLAGS) -o $@ $(OBJS)
|
||||
|
||||
plm-parse.h: plm-parse.c
|
||||
|
||||
plm-lex.c: plm-lex.l
|
||||
$(LEX) $(LEXFLAGS) -t $< > $@
|
||||
|
||||
plm-parse.c: plm-parse.y
|
||||
$(YACC) $(YACCFLAGS) $< -o $@
|
||||
|
||||
plm-lex.o: plm-lex.c plm-manifest.h plm-parse.h scope.h
|
||||
|
||||
plm-parse.o: plm-parse.c plm-manifest.h scope.h
|
||||
|
||||
scope.o: scope.c tree.h scope.h
|
||||
|
||||
clean:
|
||||
rm -f plm-parse.c plm-parse.h plm-parse.output \
|
||||
plm-*.o scope.o lex.backtrack tmp *~ plm-lex.c core plm \
|
||||
plm.shar
|
||||
|
||||
source:
|
||||
$(CO) $(DIST)
|
||||
|
||||
dist: source
|
||||
shar $(DIST) > plm.shar
|
||||
|
||||
|
||||
|
||||
189
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/README
Normal file
189
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/README
Normal file
@@ -0,0 +1,189 @@
|
||||
$Id: README,v 1.4 1994/04/05 20:33:58 hays Exp $
|
||||
|
||||
Ah, the wisdom of the ages...
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
What you are looking at is a basic (very basic) parser for a PL/M
|
||||
language.
|
||||
|
||||
The parser does nothing useful, and it isn't even a terribly wonderful
|
||||
example. On the other hand, it appears that no one else has bothered
|
||||
to publish even this much, before.
|
||||
|
||||
However, the parser does recognize a language very like PL/M-86,
|
||||
PL/M-286, or PL/M-386, as best we can determine.
|
||||
|
||||
All the information used to derive this parser comes from published
|
||||
manuals, sold to the public. No proprietary information, trade
|
||||
secrets, patented information, corporate assets, or skulduggery was
|
||||
used to develop this parser. Neither of the authors has ever seen the
|
||||
source to a working PL/M compiler (or, for that matter, to a
|
||||
non-working PL/M compiler).
|
||||
|
||||
Implementation Limits
|
||||
---------------------
|
||||
|
||||
This PL/M parser was developed and tested on a 486DX2/66 clone PC
|
||||
running Linux. The C code is written for an ANSI-compliant C
|
||||
compiler; GCC was used in our testing. Also, flex and bison were
|
||||
used, not lex and yacc. Paul Vixie's comp.sources.unix implementation
|
||||
of AVL trees was used to implement symbol table lookups.
|
||||
|
||||
You should expect some problems if you plan on building this parser
|
||||
with a K&R style C compiler. Using yacc and/or lex may be
|
||||
problematic, as well.
|
||||
|
||||
This parser does not support any of the "dollar" directives of a
|
||||
proper PL/M compiler. In fact, it will croak with the helpful message
|
||||
"parse error". Thus, implementing include files and compiler
|
||||
directives is left as an exercise for the reader.
|
||||
|
||||
The macro facility (aka "literally" declarations) depends on the
|
||||
lexical analysis skeleton allowing multiple characters of push-back on
|
||||
the input stream. This is a very, very poor assumption, but, with
|
||||
flex, at least, workable for this example. A real PL/M compiler would
|
||||
allow literals of unlimited length. To find the offending code, grep
|
||||
for the string "very weak" in the file "plm-lex.l".
|
||||
|
||||
No error recovery is implemented in the parser, at all.
|
||||
|
||||
There are no shift-reduce conflicts, nor reduce-reduce conflicts.
|
||||
|
||||
There are a couple of places in the parser where similar constructs
|
||||
cannot be distinguished, except by semantic analysis. These are
|
||||
marked by appropriate comments in the parser source file.
|
||||
|
||||
The "scoped literal table" implementation depends on Paul Vixie's
|
||||
(paul@vix.com) public domain AVL tree code, available as
|
||||
comp.sources.unix Volume 27, Issue 34 (`avl-subs'), at a friendly ftp
|
||||
site near you. We use "gatekeeper.dec.com". The benefits of using
|
||||
AVL trees for a symbol table (versus, say, hashing) are not subject to
|
||||
discussion. We used the avl-subs source code because it is reliable
|
||||
and easy to use.
|
||||
|
||||
This grammar has been validated against about 10,000 lines of real and
|
||||
artificial PL/M code.
|
||||
|
||||
PL/M Quirks
|
||||
-----------
|
||||
|
||||
PL/M has some very interesting quirks. For example, a value is
|
||||
considered to be "true", for the purposes of an `if' test, if it is
|
||||
odd (low bit set). Thus, the value 0x3 is true, whereas 0x4 is not.
|
||||
The language itself, given a boolean expression, generates the value
|
||||
0xff for true. [This factoid doesn't affect the parser per se, but
|
||||
does appear to be the main pitfall for those whose hubris leads them
|
||||
to translate PL/M to C.]
|
||||
|
||||
String constants can contain any ASCII value, excepting a single
|
||||
apostrophe, a newline, or 0x81. The latter, presumably, has something
|
||||
to do with Kanji support.
|
||||
|
||||
To embed a single apostrophe in a string constant, two apostrophes may
|
||||
be used. Thus, 'k''s' is a string consisting of a letter k, a single
|
||||
apostrophe, and a letter s. Strings are not null terminated, so our
|
||||
example string, 'k''s', requires just three bytes of storage.
|
||||
|
||||
PL/M supports a macro language, of sorts, that is integrated into the
|
||||
language's declaration syntax:
|
||||
|
||||
declare Ford literally 'Edsel';
|
||||
declare Mercury literally 'Ford';
|
||||
|
||||
After the above declarations, any instance of the identifier "Ford"
|
||||
will be replaced with the string "Edsel", and any occurrence of the
|
||||
identifier "Mercury" will be replaced by the string "Ford", which will
|
||||
then be replaced by the string "Edsel". The literal string can be
|
||||
more complicated, of course. Only identifiers are subject to
|
||||
substitution - substitution does not occur inside string constants.
|
||||
|
||||
Literal macros are parameterless, and obey the scoping rules of the
|
||||
language. Thus, it is possible to have different values for the same
|
||||
macro in different, non-nested scopes. [Exercise: Why can't you have
|
||||
different values for literals in nested scopes?]
|
||||
|
||||
Keywords, of course, cannot be macro names, because they are not
|
||||
allowed as variable names.
|
||||
|
||||
PL/M allows dollar signs ("$") to be used inside keywords,
|
||||
identifiers, and numerical constants. PL/M is also case insensitive.
|
||||
Thus, the following two identifiers are the "same":
|
||||
|
||||
my_very_own_variable_02346
|
||||
|
||||
m$Y_$$$VeRy_$$O$$$$$W$$$$$$N_varIABLE$$$$$$$$$$_$02$346
|
||||
|
||||
Loverly, eh? Obfuscated C, stand to the side.
|
||||
|
||||
Casting in PL/M (a relatively late addition to the language) is
|
||||
provided by a motley assortment of functions with the same names as
|
||||
the basic types to which they are casting, accepting a single argument
|
||||
of some other (or even the same) type.
|
||||
|
||||
Note that the EBNF grammar published in what must be considered the
|
||||
definitive work, _PL/M Programmer's Guide_, Intel order number
|
||||
452161-003, Appendix C, is incorrect in several respects. If you're
|
||||
interested in the differences, we've preserved, as much as is
|
||||
possible, the production names of that EBNF in the YACCable grammar.
|
||||
|
||||
Some known problems with the published, Appendix C, EBNF grammar:
|
||||
|
||||
- One of the productions is an orphan, ("scoping_statements").
|
||||
|
||||
- unary minus is shown as a prefix operator, and unary plus as a
|
||||
postfix operator ("secondary").
|
||||
|
||||
- Casting does not appear in the published grammar.
|
||||
|
||||
- Nested structures do not appear in the published grammar, and
|
||||
the reference syntax for selecting a nested structure member
|
||||
is also missing.
|
||||
|
||||
- The WORD type is missing from the "basic_type" production.
|
||||
|
||||
- The "initialization" production allows the initial value list
|
||||
only after the INITIAL keyword, when, in fact, the initial value
|
||||
list may follow the DATA keyword, as well.
|
||||
|
||||
On the other hand, the precedence of the expression operators is
|
||||
correct as written in the EBNF grammar, the dangling else problem is
|
||||
non-existent, and there are no associativity problems, as all
|
||||
operators associate left-to-right.
|
||||
|
||||
To complicate matters, the above referenced manual may be out of
|
||||
print. A more recent version, which covers the PL/M-386 dialect only,
|
||||
is _PL/M-386 Programmer's Guide_, Intel order number 611052-001.
|
||||
|
||||
The latter manual has some corrections, but has some introduced errors
|
||||
in the EBNF, as well. The problems with the unary minus and the
|
||||
"initialization" production are repaired, but the definition for a
|
||||
"binary_number" is malformed, as are the definitions for the
|
||||
"fractional_part", "string_body_element", "variable_element", and
|
||||
"if_condition" productions.
|
||||
|
||||
We're right, they're wrong.
|
||||
|
||||
The Authors
|
||||
-----------
|
||||
|
||||
Gary Funck (gary@intrepid.com) was responsible for starting this
|
||||
effort. He authored the original grammar.
|
||||
|
||||
Kirk Hays (hays@ichips.intel.com) wrote the lexical analyzer and the
|
||||
scoped literal table implementation. He also validated and corrected
|
||||
the grammar, and extended it to cover documented features not
|
||||
appearing in the published EBNF.
|
||||
|
||||
Future Plans
|
||||
------------
|
||||
|
||||
If there is enough interest (or, even if there isn't), Kirk is
|
||||
planning on producing a PL/M front end for the GNU compiler. Contact
|
||||
him at the above Email address for further information. Donations of
|
||||
PL/M source code of any dialect (including PL/M-80, PL/M-51, and
|
||||
PL/M-96)(yes, we already have the Kermit implementations), or a
|
||||
willingness to be a pre-alpha tester with code you cannot donate, are
|
||||
sufficient grounds to contact Kirk.
|
||||
|
||||
301
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/plm-lex.l
Normal file
301
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/plm-lex.l
Normal file
@@ -0,0 +1,301 @@
|
||||
%{
|
||||
/* lexer for PL/M syntax.
|
||||
|
||||
$Id: plm-lex.l,v 1.2 1994/02/28 22:24:34 hays Exp $
|
||||
|
||||
Copyright 1994 by Kirk Hays (hays@ichips.intel.com) and Gary Funck
|
||||
(gary@intrepid.com)
|
||||
|
||||
USE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but without any warranty. Further, there is no implied warranty of
|
||||
merchantability or fitness for a particular purpose.
|
||||
|
||||
*/
|
||||
|
||||
/* This file defines the syntax of PL/M. */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "plm-manifest.h"
|
||||
#include "plm-parse.h"
|
||||
#include "scope.h"
|
||||
|
||||
int lineno = 1;
|
||||
|
||||
/* forward references */
|
||||
char * canonical_string (char *);
|
||||
char * canonical_identifier (char *);
|
||||
static void error (char *);
|
||||
|
||||
%}
|
||||
|
||||
DIGIT_STRING [0-9][0-9$]*
|
||||
A [Aa]($)*
|
||||
B [Bb]($)*
|
||||
C [Cc]($)*
|
||||
D [Dd]($)*
|
||||
E [Ee]($)*
|
||||
F [Ff]($)*
|
||||
G [Gg]($)*
|
||||
H [Hh]($)*
|
||||
I [Ii]($)*
|
||||
L [Ll]($)*
|
||||
M [Mm]($)*
|
||||
N [Nn]($)*
|
||||
O [Oo]($)*
|
||||
P [Pp]($)*
|
||||
Q [Qq]($)*
|
||||
R [Rr]($)*
|
||||
S [Ss]($)*
|
||||
T [Tt]($)*
|
||||
U [Uu]($)*
|
||||
W [Ww]($)*
|
||||
X [Xx]($)*
|
||||
Y [Yy]($)*
|
||||
|
||||
%%
|
||||
|
||||
{A}{D}{D}{R}{E}{S}{S} return ADDRESS;
|
||||
{A}{N}{D} return AND;
|
||||
{A}{T} return AT;
|
||||
{B}{A}{S}{E}{D} return BASED;
|
||||
{B}{Y} return BY;
|
||||
{B}{Y}{T}{E} return BYTE;
|
||||
{C}{A}{L}{L} return CALL;
|
||||
{C}{A}{S}{E} return CASE;
|
||||
{C}{A}{U}{S}{E}{I}{N}{T}{E}{R}{R}{U}{P}{T} return CAUSE_INTERRUPT;
|
||||
{C}{H}{A}{R}{I}{N}{T} return CHARINT;
|
||||
{D}{A}{T}{A} return DATA;
|
||||
{D}{E}{C}{L}{A}{R}{E} return DECLARE;
|
||||
{D}{I}{S}{A}{B}{L}{E} return DISABLE;
|
||||
{D}{O} return DO;
|
||||
{D}{W}{O}{R}{D} return DWORD;
|
||||
{E}{L}{S}{E} return ELSE;
|
||||
{E}{N}{A}{B}{L}{E} return ENABLE;
|
||||
{E}{N}{D} return END;
|
||||
{E}{O}{F} return EOF_KW;
|
||||
{E}{X}{T}{E}{R}{N}{A}{L} return EXTERNAL;
|
||||
{G}{O} return GO;
|
||||
{G}{O}{T}{O} return GOTO;
|
||||
{H}{A}{L}{T} return HALT;
|
||||
{H}{W}{O}{R}{D} return HWORD;
|
||||
{I}{F} return IF;
|
||||
{I}{N}{I}{T}{I}{A}{L} return INITIAL_KW;
|
||||
{I}{N}{T}{E}{G}{E}{R} return INTEGER;
|
||||
{I}{N}{T}{E}{R}{R}{U}{P}{T} return INTERRUPT;
|
||||
{L}{A}{B}{E}{L} return LABEL;
|
||||
{L}{I}{T}{E}{R}{A}{L}{L}{Y} return LITERALLY;
|
||||
{L}{O}{N}{G}{I}{N}{T} return LONGINT;
|
||||
{M}{I}{N}{U}{S} return MINUS;
|
||||
{M}{O}{D} return MOD;
|
||||
{N}{O}{T} return NOT;
|
||||
{O}{F}{F}{S}{E}{T} return OFFSET;
|
||||
{O}{R} return OR;
|
||||
{P}{L}{U}{S} return PLUS;
|
||||
{P}{O}{I}{N}{T}{E}{R} return POINTER;
|
||||
{P}{R}{O}{C}{E}{D}{U}{R}{E} return PROCEDURE;
|
||||
{P}{U}{B}{L}{I}{C} return PUBLIC;
|
||||
{Q}{W}{O}{R}{D} return QWORD;
|
||||
{R}{E}{A}{L} return REAL;
|
||||
{R}{E}{E}{N}{T}{R}{A}{N}{T} return REENTRANT;
|
||||
{R}{E}{T}{U}{R}{N} return RETURN;
|
||||
{S}{E}{L}{E}{C}{T}{O}{R} return SELECTOR;
|
||||
{S}{H}{O}{R}{T}{I}{N}{T} return SHORTINT;
|
||||
{S}{T}{R}{U}{C}{T}{U}{R}{E} return STRUCTURE;
|
||||
{T}{H}{E}{N} return THEN;
|
||||
{T}{O} return TO;
|
||||
{W}{H}{I}{L}{E} return WHILE;
|
||||
{W}{O}{R}{D} return WORD;
|
||||
{X}{O}{R} return XOR;
|
||||
|
||||
[_A-Za-z][_$0-9A-Za-z]* {
|
||||
char * string;
|
||||
int i;
|
||||
yylval = canonical_identifier(yytext);
|
||||
string = lookup_literal(yylval);
|
||||
if (!string)
|
||||
{
|
||||
return IDENTIFIER;
|
||||
}
|
||||
free(yylval);
|
||||
yylval=0; /*excessive neatness*/
|
||||
/* push the string back onto the input
|
||||
stream - it is necessary to push
|
||||
from right to left */
|
||||
for (i = strlen (string);
|
||||
i >= 0;
|
||||
i--)
|
||||
{
|
||||
/* very weak - depends on lexical
|
||||
generator allowing sufficient
|
||||
push-back */
|
||||
unput (string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
[0-9][0-9$]*(d)? return DECIMAL_NUMBER;
|
||||
|
||||
{DIGIT_STRING}\.({DIGIT_STRING})?([E|e][+|-]?{DIGIT_STRING})? return FLOATING_POINT_NUMBER;
|
||||
|
||||
[01][01$]*[bB] return BINARY_NUMBER;
|
||||
|
||||
[0-9][0-9a-fA-F$]*[hH] return HEX_NUMBER;
|
||||
|
||||
[0-7][0-7$]*[OoQq] return OCTAL_NUMBER;
|
||||
|
||||
'([^'\n\201]|(''))+' {
|
||||
yylval = canonical_string(yytext);
|
||||
return STRING;
|
||||
}
|
||||
|
||||
:= return ASSIGN_OP;
|
||||
|
||||
[\@] return AT_SIGN;
|
||||
|
||||
: return COLON;
|
||||
|
||||
, return COMMA;
|
||||
|
||||
[\.] return DOT;
|
||||
|
||||
= return EQ;
|
||||
|
||||
>= return GE;
|
||||
|
||||
> return GT;
|
||||
|
||||
"<=" return LE;
|
||||
|
||||
\( return LPAREN;
|
||||
|
||||
"<" return LT;
|
||||
|
||||
- return MINUS_SIGN;
|
||||
|
||||
"<>" return NE;
|
||||
|
||||
"+" return PLUS_SIGN;
|
||||
|
||||
\) return RPAREN;
|
||||
|
||||
; return SEMI;
|
||||
|
||||
"/" return SLASH;
|
||||
|
||||
\* return STAR;
|
||||
|
||||
\f
|
||||
|
||||
\n lineno++;
|
||||
|
||||
[\t ]*
|
||||
|
||||
"/*" {
|
||||
register int c;
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
while ( (c = input()) != '*' &&
|
||||
c != EOF )
|
||||
if (c == '\n') lineno++;
|
||||
/* eat up text of comment */
|
||||
|
||||
if ( c == '*' )
|
||||
{
|
||||
while ( (c = input()) == '*' )
|
||||
;
|
||||
if ( c == '/' )
|
||||
break; /* found the end */
|
||||
}
|
||||
|
||||
if (c == '\n') lineno++;
|
||||
|
||||
if ( c == EOF )
|
||||
{
|
||||
error( "EOF in comment" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.
|
||||
|
||||
%%
|
||||
|
||||
static void error (char * x) {printf (x);}
|
||||
|
||||
/* Strip the single quotes from a pl/m string, and
|
||||
compress any single quote pairs to one quote.
|
||||
|
||||
Allocates new storage for the string.
|
||||
*/
|
||||
char *
|
||||
canonical_string (char * s)
|
||||
{
|
||||
int i, i_ret;
|
||||
char * ret;
|
||||
int len = strlen (s);
|
||||
|
||||
ret = malloc (len+1);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
for (i = 1, i_ret = 0; i < (len-1); i++)
|
||||
{
|
||||
ret[i_ret++] = s[i];
|
||||
if (s[i] == '\'')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
ret[i_ret] = 0;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* Strip the dollar signs from a pl/m identifier or
|
||||
numeric constant, and force all alphabetic characters
|
||||
to lower case.
|
||||
|
||||
Allocates new storage for the identifier string.
|
||||
|
||||
*/
|
||||
char *
|
||||
canonical_identifier (char * s)
|
||||
{
|
||||
int i, i_ret;
|
||||
char * ret;
|
||||
int len = strlen (s);
|
||||
|
||||
ret = malloc (len+1);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
for (i = 0, i_ret = 0; i < len; i++)
|
||||
{
|
||||
if (s[i] == '$')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ret[i_ret++] = tolower (s[i]);
|
||||
}
|
||||
|
||||
ret[i_ret] = 0;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
#ifdef LEX_ONLY
|
||||
|
||||
main() {
|
||||
|
||||
for (;;)
|
||||
yylex();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
21
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/plm-manifest.h
Normal file
21
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/plm-manifest.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* manifest constants/types for PL/M lexer/parser.
|
||||
|
||||
$Id: plm-manifest.h,v 1.1 1994/02/28 20:54:26 hays Exp $
|
||||
|
||||
Copyright 1994 by Kirk Hays (hays@ichips.intel.com)
|
||||
|
||||
USE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but without any warranty. Further, there is no implied warranty of
|
||||
merchantability or fitness for a particular purpose.
|
||||
|
||||
*/
|
||||
|
||||
extern int lineno;
|
||||
|
||||
/* brute force type the value stack - this would not be appropriate in
|
||||
a real compiler, but suits our purposes just fine */
|
||||
|
||||
typedef char * CHAR_PTR;
|
||||
#define YYSTYPE CHAR_PTR
|
||||
|
||||
634
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/plm-parse.y
Normal file
634
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/plm-parse.y
Normal file
@@ -0,0 +1,634 @@
|
||||
/* YACC parser for PL/M syntax.
|
||||
|
||||
$Id: plm-parse.y,v 1.1 1994/02/28 20:54:56 hays Exp $
|
||||
|
||||
Copyright 1994 by Kirk Hays (hays@ichips.intel.com) and Gary Funck
|
||||
(gary@intrepid.com)
|
||||
|
||||
USE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but without any warranty. Further, there is no implied warranty of
|
||||
merchantability or fitness for a particular purpose.
|
||||
|
||||
*/
|
||||
|
||||
/* This file defines the grammar of PL/M. */
|
||||
|
||||
%{
|
||||
|
||||
/*
|
||||
* YACC grammar of PL/M
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "plm-manifest.h"
|
||||
#include "scope.h"
|
||||
|
||||
void yyerror ();
|
||||
|
||||
/* Cause the `yydebug' variable to be defined. */
|
||||
#define YYDEBUG (1)
|
||||
|
||||
%}
|
||||
|
||||
%token ADDRESS AND ASSIGN_OP AT AT_SIGN BASED
|
||||
%token BINARY_NUMBER BY BYTE CALL CASE
|
||||
%token CAUSE_INTERRUPT CHARINT COLON COMMA DATA
|
||||
%token DECIMAL_NUMBER DECLARE DISABLE DO DOT
|
||||
%token DWORD ELSE ENABLE END EOF_KW EQ
|
||||
%token EXTERNAL FLOATING_POINT_NUMBER GE GO
|
||||
%token GOTO GT HALT HEX_NUMBER HWORD
|
||||
%token IDENTIFIER
|
||||
%token IF INITIAL_KW INTEGER INTERRUPT
|
||||
%token LABEL LE LITERALLY LONGINT LPAREN LT
|
||||
%token MINUS MINUS_SIGN MOD NE NOT
|
||||
%token OCTAL_NUMBER OFFSET OR PLUS PLUS_SIGN
|
||||
%token POINTER PROCEDURE PUBLIC QWORD
|
||||
%token REAL REENTRANT RETURN RPAREN SELECTOR
|
||||
%token SEMI SHORTINT SLASH STAR STRING
|
||||
%token STRUCTURE THEN TO WHILE WORD XOR
|
||||
|
||||
|
||||
%start compilation
|
||||
|
||||
%%
|
||||
actual_parameters:
|
||||
LPAREN expression_list RPAREN
|
||||
;
|
||||
adding_operator:
|
||||
MINUS
|
||||
| MINUS_SIGN
|
||||
| PLUS
|
||||
| PLUS_SIGN
|
||||
;
|
||||
and_operator:
|
||||
AND
|
||||
;
|
||||
arithmetic_expression:
|
||||
term
|
||||
| arithmetic_expression adding_operator term
|
||||
;
|
||||
array_specifier:
|
||||
explicit_dimension
|
||||
| implicit_dimension
|
||||
;
|
||||
assignment_statement:
|
||||
left_part EQ expression SEMI
|
||||
;
|
||||
base_specifier:
|
||||
IDENTIFIER
|
||||
| IDENTIFIER DOT IDENTIFIER
|
||||
;
|
||||
basic_statement:
|
||||
assignment_statement
|
||||
| call_statement
|
||||
| goto_statement
|
||||
| microprocessor_dependent_statement
|
||||
| null_statement
|
||||
| return_statement
|
||||
;
|
||||
basic_type:
|
||||
ADDRESS
|
||||
| BYTE
|
||||
| CHARINT
|
||||
| DWORD
|
||||
| HWORD
|
||||
| INTEGER
|
||||
| LONGINT
|
||||
| OFFSET
|
||||
| POINTER
|
||||
| QWORD
|
||||
| REAL
|
||||
| SELECTOR
|
||||
| SHORTINT
|
||||
| WORD
|
||||
;
|
||||
bound_expression:
|
||||
expression
|
||||
;
|
||||
by_part:
|
||||
BY step_expression
|
||||
;
|
||||
call_statement:
|
||||
CALL simple_variable SEMI
|
||||
| CALL simple_variable actual_parameters SEMI
|
||||
;
|
||||
cast_type:
|
||||
basic_type
|
||||
;
|
||||
cause_interrupt_statement:
|
||||
CAUSE_INTERRUPT LPAREN integer_constant RPAREN SEMI
|
||||
;
|
||||
compilation:
|
||||
module
|
||||
| module EOF_KW
|
||||
;
|
||||
conditional_clause:
|
||||
if_condition true_unit
|
||||
| if_condition true_element ELSE false_element
|
||||
;
|
||||
constant:
|
||||
STRING
|
||||
| numeric_constant
|
||||
;
|
||||
constant_attribute:
|
||||
DATA
|
||||
;
|
||||
constant_list:
|
||||
constant
|
||||
| constant_list COMMA constant
|
||||
;
|
||||
declaration:
|
||||
declare_statement
|
||||
| procedure_definition
|
||||
;
|
||||
declaration_sequence:
|
||||
declaration
|
||||
| declaration_sequence declaration
|
||||
;
|
||||
declare_element:
|
||||
factored_element
|
||||
| unfactored_element
|
||||
;
|
||||
declare_element_list:
|
||||
declare_element
|
||||
| declare_element_list COMMA declare_element
|
||||
;
|
||||
declare_statement:
|
||||
DECLARE declare_element_list SEMI
|
||||
;
|
||||
disable_statement:
|
||||
DISABLE SEMI
|
||||
;
|
||||
do_block:
|
||||
do_case_block
|
||||
| do_while_block
|
||||
| iterative_do_block
|
||||
| simple_do_block
|
||||
;
|
||||
do_case_block:
|
||||
do_case_statement ending
|
||||
| do_case_statement unit_sequence ending
|
||||
;
|
||||
do_case_statement:
|
||||
DO CASE expression SEMI {
|
||||
push_scope();
|
||||
}
|
||||
;
|
||||
do_while_block:
|
||||
do_while_statement ending
|
||||
| do_while_statement unit_sequence ending
|
||||
;
|
||||
do_while_statement:
|
||||
DO WHILE expression SEMI {
|
||||
push_scope();
|
||||
}
|
||||
;
|
||||
embedded_assignment:
|
||||
variable_reference ASSIGN_OP logical_expression
|
||||
;
|
||||
enable_statement:
|
||||
ENABLE SEMI
|
||||
;
|
||||
end_statement:
|
||||
END opt_identifier SEMI {
|
||||
pop_scope();
|
||||
}
|
||||
;
|
||||
ending:
|
||||
end_statement
|
||||
| label_definition_sequence end_statement
|
||||
;
|
||||
explicit_dimension:
|
||||
LPAREN numeric_constant RPAREN
|
||||
;
|
||||
expression:
|
||||
embedded_assignment
|
||||
| logical_expression
|
||||
;
|
||||
expression_list:
|
||||
expression
|
||||
| expression_list COMMA expression
|
||||
;
|
||||
factored_element:
|
||||
factored_label_element
|
||||
| factored_variable_element
|
||||
;
|
||||
/*
|
||||
* factored_label_element doesn't permit based variables,
|
||||
* yet factored_variable_element does. This can't be disambiguated
|
||||
* syntactically. Thus, the factored_label element will have to
|
||||
* make the proper semantic checks to make the sure that the
|
||||
* variable_name_specifier_list is in fact an identifier_list.
|
||||
*/
|
||||
factored_label_element:
|
||||
LPAREN variable_name_specifier_list RPAREN LABEL opt_public_or_external
|
||||
;
|
||||
factored_member:
|
||||
LPAREN member_name_list RPAREN opt_explicit_dimension variable_type
|
||||
;
|
||||
factored_variable_element:
|
||||
LPAREN variable_name_specifier_list RPAREN opt_explicit_dimension variable_type opt_variable_attributes
|
||||
;
|
||||
false_element:
|
||||
unit
|
||||
;
|
||||
formal_parameter:
|
||||
IDENTIFIER
|
||||
;
|
||||
formal_parameter_list:
|
||||
formal_parameter
|
||||
| formal_parameter_list COMMA formal_parameter
|
||||
;
|
||||
formal_parameter_specifier:
|
||||
LPAREN formal_parameter_list RPAREN
|
||||
;
|
||||
go_to:
|
||||
GOTO
|
||||
| GO TO
|
||||
;
|
||||
goto_statement:
|
||||
go_to IDENTIFIER SEMI
|
||||
;
|
||||
halt_statement:
|
||||
HALT SEMI
|
||||
;
|
||||
id_colon:
|
||||
IDENTIFIER COLON
|
||||
;
|
||||
if_condition:
|
||||
IF expression THEN
|
||||
;
|
||||
implicit_dimension:
|
||||
LPAREN STAR RPAREN
|
||||
;
|
||||
index_part:
|
||||
index_variable EQ start_expression
|
||||
;
|
||||
index_variable:
|
||||
simple_variable
|
||||
;
|
||||
initial_value:
|
||||
expression
|
||||
;
|
||||
initial_value_list:
|
||||
initial_value
|
||||
| initial_value_list COMMA initial_value
|
||||
;
|
||||
initialization:
|
||||
DATA LPAREN initial_value_list RPAREN
|
||||
| INITIAL_KW LPAREN initial_value_list RPAREN
|
||||
;
|
||||
integer_constant:
|
||||
BINARY_NUMBER
|
||||
| DECIMAL_NUMBER
|
||||
| HEX_NUMBER
|
||||
| OCTAL_NUMBER
|
||||
;
|
||||
interrupt:
|
||||
INTERRUPT opt_interrupt_number
|
||||
;
|
||||
interrupt_number:
|
||||
integer_constant
|
||||
;
|
||||
iterative_do_block:
|
||||
iterative_do_statement ending
|
||||
| iterative_do_statement unit_sequence ending
|
||||
;
|
||||
iterative_do_statement:
|
||||
DO index_part to_part opt_by_part SEMI {
|
||||
push_scope();
|
||||
}
|
||||
;
|
||||
label_definition:
|
||||
id_colon
|
||||
;
|
||||
label_definition_sequence:
|
||||
label_definition
|
||||
| label_definition_sequence label_definition
|
||||
;
|
||||
label_element:
|
||||
IDENTIFIER LABEL opt_public_or_external
|
||||
;
|
||||
left_part:
|
||||
variable_reference_list
|
||||
;
|
||||
literal_element:
|
||||
IDENTIFIER LITERALLY STRING {
|
||||
enter_literal ($1, $3);
|
||||
}
|
||||
;
|
||||
location_reference:
|
||||
AT_SIGN variable_reference
|
||||
| AT_SIGN LPAREN constant_list RPAREN
|
||||
| DOT variable_reference
|
||||
| DOT LPAREN constant_list RPAREN
|
||||
;
|
||||
locator:
|
||||
AT LPAREN expression RPAREN
|
||||
;
|
||||
locator_initialization:
|
||||
locator
|
||||
| initialization
|
||||
| locator initialization
|
||||
;
|
||||
logical_expression:
|
||||
logical_factor
|
||||
| logical_expression or_operator logical_factor
|
||||
;
|
||||
logical_factor:
|
||||
logical_secondary
|
||||
| logical_factor and_operator logical_secondary
|
||||
;
|
||||
logical_primary:
|
||||
arithmetic_expression
|
||||
| arithmetic_expression relation_operator arithmetic_expression
|
||||
;
|
||||
logical_secondary:
|
||||
logical_primary
|
||||
| NOT logical_primary
|
||||
;
|
||||
member_element:
|
||||
structure_type
|
||||
| factored_member
|
||||
| unfactored_member
|
||||
;
|
||||
member_element_list:
|
||||
member_element
|
||||
| member_element_list COMMA member_element
|
||||
;
|
||||
member_name:
|
||||
IDENTIFIER
|
||||
;
|
||||
member_name_list:
|
||||
member_name
|
||||
| member_name_list COMMA member_name
|
||||
;
|
||||
member_specifier:
|
||||
DOT member_name
|
||||
| DOT member_name subscript
|
||||
;
|
||||
member_specifier_sequence:
|
||||
member_specifier_sequence member_specifier
|
||||
| member_specifier
|
||||
;
|
||||
microprocessor_dependent_statement:
|
||||
cause_interrupt_statement
|
||||
| disable_statement
|
||||
| enable_statement
|
||||
| halt_statement
|
||||
;
|
||||
module:
|
||||
module_name COLON simple_do_block
|
||||
;
|
||||
module_name:
|
||||
IDENTIFIER
|
||||
;
|
||||
multiplying_operator:
|
||||
MOD
|
||||
| SLASH
|
||||
| STAR
|
||||
;
|
||||
null_statement:
|
||||
SEMI
|
||||
;
|
||||
numeric_constant:
|
||||
FLOATING_POINT_NUMBER
|
||||
| integer_constant
|
||||
;
|
||||
opt_array_specifier:
|
||||
/* empty */
|
||||
| array_specifier
|
||||
;
|
||||
opt_by_part:
|
||||
/* empty */
|
||||
| by_part
|
||||
;
|
||||
opt_explicit_dimension:
|
||||
/* empty */
|
||||
| explicit_dimension
|
||||
;
|
||||
opt_formal_parameter_specifier:
|
||||
/* empty */
|
||||
| formal_parameter_specifier
|
||||
;
|
||||
opt_identifier:
|
||||
/* empty */
|
||||
| IDENTIFIER
|
||||
;
|
||||
opt_interrupt_number:
|
||||
/* empty */
|
||||
| interrupt_number
|
||||
;
|
||||
opt_procedure_attribute_sequence:
|
||||
/* empty */
|
||||
| procedure_attribute_sequence
|
||||
;
|
||||
opt_procedure_type:
|
||||
/* empty */
|
||||
| procedure_type
|
||||
;
|
||||
opt_public_or_external:
|
||||
/* empty */
|
||||
| EXTERNAL
|
||||
| PUBLIC
|
||||
;
|
||||
opt_variable_attributes:
|
||||
/* empty */
|
||||
| variable_attributes
|
||||
;
|
||||
or_operator:
|
||||
OR
|
||||
| XOR
|
||||
;
|
||||
primary:
|
||||
constant
|
||||
| location_reference
|
||||
| subexpression
|
||||
| variable_reference
|
||||
;
|
||||
procedure_attribute:
|
||||
EXTERNAL
|
||||
| PUBLIC
|
||||
| REENTRANT
|
||||
| interrupt PUBLIC
|
||||
| interrupt EXTERNAL
|
||||
;
|
||||
procedure_attribute_sequence:
|
||||
procedure_attribute
|
||||
| procedure_attribute_sequence procedure_attribute
|
||||
;
|
||||
procedure_definition:
|
||||
procedure_statement ending
|
||||
| procedure_statement declaration_sequence ending
|
||||
| procedure_statement unit_sequence ending
|
||||
| procedure_statement declaration_sequence unit_sequence ending
|
||||
;
|
||||
procedure_statement:
|
||||
id_colon PROCEDURE opt_formal_parameter_specifier opt_procedure_type opt_procedure_attribute_sequence SEMI
|
||||
{
|
||||
push_scope();
|
||||
}
|
||||
;
|
||||
procedure_type:
|
||||
basic_type
|
||||
;
|
||||
relation_operator:
|
||||
EQ
|
||||
| GE
|
||||
| GT
|
||||
| LE
|
||||
| LT
|
||||
| NE
|
||||
;
|
||||
return_statement:
|
||||
typed_return
|
||||
| untyped_return
|
||||
;
|
||||
secondary:
|
||||
primary
|
||||
| unary_sign primary
|
||||
;
|
||||
simple_do_block:
|
||||
simple_do_statement ending
|
||||
| simple_do_statement unit_sequence ending
|
||||
| simple_do_statement declaration_sequence ending
|
||||
| simple_do_statement declaration_sequence unit_sequence ending
|
||||
;
|
||||
simple_do_statement:
|
||||
DO SEMI {
|
||||
push_scope();
|
||||
}
|
||||
;
|
||||
simple_variable:
|
||||
IDENTIFIER
|
||||
| IDENTIFIER DOT IDENTIFIER
|
||||
;
|
||||
start_expression:
|
||||
expression
|
||||
;
|
||||
step_expression:
|
||||
expression
|
||||
;
|
||||
structure_type:
|
||||
STRUCTURE LPAREN member_element_list RPAREN
|
||||
;
|
||||
subexpression:
|
||||
LPAREN expression RPAREN
|
||||
;
|
||||
subscript:
|
||||
LPAREN expression RPAREN
|
||||
;
|
||||
subscript_or_actual_parameters:
|
||||
LPAREN expression_list RPAREN
|
||||
;
|
||||
term:
|
||||
secondary
|
||||
| term multiplying_operator secondary
|
||||
;
|
||||
to_part:
|
||||
TO bound_expression
|
||||
;
|
||||
true_element:
|
||||
true_statement
|
||||
| label_definition_sequence true_statement
|
||||
;
|
||||
true_statement:
|
||||
do_block
|
||||
| basic_statement
|
||||
;
|
||||
true_unit:
|
||||
unit
|
||||
;
|
||||
typed_return:
|
||||
RETURN expression SEMI
|
||||
;
|
||||
unary_minus:
|
||||
MINUS_SIGN
|
||||
;
|
||||
unary_plus:
|
||||
PLUS_SIGN
|
||||
;
|
||||
unary_sign:
|
||||
unary_minus
|
||||
| unary_plus
|
||||
;
|
||||
unfactored_element:
|
||||
label_element
|
||||
| literal_element
|
||||
| variable_element
|
||||
;
|
||||
unfactored_member:
|
||||
member_name opt_explicit_dimension variable_type
|
||||
;
|
||||
unit:
|
||||
unit_element
|
||||
| label_definition_sequence unit_element
|
||||
;
|
||||
unit_element:
|
||||
basic_statement
|
||||
| conditional_clause
|
||||
| do_block
|
||||
;
|
||||
unit_sequence:
|
||||
unit
|
||||
| unit_sequence unit
|
||||
;
|
||||
untyped_return:
|
||||
RETURN SEMI
|
||||
;
|
||||
variable_attributes:
|
||||
EXTERNAL constant_attribute
|
||||
| EXTERNAL
|
||||
| PUBLIC locator_initialization
|
||||
| PUBLIC
|
||||
| locator_initialization
|
||||
;
|
||||
variable_element:
|
||||
variable_name_specifier opt_array_specifier variable_type opt_variable_attributes
|
||||
;
|
||||
variable_name_specifier:
|
||||
IDENTIFIER
|
||||
| IDENTIFIER BASED base_specifier
|
||||
;
|
||||
variable_name_specifier_list:
|
||||
variable_name_specifier
|
||||
| variable_name_specifier_list COMMA variable_name_specifier
|
||||
;
|
||||
/*
|
||||
* Variable references may be either data references or function
|
||||
* references. Syntactically, they appear to be the same, each
|
||||
* is followed by a parenthesized comma separated list of expressions.
|
||||
*
|
||||
* A function reference, of course, cannot have the trailing list of
|
||||
* member specifiers - semantic checking will catch this.
|
||||
*/
|
||||
variable_reference:
|
||||
IDENTIFIER
|
||||
| IDENTIFIER member_specifier_sequence
|
||||
| cast_type subscript
|
||||
| IDENTIFIER subscript_or_actual_parameters
|
||||
| IDENTIFIER subscript_or_actual_parameters member_specifier_sequence
|
||||
;
|
||||
variable_reference_list:
|
||||
variable_reference
|
||||
| variable_reference_list COMMA variable_reference
|
||||
;
|
||||
variable_type:
|
||||
basic_type
|
||||
| structure_type
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void
|
||||
yyerror(char * s)
|
||||
{
|
||||
fprintf (stderr, "error at line %d: %s\n", lineno, s);
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
init_scope();
|
||||
return yyparse();
|
||||
}
|
||||
151
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/scope.c
Normal file
151
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/scope.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/* literal symbol table for PL/M.
|
||||
|
||||
$Id: scope.c,v 1.1 1994/02/28 20:55:56 hays Exp $
|
||||
|
||||
Copyright 1994 by Kirk Hays (hays@ichips.intel.com)
|
||||
|
||||
USE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but without any warranty. Further, there is no implied warranty of
|
||||
merchantability or fitness for a particular purpose.
|
||||
|
||||
This code implements a scoped symbol table. It depends on Paul
|
||||
Vixie's PD AVL Tree code, distributed in comp.sources.unix, Volume 27,
|
||||
Issue 34.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "tree.h"
|
||||
#include "scope.h"
|
||||
|
||||
typedef struct lit_table_stack_t_elem {
|
||||
struct lit_table_stack_t_elem *next;
|
||||
tree * literal_table;
|
||||
} lit_table_stack_t;
|
||||
|
||||
/* innermost scope for scope list */
|
||||
static lit_table_stack_t *lit_table_stack;
|
||||
|
||||
typedef struct {
|
||||
char * identifier;
|
||||
char * string;
|
||||
} literal_t;
|
||||
|
||||
/* static forward references */
|
||||
static void new_scope (lit_table_stack_t *);
|
||||
static int literal_compar (literal_t *, literal_t *);
|
||||
static void literal_error (literal_t *);
|
||||
static void literal_t_delete (literal_t *);
|
||||
|
||||
/* lookup an identifier in the scoped symbol table */
|
||||
char *
|
||||
lookup_literal (char * identifier)
|
||||
{
|
||||
literal_t * datum;
|
||||
literal_t * node;
|
||||
lit_table_stack_t * scope;
|
||||
|
||||
node = alloca (sizeof (literal_t));
|
||||
node->identifier = identifier;
|
||||
|
||||
for (scope = lit_table_stack; scope; scope=scope->next)
|
||||
{
|
||||
datum = tree_srch(&(scope->literal_table), literal_compar, node);
|
||||
if (datum)
|
||||
{
|
||||
return datum->string;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* enter an identifier in the current scoping level */
|
||||
void
|
||||
enter_literal (char * identifier, char * string)
|
||||
{
|
||||
literal_t * datum;
|
||||
|
||||
datum = malloc (sizeof (literal_t));
|
||||
datum->identifier = identifier;
|
||||
datum->string = string;
|
||||
tree_add (&(lit_table_stack->literal_table),
|
||||
literal_compar,
|
||||
datum,
|
||||
literal_error);
|
||||
}
|
||||
|
||||
/* increase scope depth by one level - creates a new symbol table
|
||||
for the current scope */
|
||||
void
|
||||
push_scope (void)
|
||||
{
|
||||
new_scope (lit_table_stack);
|
||||
}
|
||||
|
||||
/* remove the innermost scope of the symbol table - releases all
|
||||
allocated storage for that scope */
|
||||
void
|
||||
pop_scope (void)
|
||||
{
|
||||
lit_table_stack_t * p;
|
||||
|
||||
p = lit_table_stack;
|
||||
lit_table_stack = lit_table_stack->next;
|
||||
tree_mung (&(p->literal_table), literal_t_delete);
|
||||
if (p->literal_table)
|
||||
{
|
||||
free(p->literal_table);
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
||||
/* initialize this module, creating the outermost scope */
|
||||
void
|
||||
init_scope (void)
|
||||
{
|
||||
new_scope (0);
|
||||
}
|
||||
|
||||
/* work procedure to create a new scope */
|
||||
static void
|
||||
new_scope (lit_table_stack_t * next)
|
||||
{
|
||||
lit_table_stack = malloc (sizeof (lit_table_stack_t));
|
||||
lit_table_stack->next = next;
|
||||
tree_init (&(lit_table_stack->literal_table));
|
||||
}
|
||||
|
||||
/* internal procedure to free storage when a symbol table entry is
|
||||
deleted */
|
||||
static
|
||||
void literal_t_delete (literal_t * datum)
|
||||
{
|
||||
free (datum->string);
|
||||
free (datum->identifier);
|
||||
}
|
||||
|
||||
/* internal procedure to determine the match order for two symbol
|
||||
table entries */
|
||||
|
||||
static int
|
||||
literal_compar (literal_t * left, literal_t * right)
|
||||
{
|
||||
return strcmp (left->identifier, right->identifier);
|
||||
}
|
||||
|
||||
/* assertion procedure to assure that duplicate literals are never
|
||||
added at a single scoping level */
|
||||
|
||||
static void
|
||||
literal_error (literal_t * in_error)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"literal table error - attempt to enter same identifier twice\n");
|
||||
exit (255);
|
||||
}
|
||||
|
||||
|
||||
22
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/scope.h
Normal file
22
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm/scope.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* public interfaces for literal symbol table for PL/M.
|
||||
|
||||
$Id: scope.h,v 1.1 1994/02/28 20:56:13 hays Exp $
|
||||
|
||||
Copyright 1994 by Kirk Hays (hays@ichips.intel.com)
|
||||
|
||||
USE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but without any warranty. Further, there is no implied warranty of
|
||||
merchantability or fitness for a particular purpose.
|
||||
|
||||
This code implements a scoped symbol table. It depends on Paul
|
||||
Vixie's PD AVL Tree code, distributed in comp.sources.unix, Volume 27,
|
||||
Issue 34.
|
||||
|
||||
*/
|
||||
|
||||
char * lookup_literal (char *);
|
||||
void enter_literal (char *, char *);
|
||||
void push_scope (void);
|
||||
void pop_scope (void);
|
||||
void init_scope (void);
|
||||
108
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/CAVEATS.DOC
Normal file
108
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/CAVEATS.DOC
Normal file
@@ -0,0 +1,108 @@
|
||||
Some notes about the PL/M to C converter:
|
||||
|
||||
With case conversion enabled by the "ifdef" in main.c, all upper case
|
||||
characters in an identifier are converted to lower case, and all lower case
|
||||
characters are converted to upper case except for identifiers declared
|
||||
LITERALLY, in which case the identifier is not case converted.
|
||||
|
||||
Dollar signs used in identifiers are discarded.
|
||||
|
||||
The use of the AND, OR and NOT operators are converted to &&, ||, and !
|
||||
operators respectively. This should work, but conversion to &, |, and ~
|
||||
may be desirable in many cases. There is no clear way to distinguish which
|
||||
conversion to use, thus the previous conversions were chosen. A #define
|
||||
in tokens.h allows either convention to be chosen. A more intelligent
|
||||
expression parser could do a better job of determining use of these operators.
|
||||
|
||||
Labels are limited in scope to that defined in C. That is, use of labels is
|
||||
limited to the current function. PL/M allows external labels.
|
||||
|
||||
The dot operator is treated the same as the @ operator (converted to a &
|
||||
reference).
|
||||
|
||||
Constant lists of the form:
|
||||
@('string', 0)
|
||||
are converted to:
|
||||
"string"
|
||||
|
||||
Constant lists of the form:
|
||||
@('string')
|
||||
are converted to:
|
||||
's', 't', 'r', 'i', 'n', 'g'
|
||||
|
||||
BYTE strings of the form:
|
||||
'string'
|
||||
are converted to:
|
||||
's', 't', 'r', 'i', 'n', 'g'
|
||||
|
||||
ADDRESSes and SELECTORs are not supported.
|
||||
|
||||
Variables declared AT in one module and EXTERNAL in another will produce
|
||||
incorrect results, as the EXTERNAL declared variable will not be treated
|
||||
as a pointer. For example, in module A:
|
||||
|
||||
PL/M code: C code:
|
||||
--------------------------------- ----------------------------------
|
||||
DECLARE MEMVAR BYTE AT(8000H); BYTE *memvar = (BYTE *) 0x8000;
|
||||
MEMVAR = 14H; (*memvar) = 0x14;
|
||||
|
||||
And in module B:
|
||||
|
||||
PL/M code: C code:
|
||||
--------------------------------- ----------------------------------
|
||||
DECLARE MEMVAR BYTE EXTERNAL; BYTE memvar;
|
||||
MEMVAR = 14H; memvar = 0x14;
|
||||
|
||||
To avoid this problem, list each AT variable used on a single line in a file
|
||||
called "at_decl.cvt".
|
||||
|
||||
Variable declarations within a procedure with the PUBLIC attribute *probably*
|
||||
should be placed prior to the procedure definition. Currently, the PUBLIC
|
||||
attribute is ignored.
|
||||
|
||||
Variable declarations of type POINTER are treated as type void.
|
||||
BASED variables are treated as a pointer to the based variable.
|
||||
For example, for the following declarations, the associated C code is
|
||||
generated:
|
||||
|
||||
PL/M code: C code:
|
||||
--------------------------------- ----------------------------------
|
||||
DECLARE I BYTE; BYTE i;
|
||||
DECLARE ITEM_PTR POINTER; void *item_ptr;
|
||||
DECLARE ITEM BASED ITEM_PTR BYTE; BYTE **item = (BYTE **) &item_ptr;
|
||||
ITEM_PTR = @I; item_ptr = &i;
|
||||
ITEM = 77H; (**item) = 0x77;
|
||||
|
||||
|
||||
Care should be taken in the use of LITERALLY declared variables. Such
|
||||
declarations are converted to a #define directive. With the cvt.h flag
|
||||
PARSE_LITERALS defined, the converter attempts to parse the contents of
|
||||
all LITERALLY declared variables as the definition for the #define
|
||||
directive. With PARSE_LITERALS undefined, no parsing takes place. Thus,
|
||||
for the declaration:
|
||||
DECLARE MAX_COUNT LITERALLY '55H';
|
||||
the code generated with PARSE_LITERALS defined is:
|
||||
#define MAX_COUNT 0x55
|
||||
and the code generated with PARSE_LITERALS undefined is:
|
||||
#define MAX_COUNT 55H
|
||||
|
||||
|
||||
Control directives within comments are ignored.
|
||||
|
||||
The procedure attribute REENTRANT is ignored. Technically, all PL/M variables
|
||||
are static and could be declared as such in all but REENTRANT procedures.
|
||||
This was not done, as it was deemed improbable that any problems would result.
|
||||
The user should keep this fact in mind though. Especially in cases where the
|
||||
C compiler warns about using a variable before it has been defined.
|
||||
|
||||
In most cases, white space (spaces, tabs, returns, line-feeds and comments)
|
||||
are retained in their appropriate place. In obscure instances, white space
|
||||
may be discarded for the sake of simpler code. For example, white space in
|
||||
some portions of a DECLARE statement is discarded, since the structure of
|
||||
a DECLARE statement is drastically converted.
|
||||
|
||||
Array subscripts and function calls appear to be ambiguous. The converter
|
||||
keeps a symbol table of DECLARATIONS to try to correctly distinguish one from
|
||||
the other.
|
||||
|
||||
|
||||
31
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/FILES
Normal file
31
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/FILES
Normal file
@@ -0,0 +1,31 @@
|
||||
README
|
||||
CAVEATS.DOC
|
||||
FILES
|
||||
at_decl.cvt
|
||||
const.c
|
||||
context.c
|
||||
control.c
|
||||
convert.c
|
||||
cvt.h
|
||||
cvt_id.h
|
||||
decl_out.c
|
||||
declare.c
|
||||
defs.h
|
||||
error.c
|
||||
io.c
|
||||
lit.c
|
||||
main.c
|
||||
makefile
|
||||
makefile.ibm
|
||||
mem.c
|
||||
misc.h
|
||||
parse.c
|
||||
struct.h
|
||||
test.c.out
|
||||
test.plm
|
||||
tkn_defs.h
|
||||
tkn_ext.h
|
||||
token.c
|
||||
tokens.h
|
||||
typedefs.c
|
||||
version.c
|
||||
37
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/README
Normal file
37
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/README
Normal file
@@ -0,0 +1,37 @@
|
||||
This is a PL/M to C converter. It will take most PL/M code and do a nice
|
||||
job of converting it to C. It tries to be intelligent about leaving formatting
|
||||
and comments intact. This version supports PL/M-286. It is something I wrote
|
||||
about a year ago to convert several meg of source code, and it did a 99.5%
|
||||
conversion. I was later handed some source code that it crashed on, and I
|
||||
extended it to support that code too.
|
||||
Please keep in mind that this may well not work for your code. It has
|
||||
been tested only on a few sets of code, each following its own set of coding
|
||||
standards. Also, don't expect a lot of support from me, as my interest in
|
||||
PL/M is next to none. I no longer work for the employer for whom I wrote
|
||||
this converter, but they have given me permission to own and post the sources.
|
||||
I will, time permitting, collect bug fixes and post patches to the software.
|
||||
Please mail fixes directly to me, as I may miss any posting of them. If
|
||||
anyone is interested in taking over maintenance of this code, please let me
|
||||
know!
|
||||
The source code compiles under Unix. I've compiled it on a Sun-4, a VAX
|
||||
running Ultrix, and a VAX running Mt. Xinu. At one time I had a version that
|
||||
ran under MSDOS, but I can't guarantee it will now. I've included a makefile
|
||||
for use with Turbo-C. You need to define IBMPC to compile it. What it could
|
||||
really use is tuning for a large memory model, as in it's present state, it
|
||||
can only handle small source files. It could also benefit from a good man
|
||||
page.
|
||||
The converter expects source code to be in "proper" format (i.e. proper
|
||||
use of EXTERNAL declarations, and following of the Intel PL/M grammar as the
|
||||
converter knows it.) It has some moderate error-recovery, but may well dump
|
||||
core if it expects one thing and gets another.
|
||||
I've included a garbage file test.plm; typeing "plm2c test.plm" should
|
||||
result in a test.c file that is identical to the provided test.c.out.
|
||||
See the file CAVEATS.DOC for compatibility issues.
|
||||
|
||||
Hope you find it useful!
|
||||
|
||||
Robert Ankeney
|
||||
April 9, 1991
|
||||
...!tektronix!bob@reed.bitnet
|
||||
|
||||
|
||||
27
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/const.c
Normal file
27
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/const.c
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
|
||||
foop(i, j)
|
||||
short i, j;
|
||||
{
|
||||
}
|
||||
|
||||
float foo()
|
||||
{
|
||||
}
|
||||
|
||||
WORD bletch;
|
||||
void *ptr;
|
||||
|
||||
farp("Hi\014\037\253\036");
|
||||
farp(&foo, &bar, &bletch);
|
||||
bletch = foo + foop(1, 2);
|
||||
bletch = foo + foop;
|
||||
ptr = (void *) &foo;
|
||||
ptr = (void *) &bar;
|
||||
ptr = (void *) &bletch;
|
||||
foo();
|
||||
bar();
|
||||
(*ptr)();
|
||||
(*bletch)();
|
||||
(*ptr)(1, 2);
|
||||
|
||||
154
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/context.c
Normal file
154
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/context.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
|
||||
/*
|
||||
* Pointer to the current context
|
||||
*/
|
||||
CONTEXT *context_head;
|
||||
/*
|
||||
* Pointer to all popped contexts
|
||||
*/
|
||||
CONTEXT *old_context;
|
||||
|
||||
/*
|
||||
* Search DECL_MEMBER list for symbol and if found, return TRUE
|
||||
* and pointer to DECL_ID for that symbol.
|
||||
*/
|
||||
find_member_symbol(symbol, decl_ptr, decl_id)
|
||||
TOKEN *symbol;
|
||||
DECL_MEMBER *decl_ptr;
|
||||
DECL_ID **decl_id;
|
||||
{
|
||||
DECL_ID *var_ptr;
|
||||
|
||||
for (var_ptr = decl_ptr->name_list; var_ptr;
|
||||
var_ptr = var_ptr->next_var) {
|
||||
if (!strcmp(var_ptr->name->token_name, symbol->token_name)) {
|
||||
*decl_id = var_ptr;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
*decl_id = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search DECL_MEMBER list for symbol.
|
||||
* If found, return pointer to DECL_MEMBER containing that symbol
|
||||
* in decl_found, and return TRUE.
|
||||
* If not found, return null pointer in decl_found, and return FALSE.
|
||||
*/
|
||||
find_list_symbol(symbol, decl_ptr, decl_found, decl_id)
|
||||
TOKEN *symbol;
|
||||
DECL_MEMBER *decl_ptr, **decl_found;
|
||||
DECL_ID **decl_id;
|
||||
{
|
||||
for (*decl_found = decl_ptr; *decl_found;
|
||||
*decl_found = (*decl_found)->next_member) {
|
||||
if (find_member_symbol(symbol, *decl_found, decl_id))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search context for symbol.
|
||||
* If found, return pointer to DECL_MEMBER containing that symbol
|
||||
* in decl_found, return DECL_ID for that symbol in decl_id, and
|
||||
* return TRUE.
|
||||
* If not found, return null pointers in decl_found and decl_id,
|
||||
* and return FALSE.
|
||||
*/
|
||||
find_symbol(symbol, decl_found, decl_id)
|
||||
TOKEN *symbol;
|
||||
DECL_MEMBER **decl_found;
|
||||
DECL_ID **decl_id;
|
||||
{
|
||||
CONTEXT *context_ptr;
|
||||
|
||||
for (context_ptr = context_head; context_ptr;
|
||||
context_ptr = context_ptr->next_context) {
|
||||
if (find_list_symbol(symbol, context_ptr->decl_head,
|
||||
decl_found, decl_id))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a declaration to current context
|
||||
*/
|
||||
add_to_context(decl)
|
||||
DECL_MEMBER *decl;
|
||||
{
|
||||
DECL_MEMBER *decl_ptr;
|
||||
|
||||
/* Find end of declaration list */
|
||||
for (decl_ptr = decl; decl_ptr->next_member; )
|
||||
decl_ptr = decl_ptr->next_member;
|
||||
|
||||
/* Add current declarations to tail of new list */
|
||||
decl_ptr->next_member = context_head->decl_head;
|
||||
context_head->decl_head = decl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a DECL list to context and NULL the list pointer
|
||||
*/
|
||||
add_decl_to_context(decl)
|
||||
DECL *decl;
|
||||
{
|
||||
DECL *decl_ptr;
|
||||
|
||||
/* Find end of declaration list */
|
||||
for (decl_ptr = decl; decl_ptr; decl_ptr = decl_ptr->next_decl) {
|
||||
if (decl_ptr->decl_list)
|
||||
add_to_context(decl_ptr->decl_list);
|
||||
decl_ptr->decl_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a new context of specified type and name
|
||||
*/
|
||||
new_context(type, name)
|
||||
int type;
|
||||
TOKEN *name;
|
||||
{
|
||||
CONTEXT *new_context;
|
||||
|
||||
get_context_ptr(&new_context);
|
||||
new_context->context_type = type;
|
||||
if (name) {
|
||||
get_token_ptr(&new_context->context_name);
|
||||
token_copy(name, new_context->context_name);
|
||||
} else
|
||||
new_context->context_name = NULL;
|
||||
new_context->next_context = context_head;
|
||||
context_head = new_context;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pop current context and place on old context
|
||||
*/
|
||||
pop_context()
|
||||
{
|
||||
CONTEXT *popped_context;
|
||||
|
||||
popped_context = context_head;
|
||||
context_head = popped_context->next_context;
|
||||
popped_context->next_context = old_context;
|
||||
old_context = popped_context;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes context pointers
|
||||
*/
|
||||
init_context()
|
||||
{
|
||||
context_head = NULL;
|
||||
old_context = NULL;
|
||||
}
|
||||
|
||||
89
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/control.c
Normal file
89
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/control.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
#include "tkn_ext.h"
|
||||
|
||||
extern char *text_buffer;
|
||||
extern char *text_ptr;
|
||||
|
||||
/*
|
||||
* Parse a control directive.
|
||||
* Handles: Abbreviation:
|
||||
* $INCLUDE $IC
|
||||
* $SET
|
||||
* $RESET
|
||||
* $IF
|
||||
* $ELSE
|
||||
* $ELSEIF
|
||||
* $ENDIF
|
||||
*/
|
||||
parse_control()
|
||||
{
|
||||
TOKEN ctl_token, token;
|
||||
int token_class;
|
||||
RESERVED_WORD *word_ptr;
|
||||
char include_file[128], *include_ptr;
|
||||
|
||||
token_class = get_token(&ctl_token);
|
||||
if (token_class != IDENTIFIER) {
|
||||
control_error("Invalid directive");
|
||||
return;
|
||||
}
|
||||
|
||||
for (word_ptr = &control_directives[0]; word_ptr->token != END_OF_FILE;
|
||||
word_ptr++) {
|
||||
if ((strlen(word_ptr->name) == ctl_token.token_length) &&
|
||||
!strncmp(word_ptr->name, ctl_token.token_start,
|
||||
ctl_token.token_length)) {
|
||||
switch (word_ptr->token) {
|
||||
|
||||
case C_INCLUDE :
|
||||
token_class = get_token(&token);
|
||||
if (token_class != LEFT_PAREN) {
|
||||
control_error("'(' expected");
|
||||
return;
|
||||
}
|
||||
/* Copy and send file name (up to ')') */
|
||||
include_ptr = include_file;
|
||||
while (*text_ptr != ')') {
|
||||
if ((*text_ptr >= 'A') && (*text_ptr <= 'Z'))
|
||||
/* Convert to lower case */
|
||||
*include_ptr++ = *text_ptr++ + ' ';
|
||||
else
|
||||
*include_ptr++ = *text_ptr++;
|
||||
}
|
||||
*include_ptr++ = '\0';
|
||||
|
||||
/* Skip ')' */
|
||||
text_ptr++;
|
||||
|
||||
/* Parse include file */
|
||||
cvt_file(include_file);
|
||||
|
||||
/* Convert .plm to .c */
|
||||
if (strcmp(include_ptr - 5, "plm")) {
|
||||
(void) strcpy(include_ptr - 5, ".c");
|
||||
include_ptr -= 2;
|
||||
}
|
||||
|
||||
out_to_start();
|
||||
out_str("#include");
|
||||
out_must_white(&token);
|
||||
out_char('"');
|
||||
out_str(include_file);
|
||||
|
||||
out_char('"');
|
||||
return;
|
||||
|
||||
default :
|
||||
control_error("Non-supported directive");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
control_error("Invalid directive");
|
||||
}
|
||||
|
||||
145
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/convert.c
Normal file
145
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/convert.c
Normal file
@@ -0,0 +1,145 @@
|
||||
#include <stdio.h>
|
||||
#ifdef IBMPC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
|
||||
BOOLEAN syntax_error;
|
||||
|
||||
extern char *text_buffer, *text_ptr;
|
||||
extern int line_count;
|
||||
|
||||
/*
|
||||
* Determine statement type and call appropriate parse routine.
|
||||
* Return statement class or, if a reserved word, reserved word token.
|
||||
*/
|
||||
parse_statement(first_token)
|
||||
TOKEN *first_token;
|
||||
{
|
||||
int token_type;
|
||||
|
||||
/* Flush standard output and standard error */
|
||||
(void) fflush(stdout);
|
||||
(void) fflush(stderr);
|
||||
|
||||
/* Flag no error yet */
|
||||
syntax_error = FALSE;
|
||||
|
||||
switch (first_token->token_class) {
|
||||
|
||||
case RESERVED:
|
||||
token_type = first_token->token_type;
|
||||
|
||||
switch (token_type) {
|
||||
|
||||
case DECLARE :
|
||||
parse_declare(first_token);
|
||||
break;
|
||||
|
||||
case DO :
|
||||
parse_do(first_token);
|
||||
break;
|
||||
|
||||
case IF :
|
||||
parse_if(first_token);
|
||||
break;
|
||||
|
||||
case THEN :
|
||||
parse_then();
|
||||
break;
|
||||
|
||||
case ELSE :
|
||||
parse_else(first_token);
|
||||
break;
|
||||
|
||||
case GOTO :
|
||||
parse_goto(first_token);
|
||||
break;
|
||||
|
||||
case GO :
|
||||
parse_go(first_token);
|
||||
break;
|
||||
|
||||
case CALL :
|
||||
parse_call(first_token);
|
||||
break;
|
||||
|
||||
case RETURN :
|
||||
parse_return(first_token);
|
||||
break;
|
||||
|
||||
case END :
|
||||
parse_end(first_token);
|
||||
break;
|
||||
|
||||
case DISABLE :
|
||||
parse_int_ctl(first_token);
|
||||
break;
|
||||
|
||||
case ENABLE :
|
||||
parse_int_ctl(first_token);
|
||||
break;
|
||||
|
||||
case OUTPUT :
|
||||
parse_output(first_token);
|
||||
break;
|
||||
|
||||
case OUTWORD :
|
||||
parse_outword(first_token);
|
||||
break;
|
||||
|
||||
case OUTHWORD :
|
||||
parse_outhword(first_token);
|
||||
break;
|
||||
|
||||
default :
|
||||
parse_error("Illegal reserved word");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return token_type;
|
||||
|
||||
case IDENTIFIER:
|
||||
parse_identifier(first_token);
|
||||
break;
|
||||
|
||||
case LABEL:
|
||||
parse_label();
|
||||
break;
|
||||
|
||||
case END_OF_LINE:
|
||||
parse_eol(first_token);
|
||||
break;
|
||||
|
||||
case END_OF_FILE:
|
||||
out_white_space(first_token);
|
||||
return END_OF_FILE;
|
||||
|
||||
default:
|
||||
parse_error("Illegal statement");
|
||||
return ERROR;
|
||||
|
||||
}
|
||||
|
||||
return first_token->token_class;
|
||||
}
|
||||
|
||||
parse_new_statement()
|
||||
{
|
||||
TOKEN first_token;
|
||||
|
||||
/* Get first token on line */
|
||||
(void) get_token(&first_token);
|
||||
|
||||
return parse_statement(&first_token);
|
||||
}
|
||||
|
||||
parse_file()
|
||||
{
|
||||
while (parse_new_statement() != END_OF_FILE) ;
|
||||
}
|
||||
|
||||
82
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/cvt.h
Normal file
82
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/cvt.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Parse LITERALLY declared strings
|
||||
*/
|
||||
#define PARSE_LITERALS
|
||||
|
||||
/*
|
||||
* Ignore Invalid control errors
|
||||
*/
|
||||
#define IGNORE_CONTROL_ERRORS
|
||||
|
||||
/*
|
||||
* Convert lower case to upper and upper to lower in identifiers
|
||||
*/
|
||||
#define CONVERT_CASE
|
||||
|
||||
/*
|
||||
* If CONVERT_TYPES defined, use the following type conversions.
|
||||
*/
|
||||
#define CONVERT_TYPES
|
||||
|
||||
/*
|
||||
* Type conversions
|
||||
*/
|
||||
#define TYPE_BYTE "BYTE"
|
||||
#define TYPE_WORD "WORD"
|
||||
#define TYPE_DWORD "DWORD"
|
||||
#define TYPE_INTEGER "short"
|
||||
#define TYPE_REAL "float"
|
||||
|
||||
/*
|
||||
* For initialized DATA, use this prefix.
|
||||
* Probably should be "const" or "static".
|
||||
*/
|
||||
#define TYPE_DATA "const"
|
||||
|
||||
/*
|
||||
* Default POINTER type.
|
||||
*/
|
||||
#define TYPE_POINTER "void"
|
||||
|
||||
/*
|
||||
* Sizes of data types
|
||||
*/
|
||||
#define SIZE_BYTE 1
|
||||
#define SIZE_WORD 2
|
||||
#define SIZE_DWORD 4
|
||||
|
||||
/*
|
||||
* Conversion operators
|
||||
*/
|
||||
#define AND_OP "&&"
|
||||
#define OR_OP "||"
|
||||
#define NOT_OP "!"
|
||||
/*
|
||||
#define AND_OP "&"
|
||||
#define OR_OP "|"
|
||||
#define NOT_OP "~"
|
||||
*/
|
||||
/*
|
||||
#define AND_OP "AND"
|
||||
#define OR_OP "OR"
|
||||
#define NOT_OP "NOT"
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function call equivalent to OUTPUT(port) = expr
|
||||
* Becomes: FUNC_OUTPUT(port, expr)
|
||||
*/
|
||||
#define FUNC_OUTPUT "outportb"
|
||||
|
||||
/*
|
||||
* Function call equivalent to OUTWORD(port) = expr
|
||||
* Becomes: FUNC_OUTWORD(port, expr)
|
||||
*/
|
||||
#define FUNC_OUTWORD "outport"
|
||||
|
||||
/*
|
||||
* Function call equivalent to OUTHWORD(port) = expr
|
||||
* Becomes: FUNC_OUTHWORD(port, expr)
|
||||
*/
|
||||
#define FUNC_OUTHWORD "outporth"
|
||||
|
||||
40
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/cvt_id.h
Normal file
40
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/cvt_id.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* PL/M Cast function equivalents
|
||||
*/
|
||||
CVT_ID cast_functions[] = {
|
||||
"float", TYPE_REAL,
|
||||
"real", TYPE_REAL,
|
||||
"fix", TYPE_INTEGER,
|
||||
"int", TYPE_INTEGER,
|
||||
"signed", TYPE_INTEGER,
|
||||
"integer", TYPE_INTEGER,
|
||||
"unsign", TYPE_WORD,
|
||||
"word", TYPE_WORD,
|
||||
"byte", TYPE_BYTE,
|
||||
"dword", TYPE_DWORD,
|
||||
"pointer", TYPE_POINTER,
|
||||
"", ""
|
||||
};
|
||||
|
||||
/*
|
||||
* PL/M function equivalents
|
||||
*/
|
||||
CVT_ID cvt_functions[] = {
|
||||
"size", "sizeof",
|
||||
"abs", "fabs",
|
||||
"iabs", "abs",
|
||||
"input", "inportb",
|
||||
"inword", "inport",
|
||||
"setinterrupt", "signal",
|
||||
"initrealmathunit", "_fpreset",
|
||||
"", ""
|
||||
};
|
||||
|
||||
/*
|
||||
* PL/M identifier equivalents
|
||||
*/
|
||||
CVT_ID cvt_identifiers[] = {
|
||||
"getrealerror", "_status87()",
|
||||
"", ""
|
||||
};
|
||||
|
||||
408
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/decl_out.c
Normal file
408
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/decl_out.c
Normal file
@@ -0,0 +1,408 @@
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
|
||||
extern char *text_ptr;
|
||||
extern int at_decl_count;
|
||||
extern char at_decl_list[MAX_AT_DECLS][MAX_TOKEN_LENGTH];
|
||||
|
||||
/*
|
||||
* Output *<name> if use_parens == NULL, else (*<name>).
|
||||
*/
|
||||
out_pointer(name, use_parens)
|
||||
TOKEN *name;
|
||||
BOOLEAN use_parens;
|
||||
{
|
||||
/* Use parentheses? */
|
||||
if (use_parens) {
|
||||
/* Yes - make it (*name) */
|
||||
out_str("(*");
|
||||
out_token_name(name);
|
||||
out_char(')');
|
||||
} else {
|
||||
/* No - make it *name */
|
||||
out_char('*');
|
||||
out_token_name(name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output array bound (if any)
|
||||
*/
|
||||
out_bound(bound)
|
||||
TOKEN *bound;
|
||||
{
|
||||
if (bound) {
|
||||
out_char('[');
|
||||
out_token(bound);
|
||||
out_char(']');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a declaration type.
|
||||
*/
|
||||
out_decl_type(decl_ptr)
|
||||
DECL_MEMBER *decl_ptr;
|
||||
{
|
||||
if (decl_ptr->type->token_type != STRUCTURE) {
|
||||
out_type(decl_ptr->type->token_type);
|
||||
} else {
|
||||
out_struct(decl_ptr->struct_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output structure contents.
|
||||
*/
|
||||
out_struct(el_ptr)
|
||||
DECL_MEMBER *el_ptr;
|
||||
{
|
||||
DECL_ID *var_ptr;
|
||||
|
||||
out_str("struct {");
|
||||
|
||||
while (el_ptr) {
|
||||
/* Use initial white space before type */
|
||||
var_ptr = el_ptr->name_list;
|
||||
if (var_ptr)
|
||||
out_must_white(var_ptr->name);
|
||||
|
||||
out_decl_type(el_ptr);
|
||||
out_char(' ');
|
||||
|
||||
while (var_ptr) {
|
||||
out_token_name(var_ptr->name);
|
||||
out_bound(el_ptr->array_bound);
|
||||
var_ptr = var_ptr->next_var;
|
||||
if (var_ptr) {
|
||||
out_char(',');
|
||||
out_must_white(var_ptr->name);
|
||||
}
|
||||
}
|
||||
if ((el_ptr = el_ptr->next_member) != NULL)
|
||||
out_char(';');
|
||||
}
|
||||
out_char('}');
|
||||
}
|
||||
|
||||
/*
|
||||
* Output C declaration list member.
|
||||
*/
|
||||
out_decl_member(decl_list, decl_token)
|
||||
DECL_MEMBER *decl_list;
|
||||
TOKEN *decl_token;
|
||||
{
|
||||
int i;
|
||||
TOKEN token, tmp_token;
|
||||
int token_class;
|
||||
int name_count;
|
||||
char count_str[8];
|
||||
DECL_ID *var_ptr;
|
||||
char *tmp_white_start, *tmp_white_end;
|
||||
char *tmp_text_ptr;
|
||||
BOOLEAN typedefed, is_at;
|
||||
int string_len, string_size;
|
||||
char *string_ptr;
|
||||
|
||||
/* Output characters up to CR */
|
||||
out_pre_white(decl_token);
|
||||
|
||||
if (decl_list->type->token_type == LABEL)
|
||||
/* Ignore label declarations */
|
||||
return;
|
||||
|
||||
var_ptr = decl_list->name_list;
|
||||
|
||||
if (decl_list->type->token_type == LITERALLY) {
|
||||
/* Make sure we're at start of new line */
|
||||
out_pre_white(var_ptr->name);
|
||||
out_to_start();
|
||||
|
||||
/* Convert to a #define */
|
||||
out_str("#define ");
|
||||
out_cvt_name(var_ptr->name);
|
||||
out_char(' ');
|
||||
out_str(decl_list->literal);
|
||||
/*
|
||||
out_str("\n");
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
var_ptr->name->white_space_start = decl_token->white_space_start;
|
||||
var_ptr->name->white_space_end = decl_token->white_space_end;
|
||||
|
||||
/* Swap white space between type and first identifier */
|
||||
/* and eat any new_lines prior to first identifier */
|
||||
tmp_white_start = decl_list->type->white_space_start;
|
||||
tmp_white_end = decl_list->type->white_space_end;
|
||||
|
||||
while ((tmp_white_start < tmp_white_end) && (*tmp_white_start < ' '))
|
||||
tmp_white_start++;
|
||||
|
||||
decl_list->type->white_space_start = var_ptr->name->white_space_start;
|
||||
var_ptr->name->white_space_start = tmp_white_start;
|
||||
decl_list->type->white_space_end = var_ptr->name->white_space_end;
|
||||
var_ptr->name->white_space_end = tmp_white_end;
|
||||
|
||||
out_white_space(decl_list->type);
|
||||
|
||||
if (decl_list->attributes == EXTERNAL) {
|
||||
out_str("extern ");
|
||||
|
||||
/* Check if declared AT in another module */
|
||||
for (i = 0; i < at_decl_count; i++)
|
||||
if (!strcmp(var_ptr->name->token_name, at_decl_list[i]))
|
||||
/* Yes - flag as so */
|
||||
var_ptr->is_ext_at = TRUE;
|
||||
} else
|
||||
|
||||
if (decl_list->initialization == DATA) {
|
||||
out_str(TYPE_DATA);
|
||||
out_char(' ');
|
||||
}
|
||||
|
||||
|
||||
is_at = (decl_list->at_ptr != NULL) || var_ptr->is_ext_at;
|
||||
|
||||
/* Determine if a structure with an AT attribute */
|
||||
typedefed = (decl_list->type->token_type == STRUCTURE) && is_at;
|
||||
|
||||
/* Output type */
|
||||
/* Is this a structure with an AT attribute? */
|
||||
if (typedefed) {
|
||||
/* Yes - output typedefed structure */
|
||||
out_str("typedef ");
|
||||
out_struct(decl_list->struct_list);
|
||||
out_must_white(var_ptr->name);
|
||||
#ifdef USE_DEFINES
|
||||
out_char('_');
|
||||
#endif
|
||||
out_cvt_name(var_ptr->name);
|
||||
if (decl_list->array_bound)
|
||||
out_bound(decl_list->array_bound);
|
||||
out_str(";\n");
|
||||
out_white_space(decl_token);
|
||||
#ifdef USE_DEFINES
|
||||
out_char('_');
|
||||
#endif
|
||||
out_cvt_name(var_ptr->name);
|
||||
} else
|
||||
out_decl_type(decl_list);
|
||||
|
||||
/* Walk through name list */
|
||||
name_count = 0;
|
||||
while (var_ptr) {
|
||||
if (is_at) {
|
||||
/* AT (<expression>) -
|
||||
OK... don't panic...
|
||||
we can handle this
|
||||
*/
|
||||
/*
|
||||
* Output:
|
||||
* <type> *<ident> = (<type> *) <AT expr> + name_count
|
||||
*
|
||||
* NOTE: BASED variables are not dealt with.
|
||||
*/
|
||||
out_must_white(var_ptr->name);
|
||||
/* Is this an array? */
|
||||
if ((decl_list->array_bound) && !typedefed)
|
||||
/* Yes - output ( *<ident> ) */
|
||||
out_char('(');
|
||||
out_char('*');
|
||||
#ifdef USE_DEFINES
|
||||
/* Output case converted name */
|
||||
out_cvt_name(var_ptr->name);
|
||||
#else
|
||||
out_token_name(var_ptr->name);
|
||||
#endif
|
||||
if ((decl_list->array_bound) && !typedefed) {
|
||||
out_char(')');
|
||||
/* Output array bound (if any) */
|
||||
out_bound(decl_list->array_bound);
|
||||
}
|
||||
|
||||
if (decl_list->attributes != EXTERNAL) {
|
||||
out_str(" = (");
|
||||
/* Is this a structure? */
|
||||
if (decl_list->type->token_type == STRUCTURE) {
|
||||
/* Yes - output structure name prefix */
|
||||
#ifdef USE_DEFINES
|
||||
out_char('_');
|
||||
#endif
|
||||
out_cvt_name(decl_list->name_list->name);
|
||||
} else
|
||||
out_decl_type(decl_list);
|
||||
out_str(" *) ");
|
||||
|
||||
out_str(decl_list->at_ptr);
|
||||
if (name_count) {
|
||||
(void) sprintf(count_str, " + %d", name_count);
|
||||
out_str(count_str);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Not an AT expression (whew!) */
|
||||
out_must_white(var_ptr->name);
|
||||
|
||||
/* Is variable based? */
|
||||
if (var_ptr->based_name) {
|
||||
/* Yes - Output **name = */
|
||||
/* (type **) &based_name */
|
||||
if (decl_list->array_bound) {
|
||||
/* Use (**name)[] */
|
||||
out_str("(**");
|
||||
out_token_name(var_ptr->name);
|
||||
out_str(")[]");
|
||||
} else {
|
||||
out_str("**");
|
||||
out_token_name(var_ptr->name);
|
||||
}
|
||||
|
||||
out_str(" = (");
|
||||
out_decl_type(decl_list);
|
||||
out_str(" **) &");
|
||||
out_token_name(var_ptr->based_name);
|
||||
} else
|
||||
|
||||
if (decl_list->type->token_type == POINTER) {
|
||||
/* Yes - if based on an array */
|
||||
/* output (*name) else output *name */
|
||||
out_pointer(var_ptr->name,
|
||||
(BOOLEAN) decl_list->array_bound);
|
||||
} else {
|
||||
/* Output variable name */
|
||||
out_token_name(var_ptr->name);
|
||||
|
||||
/* Output array bound (if any) */
|
||||
out_bound(decl_list->array_bound);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get next name */
|
||||
if ((var_ptr = var_ptr->next_var) != NULL) {
|
||||
out_char(',');
|
||||
name_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for INITIAL or DATA initializers */
|
||||
if (decl_list->initialization != NONE) {
|
||||
out_str(" = ");
|
||||
/* Point back to initializer string */
|
||||
tmp_text_ptr = text_ptr;
|
||||
text_ptr = decl_list->init_ptr;
|
||||
if (decl_list->array_bound) {
|
||||
out_char('{');
|
||||
/* Array - determine if just a single string */
|
||||
switch (decl_list->type->token_type) {
|
||||
|
||||
case BYTE :
|
||||
string_size = SIZE_BYTE;
|
||||
break;
|
||||
|
||||
case WORD :
|
||||
string_size = SIZE_WORD;
|
||||
break;
|
||||
|
||||
case DWORD :
|
||||
string_size = SIZE_DWORD;
|
||||
break;
|
||||
|
||||
case STRUCTURE :
|
||||
/*
|
||||
* Oh, SH-T!! fake it!
|
||||
*/
|
||||
string_size = SIZE_BYTE;
|
||||
break;
|
||||
|
||||
default :
|
||||
string_size = 0;
|
||||
}
|
||||
|
||||
if (string_size && (get_token(&token) == STRING) &&
|
||||
(get_token(&tmp_token) == RIGHT_PAREN)) {
|
||||
/* Single string - break up into */
|
||||
/* Pieces of sizeof(<type>) size */
|
||||
string_ptr = token.token_name;
|
||||
string_len = token.token_length;
|
||||
while (string_len) {
|
||||
out_str_const(string_ptr, string_size);
|
||||
if (string_size > string_len)
|
||||
string_size = string_len;
|
||||
string_ptr += string_size;
|
||||
if (string_len -= string_size)
|
||||
out_char(',');
|
||||
}
|
||||
} else {
|
||||
/* Point back to init string */
|
||||
text_ptr = decl_list->init_ptr;
|
||||
do {
|
||||
token_class = parse_expression(&token);
|
||||
if (token_class == COMMA)
|
||||
out_token(&token);
|
||||
} while (token_class == COMMA);
|
||||
}
|
||||
|
||||
out_char('}');
|
||||
/* Point past init string */
|
||||
text_ptr = token.token_start + token.token_length + 2;
|
||||
token_class = get_token(&token);
|
||||
} else {
|
||||
token_class = parse_expression(&token);
|
||||
}
|
||||
if (token_class != RIGHT_PAREN)
|
||||
parse_error("')' expected");
|
||||
text_ptr = tmp_text_ptr;
|
||||
}
|
||||
|
||||
out_char(';');
|
||||
|
||||
#ifdef USE_DEFINES
|
||||
/* Walk through name list and check for BASED variables */
|
||||
var_ptr = decl_list->name_list;
|
||||
while (var_ptr) {
|
||||
/* See if variable is BASED */
|
||||
if (var_ptr->based_name) {
|
||||
/* Make sure we're at start of new line */
|
||||
out_to_start();
|
||||
out_str("#define");
|
||||
out_must_token(var_ptr->based_name);
|
||||
out_white_space(var_ptr->name);
|
||||
out_str("(*");
|
||||
out_token_name(var_ptr->name);
|
||||
out_str(")\n");
|
||||
}
|
||||
|
||||
/* See if variable is AT */
|
||||
if (is_at) {
|
||||
/* Make sure we're at start of new line */
|
||||
out_to_start();
|
||||
out_str("#define");
|
||||
out_must_token(var_ptr->name);
|
||||
out_white_space(var_ptr->name);
|
||||
out_str("(*");
|
||||
out_cvt_name(var_ptr->name);
|
||||
out_str(")\n");
|
||||
}
|
||||
|
||||
var_ptr = var_ptr->next_var;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
out_decl(decl)
|
||||
DECL *decl;
|
||||
{
|
||||
DECL_MEMBER *decl_list;
|
||||
|
||||
while (decl) {
|
||||
for (decl_list = decl->decl_list; decl_list;
|
||||
decl_list = decl_list->next_member)
|
||||
out_decl_member(decl_list, decl->decl_token);
|
||||
decl = decl->next_decl;
|
||||
}
|
||||
}
|
||||
506
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/declare.c
Normal file
506
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/declare.c
Normal file
@@ -0,0 +1,506 @@
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
|
||||
extern char *text_ptr;
|
||||
extern char *out_string;
|
||||
|
||||
/*
|
||||
* Routines to process DECLARE statements.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Skip to closing right parenthesis
|
||||
*/
|
||||
find_right_paren()
|
||||
{
|
||||
TOKEN token;
|
||||
int token_class;
|
||||
int paren_count;
|
||||
|
||||
paren_count = 1;
|
||||
do {
|
||||
token_class = get_token(&token);
|
||||
if (token_class == LEFT_PAREN)
|
||||
paren_count++;
|
||||
else
|
||||
if (token_class == RIGHT_PAREN)
|
||||
paren_count--;
|
||||
} while (paren_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy an element from source to destination
|
||||
*/
|
||||
element_copy(src, dest)
|
||||
DECL_MEMBER *src, *dest;
|
||||
{
|
||||
/* Don't copy name list */
|
||||
dest->name_list = NULL;
|
||||
/* Don't copy link */
|
||||
dest->next_member = NULL;
|
||||
dest->literal = src->literal;
|
||||
dest->array_bound = src->array_bound;
|
||||
dest->type = src->type;
|
||||
dest->attributes = src->attributes;
|
||||
dest->initialization = src->initialization;
|
||||
dest->at_ptr = src->at_ptr;
|
||||
dest->init_ptr = src->init_ptr;
|
||||
if (src->struct_list)
|
||||
element_copy(src->struct_list, dest->struct_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a linked list of variables of the form:
|
||||
* <id> [BASED <id>[.<id>]] or
|
||||
* ( <id> [BASED <id>[.<id>]] [ ,<id> [BASED <id>[.<id>]] ] ... )
|
||||
* Return token following variable list.
|
||||
*/
|
||||
get_var_list(list_ptr, sep_token)
|
||||
DECL_ID **list_ptr;
|
||||
TOKEN *sep_token;
|
||||
{
|
||||
DECL_ID *var_ptr, *last_var;
|
||||
TOKEN *token;
|
||||
int token_class;
|
||||
BOOLEAN multi_list;
|
||||
char *par_white_start, *par_white_end;
|
||||
|
||||
*list_ptr = NULL;
|
||||
/* Get first token */
|
||||
get_token_ptr(&token);
|
||||
token_class = get_token(token);
|
||||
|
||||
/* Determine if <var> or list of ( <var> [,<var>] ... ) */
|
||||
if (token_class == LEFT_PAREN) {
|
||||
/* List of ( <var> [,<var>] ... ) */
|
||||
multi_list = TRUE;
|
||||
|
||||
/* Use white space before '(' for first identifier */
|
||||
par_white_start = token->white_space_start;
|
||||
par_white_end = token->white_space_end;
|
||||
|
||||
/* Get first identifier */
|
||||
token_class = get_token(token);
|
||||
token->white_space_start = par_white_start;
|
||||
token->white_space_end = par_white_end;
|
||||
} else
|
||||
/* <var> */
|
||||
multi_list = FALSE;
|
||||
|
||||
/* Process identifier list */
|
||||
last_var = NULL;
|
||||
while (1) {
|
||||
if (token_class != IDENTIFIER) {
|
||||
parse_error("Identifier expected");
|
||||
free_var_list(*list_ptr);
|
||||
free((char *) token);
|
||||
*list_ptr = NULL;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get a variable structure */
|
||||
get_var_ptr(&var_ptr);
|
||||
|
||||
if (*list_ptr == NULL)
|
||||
/* Point to first variable */
|
||||
*list_ptr = var_ptr;
|
||||
|
||||
if (last_var)
|
||||
last_var->next_var = var_ptr;
|
||||
last_var = var_ptr;
|
||||
|
||||
/* Save variable name */
|
||||
var_ptr->name = token;
|
||||
|
||||
/* Check for BASED */
|
||||
token_class = get_token(sep_token);
|
||||
|
||||
if ((token_class == RESERVED) &&
|
||||
(sep_token->token_type == BASED)) {
|
||||
/* BASED <id>[ .<id> ] */
|
||||
/* Get based name */
|
||||
get_token_ptr(&token);
|
||||
token_class = get_token(token);
|
||||
if (token_class != IDENTIFIER) {
|
||||
parse_error("Identifier expected");
|
||||
free_var_list(*list_ptr);
|
||||
free((char *) token);
|
||||
*list_ptr = NULL;
|
||||
return ERROR;
|
||||
}
|
||||
token_class = parse_simple_variable(token, sep_token);
|
||||
|
||||
#ifdef USE_DEFINES
|
||||
/* Swap variable name with based name */
|
||||
var_ptr->based_name = var_ptr->name;
|
||||
var_ptr->name = token;
|
||||
#else
|
||||
var_ptr->based_name = token;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!multi_list)
|
||||
return token_class;
|
||||
|
||||
if (token_class != COMMA)
|
||||
break;
|
||||
|
||||
/* Get next variable */
|
||||
get_token_ptr(&token);
|
||||
token_class = get_token(token);
|
||||
}
|
||||
|
||||
if (token_class == RIGHT_PAREN) {
|
||||
/* Get next token */
|
||||
token_class = get_token(sep_token);
|
||||
return token_class;
|
||||
} else {
|
||||
parse_error("')' expected");
|
||||
free_var_list(*list_ptr);
|
||||
*list_ptr = NULL;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a structure declaration of the form:
|
||||
* STRUCTURE ( <member> [ ,<member> ] ... )
|
||||
* where:
|
||||
* <member> ::= { <id> | ( <id> [ ,<id> ] ... ) } [ ( <numeric> ) ] <type>
|
||||
*/
|
||||
parse_structure(list_ptr)
|
||||
DECL_MEMBER **list_ptr;
|
||||
{
|
||||
DECL_MEMBER *struct_ptr, *last_struct;
|
||||
TOKEN token;
|
||||
int token_class;
|
||||
|
||||
*list_ptr = NULL;
|
||||
|
||||
/* Get left paren */
|
||||
token_class = get_token(&token);
|
||||
if (token_class != LEFT_PAREN) {
|
||||
parse_error("'(' expected");
|
||||
return;
|
||||
}
|
||||
|
||||
last_struct = NULL;
|
||||
do {
|
||||
/* Get a DECL_MEMBER structure */
|
||||
get_element_ptr(&struct_ptr);
|
||||
|
||||
if (*list_ptr == NULL)
|
||||
/* Point to first structure */
|
||||
*list_ptr = struct_ptr;
|
||||
|
||||
if (last_struct)
|
||||
last_struct->next_member = struct_ptr;
|
||||
last_struct = struct_ptr;
|
||||
|
||||
/* Get variable list */
|
||||
token_class = get_var_list(&struct_ptr->name_list, &token);
|
||||
|
||||
/* Get type and optional array designator */
|
||||
get_token_ptr(&struct_ptr->type);
|
||||
token_class = parse_type(struct_ptr, &token);
|
||||
|
||||
/* Get seperator */
|
||||
token_class = get_token(&token);
|
||||
} while (token_class == COMMA);
|
||||
|
||||
if (token_class != RIGHT_PAREN) {
|
||||
parse_error("'(' expected");
|
||||
free_decl_list(*list_ptr);
|
||||
*list_ptr = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse type and optional array designator.
|
||||
* Passed initial token.
|
||||
* Returns RESERVED if appropriate type found, else returns END_OF_LINE.
|
||||
*/
|
||||
parse_type(el_ptr, token)
|
||||
DECL_MEMBER *el_ptr;
|
||||
TOKEN *token;
|
||||
{
|
||||
TOKEN *temp_token;
|
||||
int token_class;
|
||||
|
||||
token_class = token->token_class;
|
||||
if (token_class == LEFT_PAREN) {
|
||||
/* Array specifier */
|
||||
/* Get numeric or '*' */
|
||||
get_token_ptr(&temp_token);
|
||||
token_class = get_token(temp_token);
|
||||
|
||||
if ((token_class == NUMERIC) ||
|
||||
((token_class == OPERATOR) &&
|
||||
(temp_token->token_type == TIMES))) {
|
||||
if (token_class != NUMERIC)
|
||||
/* array(*) specified - ignore '*' */
|
||||
temp_token->token_name[0] = '\0';
|
||||
|
||||
/* Save array bound token */
|
||||
el_ptr->array_bound = temp_token;
|
||||
} else {
|
||||
parse_error("Illegal array bound");
|
||||
free((char *) temp_token);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get right paren */
|
||||
token_class = get_token(token);
|
||||
if (token_class != RIGHT_PAREN) {
|
||||
parse_error("')' expected");
|
||||
free((char *) temp_token);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Get type */
|
||||
token_class = get_token(token);
|
||||
}
|
||||
|
||||
if ((token_class == RESERVED) && (token->token_type >= BYTE) &&
|
||||
(token->token_type <= STRUCTURE)) {
|
||||
|
||||
/* Save type token */
|
||||
token_copy(token, el_ptr->type);
|
||||
|
||||
if (token->token_type == STRUCTURE) {
|
||||
/* Get structure list */
|
||||
parse_structure(&el_ptr->struct_list);
|
||||
}
|
||||
return token_class;
|
||||
} else {
|
||||
parse_error("Illegal type");
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a DECLARE element.
|
||||
* Return token terminating DECLARE element.
|
||||
*/
|
||||
get_element(element, token)
|
||||
DECL_MEMBER **element;
|
||||
TOKEN *token;
|
||||
{
|
||||
DECL_MEMBER *el_ptr;
|
||||
TOKEN temp_token, eof_token;
|
||||
int token_class;
|
||||
char *tmp_text_ptr;
|
||||
char *tmp_out_string;
|
||||
|
||||
char *get_mem();
|
||||
|
||||
get_element_ptr(element);
|
||||
|
||||
/* Point to element */
|
||||
el_ptr = *element;
|
||||
|
||||
/* Get name list */
|
||||
token_class = get_var_list(&el_ptr->name_list, token);
|
||||
|
||||
/* Malloc space for type */
|
||||
get_token_ptr(&el_ptr->type);
|
||||
|
||||
if (token_class == RESERVED)
|
||||
switch (token->token_type) {
|
||||
|
||||
case LABEL :
|
||||
/* LABEL declaration */
|
||||
token_copy(token, el_ptr->type);
|
||||
|
||||
/* Check for PUBLIC or EXTERNAL */
|
||||
token_class = get_token(token);
|
||||
if ((token_class == RESERVED) &&
|
||||
((token->token_type == PUBLIC) ||
|
||||
(token->token_type == EXTERNAL)))
|
||||
/* Indeed, who cares? */
|
||||
token_class = get_token(token);
|
||||
return token_class;
|
||||
|
||||
case LITERALLY :
|
||||
token_copy(token, el_ptr->type);
|
||||
|
||||
/* Check for 'string' */
|
||||
if (get_token(token) != STRING) {
|
||||
parse_error("String expected");
|
||||
free_decl_list(el_ptr);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
el_ptr->literal = get_mem(MAX_LITERAL_SIZE);
|
||||
#ifdef PARSE_LITERALS
|
||||
/* Parse literal string if only one token in string */
|
||||
tmp_text_ptr = text_ptr;
|
||||
text_ptr = token->token_name;
|
||||
|
||||
/* Parse token in string */
|
||||
if (get_token(&temp_token) == END_OF_FILE)
|
||||
el_ptr->literal[0] = '\0';
|
||||
else
|
||||
if (get_token(&eof_token) == END_OF_FILE) {
|
||||
/* Single token literal */
|
||||
(void) strcpy(el_ptr->literal, temp_token.token_name);
|
||||
/* Save parsed token */
|
||||
get_token_ptr(&el_ptr->literal_token);
|
||||
token_copy(&temp_token, el_ptr->literal_token);
|
||||
} else
|
||||
(void) strcpy(el_ptr->literal, token->token_name);
|
||||
|
||||
text_ptr = tmp_text_ptr;
|
||||
#else
|
||||
/* Put string in literal */
|
||||
(void) strcpy(el_ptr->literal, token->token_name);
|
||||
#endif
|
||||
|
||||
/* Return following token */
|
||||
token_class = get_token(token);
|
||||
return token_class;
|
||||
}
|
||||
|
||||
if (parse_type(el_ptr, token) != RESERVED) {
|
||||
/* Error occurred */
|
||||
free_decl_list(el_ptr);
|
||||
return END_OF_LINE;
|
||||
}
|
||||
|
||||
/* Process attribute information (if any) */
|
||||
/* Check for EXTERNAL [ DATA ] */
|
||||
token_class = get_token(token);
|
||||
if (token_class != RESERVED)
|
||||
return token_class;
|
||||
|
||||
if (token->token_type == EXTERNAL) {
|
||||
el_ptr->attributes = EXTERNAL;
|
||||
|
||||
/* Check for DATA attribute */
|
||||
token_class = get_token(token);
|
||||
if (token_class == RESERVED) {
|
||||
if (token->token_type == DATA) {
|
||||
/*
|
||||
* Ignore attribute
|
||||
* el_ptr->initialization = DATA;
|
||||
*/
|
||||
token_class = get_token(token);
|
||||
} else {
|
||||
parse_error("Illegal attribute");
|
||||
free_decl_list(el_ptr);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return token_class;
|
||||
} else
|
||||
|
||||
/* Check for PUBLIC */
|
||||
if (token->token_type == PUBLIC) {
|
||||
el_ptr->attributes = PUBLIC;
|
||||
token_class = get_token(token);
|
||||
}
|
||||
|
||||
if (token_class != RESERVED)
|
||||
return token_class;
|
||||
|
||||
/* Check for AT ( <expr> ) */
|
||||
if (token->token_type == AT) {
|
||||
/* Check for '(' */
|
||||
token_class = get_token(token);
|
||||
|
||||
if (token_class != LEFT_PAREN) {
|
||||
parse_error("'(' expected");
|
||||
free_decl_list(el_ptr);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Generate a string for the AT expression */
|
||||
el_ptr->at_ptr = get_mem(MAX_AT_EXPR_SIZE);
|
||||
el_ptr->at_ptr[0] = '\0';
|
||||
tmp_out_string = out_string;
|
||||
out_string = el_ptr->at_ptr;
|
||||
|
||||
/* Parse the expression into at_ptr */
|
||||
token_class = parse_expression(token);
|
||||
if (token_class != RIGHT_PAREN) {
|
||||
parse_error("')' expected");
|
||||
free_decl_list(el_ptr);
|
||||
return ERROR;
|
||||
}
|
||||
out_string = tmp_out_string;
|
||||
token_class = get_token(token);
|
||||
}
|
||||
|
||||
if (token_class != RESERVED)
|
||||
return token_class;
|
||||
|
||||
/* Check for INITIAL or DATA ( <expr> ) */
|
||||
if ((token->token_type == INITIAL) ||
|
||||
(token->token_type == DATA)) {
|
||||
|
||||
el_ptr->initialization = token->token_type;
|
||||
|
||||
/* Check for '(' */
|
||||
token_class = get_token(token);
|
||||
|
||||
if (token_class != LEFT_PAREN) {
|
||||
parse_error("'(' expected");
|
||||
free_decl_list(el_ptr);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
el_ptr->init_ptr = text_ptr;
|
||||
/* Skip to ')' */
|
||||
find_right_paren();
|
||||
token_class = get_token(token);
|
||||
}
|
||||
return token_class;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a DECLARE list.
|
||||
* Passed a pointer to a DECL, returns with DECL filled.
|
||||
*/
|
||||
get_decl_list(decl)
|
||||
DECL *decl;
|
||||
{
|
||||
DECL_MEMBER *el_ptr, *decl_ptr;
|
||||
TOKEN token;
|
||||
int token_class;
|
||||
|
||||
decl->decl_list = NULL;
|
||||
decl->next_decl = NULL;
|
||||
decl_ptr = NULL;
|
||||
|
||||
do {
|
||||
/* Get a declaration element */
|
||||
token_class = get_element(&el_ptr, &token);
|
||||
|
||||
if (decl->decl_list == NULL)
|
||||
decl->decl_list = el_ptr;
|
||||
|
||||
/* Link previous element */
|
||||
if (decl_ptr)
|
||||
decl_ptr->next_member = el_ptr;
|
||||
decl_ptr = el_ptr;
|
||||
} while (token_class == COMMA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a DECLARE statement.
|
||||
*/
|
||||
parse_declare(first_token)
|
||||
TOKEN *first_token;
|
||||
{
|
||||
DECL decl;
|
||||
|
||||
decl.decl_token = first_token;
|
||||
get_decl_list(&decl);
|
||||
out_decl(&decl);
|
||||
add_to_context(decl.decl_list);
|
||||
}
|
||||
24
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/defs.h
Normal file
24
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/defs.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Maximum number of characters in a token
|
||||
*/
|
||||
#define MAX_TOKEN_LENGTH 512
|
||||
|
||||
/*
|
||||
* Maximum number of characters in an individual DO CASE statement
|
||||
*/
|
||||
#define MAX_CASE_STATEMENT_SIZE 10240
|
||||
|
||||
/*
|
||||
* Maximum number of characters in an AT expression
|
||||
*/
|
||||
#define MAX_AT_EXPR_SIZE 128
|
||||
|
||||
/*
|
||||
* Maximum number of characters in a literal string
|
||||
*/
|
||||
#define MAX_LITERAL_SIZE 512
|
||||
|
||||
/*
|
||||
* Maximum number of identifier names in at_decl.cvt
|
||||
*/
|
||||
#define MAX_AT_DECLS 64
|
||||
116
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/error.c
Normal file
116
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/error.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
#include "tkn_ext.h"
|
||||
|
||||
extern BOOLEAN syntax_error;
|
||||
|
||||
extern char *text_ptr;
|
||||
extern int line_count;
|
||||
extern char *line_ptr;
|
||||
extern char current_file_name[];
|
||||
|
||||
/*
|
||||
* parse_mesg() - Print given message, message type, and current
|
||||
* line number. Skip to error_eol.
|
||||
*/
|
||||
parse_mesg(error_string, error_type, error_eol)
|
||||
char *error_string, *error_type;
|
||||
char error_eol;
|
||||
{
|
||||
char *err_ptr;
|
||||
int i, offset;
|
||||
TOKEN token;
|
||||
|
||||
syntax_error = TRUE;
|
||||
|
||||
offset = text_ptr - line_ptr - 1;
|
||||
|
||||
/* Find end of line */
|
||||
for (err_ptr = line_ptr; (*err_ptr != '\0') &&
|
||||
(*err_ptr != LF); err_ptr++) ;
|
||||
|
||||
if (*error_string) {
|
||||
(void) fprintf(stderr, "\n%s - Parse %s: %s.\nOccurred at line %d near:\n",
|
||||
current_file_name, error_type, error_string, line_count);
|
||||
|
||||
/* Print offending line */
|
||||
(void) fwrite(line_ptr, err_ptr - line_ptr + 1, 1, stderr);
|
||||
|
||||
for (i = 0; i < offset; i++)
|
||||
if (line_ptr[i] < ' ')
|
||||
(void) fputc(line_ptr[i], stderr);
|
||||
else
|
||||
(void) fputc(' ', stderr);
|
||||
(void) fputc('^', stderr);
|
||||
|
||||
if (*err_ptr == '\0')
|
||||
(void) fputc(LF, stderr);
|
||||
}
|
||||
|
||||
if (*err_ptr != '\0')
|
||||
err_ptr++;
|
||||
|
||||
/* Skip to end-of-line */
|
||||
if (error_eol == '\0')
|
||||
return;
|
||||
else
|
||||
|
||||
if (error_eol == LF) {
|
||||
text_ptr = err_ptr;
|
||||
line_ptr = err_ptr;
|
||||
line_count++;
|
||||
} else {
|
||||
|
||||
if (*(text_ptr - 1) != ';') {
|
||||
do {
|
||||
i = get_token(&token);
|
||||
} while ((i != END_OF_FILE) && (i != END_OF_LINE));
|
||||
}
|
||||
|
||||
/* Point at end of line */
|
||||
text_ptr--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_error() - Print given error message and current line number.
|
||||
* Called when an unrecognised or unprocessable token
|
||||
* appears.
|
||||
*/
|
||||
parse_error(error_string)
|
||||
char *error_string;
|
||||
{
|
||||
if (syntax_error)
|
||||
/* Already had an error on this line */
|
||||
return;
|
||||
|
||||
parse_mesg(error_string, "error", END_OF_LINE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a parse_error(), but move to END_OF_LINE, not ';'
|
||||
*/
|
||||
control_error(error_string)
|
||||
char *error_string;
|
||||
{
|
||||
#ifdef IGNORE_CONTROL_ERRORS
|
||||
parse_mesg("", "", LF);
|
||||
#else
|
||||
parse_mesg(error_string, "error", LF);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_warning - Generate a warning message
|
||||
*/
|
||||
parse_warning(warning_string)
|
||||
char *warning_string;
|
||||
{
|
||||
parse_mesg(warning_string, "warning", '\0');
|
||||
}
|
||||
|
||||
354
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/io.c
Normal file
354
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/io.c
Normal file
@@ -0,0 +1,354 @@
|
||||
#include <stdio.h>
|
||||
#ifdef IBMPC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
|
||||
char *out_string;
|
||||
char last_out_ch;
|
||||
|
||||
char *str_shifts[] = { "0", "8", "16", "24" };
|
||||
|
||||
extern char *text_buffer, *text_ptr;
|
||||
extern int line_count;
|
||||
extern int file_depth;
|
||||
extern FILE *ofd;
|
||||
|
||||
extern BOOLEAN parsing_literal;
|
||||
extern TOKEN literal_token;
|
||||
|
||||
/*
|
||||
* Output data of specified length.
|
||||
* If out_string is not NULL, append string to out_string.
|
||||
* Otherwise write string to stdout.
|
||||
*/
|
||||
out_data(string, length)
|
||||
char *string;
|
||||
int length;
|
||||
{
|
||||
if (length) {
|
||||
if (out_string)
|
||||
(void) strncat(out_string, string, length);
|
||||
else
|
||||
if (file_depth == 1)
|
||||
#ifdef DEBUG
|
||||
(void) fwrite(string, length, 1, stdout);
|
||||
#else
|
||||
(void) fwrite(string, length, 1, ofd);
|
||||
#endif
|
||||
else
|
||||
return;
|
||||
|
||||
/* Save last character output */
|
||||
last_out_ch = *(string + length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print white space
|
||||
*/
|
||||
out_white_space(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
int length;
|
||||
|
||||
/* Compute length of white space */
|
||||
length = token->white_space_end - token->white_space_start;
|
||||
|
||||
if (length)
|
||||
out_data(token->white_space_start, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print white space, if any. If start of white space string is not
|
||||
* white, prefix with a space.
|
||||
*/
|
||||
out_must_white(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
if (!is_white(*(token->white_space_start)))
|
||||
out_char(' ');
|
||||
out_white_space(token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print all white space up first new-line (if any).
|
||||
* Move white_space_start to point past first new-line.
|
||||
*/
|
||||
out_pre_line(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
while ((token->white_space_start < token->white_space_end) &&
|
||||
(*token->white_space_start != '\n')) {
|
||||
out_char(*token->white_space_start);
|
||||
token->white_space_start++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print all white space up to but not including last new-line.
|
||||
* Move white_space_start to point to last new-line.
|
||||
*/
|
||||
out_pre_white(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
char *ptr;
|
||||
int length;
|
||||
|
||||
for (ptr = token->white_space_end;
|
||||
(ptr > token->white_space_start) && (*(ptr - 1) != '\n') ; )
|
||||
ptr--;
|
||||
|
||||
if (ptr == token->white_space_start)
|
||||
return;
|
||||
|
||||
/* Compute length of white space */
|
||||
length = ptr - token->white_space_start - 1;
|
||||
|
||||
if (length)
|
||||
out_data(token->white_space_start, length);
|
||||
|
||||
token->white_space_start = ptr - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output token name
|
||||
*/
|
||||
out_token_name(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
if (is_a_type(token))
|
||||
out_type(token->token_type);
|
||||
else
|
||||
out_data(token->token_name, strlen(token->token_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Output white space and token name
|
||||
*/
|
||||
out_token(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
out_white_space(token);
|
||||
out_token_name(token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output guaranteed white space and token name
|
||||
*/
|
||||
out_must_token(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
out_must_white(token);
|
||||
out_token_name(token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output case converted token name
|
||||
*/
|
||||
out_cvt_name(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
for (ptr = token->token_name; *ptr; ptr++) {
|
||||
if (is_a_lc_char(*ptr))
|
||||
out_char(*ptr - 32);
|
||||
else
|
||||
if (is_a_uc_char(*ptr))
|
||||
out_char(*ptr + 32);
|
||||
else
|
||||
out_char(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output string
|
||||
*/
|
||||
out_str(string)
|
||||
char *string;
|
||||
{
|
||||
out_data(string, strlen(string));
|
||||
}
|
||||
|
||||
/*
|
||||
* Output character
|
||||
*/
|
||||
out_char(ch)
|
||||
char ch;
|
||||
{
|
||||
out_data(&ch, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output new-line if not at start of line
|
||||
*/
|
||||
out_to_start()
|
||||
{
|
||||
if (last_out_ch != LF)
|
||||
out_char(LF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output type
|
||||
*/
|
||||
out_type(type)
|
||||
int type;
|
||||
{
|
||||
switch (type) {
|
||||
|
||||
case BYTE :
|
||||
#ifdef CONVERT_TYPES
|
||||
out_str(TYPE_BYTE);
|
||||
#else
|
||||
out_str("BYTE");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case WORD :
|
||||
#ifdef CONVERT_TYPES
|
||||
out_str(TYPE_WORD);
|
||||
#else
|
||||
out_str("WORD");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DWORD :
|
||||
#ifdef CONVERT_TYPES
|
||||
out_str(TYPE_DWORD);
|
||||
#else
|
||||
out_str("DWORD");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case INTEGER :
|
||||
#ifdef CONVERT_TYPES
|
||||
out_str(TYPE_INTEGER);
|
||||
#else
|
||||
out_str("INTEGER");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REAL :
|
||||
#ifdef CONVERT_TYPES
|
||||
out_str(TYPE_REAL);
|
||||
#else
|
||||
out_str("REAL");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case POINTER :
|
||||
out_str(TYPE_POINTER);
|
||||
break;
|
||||
|
||||
default :
|
||||
parse_error("Unknown type");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize variables for I/O.
|
||||
*/
|
||||
out_init()
|
||||
{
|
||||
out_string = NULL;
|
||||
last_out_ch = '\0';
|
||||
parsing_literal = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output string constant of form 'WXYZ' in form:
|
||||
* 'W' << 24 | 'X' << 16 | 'Y' << 8 | Z
|
||||
* where len specifies the number of bytes in the string to output.
|
||||
*/
|
||||
out_str_const(str_ptr, len)
|
||||
char *str_ptr;
|
||||
int len;
|
||||
{
|
||||
while (len-- && *str_ptr) {
|
||||
out_char('\'');
|
||||
if (*str_ptr == '\'')
|
||||
out_char('\\');
|
||||
out_char(*str_ptr++);
|
||||
out_char('\'');
|
||||
|
||||
if (len) {
|
||||
out_str(" << ");
|
||||
out_str(str_shifts[len]);
|
||||
if (*str_ptr)
|
||||
out_str(" | ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert NUMERIC constant to octal constant
|
||||
*/
|
||||
cvt_octal(token, octal_string)
|
||||
TOKEN *token;
|
||||
char octal_string[];
|
||||
{
|
||||
int octal;
|
||||
char ch, *ptr;
|
||||
|
||||
octal = 0;
|
||||
octal_string[0] = '\\';
|
||||
octal_string[4] = '\0';
|
||||
|
||||
ch = *(token->token_start + token->token_length - 1);
|
||||
|
||||
/* Determine base of numeric */
|
||||
if (ch == 'H') {
|
||||
/* Hex */
|
||||
for (ptr = token->token_name + 2; *ptr; ptr++) {
|
||||
octal *= 16;
|
||||
if ((*ptr >= '0') && (*ptr <= '9'))
|
||||
octal += *ptr - '0';
|
||||
else
|
||||
if ((*ptr >= 'A') && (*ptr <= 'Z'))
|
||||
octal += *ptr - 'A' + 10;
|
||||
else
|
||||
if ((*ptr >= 'a') && (*ptr <= 'z'))
|
||||
octal += *ptr - 'a' + 10;
|
||||
else {
|
||||
parse_error("Illegal hex character");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
|
||||
if ((ch == 'O') || (ch == 'Q')) {
|
||||
/* Octal constant */
|
||||
for (ptr = token->token_name + 1; *ptr; ptr++) {
|
||||
octal *= 8;
|
||||
if ((*ptr >= '0') && (*ptr <= '7'))
|
||||
octal += *ptr - '0';
|
||||
else {
|
||||
parse_error("Illegal decimal character");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Decimal constant */
|
||||
for (ptr = token->token_name + 1; *ptr; ptr++) {
|
||||
octal *= 10;
|
||||
if ((*ptr >= '0') && (*ptr <= '9'))
|
||||
octal += *ptr - '0';
|
||||
else {
|
||||
parse_error("Illegal decimal character");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Generate octal constant */
|
||||
octal_string[1] = ((octal >> 6) & 3) + '0';
|
||||
octal_string[2] = ((octal >> 3) & 7) + '0';
|
||||
octal_string[3] = (octal & 7) + '0';
|
||||
}
|
||||
168
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/lit.c
Normal file
168
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/lit.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/*********************************************************************
|
||||
*********************************************************************
|
||||
** **
|
||||
** **
|
||||
** LITERALS **
|
||||
** **
|
||||
** **
|
||||
** Revision History: SCO #23 (12/11/84) **
|
||||
** SCO #31 (02/12/86) {SCO31.DOC} **
|
||||
** SCO #33 (06/03/86) {SCO33.DOC} **
|
||||
** SCO #34 (10/28/86) {SCO34.DOC} **
|
||||
** SCO #36 (07/16/86) {SCO36.DOC} **
|
||||
** SCO #48 (03/21/87) {SCO48.DOC} **
|
||||
** **
|
||||
*********************************************************************
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define POWER_FAIL_SENSE_LATCH 0x0080
|
||||
#define INTERRUPT_CONTROLLER_PORT_1 0x00C0
|
||||
#define INTERRUPT_CONTROLLER_PORT_2 0x00C2
|
||||
#define INSTRUCTION_WORD_1 0x13
|
||||
#define INSTRUCTION_WORD_2 0x20
|
||||
#define INSTRUCTION_WORD_3 0x01
|
||||
#define END_OF_PARITY_INTERRUPT 0x60
|
||||
#define END_OF_EXCEPTION_INTERRUPT 0x61
|
||||
#define END_OF_REFRESH_INTERRUPT 0x62
|
||||
#define END_OF_CYCLE_INTERRUPT 0x63
|
||||
#define END_OF_SHORT_INTERRUPT 0x67
|
||||
#define INTERRUPT_CONTROLLER_MASK_0 0x0F0
|
||||
#define INTERRUPT_CONTROLLER_MASK_1 0x0FC
|
||||
#define INTERRUPT_CONTROLLER_MASK_2 0x0F8
|
||||
#define INTERRUPT_CONTROLLER_MASK_3 0x0F4
|
||||
#define INTERVAL_TIMER_PORT_1 0x0D2
|
||||
#define INTERVAL_TIMER_PORT_2 0x0D6
|
||||
#define CONTROL_WORD 0x74
|
||||
#define DATA_WORD_1 0x12
|
||||
#define DATA_WORD_2 0x7A
|
||||
#define CONTROL_WORD_87 0x033C
|
||||
#define DPM_CONTROL_WORD_87 0x0F3C
|
||||
#define BIT_CONTROL_WORD_87 0x0F3C
|
||||
#define INTERFACE_1_START_CODE 0x01
|
||||
#define INTERFACE_2_START_CODE 0x01
|
||||
#define HCP_NORMAL 0x00
|
||||
#define HCP_TEST_MODE 0x01
|
||||
#define HCP_ADVANCE 0x02
|
||||
#define HCP_RESET 0x03
|
||||
#define HCP_ALTITUDE_HOLD_RESET 0x04
|
||||
#define HCP_FAIL 0x07
|
||||
|
||||
#define IS =
|
||||
#define VALID 0x55
|
||||
#define NO_COMPUTED_DATA 0x66
|
||||
#define FUNCTIONAL_TEST 0x99
|
||||
#define TEST_MODE 0x0AA /*{SCO36.DOC}*/
|
||||
#define FLIGHT_MODE 0x55 /*{SCO36.DOC}*/
|
||||
#define POSITIVE_BIAS 0 /*{SCO31.DOC}*/
|
||||
#define NEGATIVE_BIAS 1 /*{SCO31.DOC}*/
|
||||
#define RESET 0x0AA
|
||||
#define PASS 0x55
|
||||
#define ON 0x55
|
||||
#define TO_VOR 0x55
|
||||
#define FROM_VOR 0x99
|
||||
#define ILS 0x55 /*{SCO48.DOC}*/
|
||||
#define VOR 0x0AA /*{SCO48.DOC}*/
|
||||
#define INVALID 0x0AA
|
||||
#define OFF 0x0AA
|
||||
#define PUSHED 0x55
|
||||
#define SET 0x55
|
||||
#define FAIL 0x0AA
|
||||
#define FAILED 0x0FF
|
||||
#define VMC 4
|
||||
#define IMC 5
|
||||
#define CRZ 6
|
||||
#define TOGA 7
|
||||
#define BLANK 10
|
||||
#define NEGATIVE_SIGN 11
|
||||
|
||||
#define ERROR_DISPLAY 0x5554
|
||||
#define PFM_KEY_COUNTER 0x5555
|
||||
#define PFM_TIMER 0x5556
|
||||
#define COMPUTER_FAULT 0x5557
|
||||
#define KEY1 5
|
||||
#define KEY2 4
|
||||
#define KEY3 3
|
||||
#define KEY4 2
|
||||
#define KEY5 1
|
||||
#define KEY6 0
|
||||
#define DISPLAY_GENERATOR_PORT 0x0C000
|
||||
#define DISPLAY_GENERATOR_HALT_CODE 3
|
||||
#define DISPLAY_GENERATOR_START_CODE 4
|
||||
#define DISPLAY_HALT_ENABLE_CODE 0
|
||||
#define DG_HALT 0x0005
|
||||
#define LOAD_ROTATION_ANGLE 0x0007
|
||||
#define LOAD_PRESENT_POSITION 0x0008
|
||||
#define DRAW_VECTOR 0x0009
|
||||
#define LOAD_BORDERS 0x000D
|
||||
#define ZERO_DEGREE_ANGLE 0
|
||||
#define NINETY_DEGREE_ANGLE 0x4000
|
||||
#define NEG_NINETY_DEGREE_ANGLE 0x0C000
|
||||
#define ONE_EIGHTY_DEGREE_ANGLE 0x8000
|
||||
#define FIRST_HALF_OF_BUFFER 0
|
||||
#define SECOND_HALF_OF_BUFFER 750
|
||||
#define WINDOW_COMPARATOR_FAIL 0
|
||||
#define WINDOW_COMPARATOR_PASS 7
|
||||
#define TWENTY_CYCLES 20
|
||||
#define FORTY_CYCLES 40
|
||||
|
||||
#define IOS1_CODE_CHECKSUM_ERROR 0x11 /*{SCO31.DOC}*/
|
||||
#define IOS1_RAM_ERROR 0x12 /*{SCO31.DOC}*/
|
||||
#define IOS1_80186_ERROR 0x13 /*{SCO31.DOC}*/
|
||||
#define IOS1_8087_ERROR 0x14 /*{SCO31.DOC}*/
|
||||
#define IOS1_CONVERTOR_ERROR 0x15 /*{SCO31.DOC}*/
|
||||
#define IOS1_HUD_POWER_SUPPLY_ERROR 0x16 /*{SCO31.DOC}*/
|
||||
#define IOS2_CODE_CHECKSUM_ERROR 0x21 /*{SCO31.DOC}*/
|
||||
#define IOS2_RAM_ERROR 0x22 /*{SCO31.DOC}*/
|
||||
#define IOS2_80186_ERROR 0x23 /*{SCO31.DOC}*/
|
||||
#define IOS2_8087_ERROR 0x24 /*{SCO31.DOC}*/
|
||||
#define IOS2_CONVERTOR_ERROR 0x25 /*{SCO31.DOC}*/
|
||||
#define CLP_CODE_CHECKSUM_ERROR 0x31 /*{SCO31.DOC}*/
|
||||
#define CLP_RAM_ERROR 0x32 /*{SCO31.DOC}*/
|
||||
#define CLP_8086_ERROR 0x33 /*{SCO31.DOC}*/
|
||||
#define CLP_8087_ERROR 0x34 /*{SCO31.DOC}*/
|
||||
#define SM_CODE_CHECKSUM_ERROR 0x41 /*{SCO31.DOC}*/
|
||||
#define SM_RAM_ERROR 0x42 /*{SCO31.DOC}*/
|
||||
#define SM_8086_ERROR 0x43 /*{SCO31.DOC}*/
|
||||
#define SM_8087_ERROR 0x44 /*{SCO31.DOC}*/
|
||||
#define SYSTEM_MONITOR_INACTIVE 0x45 /*{SCO31.DOC}*/
|
||||
#define DISPLAY_GENERATOR_ERROR 0x51 /*{SCO31.DOC}*/
|
||||
#define SYMBOL_MISPOSITIONED_1 0x52 /*{SCO31.DOC}*/
|
||||
#define OHU_VIDEO_FAIL 0x63 /*{SCO31.DOC}*/
|
||||
#define OHU_HVPS_FAIL 0x64 /*{SCO31.DOC}*/
|
||||
#define OHU_95_OR_30_VOLT_SUPPLY_FAIL 0x65 /*{SCO31.DOC}*/
|
||||
#define SYMBOL_MISPOSITIONED_2 0x71 /*{SCO31.DOC}*/
|
||||
#define WINDOW_COMPARATOR_ERROR 0x77 /*{SCO31.DOC}*/
|
||||
#define DEU_VERTICAL_DEFLECTION_FAIL 0x7A /*{SCO31.DOC}*/
|
||||
#define DEU_HORIZONTAL_DEFLECTION_FAIL 0x7B /*{SCO31.DOC}*/
|
||||
#define DEU_DC_SUPPLY_FAIL 0x7C /*{SCO31.DOC}*/
|
||||
#define DEU_BOOST_SUPPLY_FAIL 0x7D /*{SCO31.DOC}*/
|
||||
#define DEU_DEFLECTION_SUPPLY_FAIL 0x7E /*{SCO31.DOC}*/
|
||||
#define TEST_ERROR_DISPLAY 0x88
|
||||
#define DISPLAY_GENERATOR_TEST 0x89
|
||||
#define HCP_FAILURE 0x91 /*{SCO31.DOC}*/
|
||||
#define RSU_FAILURE 0x0A1 /*{SCO34.DOC}*/
|
||||
#define COMBINER_NOT_LOCKED 0x0B1 /*{SCO33.DOC}*/
|
||||
#define EIGHTH_SECOND 3
|
||||
#define ONE_SIXTH_SECOND 3
|
||||
#define QUARTER_SECOND 5
|
||||
#define ONE_THIRD_SECOND 6
|
||||
#define HALF_SECOND 10
|
||||
#define ONE_SECOND 20
|
||||
#define ONE_POINT_FIVE_SECONDS 30
|
||||
#define TWO_SECONDS 40
|
||||
#define FIVE_SECONDS 100
|
||||
|
||||
#define HALF_PI 1.57079633F
|
||||
#define PI 3.14159265F
|
||||
#define TWO_PI 6.28318531F
|
||||
#define TEN_KNOTS 16.9F
|
||||
#define TEN_DEGREES 0.1745F
|
||||
#define FIFTEEN_DEGREES 0.2618F
|
||||
#define MAXIMUM_NUMBER 99999.9F
|
||||
|
||||
#define FOREVER while (1)
|
||||
|
||||
248
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/main.c
Normal file
248
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/main.c
Normal file
@@ -0,0 +1,248 @@
|
||||
#include <stdio.h>
|
||||
#ifdef IBMPC
|
||||
#include <stdlib.h>
|
||||
#include <sys\stat.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
#include "tkn_defs.h"
|
||||
|
||||
char *text_buffer, *text_ptr;
|
||||
int line_count;
|
||||
char *line_ptr;
|
||||
char current_file_name[128];
|
||||
char out_file_name[128];
|
||||
int at_decl_count;
|
||||
char at_decl_list[MAX_AT_DECLS][MAX_TOKEN_LENGTH];
|
||||
FILE *ofd;
|
||||
|
||||
int file_depth;
|
||||
|
||||
FILE *fopen();
|
||||
|
||||
/*
|
||||
* Get list of AT declaration variables for EXTERNAL declaration checks
|
||||
*/
|
||||
get_at_decl()
|
||||
{
|
||||
int i, fd;
|
||||
char ch;
|
||||
|
||||
at_decl_count = 0;
|
||||
if ((fd = open("at_decl.cvt", O_RDONLY)) == -1)
|
||||
/* Not found */
|
||||
return;
|
||||
|
||||
while (read(fd, &ch, 1) == 1) {
|
||||
i = 0;
|
||||
if (!is_a_char(ch)) {
|
||||
fprintf(stderr, "Illegal identifier in line %d at_decl.cvt\n",
|
||||
at_decl_count + 1);
|
||||
exit(1);
|
||||
}
|
||||
do {
|
||||
#ifdef CONVERT_CASE
|
||||
if (is_a_uc_char(ch))
|
||||
/* Convert to lower case */
|
||||
ch += 32;
|
||||
else
|
||||
if (is_a_lc_char(ch))
|
||||
/* Convert to upper case */
|
||||
ch -= 32;
|
||||
#endif
|
||||
at_decl_list[at_decl_count][i++] = ch;
|
||||
if (read(fd, &ch, 1) != 1) {
|
||||
fprintf(stderr, "Unexpected EOF in at_decl.cvt\n");
|
||||
exit(1);
|
||||
}
|
||||
} while ((ch != '\n') && (ch != ' '));
|
||||
|
||||
at_decl_list[at_decl_count++][i] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open specified file, init options, and parse.
|
||||
*/
|
||||
cvt_file(file_name)
|
||||
char *file_name;
|
||||
{
|
||||
int fd, nr;
|
||||
struct stat file_stat;
|
||||
TOKEN token, fname_token, token_module, token_do;
|
||||
int token_class;
|
||||
char *tmp_text_buffer, *tmp_text_ptr, *tmp_line_ptr;
|
||||
char *tmp_ptr;
|
||||
int tmp_line_count;
|
||||
char tmp_file_name[128];
|
||||
|
||||
char *get_mem();
|
||||
|
||||
/* Is this the first file? */
|
||||
if (file_depth) {
|
||||
/* No - save old text pointers */
|
||||
tmp_text_buffer = text_buffer;
|
||||
tmp_text_ptr = text_ptr;
|
||||
tmp_line_ptr = line_ptr;
|
||||
tmp_line_count = line_count;
|
||||
(void) strcpy(tmp_file_name, current_file_name);
|
||||
}
|
||||
|
||||
/* Save file name */
|
||||
(void) strcpy(current_file_name, file_name);
|
||||
|
||||
/* Open file */
|
||||
if ((fd = open(file_name, O_RDONLY)) == -1) {
|
||||
(void) fprintf(stderr, "Cannot open input file %s", file_name);
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Get length */
|
||||
if (fstat(fd, &file_stat)) {
|
||||
perror("Cannot stat input file");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Allocate that much RAM */
|
||||
text_buffer = get_mem((unsigned int) file_stat.st_size + 1);
|
||||
|
||||
/* Read file */
|
||||
if ((nr = read(fd, text_buffer, (int) file_stat.st_size)) == -1) {
|
||||
perror("Cannot read input file");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Insert End-of-file Mark */
|
||||
text_buffer[nr] = '\0';
|
||||
(void) close(fd);
|
||||
|
||||
/* Init pointers */
|
||||
text_ptr = text_buffer;
|
||||
line_ptr = text_ptr;
|
||||
line_count = 1;
|
||||
|
||||
/* Init I/O */
|
||||
out_init();
|
||||
|
||||
/* Start with initial context using file name */
|
||||
(void) strcpy(fname_token.token_name, file_name);
|
||||
fname_token.token_class = IDENTIFIER;
|
||||
new_context(MODULE, &fname_token);
|
||||
|
||||
/* Is this the first file? */
|
||||
if (file_depth++ == 0) {
|
||||
/* Yes - open output file */
|
||||
if ((ofd = fopen(out_file_name, "w")) == NULL) {
|
||||
(void) fprintf(stderr, "Cannot create output file %s",
|
||||
out_file_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check for module name */
|
||||
token_class = get_token(&token_module);
|
||||
out_pre_white(&token_module);
|
||||
tmp_ptr = token_module.token_start;
|
||||
if ((token_class == IDENTIFIER) &&
|
||||
/* Maybe got module name - Check for : */
|
||||
(get_token(&token) == LABEL) &&
|
||||
/* Check for DO; */
|
||||
((get_token(&token_do) == RESERVED) &&
|
||||
(token_do.token_type == DO)) &&
|
||||
(get_token(&token) == END_OF_LINE)) {
|
||||
|
||||
/* Got module header */
|
||||
out_pre_white(&token_do);
|
||||
|
||||
/* Parse to END [<module name>] */
|
||||
parse_till_end(&token);
|
||||
out_white_space(&token);
|
||||
|
||||
token_class = get_token(&token);
|
||||
if (token_class == IDENTIFIER) {
|
||||
out_pre_white(&token);
|
||||
token_class = get_token(&token);
|
||||
}
|
||||
|
||||
/* Should be at end of line */
|
||||
if (token_class != END_OF_LINE) {
|
||||
parse_error("';' expected");
|
||||
}
|
||||
|
||||
/* Should be at end of file */
|
||||
if (get_token(&token) != END_OF_FILE) {
|
||||
parse_error("End of file expected");
|
||||
}
|
||||
out_white_space(&token);
|
||||
} else {
|
||||
out_pre_white(&token_do);
|
||||
parse_warning("Module name expected");
|
||||
text_ptr = tmp_ptr;
|
||||
parse_file();
|
||||
}
|
||||
} else
|
||||
parse_file();
|
||||
|
||||
free(text_buffer);
|
||||
|
||||
/* Was this the first file? */
|
||||
if (--file_depth) {
|
||||
/* No - restore old text pointers */
|
||||
text_buffer = tmp_text_buffer;
|
||||
text_ptr = tmp_text_ptr;
|
||||
line_ptr = tmp_line_ptr;
|
||||
line_count = tmp_line_count;
|
||||
(void) strcpy(current_file_name, tmp_file_name);
|
||||
} else
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open file and init options
|
||||
*/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i;
|
||||
char ch;
|
||||
|
||||
if (argc != 2) {
|
||||
(void) fprintf(stderr, "usage: %s filename\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Search for a '.' in filename */
|
||||
for (i = strlen(argv[1]) - 1; i; i--) {
|
||||
ch = argv[1][i];
|
||||
if ((ch == '.') || (ch == '/') || (ch == '\\'))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch != '.')
|
||||
i = strlen(argv[1]);
|
||||
|
||||
/* Append a '.c' */
|
||||
(void) strncpy(out_file_name, argv[1], i);
|
||||
out_file_name[i] = '\0';
|
||||
(void) strcat(out_file_name, ".c");
|
||||
(void) printf("Output to: %s\n", out_file_name);
|
||||
|
||||
/* Get AT declaration list */
|
||||
get_at_decl();
|
||||
|
||||
/* Init context */
|
||||
init_context();
|
||||
|
||||
file_depth = 0;
|
||||
|
||||
/* Parse main file */
|
||||
cvt_file(argv[1]);
|
||||
}
|
||||
83
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/makefile
Normal file
83
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/makefile
Normal file
@@ -0,0 +1,83 @@
|
||||
# Makefile for Unix
|
||||
|
||||
SRCS = convert.c \
|
||||
parse.c \
|
||||
declare.c \
|
||||
decl_out.c \
|
||||
control.c \
|
||||
io.c \
|
||||
token.c \
|
||||
context.c \
|
||||
mem.c \
|
||||
error.c \
|
||||
version.c \
|
||||
main.c
|
||||
|
||||
OBJS = convert.o \
|
||||
parse.o \
|
||||
declare.o \
|
||||
decl_out.o \
|
||||
control.o \
|
||||
io.o \
|
||||
token.o \
|
||||
context.o \
|
||||
mem.o \
|
||||
error.o \
|
||||
version.o \
|
||||
main.o
|
||||
|
||||
LNKS = convert parse declare decl_out control io token context mem error version main
|
||||
|
||||
TOKEN_HDRS = misc.h defs.h struct.h cvt.h cvt_id.h tokens.h
|
||||
HDRS = $(TOKEN_HDRS) tkn_defs.h tkn_ext.h
|
||||
|
||||
OPTS = -c -O
|
||||
|
||||
plm2c: $(OBJS)
|
||||
$(CC) -o plm2c $(OBJS)
|
||||
|
||||
convert.o: convert.c $(TOKEN_HDRS)
|
||||
$(CC) $(OPTS) convert.c
|
||||
|
||||
parse.o: parse.c $(TOKEN_HDRS) cvt_id.h
|
||||
$(CC) $(OPTS) parse.c
|
||||
|
||||
declare.o: declare.c $(TOKEN_HDRS)
|
||||
$(CC) $(OPTS) declare.c
|
||||
|
||||
control.o: control.c $(TOKEN_HDRS) tkn_ext.h
|
||||
$(CC) $(OPTS) control.c
|
||||
|
||||
decl_out.o: decl_out.c $(TOKEN_HDRS)
|
||||
$(CC) $(OPTS) decl_out.c
|
||||
|
||||
io.o: io.c $(TOKEN_HDRS) tkn_ext.h
|
||||
$(CC) $(OPTS) io.c
|
||||
|
||||
token.o: token.c $(TOKEN_HDRS) tkn_ext.h
|
||||
$(CC) $(OPTS) token.c
|
||||
|
||||
context.o: context.c $(TOKEN_HDRS)
|
||||
$(CC) $(OPTS) context.c
|
||||
|
||||
mem.o: mem.c $(TOKEN_HDRS)
|
||||
$(CC) $(OPTS) mem.c
|
||||
|
||||
error.o: error.c $(TOKEN_HDRS)
|
||||
$(CC) $(OPTS) error.c
|
||||
|
||||
version.o: version.c
|
||||
$(CC) $(OPTS) version.c
|
||||
|
||||
main.o: main.c $(TOKEN_HDRS) tkn_defs.h
|
||||
$(CC) $(OPTS) main.c
|
||||
|
||||
backup:
|
||||
cp $(HDRS) Makefile bak
|
||||
cp $(SRCS) bak
|
||||
|
||||
lint:
|
||||
lint $(SRCS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS)
|
||||
86
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/makefile.ibm
Normal file
86
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/makefile.ibm
Normal file
@@ -0,0 +1,86 @@
|
||||
# Makefile for IBM-PC MSDOS
|
||||
|
||||
SRCS = convert.c \
|
||||
parse.c \
|
||||
declare.c \
|
||||
decl_out.c \
|
||||
control.c \
|
||||
io.c \
|
||||
token.c \
|
||||
context.c \
|
||||
mem.c \
|
||||
error.c \
|
||||
version.c \
|
||||
main.c
|
||||
|
||||
OBJS = convert.obj \
|
||||
parse.obj \
|
||||
declare.obj \
|
||||
decl_out.obj \
|
||||
control.obj \
|
||||
io.obj \
|
||||
token.obj \
|
||||
context.obj \
|
||||
mem.obj \
|
||||
error.obj \
|
||||
version.obj \
|
||||
main.obj
|
||||
|
||||
LNKS = convert parse declare decl_out control io token context mem error version main
|
||||
|
||||
TOKEN_HDRS = misc.h defs.h struct.h cvt.h cvt_id.h tokens.h
|
||||
HDRS = $(TOKEN_HDRS) tkn_defs.h tkn_ext.h
|
||||
|
||||
MDL = m
|
||||
OPTS = -c -N -v -DIBMPC -m$(MDL)
|
||||
|
||||
plm2c: $(OBJS)
|
||||
tlink /c /v c:\tc\lib\c0$(MDL) $(LNKS), plm2c, plm2c, c:\tc\lib\c$(MDL)
|
||||
|
||||
convert.obj: convert.c $(TOKEN_HDRS)
|
||||
tcc $(OPTS) convert
|
||||
|
||||
parse.obj: parse.c $(TOKEN_HDRS) cvt_id.h
|
||||
tcc $(OPTS) parse
|
||||
|
||||
declare.obj: declare.c $(TOKEN_HDRS)
|
||||
tcc $(OPTS) declare
|
||||
|
||||
control.obj: control.c $(TOKEN_HDRS) tkn_ext.h
|
||||
tcc $(OPTS) control
|
||||
|
||||
decl_out.obj: decl_out.c $(TOKEN_HDRS)
|
||||
tcc $(OPTS) decl_out
|
||||
|
||||
io.obj: io.c $(TOKEN_HDRS) tkn_ext.h
|
||||
tcc $(OPTS) io
|
||||
|
||||
token.obj: token.c $(TOKEN_HDRS) tkn_ext.h
|
||||
tcc $(OPTS) token
|
||||
|
||||
context.obj: context.c $(TOKEN_HDRS)
|
||||
tcc $(OPTS) context
|
||||
|
||||
mem.obj: mem.c $(TOKEN_HDRS)
|
||||
tcc $(OPTS) mem
|
||||
|
||||
error.obj: error.c $(TOKEN_HDRS)
|
||||
tcc $(OPTS) error
|
||||
|
||||
version.obj: version.c
|
||||
tcc $(OPTS) version
|
||||
|
||||
main.obj: main.c $(TOKEN_HDRS) tkn_defs.h
|
||||
tcc $(OPTS) main
|
||||
|
||||
backup:
|
||||
cp $(HDRS) Makefile bak
|
||||
cp $(SRCS) bak
|
||||
|
||||
floppy:
|
||||
cp $(HDRS) makefile a:
|
||||
cp $(SRCS) a:
|
||||
|
||||
lint:
|
||||
lint $(SRCS)
|
||||
|
||||
196
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/mem.c
Normal file
196
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/mem.c
Normal file
@@ -0,0 +1,196 @@
|
||||
#ifdef IBMPC
|
||||
#include <alloc.h>
|
||||
#endif
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
|
||||
/*
|
||||
* Memory allocation and deallocation routines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocate memory
|
||||
*/
|
||||
char *get_mem(size)
|
||||
unsigned int size;
|
||||
{
|
||||
char *malloc_ptr;
|
||||
void *malloc();
|
||||
|
||||
if ((malloc_ptr = (char *)malloc(size)) == NULL) {
|
||||
parse_error("Out of memory");
|
||||
exit(1);
|
||||
}
|
||||
return malloc_ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a new context.
|
||||
*/
|
||||
get_context_ptr(context)
|
||||
CONTEXT **context;
|
||||
{
|
||||
*context = (CONTEXT *) get_mem(sizeof(CONTEXT));
|
||||
(*context)->decl_head = NULL;
|
||||
(*context)->next_context = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Malloc memory for a TOKEN.
|
||||
*/
|
||||
get_token_ptr(token)
|
||||
TOKEN **token;
|
||||
{
|
||||
*token = (TOKEN *) get_mem(sizeof(TOKEN));
|
||||
}
|
||||
|
||||
/*
|
||||
* Malloc memory for a DECL_ID.
|
||||
*/
|
||||
get_var_ptr(var)
|
||||
DECL_ID **var;
|
||||
{
|
||||
*var = (DECL_ID *) get_mem(sizeof(DECL_ID));
|
||||
(*var)->name = NULL;
|
||||
(*var)->based_name = NULL;
|
||||
(*var)->next_var = NULL;
|
||||
(*var)->is_ext_at = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a linked list of variables.
|
||||
*/
|
||||
free_var_list(list_ptr)
|
||||
DECL_ID *list_ptr;
|
||||
{
|
||||
DECL_ID *next_ptr;
|
||||
|
||||
while (list_ptr) {
|
||||
if (list_ptr->name)
|
||||
free( (char *) list_ptr->name);
|
||||
if (list_ptr->based_name)
|
||||
free( (char *) list_ptr->based_name);
|
||||
next_ptr = list_ptr->next_var;
|
||||
free((char *) list_ptr);
|
||||
list_ptr = next_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Malloc space for a DECL_MEMBER structure and return pointer.
|
||||
*/
|
||||
get_element_ptr(element)
|
||||
DECL_MEMBER **element;
|
||||
{
|
||||
DECL_MEMBER *el_ptr;
|
||||
|
||||
/* Malloc space for element */
|
||||
el_ptr = (DECL_MEMBER *) get_mem(sizeof(DECL_MEMBER));
|
||||
|
||||
/* Init pointers */
|
||||
el_ptr->name_list = NULL;
|
||||
el_ptr->literal = NULL;
|
||||
#ifdef PARSE_LITERALS
|
||||
el_ptr->literal_token = NULL;
|
||||
#endif
|
||||
el_ptr->array_bound = NULL;
|
||||
el_ptr->type = NULL;
|
||||
el_ptr->struct_list = NULL;
|
||||
el_ptr->at_ptr = NULL;
|
||||
el_ptr->init_ptr = NULL;
|
||||
el_ptr->next_member = NULL;
|
||||
|
||||
el_ptr->attributes = NONE;
|
||||
el_ptr->initialization = NONE;
|
||||
|
||||
*element = el_ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a DECL_MEMBER list.
|
||||
*/
|
||||
free_decl_list(element)
|
||||
DECL_MEMBER *element;
|
||||
{
|
||||
DECL_MEMBER *el_ptr;
|
||||
|
||||
while (element) {
|
||||
if (element->name_list)
|
||||
free_var_list(element->name_list);
|
||||
if (element->literal)
|
||||
free((char *) element->literal);
|
||||
if (element->array_bound)
|
||||
free((char *) element->array_bound);
|
||||
if (element->type)
|
||||
free((char *) element->type);
|
||||
if (element->struct_list)
|
||||
free_decl_list(element->struct_list);
|
||||
if (element->at_ptr)
|
||||
free(element->at_ptr);
|
||||
|
||||
el_ptr = element->next_member;
|
||||
free((char *) element);
|
||||
element = el_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Malloc space for a procedure parameter
|
||||
*/
|
||||
get_param_ptr(param)
|
||||
PARAM_LIST **param;
|
||||
{
|
||||
*param = (PARAM_LIST *) get_mem(sizeof(PARAM_LIST));
|
||||
(*param)->next_param = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free parameter list
|
||||
*/
|
||||
free_param_list(param_list)
|
||||
PARAM_LIST *param_list;
|
||||
{
|
||||
PARAM_LIST *param_ptr;
|
||||
|
||||
while (param_list) {
|
||||
param_ptr = param_list->next_param;
|
||||
free((char *) param_list);
|
||||
param_list = param_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Malloc space for a DECLARE statement
|
||||
*/
|
||||
get_decl_ptr(decl)
|
||||
DECL **decl;
|
||||
{
|
||||
*decl = (DECL *) get_mem(sizeof(DECL));
|
||||
(*decl)->decl_list = NULL;
|
||||
(*decl)->next_decl = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free DECL list
|
||||
*/
|
||||
free_decl(decl_list)
|
||||
DECL *decl_list;
|
||||
{
|
||||
DECL *decl_ptr;
|
||||
|
||||
while (decl_list) {
|
||||
decl_ptr = decl_list->next_decl;
|
||||
#ifdef FREE_DECL_TOKEN
|
||||
if (decl_list->decl_token)
|
||||
free((char *) decl_list->decl_token);
|
||||
#endif
|
||||
if (decl_list->decl_list)
|
||||
free_decl_list(decl_list->decl_list);
|
||||
free((char *) decl_list);
|
||||
decl_list = decl_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
46
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/misc.h
Normal file
46
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/misc.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Miscellaneous defines
|
||||
*/
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned char BOOLEAN;
|
||||
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* White space characters
|
||||
*/
|
||||
#define SPACE ' '
|
||||
#define TAB 9
|
||||
#define CR 13
|
||||
#define LF 10
|
||||
|
||||
/*
|
||||
* Useful defines
|
||||
*/
|
||||
#define is_a_uc_char(char) ((char >= 'A') && (char <= 'Z'))
|
||||
#define is_a_lc_char(char) ((char >= 'a') && (char <= 'z'))
|
||||
#define is_a_char(char) (((char & 0x5F) >= 'A') && ((char & 0x5F) <= 'Z'))
|
||||
#define is_a_digit(char) ((char >= '0') && (char <= '9'))
|
||||
|
||||
#define is_a_type(token) ((token->token_class == RESERVED) && \
|
||||
(token->token_type >= BYTE) && (token->token_type <= REAL))
|
||||
|
||||
#define is_white(ch) ((ch == ' ') || (ch == TAB))
|
||||
|
||||
#define NONE 0
|
||||
|
||||
char *strcat(), *strncat(), *strcpy(), *strncpy();
|
||||
#ifdef IBMPC
|
||||
int sprintf();
|
||||
#endif
|
||||
1525
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/parse.c
Normal file
1525
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
131
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/struct.h
Normal file
131
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/struct.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Format of a token returned by get_token().
|
||||
*/
|
||||
typedef struct TOKEN {
|
||||
/* Class of token (see below) */
|
||||
int token_class;
|
||||
/* Type of token (see below) */
|
||||
int token_type;
|
||||
/* Converted token name (when applicable) */
|
||||
char token_name[MAX_TOKEN_LENGTH];
|
||||
/* Pointer to start of token in text_buffer */
|
||||
char *token_start;
|
||||
/* Number of characters token_start points to */
|
||||
int token_length;
|
||||
/* Pointer to start of white space in text_buffer */
|
||||
char *white_space_start;
|
||||
/* Pointer to char after end of white space in text_buffer */
|
||||
char *white_space_end;
|
||||
#ifdef LINKED_TOKENS
|
||||
/* Pointer for use in linked list */
|
||||
struct TOKEN *next_token;
|
||||
#endif
|
||||
} TOKEN;
|
||||
|
||||
/*
|
||||
* Format of a procedure parameter list
|
||||
*/
|
||||
typedef struct PARAM_LIST {
|
||||
/* Parameter name */
|
||||
TOKEN param;
|
||||
/* Pointer for use in linked list */
|
||||
struct PARAM_LIST *next_param;
|
||||
} PARAM_LIST;
|
||||
|
||||
/*
|
||||
* Format of a variable in a DECLARE statement.
|
||||
*/
|
||||
typedef struct DECL_ID {
|
||||
/* Variable name */
|
||||
TOKEN *name;
|
||||
/* BASED identifier token */
|
||||
TOKEN *based_name;
|
||||
/* If declared AT in another module */
|
||||
BOOLEAN is_ext_at;
|
||||
/* Pointer for use in linked list */
|
||||
struct DECL_ID *next_var;
|
||||
} DECL_ID;
|
||||
|
||||
/*
|
||||
* Format of an element in a DECLARE statement.
|
||||
*/
|
||||
typedef struct DECL_MEMBER {
|
||||
/* Linked list of identifiers of designated type */
|
||||
DECL_ID *name_list;
|
||||
/* LITERALLY string */
|
||||
char *literal;
|
||||
#ifdef PARSE_LITERALS
|
||||
/* Parsed LITERAL token */
|
||||
TOKEN *literal_token;
|
||||
#endif
|
||||
/* Array bound token */
|
||||
TOKEN *array_bound;
|
||||
/* Type of variable (INTEGER, WORD, LABEL, LITERALLY, etc.) */
|
||||
TOKEN *type;
|
||||
/* Attributes (NONE, EXTERNAL or PUBLIC) */
|
||||
int attributes;
|
||||
/* Initialization attribute (NONE, INITIAL or DATA) */
|
||||
/* If PROCEDURE, DATA if has parameters */
|
||||
int initialization;
|
||||
/* Pointer to linked list of structure elements */
|
||||
struct DECL_MEMBER *struct_list;
|
||||
/* Pointer to parsed AT expression */
|
||||
char *at_ptr;
|
||||
/* Pointer in text_buffer to start of INITIAL/DATA values */
|
||||
char *init_ptr;
|
||||
/* Pointer for use in linked list */
|
||||
struct DECL_MEMBER *next_member;
|
||||
} DECL_MEMBER;
|
||||
|
||||
/*
|
||||
* Format of a DECLARE statement.
|
||||
*/
|
||||
typedef struct DECL {
|
||||
/* DECLARE token */
|
||||
TOKEN *decl_token;
|
||||
/* Linked list of DECL_MEMBERs */
|
||||
DECL_MEMBER *decl_list;
|
||||
/* Pointer for use in linked list */
|
||||
struct DECL *next_decl;
|
||||
} DECL;
|
||||
|
||||
/*
|
||||
* Format of a context element
|
||||
*/
|
||||
typedef struct CONTEXT {
|
||||
/* Type of context (MODULE, PROCEDURE or DO) */
|
||||
int context_type;
|
||||
/* Name of module or procedure */
|
||||
TOKEN *context_name;
|
||||
/* Pointer to linked list of declaration members */
|
||||
DECL_MEMBER *decl_head;
|
||||
/* Pointer for use in linked list */
|
||||
struct CONTEXT *next_context;
|
||||
} CONTEXT;
|
||||
|
||||
|
||||
/*
|
||||
* Format of a PL/M identifier equivalent
|
||||
*/
|
||||
typedef struct {
|
||||
char *id_name, *new_id;
|
||||
} CVT_ID;
|
||||
|
||||
|
||||
/*
|
||||
* Format of a PL/M reserved word
|
||||
*/
|
||||
typedef struct {
|
||||
char *name;
|
||||
int token;
|
||||
} RESERVED_WORD;
|
||||
|
||||
/*
|
||||
* Format of a PL/M reserved operator
|
||||
*/
|
||||
typedef struct {
|
||||
char *operator;
|
||||
char *cvt_operator;
|
||||
int name;
|
||||
} RESERVED_OPERATOR;
|
||||
|
||||
26
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/test.c.out
Normal file
26
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/test.c.out
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
|
||||
extern farp();
|
||||
|
||||
|
||||
slug()
|
||||
{
|
||||
void *ptr;
|
||||
short i;
|
||||
short **iptr = (short **) &ptr;
|
||||
float j;
|
||||
float k;
|
||||
float l;
|
||||
WORD mqaFOO;
|
||||
DWORD fooBAR;
|
||||
|
||||
ptr = (void *) &i;
|
||||
(**iptr) = 72;
|
||||
iptfil();
|
||||
setinterrput(0, farp);
|
||||
signal(abs(i), (short) (i));
|
||||
j = (float) ((short) (i));
|
||||
|
||||
} /* slug */
|
||||
|
||||
|
||||
25
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/test.plm
Normal file
25
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/test.plm
Normal file
@@ -0,0 +1,25 @@
|
||||
FOO: DO;
|
||||
|
||||
FARP: PROCEDURE EXTERNAL;
|
||||
END;
|
||||
|
||||
SLUG :PROCEDURE;
|
||||
DECLARE PTR POINTER;
|
||||
DECLARE I INTEGER;
|
||||
DECLARE IPTR BASED PTR INTEGER;
|
||||
DECLARE J REAL;
|
||||
declare k real;
|
||||
declare l REAL;
|
||||
declare mqaFOO WORD;
|
||||
declare FOObar DWORD;
|
||||
|
||||
PTR = @I;
|
||||
IPTR = 72;
|
||||
CALL IPTFIL;
|
||||
CALL SET$INTERRPUT(0, FARP);
|
||||
CALL SET$INTERRUPT(IABS(I), FIX(I));
|
||||
J = FLOAT(FIX(I));
|
||||
|
||||
END SLUG;
|
||||
END FOO;
|
||||
|
||||
191
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/tkn_defs.h
Normal file
191
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/tkn_defs.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Reserved word list
|
||||
*/
|
||||
RESERVED_WORD reserved_words[] = {
|
||||
|
||||
/* Statements */
|
||||
"DECLARE", DECLARE,
|
||||
"DO", DO,
|
||||
"END", END,
|
||||
"IF", IF,
|
||||
"THEN", THEN,
|
||||
"ELSE", ELSE,
|
||||
"GOTO", GOTO,
|
||||
"GO", GO,
|
||||
"CALL", CALL,
|
||||
"RETURN", RETURN,
|
||||
"DISABLE", DISABLE,
|
||||
"ENABLE", ENABLE,
|
||||
"OUTPUT", OUTPUT,
|
||||
"OUTWORD", OUTWORD,
|
||||
"OUTHWORD", OUTHWORD,
|
||||
|
||||
/* Operators */
|
||||
"AND", AND,
|
||||
"OR", OR,
|
||||
"XOR", XOR,
|
||||
"NOT", NOT,
|
||||
"MOD", MOD,
|
||||
"PLUS", PLUS,
|
||||
"MINUS", MINUS,
|
||||
|
||||
/* DO options */
|
||||
"CASE", CASE,
|
||||
"WHILE", WHILE,
|
||||
"TO", TO,
|
||||
"BY", BY,
|
||||
|
||||
/* DECLARE types */
|
||||
"BYTE", BYTE,
|
||||
"WORD", WORD,
|
||||
"DWORD", DWORD,
|
||||
"INTEGER", INTEGER,
|
||||
"REAL", REAL,
|
||||
"SELECTOR", SELECTOR,
|
||||
"ADDRESS", ADDRESS,
|
||||
"STRUCTURE", STRUCTURE,
|
||||
"LABEL", LABEL,
|
||||
"POINTER", POINTER,
|
||||
"BASED", BASED,
|
||||
"LITERALLY", LITERALLY,
|
||||
|
||||
/* DECLARE options */
|
||||
"DATA", DATA,
|
||||
"EXTERNAL", EXTERNAL,
|
||||
"INITIAL", INITIAL,
|
||||
"PUBLIC", PUBLIC,
|
||||
"AT", AT,
|
||||
|
||||
/* Misc reserved words */
|
||||
"PROCEDURE", PROCEDURE,
|
||||
"REENTRANT", REENTRANT,
|
||||
"INTERRUPT", INTERRUPT,
|
||||
|
||||
/* End of list */
|
||||
"", END_OF_FILE
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Operator list
|
||||
*/
|
||||
RESERVED_OPERATOR reserved_operators[] = {
|
||||
"+", "+", PLUS,
|
||||
"-", "-", MINUS,
|
||||
"*", "*", TIMES,
|
||||
"/", "/", DIVIDE,
|
||||
"<>", "!=", NOT_EQUAL,
|
||||
"<=", "<=", LESS_EQUAL,
|
||||
">=", ">=", GREATER_EQUAL,
|
||||
"<", "<", LESS,
|
||||
">", ">", GREATER,
|
||||
"=", "=", EQUAL,
|
||||
":=", "=", EQUATE,
|
||||
"@", "&", AT_OP,
|
||||
"", "", END_OF_FILE
|
||||
};
|
||||
|
||||
/*
|
||||
* Control directives list
|
||||
*/
|
||||
RESERVED_WORD control_directives[] = {
|
||||
#ifdef USE_ALL_CONTROLS
|
||||
"CODE", C_CODE,
|
||||
"CO", C_CODE,
|
||||
"NOCODE", C_NOCODE,
|
||||
"NOCO", C_NOCODE,
|
||||
"COND", C_COND,
|
||||
"NOCOND", C_NOCOND,
|
||||
"DEBUG", C_DEBUG,
|
||||
"DB", C_DEBUG,
|
||||
"NODEBUG", C_NODEBUG,
|
||||
"NODB", C_NODEBUG,
|
||||
"EJECT", C_EJECT,
|
||||
"EJ", C_EJECT,
|
||||
#endif
|
||||
"IF", C_IF,
|
||||
"ELSEIF", C_ELSEIF,
|
||||
"ELSE", C_ELSE,
|
||||
"ENDIF", C_ENDIF,
|
||||
"INCLUDE", C_INCLUDE,
|
||||
"IC", C_INCLUDE,
|
||||
#ifdef USE_ALL_CONTROLS
|
||||
"INTERFACE", C_INTERFACE,
|
||||
"ITF", C_INTERFACE,
|
||||
"LEFTMARGIN", C_LEFTMARGIN,
|
||||
"LM", C_LEFTMARGIN,
|
||||
"LIST", C_LIST,
|
||||
"LI", C_LIST,
|
||||
"NOLIST", C_NOLIST,
|
||||
"NOLI", C_NOLIST,
|
||||
"OBJECT", C_OBJECT,
|
||||
"OJ", C_OBJECT,
|
||||
"NOOBJECT", C_NOOBJECT,
|
||||
"NOOJ", C_NOOBJECT,
|
||||
"OPTIMIZE", C_OPTIMIZE,
|
||||
"OT", C_OPTIMIZE,
|
||||
"OVERFLOW", C_OVERFLOW,
|
||||
"OV", C_OVERFLOW,
|
||||
"NOOVERFLOW", C_NOOVERFLOW,
|
||||
"NOOV", C_NOOVERFLOW,
|
||||
"PAGELENGTH", C_PAGELENGTH,
|
||||
"PL", C_PAGELENGTH,
|
||||
"PAGEWIDTH", C_PAGEWIDTH,
|
||||
"PW", C_PAGEWIDTH,
|
||||
"PAGING", C_PAGING,
|
||||
"PI", C_PAGING,
|
||||
"NOPAGING", C_NOPAGING,
|
||||
"NOPI", C_NOPAGING,
|
||||
"PRINT", C_PRINT,
|
||||
"PR", C_PRINT,
|
||||
"NOPRINT", C_NOPRINT,
|
||||
"NOPR", C_NOPRINT,
|
||||
"RAM", C_RAM,
|
||||
"ROM", C_ROM,
|
||||
"SAVE", C_SAVE,
|
||||
"SA", C_SAVE,
|
||||
"RESTORE", C_RESTORE,
|
||||
"RS", C_RESTORE,
|
||||
#endif
|
||||
"SET", C_SET,
|
||||
"RESET", C_RESET,
|
||||
#ifdef USE_ALL_CONTROLS
|
||||
"SMALL", C_SMALL,
|
||||
"SM", C_SMALL,
|
||||
"COMPACT", C_COMPACT,
|
||||
"CP", C_COMPACT,
|
||||
"MEDIUM", C_MEDIUM,
|
||||
"MD", C_MEDIUM,
|
||||
"LARGE", C_LARGE,
|
||||
"LA", C_LARGE,
|
||||
"SUBTITLE", C_SUBTITLE,
|
||||
"ST", C_SUBTITLE,
|
||||
"SYMBOLS", C_SYMBOLS,
|
||||
"SB", C_SYMBOLS,
|
||||
"NOSYMBOLS", C_NOSYMBOLS,
|
||||
"NOSB", C_NOSYMBOLS,
|
||||
"TITLE", C_TITLE,
|
||||
"TT", C_TITLE,
|
||||
"TYPE", C_TYPE,
|
||||
"TY", C_TYPE,
|
||||
"NOTYPE", C_NOTYPE,
|
||||
"NOTY", C_NOTYPE,
|
||||
"XREF", C_XREF,
|
||||
"XR", C_XREF,
|
||||
"NOXREF", C_NOXREF,
|
||||
"NOXR", C_NOXREF,
|
||||
"INTVECTOR", C_INTVECTOR,
|
||||
"IV", C_INTVECTOR,
|
||||
"NOINTVECTOR", C_NOINTVECTOR,
|
||||
"NOIV", C_NOINTVECTOR,
|
||||
"MOD86", C_MOD86,
|
||||
"MOD186", C_MOD186,
|
||||
"WORD16", C_WORD16,
|
||||
"W16", C_WORD16,
|
||||
"WORD32", C_WORD32,
|
||||
"W32", C_WORD32,
|
||||
#endif
|
||||
/* End of list */
|
||||
"", END_OF_FILE
|
||||
};
|
||||
|
||||
15
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/tkn_ext.h
Normal file
15
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/tkn_ext.h
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
/*
|
||||
* Reserved word list
|
||||
*/
|
||||
extern RESERVED_WORD reserved_words[];
|
||||
|
||||
/*
|
||||
* Operator list
|
||||
*/
|
||||
extern RESERVED_OPERATOR reserved_operators[];
|
||||
|
||||
/*
|
||||
* Control directives list
|
||||
*/
|
||||
extern RESERVED_WORD control_directives[];
|
||||
478
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/token.c
Normal file
478
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/token.c
Normal file
@@ -0,0 +1,478 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "misc.h"
|
||||
#include "defs.h"
|
||||
#include "cvt.h"
|
||||
#include "struct.h"
|
||||
#include "tokens.h"
|
||||
#include "tkn_ext.h"
|
||||
|
||||
BOOLEAN parsing_literal;
|
||||
TOKEN literal_token, eof_token;
|
||||
char *lit_text_ptr;
|
||||
|
||||
extern char *text_buffer, *text_ptr;
|
||||
extern int line_count;
|
||||
extern char *line_ptr;
|
||||
extern char current_file_name[];
|
||||
|
||||
/*
|
||||
* get_token() - Fetch a token from the buffer and return type,
|
||||
* pointer and associated white space.
|
||||
*/
|
||||
get_token(token)
|
||||
TOKEN *token;
|
||||
{
|
||||
RESERVED_WORD *word_ptr;
|
||||
RESERVED_OPERATOR *op_ptr;
|
||||
char token_ch, last_token;
|
||||
char *token_name_ptr;
|
||||
char *op_name;
|
||||
BOOLEAN got_fraction;
|
||||
BOOLEAN cvt_case;
|
||||
char id[MAX_TOKEN_LENGTH], *id_ptr;
|
||||
DECL_MEMBER *decl_ptr;
|
||||
DECL_ID *decl_id;
|
||||
int token_class;
|
||||
char *cvt_ptr;
|
||||
TOKEN *token_ptr;
|
||||
|
||||
/* Point to start of white space (if any) */
|
||||
token->white_space_start = text_ptr;
|
||||
token->white_space_end = text_ptr;
|
||||
|
||||
/* Get first character */
|
||||
token_ch = *text_ptr++;
|
||||
|
||||
/* Check for white space */
|
||||
while ((token_ch == SPACE) || (token_ch == TAB) || (token_ch == CR) ||
|
||||
(token_ch == LF) || (token_ch == '$') ||
|
||||
((token_ch == '/') && (*text_ptr == '*'))) {
|
||||
|
||||
if (token_ch == '$') {
|
||||
/* Check for a control directive */
|
||||
if ((text_ptr - 1 == text_buffer) ||
|
||||
(*(text_ptr - 2) == '\n')) {
|
||||
out_pre_white(token);
|
||||
parse_control();
|
||||
|
||||
/* Reset start of white space */
|
||||
token->white_space_start = text_ptr;
|
||||
token->white_space_end = text_ptr;
|
||||
} else {
|
||||
parse_error("Illegal character");
|
||||
return ERROR;
|
||||
}
|
||||
} else {
|
||||
|
||||
*(token->white_space_end++) = token_ch;
|
||||
|
||||
if (token_ch == LF) {
|
||||
/* Increment input line count */
|
||||
line_count++;
|
||||
/* Point to start of line */
|
||||
line_ptr = text_ptr;
|
||||
} else
|
||||
|
||||
if (token_ch == '/') {
|
||||
/* Comment - search to end */
|
||||
/* Add '*' of comment */
|
||||
token_ch = *(token->white_space_end++) = *text_ptr++;
|
||||
|
||||
do {
|
||||
last_token = token_ch;
|
||||
token_ch = *(token->white_space_end++) = *text_ptr++;
|
||||
if (token_ch == LF) {
|
||||
/* Increment input line count */
|
||||
line_count++;
|
||||
/* Point to start of line */
|
||||
line_ptr = text_ptr;
|
||||
}
|
||||
} while ((token_ch != '/') || (last_token != '*'));
|
||||
}
|
||||
}
|
||||
|
||||
token_ch = *text_ptr++;
|
||||
}
|
||||
|
||||
|
||||
/* Point to start of current token */
|
||||
token->token_start = text_ptr - 1;
|
||||
/* Point to start of converted token */
|
||||
token_name_ptr = token->token_name;
|
||||
|
||||
if (is_a_char(token_ch)) {
|
||||
/* Process identifier */
|
||||
#ifdef CONVERT_CASE
|
||||
/* Convert identifiers starting with an */
|
||||
/* upper-case character to opposite case. */
|
||||
cvt_case = is_a_uc_char(token_ch);
|
||||
#else
|
||||
cvt_case = FALSE;
|
||||
#endif
|
||||
while (TRUE) {
|
||||
if (is_a_char(token_ch)) {
|
||||
if (cvt_case) {
|
||||
if (is_a_uc_char(token_ch))
|
||||
/* Convert to lower-case character */
|
||||
*token_name_ptr++ = token_ch + ' ';
|
||||
else
|
||||
|
||||
/* Convert to upper-case character */
|
||||
*token_name_ptr++ = token_ch - ' ';
|
||||
} else
|
||||
*token_name_ptr++ = token_ch;
|
||||
} else
|
||||
|
||||
if (is_a_digit(token_ch))
|
||||
*token_name_ptr++ = token_ch;
|
||||
else
|
||||
|
||||
if (token_ch == '_')
|
||||
*token_name_ptr++ = token_ch;
|
||||
else
|
||||
|
||||
if (token_ch == '$')
|
||||
#ifdef CONVERT_DOLLAR
|
||||
*token_name_ptr++ = CONVERT_DOLLAR;
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
else
|
||||
break;
|
||||
|
||||
token_ch = *text_ptr++;
|
||||
}
|
||||
|
||||
|
||||
/* Mark end of token */
|
||||
text_ptr--;
|
||||
token->token_length = text_ptr - token->token_start;
|
||||
*token_name_ptr = '\0';
|
||||
|
||||
/* Get a copy of identifier */
|
||||
(void) strcpy(id, token->token_name);
|
||||
/* If lower-case, convert to upper case for comparison */
|
||||
if (is_a_lc_char(*id)) {
|
||||
for (id_ptr = id; *id_ptr; id_ptr++)
|
||||
if (is_a_lc_char(*id_ptr))
|
||||
*id_ptr -= ' ';
|
||||
}
|
||||
|
||||
/* Check for reserved word */
|
||||
for (word_ptr = &reserved_words[0]; word_ptr->token != END_OF_FILE;
|
||||
word_ptr++)
|
||||
{
|
||||
if (!strcmp(word_ptr->name, id)) {
|
||||
|
||||
token->token_type = word_ptr->token;
|
||||
|
||||
/* Check for reserved operator */
|
||||
switch (token->token_type) {
|
||||
|
||||
case AND :
|
||||
op_name = AND_OP;
|
||||
break;
|
||||
|
||||
case OR :
|
||||
op_name = OR_OP;
|
||||
break;
|
||||
|
||||
case NOT :
|
||||
op_name = NOT_OP;
|
||||
break;
|
||||
|
||||
case XOR :
|
||||
op_name = "^";
|
||||
break;
|
||||
|
||||
case MOD :
|
||||
op_name = "%";
|
||||
break;
|
||||
|
||||
case PLUS :
|
||||
parse_error("Cannot convert PLUS operator");
|
||||
token->token_class = token->token_type = ERROR;
|
||||
return ERROR;
|
||||
|
||||
case MINUS :
|
||||
parse_error("Cannot convert MINUS operator");
|
||||
token->token_class = token->token_type = ERROR;
|
||||
return ERROR;
|
||||
|
||||
default :
|
||||
/* Must not be an operator! */
|
||||
token->token_class = RESERVED;
|
||||
return RESERVED;
|
||||
}
|
||||
|
||||
/* Switch to appropriate operator */
|
||||
(void) strcpy(token->token_name, op_name);
|
||||
token->token_class = OPERATOR;
|
||||
return OPERATOR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not a reserved word - must be an identifier */
|
||||
token->token_class = token->token_type = IDENTIFIER;
|
||||
|
||||
/* Check for a literal */
|
||||
if (!parsing_literal && find_symbol(token, &decl_ptr, &decl_id) &&
|
||||
(decl_ptr->type->token_type == LITERALLY)) {
|
||||
#ifdef CONVERT_CASE
|
||||
/* Convert case of literal */
|
||||
for (cvt_ptr = token->token_name; *cvt_ptr;
|
||||
cvt_ptr++) {
|
||||
if (is_a_uc_char(*cvt_ptr))
|
||||
*cvt_ptr += 32;
|
||||
else
|
||||
if (is_a_lc_char(*cvt_ptr))
|
||||
*cvt_ptr -= 32;
|
||||
}
|
||||
#endif
|
||||
#ifdef PARSE_LITERALS
|
||||
/* Yes - Has literal been parsed? */
|
||||
if (decl_ptr->literal_token) {
|
||||
/* Yes - return parsed literal token */
|
||||
/* with token_name set to literal name */
|
||||
token_ptr = decl_ptr->literal_token;
|
||||
token->token_class = token_ptr->token_class;
|
||||
token->token_type = token_ptr->token_type;
|
||||
return token->token_class;
|
||||
}
|
||||
#endif
|
||||
/* Is literal a single token? */
|
||||
lit_text_ptr = text_ptr;
|
||||
text_ptr = decl_ptr->literal;
|
||||
token_class = get_token(&literal_token);
|
||||
if (get_token(&eof_token) == END_OF_FILE) {
|
||||
/* Yes - return single token with */
|
||||
/* token_name set to literal name */
|
||||
token->token_class = token_class;
|
||||
token->token_type = literal_token.token_type;
|
||||
text_ptr = lit_text_ptr;
|
||||
parsing_literal = FALSE;
|
||||
return token->token_class;
|
||||
}
|
||||
|
||||
/* No - parse complex literal and replace */
|
||||
/* Use of literal declaration */
|
||||
parsing_literal = TRUE;
|
||||
text_ptr = lit_text_ptr;
|
||||
parse_warning("Literal expanded");
|
||||
text_ptr = decl_ptr->literal;
|
||||
return get_token(token);
|
||||
}
|
||||
|
||||
return IDENTIFIER;
|
||||
} else
|
||||
|
||||
if (is_a_digit(token_ch)) {
|
||||
/* Process number */
|
||||
/* Flag not a floating point number */
|
||||
got_fraction = FALSE;
|
||||
|
||||
while (TRUE) {
|
||||
if (is_a_digit(token_ch))
|
||||
*token_name_ptr++ = token_ch;
|
||||
else
|
||||
|
||||
if (token_ch == '.') {
|
||||
got_fraction = TRUE;
|
||||
*token_name_ptr++ = token_ch;
|
||||
} else
|
||||
|
||||
if ((token_ch == 'E') && got_fraction) {
|
||||
/* Process exponent */
|
||||
*token_name_ptr++ = token_ch;
|
||||
/* Signed exponent? */
|
||||
if ((*text_ptr != '+') && (*text_ptr != '-')) {
|
||||
/* No - default to + exponent */
|
||||
*token_name_ptr++ = '+';
|
||||
} else {
|
||||
/* Yes - add sign */
|
||||
token_ch = *text_ptr++;
|
||||
*token_name_ptr++ = token_ch;
|
||||
}
|
||||
} else
|
||||
|
||||
/* Assume it's a hex char or constant designator */
|
||||
if (is_a_char(token_ch))
|
||||
*token_name_ptr++ = token_ch;
|
||||
else
|
||||
|
||||
if (token_ch != '$')
|
||||
break;
|
||||
|
||||
token_ch = *text_ptr++;
|
||||
}
|
||||
|
||||
/* Point to last character in constant */
|
||||
token_name_ptr--;
|
||||
token_ch = *token_name_ptr;
|
||||
|
||||
if (got_fraction) {
|
||||
/* Floating point - add suffix */
|
||||
*++token_name_ptr = 'F';
|
||||
/* Mark end of token */
|
||||
*++token_name_ptr = '\0';
|
||||
} else
|
||||
|
||||
if (token_ch == 'B') {
|
||||
parse_error("Binary constant");
|
||||
token->token_class = token->token_type = ERROR;
|
||||
return ERROR;
|
||||
} else
|
||||
|
||||
if ((token_ch == 'O') || (token_ch == 'Q')) {
|
||||
/* Octal constant */
|
||||
/* Mark end of token */
|
||||
*token_name_ptr++ = '\0';
|
||||
/* Move constant up 1 character */
|
||||
while (token_name_ptr != token->token_name) {
|
||||
*token_name_ptr = *(token_name_ptr - 1);
|
||||
token_name_ptr--;
|
||||
}
|
||||
|
||||
/* Make a C octal constant */
|
||||
*token_name_ptr = '0';
|
||||
} else
|
||||
|
||||
if (token_ch == 'H') {
|
||||
/* Hex constant */
|
||||
/* Mark end of token */
|
||||
*token_name_ptr++ = '\0';
|
||||
token_name_ptr++;
|
||||
/* Move constant up 2 characters */
|
||||
while (token_name_ptr != (token->token_name + 1)) {
|
||||
*token_name_ptr = *(token_name_ptr - 2);
|
||||
token_name_ptr--;
|
||||
}
|
||||
|
||||
/* Make a C hex constant */
|
||||
*token_name_ptr-- = 'x';
|
||||
*token_name_ptr = '0';
|
||||
} else
|
||||
|
||||
if (token_ch == 'D')
|
||||
/* Decimal constant - ignore 'D' */
|
||||
*token_name_ptr = '\0';
|
||||
else
|
||||
/* Regular constant */
|
||||
*++token_name_ptr = '\0';
|
||||
|
||||
/* Mark end of token */
|
||||
text_ptr--;
|
||||
token->token_length = text_ptr - token->token_start;
|
||||
|
||||
token->token_class = token->token_type = NUMERIC;
|
||||
return NUMERIC;
|
||||
} else {
|
||||
|
||||
/* Check for operator */
|
||||
for (op_ptr = &reserved_operators[0]; op_ptr->name != END_OF_FILE;
|
||||
op_ptr++) {
|
||||
token->token_length = strlen(op_ptr->operator);
|
||||
if (!strncmp(text_ptr - 1, op_ptr->operator,
|
||||
token->token_length)) {
|
||||
/* Found operator */
|
||||
/* Save converted type */
|
||||
(void) strcpy(token->token_name, op_ptr->cvt_operator);
|
||||
token->token_type = op_ptr->name;
|
||||
/* Point past operator */
|
||||
text_ptr += token->token_length - 1;
|
||||
|
||||
token->token_class = OPERATOR;
|
||||
return OPERATOR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assume single character token */
|
||||
*token_name_ptr++ = token_ch;
|
||||
*token_name_ptr = '\0';
|
||||
/* Mark end of token so far */
|
||||
token->token_length = 1;
|
||||
|
||||
|
||||
switch (token_ch) {
|
||||
|
||||
case ';' :
|
||||
token->token_class = token->token_type = END_OF_LINE;
|
||||
return END_OF_LINE;
|
||||
|
||||
case ':' :
|
||||
token->token_class = token->token_type = LABEL;
|
||||
return LABEL;
|
||||
|
||||
case ',' :
|
||||
token->token_class = token->token_type = COMMA;
|
||||
return COMMA;
|
||||
|
||||
case '.' :
|
||||
token->token_class = token->token_type = PERIOD;
|
||||
return PERIOD;
|
||||
|
||||
case '(' :
|
||||
token->token_class = token->token_type = LEFT_PAREN;
|
||||
return LEFT_PAREN;
|
||||
|
||||
case ')' :
|
||||
token->token_class = token->token_type = RIGHT_PAREN;
|
||||
return RIGHT_PAREN;
|
||||
|
||||
case '\'' :
|
||||
/* String constant */
|
||||
token_name_ptr--;
|
||||
while (1) {
|
||||
if (*text_ptr == '\'') {
|
||||
if ((*(text_ptr + 1) == '\''))
|
||||
text_ptr++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
*token_name_ptr++ = *text_ptr++;
|
||||
}
|
||||
|
||||
text_ptr++;
|
||||
*token_name_ptr++ = '\0';
|
||||
token->token_length = strlen(token->token_name);
|
||||
|
||||
token->token_class = token->token_type = STRING;
|
||||
return STRING;
|
||||
|
||||
case 0:
|
||||
if (parsing_literal) {
|
||||
/* Done parsing literal - */
|
||||
/* Switch back to text_ptr */
|
||||
parsing_literal = FALSE;
|
||||
text_ptr = lit_text_ptr;
|
||||
return get_token(token);
|
||||
}
|
||||
token->token_class = token->token_type = END_OF_FILE;
|
||||
return END_OF_FILE;
|
||||
|
||||
default:
|
||||
parse_error("Illegal character");
|
||||
/* Eat the evidence */
|
||||
token->token_name[0] = '\0';
|
||||
token->token_class = token->token_type = ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy source token to destination token
|
||||
*/
|
||||
token_copy(src, dest)
|
||||
TOKEN *src, *dest;
|
||||
{
|
||||
dest->token_class = src->token_class;
|
||||
dest->token_type = src->token_type;
|
||||
(void) strcpy(dest->token_name, src->token_name);
|
||||
dest->token_start = src->token_start;
|
||||
dest->token_length = src->token_length;
|
||||
dest->white_space_start = src->white_space_start;
|
||||
dest->white_space_end = src->white_space_end;
|
||||
}
|
||||
|
||||
151
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/tokens.h
Normal file
151
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/tokens.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/**************************
|
||||
* Token classes
|
||||
*************************/
|
||||
#define END_OF_FILE 0
|
||||
#define RESERVED 1
|
||||
#define IDENTIFIER 2
|
||||
#define NUMERIC 3
|
||||
#define OPERATOR 4
|
||||
#define STRING 5
|
||||
#define LABEL 6
|
||||
#define END_OF_LINE 7
|
||||
#define COMMA 8
|
||||
#define PERIOD 9
|
||||
#define LEFT_PAREN 10
|
||||
#define RIGHT_PAREN 11
|
||||
#define SUBSCRIPT 12
|
||||
#define MODULE 13
|
||||
#define ERROR 19
|
||||
|
||||
|
||||
/**************************
|
||||
* Token types
|
||||
*************************/
|
||||
/*
|
||||
* Operators
|
||||
*/
|
||||
#define PLUS 20 /* + */
|
||||
#define MINUS 21 /* - */
|
||||
#define TIMES 22 /* * */
|
||||
#define DIVIDE 23 /* / */
|
||||
#define NOT_EQUAL 24 /* <> */
|
||||
#define LESS_EQUAL 25 /* <= */
|
||||
#define GREATER_EQUAL 26 /* >= */
|
||||
#define LESS 27 /* < */
|
||||
#define GREATER 28 /* > */
|
||||
#define EQUAL 29 /* = */
|
||||
#define EQUATE 30 /* := */
|
||||
#define COLON 31 /* : */
|
||||
#define AT_OP 32 /* @ */
|
||||
|
||||
/*
|
||||
* Reserved word values
|
||||
*/
|
||||
/* Statements */
|
||||
#define DECLARE 40
|
||||
#define DO 41
|
||||
#define END 42
|
||||
#define IF 43
|
||||
#define THEN 44
|
||||
#define ELSE 45
|
||||
#define GOTO 46
|
||||
#define GO 47
|
||||
#define CALL 48
|
||||
#define RETURN 49
|
||||
#define DISABLE 50
|
||||
#define ENABLE 51
|
||||
#define OUTPUT 52
|
||||
#define OUTWORD 53
|
||||
#define OUTHWORD 54
|
||||
|
||||
/* Operators */
|
||||
#define AND 60
|
||||
#define OR 61
|
||||
#define XOR 62
|
||||
#define NOT 63
|
||||
#define MOD 64
|
||||
|
||||
/* DO options */
|
||||
#define CASE 70
|
||||
#define WHILE 71
|
||||
#define TO 72
|
||||
#define BY 73
|
||||
|
||||
/* DECLARE types */
|
||||
#define BYTE 80
|
||||
#define WORD 81
|
||||
#define DWORD 82
|
||||
#define INTEGER 83
|
||||
#define REAL 84
|
||||
#define ADDRESS 85
|
||||
#define SELECTOR 86
|
||||
#define POINTER 87
|
||||
#define STRUCTURE 88
|
||||
|
||||
/* DECLARE options */
|
||||
#define BASED 90
|
||||
#define LITERALLY 91
|
||||
#define DATA 92
|
||||
#define EXTERNAL 93
|
||||
#define INITIAL 94
|
||||
#define PUBLIC 95
|
||||
#define AT 96
|
||||
|
||||
/* Misc reserved words */
|
||||
#define PROCEDURE 101
|
||||
#define REENTRANT 102
|
||||
#define INTERRUPT 103
|
||||
|
||||
/* Control Directives */
|
||||
#define C_CODE 200
|
||||
#define C_NOCODE 201
|
||||
#define C_COND 202
|
||||
#define C_NOCOND 203
|
||||
#define C_DEBUG 204
|
||||
#define C_NODEBUG 205
|
||||
#define C_EJECT 206
|
||||
#define C_IF 207
|
||||
#define C_ELSEIF 208
|
||||
#define C_ELSE 209
|
||||
#define C_ENDIF 210
|
||||
#define C_INCLUDE 211
|
||||
#define C_INTERFACE 212
|
||||
#define C_LEFTMARGIN 213
|
||||
#define C_LIST 214
|
||||
#define C_NOLIST 215
|
||||
#define C_OBJECT 216
|
||||
#define C_NOOBJECT 217
|
||||
#define C_OPTIMIZE 218
|
||||
#define C_OVERFLOW 219
|
||||
#define C_NOOVERFLOW 220
|
||||
#define C_PAGELENGTH 221
|
||||
#define C_PAGEWIDTH 222
|
||||
#define C_PAGING 223
|
||||
#define C_NOPAGING 224
|
||||
#define C_PRINT 225
|
||||
#define C_NOPRINT 226
|
||||
#define C_RAM 227
|
||||
#define C_ROM 228
|
||||
#define C_SAVE 229
|
||||
#define C_RESTORE 230
|
||||
#define C_SET 231
|
||||
#define C_RESET 232
|
||||
#define C_SMALL 233
|
||||
#define C_COMPACT 234
|
||||
#define C_MEDIUM 235
|
||||
#define C_LARGE 236
|
||||
#define C_SUBTITLE 237
|
||||
#define C_SYMBOLS 238
|
||||
#define C_NOSYMBOLS 239
|
||||
#define C_TITLE 240
|
||||
#define C_TYPE 241
|
||||
#define C_NOTYPE 242
|
||||
#define C_XREF 243
|
||||
#define C_NOXREF 244
|
||||
#define C_INTVECTOR 245
|
||||
#define C_NOINTVECTOR 246
|
||||
#define C_MOD86 247
|
||||
#define C_MOD186 248
|
||||
#define C_WORD16 249
|
||||
#define C_WORD32 250
|
||||
|
||||
6
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/typedefs.c
Normal file
6
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/typedefs.c
Normal file
@@ -0,0 +1,6 @@
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned int DWORD;
|
||||
typedef short INTEGER;
|
||||
typedef float REAL;
|
||||
|
||||
1
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/version.c
Normal file
1
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/plm2c/version.c
Normal file
@@ -0,0 +1 @@
|
||||
char version[] = "Version 1.02 (Alpha)";
|
||||
Reference in New Issue
Block a user