ack/lang/pc/comp/readwrite.c

483 lines
9.2 KiB
C
Raw Normal View History

1988-10-26 15:21:11 +00:00
/* R E A D ( L N ) & W R I T E ( L N ) */
#include "debug.h"
#include <assert.h>
#include <em.h>
#include "LLlex.h"
#include "def.h"
#include "main.h"
1989-05-03 10:30:22 +00:00
#include "misc.h"
1988-10-26 15:21:11 +00:00
#include "node.h"
#include "scope.h"
#include "type.h"
1989-05-03 10:30:22 +00:00
/* DEBUG */
#include "idf.h"
1991-04-25 16:26:11 +00:00
extern char *sprint();
1988-10-26 15:21:11 +00:00
ChkRead(arg)
register struct node *arg;
{
struct node *file;
char *name = "read";
1989-05-03 10:30:22 +00:00
char *message, buff[80];
extern char *ChkAllowedVar();
1988-10-26 15:21:11 +00:00
assert(arg);
assert(arg->nd_symb == ',');
if( arg->nd_left->nd_type->tp_fund == T_FILE ) {
file = arg->nd_left;
arg = arg->nd_right;
if( !arg ) {
error("\"%s\": variable-access expected", name);
return;
}
MarkUsed(file);
1988-10-26 15:21:11 +00:00
}
else if( !(file = ChkStdInOut(name, 0)) )
return;
while( arg ) {
assert(arg->nd_symb == ',');
if( file->nd_type != text_type ) {
/* real var & file of integer */
if( !TstAssCompat(arg->nd_left->nd_type,
BaseType(file->nd_type->next)) ) {
node_error(arg->nd_left,
"\"%s\": illegal parameter type",name);
return;
}
1989-05-03 10:30:22 +00:00
else if( (BaseType(file->nd_type->next) == long_type
&& arg->nd_left->nd_type == int_type)
||
(BaseType(file->nd_type->next) == int_type
&& arg->nd_left->nd_type == long_type) ) {
if( int_size != long_size ) {
node_error(arg->nd_left,
"\"%s\": longs and integers have different sizes",name);
return;
}
else node_warning(arg->nd_left,
"\"%s\": mixture of longs and integers", name);
}
1988-10-26 15:21:11 +00:00
}
else if( !(BaseType(arg->nd_left->nd_type)->tp_fund &
( T_CHAR | T_NUMERIC )) ) {
node_error(arg->nd_left,
"\"%s\": illegal parameter type",name);
return;
}
1989-05-03 10:30:22 +00:00
message = ChkAllowedVar(arg->nd_left, 1);
if( message ) {
sprint(buff,"\"%%s\": %s can't be a variable parameter",
message);
node_error(arg->nd_left, buff, name);
return;
}
1988-10-26 15:21:11 +00:00
CodeRead(file, arg->nd_left);
arg = arg->nd_right;
}
}
ChkReadln(arg)
register struct node *arg;
{
struct node *file;
char *name = "readln";
1989-05-03 10:30:22 +00:00
char *message, buff[80];
extern char *ChkAllowedVar();
1988-10-26 15:21:11 +00:00
if( !arg ) {
if( !(file = ChkStdInOut(name, 0)) )
return;
else {
CodeReadln(file);
return;
}
}
assert(arg->nd_symb == ',');
if( arg->nd_left->nd_type->tp_fund == T_FILE ) {
if( arg->nd_left->nd_type != text_type ) {
node_error(arg->nd_left,
"\"%s\": textfile expected", name);
return;
}
else {
file = arg->nd_left;
arg = arg->nd_right;
MarkUsed(file);
1988-10-26 15:21:11 +00:00
}
}
else if( !(file = ChkStdInOut(name, 0)) )
return;
while( arg ) {
assert(arg->nd_symb == ',');
if( !(BaseType(arg->nd_left->nd_type)->tp_fund &
( T_CHAR | T_NUMERIC )) ) {
node_error(arg->nd_left,
"\"%s\": illegal parameter type",name);
return;
}
1989-05-03 10:30:22 +00:00
message = ChkAllowedVar(arg->nd_left, 1);
if( message ) {
sprint(buff,"\"%%s\": %s can't be a variable parameter",
message);
node_error(arg->nd_left, buff, name);
return;
}
1988-10-26 15:21:11 +00:00
CodeRead(file, arg->nd_left);
arg = arg->nd_right;
}
CodeReadln(file);
}
ChkWrite(arg)
register struct node *arg;
{
struct node *left, *expp, *file;
char *name = "write";
assert(arg);
assert(arg->nd_symb == ',');
assert(arg->nd_left->nd_symb == ':');
left = arg->nd_left;
expp = left->nd_left;
if( expp->nd_type->tp_fund == T_FILE ) {
if( left->nd_right ) {
node_error(expp,
"\"%s\": filevariable can't have a width",name);
return;
}
file = expp;
MarkUsed(file);
1988-10-26 15:21:11 +00:00
arg = arg->nd_right;
if( !arg ) {
error("\"%s\": expression expected", name);
return;
}
}
else if( !(file = ChkStdInOut(name, 1)) )
return;
while( arg ) {
assert(arg->nd_symb == ',');
if( !ChkWriteParameter(file->nd_type, arg->nd_left, name) )
return;
CodeWrite(file, arg->nd_left);
arg = arg->nd_right;
}
}
ChkWriteln(arg)
register struct node *arg;
{
struct node *left, *expp, *file;
char *name = "writeln";
if( !arg ) {
if( !(file = ChkStdInOut(name, 1)) )
return;
else {
CodeWriteln(file);
return;
}
}
assert(arg->nd_symb == ',');
assert(arg->nd_left->nd_symb == ':');
left = arg->nd_left;
expp = left->nd_left;
if( expp->nd_type->tp_fund == T_FILE ) {
if( expp->nd_type != text_type ) {
node_error(expp, "\"%s\": textfile expected", name);
return;
}
if( left->nd_right ) {
node_error(expp,
"\"%s\": filevariable can't have a width", name);
return;
}
file = expp;
MarkUsed(file);
1988-10-26 15:21:11 +00:00
arg = arg->nd_right;
}
else if( !(file = ChkStdInOut(name, 1)) )
return;
while( arg ) {
assert(arg->nd_symb == ',');
if( !ChkWriteParameter(text_type, arg->nd_left, name) )
return;
CodeWrite(file, arg->nd_left);
arg = arg->nd_right;
}
CodeWriteln(file);
}
ChkWriteParameter(filetype, arg, name)
struct type *filetype;
struct node *arg;
char *name;
{
struct type *tp;
char *mess = "illegal write parameter";
assert(arg->nd_symb == ':');
tp = BaseType(arg->nd_left->nd_type);
if( filetype == text_type ) {
1989-05-03 10:30:22 +00:00
if( !(tp == bool_type ||
tp->tp_fund & (T_CHAR | T_NUMERIC | T_STRING) ||
IsString(tp)) ) {
1988-10-26 15:21:11 +00:00
node_error(arg->nd_left, "\"%s\": %s", name, mess);
return 0;
}
}
else {
if( !TstAssCompat(BaseType(filetype->next), tp) ) {
node_error(arg->nd_left, "\"%s\": %s", name, mess);
return 0;
}
if( arg->nd_right ) {
node_error(arg->nd_left, "\"%s\": %s", name, mess);
return 0;
}
else
return 1;
}
/* Here we have a text-file */
if( arg = arg->nd_right ) {
/* Total width */
assert(arg->nd_symb == ':');
if( BaseType(arg->nd_left->nd_type) != int_type ) {
node_error(arg->nd_left, "\"%s\": %s", name, mess);
return 0;
}
}
else
return 1;
if( arg = arg->nd_right ) {
/* Fractional Part */
assert(arg->nd_symb == ':');
if( tp != real_type ) {
node_error(arg->nd_left, "\"%s\": %s", name, mess);
return 0;
}
if( BaseType(arg->nd_left->nd_type) != int_type ) {
node_error(arg->nd_left, "\"%s\": %s", name, mess);
return 0;
}
}
return 1;
}
struct node *
ChkStdInOut(name, st_out)
char *name;
{
register struct def *df;
register struct node *nd;
1989-05-03 10:30:22 +00:00
if( !(df = lookup(str2idf(st_out ? output : input, 0),
GlobalScope, D_INUSE)) ||
!(df->df_flags & D_PROGPAR) ) {
1988-10-26 15:21:11 +00:00
error("\"%s\": standard input/output not defined", name);
return NULLNODE;
}
nd = MkLeaf(Def, &dot);
nd->nd_def = df;
nd->nd_type = df->df_type;
1989-05-03 10:30:22 +00:00
df->df_flags |= D_USED;
1988-10-26 15:21:11 +00:00
return nd;
}
CodeRead(file, arg)
register struct node *file, *arg;
{
struct type *tp = BaseType(arg->nd_type);
if( err_occurred ) return;
CodeDAddress(file);
if( file->nd_type == text_type ) {
switch( tp->tp_fund ) {
case T_CHAR:
C_cal("_rdc");
break;
case T_INTEGER:
C_cal("_rdi");
break;
1989-05-03 10:30:22 +00:00
case T_LONG:
C_cal("_rdl");
break;
1988-10-26 15:21:11 +00:00
case T_REAL:
C_cal("_rdr");
break;
default:
crash("(CodeRead)");
/*NOTREACHED*/
}
C_asp(pointer_size);
C_lfr(tp->tp_size);
RangeCheck(arg->nd_type, file->nd_type->next);
CodeDStore(arg);
}
else {
/* Keep the address of the file on the stack */
C_dup(pointer_size);
C_cal("_wdw");
C_asp(pointer_size);
C_lfr(pointer_size);
RangeCheck(arg->nd_type, file->nd_type->next);
C_loi(file->nd_type->next->tp_psize);
1989-05-03 10:30:22 +00:00
if( tp == real_type ) {
if( BaseType(file->nd_type->next) == int_type ||
BaseType(file->nd_type->next) == long_type )
Int2Real(file->nd_type->next->tp_psize);
}
1988-10-26 15:21:11 +00:00
CodeDStore(arg);
C_cal("_get");
C_asp(pointer_size);
}
}
CodeReadln(file)
struct node *file;
{
if( err_occurred ) return;
CodeDAddress(file);
C_cal("_rln");
C_asp(pointer_size);
}
CodeWrite(file, arg)
register struct node *file, *arg;
{
int width = 0;
register arith nbpars = pointer_size;
register struct node *expp = arg->nd_left;
struct node *right = arg->nd_right;
struct type *tp = BaseType(expp->nd_type);
if( err_occurred ) return;
CodeDAddress(file);
CodePExpr(expp);
if( file->nd_type == text_type ) {
1989-05-03 10:30:22 +00:00
if( tp->tp_fund & (T_ARRAY | T_STRINGCONST) ) {
1988-10-26 15:21:11 +00:00
C_loc(IsString(tp));
nbpars += pointer_size + int_size;
}
else nbpars += tp->tp_size;
if( right ) {
width = 1;
CodePExpr(right->nd_left);
nbpars += int_size;
right = right->nd_right;
}
switch( tp->tp_fund ) {
case T_ENUMERATION: /* boolean */
C_cal(width ? "_wsb" : "_wrb");
break;
case T_CHAR:
C_cal(width ? "_wsc" : "_wrc");
break;
case T_INTEGER:
C_cal(width ? "_wsi" : "_wri");
break;
1989-05-03 10:30:22 +00:00
case T_LONG:
C_cal(width ? "_wsl" : "_wrl");
break;
1988-10-26 15:21:11 +00:00
case T_REAL:
if( right ) {
CodePExpr(right->nd_left);
nbpars += int_size;
C_cal("_wrf");
}
else C_cal(width ? "_wsr" : "_wrr");
break;
case T_ARRAY:
1989-05-03 10:30:22 +00:00
case T_STRINGCONST:
1988-10-26 15:21:11 +00:00
C_cal(width ? "_wss" : "_wrs");
break;
1989-05-03 10:30:22 +00:00
case T_STRING:
C_cal(width ? "_wsz" : "_wrz");
break;
1988-10-26 15:21:11 +00:00
default:
1989-05-03 10:30:22 +00:00
crash("(CodeWrite)");
1988-10-26 15:21:11 +00:00
/*NOTREACHED*/
}
C_asp(nbpars);
}
else {
if( file->nd_type->next == real_type && tp == int_type )
1989-05-03 10:30:22 +00:00
Int2Real(int_size);
else if( file->nd_type->next == real_type && tp == long_type )
Int2Real(long_size);
1988-10-26 15:21:11 +00:00
CodeDAddress(file);
C_cal("_wdw");
C_asp(pointer_size);
C_lfr(pointer_size);
C_sti(file->nd_type->next->tp_psize);
C_cal("_put");
C_asp(pointer_size);
}
}
CodeWriteln(file)
register struct node *file;
{
if( err_occurred ) return;
CodeDAddress(file);
C_cal("_wln");
C_asp(pointer_size);
}