home *** CD-ROM | disk | FTP | other *** search
-
- /* Miscellaneous operations in LOGO.
- * Copyright (C) 1979, The Children's Museum, Boston, Mass.
- * Written by Douglas B. Klunder.
- */
-
- #include "logo.h"
-
- struct object *true()
- {
- return(localize(objcpstr("true")));
- }
-
- struct object *false()
- {
- return(localize(objcpstr("false")));
- }
-
- obstrcmp(obj,str)
- register struct object *obj;
- char *str;
- {
- if (!stringp(obj)) return(1);
- return(strcmp(obj->obstr,str));
- }
-
- int truth(x) /* used by if handler in logo.y */
- register struct object *x;
- {
- if (obstrcmp(x,"true") && obstrcmp(x,"false")) ungood("If",x);
- if (!obstrcmp(x,"true")) {
- mfree(x);
- return(1);
- } else {
- mfree(x);
- return(0);
- }
- }
-
- char *mkstring(obj)
- register struct object *obj;
- {
- /* subroutine for several operations which treat numbers as words,
- * turn number into character string.
- * Note: obj must be known to be nonempty; result is ptr to static.
- */
-
- register char *cp;
- static char str[30];
-
- switch(obj->obtype) {
- case STRING:
- cp = obj->obstr;
- break;
- case INT:
- sprintf(str,FIXFMT,obj->obint);
- cp = str;
- break;
- case DUB:
- sprintf(str,"%g",obj->obdub);
- if (!index(str,'.')) strcat(str,".0");
- cp = str;
- break;
- default: /* case CONS */
- return(0); /* not a string, handle uplevel */
- }
- return(cp);
- }
-
- struct object *and(x,y) /* both */
- register struct object *x,*y;
- {
- if (obstrcmp(x,"true") && obstrcmp(x,"false")) ungood("Both",x);
- if (obstrcmp(y,"true") && obstrcmp(y,"false")) ungood("Both",y);
- if (!obstrcmp(x,"true")) {
- mfree(x);
- return(y);
- } else {
- mfree(y);
- return(x);
- }
- }
-
- struct object *or(x,y) /* either */
- register struct object *x,*y;
- {
- if (obstrcmp(x,"true") && obstrcmp(x,"false")) ungood("Either",x);
- if (obstrcmp(y,"true") && obstrcmp(y,"false")) ungood("Either",y);
- if (!obstrcmp(x,"true")) {
- mfree(y);
- return(x);
- } else {
- mfree(x);
- return(y);
- }
- }
-
- emptyp(x) /* non-LOGO emptyp, returning 1 if empty, 0 if not. */
- register struct object *x;
- {
- if (x==0) return(1);
- switch (x->obtype) {
- case STRING:
- if (*(x->obstr)=='\0') /* check for character */
- return(1);
- default:
- return(0);
- }
- }
-
- struct object *lemp(x) /* LOGO emptyp */
- register struct object *x;
- {
- if (emptyp(x)) {
- mfree(x);
- return(true());
- } else {
- mfree(x);
- return(false());
- }
- }
-
- struct object *comp(x) /* not */
- register struct object *x;
- {
- if (!obstrcmp(x,"true")) {
- mfree(x);
- return(false());
- } else if (!obstrcmp(x,"false")) {
- mfree(x);
- return(true());
- } else ungood("Not",x);
- }
-
- struct object *lsentp(x) /* LOGO sentencep */
- register struct object *x;
- {
- register struct object *y;
-
- if (x==0) return(true());
- if (listp(x)) {
- /* BH 4/30/81 true only for a flat sentence,
- not a list of lists */
- for (y = x; y; y = y->obcdr)
- if (listp(y->obcar)) {
- mfree(x);
- return(false());
- }
- mfree(x);
- return(true());
- } else {
- mfree(x);
- return(false());
- }
- }
-
- struct object *lwordp(x) /* LOGO wordp */
- register struct object *x;
- {
- if (!listp(x)) {
- mfree(x);
- return(true());
- } else {
- mfree(x);
- return(false());
- }
- }
-
- struct object *first(x) /* first */
- register struct object *x;
- {
- register struct object *temp;
- register char *cp;
- char str[2];
-
- if (emptyp(x)) ungood("First",x);
- if (cp = mkstring(x)) {
- str[0] = *cp;
- str[1] = '\0';
- mfree(x);
- return(localize(objcpstr(str)));
- } else {
- temp = x->obcar;
- localize(temp);
- mfree(x);
- return(temp);
- }
- }
-
- struct object *butfir(x) /* butfirst */
- register struct object *x;
- {
- register struct object *temp;
- register char *cp;
-
- if (emptyp(x)) ungood("Butfirst",x);
- if (cp = mkstring(x)) {
- cp++; /* skip first char */
- mfree(x);
- return(localize(objcpstr(cp)));
- } else {
- temp = x->obcdr;
- localize(temp);
- mfree(x);
- return(temp);
- }
- }
-
- struct object *last(x) /* last */
- register struct object *x;
- {
- register struct object *temp;
- register char *cp;
-
- if (emptyp(x)) ungood("Last",x);
- if (cp = mkstring(x)) {
- mfree(x);
- return(localize(objcpstr(&cp[strlen(cp)-1])));
- } else {
- for(temp=x; temp->obcdr; temp=temp->obcdr) ;
- temp = temp->obcar;
- localize(temp);
- mfree(x);
- return(temp);
- }
- }
-
- struct object *butlas(x) /* butlast */
- register struct object *x;
- {
- register struct object *temp,*temp2,*ans;
- register char *cp;
-
- if (emptyp(x)) ungood("Butlast",x);
- if (cp = mkstring(x)) {
- mfree(x);
- temp = objstr(ckmalloc(strlen(cp)));
- strncpy(temp->obstr,cp,strlen(cp)-1);
- (temp->obstr)[strlen(cp)-1] = '\0';
- return(localize(temp));
- } else {
- if ((x->obcdr)==0) {
- mfree(x);
- return(0);
- }
- temp2 = ans = globcons(0,0);
- for(temp=x; temp->obcdr->obcdr; temp=temp->obcdr) {
- temp2->obcar = globcopy(temp->obcar);
- temp2->obcdr = globcopy(globcons(0,0));
- temp2 = temp2->obcdr;
- }
- temp2->obcar = globcopy(temp->obcar);
- localize(ans);
- mfree(x);
- return(ans);
- }
- }
-
- struct object *fput(x,y)
- register struct object *x,*y;
- {
- register struct object *z;
-
- if(!listp(y)) {
- printf("Second input of fput must be a list.\n");
- errhand();
- }
- z = loccons(x,y);
- mfree(x);
- mfree(y);
- return(z);
- }
-
- struct object *lput(x,y)
- struct object *x,*y;
- {
- register struct object *a,*b,*ans;
-
- if (!listp(y)) {
- printf("Second input of lput must be a list.\n");
- errhand();
- }
- if (y == 0) { /* 2nd input is empty list */
- b = loccons(x,0);
- mfree(x);
- return(b);
- }
- ans = a = loccons(0,0);
- for (b=y; b; b=b->obcdr) {
- a->obcar = globcopy(b->obcar);
- a->obcdr = globcopy(globcons(0,0));
- a = a->obcdr;
- }
- a->obcar = globcopy(x);
- mfree(x);
- mfree(y);
- return(ans);
- }
-
- struct object *list(x,y)
- struct object *x,*y;
- {
- register struct object *a,*b;
-
- b = globcons(y,0);
- a = loccons(x,b);
- mfree(x);
- mfree(y);
- return(a);
- }
-
- struct object *length(x) /* count */
- register struct object *x;
- {
- register struct object *temp;
- register char *cp;
- register int i;
-
- if (x==0) return(localize(objint((FIXNUM)0)));
- if (cp = mkstring(x)) {
- i = strlen(cp);
- mfree(x);
- return(localize(objint((FIXNUM)i)));
- } else {
- i = 0;
- for (temp=x; temp; temp = temp->obcdr)
- i++;
- mfree(x);
- return(localize(objint((FIXNUM)i)));
- }
- }
-
- logois(x,y) /* non-Logo is, despite the name */
- register struct object *x,*y;
- {
- if (listp(x)) {
- if (listp(y)) {
- if (x==0) return(y==0);
- if (y==0) return(0);
- return(logois(x->obcar,y->obcar) &&
- logois(x->obcdr,y->obcdr) );
- }
- return(0);
- }
- if (listp(y)) return(0);
- if (x->obtype != y->obtype) return(0);
- switch (x->obtype) {
- case INT:
- return(x->obint == y->obint);
- case DUB:
- return(x->obdub == y->obdub);
- default: /* case STRING */
- return(!strcmp(x->obstr,y->obstr));
- }
- }
-
- struct object *lis(x,y)
- register struct object *x,*y;
- {
- register z;
-
- z = logois(x,y);
- mfree(x);
- mfree(y);
- return(z ? true() : false());
- }
-
- leq(x,y) /* non-Logo numeric equal */
- register struct object *x,*y;
- {
- NUMBER dx,dy;
- FIXNUM ix,iy;
- int xint,yint;
-
- if (listp(x) || listp(y)) return(logois(x,y));
- if (stringp(x) && !nump(x)) return(logois(x,y));
- if (stringp(y) && !nump(y)) return(logois(x,y));
- xint = yint = 0;
- if (stringp(x)) {
- if (isint(x)) {
- xint++;
- sscanf(x->obstr,FIXFMT,&ix);
- } else {
- sscanf(x->obstr,EFMT,&dx);
- }
- } else {
- if (intp(x)) {
- xint++;
- ix = x->obint;
- } else {
- dx = x->obdub;
- }
- }
- if (stringp(y)) {
- if (isint(y)) {
- yint++;
- sscanf(y->obstr,FIXFMT,&iy);
- } else {
- sscanf(y->obstr,EFMT,&dy);
- }
- } else {
- if (intp(y)) {
- yint++;
- iy = y->obint;
- } else {
- dy = y->obdub;
- }
- }
- if (xint != yint) {
- if (xint) dx = ix;
- else dy = iy;
- xint = 0;
- }
- if (xint)
- return (ix == iy);
- else
- return (dx == dy);
- }
-
- struct object *equal(x,y) /* Logo equalp */
- register struct object *x,*y;
- {
- register z;
-
- z = leq(x,y);
- mfree(x);
- mfree(y);
- return(z ? true() : false());
- }
-
- struct object *worcat(x,y) /* word */
- register struct object *x,*y;
- {
- char *val,*xp,*yp;
- char xstr[30],ystr[30];
-
- if (listp(x)) ungood("Word",x);
- if (listp(y)) ungood("Word",y);
- switch(x->obtype) {
- case INT:
- sprintf(xstr,FIXFMT,x->obint);
- xp = xstr;
- break;
- case DUB:
- sprintf(xstr,"%g",x->obdub);
- if (!index(xstr,'.')) strcat(xstr,".0");
- xp = xstr;
- break;
- default: /* case STRING */
- xp = x->obstr;
- }
- switch(y->obtype) {
- case INT:
- sprintf(ystr,FIXFMT,y->obint);
- yp = ystr;
- break;
- case DUB:
- sprintf(ystr,"%g",y->obdub);
- if (!index(ystr,'.')) strcat(ystr,".0");
- yp = ystr;
- break;
- default: /* case STRING */
- yp = y->obstr;
- }
- val=ckmalloc(strlen(xp)+strlen(yp)+1);
- cpystr(val,xp,yp,NULL);
- mfree(x);
- mfree(y);
- return(localize(objstr(val)));
- }
-
- struct object *sencat(x,y) /* sentence */
- struct object *x,*y;
- {
- register struct object *a,*b,*c;
-
- if (x==0) {
- if (listp(y)) return(y);
- a = loccons(y,0);
- mfree(y);
- return(a);
- }
- if (listp(x)) {
- c = a = globcons(0,0);
- for (b=x; b->obcdr; b = b->obcdr) {
- a->obcar = globcopy(b->obcar);
- a->obcdr = globcopy(globcons(0,0));
- a = a->obcdr;
- }
- a->obcar = globcopy(b->obcar);
- }
- else c = a = globcons(x,0);
-
- if (listp(y)) b = y;
- else b = globcons(y,0);
-
- a->obcdr = globcopy(b);
- mfree(x);
- mfree(y);
- return(localize(c));
- }
-
- struct object *memberp(thing,group)
- struct object *thing,*group;
- {
- register char *cp;
- register struct object *rest;
- int i;
-
- if (group==0) {
- mfree(thing);
- return(false());
- }
- if (cp = mkstring(group)) {
- if (thing==0) {
- mfree(group);
- return(false());
- }
- switch (thing->obtype) {
- case INT:
- if((thing->obint >= 0)&&(thing->obint < 10)) {
- i = memb('0'+thing->obint,cp);
- break;
- }
- case CONS:
- case DUB:
- i = 0;
- break;
- default: /* STRING */
- if (strlen(thing->obstr) == 1) {
- i = memb(*(thing->obstr),cp);
- } else i = 0;
- }
- } else {
- i = 0;
- for (rest=group; rest; rest=rest->obcdr) {
- if (leq(rest->obcar,thing)) {
- i++;
- break;
- }
- }
- }
- mfree(thing);
- mfree(group);
- return(torf(i));
- }
-
- struct object *item(num,group)
- struct object *num,*group;
- {
- int inum,ernum;
- register char *cp;
- register struct object *rest;
- char str[2];
-
- num = numconv(num,"Item");
- if (intp(num)) inum = num->obint;
- else inum = num->obdub;
- if (inum <= 0) ungood("Item",num);
- if (group == 0) ungood("Item",group);
- if (cp = mkstring(group)) {
- if (inum > strlen(cp)) {
- pf1("%p has fewer than %d items.\n",group,inum);
- errhand();
- }
- str[0] = cp[inum-1];
- str[1] = '\0';
- mfree(num);
- mfree(group);
- return(localize(objcpstr(str)));
- } else {
- ernum = inum;
- for (rest = group; --inum; rest = rest->obcdr) {
- if (rest==0) break;
- }
- if (rest==0) {
- pf1("%p has fewer than %d items.\n",
- group,ernum);
- errhand();
- }
- mfree(num);
- rest = localize(rest->obcar);
- mfree(group);
- return(rest);
- }
- }
-
-