https://github.com/jrincayc/ucblogo-code
Revision b2227ae71f14b631a8e1c9fead6fed7f2db2f6e6 authored by Dan Malec on 13 November 2020, 01:06:03 UTC, committed by Dan Malec on 13 November 2020, 02:04:05 UTC
On Raspberry Pi (ARM), converting the int output of getc to char and then back to int results in the EOF character being represented as 255 instead of -1. This causes infinite loops when attempting to detect the end of input from the editor.
1 parent a7bd4e1
Tip revision: b2227ae71f14b631a8e1c9fead6fed7f2db2f6e6 authored by Dan Malec on 13 November 2020, 01:06:03 UTC
ISSUE-67: Pass the output of getc as int.
ISSUE-67: Pass the output of getc as int.
Tip revision: b2227ae
coms.c
/*
* coms.c program execution control module dvb
*
* Copyright (C) 1993 by the Regents of the University of California
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_WX
#define fgets wx_fgets
extern int check_wx_stop(int force_yield);
#endif
#define WANT_EVAL_REGS 1
#include <math.h>
#include "logo.h"
#include "globals.h"
#include "eval.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef ibm
#include "process.h"
#endif
#ifdef mac
#include <console.h>
#include <Events.h>
#endif
#ifdef __RZTC__
#include <time.h>
#include <controlc.h>
#include <dos.h>
#include <msmouse.h>
#endif
#ifdef HAVE_TERMIO_H
#ifdef HAVE_WX
#include <termios.h>
#else
#include <termio.h>
#endif
#else
#ifdef HAVE_SGTTY_H
#include <sgtty.h>
#endif
#endif
#ifdef __APPLE__
#include <sys/time.h>
#else
#include <time.h>
#endif
NODE *make_cont(enum labels cont, NODE *val) {
#ifdef __RZTC__
union { enum labels lll;
NODE *ppp;} cast;
#endif
NODE *retval = cons(NIL, val);
#ifdef __RZTC__
cast.lll = cont;
retval->n_car = cast.ppp;
#else
retval->n_car = (NODE *)cont;
#endif
settype(retval, CONT);
return retval;
}
NODE *loutput(NODE *arg) {
if (NOT_THROWING) {
if (ufun == NIL) {
err_logo(AT_TOPLEVEL, fun);
} else if (val_status & OUTPUT_TAIL
/* This happens if OP seen when val_status & STOP_OK */
|| !(val_status & OUTPUT_OK)) {
/* This happens on OP OP 3 */
if (didnt_output_name == NIL) didnt_output_name = fun;
if (didnt_get_output == UNBOUND) {
didnt_get_output = cons_list(0,theName(Name_output),
ufun,this_line,END_OF_LIST);
/* Not quite right; could be .maybeoutput */
didnt_output_name = fun;
}
err_logo(DIDNT_OUTPUT, NIL);
} else {
stopping_flag = OUTPUT;
output_unode = current_unode;
output_node = car(arg);
}
}
return(UNBOUND);
}
NODE *lstop(NODE *args) {
if (NOT_THROWING) {
if (ufun == NIL)
err_logo(AT_TOPLEVEL, theName(Name_stop));
else if (val_status & OUTPUT_TAIL
|| !(val_status & STOP_OK)) {
didnt_output_name = fun;
err_logo(DIDNT_OUTPUT, NIL);
} else {
stopping_flag = STOP;
output_unode = current_unode;
}
}
return(UNBOUND);
}
NODE *lthrow(NODE *arg) {
if (NOT_THROWING) {
if (isName(car(arg), Name_error)) {
if (cdr(arg) != NIL)
err_logo(USER_ERR_MESSAGE, cadr(arg));
else
err_logo(USER_ERR, UNBOUND);
} else {
stopping_flag = THROWING;
throw_node = car(arg);
if (cdr(arg) != NIL)
output_node = cadr(arg);
else
output_node = UNBOUND;
}
}
return(UNBOUND);
}
NODE *lcatch(NODE *args) {
return make_cont(catch_continuation, cons(car(args), lrun(cdr(args))));
}
int torf_arg(NODE *args) {
NODE *arg = car(args);
while (NOT_THROWING) {
if (is_list(arg)) { /* accept a list and run it */
val_status = VALUE_OK;
arg = evaluator(arg, begin_seq);
}
if (isName(arg, Name_true)) return TRUE;
if (isName(arg, Name_false)) return FALSE;
if (NOT_THROWING) arg = err_logo(BAD_DATA, arg);
}
return -1;
}
NODE *lgoto(NODE *args) {
return make_cont(goto_continuation, car(args));
}
NODE *ltag(NODE *args) {
return UNBOUND;
}
NODE *lnot(NODE *args) {
int arg = torf_arg(args);
if (NOT_THROWING) {
if (arg) return(FalseName());
else return(TrueName());
}
return(UNBOUND);
}
NODE *land(NODE *args) {
int arg;
if (args == NIL) return(TrueName());
while (NOT_THROWING) {
arg = torf_arg(args);
if (arg == FALSE)
return(FalseName());
args = cdr(args);
if (args == NIL) break;
}
if (NOT_THROWING) return(TrueName());
else return(UNBOUND);
}
NODE *lor(NODE *args) {
int arg;
if (args == NIL) return(FalseName());
while (NOT_THROWING) {
arg = torf_arg(args);
if (arg == TRUE)
return(TrueName());
args = cdr(args);
if (args == NIL) break;
}
if (NOT_THROWING) return(FalseName());
else return(UNBOUND);
}
NODE *runnable_arg(NODE *args) {
NODE *arg = car(args);
if (!aggregate(arg)) {
setcar(args, parser(arg, TRUE));
arg = car(args);
}
while (!is_list(arg) && NOT_THROWING) {
setcar(args, err_logo(BAD_DATA, arg));
arg = car(args);
}
return(arg);
}
NODE *lif(NODE *args) { /* macroized */
NODE *yes;
int pred;
if (cddr(args) != NIL) return(lifelse(args));
pred = torf_arg(args);
yes = runnable_arg(cdr(args));
if (NOT_THROWING) {
if (pred) return(yes);
return(NIL);
}
return(UNBOUND);
}
NODE *lifelse(NODE *args) { /* macroized */
NODE *yes, *no;
int pred;
pred = torf_arg(args);
yes = runnable_arg(cdr(args));
no = runnable_arg(cddr(args));
if (NOT_THROWING) {
if (pred) return(yes);
return(no);
}
return(UNBOUND);
}
NODE *lrun(NODE *args) { /* macroized */
NODE *arg = runnable_arg(args);
if (NOT_THROWING) return(arg);
return(UNBOUND);
}
NODE *lrunresult(NODE *args) {
return make_cont(runresult_continuation, lrun(args));
}
NODE *pos_int_arg(NODE *args) {
NODE *arg = car(args), *val;
FIXNUM i;
FLONUM f;
val = cnv_node_to_numnode(arg);
while ((nodetype(val) != INT || getint(val) < 0) && NOT_THROWING) {
if (nodetype(val) == FLOATT &&
fmod((f = getfloat(val)), 1.0) == 0.0 &&
f >= 0.0 && f < (FLONUM)MAXLOGOINT) {
#if HAVE_IRINT
i = irint(f);
#else
i = (FIXNUM)f;
#endif
val = make_intnode(i);
break;
}
setcar(args, err_logo(BAD_DATA, arg));
arg = car(args);
val = cnv_node_to_numnode(arg);
}
setcar(args,val);
if (nodetype(val) == INT) return(val);
return UNBOUND;
}
NODE *lrepeat(NODE *args) {
NODE *cnt, *torpt, *retval = NIL;
cnt = pos_int_arg(args);
torpt = lrun(cdr(args));
if (NOT_THROWING) {
retval = make_cont(repeat_continuation, cons(cnt,torpt));
}
return(retval);
}
NODE *lrepcount(NODE *args) {
return make_intnode(user_repcount);
}
NODE *lforever(NODE *args) {
NODE *torpt = lrun(args);
if (NOT_THROWING)
return make_cont(repeat_continuation, cons(make_intnode(-1), torpt));
return NIL;
}
NODE *ltest(NODE *args) {
int arg = torf_arg(args);
if (ufun != NIL && tailcall != 0) return UNBOUND;
if (NOT_THROWING) {
dont_fix_ift = arg+1;
}
return(UNBOUND);
}
NODE *liftrue(NODE *args) {
if (ift_iff_flag < 0)
return(err_logo(NO_TEST,NIL));
else if (ift_iff_flag > 0)
return(lrun(args));
else
return(NIL);
}
NODE *liffalse(NODE *args) {
if (ift_iff_flag < 0)
return(err_logo(NO_TEST,NIL));
else if (ift_iff_flag == 0)
return(lrun(args));
else
return(NIL);
}
void prepare_to_exit(BOOLEAN okay) {
#ifdef HAVE_WX
extern void doClose();
doClose();
wxLogoExit (0);
#endif
#ifdef mac
if (okay) {
console_options.pause_atexit = 0;
exit(0);
}
#endif
#ifndef WIN32 /* sowings */
#ifdef ibm
ltextscreen(NIL);
ibm_plain_mode();
#ifdef __RZTC__
msm_term();
zflush();
controlc_close();
#endif
#endif
#endif /* !WIN32 */
#ifdef unix
#ifndef HAVE_UNISTD_H
extern int getpid();
#endif
char ef[30];
charmode_off();
sprintf(ef, "/tmp/logo%d", (int)getpid());
unlink(ef);
#endif
}
NODE *lbye(NODE *args) {
prepare_to_exit(TRUE);
if (ufun != NIL || loadstream != stdin) exit(0);
#ifndef WIN32
if (isatty(0) && isatty(1))
#endif
lcleartext(NIL);
ndprintf(stdout, "%t\n", message_texts[THANK_YOU]);
ndprintf(stdout, "%t\n", message_texts[NICE_DAY]);
#ifdef __RZTC__
printf("\n");
#endif
#ifdef HAVE_WX
wx_leave_mainloop++;
return UNBOUND;
#else
exit(0);
return UNBOUND; /* not reached, but makes compiler happy */
#endif
}
NODE *lwait(NODE *args) {
NODE *num;
unsigned int n;
#if defined(unix) && HAVE_USLEEP
unsigned int seconds, microseconds;
#endif
#ifdef mac
long target;
extern void ProcessEvent(void);
#endif
num = pos_int_arg(args);
if (NOT_THROWING) {
/*#ifdef HAVE_WX
n = (unsigned int)getint(num) * 10; // milliseconds
wxLogoSleep(n);
return(UNBOUND);
#endif*/
#ifndef HAVE_WX
#ifdef WIN32
win32_update_text();
#else
fflush(stdout); /* csls v. 1 p. 7 */
#endif
#else
//doesn't seem to work in WX. now done in wxLogoSleep
//fflush(stdout); /* csls v. 1 p. 7 */
#endif
#if defined(__RZTC__)
zflush();
#endif
fix_turtle_shownness();
#ifdef HAVE_WX
n = (unsigned int)getint(num) * 100 / 6; // milliseconds
wxLogoSleep(n);
//check_throwing;
return(UNBOUND);
#endif
if (getint(num) > 0) {
#ifdef unix
#ifdef HAVE_USLEEP
n = (unsigned int)getint(num);
if ((seconds = n / 60))
sleep(seconds);
if ((microseconds = (n % 60) * 16667))
usleep(microseconds);
#else
n = (unsigned int)getint(num) / 60;
sleep(n);
#endif
#elif defined(__RZTC__)
usleep(getint(num) * 16667L);
#elif defined(mac)
target = getint(num)+TickCount();
while (TickCount() < target) {
if (check_throwing) break;
ProcessEvent();
}
#elif defined(_MSC_VER)
n = (unsigned int)getint(num);
while (n > 60) {
_sleep(1000);
n -= 60;
if (check_throwing) n = 0;
}
if (n > 0) _sleep(n*1000/60);
#else /* unreachable, I think */
if (!setjmp(iblk_buf)) {
input_blocking++;
n = ((unsigned int)getint(num)+30) / 60;
if (n > 0) sleep(n);
}
input_blocking = 0;
#endif
}
}
return(UNBOUND);
}
NODE *lshell(NODE *args) {
#if defined(mac)
printf("%s\n", message_texts[NOSHELL_MAC]);
return(UNBOUND);
#else
#ifdef ibm
NODE *arg;
char doscmd[200];
/* union REGS r; */
char *old_stringptr = print_stringptr;
int old_stringlen = print_stringlen;
arg = car(args);
while (!is_list(arg) && NOT_THROWING) {
setcar(args, err_logo(BAD_DATA, arg));
arg = car(args);
}
if (arg == NIL) {
ndprintf(stdout, "%t\n", message_texts[TYPE_EXIT]);
if (spawnlp(P_WAIT, "command", "command", NULL))
err_logo(FILE_ERROR,
make_static_strnode
("Could not open shell (probably due to low memory)"));
}
else {
print_stringlen = 199;
print_stringptr = doscmd;
ndprintf((FILE *)NULL,"%p",arg);
*print_stringptr = '\0';
if (system(doscmd) < 0)
err_logo(FILE_ERROR,
make_static_strnode
("Could not open shell (probably due to low memory)"));
print_stringptr = old_stringptr;
print_stringlen = old_stringlen;
}
/*
r.h.ah = 0x3;
r.h.al = 0;
r.h.dh = 0; r.h.dl = 0;
int86(0x21, &r, &r);
x_coord = x_margin;
y_coord = r.h.dh;
*/
#ifndef WIN32
x_coord = x_margin;
y_coord = y_max;
ibm_gotoxy(x_coord, y_coord);
#else
win32_repaint_screen();
#endif
return(UNBOUND);
#else
extern FILE *popen();
char cmdbuf[300];
FILE *strm;
NODE *head = NIL, *tail = NIL, *this;
BOOLEAN wordmode = FALSE;
int len;
char *old_stringptr = print_stringptr;
int old_stringlen = print_stringlen;
if (cdr(args) != NIL) wordmode = TRUE;
print_stringptr = cmdbuf;
print_stringlen = 300;
ndprintf((FILE *)NULL,"%p\n",car(args));
*print_stringptr = '\0';
#ifdef __WXMSW__
strm = _popen(cmdbuf,"r");
#else
strm = popen(cmdbuf,"r");
#endif
print_stringptr = old_stringptr;
print_stringlen = old_stringlen;
fgets(cmdbuf,300,strm);
while (!feof(strm)) {
len = (int)strlen(cmdbuf);
if (cmdbuf[len-1] == '\n')
cmdbuf[--len] = '\0';
if (wordmode)
this = make_strnode(cmdbuf, (struct string_block *)NULL, len,
STRING, strnzcpy);
else
this = parser(make_static_strnode(cmdbuf), FALSE);
if (head == NIL) {
tail = head = cons(this,NIL);
} else {
setcdr(tail, cons(this,NIL));
tail = cdr(tail);
}
fgets(cmdbuf,300,strm);
}
#ifdef __WXMSW__
_pclose(strm);
#else
pclose(strm);
#endif
return(head);
#endif
#endif
}
NODE *ltime(NODE *args) {
NODE *val;
FLONUM fval = 0.0;
#ifdef __APPLE__
struct timeval tp;
gettimeofday(&tp, NULL);
fval = tp.tv_sec + (FLONUM) tp.tv_usec / 1000000.0;
#else
fval = (FLONUM) time(NULL);
#endif
val = newnode(FLOATT);
setfloat(val, fval);
return val;
}
Computing file changes ...