/* * calcbdist - calculate binding distance for each variable */ void calcbdist_r(Cellidx ci, int depth) { int i; switch (Ctype(ci)) { case VAR: /* search the binding lambda */ for (i = depth - 1; i >= 0; i--) if (Cvar(ci) == boundvars[i]) break; if (i < 0) /* free variable */ Cbdist(ci) = -(depth + 1); /* +1 to reserve 0 */ else { /* bound variable */ Cbdist(ci) = depth - i; } return; case ABST: if (depth < MAXABSTDEPTH) { boundvars[depth] = Cbv(ci); calcbdist_r(Cbody(ci), depth + 1); } else { msg_warning("calcbdist: MAXABSTDEPTH reached; ignoring the subtree\n"); } return; case APPL: calcbdist_r(Cleft(ci), depth); calcbdist_r(Cright(ci), depth); return; default: fatal("calcbdist: invalid cell type %d\n", Ctype(ci)); /*NOTREACHED*/ } }
static int arraynodes_r(Cellidx ci, int curlev, int a[], int asize) { int lev1, lev2; if (curlev >= asize) { msg_warning("arraynodes_r: array size (%d) reached; ignoring the subtree\n", asize); return asize; } a[curlev]++; curlev++; switch (Ctype(ci)) { case VAR: return curlev; case ABST: return arraynodes_r(Cbody(ci), curlev, a, asize); case APPL: lev1 = arraynodes_r(Cleft(ci), curlev, a, asize); lev2 = arraynodes_r(Cright(ci), curlev, a, asize); return max(lev1, lev2); default: fatal("arraynodes_r: unexpected cell type %d\n", Ctype(ci)); } /*NOTREACHED*/ return curlev; }
void fprintcell(FILE *fp, Cellidx c) { fprintf(fp, "[cell#%ld]", c); if (poolsize <= c) { fprintf(fp, " out of range (poolsize %ld)\n", poolsize); } if (Ctype(c) <= NOTYPE) { /* nb. NOTYPE is curious but it has typename entry */ fprintf(fp, " type = %d (%s)\n", Ctype(c), typename[Ctype(c)]); } else {
int func(Cellidx ci, int descending) { if (!descending) return 0; printf("cell #%ld:\n", ci); printf(" type %d (%s)\n", Ctype(ci), typename[Ctype(ci)]); switch (Ctype(ci)) { case VAR: printf(" var = %ld\n", Cvar(ci)); break; case ABST: printf(" bv = %ld, body cell=#%ld\n", Cbv(ci), Cbody(ci)); break; case APPL: printf(" left cell=#%ld, right cell=#%ld\n", Cleft(ci), Cright(ci)); break; default: printf(" unknown\n"); break; } return 1; /* always continue (expect to bounce at VARs) */ }
static int diff_r(Cellidx c1, Cellidx c2) { int i; int w1, w2, dif; int a1[MAXTREEHEIGHT], a2[MAXTREEHEIGHT]; int lev1, lev2, bot; if (Ctype(c1) == VAR && Ctype(c2) == VAR) { w1 = Cbdist(c1); w2 = Cbdist(c2); if (w1 > 0 && w2 > 0) { /* both bound; return difference */ return DIST(w1, w2); } else if (w1 > 0) { /* c1 is bound, c2 is free */ return w1 - w2; } else if (w2 > 0) { /* c2 is bound, c1 is free */ return w2 - w1; } else { /* both free */ return DIST(Cvar(c1), Cvar(c2)); } } else if (Ctype(c1) == VAR && Ctype(c2) == ABST) { return numnodes(c2); } else if (Ctype(c1) == ABST && Ctype(c2) == VAR) { return numnodes(c1); } else if (Ctype(c1) == VAR && Ctype(c2) == APPL) { return numnodes(c2); } else if (Ctype(c1) == APPL && Ctype(c2) == VAR) { return numnodes(c1); } else if (Ctype(c1) == ABST && Ctype(c2) == ABST) { return diff_r(Cbody(c1), Cbody(c2)); } else if ((Ctype(c1) == ABST && Ctype(c2) == APPL) || (Ctype(c1) == APPL && Ctype(c2) == ABST)) { lev1 = arraynodes(c1, a1, MAXTREEHEIGHT); lev2 = arraynodes(c2, a2, MAXTREEHEIGHT); bot = max(lev1, lev2); dif = 0; for (i = 0; i < bot; i++) dif += 2 + DIST(a1[i], a2[i]); return dif; } else if (Ctype(c1) == APPL && Ctype(c2) == APPL) { return diff_r(Cleft(c1), Cleft(c2)) + diff_r(Cright(c1), Cright(c2)); } else { fatal("diff_r: unexpected cell type %d and %d\n", Ctype(c1), Ctype(c2)); } fatal("diff_r: cannot come here\n"); /*NOTREACHED*/ return 0; }
/* void Ucommand (void) ------------------------- * * OS/0 command processor. * * Before spawning/calling this process, set the * external variable CurrentTerm to the number * of the terminal you want the command processor to * run on. Note that CurrentTerm is incremented by * the command processor after it "uses" the value. * This allows Ucommand to be spawned in a loop. * * This command interpreter was designed to be both * spawned and called. It is suggested that terms * 1-3 be spawned, then term 1 be called directly. * This way when the "bye" command is issued at a terminal * greater than 0 the system will not shut down. */ void Ucommand (void) { int TermNum = (CurrentTerm++) ; ARG Args ; char *Cmd ; char *user ; char *prompt ; char *buf ; int NumChars, CmdNum, i ; short bLoggedIn = FALSE ; Cmd = (char*) malloc (sizeof(char)*256) ; user = (char*) malloc (sizeof(char)*256) ; prompt = (char*) malloc (sizeof(char)*256) ; buf = (char*) malloc (sizeof(char)*256) ; tprint (" Command processor %d active\n", TermNum) ; sprintf (buf, "\aOS/0 Mail - Copyright (c) 1990, Charles Kindel and Sandy Smith.\n") ; Writeterm (buf, strlen (buf), TermNum) ; sprintf (buf, "\tCommand processor %d active\n", TermNum) ; Writeterm (buf, strlen (buf), TermNum) ; sprintf (buf, "Available commands:\n") ; Writeterm (buf, strlen(buf), TermNum) ; for (i = 0 ; i < NCMDS ; i++) { sprintf (buf, "\t%s\n", cmdnames[i]) ; Writeterm (buf, strlen(buf), TermNum) ; } strcpy (user, "OS/0") ; while (TRUE) { if (!bLoggedIn && TermNum) sprintf (prompt, "\x1b[1mType \"login <username>\" to get started:\x1b[0m ") ; else sprintf (prompt, "\x1b[1m[%s]\x1b[0m ", user) ; Writeterm (prompt, strlen(prompt), TermNum) ; NumChars = Readterm (Cmd, CMDSIZE, TermNum) ; CmdNum = CmdToNum (Cmd, &Args) ; if (bEcho) { /* echo cmd to terminal */ for (i = 0 ; i <= Args.num ; i++) { sprintf (buf, "%s ", Args.arg[i]) ; Writeterm (buf, strlen(buf), TermNum) ; } Writeterm ("\n", 1, TermNum) ; } switch (CmdNum) { case CECHO : if (TermNum) { sprintf (buf, "\aYou must be logged in to use that command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } if (Args.num) { if (!strcmp (Args.arg[1], "on")) bEcho = TRUE ; else if (!strcmp (Args.arg[1], "off")) bEcho = FALSE ; else { sprintf (buf, "The usage for the echo command is : \"echo [on|off]\"\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } } else { sprintf (buf, "\techo is %s\n", bEcho ? "on" : "off") ; Writeterm (buf, strlen(buf), TermNum) ; } break ; case CHELP : sprintf (buf, "Available commands:\n") ; Writeterm (buf, strlen(buf), TermNum) ; for (i = 0 ; i < NCMDS ; i++) { sprintf (buf, "\t%s\n", cmdnames[i]) ; Writeterm (buf, strlen(buf), TermNum) ; } break ; case CLIST : if (bLoggedIn || !TermNum) Mlist (TermNum) ; else { sprintf (buf, "\aYou must be logged in to use that command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } break ; case CADDUSER: Madduser (TermNum, &Args) ; break ; case CLOGIN : if (bLoggedIn) { Mlogout (TermNum, user, &Args) ; strcpy (user, "OS/0") ; } if (Mlogin (TermNum, user, &Args)) bLoggedIn = TRUE ; break ; case CLOGOUT : if (!bLoggedIn) { sprintf (buf, "\aNo one is logged in!\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } bLoggedIn = !Mlogout (TermNum, user, &Args) ; strcpy (user, "OS/0") ; break ; case CMAIL : if (!bLoggedIn) { sprintf (buf, "\aYou must be logged in to use that command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } MMail (TermNum, user, &Args) ; break ; case CCMD : if (!bLoggedIn && TermNum) { sprintf (buf, "\aYou must be logged in to use that command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } if (Args.num != 1) { sprintf (buf, "\aThe usage for \"cmd\" is: cmd <time>\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } sprintf (buf, "Executing a psuedo-command...\n") ; Writeterm (buf, strlen(buf), TermNum) ; Delay (atoi(Args.arg[1]) / 10) ; break ; case CDIR : if (bLoggedIn || !TermNum) Udir (TermNum) ; else { sprintf (buf, "\aYou must be logged in to use that command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; } break ; case CTIME: if (bLoggedIn || !TermNum) { sprintf (buf, "The current time is %d\n", Get_Time_of_Day()) ; Writeterm (buf, strlen(buf), TermNum) ; } else { sprintf (buf, "\aYou must be logged in to use that command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; } break ; case CDEL: if (TermNum) /* check to see if were on term 0 */ { sprintf (buf, "\aFiles can be deleted from Terminal 0 only.\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } for (i = 1 ; i <= Args.num ; i++) { if (!(strcmp (Args.arg[i], ".")) || (-1 == Uremove (Args.arg[i]))) { sprintf (buf, "\t%s does not exist.\n", Args.arg[i]) ; Writeterm (buf, strlen(buf), TermNum) ; } sprintf (buf, "\t%s deleted.\n", Args.arg[i]) ; Writeterm (buf, strlen(buf), TermNum) ; } break ; case CFORMAT : if (TermNum) /* check to see if were on term 0 */ { sprintf (buf, "\aThe disk can be formatted from Terminal 0 only.\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } Uformat (INODESPACE) ; break ; case CTYPE : if (TermNum && !bLoggedIn) { sprintf (buf, "\aYou must be logged in to use this command!\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } Ctype (TermNum, &Args) ; break ; case CBYE : if (TermNum) /* check to see if were on term 0 */ { sprintf (buf, "\aThe system can only be shut down from Terminal 0.\n") ; Writeterm (buf, strlen(buf), TermNum) ; break ; } sprintf (buf, "Shutting down the OS/0 file system!\n") ; Writeterm (buf, strlen(buf), TermNum) ; for (i = 1 ; i < 4 ; i++) { sprintf (buf, "\n\a\a\aNotice! The OS/0 file system is going down in 10 seconds!\n") ; Writeterm (buf, strlen(buf), i) ; } Delay (10) ; free (Cmd) ; free (user) ; free (prompt) ; free (buf) ; Terminate () ; break ; default : if (strlen(Cmd)) { sprintf (buf, "\a\"%s\" is an invalid command!\n", Cmd) ; Writeterm (buf, strlen(buf), TermNum) ; } break ; } } } /* Ucommand */