Initial commit of newLISP.
[newlisp.git] / newlisp.c
blobc6d6443985c43212acd3ef062946537126c939dd
1 /* newlisp.c --- enrty point and main functions for newLISP
3 Copyright (C) 2008 Lutz Mueller
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "newlisp.h"
20 #include "pcre.h"
21 #include "protos.h"
22 #include "primes.h"
24 #ifdef WIN_32
25 #include <winsock2.h>
26 #endif
28 #ifdef READLINE
29 #include <readline/readline.h>
30 #include <readline/history.h>
31 #endif
33 #ifdef SUPPORT_UTF8
34 #include <wctype.h>
35 #endif
37 #ifdef IPV6
38 #define IPV 6
39 #else
40 #define IPV 4
41 #endif
43 #define freeMemory free
45 #ifdef WIN_32
46 #define INIT_FILE "init.lsp"
47 #define fprintf win32_fprintf
48 #define fgets win32_fgets
49 #define fclose win32_fclose
50 #else
51 #define INIT_FILE "/usr/share/newlisp/init.lsp"
52 #endif
54 #ifdef LIBRARY
55 extern STREAM libStrStream;
56 #endif
58 #ifdef LINUX
59 int opsys = 1;
60 char ostype[]="Linux";
61 #endif
63 #ifdef _BSD
64 int opsys = 2;
65 char ostype[]="BSD";
66 #endif
68 #ifdef MAC_OSX
69 int opsys = 3;
70 char ostype[]="OSX";
71 #endif
73 #ifdef SOLARIS
74 #ifdef TRU64
75 int opsys = 9;
76 char ostype[]="Tru64Unix";
77 #else
78 int opsys = 4;
79 char ostype[]="Solaris";
80 #endif
81 #endif
83 #ifdef WIN_32
84 int opsys = 6;
85 char ostype[]="Win32";
86 #endif
88 #ifdef OS2
89 int opsys = 7;
90 char ostype[]="OS/2";
91 #endif
93 int version = 9303;
95 char copyright[]=
96 "\nnewLISP v.9.3.3 Copyright (c) 2008 Lutz Mueller. All rights reserved.\n\n%s\n\n";
98 #ifndef NEWLISP64
99 #ifdef SUPPORT_UTF8
100 char banner[]=
101 "newLISP v.9.3.3 on %s IPv%d UTF-8%s\n\n";
102 #else
103 char banner[]=
104 "newLISP v.9.3.3 on %s IPv%d%s\n\n";
105 #endif
106 #else
107 #ifdef SUPPORT_UTF8
108 char banner[]=
109 "newLISP v.9.3.3 64-bit on %s IPv%d UTF-8%s\n\n";
110 #else
111 char banner[]=
112 "newLISP v.9.3.3 64-bit on %s IPv%d%s\n\n";
113 #endif
114 #endif
116 char banner2[]=
117 ", execute 'newlisp -h' for more info.";
119 char linkOffset[] = "@@@@@@@@";
121 void printHelpText(void);
123 /* --------------------- globals -------------------------------------- */
125 /* interactive command line */
127 int commandLineFlag = TRUE;
128 int isTTY = FALSE;
129 int demonMode = 0;
131 int noPromptMode = 0;
132 int forcePromptMode = 0;
133 int httpMode = 0;
135 FILE * IOchannel;
136 int IOport = 0;
137 char * IOdomain = NULL;
138 int logTraffic = 0;
139 #define LOG_LESS 1
140 #define LOG_MORE 2
142 /* initialization */
143 int MAX_CPU_STACK = 0x800;
144 int MAX_ENV_STACK;
145 int MAX_RESULT_STACK;
146 #ifndef NEWLISP64
147 long MAX_CELL_COUNT = 0x10000000;
148 #else
149 long MAX_CELL_COUNT = 0x800000000000000LL;
150 #endif
152 CELL * firstFreeCell = NULL;
154 CELL * nilCell;
155 CELL * trueCell;
156 CELL * lastCellCopied;
157 SYMBOL * nilSymbol;
158 SYMBOL * trueSymbol;
159 SYMBOL * starSymbol;
160 SYMBOL * plusSymbol;
161 SYMBOL * questionSymbol;
162 SYMBOL * atSymbol;
163 SYMBOL * currentFunc;
164 SYMBOL * argsSymbol;
165 SYMBOL * mainArgsSymbol;
166 SYMBOL * dolistIdxSymbol;
168 SYMBOL * sysSymbol[MAX_REGEX_EXP];
170 SYMBOL * errorEvent;
171 SYMBOL * currentContext = NULL;
172 SYMBOL * mainContext = NULL;
173 SYMBOL * demonRequest;
174 SYMBOL * timerEvent;
176 SYMBOL * symHandler[32];
177 int currentSignal = 0;
179 jmp_buf errorJump;
181 char lc_decimal_point;
183 /* error and exception handling */
185 #define EXCEPTION_THROW -1
186 int errorReg = 0;
187 CELL * throwResult;
188 int errnoSave;
190 /* buffer for read-line */
191 STREAM readLineStream;
193 /* compiler */
195 size_t cellCount = 0;
196 size_t symbolCount = 0;
198 int parStackCounter = 0;
200 /* expression evaluation */
202 static CELL * (*evalFunc)(CELL *) = NULL;
203 UINT * envStack = NULL;
204 UINT * resultStack = NULL;
205 UINT * lambdaStack = NULL;
206 int envStackIdx, resultStackIdx, lambdaStackIdx;
207 int evalSilent = 0;
209 extern PRIMITIVE primitive[];
211 int traceFlag = 0;
212 int evalCatchFlag = 0;
213 int recursionCount = 0;
214 int symbolProtectionLevel = 0;
216 int prettyPrintPars = 0;
217 int prettyPrintCurrent = 0;
218 int prettyPrintFlags = 0;
219 int prettyPrintLength = 0;
220 char * prettyPrintTab = " ";
221 #define MAX_PRETTY_PRINT_LENGTH 80
222 UINT prettyPrintMaxLength = MAX_PRETTY_PRINT_LENGTH;
223 int stringOutputRaw = TRUE;
225 #define pushLambda(A) (*(lambdaStack + lambdaStackIdx++) = (UINT)(A))
226 #define popLambda() ((CELL *)*(lambdaStack + --lambdaStackIdx))
228 int pushResultFlag = TRUE;
230 char startupDir[PATH_MAX]; /* start up directory, if defined via -w */
231 char logFile[PATH_MAX]; /* logFile, is define with -l, -L */
233 /* ============================== MAIN ================================ */
236 void setupSignalHandler(int sig, void (* handler)(int))
238 static struct sigaction sig_act;
239 sig_act.sa_handler = handler;
240 sigemptyset(&sig_act.sa_mask);
241 sig_act.sa_flags = SA_RESTART | SA_NOCLDSTOP;
242 if(sigaction(sig, &sig_act, 0) != 0)
243 printf("Error setting signal:%d handler\n", sig);
247 void setupSignalHandler(int sig, void (* handler)(int))
249 if(signal(sig, handler) == SIG_ERR)
250 printf("Error setting signal:%d handler\n", sig);
253 #ifdef SOLARIS
254 void sigpipe_handler(int sig)
256 setupSignalHandler(SIGPIPE, sigpipe_handler);
259 void sigchld_handler(int sig)
261 waitpid(-1, (int *)0, WNOHANG);
264 void ctrlC_handler(int sig)
266 char chr;
268 setupSignalHandler(SIGINT, ctrlC_handler);
270 if(commandLineFlag != TRUE) return;
272 traceFlag |= TRACE_SIGINT;
274 printErrorMessage(ERR_SIGINT, NULL, 0);
275 printf("(c)ontinue, e(x)it, (r)eset:");
276 fflush(NULL);
277 chr = getchar();
278 if(chr == 'x') exit(1);
279 if(chr == 'c') traceFlag &= ~TRACE_SIGINT;
283 void sigalrm_handler(int sig)
285 setupSignalHandler(sig, sigalrm_handler);
286 /* check if not sitting idle */
287 if(recursionCount)
288 traceFlag |= TRACE_TIMER;
289 else /* if idle */
290 executeSymbol(timerEvent, NULL);
293 #endif /* solaris */
296 void setupAllSignals(void)
298 #ifdef SOLARIS
299 setupSignalHandler(SIGINT,ctrlC_handler);
300 #else
301 setupSignalHandler(SIGINT, signal_handler);
302 #endif
304 #ifndef WIN_32
306 #ifdef SOLARIS
307 setupSignalHandler(SIGALRM, sigalrm_handler);
308 setupSignalHandler(SIGVTALRM, sigalrm_handler);
309 setupSignalHandler(SIGPROF, sigalrm_handler);
310 setupSignalHandler(SIGPIPE, sigpipe_handler);
311 setupSignalHandler(SIGCHLD, sigchld_handler);
312 #else
313 setupSignalHandler(SIGALRM, signal_handler);
314 setupSignalHandler(SIGVTALRM, signal_handler);
315 setupSignalHandler(SIGPROF, signal_handler);
316 setupSignalHandler(SIGPIPE, signal_handler);
317 setupSignalHandler(SIGCHLD, signal_handler);
318 #endif
320 #endif
323 void signal_handler(int sig)
325 #ifndef WIN_32
326 char chr;
327 #endif
329 if(sig > 32 || sig < 1) return;
331 #ifdef SOLARIS
332 switch(sig)
334 case SIGALRM:
335 case SIGVTALRM:
336 case SIGPROF:
337 setupSignalHandler(sig, sigalrm_handler);
338 break;
339 case SIGPIPE:
340 setupSignalHandler(SIGPIPE, sigpipe_handler);
341 break;
342 case SIGCHLD:
343 setupSignalHandler(SIGCHLD, sigchld_handler);
344 break;
346 #else
347 setupSignalHandler(sig, signal_handler);
348 #endif
350 if(symHandler[sig - 1] != nilSymbol)
352 if(recursionCount)
354 currentSignal = sig;
355 traceFlag |= TRACE_SIGNAL;
356 return;
358 else
360 executeSymbol(symHandler[sig-1], stuffInteger(sig));
361 return;
365 switch(sig)
367 case SIGINT:
368 if(commandLineFlag != TRUE) return;
370 printErrorMessage(ERR_SIGINT, NULL, 0);
372 #ifdef WIN_32
373 traceFlag |= TRACE_SIGINT;
374 #else
375 printf("\n(c)ontinue, (d)ebug, e(x)it, (r)eset:");
376 fflush(NULL);
377 chr = getchar();
378 if(chr == 'x') exit(1);
379 if(chr == 'd')
381 traceFlag &= ~TRACE_SIGINT;
382 openTrace();
384 if(chr == 'r') traceFlag |= TRACE_SIGINT;
385 break;
386 case SIGPIPE:
387 break;
388 case SIGALRM:
389 case SIGVTALRM:
390 case SIGPROF:
391 /* check if not sitting idle */
392 if(recursionCount)
393 traceFlag |= TRACE_TIMER;
394 else /* if idle */
395 executeSymbol(timerEvent, NULL);
396 break;
397 case SIGCHLD:
398 waitpid(-1, (int *)0, WNOHANG);
399 #endif
400 break;
401 default:
402 return;
407 void loadStartup(char * name)
409 #ifdef WIN_32
410 #ifndef LIBRARY
411 char * ptr;
412 char EXEName[MAX_LINE];
413 char initFile[MAX_LINE];
415 GetModuleFileName(NULL, EXEName, MAX_LINE);
416 name = EXEName;
417 #endif
418 #endif
420 if(strncmp(linkOffset, "@@@@", 4) == 0)
422 #ifdef WIN_32
423 #ifndef LIBRARY
424 ptr = name + strlen(name) - 1;
425 while(ptr != name)
427 if(*ptr == '/' || *ptr == '\\') break;
428 ptr--;
430 *ptr = 0;
431 strncpy(initFile, name, MAX_LINE - 9);
432 strcat(initFile, "/");
433 strcat(initFile, INIT_FILE);
434 loadFile(initFile, 0, 0, mainContext);
435 #else
436 loadFile(INIT_FILE, 0, 0, mainContext);
437 #endif
438 #else
439 loadFile(INIT_FILE, 0, 0, mainContext);
440 #endif
442 else /* load encrypted part at offset */
443 loadFile(name, *(UINT*)linkOffset, 1, mainContext);
447 #ifdef _BSD
448 struct lconv *localeconv(void);
449 char *setlocale(int, const char *);
450 #endif
452 void initLocale(void)
454 struct lconv * lc;
455 char * locale;
457 #ifndef SUPPORT_UTF8
458 locale = setlocale(LC_ALL, "C");
459 #else
460 locale = setlocale(LC_ALL, "");
461 #endif
463 if (locale != NULL)
464 stringOutputRaw = (strcmp(locale, "C") == 0);
466 lc = localeconv();
467 lc_decimal_point = *lc->decimal_point;
470 /* set NEWLISPDIR only if not set already */
471 void initNewlispDir(void)
473 #ifdef WIN_32
474 char * varValue;
475 char * newlispDir;
477 if(getenv("NEWLISPDIR") == NULL)
479 newlispDir = alloca(MAX_PATH);
480 varValue = getenv("PROGRAMFILES");
481 if(varValue != NULL)
483 strncpy(newlispDir, varValue, MAX_PATH);
484 strncat(newlispDir, "/newlisp", 8);
485 setenv("NEWLISPDIR", newlispDir, TRUE);
487 else setenv("NEWLISPDIR", "newlisp", TRUE);
489 #else
490 if(getenv("NEWLISPDIR") == NULL)
491 setenv("NEWLISPDIR", "/usr/share/newlisp", TRUE);
492 #endif
495 #ifndef LIBRARY
496 char * getArg(char * * arg, int argc, int * index)
498 if(strlen(arg[*index]) > 2)
499 return(arg[*index] + 2);
501 if(*index >= (argc - 1))
503 printf("missing parameter for %s\n", arg[*index]);
504 exit(-1);
507 *index = *index + 1;
509 return(arg[*index]);
512 #ifndef WIN_32
513 char ** MainArgs;
514 #endif
516 CELL * getMainArgs(char * mainArgs[])
518 CELL * argList;
519 #ifndef LIBRARY
520 CELL * lastEntry;
521 int idx = 0;
522 #endif
524 #ifndef WIN_32
525 MainArgs = mainArgs;
526 #endif
528 argList = getCell(CELL_EXPRESSION);
530 #ifndef LIBRARY
531 lastEntry = NULL;
532 while(mainArgs[idx] != NULL)
534 if(lastEntry == NULL)
536 lastEntry = stuffString(mainArgs[idx]);
537 argList->contents = (UINT)lastEntry;
539 else
541 lastEntry->next = stuffString(mainArgs[idx]);
542 lastEntry = lastEntry->next;
544 idx++;
546 #endif
548 return(argList);
552 int main(int argc, char * argv[])
554 char command[MAX_LINE];
555 STREAM cmdStream;
556 int idx;
557 #ifdef READLINE
558 char * cmd;
559 #endif
561 #ifdef WIN_32
562 WSADATA WSAData;
563 WSAStartup(MAKEWORD(1,1), &WSAData);
564 #endif
566 #ifdef SUPPORT_UTF8
567 opsys += 128;
568 #endif
570 memset(&cmdStream, 0, sizeof(STREAM));
572 initLocale();
573 initNewlispDir();
574 IOchannel = stdin;
576 initialize();
577 initStacks();
579 mainArgsSymbol->contents = (UINT)getMainArgs(argv);
581 if((errorReg = setjmp(errorJump)) != 0)
583 if(errorReg && (errorEvent != nilSymbol) && !isNil((CELL*)errorEvent->contents))
584 executeSymbol(errorEvent, NULL);
585 else exit(-1);
586 goto AFTER_ERROR_ENTRY;
589 setupAllSignals();
591 loadStartup(argv[0]);
592 errno = 0;
594 realpath(".", startupDir);
596 for(idx = 1; idx < argc; idx++)
598 #ifndef NOCMD
599 if(strncmp(argv[idx], "-c", 2) == 0)
600 noPromptMode = TRUE;
602 if(strncmp(argv[idx], "-C", 2) == 0)
603 forcePromptMode = TRUE;
605 if(strncmp(argv[idx], "-http", 5) == 0)
607 noPromptMode = TRUE;
608 httpMode = TRUE;
611 if(strncmp(argv[idx], "-s", 2) == 0)
613 MAX_CPU_STACK = atoi(getArg(argv, argc, &idx));
615 if(MAX_CPU_STACK < 1024) MAX_CPU_STACK = 1024;
616 initStacks();
617 continue;
620 if(strncmp(argv[idx], "-p", 2) == 0 || strncmp(argv[idx], "-d", 2) == 0 )
622 if(strncmp(argv[idx], "-d", 2) == 0)
623 demonMode = TRUE;
625 IOdomain = getArg(argv, argc, &idx);
626 IOport = atoi(IOdomain);
628 setupServer(0);
629 continue;
632 if(strncmp(argv[idx], "-e", 2) == 0)
634 executeCommandLine(getArg(argv, argc, &idx), OUT_CONSOLE, &cmdStream);
635 exit(0);
638 if(strncmp(argv[idx], "-l", 2) == 0 || strncmp(argv[idx], "-L", 2) == 0)
640 logTraffic = (strncmp(argv[idx], "-L", 2) == 0) ? LOG_MORE : LOG_LESS;
641 realpath(getArg(argv, argc, &idx), logFile);
642 continue;
645 if(strncmp(argv[idx], "-m", 2) == 0)
647 #ifndef NEWLISP64
648 MAX_CELL_COUNT = abs(0x0010000 * atoi(getArg(argv, argc, &idx)));
649 #else
650 MAX_CELL_COUNT = abs(0x0008000 * atoi(getArg(argv, argc, &idx)));
651 #endif
652 continue;
655 if(strncmp(argv[idx], "-w", 2) == 0)
657 realpath(getArg(argv, argc, &idx), startupDir);
658 chdir(startupDir);
659 continue;
662 if(strcmp(argv[idx], "-h") == 0)
664 printHelpText();
665 exit(0);
667 #endif
669 loadFile(argv[idx], 0, 0, mainContext);
672 AFTER_ERROR_ENTRY:
674 if(isatty(fileno(IOchannel)))
676 isTTY = TRUE;
677 if(!noPromptMode)
678 varPrintf(OUT_CONSOLE, banner, ostype, IPV, banner2);
680 else
682 #ifdef WIN_32
683 /* its a faked FILE struct, see win32_fdopen() in nl-sock.c */
684 if(!isSocketStream(IOchannel))
685 #endif
686 setbuf(IOchannel,0);
687 if(forcePromptMode)
688 varPrintf(OUT_CONSOLE, banner, ostype, IPV, banner2);
692 errorReg = setjmp(errorJump);
694 setupAllSignals();
695 reset();
696 initStacks();
698 if(errorReg && !isNil((CELL*)errorEvent->contents) )
699 executeSymbol(errorEvent, NULL);
701 while(TRUE)
703 if(commandLineFlag == TRUE)
705 #ifdef READLINE
706 if(isTTY)
708 errnoSave = errno;
709 if((cmd = readline(prompt())) == NULL) exit(0);
710 errno = errnoSave; /* reset errno, set by readline() */
711 if(strlen(cmd) > 0) add_history(cmd);
712 executeCommandLine(cmd, OUT_CONSOLE, &cmdStream);
713 free(cmd);
714 continue;
717 if(IOchannel != stdin || forcePromptMode)
718 varPrintf(OUT_CONSOLE, prompt());
719 #endif
720 #ifndef READLINE
721 if(isTTY || IOchannel != stdin || forcePromptMode)
722 varPrintf(OUT_CONSOLE, prompt());
723 #endif
724 if(IOchannel == NULL || fgets(command, MAX_LINE - 1, IOchannel) == NULL)
726 if(!demonMode) exit(1);
727 if(IOchannel != NULL) fclose(IOchannel);
728 setupServer(1);
729 continue;
732 executeCommandLine(command, OUT_CONSOLE, &cmdStream);
736 #ifndef WIN_32
737 return 0;
738 #endif
740 #endif
743 void printHelpText(void)
745 varPrintf(OUT_CONSOLE, copyright,
746 "usage: newlisp [file | url ...] [options ...] [file | url ...]\n\noptions:\n");
747 varPrintf(OUT_CONSOLE, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n%s\n\n",
748 " -h this help",
749 " -s <stacksize>",
750 " -m <max-mem-megabyte>",
751 " -l log connections only",
752 " -L log all",
753 " -p <port-number>",
754 " -d <port-number>",
755 " -e <quoted lisp expression>",
756 " -c no prompts, HTTP",
757 " -C force prompts",
758 " -http HTTP only",
759 " -w <working-directory>",
760 "more information at http://newlisp.org");
764 void setupServer(int reconnect)
766 if((IOchannel = serverFD(IOport, IOdomain, reconnect)) == NULL)
768 printf("newLISP server setup on %s failed.\n", IOdomain);
769 exit(1);
772 #ifdef WIN_32
773 if(!isSocketStream(IOchannel))
774 #endif
775 setbuf(IOchannel,0);
777 if(!reconnect && !noPromptMode)
778 varPrintf(OUT_CONSOLE, banner, ostype, IPV, ".");
782 char * prompt(void)
784 char * context;
785 static char string[32];
787 if(evalSilent || noPromptMode)
789 evalSilent = 0;
790 return("");
793 if(currentContext != mainContext)
794 context = currentContext->name;
795 else context = "";
797 if(traceFlag & TRACE_SIGINT)
799 traceFlag &= ~TRACE_SIGINT;
800 longjmp(errorJump, errorReg);
803 if(traceFlag)
804 snprintf(string, 31, "%s %d> ", context, recursionCount);
805 else
806 snprintf(string, 31, "%s> ", context);
808 return(string);
812 void reset()
814 recoverEnvironment(0);
816 collectGarbage();
818 if(printDevice) close((int)printDevice);
819 printDevice = recursionCount = resultStackIdx = envStackIdx = lambdaStackIdx = 0;
820 symbolProtectionLevel = traceFlag = prettyPrintFlags = 0;
821 evalFunc = NULL;
822 pushResultFlag = commandLineFlag = TRUE;
823 currentContext = mainContext;
827 void recoverEnvironment(int index)
829 SYMBOL * symbol;
830 CELL * cell;
832 while(envStackIdx > index)
834 symbol = (SYMBOL *)popEnvironment();
835 cell = (CELL*)popEnvironment();
836 if(cell != (CELL*)symbol->contents)
838 deleteList((CELL*)symbol->contents);
839 symbol->contents = (UINT)cell;
840 if(isProtected(symbol->flags))
841 symbol->flags &= ~SYMBOL_PROTECTED;
847 void executeCommandLine(char * command, int outDevice, STREAM * cmdStream)
849 STREAM stream;
850 char buff[MAX_LINE];
852 if(strlen(command) == 0 || *command == '\n') return;
854 if(noPromptMode)
856 if(logTraffic == LOG_MORE)
857 writeLog(command, 0);
858 if(strncmp(command, "GET /", 5) == 0)
860 executeHTTPrequest(command + 5, HTTP_GET_URL);
861 return;
863 else if(strncmp(command, "HEAD /", 6) == 0)
865 executeHTTPrequest(command + 5, HTTP_GET_HEAD);
866 return;
868 else if(strncmp(command, "PUT /", 5) == 0)
870 executeHTTPrequest(command + 5, HTTP_PUT_URL);
871 return;
873 else if(strncmp(command, "POST /", 6) == 0)
875 executeHTTPrequest(command + 6, HTTP_POST_URL);
876 return;
878 else if(strncmp(command, "DELETE /", 8) == 0)
880 executeHTTPrequest(command + 8, HTTP_DELETE_URL);
881 return;
884 if(httpMode) return;
887 if(*command == '!' && *(command + 1) != ' ' && strlen(command) > 2)
889 system((command + 1));
890 return;
893 if(cmdStream != NULL && strncmp(command, "[cmd]", 5) == 0)
895 openStrStream(cmdStream, 1024, TRUE);
896 while(fgets(buff, MAX_LINE - 1, IOchannel) != NULL)
898 if(strncmp(buff, "[/cmd]", 6) == 0)
900 if(logTraffic)
902 writeLog(cmdStream->buffer, 0);
903 writeLog(buff, 0);
905 /* make stream for evaluation */
906 makeStreamFromString(&stream, cmdStream->buffer);
907 evaluateStream(&stream, OUT_CONSOLE, 0);
908 closeStrStream(cmdStream);
909 return;
911 writeStreamStr(cmdStream, buff, 0);
913 closeStrStream(cmdStream);
914 if(!demonMode) exit(1);
915 if(IOchannel != NULL) fclose(IOchannel);
916 setupServer(1);
917 return;
920 if(logTraffic) writeLog(command, TRUE);
921 prettyPrintLength = 0;
923 makeStreamFromString(&stream, command);
924 evaluateStream(&stream, outDevice, 0);
926 return;
930 CELL * evaluateStream(STREAM * stream, UINT outDevice, int flag)
932 CELL * program;
933 CELL * eval = nilCell;
934 int resultIdxSave;
935 int result;
937 result = TRUE;
938 resultIdxSave = resultStackIdx;
939 while(result)
941 pushResult(program = getCell(CELL_QUOTE));
942 result = compileExpression(stream, program);
943 if(result)
945 if(flag && eval != nilCell) deleteList(eval);
946 eval = evaluateExpression((CELL *)program->contents);
947 if(outDevice != 0 && !evalSilent)
949 printCell(eval, TRUE, outDevice);
950 varPrintf(outDevice, "\n");
951 if(logTraffic == LOG_MORE)
953 printCell(eval, TRUE, OUT_LOG);
954 writeLog("", TRUE);
957 if(flag) eval = copyCell(eval);
959 cleanupResults(resultIdxSave);
962 if(flag) return(eval);
963 return(NULL);
967 long executeSymbol(SYMBOL * symbol, CELL * params)
969 CELL * program;
970 CELL * cell;
971 int resultIdxSave;
973 if(symbol == nilSymbol || symbol == NULL) return(0);
974 resultIdxSave = resultStackIdx;
975 pushResult(program = getCell(CELL_EXPRESSION));
976 cell = getCell(CELL_SYMBOL);
977 program->contents = (UINT)cell;
978 cell->contents = (UINT)symbol;
979 if(params != NULL) cell->next = params;
980 cell = evaluateExpression(program);
981 cleanupResults(resultIdxSave);
983 return(cell->contents);
987 void initialize()
989 int i;
990 SYMBOL * symbol;
991 CELL * pCell;
992 char symName[8];
994 /* build true and false cells */
996 nilCell = getCell(CELL_NIL);
997 trueCell = getCell(CELL_TRUE);
998 nilCell->contents = (UINT)nilCell;
999 trueCell->contents = (UINT)trueCell;
1000 nilCell->next = trueCell->next = nilCell;
1002 /* build first symbol and context MAIN */
1003 mainContext = currentContext = translateCreateSymbol("MAIN", CELL_CONTEXT, NULL, TRUE);
1004 makeContextFromSymbol(mainContext, mainContext);
1006 /* build symbols for primitives */
1008 for(i = 0; primitive[i].name != NULL; i++)
1010 pCell = getCell(CELL_PRIMITIVE);
1011 symbol = translateCreateSymbol(
1012 primitive[i].name, CELL_PRIMITIVE, mainContext, TRUE);
1013 symbol->contents = (UINT)pCell;
1014 symbol->flags = primitive[i].prettyPrint | SYMBOL_PROTECTED | SYMBOL_GLOBAL | SYMBOL_BUILTIN;
1015 pCell->contents = (UINT)primitive[i].function;
1016 pCell->aux = (UINT)symbol->name;
1019 /* build true, nil, * and ? symbols */
1021 trueSymbol = translateCreateSymbol("true", CELL_TRUE, mainContext, TRUE);
1022 trueSymbol->contents = (UINT)trueCell;
1023 nilSymbol = translateCreateSymbol("nil", CELL_NIL, mainContext, TRUE);
1024 nilSymbol->contents = (UINT)nilCell;
1025 starSymbol = translateCreateSymbol("*", CELL_PRIMITIVE, mainContext, TRUE);
1026 plusSymbol = translateCreateSymbol("+", CELL_PRIMITIVE, mainContext, TRUE);
1027 questionSymbol = translateCreateSymbol("?", CELL_NIL, mainContext, TRUE);
1028 atSymbol = translateCreateSymbol("@", CELL_NIL, mainContext, TRUE);
1029 argsSymbol = translateCreateSymbol("$args", CELL_NIL, mainContext, TRUE);
1030 mainArgsSymbol = translateCreateSymbol("$main-args", CELL_NIL, mainContext, TRUE);
1031 dolistIdxSymbol = translateCreateSymbol("$idx", CELL_NIL, mainContext, TRUE);
1033 for(i = 0; i < MAX_REGEX_EXP; i++)
1035 snprintf(symName, 8, "$%d", i);
1036 sysSymbol[i] = translateCreateSymbol(symName, CELL_NIL, mainContext, TRUE);
1037 sysSymbol[i]->flags |= SYMBOL_GLOBAL | SYMBOL_BUILTIN;
1040 currentFunc = errorEvent = timerEvent = nilSymbol;
1042 trueSymbol->flags |= SYMBOL_PROTECTED | SYMBOL_GLOBAL;
1043 nilSymbol->flags |= SYMBOL_PROTECTED | SYMBOL_GLOBAL;
1044 questionSymbol->flags |= SYMBOL_PROTECTED | SYMBOL_GLOBAL;
1045 atSymbol->flags |= SYMBOL_GLOBAL | SYMBOL_BUILTIN;
1046 argsSymbol->flags |= SYMBOL_GLOBAL | SYMBOL_BUILTIN | SYMBOL_PROTECTED;
1047 mainArgsSymbol->flags |= SYMBOL_GLOBAL | SYMBOL_BUILTIN | SYMBOL_PROTECTED;
1048 dolistIdxSymbol->flags |= SYMBOL_GLOBAL | SYMBOL_BUILTIN | SYMBOL_PROTECTED;
1049 argsSymbol->contents = (UINT)getCell(CELL_EXPRESSION);
1051 symbol = translateCreateSymbol("ostype", CELL_STRING, mainContext, TRUE);
1052 symbol->contents = (UINT)stuffString(ostype);
1053 symbol->flags |= SYMBOL_GLOBAL | SYMBOL_BUILTIN | SYMBOL_PROTECTED;
1055 /* init signal handlers */
1056 for(i = 0; i < 32; i++)
1057 symHandler[i] = nilSymbol;
1059 /* init readLineStream */
1060 openStrStream(&readLineStream, 16, 0);
1064 void initStacks()
1066 MAX_ENV_STACK = (MAX_CPU_STACK * 8 * 2);
1067 MAX_RESULT_STACK = (MAX_CPU_STACK * 2);
1068 if(envStack != NULL) freeMemory(envStack);
1069 if(resultStack != NULL) freeMemory(resultStack);
1070 if(lambdaStack != NULL) freeMemory(lambdaStack);
1071 envStack = (UINT *)allocMemory((MAX_ENV_STACK + 16) * sizeof(UINT));
1072 resultStack = (UINT *)allocMemory((MAX_RESULT_STACK + 16) * sizeof(UINT));
1073 lambdaStack = (UINT *)allocMemory((MAX_RESULT_STACK + 16) * sizeof(UINT));
1074 envStackIdx = resultStackIdx = lambdaStackIdx = 0;
1078 /* ------------------------- evaluate s-expression --------------------- */
1081 CELL * evaluateExpression(CELL * cell)
1083 CELL * result;
1084 CELL * args = NULL;
1085 CELL * pCell = NULL;
1086 SYMBOL * newContext = NULL;
1087 SYMBOL * sPtr;
1088 int resultIdxSave = 0;
1090 if(cell->type & EVAL_SELF_TYPE_MASK) return cell;
1091 switch(cell->type)
1093 case CELL_SYMBOL:
1094 case CELL_CONTEXT:
1095 return((CELL*)((SYMBOL *)cell->contents)->contents);
1097 case CELL_QUOTE:
1098 return((CELL *)cell->contents);
1100 case CELL_EXPRESSION:
1101 args = (CELL *)cell->contents;
1102 resultIdxSave = resultStackIdx;
1104 if(++recursionCount > (int)MAX_CPU_STACK)
1105 fatalError(ERR_OUT_OF_CALL_STACK, args, 0);
1107 if(args->type == CELL_SYMBOL) /* precheck for speedup */
1109 newContext = ((SYMBOL *)args->contents)->context;
1110 pCell = (CELL*)((SYMBOL *)args->contents)->contents;
1112 else if(args->type == CELL_DYN_SYMBOL)
1114 sPtr = getDynamicSymbol(args);
1115 newContext = sPtr->context;
1116 pCell = (CELL *)sPtr->contents;
1118 else
1120 pCell = evaluateExpression(args);
1121 newContext = currentContext;
1124 if(traceFlag) traceEntry(cell, pCell, args);
1126 if(pCell->type == CELL_PRIMITIVE)
1128 evalFunc = (CELL *(*)(CELL*))pCell->contents;
1129 result = (*evalFunc)(args->next);
1130 evalFunc = NULL;
1131 break;
1134 if(pCell->type == CELL_LAMBDA)
1136 pushLambda(args);
1137 result = evaluateLambda((CELL *)pCell->contents, args->next, newContext);
1138 --lambdaStackIdx;
1139 break;
1142 if(pCell->type == CELL_MACRO)
1144 result = evaluateMacro((CELL *)pCell->contents, args->next, newContext);
1145 break;
1148 if(pCell->type == CELL_IMPORT_CDECL
1149 #ifdef WIN_32
1150 || pCell->type == CELL_IMPORT_DLL
1151 #endif
1154 result = executeLibfunction(pCell, args->next);
1155 break;
1158 /* check for 'default' functor
1159 * allow function call with context name, i.e: (ctx)
1160 * assumes that a ctx:ctx contains a function
1162 if(pCell->type == CELL_CONTEXT)
1164 newContext = (SYMBOL *)pCell->contents;
1165 sPtr= translateCreateSymbol(newContext->name, CELL_NIL, newContext, TRUE);
1166 pCell = (CELL *)sPtr->contents;
1168 if(pCell->type == CELL_PRIMITIVE)
1170 evalFunc = (CELL *(*)(CELL*))pCell->contents;
1171 result = (*evalFunc)(args->next);
1172 evalFunc = NULL;
1173 break;
1176 else if(pCell->type == CELL_LAMBDA)
1178 pushLambda(args);
1179 result = evaluateLambda((CELL *)pCell->contents, args->next, newContext);
1180 --lambdaStackIdx;
1181 break;
1184 else if(pCell->type == CELL_MACRO)
1186 result = evaluateMacro((CELL *)pCell->contents, args->next, newContext);
1187 break;
1193 /* allow 'implicit indexing' if pCell is a list, array, string or number:
1194 (pCell idx1 idx2 ...)
1197 if(args->next != nilCell)
1199 if(pCell->type == CELL_EXPRESSION)
1200 result = copyCell(implicitIndexList(pCell, args->next));
1202 else if(pCell->type == CELL_ARRAY)
1203 result = copyCell(implicitIndexArray(pCell, args->next));
1205 else if(pCell->type == CELL_STRING)
1206 result = implicitIndexString(pCell, args->next);
1208 else if(isNumber(pCell->type))
1209 result = implicitNrestSlice(pCell, args->next);
1211 else result = errorProcExt(ERR_INVALID_FUNCTION, cell);
1213 else
1214 result = errorProcExt(ERR_INVALID_FUNCTION, cell);
1215 break;
1217 case CELL_DYN_SYMBOL:
1218 return((CELL*)(getDynamicSymbol(cell))->contents);
1220 default:
1221 result = nilCell;
1224 while(resultStackIdx > resultIdxSave)
1225 deleteList(popResult());
1227 if(pushResultFlag)
1229 if(resultStackIdx > MAX_RESULT_STACK)
1230 fatalError(ERR_OUT_OF_CALL_STACK, pCell, 0);
1231 pushResult(result);
1233 else pushResultFlag = TRUE;
1235 if(traceFlag) traceExit(result, cell, pCell, args);
1236 --recursionCount;
1237 return(result);
1241 CELL * evaluateExpressionSafe(CELL * cell, int * errNo)
1243 jmp_buf errorJumpSave;
1244 CELL * result;
1246 memcpy(errorJumpSave, errorJump, sizeof(jmp_buf));
1247 if((*errNo = setjmp(errorJump)) != 0)
1249 memcpy(errorJump, errorJumpSave, sizeof(jmp_buf));
1250 return(NULL);
1253 result = evaluateExpression(cell);
1254 memcpy(errorJump, errorJumpSave, sizeof(jmp_buf));
1255 return(result);
1259 /* a symbol belonging to a dynamic context */
1260 /* the parent context symbol points to the real context */
1261 /* cell->contents -> name str of this symbol */
1262 /* cell->aux -> symbol var which holds context (dynamic) */
1263 /* ((SYMBOL*)cell->aux)->contents -> context cell */
1264 SYMBOL * getDynamicSymbol(CELL * cell)
1266 CELL * contextCell;
1268 contextCell = (CELL *)((SYMBOL *)cell->aux)->contents;
1269 if(contextCell->type != CELL_CONTEXT)
1270 fatalError(ERR_CONTEXT_EXPECTED, stuffSymbol((SYMBOL*)cell->aux), TRUE);
1272 return(translateCreateSymbol(
1273 (char*)cell->contents, /* name of dyn symbol */
1274 CELL_NIL,
1275 (SYMBOL*)contextCell->contents, /* contextPtr */
1276 TRUE));
1280 CELL * evalCheckProtected(CELL * cell, CELL * * flagPtr)
1282 CELL * result;
1283 SYMBOL * sPtr;
1285 if(isSymbol(cell->type))
1287 if(cell->type == CELL_SYMBOL)
1288 sPtr = (SYMBOL *)cell->contents;
1289 else
1290 sPtr = getDynamicSymbol(cell);
1292 if(isProtected(sPtr->flags))
1293 return(errorProcExt(ERR_SYMBOL_PROTECTED, cell));
1295 return((CELL *)sPtr->contents);
1298 symbolProtectionLevel = recursionCount;
1299 result = evaluateExpression(cell);
1300 if(symbolProtectionLevel == 0xFFFFFFFF)
1302 if(flagPtr == NULL)
1303 return(errorProcExt(ERR_SYMBOL_PROTECTED, cell));
1304 else *flagPtr = cell;
1307 symbolProtectionLevel = 0;
1308 return(result);
1312 /* -------------------- evaluate lambda function ----------------------- */
1314 CELL * evaluateLambda(CELL * localLst, CELL * arg, SYMBOL * newContext)
1316 CELL * local;
1317 CELL * result = nilCell;
1318 CELL * cell;
1319 SYMBOL * symbol;
1320 SYMBOL * contextSave;
1321 int localCount = 0;
1323 if(envStackIdx > (UINT)MAX_ENV_STACK)
1324 return(errorProc(ERR_OUT_OF_ENV_STACK));
1326 if(localLst->type != CELL_EXPRESSION)
1327 return(errorProcExt(ERR_INVALID_LAMBDA, localLst));
1329 /* evaluate arguments */
1330 if(arg != nilCell)
1332 /* this symbol precheck does 10% speed improvment on lambdas */
1333 if(arg->type == CELL_SYMBOL)
1334 cell = result = copyCell((CELL*)((SYMBOL *)arg->contents)->contents);
1335 else
1336 cell = result = copyCell(evaluateExpression(arg));
1338 while((arg = arg->next) != nilCell)
1340 if(arg->type == CELL_SYMBOL)
1341 cell->next = copyCell((CELL*)((SYMBOL *)arg->contents)->contents);
1342 else
1343 cell->next = copyCell(evaluateExpression(arg));
1345 cell = cell->next;
1349 /* change to new context */
1350 contextSave = currentContext;
1351 currentContext = newContext;
1353 /* save environment and get parameters */
1354 local = (CELL*)localLst->contents;
1355 GET_LOCAL:
1357 if(local->type == CELL_SYMBOL)
1358 symbol = (SYMBOL *)local->contents;
1359 /* get default parameters */
1360 else if(local->type == CELL_EXPRESSION)
1362 if(((CELL*)local->contents)->type == CELL_SYMBOL)
1364 cell = (CELL *)local->contents;
1365 if(cell->type == CELL_SYMBOL)
1367 symbol = (SYMBOL *)cell->contents;
1368 if(result == nilCell)
1369 result = copyCell(evaluateExpression(cell->next));
1371 else goto GOT_LOCALS;
1373 else goto GOT_LOCALS;
1375 else goto GOT_LOCALS;
1377 if(isProtected(symbol->flags))
1378 return(errorProcExt(ERR_SYMBOL_PROTECTED, local));
1380 /* save symbol environment */
1381 pushEnvironment(symbol->contents);
1382 pushEnvironment((UINT)symbol);
1384 /* fill local symbols */
1385 symbol->contents = (UINT)result;
1386 cell = result;
1387 result = result->next;
1389 /* unlink list */
1390 cell->next = nilCell;
1392 local = local->next;
1393 localCount++;
1395 goto GET_LOCAL;
1397 GOT_LOCALS:
1398 /* put unassigned args in $args */
1399 pushEnvironment(argsSymbol->contents);
1400 pushEnvironment((UINT)argsSymbol);
1401 argsSymbol->contents = (UINT)getCell(CELL_EXPRESSION);
1402 if(result != nilCell)
1403 ((CELL*)argsSymbol->contents)->contents = (UINT)result;
1404 ++localCount;
1406 /* evaluate body expressions */
1407 cell = localLst->next;
1408 result = nilCell;
1409 while(cell != nilCell)
1411 result = evaluateExpression(cell);
1412 cell = cell->next;
1414 result = copyCell(result);
1416 /* recover environment of local symbols */
1417 while(localCount--)
1419 symbol = (SYMBOL *)popEnvironment();
1420 if(isProtected(symbol->flags) && (symbol != argsSymbol))
1421 symbol->flags &= ~SYMBOL_PROTECTED;
1422 deleteList((CELL *)symbol->contents);
1423 symbol->contents = popEnvironment();
1426 currentContext = contextSave;
1427 return(result);
1431 CELL * evaluateMacro(CELL * localLst, CELL * arg, SYMBOL * newContext)
1433 CELL * local;
1434 CELL * result;
1435 CELL * cell;
1436 SYMBOL * symbol;
1437 SYMBOL * contextSave;
1438 int localCount;
1440 if(envStackIdx > (UINT)MAX_ENV_STACK)
1441 return(errorProc(ERR_OUT_OF_ENV_STACK));
1443 if(localLst->type != CELL_EXPRESSION)
1444 return(errorProcExt(ERR_INVALID_MACRO, localLst));
1445 local = (CELL *)localLst->contents;
1447 contextSave = currentContext;
1448 currentContext = newContext;
1450 /* save environment and get parameters */
1451 localCount = 0;
1452 GET_ARGS:
1454 if(local->type == CELL_SYMBOL)
1455 symbol = (SYMBOL *)local->contents;
1456 /* get default parameters */
1457 else if(local->type == CELL_EXPRESSION)
1459 if(((CELL*)local->contents)->type == CELL_SYMBOL)
1461 cell = (CELL *)local->contents;
1462 if(cell->type == CELL_SYMBOL)
1464 symbol = (SYMBOL *)cell->contents;
1465 if(arg == nilCell)
1466 arg = evaluateExpression(cell->next);
1468 else goto GOT_ARGS;
1470 else goto GOT_ARGS;
1472 else goto GOT_ARGS;
1474 if(isProtected(symbol->flags))
1475 return(errorProcExt(ERR_SYMBOL_PROTECTED, local));
1477 pushEnvironment(symbol->contents);
1478 pushEnvironment((UINT)symbol);
1479 symbol->contents = (UINT)copyCell(arg);
1480 local = local->next;
1481 arg = arg->next;
1482 localCount++;
1484 goto GET_ARGS;
1486 GOT_ARGS:
1488 pushEnvironment(argsSymbol->contents);
1489 pushEnvironment((UINT)argsSymbol);
1490 argsSymbol->contents = (UINT)getCell(CELL_EXPRESSION);
1491 if(arg != nilCell)
1492 ((CELL*)argsSymbol->contents)->contents = (UINT)copyList(arg);
1493 ++localCount;
1495 arg = localLst->next;
1496 result = nilCell;
1498 while(arg != nilCell)
1500 result = evaluateExpression(arg);
1501 arg = arg->next;
1503 result = copyCell(result);
1505 while(localCount--)
1507 symbol = (SYMBOL *)popEnvironment();
1508 if(isProtected(symbol->flags) && (symbol != argsSymbol))
1509 symbol->flags &= ~SYMBOL_PROTECTED;
1510 deleteList((CELL *)symbol->contents);
1511 symbol->contents = popEnvironment();
1514 currentContext = contextSave;
1515 return(result);
1519 /* -------------- list/cell creation/deletion routines ---------------- */
1522 CELL * stuffInteger(UINT contents)
1524 CELL * cell;
1526 cell = getCell(CELL_LONG);
1527 cell->contents = (UINT) contents;
1528 return(cell);
1531 #ifndef NEWLISP64
1532 CELL * stuffInteger64(INT64 contents)
1534 CELL * cell;
1536 cell = getCell(CELL_INT64);
1537 *(INT64 *)&cell->aux = contents;
1538 return(cell);
1540 #endif
1543 CELL * stuffIntegerList(int argc, ...)
1545 CELL * cell;
1546 CELL * list;
1547 va_list ap;
1549 va_start(ap, argc);
1551 list = getCell(CELL_EXPRESSION);
1552 list->contents = (UINT)stuffInteger(va_arg(ap, UINT));
1553 cell = (CELL *)list->contents;
1555 while(--argc)
1557 cell->next = stuffInteger(va_arg(ap, UINT));
1558 cell = cell->next;
1560 va_end(ap);
1562 return(list);
1566 CELL * stuffString(char * string)
1568 CELL * cell;
1570 cell = getCell(CELL_STRING);
1571 cell->aux = strlen(string) + 1;
1572 cell->contents = (UINT)allocMemory((UINT)cell->aux);
1573 memcpy((void *)cell->contents, string, (UINT)cell->aux);
1574 return(cell);
1578 CELL * stuffStringN(char * string, int len)
1580 CELL * cell;
1582 cell = getCell(CELL_STRING);
1583 cell->aux = len + 1;
1584 cell->contents = (UINT)allocMemory((UINT)cell->aux);
1585 memcpy((void *)cell->contents, string, len);
1586 *(char*)(cell->contents + len) = 0;
1587 return(cell);
1590 CELL * stuffFloat(double * floatPtr)
1592 CELL * cell;
1594 cell = getCell(CELL_FLOAT);
1595 #ifndef NEWLISP64
1596 *(double *)&cell->aux = *floatPtr;
1597 #else
1598 *(double *)&cell->contents = *floatPtr;
1599 #endif
1600 return(cell);
1604 CELL * stuffSymbol(SYMBOL * sPtr)
1606 CELL * cell;
1608 cell = getCell(CELL_SYMBOL);
1609 cell->contents = (UINT)sPtr;
1610 return(cell);
1613 ssize_t convertNegativeOffset(ssize_t offset, CELL * list)
1615 int len=0;
1617 while(list != nilCell)
1619 ++len;
1620 list = list->next;
1622 offset = len + offset;
1623 if(offset < 0)
1624 errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS);
1625 return(offset);
1628 /* ------------------------ creating and freeing cells ------------------- */
1630 CELL * getCell(int type)
1632 CELL * cell;
1634 if(firstFreeCell == NULL) allocBlock();
1635 cell = firstFreeCell;
1636 firstFreeCell = cell->next;
1637 ++cellCount;
1639 cell->type = type;
1640 cell->next = nilCell;
1641 cell->aux = (UINT)nilCell;
1642 cell->contents = (UINT)nilCell;
1644 return(cell);
1648 CELL * copyCell(CELL * cell)
1650 CELL * newCell;
1651 UINT len;
1653 if(firstFreeCell == NULL) allocBlock();
1654 newCell = firstFreeCell;
1655 firstFreeCell = newCell->next;
1656 ++cellCount;
1658 newCell->type = cell->type;
1659 newCell->next = nilCell;
1660 newCell->aux = cell->aux;
1661 newCell->contents = cell->contents;
1663 if(isEnvelope(cell->type))
1665 if(cell->type == CELL_ARRAY)
1666 newCell->contents = (UINT)copyArray(cell);
1667 else
1669 newCell->contents = (UINT)copyList((CELL *)cell->contents);
1670 newCell->aux = (UINT)lastCellCopied; /* last element optimization */
1673 else if(cell->type == CELL_STRING)
1675 newCell->contents = (UINT)allocMemory((UINT)cell->aux);
1676 memcpy((void *)newCell->contents, (void*)cell->contents, (UINT)cell->aux);
1678 else if(cell->type == CELL_DYN_SYMBOL)
1680 len = strlen((char *)cell->contents);
1681 newCell->contents = (UINT)allocMemory(len + 1);
1682 memcpy((char *)newCell->contents, (char *)cell->contents, len + 1);
1685 return(newCell);
1689 /* this routine must be called with the list head
1690 if copying with envelope call copyCell() instead */
1691 CELL * copyList(CELL * cell)
1693 CELL * firstCell;
1694 CELL * newCell;
1696 if(cell == nilCell || cell == trueCell) return(lastCellCopied = cell);
1697 firstCell = newCell = copyCell(cell);
1699 while((cell = cell->next) != nilCell)
1701 newCell->next = copyCell(cell);
1702 newCell = newCell->next;
1705 lastCellCopied = newCell;
1706 return(firstCell);
1710 /* for deleting lists _and_ cells */
1711 void deleteList(CELL * cell)
1713 CELL * next;
1715 while(cell != nilCell)
1717 if(isEnvelope(cell->type))
1719 if(cell->type == CELL_ARRAY)
1720 deleteArray(cell);
1721 else
1722 deleteList((CELL *)cell->contents);
1725 else if(cell->type == CELL_STRING || cell->type == CELL_DYN_SYMBOL)
1726 freeMemory( (void *)cell->contents);
1728 next = cell->next;
1730 /* free cell */
1731 if(cell == trueCell)
1733 cell = next;
1734 continue;
1737 cell->type = CELL_FREE;
1738 cell->next = firstFreeCell;
1739 firstFreeCell = cell;
1740 --cellCount;
1742 cell = next;
1746 /* --------------- cell / memory allocation and deallocation ------------- */
1748 CELL * cellMemory = NULL;
1749 CELL * cellBlock = NULL;
1751 void allocBlock()
1753 int i;
1755 if(cellCount > MAX_CELL_COUNT) fatalError(ERR_NOT_ENOUGH_MEMORY, NULL, 0);
1757 if(cellMemory == NULL)
1759 cellMemory = (CELL *)allocMemory((MAX_BLOCK + 1) * sizeof(CELL));
1760 cellBlock = cellMemory;
1762 else
1764 (cellBlock + MAX_BLOCK)->next =
1765 (CELL *)allocMemory((MAX_BLOCK + 1) * sizeof(CELL));
1766 cellBlock = (cellBlock + MAX_BLOCK)->next;
1769 for(i = 0; i < MAX_BLOCK; i++)
1771 (cellBlock + i)->type = CELL_FREE;
1772 (cellBlock + i)->next = (cellBlock + i + 1);
1774 (cellBlock + MAX_BLOCK - 1)->next = NULL;
1775 (cellBlock + MAX_BLOCK)->next = NULL;
1776 firstFreeCell = cellBlock;
1780 void * allocMemory(size_t nbytes)
1782 void * ptr;
1784 if( (ptr = (void *)malloc(nbytes)) == NULL)
1785 fatalError(ERR_NOT_ENOUGH_MEMORY, NULL, 0);
1787 return(ptr);
1790 void * callocMemory(size_t nbytes)
1792 void * ptr;
1794 if( (ptr = (void *)calloc(nbytes, 1)) == NULL)
1795 fatalError(ERR_NOT_ENOUGH_MEMORY, NULL, 0);
1797 return(ptr);
1800 void * reallocMemory(void * prevPtr, UINT size)
1802 void * ptr;
1804 if( (ptr = realloc(prevPtr, size)) == NULL)
1805 fatalError(ERR_NOT_ENOUGH_MEMORY, NULL, 0);
1807 return(ptr);
1810 /* ----------- garbage collection , only required on error --------------- */
1812 void markReferences(SYMBOL * sPtr);
1813 void markList(CELL * cell);
1814 void sweepGarbage(void);
1815 void relinkCells(void);
1818 void collectGarbage()
1820 resultStackIdx = 0;
1821 nilCell->type |= (UINT)0x00008000;
1822 markReferences((SYMBOL *)((CELL *)mainContext->contents)->aux);
1823 sweepGarbage();
1824 relinkCells();
1828 void markReferences(SYMBOL * sPtr)
1830 CELL * content;
1832 if(sPtr != NIL_SYM && sPtr != NULL)
1834 markReferences(sPtr->left);
1835 markList((CELL *)sPtr->contents);
1836 if((symbolType(sPtr) & 0xFF) == CELL_CONTEXT && sPtr != mainContext)
1838 content = (CELL *)sPtr->contents;
1839 if((SYMBOL*)content->contents != mainContext && (SYMBOL*)content->contents == sPtr)
1840 markReferences((SYMBOL *)content->aux);
1842 markReferences(sPtr->right);
1847 void markList(CELL * cell)
1849 while(cell != nilCell)
1851 cell->type |= (UINT)0x00008000;
1852 if(isEnvelope(cell->type & RAW_TYPE_MASK))
1854 if((RAW_TYPE_MASK & cell->type) == CELL_ARRAY)
1855 markArray(cell);
1856 else
1857 markList((CELL *)cell->contents);
1859 cell = cell->next;
1864 void sweepGarbage()
1866 CELL * blockPtr;
1867 CELL * lastBlockPtr;
1868 CELL * memPtr;
1869 int i, freed;
1871 lastBlockPtr = blockPtr = cellMemory;
1872 while(blockPtr != NULL)
1874 for(i = freed = 0; i < MAX_BLOCK; i++)
1876 if(*(UINT *)blockPtr != CELL_FREE)
1878 if( *(UINT *)blockPtr & (UINT)0x00008000)
1879 *(UINT *)blockPtr &= (UINT)0x00007FFF;
1880 else
1882 blockPtr->type = CELL_FREE;
1883 --cellCount;
1884 freed++;
1887 else freed++;
1888 blockPtr++;
1890 if(freed == MAX_BLOCK)
1892 memPtr = blockPtr->next;
1893 freeMemory(lastBlockPtr->next);
1894 lastBlockPtr->next = memPtr;
1895 blockPtr = memPtr;
1897 else
1899 lastBlockPtr = blockPtr;
1900 blockPtr = blockPtr->next;
1906 void relinkCells(void)
1908 CELL * blockPtr;
1909 CELL * lastFreeCell = NULL;
1910 int i;
1912 cellBlock = blockPtr = cellMemory;
1913 firstFreeCell = NULL;
1914 while(blockPtr != NULL)
1916 cellBlock = blockPtr;
1917 for(i = 0; i < MAX_BLOCK; i++)
1919 if(*(UINT *)blockPtr == CELL_FREE)
1921 if(firstFreeCell == NULL)
1922 firstFreeCell = lastFreeCell = blockPtr;
1923 else
1925 lastFreeCell->next = blockPtr;
1926 lastFreeCell = blockPtr;
1929 ++blockPtr;
1931 blockPtr = blockPtr->next;
1933 lastFreeCell->next = NULL;
1937 void cleanupResults(int from)
1939 while(resultStackIdx > from)
1940 deleteList(popResult());
1943 /* -------------------------- I/O routines ------------------------------ */
1945 UINT printDevice;
1946 STREAM errorStream;
1947 void prettyPrint(UINT device);
1949 void varPrintf(UINT device, char * format, ...)
1951 char * buffer;
1952 va_list argptr;
1954 va_start(argptr,format);
1956 /* new in 7201 , defined in nl-filesys.c if not in libc */
1957 vasprintf(&buffer, format, argptr);
1959 prettyPrintLength += strlen(buffer);
1960 switch(device)
1962 case OUT_NULL:
1963 return;
1964 case OUT_DEVICE:
1965 if(printDevice != 0)
1967 write(printDevice, buffer, strlen(buffer));
1968 break;
1970 case OUT_CONSOLE:
1971 #ifdef LIBRARY
1972 writeStreamStr(&libStrStream, buffer, 0);
1973 return;
1974 #else
1975 if(IOchannel == stdin)
1977 printf("%s", buffer);
1978 if(!isTTY) fflush(NULL);
1980 else
1982 if(IOchannel != NULL)
1983 #ifndef WIN_32
1984 fprintf(IOchannel, "%s", buffer);
1985 #else
1986 fprintf(IOchannel, buffer);
1987 #endif
1989 break;
1990 #endif
1991 case OUT_LOG:
1992 writeLog(buffer, 0);
1993 break;
1994 default:
1995 writeStreamStr((STREAM *)device, buffer, 0);
1996 break;
1999 freeMemory(buffer);
2001 va_end(argptr);
2005 int printCell(CELL * cell, UINT printFlag, UINT device)
2007 SYMBOL * sPtr;
2008 SYMBOL * sp;
2010 switch(cell->type)
2012 case CELL_NIL:
2013 varPrintf(device, "nil"); break;
2015 case CELL_TRUE:
2016 varPrintf(device, "true"); break;
2018 case CELL_LONG:
2019 varPrintf(device,"%ld", cell->contents); break;
2021 #ifndef NEWLISP64
2022 case CELL_INT64:
2023 #ifdef TRU64
2024 varPrintf(device,"%ld", *(INT64 *)&cell->aux); break;
2025 #else
2026 #ifdef WIN_32
2027 varPrintf(device,"%I64d", *(INT64 *)&cell->aux); break;
2028 #else
2029 varPrintf(device,"%lld", *(INT64 *)&cell->aux); break;
2030 #endif
2031 #endif
2032 #endif
2033 case CELL_FLOAT:
2034 #ifndef NEWLISP64
2035 varPrintf(device,"%1.10g",*(double *)&cell->aux);
2036 #else
2037 varPrintf(device,"%1.10g",*(double *)&cell->contents);
2038 #endif
2039 break;
2041 case CELL_STRING:
2042 if(printFlag)
2043 printString((char *)cell->contents, device, cell->aux - 1);
2044 else
2045 varPrintf(device,"%s",cell->contents);
2046 break;
2048 case CELL_SYMBOL:
2049 case CELL_CONTEXT:
2050 sPtr = (SYMBOL *)cell->contents;
2051 if(sPtr->context != currentContext
2052 /* if not global or global overwritten in current context */
2053 && (!(sPtr->flags & SYMBOL_GLOBAL) || (lookupSymbol(sPtr->name, currentContext)))
2054 && (symbolType(sPtr) != CELL_CONTEXT ||
2055 (SYMBOL *)((CELL*)sPtr->contents)->contents != sPtr)) /* context var */
2057 varPrintf(device,"%s:%s", (char*)((SYMBOL*)sPtr->context)->name, sPtr->name);
2058 break;
2060 /* overwriting global in MAIN */
2061 if(sPtr->context == currentContext
2062 && currentContext != mainContext
2063 && ((sp = lookupSymbol(sPtr->name, mainContext)) != NULL)
2064 && (sp->flags & SYMBOL_GLOBAL) )
2066 varPrintf(device,"%s:%s", currentContext->name, sPtr->name);
2067 break;
2070 varPrintf(device,"%s",sPtr->name);
2071 break;
2073 case CELL_PRIMITIVE:
2074 case CELL_IMPORT_CDECL:
2075 #ifdef WIN_32
2076 case CELL_IMPORT_DLL:
2077 #endif
2078 varPrintf(device,"%s <%lX>", (char *)cell->aux, cell->contents);
2079 break;
2081 case CELL_QUOTE:
2082 varPrintf(device, "'");
2083 prettyPrintFlags |= PRETTYPRINT_DOUBLE;
2084 printCell((CELL *)cell->contents, printFlag, device);
2085 break;
2087 case CELL_EXPRESSION:
2088 case CELL_LAMBDA:
2089 case CELL_MACRO:
2090 printExpression(cell, device);
2091 break;
2093 case CELL_DYN_SYMBOL:
2094 varPrintf(device, "%s:%s", ((SYMBOL*)cell->aux)->name, (char*)cell->contents);
2095 break;
2096 case CELL_ARRAY:
2097 printArray(cell, device);
2098 break;
2100 default:
2101 varPrintf(device,"?");
2104 prettyPrintFlags &= ~PRETTYPRINT_DOUBLE;
2105 return(1);
2109 void printString(char * str, UINT device, int size)
2111 char chr;
2113 if(size >= MAX_STRING)
2115 varPrintf(device, "[text]");
2116 while(size--) varPrintf(device, "%c", *str++);
2117 varPrintf(device, "[/text]");
2118 return;
2121 varPrintf(device,"\"");
2122 while(size--)
2124 switch(chr = *str++)
2126 case '\n': varPrintf(device,"\\n"); break;
2127 case '\r': varPrintf(device,"\\r"); break;
2128 case '\t': varPrintf(device,"\\t"); break;
2129 case '\\': varPrintf(device,"\\\\"); break;
2130 case '"': varPrintf(device,"\\%c",'"'); break;
2131 default:
2132 if((unsigned char)chr < 32 || (stringOutputRaw && (unsigned char)chr > 126))
2133 varPrintf(device,"\\%03u", (unsigned char)chr);
2134 else
2135 varPrintf(device,"%c",chr); break;
2138 varPrintf(device,"\"");
2142 int printExpression(CELL * cell, UINT device)
2144 CELL * item;
2145 int i, pFlags;
2147 item = (CELL *)cell->contents;
2150 if(prettyPrintPars <= prettyPrintCurrent ||
2151 prettyPrintLength > prettyPrintMaxLength)
2152 prettyPrint(device);
2154 if(cell->type == CELL_LAMBDA)
2156 varPrintf(device, "(lambda ");
2157 ++prettyPrintPars;
2159 else if(cell->type == CELL_MACRO)
2161 varPrintf(device, "(lambda-macro ");
2162 ++prettyPrintPars;
2164 else
2166 if(isSymbol(item->type))
2168 if(item->type == CELL_SYMBOL)
2169 pFlags = ((SYMBOL *)item->contents)->flags;
2170 else
2171 pFlags = 0;
2173 if((pFlags & PRINT_TYPE_MASK) != 0)
2175 prettyPrint(device);
2176 varPrintf(device, "(");
2177 ++prettyPrintPars;
2178 for(i = 0; i < (pFlags & PRINT_TYPE_MASK); i++)
2180 if(item == nilCell)
2181 {prettyPrintFlags |= PRETTYPRINT_DOUBLE; break;}
2182 printCell(item, TRUE, device);
2183 item = item->next;
2184 if(item != nilCell) varPrintf(device," ");
2185 else prettyPrintFlags |= PRETTYPRINT_DOUBLE;
2187 prettyPrint(device);
2189 else
2191 varPrintf(device, "(");
2192 ++prettyPrintPars;
2195 else
2197 varPrintf(device, "(");
2198 ++prettyPrintPars;
2203 while(item != nilCell)
2205 if(prettyPrintLength > prettyPrintMaxLength) prettyPrint(device);
2206 if(printCell(item, TRUE, device) == 0) return(0);
2207 item = item->next;
2208 if(item != nilCell) varPrintf(device," ");
2211 varPrintf(device,")");
2212 --prettyPrintPars;
2214 return(TRUE);
2218 void prettyPrint(UINT device)
2220 int i;
2222 if(prettyPrintFlags) return;
2224 if(prettyPrintPars > 0)
2225 varPrintf(device, LINE_FEED);
2226 /* varPrintf(device, LINE_FEED); before 7106 */
2228 for(i = 0; i < prettyPrintPars; i++)
2229 varPrintf(device, prettyPrintTab);
2230 prettyPrintLength = prettyPrintCurrent = prettyPrintPars;
2231 prettyPrintFlags |= PRETTYPRINT_DOUBLE;
2235 void printSymbol(SYMBOL * sPtr, UINT device)
2237 CELL * cell;
2238 CELL * list = NULL;
2239 char * setStr;
2241 prettyPrintCurrent = prettyPrintPars = 1;
2242 prettyPrintLength = 0;
2243 prettyPrintFlags &= !PRETTYPRINT_DOUBLE;
2245 if(sPtr->flags & SYMBOL_PROTECTED)
2246 setStr = "(constant ";
2247 else
2248 setStr = "(set ";
2250 switch(symbolType(sPtr))
2252 case CELL_PRIMITIVE:
2253 case CELL_IMPORT_CDECL:
2254 #ifdef WIN_32
2255 case CELL_IMPORT_DLL:
2256 #endif
2257 break;
2258 case CELL_SYMBOL:
2259 case CELL_DYN_SYMBOL:
2260 varPrintf(device, setStr);
2261 printSymbolNameExt(device, sPtr);
2262 varPrintf(device,"'");
2263 printCell((CELL *)sPtr->contents, TRUE, device);
2264 varPrintf(device, ")");
2265 break;
2266 case CELL_ARRAY:
2267 case CELL_EXPRESSION:
2268 varPrintf(device, setStr);
2269 printSymbolNameExt(device, sPtr);
2270 cell = (CELL *)sPtr->contents;
2272 if(symbolType(sPtr) == CELL_ARRAY)
2274 varPrintf(device, "(array ");
2275 printArrayDimensions(cell, device);
2276 varPrintf(device, "(flat ");
2277 list = cell = arrayList(cell);
2280 cell = (CELL *)cell->contents;
2282 varPrintf(device,"'(");
2283 prettyPrintPars = 2;
2284 if(cell->type == CELL_EXPRESSION) prettyPrint(device);
2285 while(cell != nilCell)
2287 if(prettyPrintLength > prettyPrintMaxLength)
2288 prettyPrint(device);
2289 printCell(cell, TRUE, device);
2290 cell = cell->next;
2291 if(cell != nilCell) varPrintf(device, " ");
2293 varPrintf(device, "))");
2294 if(symbolType(sPtr) == CELL_ARRAY)
2296 deleteList(list);
2297 varPrintf(device ,"))");
2299 break;
2300 case CELL_LAMBDA:
2301 case CELL_MACRO:
2302 if(isProtected(sPtr->flags))
2304 varPrintf(device, "%s%s%s", LINE_FEED, LINE_FEED, setStr);
2305 printSymbolNameExt(device, sPtr);
2306 printExpression((CELL *)sPtr->contents, device);
2307 varPrintf(device, ")");
2309 else if (isGlobal(sPtr->flags))
2311 printLambda(sPtr, device);
2312 varPrintf(device, "%s%s", LINE_FEED, LINE_FEED);
2313 printSymbolNameExt(device, sPtr);
2315 else printLambda(sPtr, device);
2316 break;
2317 default:
2318 varPrintf(device, setStr);
2319 printSymbolNameExt(device, sPtr);
2320 printCell((CELL *)sPtr->contents, TRUE, device);
2321 varPrintf(device, ")");
2322 break;
2325 varPrintf(device, "%s%s", LINE_FEED, LINE_FEED);
2327 prettyPrintLength = prettyPrintPars = 0;
2331 void printLambda(SYMBOL * sPtr, UINT device)
2333 CELL * lambda;
2334 CELL * cell;
2336 lambda = (CELL *)sPtr->contents;
2337 cell = (CELL *)lambda->contents;
2338 if(cell->type == CELL_EXPRESSION)
2339 cell = (CELL *)cell->contents;
2341 if(!isLegalSymbol(sPtr->name))
2343 varPrintf(device, "(set (sym ");
2344 printString(sPtr->name, device, strlen(sPtr->name));
2345 varPrintf(device, " %s) ", ((SYMBOL*)sPtr->context)->name);
2346 printExpression((CELL *)sPtr->contents, device);
2347 varPrintf(device, ")");
2348 return;
2351 if(symbolType(sPtr) == CELL_LAMBDA)
2352 varPrintf(device, "(define (");
2353 else
2354 varPrintf(device, "(define-macro (");
2355 prettyPrintPars += 2;
2357 printSymbolName(device, sPtr);
2358 varPrintf(device, " ");
2360 while(cell != nilCell)
2362 printCell(cell, TRUE, device);
2363 cell = cell->next;
2364 if(cell != nilCell) varPrintf(device, " ");
2366 varPrintf(device, ")");
2367 --prettyPrintPars;
2368 prettyPrint(device);
2370 cell = (CELL *)lambda->contents;
2371 while((cell = cell->next) != nilCell)
2373 if(prettyPrintLength > prettyPrintMaxLength) prettyPrint(device);
2374 printCell(cell, TRUE, device);
2375 if(!(cell->type & ENVELOPE_TYPE_MASK) && cell->next != nilCell) varPrintf(device, " ");
2378 varPrintf(device, ")");
2379 --prettyPrintPars;
2383 void printSymbolName(UINT device, SYMBOL * sPtr)
2385 SYMBOL * sp;
2387 if(sPtr->context == currentContext)
2389 if(*sPtr->name == *currentContext->name && strcmp(sPtr->name, currentContext->name) == 0)
2390 varPrintf(device, "%s:%s", sPtr->name, sPtr->name);
2392 else if(currentContext != mainContext
2393 && ((sp = lookupSymbol(sPtr->name, mainContext)) != NULL)
2394 && (sp->flags & SYMBOL_GLOBAL) )
2395 varPrintf(device, "%s:%s", currentContext->name, sPtr->name);
2396 else
2397 varPrintf(device,"%s", sPtr->name);
2399 else
2400 varPrintf(device,"%s:%s",
2401 (char *)((SYMBOL*)sPtr->context)->name, sPtr->name);
2405 void printSymbolNameExt(UINT device, SYMBOL * sPtr)
2407 if(isGlobal(sPtr->flags))
2409 varPrintf(device, "(global '");
2410 printSymbolName(device, sPtr);
2411 if(symbolType(sPtr) == CELL_LAMBDA || symbolType(sPtr) == CELL_MACRO)
2412 varPrintf(device, ")");
2413 else varPrintf(device, ") ");
2415 else
2417 if(!isLegalSymbol(sPtr->name))
2419 varPrintf(device, " (sym ");
2420 printString(sPtr->name, device, strlen(sPtr->name));
2421 varPrintf(device, " %s) ", ((SYMBOL*)sPtr->context)->name);
2423 else
2425 varPrintf(device, "'");
2426 printSymbolName(device, sPtr);
2428 varPrintf(device, " ");
2433 CELL * p_prettyPrint(CELL * params)
2435 CELL * result;
2436 char * str;
2437 size_t len;
2439 if(params != nilCell)
2440 params = getInteger(params, &prettyPrintMaxLength);
2441 if(params != nilCell)
2443 getStringSize(params, &str, &len, TRUE);
2444 prettyPrintTab = allocMemory(len + 1);
2445 memcpy(prettyPrintTab, str, len + 1);
2448 result = getCell(CELL_EXPRESSION);
2449 result->contents = (UINT)stuffInteger(prettyPrintMaxLength);
2450 ((CELL *)result->contents)->next = stuffString(prettyPrintTab);
2452 return(result);
2457 /* -------------------------- error handling --------------------------- */
2459 char * errorMessage[] =
2461 "", /* 0 */
2462 "not enough memory", /* 1 */
2463 "environment stack overflow", /* 2 */
2464 "call stack overflow", /* 3 */
2465 "problem accessing file", /* 4 */
2466 "not an expression", /* 5 */
2467 "missing parenthesis", /* 6 */
2468 "string token too long", /* 7 */
2469 "missing argument", /* 8 */
2470 "number or string expected", /* 9 */
2471 "value expected", /* 10 */
2472 "string expected", /* 11 */
2473 "symbol expected", /* 12 */
2474 "context expected", /* 13 */
2475 "symbol or context expected", /* 14 */
2476 "list expected", /* 15 */
2477 "list or array expected", /* 15 */
2478 "list or symbol expected", /* 17 */
2479 "list or string expected", /* 18 */
2480 "list or number expected", /* 19 */
2481 "array expected", /* 20 */
2482 "array, list or string expected", /* 21 */
2483 "lambda expected", /* 22 */
2484 "lambda-macro expected", /* 23 */
2485 "invalid function", /* 24 */
2486 "invalid lambda expression", /* 25 */
2487 "invalid macro expression", /* 26 */
2488 "invalid let parameter list", /* 27 */
2489 "problem saving file", /* 28 */
2490 "division by zero", /* 29 */
2491 "matrix expected", /* 30 */
2492 "wrong dimensions", /* 31 */
2493 "matrix is singular", /* 32 */
2494 "syntax in regular expression", /* 33 */
2495 "throw without catch", /* 34 */
2496 "problem loading library", /* 35 */
2497 "import function not found", /* 36 */
2498 "symbol is protected", /* 37 */
2499 "number out of range", /* 38 */
2500 "regular expression", /* 39 */
2501 "missing end of text [/text]", /* 40 */
2502 "mismatch in number of arguments", /* 41 */
2503 "problem in format string", /* 42 */
2504 "data type and format don't match", /* 43 */
2505 "invalid parameter", /* 44 */
2506 "invalid parameter: 0.0", /* 45 */
2507 "invalid parameter: NaN", /* 46 */
2508 "illegal parameter type", /* 47 */
2509 "symbol not in MAIN context", /* 48 */
2510 "symbol not in current context", /* 49 */
2511 "target cannot be MAIN", /* 50 */
2512 "list index out of bounds", /* 51 */
2513 "array index out of bounds", /* 52 */
2514 "string index out of bounds", /* 53 */
2515 "nesting level to deep", /* 54 */
2516 "invalid syntax", /* 55 */
2517 "user error", /* 56 */
2518 "user reset -", /* 57 */
2519 "received SIGINT -", /* 58 */
2520 "function is not reentrant" /* 59 */
2524 void errorMissingPar(STREAM * stream)
2526 char str[64];
2527 snprintf(str, 40, "...%-40s", ((char *)((stream->ptr - stream->buffer) > 40 ? stream->ptr - 40 : stream->buffer)));
2528 errorProcExt2(ERR_MISSING_PAR, stuffString(str));
2531 CELL * errorProcAll(int errorNumber, CELL * expr, int deleteFlag)
2533 if(!traceFlag) fatalError(errorNumber, expr, deleteFlag);
2534 printErrorMessage(errorNumber, expr, deleteFlag);
2535 openTrace();
2536 return(nilCell);
2539 CELL * errorProc(int errorNumber)
2541 return(errorProcAll(errorNumber, NULL, 0));
2544 /* extended error info in expr */
2545 CELL * errorProcExt(int errorNumber, CELL * expr)
2547 return(errorProcAll(errorNumber, expr, 0));
2550 /* extended error info in expr, which has to be discarded after printing */
2551 CELL * errorProcExt2(int errorNumber, CELL * expr)
2553 return(errorProcAll(errorNumber, expr, 1));
2556 CELL * errorProcArgs(int errorNumber, CELL * expr)
2558 if(expr == nilCell)
2559 return(errorProcExt(ERR_MISSING_ARGUMENT, NULL));
2561 return(errorProcExt(errorNumber, expr));
2564 void fatalError(int errorNumber, CELL * expr, int deleteFlag)
2566 printErrorMessage(errorNumber, expr, deleteFlag);
2567 closeTrace();
2568 longjmp(errorJump, errorReg);
2572 void printErrorMessage(UINT errorNumber, CELL * expr, int deleteFlag)
2574 CELL * lambdaFunc;
2575 UINT lambdaStackIdxSave;
2576 SYMBOL * context;
2577 int i;
2579 if(errorNumber == EXCEPTION_THROW)
2580 errorNumber = ERR_THROW_WO_CATCH;
2582 errorReg = errorNumber;
2584 if(!errorNumber) return;
2586 openStrStream(&errorStream, MAX_STRING, 1);
2587 if(traceFlag & ~TRACE_SIGINT) writeStreamStr(&errorStream, "ERR:", 4);
2588 writeStreamStr(&errorStream, errorMessage[errorReg], 0);
2590 for(i = 0; primitive[i].name != NULL; i++)
2592 if(evalFunc == primitive[i].function)
2594 writeStreamStr(&errorStream, " in function ", 0);
2595 writeStreamStr(&errorStream, primitive[i].name, 0);
2596 break;
2600 if(expr != NULL)
2602 writeStreamStr(&errorStream, " : ", 3);
2603 printCell(expr, (errorNumber != ERR_USER_ERROR), (UINT)&errorStream);
2604 if(deleteFlag) deleteList(expr);
2607 lambdaStackIdxSave = lambdaStackIdx;
2608 while(lambdaStackIdx)
2610 lambdaFunc = popLambda();
2611 if(lambdaFunc->type == CELL_SYMBOL)
2613 writeStreamStr(&errorStream, LINE_FEED, 0);
2614 writeStreamStr(&errorStream, "called from user defined function ", 0);
2615 context = ((SYMBOL *)lambdaFunc->contents)->context;
2616 if(context != mainContext)
2618 writeStreamStr(&errorStream, context->name, 0);
2619 writeStreamStr(&errorStream, ":", 0);
2621 writeStreamStr(&errorStream, ((SYMBOL *)lambdaFunc->contents)->name, 0);
2624 lambdaStackIdx = lambdaStackIdxSave;
2627 if(!(traceFlag & TRACE_SIGINT)) evalFunc = NULL;
2628 parStackCounter = prettyPrintPars = 0;
2630 if(evalCatchFlag && !(traceFlag & TRACE_SIGINT)) return;
2632 if(errorEvent == nilSymbol)
2634 if(errorNumber == ERR_SIGINT)
2635 printf(errorStream.buffer);
2636 else
2637 varPrintf(OUT_CONSOLE, "\n%.1024s\n", errorStream.buffer);
2642 /* --------------------------- load source file ------------------------- */
2645 CELL * loadFile(char * fileName, UINT offset, int encryptFlag, SYMBOL * context)
2647 CELL * result;
2648 STREAM stream;
2649 int errNo, dataLen;
2650 jmp_buf errorJumpSave;
2651 SYMBOL * contextSave;
2652 char key[16];
2653 #ifdef LOAD_DEBUG
2654 int i;
2655 #endif
2657 contextSave = currentContext;
2658 currentContext = context;
2659 if(encryptFlag)
2661 dataLen = *((int *) (linkOffset + 4));
2662 snprintf( key, 15, "%d", dataLen);
2664 else dataLen = MAX_FILE_BUFFER;
2666 if(my_strnicmp(fileName, "http://", 7) == 0)
2668 result = getPutPostDeleteUrl(fileName, nilCell, HTTP_GET_URL, 60000);
2669 pushResult(result);
2670 if(memcmp((char *)result->contents, "ERR:", 4) == 0)
2671 return(errorProcExt2(ERR_ACCESSING_FILE, stuffString((char *)result->contents)));
2672 return(copyCell(sysEvalString((char *)result->contents, nilCell, context)));
2675 if(my_strnicmp(fileName, "file://", 7) == 0)
2676 fileName = fileName + 7;
2678 if(makeStreamFromFile(&stream, fileName, dataLen + 4 * MAX_STRING, offset) == 0)
2679 return(NULL);
2681 if(encryptFlag)
2682 encryptPad(stream.buffer, stream.buffer, key, dataLen, strlen(key));
2684 memcpy(errorJumpSave, errorJump, sizeof(jmp_buf));
2685 if((errNo = setjmp(errorJump)) != 0)
2687 closeStrStream(&stream);
2688 memcpy(errorJump, errorJumpSave, sizeof(jmp_buf));
2689 currentContext = contextSave;
2690 longjmp(errorJump, errNo);
2693 #ifdef LOAD_DEBUG
2694 for(i = 0; i<recursionCount; i++) printf(" ");
2695 printf("load: %s\n", fileName);
2696 #endif
2698 result = evaluateStream(&stream, 0, TRUE);
2699 currentContext = contextSave;
2701 #ifdef LOAD_DEBUG
2702 for(i = 0; i<recursionCount; i++) printf(" ");
2703 printf("finish load: %s\n", fileName);
2704 #endif
2706 memcpy(errorJump, errorJumpSave, sizeof(jmp_buf));
2707 closeStrStream(&stream);
2708 return(result);
2711 /* -------------------------- parse / compile ----------------------------- */
2714 int compileExpression(STREAM * stream, CELL * cell)
2716 char token[MAX_STRING + 4];
2717 double floatNumber;
2718 CELL * newCell;
2719 CELL * contextCell;
2720 SYMBOL * contextPtr;
2721 int listFlag, tklen;
2722 char * lastPtr;
2723 #if experimental
2724 SYMBOL * saveContext;
2725 int defaultSymbolLevel = 0;
2727 saveContext = currentContext;
2728 #endif
2730 listFlag = TRUE; /* assumes we just entered from an envelope cell ! */
2732 GETNEXT:
2733 lastPtr = stream->ptr;
2734 switch(getToken(stream, token, &tklen))
2736 case TKN_ERROR:
2737 errorProcExt2(ERR_EXPRESSION, stuffStringN(lastPtr,
2738 (strlen(lastPtr) < 60) ? strlen(lastPtr) : 60));
2739 return(0);
2741 case TKN_EMPTY:
2742 if(parStackCounter != 0) errorMissingPar(stream);
2743 return(0);
2745 case TKN_CHARACTER:
2746 newCell = stuffInteger((UINT)token[0]);
2747 break;
2749 case TKN_HEX:
2750 #ifndef NEWLISP64
2751 newCell = stuffInteger64((INT64)strtoull(token,NULL,0));
2752 #else
2753 newCell = stuffInteger(strtoull(token,NULL,0));
2754 #endif
2755 break;
2757 case TKN_DECIMAL:
2758 #ifndef NEWLISP64
2759 newCell = stuffInteger64(strtoll(token,NULL,0));
2760 #else
2761 newCell = stuffInteger(strtoll(token,NULL,0));
2762 #endif
2763 break;
2765 case TKN_FLOAT:
2766 floatNumber = (double)atof(token);
2767 newCell = stuffFloat(&floatNumber);
2768 break;
2770 case TKN_STRING:
2771 newCell = stuffStringN(token, tklen);
2772 break;
2774 case TKN_SYMBOL:
2775 if(strcmp(token, "lambda") == 0 || strcmp(token, "fn") == 0)
2777 if(cell->type != CELL_EXPRESSION)
2779 errorProcExt2(ERR_INVALID_LAMBDA, stuffString(lastPtr));
2780 return(0);
2782 cell->type = CELL_LAMBDA;
2783 cell->aux = (UINT)nilCell;
2784 goto GETNEXT;
2786 else if(strcmp(token, "lambda-macro") == 0 || strcmp(token, "fn-macro") == 0)
2788 if(cell->type != CELL_EXPRESSION)
2790 errorProcExt2(ERR_INVALID_LAMBDA, stuffString(lastPtr));
2791 return(0);
2793 cell->type = CELL_MACRO;
2794 cell->aux = (UINT)nilCell;
2795 goto GETNEXT;
2798 else if(strncmp(token, "[text]", 6) == 0)
2800 newCell = getCell(CELL_STRING);
2801 newCell->contents = (UINT)readStreamText(stream, "[/text]");
2802 if(newCell->contents == 0)
2804 deleteList(newCell);
2805 errorProc(ERR_MISSING_TEXT_END);
2807 newCell->aux = strlen((char *)newCell->contents) + 1;
2808 newCell->type = CELL_STRING;
2809 break;
2811 newCell = getCell(CELL_SYMBOL);
2812 if(*token == '$')
2813 newCell->contents = (UINT)translateCreateSymbol(
2814 token, CELL_NIL, mainContext, TRUE);
2815 else
2816 newCell->contents = (UINT)translateCreateSymbol(
2817 token, CELL_NIL, currentContext, 0);
2818 break;
2820 case TKN_CONTEXT:
2821 contextPtr = NULL; /* since 7.5.1 dyna vars inside contexts */
2822 if(currentContext != mainContext)
2824 if(strcmp(currentContext->name, token) == 0)
2825 contextPtr = currentContext;
2826 else
2827 contextPtr = lookupSymbol(token, currentContext);
2830 if(contextPtr == NULL)
2832 contextPtr = translateCreateSymbol(
2833 token, CELL_CONTEXT, mainContext, TRUE);
2836 contextCell = (CELL *)contextPtr->contents;
2838 if(getToken(stream, token, &tklen) != TKN_SYMBOL)
2839 errorProcExt2(ERR_SYMBOL_EXPECTED, stuffString(lastPtr));
2841 /* context does not exist */
2842 if(contextCell->type != CELL_CONTEXT
2843 || contextPtr != (SYMBOL*)contextCell->contents)
2845 newCell = getCell(CELL_DYN_SYMBOL);
2846 newCell->aux = (UINT)contextPtr;
2847 newCell->contents = (UINT)allocMemory(tklen + 1);
2848 strncpy((char *)newCell->contents, token, tklen + 1);
2849 break;
2852 /* context exists make a symbol for it */
2853 newCell = getCell(CELL_SYMBOL);
2854 newCell->contents = (UINT)translateCreateSymbol(
2855 token, CELL_NIL, contextPtr, TRUE);
2856 break;
2858 case TKN_QUOTE:
2859 newCell = getCell(CELL_QUOTE);
2860 linkCell(cell, newCell, listFlag);
2861 compileExpression(stream, newCell);
2862 break;
2864 case TKN_LEFT_PAR:
2865 ++parStackCounter;
2866 newCell = getCell(CELL_EXPRESSION);
2867 linkCell(cell, newCell, listFlag);
2868 compileExpression(stream, newCell);
2869 break;
2871 case TKN_RIGHT_PAR:
2872 if(parStackCounter == 0) errorMissingPar(stream);
2873 --parStackCounter;
2874 cell->next = nilCell;
2875 return(TRUE);
2877 default:
2878 errorProcExt2(ERR_EXPRESSION, stuffString(lastPtr));
2879 return(0);
2883 linkCell(cell, newCell, listFlag);
2885 if(cell->type == CELL_QUOTE && listFlag == TRUE)
2886 return(TRUE);
2888 listFlag = 0;
2889 cell = newCell;
2891 if(parStackCounter != 0)
2893 if(*(stream->ptr) != 0) goto GETNEXT;
2894 else errorMissingPar(stream);
2897 return(0);
2901 void linkCell(CELL * left, CELL * right, int linkFlag)
2903 if(linkFlag == 0)
2904 left->next = right;
2905 else left->contents = (UINT)right;
2908 int getToken(STREAM * stream, char * token, int * ptr_len)
2910 char *tkn;
2911 char chr;
2912 int tknLen;
2913 int floatFlag;
2914 int bracketBalance;
2915 char buff[4];
2917 tkn = token;
2918 tknLen = floatFlag = 0;
2919 *tkn = 0;
2921 STRIP:
2922 if(stream->ptr > (stream->buffer + stream->size - 4 * MAX_STRING))
2924 if(stream->handle == 0)
2926 /* coming from commmand line or p_evalString */
2927 stream->buffer = stream->ptr;
2929 else
2931 stream->position += (stream->ptr - stream->buffer);
2932 lseek((int)stream->handle, stream->position, SEEK_SET);
2933 memset(stream->buffer, 0, stream->size + 1);
2935 if(read(stream->handle, stream->buffer, stream->size) > 0)
2937 stream->ptr = stream->buffer;
2938 else
2940 *stream->ptr = 0;
2941 return(TKN_EMPTY);
2946 while((unsigned char)*stream->ptr <= ' ' && (unsigned char)*stream->ptr != 0)
2947 ++stream->ptr;
2949 if(*stream->ptr == 0) return(TKN_EMPTY);
2951 /* check for comments */
2952 if(*stream->ptr == ';' || *stream->ptr == '#')
2954 stream->ptr++;
2955 for(;;)
2957 if(*stream->ptr == 0) return(TKN_EMPTY);
2958 if(*stream->ptr == '\n' || *stream->ptr == '\r')
2959 break;
2960 stream->ptr++;
2962 stream->ptr++;
2963 goto STRIP;
2967 if( *stream->ptr == '-' || *stream->ptr == '+')
2969 if(isDigit((unsigned char)*(stream->ptr + 1)) )
2970 *(tkn++) = *(stream->ptr++), tknLen++;
2974 if(isDigit((unsigned char)*stream->ptr) ||
2975 (*stream->ptr == lc_decimal_point &&
2976 isDigit((unsigned char)*(stream->ptr + 1))))
2978 if(*stream->ptr == '0' && isDigit((unsigned char)*(stream->ptr + 1)))
2980 *(tkn++) = *(stream->ptr++), tknLen++;
2981 while(*stream->ptr < '8' && *stream->ptr >= '0' && *stream->ptr != 0)
2982 *(tkn++) = *(stream->ptr++), tknLen++;
2983 *tkn = 0;
2984 return(TKN_DECIMAL);
2987 while(isDigit((unsigned char)*stream->ptr) && tknLen < MAX_SYMBOL)
2988 *(tkn++) = *(stream->ptr++), tknLen++;
2990 if(toupper(*stream->ptr) == 'X' && token[0] == '0')
2992 *(tkn++) = *(stream->ptr++), tknLen++;
2993 while(isxdigit((unsigned char)*stream->ptr) && tknLen < MAX_SYMBOL)
2994 *(tkn++) = *(stream->ptr++), tknLen++;
2995 *tkn = 0;
2996 return(TKN_HEX);
2999 if(*stream->ptr == lc_decimal_point)
3001 *(tkn++) = *(stream->ptr++), tknLen++;
3002 while(isDigit((unsigned char)*stream->ptr) && tknLen < MAX_SYMBOL)
3003 *(tkn++) = *(stream->ptr++), tknLen++;
3004 floatFlag = TRUE;
3006 else if(toupper(*stream->ptr) != 'E')
3008 *tkn = 0;
3009 return(TKN_DECIMAL);
3012 if(toupper(*stream->ptr) == 'E')
3014 if(isDigit((unsigned char)*(stream->ptr+2))
3015 && ( *(stream->ptr+1) == '-' || *(stream->ptr+1) == '+') )
3016 *(tkn++) = *(stream->ptr++), tknLen++;
3017 if(isDigit((unsigned char)*(stream->ptr+1)))
3019 *(tkn++) = *(stream->ptr++), tknLen++;
3020 while(isDigit((unsigned char)*stream->ptr) && tknLen < MAX_SYMBOL)
3021 *(tkn++) = *(stream->ptr++), tknLen++;
3023 else
3025 *tkn = 0;
3026 if(floatFlag == TRUE) return(TKN_FLOAT);
3027 else return(TKN_DECIMAL);
3030 *tkn = 0;
3031 return(TKN_FLOAT);
3033 else
3035 chr = *stream->ptr;
3036 *(tkn++) = *(stream->ptr++), tknLen++;
3037 switch(chr)
3039 case '"':
3040 --tkn; --tknLen;
3041 while(*stream->ptr != '"' && *stream->ptr != 0
3042 && tknLen < MAX_STRING)
3044 if(*stream->ptr == '\\')
3046 stream->ptr++;
3047 if(isDigit((unsigned char)*stream->ptr) &&
3048 isDigit((unsigned char)*(stream->ptr+1)) &&
3049 isDigit((unsigned char)*(stream->ptr+2)))
3051 memcpy(buff, stream->ptr, 3);
3052 buff[3] = 0;
3053 *(tkn++) = atoi(buff);
3054 tknLen++;
3055 stream->ptr += 3;
3056 continue;
3059 switch(*stream->ptr)
3061 case 0:
3062 goto SRING_TO_LONG_ERROR;
3063 break;
3064 case 'n':
3065 *(tkn++) = '\n'; break;
3066 case '\\':
3067 *(tkn++) = '\\'; break;
3068 case 'r':
3069 *(tkn++) = '\r'; break;
3070 case 't':
3071 *(tkn++) = '\t'; break;
3072 case '"':
3073 *(tkn++) = '"'; break;
3074 case 'x':
3075 if(isxdigit((unsigned char)*(stream->ptr + 1)) &&
3076 isxdigit((unsigned char)*(stream->ptr + 2)))
3078 buff[0] = '0';
3079 buff[1] = (unsigned char)*(stream->ptr + 1);
3080 buff[2] = (unsigned char)*(stream->ptr + 2);
3081 buff[3] = 0;
3082 *(tkn++) = strtol(buff, NULL, 16);
3083 stream->ptr += 2;
3084 break;
3086 default:
3087 *(tkn++) = *stream->ptr;
3089 stream->ptr++;
3090 tknLen++;
3092 else *(tkn++) = *(stream->ptr++), tknLen++;
3094 if(*stream->ptr == '\"')
3096 *tkn = 0;
3097 stream->ptr++;
3098 *ptr_len = tknLen;
3099 return(TKN_STRING);
3101 else
3103 goto SRING_TO_LONG_ERROR;
3105 break;
3107 case '\'':
3108 case '(':
3109 case ')':
3110 *tkn = 0;
3111 return(chr);
3112 case '{':
3113 --tkn; --tknLen;
3114 bracketBalance = 1;
3115 while(*stream->ptr != 0 && tknLen < MAX_STRING)
3117 if(*stream->ptr == '{') ++bracketBalance;
3118 if(*stream->ptr == '}') --bracketBalance;
3119 if(bracketBalance == 0) break;
3120 *(tkn++) = *(stream->ptr++), tknLen++;
3122 if(*stream->ptr == '}')
3124 *tkn = 0;
3125 stream->ptr++;
3126 *ptr_len = tknLen;
3127 return(TKN_STRING);
3129 else
3131 goto SRING_TO_LONG_ERROR;
3133 break;
3136 case ',':
3137 case ':':
3138 *tkn = 0;
3139 return(TKN_SYMBOL);
3141 case '[':
3142 while( tknLen < MAX_SYMBOL && *stream->ptr != 0 && *stream->ptr != ']')
3143 *(tkn++) = *(stream->ptr++), tknLen++;
3144 *tkn++ = ']';
3145 *tkn = 0;
3146 stream->ptr++;
3148 return(TKN_SYMBOL);
3150 default:
3151 while( tknLen < MAX_SYMBOL
3152 && (unsigned char)*stream->ptr > ' '
3153 && *stream->ptr != '"' && *stream->ptr != '\''
3154 && *stream->ptr != '(' && *stream->ptr != ')'
3155 && *stream->ptr != ':' && *stream->ptr != ','
3156 && *stream->ptr != 0)
3157 *(tkn++) = *(stream->ptr++), tknLen++;
3158 *tkn = 0;
3159 *ptr_len = tknLen;
3160 if(*stream->ptr == ':')
3162 stream->ptr++;
3163 return(TKN_CONTEXT);
3165 return(TKN_SYMBOL);
3168 *tkn=0;
3169 return(TKN_ERROR);
3171 SRING_TO_LONG_ERROR:
3172 *tkn = 0;
3173 errorProcExt2(ERR_STRING_TOO_LONG,
3174 stuffStringN(token, strlen(token) < 40 ? strlen(token) : 40));
3175 return(TKN_ERROR);
3178 /* -------------------------- utilities ------------------------------------ */
3180 size_t listlen(CELL * listHead)
3182 size_t len = 0;
3184 while(listHead != nilCell)
3186 len++;
3187 listHead = listHead->next;
3190 return(len);
3193 /* -------------------------- functions to get parameters ------------------ */
3195 void collectSymbols(SYMBOL * sPtr);
3197 int getFlag(CELL * params)
3199 params = evaluateExpression(params);
3200 return(!isNil(params));
3203 CELL * getInteger(CELL * params, UINT * number)
3205 CELL * cell;
3207 cell = evaluateExpression(params);
3209 #ifndef NEWLISP64
3210 if(cell->type == CELL_INT64)
3212 if(*(INT64 *)&cell->aux > 0xFFFFFFFF) *number = 0xFFFFFFFF;
3213 else if(*(INT64 *)&cell->aux < INT32_MIN_AS_INT64) *number = 0x80000000;
3214 else *number = *(INT64 *)&cell->aux;
3216 else if(cell->type == CELL_LONG)
3217 *number = cell->contents;
3218 else if(cell->type == CELL_FLOAT)
3220 #ifdef WIN_32
3221 if(isnan(*(double *)&cell->aux) || !_finite(*(double *)&cell->aux)) *number = 0;
3222 #else
3223 if(isnan(*(double *)&cell->aux)) *number = 0;
3224 #endif
3225 else if(*(double *)&cell->aux > 4294967295.0) *number = 0xFFFFFFFF;
3226 else if(*(double *)&cell->aux < -2147483648.0) *number = 0x80000000;
3227 else *number = *(double *)&cell->aux;
3229 #else
3230 if(cell->type == CELL_LONG)
3231 *number = cell->contents;
3232 else if(cell->type == CELL_FLOAT)
3234 if(isnan(*(double *)&cell->contents)) *number = 0;
3235 else if(*(double *)&cell->contents > 9223372036854775807.0) *number = 0x7FFFFFFFFFFFFFFFLL;
3236 else if(*(double *)&cell->contents < -9223372036854775808.0) *number = 0x8000000000000000LL;
3237 else *number = *(double *)&cell->contents;
3239 #endif
3240 else
3242 *number = 0;
3243 return(errorProcArgs(ERR_NUMBER_EXPECTED, params));
3246 return(params->next);
3249 #ifndef NEWLISP64
3250 CELL * getInteger64(CELL * params, INT64 * number)
3252 CELL * cell;
3254 cell = evaluateExpression(params);
3256 if(cell->type == CELL_INT64)
3257 *number = *(INT64 *)&cell->aux;
3258 else if(cell->type == CELL_LONG)
3259 *number = (int)cell->contents;
3260 else if(cell->type == CELL_FLOAT)
3262 #ifdef WIN_32
3263 if(isnan(*(double *)&cell->aux) || !_finite(*(double *)&cell->aux)) *number = 0;
3264 #else
3265 if(isnan(*(double *)&cell->aux)) *number = 0;
3266 #endif
3267 else if(*(double *)&cell->aux > 9223372036854775807.0) *number = 0x7FFFFFFFFFFFFFFFLL;
3268 else if(*(double *)&cell->aux < -9223372036854775808.0) *number = 0x8000000000000000LL;
3269 else *number = *(double *)&cell->aux;
3271 else
3273 *number = 0;
3274 return(errorProcArgs(ERR_NUMBER_EXPECTED, params));
3277 return(params->next);
3280 #else
3281 CELL * getInteger64(CELL * params, INT64 * number)
3283 CELL * cell;
3285 cell = evaluateExpression(params);
3287 if(cell->type == CELL_LONG)
3288 *number = cell->contents;
3289 else if(cell->type == CELL_FLOAT)
3291 if(isnan(*(double *)&cell->contents)) *number = 0;
3292 else if(*(double *)&cell->contents > 9223372036854775807.0) *number = 0x7FFFFFFFFFFFFFFFLL;
3293 else if(*(double *)&cell->contents < -9223372036854775808.0) *number = 0x8000000000000000LL;
3294 else *number = *(double *)&cell->contents;
3296 else
3298 *number = 0;
3299 return(errorProcArgs(ERR_NUMBER_EXPECTED, params));
3302 return(params->next);
3304 #endif
3306 CELL * getIntegerExt(CELL * params, UINT * number, int evalFlag)
3308 CELL * cell;
3310 if(evalFlag)
3311 cell = evaluateExpression(params);
3312 else cell = params;
3314 #ifndef NEWLISP64
3315 if(cell->type == CELL_INT64)
3317 if(*(INT64 *)&cell->aux > 0xFFFFFFFF) *number = 0xFFFFFFFF;
3318 else if(*(INT64 *)&cell->aux < INT32_MIN_AS_INT64) *number = 0x80000000;
3319 else *number = *(INT64 *)&cell->aux;
3321 else if(cell->type == CELL_LONG)
3322 *number = cell->contents;
3323 else if(cell->type == CELL_FLOAT)
3325 #ifdef WIN_32
3326 if(isnan(*(double *)&cell->aux) || !_finite(*(double *)&cell->aux)) *number = 0;
3327 #else
3328 if(isnan(*(double *)&cell->aux)) *number = 0;
3329 #endif
3330 else if(*(double *)&cell->aux > 4294967295.0) *number = 0xFFFFFFFF;
3331 else if(*(double *)&cell->aux < -2147483648.0) *number = 0x80000000;
3332 else *number = *(double *)&cell->aux;
3334 #else
3335 if(cell->type == CELL_LONG)
3336 *number = cell->contents;
3337 else if(cell->type == CELL_FLOAT)
3339 if(isnan(*(double *)&cell->contents)) *number = 0;
3340 else if(*(double *)&cell->contents > 9223372036854775807.0) *number = 0x7FFFFFFFFFFFFFFFLL;
3341 else if(*(double *)&cell->contents < -9223372036854775808.0) *number = 0x8000000000000000LL;
3342 else *number = *(double *)&cell->contents;
3344 #endif
3345 else
3347 *number = 0;
3348 return(errorProcArgs(ERR_NUMBER_EXPECTED, params));
3351 return(params->next);
3355 CELL * getFloat(CELL * params, double * floatNumber)
3357 CELL * cell;
3359 cell = evaluateExpression(params);
3361 #ifndef NEWLISP64
3362 if(cell->type == CELL_FLOAT)
3363 *floatNumber = *(double *)&cell->aux;
3364 else if(cell->type == CELL_INT64)
3365 *floatNumber = *(INT64 *)&cell->aux;
3366 #else
3367 if(cell->type == CELL_FLOAT)
3368 *floatNumber = *(double *)&cell->contents;
3369 #endif
3370 else if(cell->type == CELL_LONG)
3371 *floatNumber = (long)cell->contents;
3372 else
3374 *floatNumber = 0.0;
3375 return(errorProcArgs(ERR_NUMBER_EXPECTED, params));
3378 return(params->next);
3382 CELL * getString(CELL * params, char * * stringPtr)
3384 CELL * cell;
3386 cell = evaluateExpression(params);
3388 if(cell->type != CELL_STRING)
3390 *stringPtr = "";
3391 return(errorProcArgs(ERR_STRING_EXPECTED, params));
3393 *stringPtr = (char *)cell->contents;
3394 return(params->next);
3398 CELL * getStringSize(CELL * params, char * * stringPtr, size_t * size, int evalFlag)
3400 CELL * cell;
3402 if(params == nilCell)
3403 return(errorProc(ERR_MISSING_ARGUMENT));
3405 if(evalFlag)
3406 cell = evaluateExpression(params);
3407 else cell = params;
3409 if(cell->type != CELL_STRING)
3411 *stringPtr = "";
3412 return(errorProcArgs(ERR_STRING_EXPECTED, params));
3415 *stringPtr = (char *)cell->contents;
3416 if(size) *size = cell->aux - 1;
3417 return(params->next);
3421 CELL * getSymbol(CELL * params, SYMBOL * * symbol)
3423 CELL * cell;
3425 cell = evaluateExpression(params);
3427 if(cell->type != CELL_SYMBOL)
3429 if(cell->type == CELL_DYN_SYMBOL)
3431 *symbol = getDynamicSymbol(cell);
3432 return(params->next);
3434 *symbol = nilSymbol;
3435 return(errorProcArgs(ERR_SYMBOL_EXPECTED, params));
3438 *symbol = (SYMBOL *)cell->contents;
3439 return(params->next);
3442 /* only used for internal syms: $timer, $error-event and $signal-1-> $signal-32 */
3443 CELL * getCreateSymbol(CELL * params, SYMBOL * * symbol, char * name)
3445 CELL * cell;
3447 cell = evaluateExpression(params);
3449 if(cell->type != CELL_SYMBOL)
3451 if(cell->type == CELL_DYN_SYMBOL)
3453 *symbol = getDynamicSymbol(cell);
3454 return(params->next);
3456 *symbol = translateCreateSymbol(name, CELL_NIL, mainContext, TRUE);
3457 (*symbol)->flags |= SYMBOL_PROTECTED | SYMBOL_GLOBAL;
3458 (*symbol)->contents = (UINT)copyCell(cell);
3460 else
3461 *symbol = (SYMBOL *)cell->contents;
3463 return(params->next);
3467 CELL * getContext(CELL * params, SYMBOL * * context)
3469 CELL * cell;
3471 cell = evaluateExpression(params);
3473 if(cell->type == CELL_CONTEXT || cell->type == CELL_SYMBOL)
3474 *context = (SYMBOL *)cell->contents;
3475 else
3477 *context = NULL;
3478 return(errorProcArgs(ERR_CONTEXT_EXPECTED, params));
3481 if(symbolType(*context) != CELL_CONTEXT)
3482 return(errorProcExt(ERR_CONTEXT_EXPECTED, params));
3484 return(params->next);
3488 /* gets the first element, without list envelope */
3489 CELL * getListHead(CELL * params, CELL * * list)
3491 CELL * cell;
3493 cell = evaluateExpression(params);
3495 if(!isList(cell->type))
3497 *list = copyCell(nilCell);
3498 return(errorProcArgs(ERR_LIST_EXPECTED, params));
3500 *list = (CELL *)cell->contents;
3501 return(params->next);
3504 /* gets a list from an expression or default functor
3505 inside the (L foo) parameter form in nth and ref functions
3506 returns the params ptr for foo */
3507 CELL * getList(CELL * params, CELL * * result, int setFlag)
3509 SYMBOL * sPtr;
3510 CELL * list;
3512 list = (CELL *)params->contents;
3513 params = list->next;
3514 if(isSymbol(list->type))
3516 if(list->type == CELL_SYMBOL)
3517 sPtr = (SYMBOL *)list->contents;
3518 else
3519 sPtr = getDynamicSymbol(list);
3521 list = (CELL *)sPtr->contents;
3523 if(list->type == CELL_CONTEXT)
3525 sPtr = (translateCreateSymbol(
3526 ((SYMBOL*)list->contents)->name,
3527 CELL_NIL,
3528 (SYMBOL*)list->contents,
3529 TRUE));
3530 list = (CELL *)sPtr->contents;
3533 if(isProtected(sPtr->flags) && setFlag)
3534 return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(sPtr)));
3536 else
3538 if(setFlag)
3539 list = evalCheckProtected(list, NULL);
3540 else
3541 list = evaluateExpression(list);
3543 if(list->type == CELL_CONTEXT)
3545 sPtr = (translateCreateSymbol(
3546 ((SYMBOL*)list->contents)->name,
3547 CELL_NIL,
3548 (SYMBOL*)list->contents,
3549 TRUE));
3551 if(setFlag && isProtected(sPtr->flags))
3552 return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(sPtr)));
3554 list = (CELL *)sPtr->contents;
3558 *result = list;
3560 return(params);
3563 /* ------------------------------- core predicates ------------------------ */
3565 CELL * p_setlocale(CELL * params)
3567 struct lconv * lc;
3568 char * locale;
3569 UINT category;
3571 if(params != nilCell)
3572 params = getString(params, &locale);
3573 else locale = NULL;
3575 if(params != nilCell)
3576 getInteger(params, &category);
3577 else category = LC_ALL;
3579 locale = setlocale(category, locale);
3581 if(locale == NULL)
3582 return(nilCell);
3584 stringOutputRaw = (strcmp(locale, "C") == 0);
3586 lc = localeconv();
3587 lc_decimal_point = *lc->decimal_point;
3589 return(stuffString(locale));
3593 CELL * p_commandLine(CELL * params)
3595 commandLineFlag = getFlag(params);
3596 return((commandLineFlag == FALSE ? nilCell : trueCell));
3600 CELL * p_quote(CELL * params)
3602 return(copyCell(params));
3606 CELL * p_eval(CELL * params)
3608 if(params->type == CELL_SYMBOL)
3609 params = (CELL*)((SYMBOL *)params->contents)->contents;
3610 else
3611 params = evaluateExpression(params);
3613 if(params->type == CELL_SYMBOL)
3615 if(symbolProtectionLevel && symbolProtectionLevel == (recursionCount - 1))
3617 if(isProtected(((SYMBOL *)params->contents)->flags))
3618 symbolProtectionLevel = 0xFFFFFFFF;
3620 /* eval returns original symbol contents for usage in macros */
3621 pushResultFlag = 0;
3622 return((CELL*)((SYMBOL *)params->contents)->contents);
3625 return(copyCell(evaluateExpression(params)));
3629 CELL * p_catch(CELL * params)
3631 jmp_buf errorJumpSave;
3632 int envStackIdxSave;
3633 int lambdaStackIdxSave;
3634 int recursionCountSave;
3635 int value;
3636 CELL * expr;
3637 CELL * result;
3638 SYMBOL * symbol = NULL;
3639 SYMBOL * contextSave;
3641 expr = params;
3642 if(params->next != nilCell)
3644 getSymbol(params->next, &symbol);
3645 if(isProtected(symbol->flags))
3646 return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbol)));
3649 memcpy(errorJumpSave, errorJump, sizeof(jmp_buf));
3650 envStackIdxSave = envStackIdx;
3651 recursionCountSave = recursionCount;
3652 lambdaStackIdxSave = lambdaStackIdx;
3653 contextSave = currentContext;
3655 if((value = setjmp(errorJump)) != 0)
3657 memcpy(errorJump, errorJumpSave, (sizeof(jmp_buf)));
3658 recoverEnvironment(envStackIdxSave);
3659 recursionCount = recursionCountSave;
3660 lambdaStackIdx = lambdaStackIdxSave;
3661 currentContext = contextSave;
3662 evalCatchFlag--;
3664 if(value == EXCEPTION_THROW)
3666 if(symbol == NULL) return(throwResult);
3667 deleteList((CELL*)symbol->contents);
3668 symbol->contents = (UINT)throwResult;
3669 return(trueCell);
3672 if(errorStream.buffer != NULL)
3674 if(symbol == NULL)
3676 if(errorEvent == nilSymbol && evalCatchFlag == 0)
3677 varPrintf(OUT_CONSOLE, "\n%.1024s\n", errorStream.buffer);
3678 longjmp(errorJump, value);
3680 deleteList((CELL*)symbol->contents);
3681 symbol->contents = (UINT)stuffString(errorStream.buffer);
3684 return(nilCell);
3687 evalCatchFlag++;
3688 result = copyCell(evaluateExpression(expr));
3689 evalCatchFlag--;
3690 memcpy(errorJump, errorJumpSave, sizeof(jmp_buf));
3692 if(symbol == NULL) return(result);
3694 deleteList((CELL*)symbol->contents);
3695 symbol->contents = (UINT)result;
3697 return(trueCell);
3701 CELL * p_throw(CELL * params)
3703 if(evalCatchFlag == 0)
3704 return(errorProc(ERR_THROW_WO_CATCH));
3706 throwResult = copyCell(evaluateExpression(params));
3707 longjmp(errorJump, EXCEPTION_THROW);
3709 return(trueCell);
3712 CELL * p_throwError(CELL * params)
3714 evalFunc = NULL;
3715 errorProcExt(ERR_USER_ERROR, evaluateExpression(params));
3716 return(nilCell);
3720 CELL * p_evalString(CELL * params)
3722 SYMBOL * context = currentContext;
3723 char * evalString;
3725 params = getString(params, &evalString);
3726 if(params->next != nilCell)
3728 if((context = getCreateContext(params->next, TRUE)) == NULL)
3729 return(errorProcExt(ERR_SYMBOL_OR_CONTEXT_EXPECTED, params->next));
3732 return(copyCell(sysEvalString(evalString, params, context)));
3735 CELL * sysEvalString(char * evalString, CELL * proc, SYMBOL * context)
3737 CELL * program;
3738 STREAM stream;
3739 CELL * resultCell = nilCell;
3740 jmp_buf errorJumpSave;
3741 int recursionCountSave;
3742 int envStackIdxSave;
3743 int resultIdxSave;
3744 SYMBOL * contextSave = NULL;
3746 makeStreamFromString(&stream, evalString);
3747 recursionCountSave = recursionCount;
3748 envStackIdxSave = envStackIdx;
3749 resultIdxSave = resultStackIdx;
3750 contextSave = currentContext;
3751 currentContext = context;
3753 if(proc != nilCell)
3755 evalCatchFlag++;
3756 memcpy(errorJumpSave, errorJump, sizeof(jmp_buf));
3758 if(setjmp(errorJump) != 0)
3760 memcpy(errorJump, errorJumpSave, (sizeof(jmp_buf)));
3761 recoverEnvironment(envStackIdxSave);
3762 evalCatchFlag--;
3763 recursionCount = recursionCountSave;
3764 currentContext = contextSave;
3765 return(evaluateExpression(proc));
3769 while(TRUE)
3771 pushResult(program = getCell(CELL_QUOTE));
3772 if(compileExpression(&stream, program) == 0) break;
3773 resultCell = evaluateExpression((CELL *)program->contents);
3774 if(resultStackIdx > (MAX_RESULT_STACK - 256))
3776 program = popResult();
3777 cleanupResults(resultIdxSave);
3778 pushResult(program);
3782 if(proc != nilCell)
3784 memcpy(errorJump, errorJumpSave, (sizeof(jmp_buf)));
3785 evalCatchFlag--;
3788 currentContext = contextSave;
3789 return(resultCell);
3792 CELL * p_curry(CELL * params)
3794 CELL * lambda;
3795 CELL * cell;
3796 SYMBOL * xPtr;
3798 xPtr = translateCreateSymbol("_x", CELL_NIL, currentContext, TRUE);
3799 lambda = getCell(CELL_LAMBDA);
3800 cell = getCell(CELL_EXPRESSION);
3801 lambda->contents = (UINT)cell;
3802 cell->contents = (UINT)stuffSymbol(xPtr);
3803 cell->next = getCell(CELL_EXPRESSION);
3804 cell = cell->next;
3805 cell->contents = (UINT)copyCell(params);
3806 cell = (CELL *)cell->contents;
3807 cell->next = copyCell(params->next);
3808 cell = cell->next;
3809 cell->next = stuffSymbol(xPtr);
3811 return(lambda);
3815 CELL * p_apply(CELL * params)
3817 CELL * expr;
3818 CELL * args;
3819 CELL * cell;
3820 CELL * result;
3821 CELL * func;
3822 ssize_t count, cnt;
3823 int resultIdxSave;
3825 func = evaluateExpression(params);
3827 cell = copyCell(func);
3828 expr = getCell(CELL_EXPRESSION);
3829 expr->contents = (UINT)cell;
3831 params = params->next;
3832 args = evaluateExpression(params);
3834 if(params->next != nilCell)
3835 getInteger(params->next, (UINT *)&count);
3836 else count = -1;
3837 if(count < 2) count = MAX_LONG;
3839 resultIdxSave = resultStackIdx + 2;
3841 if(args->type == CELL_EXPRESSION)
3843 args = (CELL *)args->contents;
3844 cnt = count;
3845 REDUCE:
3846 while(args != nilCell && cnt-- > 0)
3848 if(isSelfEval(args->type))
3850 cell->next = copyCell(args);
3851 cell = cell->next;
3853 else
3855 cell->next = getCell(CELL_QUOTE);
3856 cell = cell->next;
3857 cell->contents = (UINT)copyCell(args);
3859 args = args->next;
3861 pushResult(expr);
3862 result = copyCell(evaluateExpression(expr));
3863 if(args == nilCell) return(result);
3864 cell = copyCell(func);
3865 expr = getCell(CELL_EXPRESSION);
3866 expr->contents = (UINT)cell;
3867 cell->next = getCell(CELL_QUOTE);
3868 cell = cell->next;
3869 cell->contents = (UINT)result;
3870 cnt = count - 1;
3871 cleanupResults(resultIdxSave);
3872 goto REDUCE;
3875 pushResult(expr);
3876 return(copyCell(evaluateExpression(expr)));
3880 CELL * p_args(CELL * params)
3882 if(params != nilCell)
3883 return(copyCell(implicitIndexList((CELL*)argsSymbol->contents, params)));
3884 return(copyCell((CELL*)argsSymbol->contents));
3887 /* in-place expansion, if symbol==NULL all uppercase, nil vars are expanded */
3888 CELL * expand(CELL * expr, SYMBOL * symbol)
3890 CELL * cell = nilCell;
3891 SYMBOL * sPtr;
3892 int enable = 1;
3893 CELL * cont, * rep;
3894 int wchar;
3896 if(expr->type == CELL_SYMBOL)
3897 return(expr);
3899 return(copyCell(expr));
3902 if(isEnvelope(expr->type))
3903 cell = (CELL*)expr->contents;
3905 while(cell != nilCell)
3907 if(cell->type == CELL_SYMBOL && (cell->contents == (UINT)symbol || symbol == NULL) )
3909 sPtr = (SYMBOL *)cell->contents;
3910 if(symbol == NULL)
3912 #ifndef SUPPORT_UTF8
3913 wchar = *sPtr->name;
3914 #else
3915 utf8_wchar(sPtr->name, &wchar);
3916 #endif
3917 enable = (wchar > 64 && wchar < 91);
3918 cont = (CELL*)sPtr->contents;
3919 enable = (enable && cont->contents != (UINT)nilCell
3920 && cont->contents != (UINT)nilSymbol);
3923 if(symbol || enable)
3925 rep = copyCell((CELL*)sPtr->contents);
3926 cell->type = rep->type;
3927 cell->aux = rep->aux;
3928 cell->contents = rep->contents;
3929 rep->type = CELL_LONG;
3930 rep->aux = 0;
3931 rep->contents = 0;
3932 deleteList(rep);
3936 else if(isEnvelope(cell->type)) expand(cell, symbol);
3937 cell = cell->next;
3940 return(expr);
3943 CELL * blockExpand(CELL * block, SYMBOL * symbol)
3945 CELL * expanded = nilCell;
3946 CELL * next = nilCell;
3948 while(block != nilCell)
3950 if(expanded == nilCell)
3952 next = expand(copyCell(block), symbol);
3953 expanded = next;
3955 else
3957 next->next = expand(copyCell(block), symbol);
3958 next = next->next;
3960 block = block->next;
3963 return(expanded);
3967 CELL * p_expand(CELL * params)
3969 SYMBOL * symbol;
3970 CELL * expr;
3971 CELL * next;
3972 CELL * list;
3973 CELL * cell;
3975 expr = evaluateExpression(params);
3976 if(!isList(expr->type) && expr->type != CELL_QUOTE)
3977 return(errorProcExt(ERR_LIST_EXPECTED, expr));
3979 params = next = params->next;
3980 if(params == nilCell)
3981 return(expand(copyCell(expr), NULL));
3983 while((params = next) != nilCell)
3985 next = params->next;
3986 params = evaluateExpression(params);
3987 if(params->type == CELL_SYMBOL)
3988 symbol = (SYMBOL*)params->contents;
3989 else if(params->type == CELL_DYN_SYMBOL)
3990 symbol = getDynamicSymbol(params);
3991 else if(params->type == CELL_EXPRESSION)
3993 list = (CELL*)params->contents;
3994 while(list != nilCell)
3996 if(list->type != CELL_EXPRESSION)
3997 return(errorProcExt(ERR_LIST_EXPECTED, list));
3998 cell = (CELL *)list->contents;
3999 if(cell->type != CELL_SYMBOL)
4000 return(errorProcExt(ERR_SYMBOL_EXPECTED, cell));
4001 symbol = (SYMBOL*)cell->contents;
4002 pushEnvironment(symbol->contents);
4003 pushEnvironment(symbol);
4004 symbol->contents = (UINT)cell->next;
4005 expr = expand(copyCell(expr), symbol);
4006 symbol = (SYMBOL*)popEnvironment();
4007 symbol->contents = popEnvironment();
4008 pushResult(expr);
4009 list = list->next;
4010 continue;
4012 break;
4014 else
4015 return(errorProcExt(ERR_LIST_OR_SYMBOL_EXPECTED, params));
4016 expr = expand(copyCell(expr), symbol);
4017 pushResult(expr);
4020 return(copyCell(expr));
4024 CELL * defineOrMacro(CELL * params, UINT cellType)
4026 SYMBOL * symbol;
4027 CELL * argsPtr;
4028 CELL * args;
4029 CELL * lambda;
4031 if(params->type != CELL_EXPRESSION)
4032 return(errorProcExt(ERR_LIST_OR_SYMBOL_EXPECTED, params));
4034 /* symbol to be defined */
4035 argsPtr = (CELL *)params->contents;
4036 if(argsPtr->type != CELL_SYMBOL)
4038 if(argsPtr->type == CELL_DYN_SYMBOL)
4039 symbol = getDynamicSymbol(argsPtr);
4040 else
4041 return(errorProcExt(ERR_SYMBOL_EXPECTED, params));
4043 else symbol = (SYMBOL *)argsPtr->contents;
4045 if(isProtected(symbol->flags))
4046 return(errorProcExt(ERR_SYMBOL_PROTECTED, params));
4048 /* local symbols */
4049 argsPtr = copyList(argsPtr->next);
4050 lambda = getCell(cellType);
4051 lambda->aux = (UINT)nilCell;
4052 args = getCell(CELL_EXPRESSION);
4053 args->contents = (UINT)argsPtr;
4054 /* body expressions */
4055 args->next = copyList(params->next);
4056 lambda->contents = (UINT)args;
4058 deleteList((CELL *)symbol->contents);
4060 symbol->contents = (UINT)lambda;
4062 pushResultFlag = FALSE;
4063 return(lambda);
4066 #define TYPE_SET 1
4067 #define TYPE_CONSTANT 2
4068 #define TYPE_DEFINE 3
4070 CELL * p_define(CELL * params)
4072 if(params->type != CELL_SYMBOL)
4074 if(params->type != CELL_DYN_SYMBOL)
4075 return(defineOrMacro(params, CELL_LAMBDA));
4076 return(setDefine(getDynamicSymbol(params), params->next, TYPE_SET));
4079 return(setDefine((SYMBOL *)params->contents, params->next, TYPE_SET));
4083 CELL * p_defineMacro(CELL * params)
4085 return(defineOrMacro(params, CELL_MACRO));
4089 CELL * p_setq(CELL * params)
4091 SYMBOL * symbol;
4092 CELL * next;
4094 for(;;)
4096 if(params->type != CELL_SYMBOL)
4098 if(params->type == CELL_DYN_SYMBOL)
4099 symbol = getDynamicSymbol(params);
4100 else
4101 return(errorProcExt(ERR_SYMBOL_EXPECTED, params));
4103 else
4104 symbol = (SYMBOL *)params->contents;
4105 params = params->next;
4106 next = params->next;
4107 if(params == nilCell)
4108 return(copyCell((CELL*)symbol->contents));
4109 if(next == nilCell) return(setDefine(symbol, params, TYPE_SET));
4110 setDefine(symbol, params, TYPE_SET);
4111 params = next;
4116 CELL * p_set(CELL *params)
4118 SYMBOL * symbol;
4119 CELL * next;
4121 for(;;)
4123 params = getSymbol(params, &symbol);
4124 next = params->next;
4125 if(params == nilCell)
4126 return(copyCell((CELL*)symbol->contents));
4127 if(next == nilCell) return(setDefine(symbol, params, TYPE_SET));
4128 setDefine(symbol, params, TYPE_SET);
4129 pushResultFlag = TRUE;
4130 params = next;
4135 CELL * p_constant(CELL *params)
4137 SYMBOL * symbol;
4138 CELL * next;
4140 for(;;)
4142 params = getSymbol(params, &symbol);
4143 /* protect contexts from being set, but not vars holding contexts */
4144 if(symbolType(symbol) == CELL_CONTEXT && (SYMBOL *)((CELL *)symbol->contents)->contents == symbol)
4145 return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbol)));
4146 next = params->next;
4147 if(symbol->context != currentContext)
4148 return(errorProcExt2(ERR_NOT_CURRENT_CONTEXT, stuffSymbol(symbol)));
4149 symbol->flags |= SYMBOL_PROTECTED;
4150 if(params == nilCell)
4151 return(copyCell((CELL*)symbol->contents));
4152 if(next == nilCell) return(setDefine(symbol, params, TYPE_CONSTANT));
4153 setDefine(symbol, params, TYPE_CONSTANT);
4154 params = next;
4159 CELL * setDefine(SYMBOL * symbol, CELL * params, int type)
4161 CELL * cell;
4163 if(isProtected(symbol->flags))
4165 if(type == TYPE_CONSTANT)
4167 if(symbol == nilSymbol || symbol == trueSymbol)
4168 return(errorProcExt2(ERR_SYMBOL_EXPECTED, stuffSymbol(symbol)));
4170 else
4171 return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbol)));
4174 cell = copyCell(evaluateExpression(params));
4176 deleteList((CELL *)symbol->contents);
4177 symbol->contents = (UINT)(cell);
4179 pushResultFlag = FALSE;
4180 return(cell);
4184 CELL * p_global(CELL * params)
4186 SYMBOL * sPtr;
4190 params = getSymbol(params, &sPtr);
4191 if(sPtr->context != mainContext || currentContext != mainContext)
4192 return(errorProcExt2(ERR_NOT_IN_MAIN, stuffSymbol(sPtr)));
4193 else
4194 sPtr->flags |= SYMBOL_GLOBAL;
4195 } while (params != nilCell);
4197 return(stuffSymbol(sPtr));
4200 #define LET_STD 0
4201 #define LET_NEST 1
4202 #define LET_EXPAND 2
4203 #define LET_LOCAL 3
4205 CELL * let(CELL * params, int type);
4207 CELL * p_let(CELL * params) { return(let(params, LET_STD)); }
4208 CELL * p_letn(CELL * params) { return(let(params, LET_NEST)); }
4209 CELL * p_letExpand(CELL * params) { return(let(params, LET_EXPAND)); }
4210 CELL * p_local(CELL * params) { return(let(params, LET_LOCAL)); }
4212 CELL * let(CELL * params, int type)
4214 CELL * inits;
4215 CELL * cell;
4216 CELL * result = nilCell;
4217 CELL * args = NULL, * list = NULL;
4218 CELL * body;
4219 SYMBOL * symbol;
4220 int localCount = 0;
4222 if(params->type != CELL_EXPRESSION)
4223 return(errorProcExt(ERR_INVALID_LET, params));
4225 /* evaluate symbol assignments in parameter list
4226 handle double syntax classic: (let ((v1 e1) (v2 e2) ...) ...)
4227 and: (let (v1 e1 v2 e2 ...) ...)
4229 inits = (CELL*)params->contents;
4230 body = params->next;
4232 if(type == LET_LOCAL)
4234 while(inits != nilCell)
4236 if(inits->type != CELL_SYMBOL)
4237 return(errorProcExt(ERR_SYMBOL_EXPECTED, inits));
4238 symbol = (SYMBOL *)inits->contents;
4239 if(isProtected(symbol->flags))
4240 return(errorProcExt(ERR_SYMBOL_PROTECTED, inits));
4241 pushEnvironment(symbol->contents);
4242 pushEnvironment(symbol);
4243 symbol->contents = (UINT)nilCell;
4244 localCount++;
4245 inits = inits->next;
4247 goto EVAL_LET_BODY;
4250 while(inits != nilCell)
4252 if(inits->type != CELL_EXPRESSION)
4254 if(inits->type != CELL_SYMBOL)
4255 return(errorProcExt(ERR_INVALID_LET, inits));
4256 cell = inits;
4257 inits = ((CELL*)cell->next)->next;
4259 else
4261 cell = (CELL *)inits->contents;
4262 if(cell->type != CELL_SYMBOL)
4263 return(errorProcExt(ERR_SYMBOL_EXPECTED, inits));
4264 inits = inits->next;
4267 if(type == LET_STD || type == LET_EXPAND)
4269 if(localCount == 0)
4270 list = args = copyCell(evaluateExpression(cell->next));
4271 else
4273 args->next = copyCell(evaluateExpression(cell->next));
4274 args = args->next;
4277 else /* LET_NEST */
4279 symbol = (SYMBOL *)cell->contents;
4280 if(isProtected(symbol->flags))
4281 return(errorProcExt(ERR_SYMBOL_PROTECTED, cell));
4282 args = copyCell(evaluateExpression(cell->next));
4283 pushEnvironment((CELL *)symbol->contents);
4284 pushEnvironment((UINT)symbol);
4285 symbol->contents = (UINT)args;
4288 localCount++;
4291 /* save symbols and get new bindings */
4292 if(type == LET_STD || type == LET_EXPAND)
4294 inits = (CELL*)params->contents;
4295 while(inits != nilCell)
4297 if(inits->type == CELL_EXPRESSION)
4299 cell = (CELL *)inits->contents;
4300 inits = inits->next;
4302 else
4304 cell = inits;
4305 inits = ((CELL*)cell->next)->next;
4308 symbol = (SYMBOL *)cell->contents;
4310 if(isProtected(symbol->flags))
4311 return(errorProcExt(ERR_SYMBOL_PROTECTED, cell));
4313 pushEnvironment((CELL *)symbol->contents);
4314 pushEnvironment((UINT)symbol);
4315 symbol->contents = (UINT)list;
4317 args = list;
4318 list = list->next;
4319 args->next = nilCell; /* decouple */
4321 /* hook in LET_EXPAND mode here */
4322 if(type == LET_EXPAND)
4324 body = blockExpand(body, symbol);
4325 pushResult(body);
4331 EVAL_LET_BODY:
4332 /* evaluate body expressions */
4333 while(body != nilCell)
4335 if(result != nilCell) deleteList(result);
4336 result = copyCell(evaluateExpression(body));
4337 body = body->next;
4340 /* restore environment */
4341 while(localCount--)
4343 symbol = (SYMBOL *)popEnvironment();
4344 if(isProtected(symbol->flags) && (symbol != argsSymbol))
4345 symbol->flags &= ~SYMBOL_PROTECTED;
4346 deleteList((CELL *)symbol->contents);
4347 symbol->contents = popEnvironment();
4350 return(result);
4353 CELL * p_first(CELL * params)
4355 char str[2];
4356 CELL * cell;
4358 cell = evaluateExpression(params);
4360 if(cell->type == CELL_STRING)
4362 if((str[0] = *(char *)cell->contents) == 0)
4363 return(stuffString(""));
4364 #ifndef SUPPORT_UTF8
4365 str[1] = 0;
4366 return(stuffString(str));
4367 #else
4368 return(stuffStringN((char*)cell->contents, utf8_1st_len((char*)cell->contents)));
4369 #endif
4372 else if(isList(cell->type))
4373 return(copyCell((CELL *)cell->contents));
4374 else if(cell->type == CELL_ARRAY)
4375 return(copyCell(*(CELL * *)cell->contents));
4377 return(errorProcExt(ERR_ARRAY_LIST_OR_STRING_EXPECTED, params));
4381 CELL * p_rest(CELL * params)
4383 CELL * cell;
4384 CELL * tail;
4386 cell = evaluateExpression(params);
4387 if(cell->type == CELL_STRING)
4389 if(*(char *)cell->contents == 0)
4390 return(stuffString(""));
4391 #ifndef SUPPORT_UTF8
4392 return(stuffString((char *)(cell->contents + 1)));
4393 #else
4394 return(stuffString((char *)(cell->contents + utf8_1st_len((char *)cell->contents))));
4395 #endif
4398 else if(isList(cell->type))
4400 tail = getCell(CELL_EXPRESSION);
4401 tail->contents = (UINT)copyList(((CELL*)cell->contents)->next);
4402 return(tail);
4404 else if(cell->type == CELL_ARRAY)
4405 return(subarray(cell, 1, MAX_LONG));
4407 return(errorProcExt(ERR_ARRAY_LIST_OR_STRING_EXPECTED, params));
4410 CELL * implicitNrestSlice(CELL * num, CELL * params)
4412 CELL * list;
4413 CELL * rest;
4414 ssize_t n, len;
4416 getIntegerExt(num, (UINT *)&n, FALSE);
4417 list = evaluateExpression(params);
4419 if(list->type == CELL_CONTEXT)
4420 list = (CELL *)(translateCreateSymbol(
4421 ((SYMBOL*)list->contents)->name,
4422 CELL_NIL,
4423 (SYMBOL*)list->contents,
4424 TRUE))->contents;
4426 /* slice */
4427 if(isNumber(list->type))
4429 getIntegerExt(list, (UINT*)&len, FALSE);
4430 list = evaluateExpression(params->next);
4432 if(list->type == CELL_CONTEXT)
4433 list = (CELL *)(translateCreateSymbol(
4434 ((SYMBOL*)list->contents)->name,
4435 CELL_NIL,
4436 (SYMBOL*)list->contents,
4437 TRUE))->contents;
4439 if(isList(list->type))
4440 return(sublist((CELL *)list->contents, n, len));
4441 else if(list->type == CELL_STRING)
4442 return(substring((char *)list->contents, list->aux-1, n, len));
4443 else if(list->type == CELL_ARRAY)
4444 return(subarray(list, n, len));
4447 /* nrest lists */
4448 else if(isList(list->type))
4450 list = (CELL *)list->contents;
4452 if(n < 0) n = convertNegativeOffset(n, list);
4454 while(n-- && list != nilCell)
4455 list = list->next;
4457 rest = getCell(CELL_EXPRESSION);
4458 rest->contents = (UINT)copyList(list);
4459 return(rest);
4462 /* nrest strings
4463 this was UTF-8 sensitive before 9.1.11, but only the
4464 explicit first/last/rest should be UTF8-sensitive
4466 else if(list->type == CELL_STRING)
4467 return(substring((char *)list->contents, list->aux - 1, n, MAX_LONG));
4469 else if(list->type == CELL_ARRAY)
4470 return(subarray(list, n, MAX_LONG));
4472 return(errorProcExt(ERR_ILLEGAL_TYPE, params));
4476 CELL * p_cons(CELL * params)
4478 CELL * cons;
4479 CELL * head;
4480 CELL * tail;
4482 if(params == nilCell)
4483 return(getCell(CELL_EXPRESSION));
4485 head = copyCell(evaluateExpression(params));
4487 cons = getCell(CELL_EXPRESSION);
4488 cons->contents = (UINT)head;
4489 params = params->next;
4491 if(params != nilCell)
4493 tail = evaluateExpression(params);
4495 if(isList(tail->type))
4497 if(params->next != nilCell)
4499 if(((CELL*)params->next)->contents == -1)
4501 cons->contents = (UINT)copyList((CELL *)tail->contents);
4502 tail = (CELL*)cons->contents;
4503 while(tail->next != nilCell)
4504 tail = tail->next;
4505 tail->next = head;
4506 return(cons);
4509 head->next = copyList((CELL *)tail->contents);
4510 cons->type = tail->type;
4512 else
4513 head->next = copyCell(tail);
4516 return(cons);
4521 CELL * p_list(CELL * params)
4523 CELL * list;
4524 CELL * lastCopy;
4525 CELL * copy;
4526 CELL * cell;
4527 int resultIdxSave;
4529 list = getCell(CELL_EXPRESSION);
4530 lastCopy = NULL;
4532 resultIdxSave = resultStackIdx;
4533 while(params != nilCell)
4535 cell = evaluateExpression(params);
4536 if(cell->type == CELL_ARRAY)
4537 copy = arrayList(cell);
4538 else
4539 copy = copyCell(cell);
4540 if(copy != nilCell)
4542 if(lastCopy == NULL)
4543 list->contents = (UINT)copy;
4544 else lastCopy->next = copy;
4546 params = params->next;
4547 lastCopy = copy;
4548 cleanupResults(resultIdxSave);
4551 return(list);
4556 CELL * p_last(CELL * params)
4558 CELL * list;
4559 CELL * listptr;
4560 char * str;
4561 #ifdef SUPPORT_UTF8
4562 char * ptr;
4563 int len;
4564 #endif
4566 list = evaluateExpression(params);
4567 if(list->type == CELL_STRING)
4569 str = (char *)list->contents;
4570 #ifndef SUPPORT_UTF8
4571 return(stuffString(str + list->aux - 2));
4572 #else
4573 ptr = str;
4574 while((len = utf8_1st_len(str)) != 0)
4576 ptr = str;
4577 str += len;
4579 return(stuffStringN(ptr, utf8_1st_len(ptr)));
4580 #endif
4583 else if(isList(list->type))
4585 if(list->aux != (UINT)nilCell) return(copyCell((CELL *)list->aux));
4586 listptr = (CELL *)list->contents;
4587 while(listptr->next != nilCell) listptr = listptr->next;
4588 list->aux = (UINT)listptr;
4589 return(copyCell(listptr));
4592 else if(list->type == CELL_ARRAY)
4593 return(copyCell(*((CELL * *)list->contents + (list->aux - 1) / sizeof(UINT) - 1)));
4595 return(errorProcExt(ERR_ARRAY_LIST_OR_STRING_EXPECTED, params));
4599 /* -------------------------- program flow and logical ------------------ */
4601 CELL * evaluateBlock(CELL * cell)
4603 CELL * result;
4605 result = nilCell;
4607 while(cell != nilCell)
4609 result = evaluateExpression(cell);
4610 cell = cell->next;
4612 return(result);
4616 CELL * p_if(CELL * params)
4618 CELL * cell;
4620 cell = evaluateExpression(params);
4621 while(isNil(cell) || isEmpty(cell))
4623 params = params->next;
4624 if(params->next == nilCell)
4625 return(copyCell(cell));
4626 params = params->next;
4627 cell = evaluateExpression(params);
4630 if(params->next == nilCell) return(copyCell(cell));
4632 return((copyCell(evaluateExpression(params->next))));
4636 CELL * p_when(CELL * params)
4638 CELL * cell;
4640 cell = evaluateExpression(params);
4641 if(isNil(cell) || isEmpty(cell)) return(nilCell);
4643 while(params->next != nilCell)
4645 cell = evaluateExpression(params->next);
4646 params = params->next;
4649 return(copyCell(cell));
4653 CELL * p_unless(CELL * params)
4655 CELL * cell;
4657 cell = evaluateExpression(params);
4658 if(!isNil(cell) && !isEmpty(cell))
4659 params = params->next;
4661 return((copyCell(evaluateExpression(params->next))));
4665 CELL * p_condition(CELL * params)
4667 CELL * condition;
4668 CELL * eval = nilCell;
4670 while(params != nilCell)
4672 if(params->type == CELL_EXPRESSION)
4674 condition = (CELL *)params->contents;
4675 eval = evaluateExpression(condition);
4676 if(!isNil(eval) && !isEmpty(eval))
4678 if(condition->next != nilCell)
4679 return(copyCell(evaluateBlock(condition->next)));
4680 return(copyCell(eval));
4682 params = params->next;
4684 else return(errorProc(ERR_LIST_EXPECTED));
4687 return(copyCell(eval));
4691 CELL * p_case(CELL * params)
4693 CELL * cases;
4694 CELL * cond;
4696 cases = params->next;
4697 params = evaluateExpression(params);
4698 while(cases != nilCell)
4700 if(cases->type == CELL_EXPRESSION)
4702 cond = (CELL *)cases->contents;
4703 if(compareCells(params, cond) == 0
4704 || (cond->type == CELL_SYMBOL && symbolType((SYMBOL *)cond->contents) == CELL_TRUE)
4705 || cond->type == CELL_TRUE)
4706 return(copyCell(evaluateBlock(cond->next)));
4708 cases = cases->next;
4710 return(nilCell);
4713 #define REPEAT_WHILE 0
4714 #define REPEAT_DOWHILE 1
4715 #define REPEAT_UNTIL 2
4716 #define REPEAT_DOUNTIL 3
4718 CELL * p_while(CELL * params) { return(repeat(params, REPEAT_WHILE)); }
4719 CELL * p_doWhile(CELL * params) { return(repeat(params, REPEAT_DOWHILE)); }
4720 CELL * p_until(CELL * params) { return(repeat(params, REPEAT_UNTIL)); }
4721 CELL * p_doUntil(CELL * params) { return(repeat(params, REPEAT_DOUNTIL)); }
4723 CELL * repeat(CELL * params, int type)
4725 CELL * result;
4726 CELL * cell;
4727 int resultIdxSave;
4729 resultIdxSave = resultStackIdx;
4730 result = nilCell;
4731 while(TRUE)
4733 switch(type)
4735 case REPEAT_WHILE:
4736 cell = evaluateExpression(params);
4737 if(isNil(cell) || isEmpty(cell)) goto END_REPEAT;
4738 cleanupResults(resultIdxSave);
4739 result = evaluateBlock(params->next);
4740 continue;
4741 case REPEAT_DOWHILE:
4742 result = evaluateBlock(params->next);
4743 cell = evaluateExpression(params);
4744 if(isNil(cell) || isEmpty(cell)) goto END_REPEAT;
4745 cleanupResults(resultIdxSave);
4746 continue;
4747 case REPEAT_UNTIL:
4748 cell = evaluateExpression(params);
4749 if(!isNil(cell) && !isEmpty(cell)) goto END_REPEAT;
4750 cleanupResults(resultIdxSave);
4751 result = evaluateBlock(params->next);
4752 continue;
4753 case REPEAT_DOUNTIL:
4754 result = evaluateBlock(params->next);
4755 cell = evaluateExpression(params);
4756 if(!isNil(cell) && !isEmpty(cell)) goto END_REPEAT;
4757 cleanupResults(resultIdxSave);
4758 continue;
4759 default:
4760 break;
4763 END_REPEAT:
4764 return(copyCell(result));
4767 #ifdef from_8_8_4_to_9_0_10
4768 CELL * repeat(CELL * params, int type)
4770 CELL * result;
4771 CELL * cell;
4772 int resultIdxSave;
4774 resultIdxSave = resultStackIdx;
4775 result = nilCell;
4776 while(TRUE)
4778 switch(type)
4780 case REPEAT_WHILE:
4781 cell = evaluateExpression(params);
4782 if(isNil(cell) || isEmpty(cell)) goto END_REPEAT;
4783 cleanupResults(resultIdxSave);
4784 deleteList(result);
4785 result = copyCell(evaluateBlock(params->next));
4786 continue;
4787 case REPEAT_DOWHILE:
4788 deleteList(result);
4789 result = copyCell(evaluateBlock(params->next));
4790 cell = evaluateExpression(params);
4791 if(isNil(cell) || isEmpty(cell)) goto END_REPEAT;
4792 cleanupResults(resultIdxSave);
4793 continue;
4794 case REPEAT_UNTIL:
4795 cell = evaluateExpression(params);
4796 if(!isNil(cell) && !isEmpty(cell)) goto END_REPEAT;
4797 cleanupResults(resultIdxSave);
4798 deleteList(result);
4799 result = copyCell(evaluateBlock(params->next));
4800 continue;
4801 case REPEAT_DOUNTIL:
4802 deleteList(result);
4803 result = copyCell(evaluateBlock(params->next));
4804 cell = evaluateExpression(params);
4805 if(!isNil(cell) && !isEmpty(cell)) goto END_REPEAT;
4806 cleanupResults(resultIdxSave);
4807 continue;
4808 default:
4809 break;
4814 END_REPEAT:
4816 return(result);
4818 #endif
4821 CELL * getPushSymbolParam(CELL * params, SYMBOL * * sym)
4823 SYMBOL * symbol;
4824 CELL * cell;
4826 if(params->type != CELL_EXPRESSION)
4827 return(errorProcExt(ERR_LIST_EXPECTED, params));
4829 cell = (CELL *)params->contents;
4830 if(cell->type != CELL_SYMBOL)
4831 return(errorProcExt(ERR_SYMBOL_EXPECTED, cell));
4833 *sym = symbol = (SYMBOL *)cell->contents;
4834 if(isProtected(symbol->flags))
4835 return(errorProcExt2(ERR_SYMBOL_PROTECTED, stuffSymbol(symbol)));
4837 pushEnvironment((CELL *)symbol->contents);
4838 pushEnvironment((UINT)symbol);
4839 symbol->contents = (UINT)nilCell;
4841 return(cell->next);
4844 CELL * loop(CELL * params, int forFlag)
4846 CELL * cell;
4847 CELL * cond = nilCell;
4848 CELL * block;
4849 SYMBOL * symbol;
4850 double fromFlt, toFlt, interval, step, cntFlt;
4851 INT64 stepCnt, i;
4852 INT64 fromInt64, toInt64;
4853 int intFlag;
4854 int resultIdxSave;
4856 cell = getPushSymbolParam(params, &symbol);
4858 /* integer loops for dotimes and (for (i from to) ...) */
4859 if((intFlag = ((CELL *)cell->next)->next == nilCell))
4861 if(forFlag)
4863 cell = getInteger64(cell, &fromInt64);
4864 getInteger64(cell, &toInt64);
4865 stepCnt = (toInt64 > fromInt64) ? toInt64 - fromInt64 : fromInt64 - toInt64;
4867 else /* dotimes */
4869 fromInt64 = toInt64 = 0;
4870 cond = getInteger64(cell, &stepCnt);
4873 else /* float (for (i from to step) ...) */
4875 cell = getFloat(cell, &fromFlt);
4876 cell = getFloat(cell, &toFlt);
4877 cond = getFloat(cell, &step);
4878 if(isnan(fromFlt) || isnan(toFlt) || isnan(step))
4879 return(errorProc(ERR_INVALID_PARAMETER_NAN));
4880 if(step < 0) step = -step;
4881 if(fromFlt > toFlt) step = -step;
4882 cntFlt = (fromFlt < toFlt) ? (toFlt - fromFlt)/step : (fromFlt - toFlt)/step;
4883 stepCnt = (cntFlt > 0.0) ? floor(cntFlt + 0.0000000001) : floor(-cntFlt + 0.0000000001);
4886 block = params->next;
4887 resultIdxSave = resultStackIdx;
4888 cell = nilCell;
4889 for(i = 0; i <= stepCnt; i++)
4891 if(!forFlag && i == stepCnt) break;
4892 deleteList((CELL *)symbol->contents);
4893 if(intFlag)
4895 symbol->contents =
4896 (UINT)stuffInteger64((fromInt64 > toInt64) ? fromInt64 - i:
4897 fromInt64 + i);
4899 else
4901 interval = fromFlt + i * step;
4902 symbol->contents = (UINT)stuffFloat(&interval);
4904 cleanupResults(resultIdxSave);
4905 if(cond != nilCell)
4907 cell = evaluateExpression(cond);
4908 if(!isNil(cell)) break;
4910 cell = evaluateBlock(block);
4913 cell = copyCell(cell);
4914 deleteList((CELL *)symbol->contents);
4915 symbol = (SYMBOL*)popEnvironment();
4916 symbol->flags &= ~SYMBOL_PROTECTED;
4917 symbol->contents = (UINT)popEnvironment();
4919 return(cell);
4923 CELL * p_dotimes(CELL * params)
4925 return(loop(params, 0));
4928 CELL * p_for(CELL * params)
4930 return(loop(params, 1));
4934 #define DOLIST 0
4935 #define DOARGS 1
4936 #define DOSTRING 2
4938 CELL * p_dolist(CELL * params)
4940 return(dolist(params, DOLIST));
4943 CELL * p_doargs(CELL * params)
4945 return(dolist(params, DOARGS));
4948 CELL * p_dostring(CELL * params)
4950 return(dolist(params, DOSTRING));
4953 CELL * dolist(CELL * params, int doType)
4955 CELL * cell;
4956 CELL * list = nilCell;
4957 char * str;
4958 #ifdef SUPPORT_UTF8
4959 int chr;
4960 #endif
4961 CELL * cond = nilCell;
4962 SYMBOL * symbol;
4963 CELL * cellIdx;
4964 int resultIdxSave;
4966 cell = getPushSymbolParam(params, &symbol);
4968 pushEnvironment(dolistIdxSymbol->contents);
4969 pushEnvironment(dolistIdxSymbol);
4970 cellIdx = stuffInteger(0);
4971 dolistIdxSymbol->contents = (UINT)cellIdx;
4973 switch(doType)
4975 case DOLIST:
4976 list = copyCell(evaluateExpression(cell));
4977 if(!isList(list->type))
4978 return(errorProcExt(ERR_LIST_EXPECTED, cell));
4979 cond = cell->next;
4980 break;
4981 case DOARGS:
4982 list = copyCell((CELL *)argsSymbol->contents);
4983 cond = cell;
4984 break;
4985 case DOSTRING:
4986 getString(cell, &str);
4987 resultIdxSave = resultStackIdx;
4988 cond = cell->next;
4989 while(*str)
4991 cleanupResults(resultIdxSave);
4992 deleteList((CELL *)symbol->contents);
4993 #ifdef SUPPORT_UTF8
4994 str = utf8_wchar(str, &chr);
4995 symbol->contents = (UINT)stuffInteger(chr);
4996 #else
4997 symbol->contents = (UINT)stuffInteger((int)*str++);
4998 #endif
4999 if(cond != nilCell)
5001 cell = evaluateExpression(cond);
5002 if(!isNil(cell)) break;
5004 cell = evaluateBlock(params->next);
5005 cellIdx->contents += 1;
5007 goto FINISH_DO;
5008 break;
5011 /* make sure worklist gets destroyed */
5012 pushResult(list);
5013 list = (CELL *)list->contents;
5015 resultIdxSave = resultStackIdx;
5016 cell = nilCell;
5017 while(list!= nilCell)
5019 cleanupResults(resultIdxSave);
5020 deleteList((CELL *)symbol->contents);
5021 symbol->contents = (UINT)copyCell(list);
5022 if(cond != nilCell)
5024 cell = evaluateExpression(cond);
5025 if(!isNil(cell)) break;
5027 cell = evaluateBlock(params->next);
5028 cellIdx->contents += 1;
5029 list = list->next;
5032 FINISH_DO:
5033 pushResult(cellIdx);
5034 cell = copyCell(cell);
5035 dolistIdxSymbol = (SYMBOL*)popEnvironment();
5036 dolistIdxSymbol->contents = (UINT)popEnvironment();
5037 deleteList((CELL *)symbol->contents);
5038 symbol = (SYMBOL*)popEnvironment();
5039 symbol->contents = (UINT)popEnvironment();
5041 return(cell);
5045 CELL * p_evalBlock(CELL * params)
5047 return(copyCell(evaluateBlock(params)));
5051 CELL * p_silent(CELL * params)
5053 evalSilent = TRUE;
5055 return(copyCell(evaluateBlock(params)));
5059 CELL * p_and(CELL * params)
5061 CELL * result = nilCell;
5063 while(params != nilCell)
5065 result = evaluateExpression(params);
5066 if(isNil(result) || isEmpty(result)) return(copyCell(result));
5067 params = params->next;
5070 return(copyCell(result));
5074 CELL * p_or(CELL * params)
5076 CELL * result = nilCell;
5078 while(params != nilCell)
5080 result = evaluateExpression(params);
5081 if(!isNil(result) && !isEmpty(result))
5082 return(copyCell(result));
5083 params = params->next;
5086 return(copyCell(result));
5090 CELL * p_not(CELL * params)
5092 CELL * eval;
5094 eval = evaluateExpression(params);
5095 if(isNil(eval) || isEmpty(eval))
5096 return(trueCell);
5097 return(nilCell);
5102 /* ------------------------------ I / O --------------------------------- */
5104 CELL * p_print(CELL * params)
5106 return println(params, FALSE);
5110 CELL * p_println(CELL * params)
5112 return println(params, TRUE);
5116 CELL * println(CELL * params, int lineFeed)
5118 CELL * result;
5120 result = nilCell;
5121 while(params != nilCell)
5123 result = evaluateExpression(params);
5124 if(printCell(result, 0, OUT_DEVICE) == 0)
5125 return(nilCell);
5126 params = params->next;
5129 if(lineFeed) varPrintf(OUT_DEVICE, LINE_FEED);
5131 return(copyCell(result));
5135 CELL * p_device(CELL * params)
5137 if(params != nilCell)
5138 getInteger(params, &printDevice);
5139 return(stuffInteger(printDevice));
5143 CELL * p_load(CELL * params)
5145 char * fileName;
5146 CELL * result = nilCell;
5147 CELL * next;
5148 SYMBOL * context;
5149 int count = 0;
5151 /* get last parameter */
5152 if((next = params) == nilCell)
5153 errorProc(ERR_MISSING_ARGUMENT);
5154 while(next->next != nilCell)
5156 count++;
5157 next = next->next;
5160 next = evaluateExpression(next);
5161 if(next->type == CELL_STRING)
5163 count++;
5164 context = mainContext;
5166 else
5168 if(count == 0)
5169 errorProcExt(ERR_STRING_EXPECTED, next);
5170 if((context = getCreateContext(next, FALSE)) == NULL)
5171 errorProcExt(ERR_SYMBOL_OR_CONTEXT_EXPECTED, next);
5172 next = NULL;
5175 while(count--)
5177 /* if last arg was a string, avoid double evaluation */
5178 if(count == 0 && next != NULL)
5179 getStringSize(next, &fileName, NULL, FALSE);
5180 else
5181 params = getString(params, &fileName);
5183 result = loadFile(fileName, 0, 0, context);
5185 if(result == NULL)
5186 return(errorProcExt2(ERR_ACCESSING_FILE, stuffString(fileName)));
5189 return(result);
5193 void saveContext(SYMBOL * sPtr, UINT device)
5195 SYMBOL * contextSave;
5197 contextSave = currentContext;
5199 currentContext = sPtr;
5201 if(sPtr != mainContext)
5202 varPrintf(device, "%s(context '%s)%s%s",
5203 LINE_FEED, sPtr->name, LINE_FEED, LINE_FEED);
5206 saveSymbols((SYMBOL *)((CELL*)sPtr->contents)->aux, device);
5208 if(sPtr != mainContext)
5209 varPrintf(device, "%s(context 'MAIN)%s%s",
5210 LINE_FEED, LINE_FEED, LINE_FEED);
5212 currentContext = contextSave;
5216 void saveSymbols(SYMBOL * sPtr, UINT device)
5218 int type;
5220 if(sPtr != NIL_SYM && sPtr != NULL)
5222 saveSymbols(sPtr->left, device);
5223 type = symbolType(sPtr);
5224 if(type == CELL_CONTEXT)
5226 if(sPtr == (SYMBOL *)((CELL *)sPtr->contents)->contents)
5228 if(sPtr != currentContext) saveContext(sPtr, device);
5230 else printSymbol(sPtr, device);
5232 else if(type != CELL_PRIMITIVE && type != CELL_NIL
5233 && sPtr != trueSymbol && type != CELL_IMPORT_CDECL
5234 && sPtr != argsSymbol
5235 #ifdef WIN_32
5236 && type != CELL_IMPORT_DLL
5237 #endif
5239 if(*sPtr->name != '$') printSymbol(sPtr, device);
5240 saveSymbols(sPtr->right, device);
5245 CELL * p_save(CELL * params)
5247 char * fileName;
5248 STREAM strStream;
5249 UINT printDeviceSave;
5250 CELL * result;
5251 SYMBOL * contextSave;
5252 CELL * dataCell;
5254 contextSave = currentContext;
5255 currentContext = mainContext;
5256 printDeviceSave = printDevice;
5258 params = getString(params, &fileName);
5260 /* check for URL format */
5261 if(my_strnicmp(fileName, "http://", 7) == 0)
5263 openStrStream(&strStream, MAX_STRING, 0);
5264 serializeSymbols(params, (UINT)&strStream);
5265 dataCell = stuffString(strStream.buffer);
5266 result = getPutPostDeleteUrl(fileName, dataCell, HTTP_PUT_URL, 60000);
5267 closeStrStream(&strStream);
5268 deleteList(dataCell);
5269 return(result);
5271 else
5273 if(my_strnicmp(fileName, "file://", 7) == 0)
5274 fileName = fileName + 7;
5275 if( (printDevice = (UINT)openFile(fileName, "write", NULL)) == (UINT)-1)
5276 return(errorProcExt2(ERR_SAVING_FILE, stuffString(fileName)));
5277 serializeSymbols(params, OUT_DEVICE);
5278 close((int)printDevice);
5281 currentContext = contextSave;
5282 printDevice = printDeviceSave;
5283 return(trueCell);
5286 void serializeSymbols(CELL * params, UINT device)
5288 SYMBOL * sPtr;
5290 if(params->type == CELL_NIL)
5291 saveSymbols((SYMBOL *)((CELL*)currentContext->contents)->aux, device);
5292 else
5293 while(params != nilCell)
5295 params = getSymbol(params, &sPtr);
5296 if(symbolType(sPtr) == CELL_CONTEXT)
5297 saveContext((SYMBOL*)((CELL *)sPtr->contents)->contents, device);
5298 else
5299 printSymbol(sPtr, device);
5303 /* ----------------------- copy a context with 'new' -------------- */
5304 static SYMBOL * fromContext;
5305 static SYMBOL * newContext;
5306 static int overWriteFlag;
5308 CELL * copyContextList(CELL * cell);
5309 UINT * copyContextArray(CELL * array);
5312 CELL * copyContextCell(CELL * cell)
5314 CELL * newCell;
5315 SYMBOL * sPtr;
5316 SYMBOL * newSptr;
5318 if(firstFreeCell == NULL) allocBlock();
5319 newCell = firstFreeCell;
5320 firstFreeCell = newCell->next;
5321 ++cellCount;
5323 newCell->type = cell->type;
5324 newCell->next = nilCell;
5325 newCell->aux = cell->aux;
5326 newCell->contents = cell->contents;
5328 if(cell->type == CELL_DYN_SYMBOL)
5330 sPtr = (SYMBOL*)cell->aux;
5331 if(sPtr->context == fromContext)
5332 newCell->aux =
5333 (UINT)translateCreateSymbol(sPtr->name, 0, newContext, TRUE);
5334 newCell->contents = (UINT)allocMemory(strlen((char *)cell->contents) + 1);
5335 memcpy((void *)newCell->contents,
5336 (void*)cell->contents, strlen((char *)cell->contents) + 1);
5339 if(cell->type == CELL_SYMBOL)
5341 /* if the cell copied itself contains a symbol copy it recursevely,
5342 if new, if not done here it might not been seen as new later and left
5343 without contents */
5344 sPtr = (SYMBOL *)cell->contents;
5345 if(sPtr->context == fromContext && !(sPtr->flags & SYMBOL_BUILTIN))
5347 if((newSptr = lookupSymbol(sPtr->name, newContext)) == NULL)
5349 newSptr = translateCreateSymbol(sPtr->name, symbolType(sPtr), newContext, TRUE);
5350 newSptr->contents = (UINT)copyContextCell((CELL*)sPtr->contents);
5352 newCell->contents = (UINT)newSptr;
5356 if(isEnvelope(cell->type))
5358 if(cell->type == CELL_ARRAY)
5359 newCell->contents = (UINT)copyContextArray(cell);
5360 else
5361 newCell->contents = (UINT)copyContextList((CELL *)cell->contents);
5364 else if(cell->type == CELL_STRING)
5366 newCell->contents = (UINT)allocMemory((UINT)cell->aux);
5367 memcpy((void *)newCell->contents,
5368 (void*)cell->contents, (UINT)cell->aux);
5371 return(newCell);
5375 CELL * copyContextList(CELL * cell)
5377 CELL * firstCell;
5378 CELL * newCell;
5380 if(cell == nilCell || cell == trueCell) return(cell);
5382 firstCell = newCell = copyContextCell(cell);
5384 while((cell = cell->next) != nilCell)
5386 newCell->next = copyContextCell(cell);
5387 newCell = newCell->next;
5390 return(firstCell);
5394 UINT * copyContextArray(CELL * array)
5396 CELL * * newAddr;
5397 CELL * * orgAddr;
5398 CELL * * addr;
5399 size_t size;
5401 addr = newAddr = (CELL * *)callocMemory(array->aux);
5403 size = (array->aux - 1) / sizeof(UINT);
5404 orgAddr = (CELL * *)array->contents;
5406 while(size--)
5407 *(newAddr++) = copyContextCell(*(orgAddr++));
5409 return((UINT*)addr);
5413 void iterateSymbols(SYMBOL * sPtr)
5415 int type, newFlag = FALSE;
5416 SYMBOL * newPtr;
5418 if(sPtr != NIL_SYM && sPtr != NULL && !(sPtr->flags & SYMBOL_BUILTIN))
5420 iterateSymbols(sPtr->left);
5421 type = symbolType(sPtr);
5423 /* check for default symbol */
5424 if(*sPtr->name == *fromContext->name && strcmp(sPtr->name, fromContext->name) == 0)
5426 if((newPtr = lookupSymbol(newContext->name, newContext)) == NULL)
5428 newPtr = translateCreateSymbol(newContext->name, type, newContext, TRUE);
5429 newFlag = TRUE;
5432 else
5434 if((newPtr = lookupSymbol(sPtr->name, newContext)) == NULL)
5436 newPtr = translateCreateSymbol(sPtr->name, type, newContext, TRUE);
5437 newFlag = TRUE;
5441 if(overWriteFlag == TRUE || newFlag == TRUE)
5443 deleteList((CELL *)newPtr->contents);
5444 newPtr->contents = (UINT)copyContextCell((CELL*)sPtr->contents);
5447 iterateSymbols(sPtr->right);
5453 CELL * p_new(CELL * params)
5455 CELL * next;
5457 overWriteFlag = FALSE;
5459 params = getContext(params, &fromContext);
5460 if(!fromContext) return(nilCell); /* for debug mode */
5462 next = params->next;
5464 if(params == nilCell)
5465 newContext = currentContext;
5466 else
5468 params = evaluateExpression(params);
5469 if(params->type == CELL_CONTEXT || params->type == CELL_SYMBOL)
5470 newContext = (SYMBOL *)params->contents;
5471 else
5472 return(errorProcExt(ERR_CONTEXT_EXPECTED, params));
5474 overWriteFlag = (evaluateExpression(next)->type != CELL_NIL);
5476 /* allow symbols to be converted to contexts */
5477 if(symbolType(newContext) != CELL_CONTEXT)
5479 if(isProtected(newContext->flags))
5480 return(errorProcExt(ERR_SYMBOL_PROTECTED, params));
5482 if(newContext->context != mainContext)
5483 return(errorProcExt2(ERR_NOT_IN_MAIN, stuffSymbol(newContext)));
5485 deleteList((CELL *)newContext->contents);
5486 makeContextFromSymbol(newContext, NULL);
5490 if(newContext == mainContext)
5491 return(errorProc(ERR_TARGET_NO_MAIN));
5493 iterateSymbols((SYMBOL *)((CELL*)fromContext->contents)->aux);
5495 return(copyCell((CELL*)newContext->contents));
5499 CELL * p_defineNew(CELL * params)
5501 SYMBOL * sourcePtr;
5502 SYMBOL * targetPtr;
5503 char * name;
5505 params = getSymbol(params, &sourcePtr);
5506 if(params != nilCell)
5508 params = getSymbol(params, &targetPtr);
5509 name = targetPtr->name;
5510 newContext = targetPtr->context;
5512 else
5514 name = sourcePtr->name;
5515 newContext = currentContext;
5518 if(newContext == mainContext)
5519 return(errorProc(ERR_TARGET_NO_MAIN));
5521 fromContext = sourcePtr->context;
5522 targetPtr = translateCreateSymbol(name, symbolType(sourcePtr), newContext, TRUE);
5524 deleteList((CELL *)targetPtr->contents);
5525 targetPtr->contents = (UINT)copyContextCell((CELL*)sourcePtr->contents);
5527 return(stuffSymbol(targetPtr));
5532 /* ------------------------------ system ------------------------------ */
5534 CELL * isType(CELL *, int);
5536 CELL * p_isNil(CELL * params)
5538 if(isNil(evaluateExpression(params)))
5539 return(trueCell);
5541 return(nilCell);
5544 CELL * p_isEmpty(CELL * params)
5546 return(isEmptyFunc(evaluateExpression(params)));
5549 CELL * isEmptyFunc(CELL * cell)
5551 if(cell->type == CELL_STRING)
5553 if(*(char*)cell->contents == 0)
5554 return(trueCell);
5555 else return(nilCell);
5558 if(!isList(cell->type))
5559 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED, cell));
5560 if(cell->contents == (UINT)nilCell)
5561 return(trueCell);
5562 return(nilCell);
5565 CELL * isZero(CELL * cell)
5567 #ifndef NEWLISP64
5568 if(cell->type == CELL_INT64)
5570 if(*(INT64 *)&cell->aux == 0)
5571 return(trueCell);
5572 else
5573 return(nilCell);
5575 #endif
5577 if(cell->type == CELL_FLOAT)
5579 #ifndef NEWLISP64
5580 if(*(double *)&cell->aux == 0.0)
5581 #else
5582 if(*(double *)&cell->contents == 0.0)
5583 #endif
5584 return(trueCell);
5585 else
5586 return(nilCell);
5589 if(cell->type == CELL_LONG)
5591 if(cell->contents == 0)
5592 return(trueCell);
5595 return(nilCell);
5599 CELL * p_isNull(CELL * params)
5601 CELL * cell;
5603 cell = evaluateExpression(params);
5604 if(isNil(cell))
5605 return(trueCell);
5607 if( (cell->type == CELL_STRING || isList(cell->type)))
5608 return(isEmptyFunc(cell));
5610 #ifndef NEWLISP64
5611 if(cell->type == CELL_FLOAT && (isnan(*(double *)&cell->aux)) )
5612 #else
5613 if(cell->type == CELL_FLOAT && (isnan(*(double *)&cell->contents)))
5614 #endif
5615 return(trueCell);
5617 return(isZero(cell));
5621 CELL * p_isZero(CELL * params)
5623 params = evaluateExpression(params);
5624 return(isZero(params));
5628 CELL * p_isTrue(CELL * params)
5630 params = evaluateExpression(params);
5631 if(!isNil(params) && !isEmpty(params))
5632 return(trueCell);
5634 return(nilCell);
5637 CELL * p_isInteger(CELL * params)
5639 params = evaluateExpression(params);
5640 if((params->type & COMPARE_TYPE_MASK) == CELL_INT)
5641 return(trueCell);
5642 return(nilCell);
5646 CELL * p_isFloat(CELL * params)
5647 { return(isType(params, CELL_FLOAT)); }
5649 CELL * p_isNumber(CELL * params)
5651 params = evaluateExpression(params);
5652 if(isNumber(params->type)) return(trueCell);
5653 return(nilCell);
5656 CELL * p_isString(CELL * params)
5657 { return(isType(params, CELL_STRING)); }
5659 CELL * p_isSymbol(CELL * params)
5660 { return(isType(params, CELL_SYMBOL)); }
5662 CELL * p_isContext(CELL * params)
5664 char * symStr;
5665 SYMBOL * ctx;
5667 /* check type */
5668 if(params->next == nilCell)
5669 return(isType(params, CELL_CONTEXT));
5671 /* check for existense of symbol */
5672 params = getContext(params, &ctx);
5673 if(!ctx) return(nilCell); /* for debug mode */
5674 getString(params, &symStr);
5676 return (lookupSymbol(symStr, ctx) ? trueCell : nilCell);
5679 CELL * p_isPrimitive(CELL * params)
5680 { return(isType(params, CELL_PRIMITIVE)); }
5683 CELL * p_isGlobal(CELL * params)
5685 params = evaluateExpression(params);
5686 if(isSymbol(params->type) && isGlobal(((SYMBOL *)params->contents)->flags))
5687 return(trueCell);
5688 return(nilCell);
5691 CELL * p_isProtected(CELL * params)
5693 params = evaluateExpression(params);
5694 if(isSymbol(params->type) && isProtected(((SYMBOL *)params->contents)->flags))
5695 return(trueCell);
5696 return(nilCell);
5699 CELL * p_isAtom(CELL * params)
5701 if(params == nilCell)
5702 return(errorProc(ERR_MISSING_ARGUMENT));
5703 params = evaluateExpression(params);
5704 if(params->type & ENVELOPE_TYPE_MASK) return(nilCell);
5705 return(trueCell);
5708 CELL * p_isQuote(CELL *params)
5709 { return(isType(params, CELL_QUOTE)); }
5711 CELL * p_isList(CELL * params)
5712 { return(isType(params, CELL_EXPRESSION)); }
5714 CELL * p_isLambda(CELL * params)
5715 { return(isType(params, CELL_LAMBDA)); }
5717 CELL * p_isMacro(CELL * params)
5718 { return(isType(params, CELL_MACRO)); }
5720 CELL * p_isArray(CELL * params)
5721 { return(isType(params, CELL_ARRAY)); }
5723 CELL * isType(CELL * params, int operand)
5725 CELL * contextCell;
5727 if(params == nilCell)
5728 return(errorProc(ERR_MISSING_ARGUMENT));
5729 params = evaluateExpression(params);
5730 if((UINT)operand == params->type) return(trueCell);
5731 switch(operand)
5733 case CELL_PRIMITIVE:
5734 if(params->type == CELL_IMPORT_CDECL
5735 #ifdef WIN_32
5736 || params->type == CELL_IMPORT_DLL
5737 #endif
5739 return(trueCell);
5740 break;
5741 case CELL_EXPRESSION:
5742 if(isList(params->type)) return(trueCell);
5743 break;
5744 case CELL_SYMBOL:
5745 if(params->type == CELL_DYN_SYMBOL) /* check if already created */
5747 contextCell = (CELL *)((SYMBOL *)params->aux)->contents;
5748 if(contextCell->type != CELL_CONTEXT)
5749 fatalError(ERR_CONTEXT_EXPECTED,
5750 stuffSymbol((SYMBOL*)params->aux), TRUE);
5751 if(lookupSymbol((char *)params->contents, (SYMBOL*)contextCell->contents))
5752 return(trueCell);
5755 break;
5756 default:
5757 break;
5760 return(nilCell);
5764 CELL * p_isLegal(CELL * params)
5766 char * symStr;
5768 getString(params, &symStr);
5770 if(isLegalSymbol(symStr)) return(trueCell);
5772 return(nilCell);
5776 int isLegalSymbol(char * source)
5778 STREAM stream;
5779 char token[MAX_SYMBOL + 1];
5780 int tklen;
5782 if(*source == (char)'"' || *source == (char)'{' || *source == (char)'['
5783 || (unsigned char)*source <= (unsigned char)' ' || *source == (char)';' || *source == (char)'#')
5784 return(0);
5786 makeStreamFromString(&stream, source);
5788 return( (getToken(&stream, token, &tklen) == TKN_SYMBOL) && tklen == strlen(source));
5792 CELL * p_exit(CELL * params)
5794 UINT result;
5796 if(demonMode)
5798 fclose(IOchannel);
5799 #ifndef WIN_32
5800 IOchannel = NULL;
5801 #endif
5802 longjmp(errorJump, ERR_USER_RESET);
5805 if(params != nilCell) getInteger(params, (UINT*)&result);
5806 else result = 0;
5807 exit(result);
5808 return(trueCell);
5813 CELL * p_reset(CELL * params)
5815 #ifndef LIBRARY
5816 #ifndef WIN_32
5817 if (getFlag(params))
5818 execv(MainArgs[0], MainArgs);
5819 #endif
5820 #endif
5822 longjmp(errorJump, ERR_USER_RESET);
5823 return(nilCell);
5827 CELL * p_errorEvent(CELL * params)
5829 CELL * symCell;
5831 if(params != nilCell) getCreateSymbol(params, &errorEvent, "$error-event");
5832 symCell = getCell(CELL_SYMBOL);
5833 symCell->contents = (UINT)errorEvent;
5834 return(symCell);
5837 #ifndef WIN_32
5839 CELL * p_timerEvent(CELL * params)
5841 CELL * symCell;
5842 double seconds;
5843 UINT timerOption = 0;
5844 struct itimerval timerVal;
5845 struct itimerval outVal;
5846 static double duration;
5848 if(params != nilCell)
5850 params = getCreateSymbol(params, &timerEvent, "$timer");
5852 if(params != nilCell)
5854 params = getFloat(params, &seconds);
5855 duration = seconds;
5856 if(params != nilCell)
5857 getInteger(params, (UINT*)&timerOption);
5858 memset(&timerVal, 0, sizeof(timerVal));
5859 timerVal.it_value.tv_sec = seconds;
5860 timerVal.it_value.tv_usec = (seconds - timerVal.it_value.tv_sec) * 1000000;
5861 if(setitimer((int)timerOption, &timerVal, &outVal) == -1)
5862 return(nilCell);
5863 return(stuffInteger(0));
5865 else
5866 getitimer(timerOption, &outVal);
5868 seconds = duration - (outVal.it_value.tv_sec + outVal.it_value.tv_usec / 1000000.0);
5869 return(stuffFloat(&seconds));
5872 symCell = getCell(CELL_SYMBOL);
5873 symCell->contents = (UINT)timerEvent;
5874 return(symCell);
5876 #endif
5878 CELL * p_signal(CELL * params)
5880 CELL * symCell;
5881 SYMBOL * signalEvent;
5882 UINT sig;
5883 char sigStr[12];
5885 params = getInteger(params, (UINT *)&sig);
5886 if(sig > 32 || sig < 1) return(nilCell);
5888 if(params != nilCell)
5890 if(isNil(params))
5892 signal(sig, SIG_IGN);
5893 symHandler[sig - 1] = nilSymbol;
5895 else if(isTrue(params))
5897 signal(sig, SIG_DFL);
5898 symHandler[sig - 1] = trueSymbol;
5900 else
5902 snprintf(sigStr, 11, "$signal-%ld", sig);
5903 getCreateSymbol(params, &signalEvent, sigStr);
5904 symHandler[sig - 1] = signalEvent;
5905 if(signal(sig, signal_handler) == SIG_ERR)
5906 return(nilCell);
5910 symCell = getCell(CELL_SYMBOL);
5911 symCell->contents = (UINT)symHandler[sig - 1];
5912 return(symCell);
5916 CELL * p_errorNumber(CELL * params)
5918 return(stuffInteger((UINT)errorReg));
5922 CELL * p_errorText(CELL * params)
5924 UINT errorNumber = errorReg;
5926 if(params == nilCell)
5928 if(errorStream.buffer != NULL)
5929 return(stuffString(errorStream.buffer));
5931 else
5932 getInteger(params, &errorNumber);
5935 if(errorNumber > MAX_ERROR_NUMBER)
5936 errorNumber = ERR_NUMBER_OUT_OF_RANGE;
5938 return(stuffString(errorMessage[errorNumber]));
5943 CELL * p_dump(CELL * params)
5945 CELL * blockPtr;
5946 int i;
5947 CELL * cell;
5949 if(params != nilCell)
5951 cell = evaluateExpression(params);
5952 return(stuffIntegerList
5953 (5, cell, cell->type, cell->next, cell->aux, cell->contents));
5956 blockPtr = cellMemory;
5957 while(blockPtr != NULL)
5959 for(i = 0; i < MAX_BLOCK; i++)
5961 if(*(UINT *)blockPtr != CELL_FREE)
5963 varPrintf(OUT_DEVICE, "address=%lX type=%d contents=", blockPtr, blockPtr->type);
5964 printCell(blockPtr, TRUE, OUT_DEVICE);
5965 varPrintf(OUT_DEVICE,LINE_FEED);
5967 ++blockPtr;
5969 blockPtr = blockPtr->next;
5971 return(trueCell);
5975 CELL * p_mainArgs(CELL * params)
5977 CELL * cell;
5978 ssize_t idx;
5980 cell = (CELL*)mainArgsSymbol->contents;
5981 if(params != nilCell)
5983 getInteger(params, (UINT *)&idx);
5984 cell = (CELL *)cell->contents;
5985 if(idx < 0) idx = convertNegativeOffset(idx, (CELL *)cell);
5986 while(idx--) cell = cell->next;
5989 return(copyCell(cell));
5993 CELL * p_context(CELL * params)
5995 CELL * cell;
5996 SYMBOL * sPtr;
5997 SYMBOL * cPtr;
5998 char * newSymStr;
6000 if(params->type == CELL_NIL)
6001 return(copyCell((CELL *)currentContext->contents));
6003 if((cPtr = getCreateContext(params, TRUE)) == NULL)
6004 return(errorProcExt(ERR_SYMBOL_OR_CONTEXT_EXPECTED, params));
6006 if(params->next == nilCell)
6008 currentContext = cPtr;
6009 return(copyCell( (CELL *)currentContext->contents));
6012 params = params->next;
6013 cell = evaluateExpression(params);
6014 if(cell->type == CELL_STRING)
6015 newSymStr = (char *)cell->contents;
6016 else if(cell->type == CELL_SYMBOL)
6017 newSymStr = ((SYMBOL *)cell->contents)->name;
6018 else if(cell->type == CELL_DYN_SYMBOL)
6020 sPtr = getDynamicSymbol(cell);
6021 newSymStr = sPtr->name;
6023 else
6024 return(errorProcExt(ERR_ILLEGAL_TYPE, cell));
6026 sPtr = translateCreateSymbol(newSymStr, CELL_NIL, cPtr, TRUE);
6027 if(params->next == nilCell)
6029 pushResultFlag = FALSE;
6030 return((CELL *)sPtr->contents);
6033 if(strcmp(cPtr->name, sPtr->name) == 0)
6034 return(nilCell);
6036 return(setDefine(sPtr, params->next, TYPE_SET));
6040 SYMBOL * getCreateContext(CELL * cell, int evaluate)
6042 SYMBOL * contextSymbol;
6044 if(evaluate)
6045 cell = evaluateExpression(cell);
6047 if(cell->type == CELL_SYMBOL || cell->type == CELL_CONTEXT)
6048 contextSymbol = (SYMBOL *)cell->contents;
6049 else
6050 return(NULL);
6053 if(symbolType(contextSymbol) != CELL_CONTEXT)
6055 if(isProtected(contextSymbol->flags))
6056 return(NULL);
6058 if(contextSymbol->context != mainContext)
6060 contextSymbol= translateCreateSymbol(
6061 contextSymbol->name, CELL_CONTEXT, mainContext, 1);
6064 if(symbolType(contextSymbol) != CELL_CONTEXT)
6066 if(isProtected(contextSymbol->flags))
6067 errorProcExt(ERR_CONTEXT_EXPECTED, stuffSymbol(contextSymbol));
6069 deleteList((CELL *)contextSymbol->contents);
6070 makeContextFromSymbol(contextSymbol, NULL);
6074 /* if this is a context var retrieve the real context symbol */
6075 return((SYMBOL *)((CELL *)contextSymbol->contents)->contents);
6079 CELL * p_default(CELL * params)
6081 SYMBOL * contextSymbol;
6083 getContext(params, &contextSymbol);
6085 return(stuffSymbol(translateCreateSymbol(contextSymbol->name, CELL_NIL, contextSymbol, TRUE)));
6088 CELL * p_colon(CELL * params)
6090 SYMBOL * contextSymbol = NULL;
6091 SYMBOL * methodSymbol;
6092 CELL * proc;
6093 CELL * cell;
6094 CELL * obj;
6095 CELL * quote;
6097 if(params->type != CELL_SYMBOL)
6098 return(errorProcExt(ERR_SYMBOL_EXPECTED, params));
6100 methodSymbol = (SYMBOL *)params->contents;
6101 params = params->next;
6102 obj = evaluateExpression(params);
6103 if(obj->type != CELL_EXPRESSION)
6104 return(errorProcExt(ERR_LIST_EXPECTED, obj));
6105 cell = (CELL *)obj->contents;
6107 if(cell->type == CELL_SYMBOL || cell->type == CELL_CONTEXT)
6108 contextSymbol = (SYMBOL *)cell->contents;
6109 if(contextSymbol == NULL || symbolType(contextSymbol) != CELL_CONTEXT)
6110 return(errorProcExt(ERR_CONTEXT_EXPECTED, cell));
6112 if((methodSymbol = lookupSymbol(methodSymbol->name, contextSymbol)) == NULL)
6113 return(errorProc(ERR_INVALID_FUNCTION));
6115 proc = getCell(CELL_EXPRESSION);
6116 proc->contents = (UINT)stuffSymbol(methodSymbol);
6117 quote = getCell(CELL_QUOTE);
6118 quote->contents = (UINT)copyCell(obj);
6119 cell = (CELL *)proc->contents;
6120 cell->next = quote;
6121 cell = quote;
6122 params = params->next;
6123 while(params != nilCell)
6125 cell->next = copyCell(params);
6126 cell = cell->next;
6127 params = params->next;
6130 pushResult(proc);
6131 return(copyCell(evaluateExpression(proc)));
6135 CELL * p_systemSymbol(CELL * params)
6137 UINT idx;
6139 getInteger(params, &idx);
6141 if(idx > 15 || idx < 0) return(nilCell);
6143 return(copyCell((CELL*)sysSymbol[idx]->contents));
6147 /* end of file */