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/>.
29 #include <readline/readline.h>
30 #include <readline/history.h>
43 #define freeMemory free
46 #define INIT_FILE "init.lsp"
47 #define fprintf win32_fprintf
48 #define fgets win32_fgets
49 #define fclose win32_fclose
51 #define INIT_FILE "/usr/share/newlisp/init.lsp"
55 extern STREAM libStrStream
;
60 char ostype
[]="Linux";
76 char ostype
[]="Tru64Unix";
79 char ostype
[]="Solaris";
85 char ostype
[]="Win32";
96 "\nnewLISP v.9.3.3 Copyright (c) 2008 Lutz Mueller. All rights reserved.\n\n%s\n\n";
101 "newLISP v.9.3.3 on %s IPv%d UTF-8%s\n\n";
104 "newLISP v.9.3.3 on %s IPv%d%s\n\n";
109 "newLISP v.9.3.3 64-bit on %s IPv%d UTF-8%s\n\n";
112 "newLISP v.9.3.3 64-bit on %s IPv%d%s\n\n";
117 ", execute 'newlisp -h' for more info.";
119 char linkOffset
[] = "@@@@@@@@";
121 void printHelpText(void);
123 /* --------------------- globals -------------------------------------- */
125 /* interactive command line */
127 int commandLineFlag
= TRUE
;
131 int noPromptMode
= 0;
132 int forcePromptMode
= 0;
137 char * IOdomain
= NULL
;
143 int MAX_CPU_STACK
= 0x800;
145 int MAX_RESULT_STACK
;
147 long MAX_CELL_COUNT
= 0x10000000;
149 long MAX_CELL_COUNT
= 0x800000000000000LL
;
152 CELL
* firstFreeCell
= NULL
;
156 CELL
* lastCellCopied
;
161 SYMBOL
* questionSymbol
;
163 SYMBOL
* currentFunc
;
165 SYMBOL
* mainArgsSymbol
;
166 SYMBOL
* dolistIdxSymbol
;
168 SYMBOL
* sysSymbol
[MAX_REGEX_EXP
];
171 SYMBOL
* currentContext
= NULL
;
172 SYMBOL
* mainContext
= NULL
;
173 SYMBOL
* demonRequest
;
176 SYMBOL
* symHandler
[32];
177 int currentSignal
= 0;
181 char lc_decimal_point
;
183 /* error and exception handling */
185 #define EXCEPTION_THROW -1
190 /* buffer for read-line */
191 STREAM readLineStream
;
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
;
209 extern PRIMITIVE primitive
[];
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
);
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
)
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:");
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 */
288 traceFlag
|= TRACE_TIMER
;
290 executeSymbol(timerEvent
, NULL
);
296 void setupAllSignals(void)
299 setupSignalHandler(SIGINT
,ctrlC_handler
);
301 setupSignalHandler(SIGINT
, signal_handler
);
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
);
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
);
323 void signal_handler(int sig
)
329 if(sig
> 32 || sig
< 1) return;
337 setupSignalHandler(sig
, sigalrm_handler
);
340 setupSignalHandler(SIGPIPE
, sigpipe_handler
);
343 setupSignalHandler(SIGCHLD
, sigchld_handler
);
347 setupSignalHandler(sig
, signal_handler
);
350 if(symHandler
[sig
- 1] != nilSymbol
)
355 traceFlag
|= TRACE_SIGNAL
;
360 executeSymbol(symHandler
[sig
-1], stuffInteger(sig
));
368 if(commandLineFlag
!= TRUE
) return;
370 printErrorMessage(ERR_SIGINT
, NULL
, 0);
373 traceFlag
|= TRACE_SIGINT
;
375 printf("\n(c)ontinue, (d)ebug, e(x)it, (r)eset:");
378 if(chr
== 'x') exit(1);
381 traceFlag
&= ~TRACE_SIGINT
;
384 if(chr
== 'r') traceFlag
|= TRACE_SIGINT
;
391 /* check if not sitting idle */
393 traceFlag
|= TRACE_TIMER
;
395 executeSymbol(timerEvent
, NULL
);
398 waitpid(-1, (int *)0, WNOHANG
);
407 void loadStartup(char * name
)
412 char EXEName
[MAX_LINE
];
413 char initFile
[MAX_LINE
];
415 GetModuleFileName(NULL
, EXEName
, MAX_LINE
);
420 if(strncmp(linkOffset
, "@@@@", 4) == 0)
424 ptr
= name
+ strlen(name
) - 1;
427 if(*ptr
== '/' || *ptr
== '\\') break;
431 strncpy(initFile
, name
, MAX_LINE
- 9);
432 strcat(initFile
, "/");
433 strcat(initFile
, INIT_FILE
);
434 loadFile(initFile
, 0, 0, mainContext
);
436 loadFile(INIT_FILE
, 0, 0, mainContext
);
439 loadFile(INIT_FILE
, 0, 0, mainContext
);
442 else /* load encrypted part at offset */
443 loadFile(name
, *(UINT
*)linkOffset
, 1, mainContext
);
448 struct lconv
*localeconv(void);
449 char *setlocale(int, const char *);
452 void initLocale(void)
458 locale
= setlocale(LC_ALL
, "C");
460 locale
= setlocale(LC_ALL
, "");
464 stringOutputRaw
= (strcmp(locale
, "C") == 0);
467 lc_decimal_point
= *lc
->decimal_point
;
470 /* set NEWLISPDIR only if not set already */
471 void initNewlispDir(void)
477 if(getenv("NEWLISPDIR") == NULL
)
479 newlispDir
= alloca(MAX_PATH
);
480 varValue
= getenv("PROGRAMFILES");
483 strncpy(newlispDir
, varValue
, MAX_PATH
);
484 strncat(newlispDir
, "/newlisp", 8);
485 setenv("NEWLISPDIR", newlispDir
, TRUE
);
487 else setenv("NEWLISPDIR", "newlisp", TRUE
);
490 if(getenv("NEWLISPDIR") == NULL
)
491 setenv("NEWLISPDIR", "/usr/share/newlisp", TRUE
);
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
]);
516 CELL
* getMainArgs(char * mainArgs
[])
528 argList
= getCell(CELL_EXPRESSION
);
532 while(mainArgs
[idx
] != NULL
)
534 if(lastEntry
== NULL
)
536 lastEntry
= stuffString(mainArgs
[idx
]);
537 argList
->contents
= (UINT
)lastEntry
;
541 lastEntry
->next
= stuffString(mainArgs
[idx
]);
542 lastEntry
= lastEntry
->next
;
552 int main(int argc
, char * argv
[])
554 char command
[MAX_LINE
];
563 WSAStartup(MAKEWORD(1,1), &WSAData
);
570 memset(&cmdStream
, 0, sizeof(STREAM
));
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
);
586 goto AFTER_ERROR_ENTRY
;
591 loadStartup(argv
[0]);
594 realpath(".", startupDir
);
596 for(idx
= 1; idx
< argc
; idx
++)
599 if(strncmp(argv
[idx
], "-c", 2) == 0)
602 if(strncmp(argv
[idx
], "-C", 2) == 0)
603 forcePromptMode
= TRUE
;
605 if(strncmp(argv
[idx
], "-http", 5) == 0)
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;
620 if(strncmp(argv
[idx
], "-p", 2) == 0 || strncmp(argv
[idx
], "-d", 2) == 0 )
622 if(strncmp(argv
[idx
], "-d", 2) == 0)
625 IOdomain
= getArg(argv
, argc
, &idx
);
626 IOport
= atoi(IOdomain
);
632 if(strncmp(argv
[idx
], "-e", 2) == 0)
634 executeCommandLine(getArg(argv
, argc
, &idx
), OUT_CONSOLE
, &cmdStream
);
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
);
645 if(strncmp(argv
[idx
], "-m", 2) == 0)
648 MAX_CELL_COUNT
= abs(0x0010000 * atoi(getArg(argv
, argc
, &idx
)));
650 MAX_CELL_COUNT
= abs(0x0008000 * atoi(getArg(argv
, argc
, &idx
)));
655 if(strncmp(argv
[idx
], "-w", 2) == 0)
657 realpath(getArg(argv
, argc
, &idx
), startupDir
);
662 if(strcmp(argv
[idx
], "-h") == 0)
669 loadFile(argv
[idx
], 0, 0, mainContext
);
674 if(isatty(fileno(IOchannel
)))
678 varPrintf(OUT_CONSOLE
, banner
, ostype
, IPV
, banner2
);
683 /* its a faked FILE struct, see win32_fdopen() in nl-sock.c */
684 if(!isSocketStream(IOchannel
))
688 varPrintf(OUT_CONSOLE
, banner
, ostype
, IPV
, banner2
);
692 errorReg
= setjmp(errorJump
);
698 if(errorReg
&& !isNil((CELL
*)errorEvent
->contents
) )
699 executeSymbol(errorEvent
, NULL
);
703 if(commandLineFlag
== TRUE
)
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
);
717 if(IOchannel
!= stdin
|| forcePromptMode
)
718 varPrintf(OUT_CONSOLE
, prompt());
721 if(isTTY
|| IOchannel
!= stdin
|| forcePromptMode
)
722 varPrintf(OUT_CONSOLE
, prompt());
724 if(IOchannel
== NULL
|| fgets(command
, MAX_LINE
- 1, IOchannel
) == NULL
)
726 if(!demonMode
) exit(1);
727 if(IOchannel
!= NULL
) fclose(IOchannel
);
732 executeCommandLine(command
, OUT_CONSOLE
, &cmdStream
);
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",
750 " -m <max-mem-megabyte>",
751 " -l log connections only",
755 " -e <quoted lisp expression>",
756 " -c no prompts, HTTP",
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
);
773 if(!isSocketStream(IOchannel
))
777 if(!reconnect
&& !noPromptMode
)
778 varPrintf(OUT_CONSOLE
, banner
, ostype
, IPV
, ".");
785 static char string
[32];
787 if(evalSilent
|| noPromptMode
)
793 if(currentContext
!= mainContext
)
794 context
= currentContext
->name
;
797 if(traceFlag
& TRACE_SIGINT
)
799 traceFlag
&= ~TRACE_SIGINT
;
800 longjmp(errorJump
, errorReg
);
804 snprintf(string
, 31, "%s %d> ", context
, recursionCount
);
806 snprintf(string
, 31, "%s> ", context
);
814 recoverEnvironment(0);
818 if(printDevice
) close((int)printDevice
);
819 printDevice
= recursionCount
= resultStackIdx
= envStackIdx
= lambdaStackIdx
= 0;
820 symbolProtectionLevel
= traceFlag
= prettyPrintFlags
= 0;
822 pushResultFlag
= commandLineFlag
= TRUE
;
823 currentContext
= mainContext
;
827 void recoverEnvironment(int index
)
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
)
852 if(strlen(command
) == 0 || *command
== '\n') return;
856 if(logTraffic
== LOG_MORE
)
857 writeLog(command
, 0);
858 if(strncmp(command
, "GET /", 5) == 0)
860 executeHTTPrequest(command
+ 5, HTTP_GET_URL
);
863 else if(strncmp(command
, "HEAD /", 6) == 0)
865 executeHTTPrequest(command
+ 5, HTTP_GET_HEAD
);
868 else if(strncmp(command
, "PUT /", 5) == 0)
870 executeHTTPrequest(command
+ 5, HTTP_PUT_URL
);
873 else if(strncmp(command
, "POST /", 6) == 0)
875 executeHTTPrequest(command
+ 6, HTTP_POST_URL
);
878 else if(strncmp(command
, "DELETE /", 8) == 0)
880 executeHTTPrequest(command
+ 8, HTTP_DELETE_URL
);
887 if(*command
== '!' && *(command
+ 1) != ' ' && strlen(command
) > 2)
889 system((command
+ 1));
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)
902 writeLog(cmdStream
->buffer
, 0);
905 /* make stream for evaluation */
906 makeStreamFromString(&stream
, cmdStream
->buffer
);
907 evaluateStream(&stream
, OUT_CONSOLE
, 0);
908 closeStrStream(cmdStream
);
911 writeStreamStr(cmdStream
, buff
, 0);
913 closeStrStream(cmdStream
);
914 if(!demonMode
) exit(1);
915 if(IOchannel
!= NULL
) fclose(IOchannel
);
920 if(logTraffic
) writeLog(command
, TRUE
);
921 prettyPrintLength
= 0;
923 makeStreamFromString(&stream
, command
);
924 evaluateStream(&stream
, outDevice
, 0);
930 CELL
* evaluateStream(STREAM
* stream
, UINT outDevice
, int flag
)
933 CELL
* eval
= nilCell
;
938 resultIdxSave
= resultStackIdx
;
941 pushResult(program
= getCell(CELL_QUOTE
));
942 result
= compileExpression(stream
, program
);
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
);
957 if(flag
) eval
= copyCell(eval
);
959 cleanupResults(resultIdxSave
);
962 if(flag
) return(eval
);
967 long executeSymbol(SYMBOL
* symbol
, CELL
* params
)
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
);
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);
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
)
1085 CELL
* pCell
= NULL
;
1086 SYMBOL
* newContext
= NULL
;
1088 int resultIdxSave
= 0;
1090 if(cell
->type
& EVAL_SELF_TYPE_MASK
) return cell
;
1095 return((CELL
*)((SYMBOL
*)cell
->contents
)->contents
);
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
;
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
);
1134 if(pCell
->type
== CELL_LAMBDA
)
1137 result
= evaluateLambda((CELL
*)pCell
->contents
, args
->next
, newContext
);
1142 if(pCell
->type
== CELL_MACRO
)
1144 result
= evaluateMacro((CELL
*)pCell
->contents
, args
->next
, newContext
);
1148 if(pCell
->type
== CELL_IMPORT_CDECL
1150 || pCell
->type
== CELL_IMPORT_DLL
1154 result
= executeLibfunction(pCell
, args
->next
);
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
);
1176 else if(pCell
->type
== CELL_LAMBDA
)
1179 result
= evaluateLambda((CELL
*)pCell
->contents
, args
->next
, newContext
);
1184 else if(pCell
->type
== CELL_MACRO
)
1186 result
= evaluateMacro((CELL
*)pCell
->contents
, args
->next
, newContext
);
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
);
1214 result
= errorProcExt(ERR_INVALID_FUNCTION
, cell
);
1217 case CELL_DYN_SYMBOL
:
1218 return((CELL
*)(getDynamicSymbol(cell
))->contents
);
1224 while(resultStackIdx
> resultIdxSave
)
1225 deleteList(popResult());
1229 if(resultStackIdx
> MAX_RESULT_STACK
)
1230 fatalError(ERR_OUT_OF_CALL_STACK
, pCell
, 0);
1233 else pushResultFlag
= TRUE
;
1235 if(traceFlag
) traceExit(result
, cell
, pCell
, args
);
1241 CELL
* evaluateExpressionSafe(CELL
* cell
, int * errNo
)
1243 jmp_buf errorJumpSave
;
1246 memcpy(errorJumpSave
, errorJump
, sizeof(jmp_buf));
1247 if((*errNo
= setjmp(errorJump
)) != 0)
1249 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
1253 result
= evaluateExpression(cell
);
1254 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
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
)
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 */
1275 (SYMBOL
*)contextCell
->contents
, /* contextPtr */
1280 CELL
* evalCheckProtected(CELL
* cell
, CELL
* * flagPtr
)
1285 if(isSymbol(cell
->type
))
1287 if(cell
->type
== CELL_SYMBOL
)
1288 sPtr
= (SYMBOL
*)cell
->contents
;
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)
1303 return(errorProcExt(ERR_SYMBOL_PROTECTED
, cell
));
1304 else *flagPtr
= cell
;
1307 symbolProtectionLevel
= 0;
1312 /* -------------------- evaluate lambda function ----------------------- */
1314 CELL
* evaluateLambda(CELL
* localLst
, CELL
* arg
, SYMBOL
* newContext
)
1317 CELL
* result
= nilCell
;
1320 SYMBOL
* contextSave
;
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 */
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
);
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
);
1343 cell
->next
= copyCell(evaluateExpression(arg
));
1349 /* change to new context */
1350 contextSave
= currentContext
;
1351 currentContext
= newContext
;
1353 /* save environment and get parameters */
1354 local
= (CELL
*)localLst
->contents
;
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
;
1387 result
= result
->next
;
1390 cell
->next
= nilCell
;
1392 local
= local
->next
;
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
;
1406 /* evaluate body expressions */
1407 cell
= localLst
->next
;
1409 while(cell
!= nilCell
)
1411 result
= evaluateExpression(cell
);
1414 result
= copyCell(result
);
1416 /* recover environment of local symbols */
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
;
1431 CELL
* evaluateMacro(CELL
* localLst
, CELL
* arg
, SYMBOL
* newContext
)
1437 SYMBOL
* contextSave
;
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 */
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
;
1466 arg
= evaluateExpression(cell
->next
);
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
;
1488 pushEnvironment(argsSymbol
->contents
);
1489 pushEnvironment((UINT
)argsSymbol
);
1490 argsSymbol
->contents
= (UINT
)getCell(CELL_EXPRESSION
);
1492 ((CELL
*)argsSymbol
->contents
)->contents
= (UINT
)copyList(arg
);
1495 arg
= localLst
->next
;
1498 while(arg
!= nilCell
)
1500 result
= evaluateExpression(arg
);
1503 result
= copyCell(result
);
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
;
1519 /* -------------- list/cell creation/deletion routines ---------------- */
1522 CELL
* stuffInteger(UINT contents
)
1526 cell
= getCell(CELL_LONG
);
1527 cell
->contents
= (UINT
) contents
;
1532 CELL
* stuffInteger64(INT64 contents
)
1536 cell
= getCell(CELL_INT64
);
1537 *(INT64
*)&cell
->aux
= contents
;
1543 CELL
* stuffIntegerList(int argc
, ...)
1551 list
= getCell(CELL_EXPRESSION
);
1552 list
->contents
= (UINT
)stuffInteger(va_arg(ap
, UINT
));
1553 cell
= (CELL
*)list
->contents
;
1557 cell
->next
= stuffInteger(va_arg(ap
, UINT
));
1566 CELL
* stuffString(char * string
)
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
);
1578 CELL
* stuffStringN(char * string
, int len
)
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;
1590 CELL
* stuffFloat(double * floatPtr
)
1594 cell
= getCell(CELL_FLOAT
);
1596 *(double *)&cell
->aux
= *floatPtr
;
1598 *(double *)&cell
->contents
= *floatPtr
;
1604 CELL
* stuffSymbol(SYMBOL
* sPtr
)
1608 cell
= getCell(CELL_SYMBOL
);
1609 cell
->contents
= (UINT
)sPtr
;
1613 ssize_t
convertNegativeOffset(ssize_t offset
, CELL
* list
)
1617 while(list
!= nilCell
)
1622 offset
= len
+ offset
;
1624 errorProc(ERR_LIST_INDEX_OUTOF_BOUNDS
);
1628 /* ------------------------ creating and freeing cells ------------------- */
1630 CELL
* getCell(int type
)
1634 if(firstFreeCell
== NULL
) allocBlock();
1635 cell
= firstFreeCell
;
1636 firstFreeCell
= cell
->next
;
1640 cell
->next
= nilCell
;
1641 cell
->aux
= (UINT
)nilCell
;
1642 cell
->contents
= (UINT
)nilCell
;
1648 CELL
* copyCell(CELL
* cell
)
1653 if(firstFreeCell
== NULL
) allocBlock();
1654 newCell
= firstFreeCell
;
1655 firstFreeCell
= newCell
->next
;
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
);
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);
1689 /* this routine must be called with the list head
1690 if copying with envelope call copyCell() instead */
1691 CELL
* copyList(CELL
* cell
)
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
;
1710 /* for deleting lists _and_ cells */
1711 void deleteList(CELL
* cell
)
1715 while(cell
!= nilCell
)
1717 if(isEnvelope(cell
->type
))
1719 if(cell
->type
== CELL_ARRAY
)
1722 deleteList((CELL
*)cell
->contents
);
1725 else if(cell
->type
== CELL_STRING
|| cell
->type
== CELL_DYN_SYMBOL
)
1726 freeMemory( (void *)cell
->contents
);
1731 if(cell
== trueCell
)
1737 cell
->type
= CELL_FREE
;
1738 cell
->next
= firstFreeCell
;
1739 firstFreeCell
= cell
;
1746 /* --------------- cell / memory allocation and deallocation ------------- */
1748 CELL
* cellMemory
= NULL
;
1749 CELL
* cellBlock
= NULL
;
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
;
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
)
1784 if( (ptr
= (void *)malloc(nbytes
)) == NULL
)
1785 fatalError(ERR_NOT_ENOUGH_MEMORY
, NULL
, 0);
1790 void * callocMemory(size_t nbytes
)
1794 if( (ptr
= (void *)calloc(nbytes
, 1)) == NULL
)
1795 fatalError(ERR_NOT_ENOUGH_MEMORY
, NULL
, 0);
1800 void * reallocMemory(void * prevPtr
, UINT size
)
1804 if( (ptr
= realloc(prevPtr
, size
)) == NULL
)
1805 fatalError(ERR_NOT_ENOUGH_MEMORY
, NULL
, 0);
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()
1821 nilCell
->type
|= (UINT
)0x00008000;
1822 markReferences((SYMBOL
*)((CELL
*)mainContext
->contents
)->aux
);
1828 void markReferences(SYMBOL
* sPtr
)
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
)
1857 markList((CELL
*)cell
->contents
);
1867 CELL
* lastBlockPtr
;
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;
1882 blockPtr
->type
= CELL_FREE
;
1890 if(freed
== MAX_BLOCK
)
1892 memPtr
= blockPtr
->next
;
1893 freeMemory(lastBlockPtr
->next
);
1894 lastBlockPtr
->next
= memPtr
;
1899 lastBlockPtr
= blockPtr
;
1900 blockPtr
= blockPtr
->next
;
1906 void relinkCells(void)
1909 CELL
* lastFreeCell
= NULL
;
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
;
1925 lastFreeCell
->next
= blockPtr
;
1926 lastFreeCell
= 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 ------------------------------ */
1947 void prettyPrint(UINT device
);
1949 void varPrintf(UINT device
, char * format
, ...)
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
);
1965 if(printDevice
!= 0)
1967 write(printDevice
, buffer
, strlen(buffer
));
1972 writeStreamStr(&libStrStream
, buffer
, 0);
1975 if(IOchannel
== stdin
)
1977 printf("%s", buffer
);
1978 if(!isTTY
) fflush(NULL
);
1982 if(IOchannel
!= NULL
)
1984 fprintf(IOchannel
, "%s", buffer
);
1986 fprintf(IOchannel
, buffer
);
1992 writeLog(buffer
, 0);
1995 writeStreamStr((STREAM
*)device
, buffer
, 0);
2005 int printCell(CELL
* cell
, UINT printFlag
, UINT device
)
2013 varPrintf(device
, "nil"); break;
2016 varPrintf(device
, "true"); break;
2019 varPrintf(device
,"%ld", cell
->contents
); break;
2024 varPrintf(device
,"%ld", *(INT64
*)&cell
->aux
); break;
2027 varPrintf(device
,"%I64d", *(INT64
*)&cell
->aux
); break;
2029 varPrintf(device
,"%lld", *(INT64
*)&cell
->aux
); break;
2035 varPrintf(device
,"%1.10g",*(double *)&cell
->aux
);
2037 varPrintf(device
,"%1.10g",*(double *)&cell
->contents
);
2043 printString((char *)cell
->contents
, device
, cell
->aux
- 1);
2045 varPrintf(device
,"%s",cell
->contents
);
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
);
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
);
2070 varPrintf(device
,"%s",sPtr
->name
);
2073 case CELL_PRIMITIVE
:
2074 case CELL_IMPORT_CDECL
:
2076 case CELL_IMPORT_DLL
:
2078 varPrintf(device
,"%s <%lX>", (char *)cell
->aux
, cell
->contents
);
2082 varPrintf(device
, "'");
2083 prettyPrintFlags
|= PRETTYPRINT_DOUBLE
;
2084 printCell((CELL
*)cell
->contents
, printFlag
, device
);
2087 case CELL_EXPRESSION
:
2090 printExpression(cell
, device
);
2093 case CELL_DYN_SYMBOL
:
2094 varPrintf(device
, "%s:%s", ((SYMBOL
*)cell
->aux
)->name
, (char*)cell
->contents
);
2097 printArray(cell
, device
);
2101 varPrintf(device
,"?");
2104 prettyPrintFlags
&= ~PRETTYPRINT_DOUBLE
;
2109 void printString(char * str
, UINT device
, int size
)
2113 if(size
>= MAX_STRING
)
2115 varPrintf(device
, "[text]");
2116 while(size
--) varPrintf(device
, "%c", *str
++);
2117 varPrintf(device
, "[/text]");
2121 varPrintf(device
,"\"");
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;
2132 if((unsigned char)chr
< 32 || (stringOutputRaw
&& (unsigned char)chr
> 126))
2133 varPrintf(device
,"\\%03u", (unsigned char)chr
);
2135 varPrintf(device
,"%c",chr
); break;
2138 varPrintf(device
,"\"");
2142 int printExpression(CELL
* cell
, UINT device
)
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 ");
2159 else if(cell
->type
== CELL_MACRO
)
2161 varPrintf(device
, "(lambda-macro ");
2166 if(isSymbol(item
->type
))
2168 if(item
->type
== CELL_SYMBOL
)
2169 pFlags
= ((SYMBOL
*)item
->contents
)->flags
;
2173 if((pFlags
& PRINT_TYPE_MASK
) != 0)
2175 prettyPrint(device
);
2176 varPrintf(device
, "(");
2178 for(i
= 0; i
< (pFlags
& PRINT_TYPE_MASK
); i
++)
2181 {prettyPrintFlags
|= PRETTYPRINT_DOUBLE
; break;}
2182 printCell(item
, TRUE
, device
);
2184 if(item
!= nilCell
) varPrintf(device
," ");
2185 else prettyPrintFlags
|= PRETTYPRINT_DOUBLE
;
2187 prettyPrint(device
);
2191 varPrintf(device
, "(");
2197 varPrintf(device
, "(");
2203 while(item
!= nilCell
)
2205 if(prettyPrintLength
> prettyPrintMaxLength
) prettyPrint(device
);
2206 if(printCell(item
, TRUE
, device
) == 0) return(0);
2208 if(item
!= nilCell
) varPrintf(device
," ");
2211 varPrintf(device
,")");
2218 void prettyPrint(UINT device
)
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
)
2241 prettyPrintCurrent
= prettyPrintPars
= 1;
2242 prettyPrintLength
= 0;
2243 prettyPrintFlags
&= !PRETTYPRINT_DOUBLE
;
2245 if(sPtr
->flags
& SYMBOL_PROTECTED
)
2246 setStr
= "(constant ";
2250 switch(symbolType(sPtr
))
2252 case CELL_PRIMITIVE
:
2253 case CELL_IMPORT_CDECL
:
2255 case CELL_IMPORT_DLL
:
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
, ")");
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
);
2291 if(cell
!= nilCell
) varPrintf(device
, " ");
2293 varPrintf(device
, "))");
2294 if(symbolType(sPtr
) == CELL_ARRAY
)
2297 varPrintf(device
,"))");
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
);
2318 varPrintf(device
, setStr
);
2319 printSymbolNameExt(device
, sPtr
);
2320 printCell((CELL
*)sPtr
->contents
, TRUE
, device
);
2321 varPrintf(device
, ")");
2325 varPrintf(device
, "%s%s", LINE_FEED
, LINE_FEED
);
2327 prettyPrintLength
= prettyPrintPars
= 0;
2331 void printLambda(SYMBOL
* sPtr
, UINT device
)
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
, ")");
2351 if(symbolType(sPtr
) == CELL_LAMBDA
)
2352 varPrintf(device
, "(define (");
2354 varPrintf(device
, "(define-macro (");
2355 prettyPrintPars
+= 2;
2357 printSymbolName(device
, sPtr
);
2358 varPrintf(device
, " ");
2360 while(cell
!= nilCell
)
2362 printCell(cell
, TRUE
, device
);
2364 if(cell
!= nilCell
) varPrintf(device
, " ");
2366 varPrintf(device
, ")");
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
, ")");
2383 void printSymbolName(UINT device
, SYMBOL
* sPtr
)
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
);
2397 varPrintf(device
,"%s", sPtr
->name
);
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
, ") ");
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
);
2425 varPrintf(device
, "'");
2426 printSymbolName(device
, sPtr
);
2428 varPrintf(device
, " ");
2433 CELL
* p_prettyPrint(CELL
* params
)
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
);
2457 /* -------------------------- error handling --------------------------- */
2459 char * errorMessage
[] =
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
)
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
);
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
)
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
);
2568 longjmp(errorJump
, errorReg
);
2572 void printErrorMessage(UINT errorNumber
, CELL
* expr
, int deleteFlag
)
2575 UINT lambdaStackIdxSave
;
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);
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
);
2637 varPrintf(OUT_CONSOLE
, "\n%.1024s\n", errorStream
.buffer
);
2642 /* --------------------------- load source file ------------------------- */
2645 CELL
* loadFile(char * fileName
, UINT offset
, int encryptFlag
, SYMBOL
* context
)
2650 jmp_buf errorJumpSave
;
2651 SYMBOL
* contextSave
;
2657 contextSave
= currentContext
;
2658 currentContext
= context
;
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);
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)
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
);
2694 for(i
= 0; i
<recursionCount
; i
++) printf(" ");
2695 printf("load: %s\n", fileName
);
2698 result
= evaluateStream(&stream
, 0, TRUE
);
2699 currentContext
= contextSave
;
2702 for(i
= 0; i
<recursionCount
; i
++) printf(" ");
2703 printf("finish load: %s\n", fileName
);
2706 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
2707 closeStrStream(&stream
);
2711 /* -------------------------- parse / compile ----------------------------- */
2714 int compileExpression(STREAM
* stream
, CELL
* cell
)
2716 char token
[MAX_STRING
+ 4];
2720 SYMBOL
* contextPtr
;
2721 int listFlag
, tklen
;
2724 SYMBOL
* saveContext
;
2725 int defaultSymbolLevel
= 0;
2727 saveContext
= currentContext
;
2730 listFlag
= TRUE
; /* assumes we just entered from an envelope cell ! */
2733 lastPtr
= stream
->ptr
;
2734 switch(getToken(stream
, token
, &tklen
))
2737 errorProcExt2(ERR_EXPRESSION
, stuffStringN(lastPtr
,
2738 (strlen(lastPtr
) < 60) ? strlen(lastPtr
) : 60));
2742 if(parStackCounter
!= 0) errorMissingPar(stream
);
2746 newCell
= stuffInteger((UINT
)token
[0]);
2751 newCell
= stuffInteger64((INT64
)strtoull(token
,NULL
,0));
2753 newCell
= stuffInteger(strtoull(token
,NULL
,0));
2759 newCell
= stuffInteger64(strtoll(token
,NULL
,0));
2761 newCell
= stuffInteger(strtoll(token
,NULL
,0));
2766 floatNumber
= (double)atof(token
);
2767 newCell
= stuffFloat(&floatNumber
);
2771 newCell
= stuffStringN(token
, tklen
);
2775 if(strcmp(token
, "lambda") == 0 || strcmp(token
, "fn") == 0)
2777 if(cell
->type
!= CELL_EXPRESSION
)
2779 errorProcExt2(ERR_INVALID_LAMBDA
, stuffString(lastPtr
));
2782 cell
->type
= CELL_LAMBDA
;
2783 cell
->aux
= (UINT
)nilCell
;
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
));
2793 cell
->type
= CELL_MACRO
;
2794 cell
->aux
= (UINT
)nilCell
;
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
;
2811 newCell
= getCell(CELL_SYMBOL
);
2813 newCell
->contents
= (UINT
)translateCreateSymbol(
2814 token
, CELL_NIL
, mainContext
, TRUE
);
2816 newCell
->contents
= (UINT
)translateCreateSymbol(
2817 token
, CELL_NIL
, currentContext
, 0);
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
;
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);
2852 /* context exists make a symbol for it */
2853 newCell
= getCell(CELL_SYMBOL
);
2854 newCell
->contents
= (UINT
)translateCreateSymbol(
2855 token
, CELL_NIL
, contextPtr
, TRUE
);
2859 newCell
= getCell(CELL_QUOTE
);
2860 linkCell(cell
, newCell
, listFlag
);
2861 compileExpression(stream
, newCell
);
2866 newCell
= getCell(CELL_EXPRESSION
);
2867 linkCell(cell
, newCell
, listFlag
);
2868 compileExpression(stream
, newCell
);
2872 if(parStackCounter
== 0) errorMissingPar(stream
);
2874 cell
->next
= nilCell
;
2878 errorProcExt2(ERR_EXPRESSION
, stuffString(lastPtr
));
2883 linkCell(cell
, newCell
, listFlag
);
2885 if(cell
->type
== CELL_QUOTE
&& listFlag
== TRUE
)
2891 if(parStackCounter
!= 0)
2893 if(*(stream
->ptr
) != 0) goto GETNEXT
;
2894 else errorMissingPar(stream
);
2901 void linkCell(CELL
* left
, CELL
* right
, int linkFlag
)
2905 else left
->contents
= (UINT
)right
;
2908 int getToken(STREAM
* stream
, char * token
, int * ptr_len
)
2918 tknLen
= floatFlag
= 0;
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
;
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
;
2946 while((unsigned char)*stream
->ptr
<= ' ' && (unsigned char)*stream
->ptr
!= 0)
2949 if(*stream
->ptr
== 0) return(TKN_EMPTY
);
2951 /* check for comments */
2952 if(*stream
->ptr
== ';' || *stream
->ptr
== '#')
2957 if(*stream
->ptr
== 0) return(TKN_EMPTY
);
2958 if(*stream
->ptr
== '\n' || *stream
->ptr
== '\r')
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
++;
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
++;
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
++;
3006 else if(toupper(*stream
->ptr
) != 'E')
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
++;
3026 if(floatFlag
== TRUE
) return(TKN_FLOAT
);
3027 else return(TKN_DECIMAL
);
3036 *(tkn
++) = *(stream
->ptr
++), tknLen
++;
3041 while(*stream
->ptr
!= '"' && *stream
->ptr
!= 0
3042 && tknLen
< MAX_STRING
)
3044 if(*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);
3053 *(tkn
++) = atoi(buff
);
3059 switch(*stream
->ptr
)
3062 goto SRING_TO_LONG_ERROR
;
3065 *(tkn
++) = '\n'; break;
3067 *(tkn
++) = '\\'; break;
3069 *(tkn
++) = '\r'; break;
3071 *(tkn
++) = '\t'; break;
3073 *(tkn
++) = '"'; break;
3075 if(isxdigit((unsigned char)*(stream
->ptr
+ 1)) &&
3076 isxdigit((unsigned char)*(stream
->ptr
+ 2)))
3079 buff
[1] = (unsigned char)*(stream
->ptr
+ 1);
3080 buff
[2] = (unsigned char)*(stream
->ptr
+ 2);
3082 *(tkn
++) = strtol(buff
, NULL
, 16);
3087 *(tkn
++) = *stream
->ptr
;
3092 else *(tkn
++) = *(stream
->ptr
++), tknLen
++;
3094 if(*stream
->ptr
== '\"')
3103 goto SRING_TO_LONG_ERROR
;
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
== '}')
3131 goto SRING_TO_LONG_ERROR
;
3142 while( tknLen
< MAX_SYMBOL
&& *stream
->ptr
!= 0 && *stream
->ptr
!= ']')
3143 *(tkn
++) = *(stream
->ptr
++), tknLen
++;
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
++;
3160 if(*stream
->ptr
== ':')
3163 return(TKN_CONTEXT
);
3171 SRING_TO_LONG_ERROR
:
3173 errorProcExt2(ERR_STRING_TOO_LONG
,
3174 stuffStringN(token
, strlen(token
) < 40 ? strlen(token
) : 40));
3178 /* -------------------------- utilities ------------------------------------ */
3180 size_t listlen(CELL
* listHead
)
3184 while(listHead
!= nilCell
)
3187 listHead
= listHead
->next
;
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
)
3207 cell
= evaluateExpression(params
);
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
)
3221 if(isnan(*(double *)&cell
->aux
) || !_finite(*(double *)&cell
->aux
)) *number
= 0;
3223 if(isnan(*(double *)&cell
->aux
)) *number
= 0;
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
;
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
;
3243 return(errorProcArgs(ERR_NUMBER_EXPECTED
, params
));
3246 return(params
->next
);
3250 CELL
* getInteger64(CELL
* params
, INT64
* number
)
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
)
3263 if(isnan(*(double *)&cell
->aux
) || !_finite(*(double *)&cell
->aux
)) *number
= 0;
3265 if(isnan(*(double *)&cell
->aux
)) *number
= 0;
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
;
3274 return(errorProcArgs(ERR_NUMBER_EXPECTED
, params
));
3277 return(params
->next
);
3281 CELL
* getInteger64(CELL
* params
, INT64
* number
)
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
;
3299 return(errorProcArgs(ERR_NUMBER_EXPECTED
, params
));
3302 return(params
->next
);
3306 CELL
* getIntegerExt(CELL
* params
, UINT
* number
, int evalFlag
)
3311 cell
= evaluateExpression(params
);
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
)
3326 if(isnan(*(double *)&cell
->aux
) || !_finite(*(double *)&cell
->aux
)) *number
= 0;
3328 if(isnan(*(double *)&cell
->aux
)) *number
= 0;
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
;
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
;
3348 return(errorProcArgs(ERR_NUMBER_EXPECTED
, params
));
3351 return(params
->next
);
3355 CELL
* getFloat(CELL
* params
, double * floatNumber
)
3359 cell
= evaluateExpression(params
);
3362 if(cell
->type
== CELL_FLOAT
)
3363 *floatNumber
= *(double *)&cell
->aux
;
3364 else if(cell
->type
== CELL_INT64
)
3365 *floatNumber
= *(INT64
*)&cell
->aux
;
3367 if(cell
->type
== CELL_FLOAT
)
3368 *floatNumber
= *(double *)&cell
->contents
;
3370 else if(cell
->type
== CELL_LONG
)
3371 *floatNumber
= (long)cell
->contents
;
3375 return(errorProcArgs(ERR_NUMBER_EXPECTED
, params
));
3378 return(params
->next
);
3382 CELL
* getString(CELL
* params
, char * * stringPtr
)
3386 cell
= evaluateExpression(params
);
3388 if(cell
->type
!= CELL_STRING
)
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
)
3402 if(params
== nilCell
)
3403 return(errorProc(ERR_MISSING_ARGUMENT
));
3406 cell
= evaluateExpression(params
);
3409 if(cell
->type
!= CELL_STRING
)
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
)
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
)
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
);
3461 *symbol
= (SYMBOL
*)cell
->contents
;
3463 return(params
->next
);
3467 CELL
* getContext(CELL
* params
, SYMBOL
* * context
)
3471 cell
= evaluateExpression(params
);
3473 if(cell
->type
== CELL_CONTEXT
|| cell
->type
== CELL_SYMBOL
)
3474 *context
= (SYMBOL
*)cell
->contents
;
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
)
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
)
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
;
3519 sPtr
= getDynamicSymbol(list
);
3521 list
= (CELL
*)sPtr
->contents
;
3523 if(list
->type
== CELL_CONTEXT
)
3525 sPtr
= (translateCreateSymbol(
3526 ((SYMBOL
*)list
->contents
)->name
,
3528 (SYMBOL
*)list
->contents
,
3530 list
= (CELL
*)sPtr
->contents
;
3533 if(isProtected(sPtr
->flags
) && setFlag
)
3534 return(errorProcExt2(ERR_SYMBOL_PROTECTED
, stuffSymbol(sPtr
)));
3539 list
= evalCheckProtected(list
, NULL
);
3541 list
= evaluateExpression(list
);
3543 if(list
->type
== CELL_CONTEXT
)
3545 sPtr
= (translateCreateSymbol(
3546 ((SYMBOL
*)list
->contents
)->name
,
3548 (SYMBOL
*)list
->contents
,
3551 if(setFlag
&& isProtected(sPtr
->flags
))
3552 return(errorProcExt2(ERR_SYMBOL_PROTECTED
, stuffSymbol(sPtr
)));
3554 list
= (CELL
*)sPtr
->contents
;
3563 /* ------------------------------- core predicates ------------------------ */
3565 CELL
* p_setlocale(CELL
* params
)
3571 if(params
!= nilCell
)
3572 params
= getString(params
, &locale
);
3575 if(params
!= nilCell
)
3576 getInteger(params
, &category
);
3577 else category
= LC_ALL
;
3579 locale
= setlocale(category
, locale
);
3584 stringOutputRaw
= (strcmp(locale
, "C") == 0);
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
;
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 */
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
;
3638 SYMBOL
* symbol
= NULL
;
3639 SYMBOL
* contextSave
;
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
;
3664 if(value
== EXCEPTION_THROW
)
3666 if(symbol
== NULL
) return(throwResult
);
3667 deleteList((CELL
*)symbol
->contents
);
3668 symbol
->contents
= (UINT
)throwResult
;
3672 if(errorStream
.buffer
!= 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
);
3688 result
= copyCell(evaluateExpression(expr
));
3690 memcpy(errorJump
, errorJumpSave
, sizeof(jmp_buf));
3692 if(symbol
== NULL
) return(result
);
3694 deleteList((CELL
*)symbol
->contents
);
3695 symbol
->contents
= (UINT
)result
;
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
);
3712 CELL
* p_throwError(CELL
* params
)
3715 errorProcExt(ERR_USER_ERROR
, evaluateExpression(params
));
3720 CELL
* p_evalString(CELL
* params
)
3722 SYMBOL
* context
= currentContext
;
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
)
3739 CELL
* resultCell
= nilCell
;
3740 jmp_buf errorJumpSave
;
3741 int recursionCountSave
;
3742 int envStackIdxSave
;
3744 SYMBOL
* contextSave
= NULL
;
3746 makeStreamFromString(&stream
, evalString
);
3747 recursionCountSave
= recursionCount
;
3748 envStackIdxSave
= envStackIdx
;
3749 resultIdxSave
= resultStackIdx
;
3750 contextSave
= currentContext
;
3751 currentContext
= context
;
3756 memcpy(errorJumpSave
, errorJump
, sizeof(jmp_buf));
3758 if(setjmp(errorJump
) != 0)
3760 memcpy(errorJump
, errorJumpSave
, (sizeof(jmp_buf)));
3761 recoverEnvironment(envStackIdxSave
);
3763 recursionCount
= recursionCountSave
;
3764 currentContext
= contextSave
;
3765 return(evaluateExpression(proc
));
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
);
3784 memcpy(errorJump
, errorJumpSave
, (sizeof(jmp_buf)));
3788 currentContext
= contextSave
;
3792 CELL
* p_curry(CELL
* params
)
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
);
3805 cell
->contents
= (UINT
)copyCell(params
);
3806 cell
= (CELL
*)cell
->contents
;
3807 cell
->next
= copyCell(params
->next
);
3809 cell
->next
= stuffSymbol(xPtr
);
3815 CELL
* p_apply(CELL
* params
)
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
);
3837 if(count
< 2) count
= MAX_LONG
;
3839 resultIdxSave
= resultStackIdx
+ 2;
3841 if(args
->type
== CELL_EXPRESSION
)
3843 args
= (CELL
*)args
->contents
;
3846 while(args
!= nilCell
&& cnt
-- > 0)
3848 if(isSelfEval(args
->type
))
3850 cell
->next
= copyCell(args
);
3855 cell
->next
= getCell(CELL_QUOTE
);
3857 cell
->contents
= (UINT
)copyCell(args
);
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
);
3869 cell
->contents
= (UINT
)result
;
3871 cleanupResults(resultIdxSave
);
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
;
3896 if(expr
->type
== CELL_SYMBOL
)
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
;
3912 #ifndef SUPPORT_UTF8
3913 wchar
= *sPtr
->name
;
3915 utf8_wchar(sPtr
->name
, &wchar
);
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
;
3936 else if(isEnvelope(cell
->type
)) expand(cell
, symbol
);
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
);
3957 next
->next
= expand(copyCell(block
), symbol
);
3960 block
= block
->next
;
3967 CELL
* p_expand(CELL
* params
)
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();
4015 return(errorProcExt(ERR_LIST_OR_SYMBOL_EXPECTED
, params
));
4016 expr
= expand(copyCell(expr
), symbol
);
4020 return(copyCell(expr
));
4024 CELL
* defineOrMacro(CELL
* params
, UINT cellType
)
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
);
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
));
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
;
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
)
4096 if(params
->type
!= CELL_SYMBOL
)
4098 if(params
->type
== CELL_DYN_SYMBOL
)
4099 symbol
= getDynamicSymbol(params
);
4101 return(errorProcExt(ERR_SYMBOL_EXPECTED
, params
));
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
);
4116 CELL
* p_set(CELL
*params
)
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
;
4135 CELL
* p_constant(CELL
*params
)
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
);
4159 CELL
* setDefine(SYMBOL
* symbol
, CELL
* params
, int type
)
4163 if(isProtected(symbol
->flags
))
4165 if(type
== TYPE_CONSTANT
)
4167 if(symbol
== nilSymbol
|| symbol
== trueSymbol
)
4168 return(errorProcExt2(ERR_SYMBOL_EXPECTED
, stuffSymbol(symbol
)));
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
;
4184 CELL
* p_global(CELL
* params
)
4190 params
= getSymbol(params
, &sPtr
);
4191 if(sPtr
->context
!= mainContext
|| currentContext
!= mainContext
)
4192 return(errorProcExt2(ERR_NOT_IN_MAIN
, stuffSymbol(sPtr
)));
4194 sPtr
->flags
|= SYMBOL_GLOBAL
;
4195 } while (params
!= nilCell
);
4197 return(stuffSymbol(sPtr
));
4202 #define LET_EXPAND 2
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
)
4216 CELL
* result
= nilCell
;
4217 CELL
* args
= NULL
, * list
= NULL
;
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
;
4245 inits
= inits
->next
;
4250 while(inits
!= nilCell
)
4252 if(inits
->type
!= CELL_EXPRESSION
)
4254 if(inits
->type
!= CELL_SYMBOL
)
4255 return(errorProcExt(ERR_INVALID_LET
, inits
));
4257 inits
= ((CELL
*)cell
->next
)->next
;
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
)
4270 list
= args
= copyCell(evaluateExpression(cell
->next
));
4273 args
->next
= copyCell(evaluateExpression(cell
->next
));
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
;
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
;
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
;
4319 args
->next
= nilCell
; /* decouple */
4321 /* hook in LET_EXPAND mode here */
4322 if(type
== LET_EXPAND
)
4324 body
= blockExpand(body
, symbol
);
4332 /* evaluate body expressions */
4333 while(body
!= nilCell
)
4335 if(result
!= nilCell
) deleteList(result
);
4336 result
= copyCell(evaluateExpression(body
));
4340 /* restore environment */
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();
4353 CELL
* p_first(CELL
* params
)
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
4366 return(stuffString(str
));
4368 return(stuffStringN((char*)cell
->contents
, utf8_1st_len((char*)cell
->contents
)));
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
)
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)));
4394 return(stuffString((char *)(cell
->contents
+ utf8_1st_len((char *)cell
->contents
))));
4398 else if(isList(cell
->type
))
4400 tail
= getCell(CELL_EXPRESSION
);
4401 tail
->contents
= (UINT
)copyList(((CELL
*)cell
->contents
)->next
);
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
)
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
,
4423 (SYMBOL
*)list
->contents
,
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
,
4436 (SYMBOL
*)list
->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
));
4448 else if(isList(list
->type
))
4450 list
= (CELL
*)list
->contents
;
4452 if(n
< 0) n
= convertNegativeOffset(n
, list
);
4454 while(n
-- && list
!= nilCell
)
4457 rest
= getCell(CELL_EXPRESSION
);
4458 rest
->contents
= (UINT
)copyList(list
);
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
)
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
)
4509 head
->next
= copyList((CELL
*)tail
->contents
);
4510 cons
->type
= tail
->type
;
4513 head
->next
= copyCell(tail
);
4521 CELL
* p_list(CELL
* params
)
4529 list
= getCell(CELL_EXPRESSION
);
4532 resultIdxSave
= resultStackIdx
;
4533 while(params
!= nilCell
)
4535 cell
= evaluateExpression(params
);
4536 if(cell
->type
== CELL_ARRAY
)
4537 copy
= arrayList(cell
);
4539 copy
= copyCell(cell
);
4542 if(lastCopy
== NULL
)
4543 list
->contents
= (UINT
)copy
;
4544 else lastCopy
->next
= copy
;
4546 params
= params
->next
;
4548 cleanupResults(resultIdxSave
);
4556 CELL
* p_last(CELL
* params
)
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));
4574 while((len
= utf8_1st_len(str
)) != 0)
4579 return(stuffStringN(ptr
, utf8_1st_len(ptr
)));
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
)
4607 while(cell
!= nilCell
)
4609 result
= evaluateExpression(cell
);
4616 CELL
* p_if(CELL
* params
)
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
)
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
)
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
)
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
)
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
;
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
)
4729 resultIdxSave
= resultStackIdx
;
4736 cell
= evaluateExpression(params
);
4737 if(isNil(cell
) || isEmpty(cell
)) goto END_REPEAT
;
4738 cleanupResults(resultIdxSave
);
4739 result
= evaluateBlock(params
->next
);
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
);
4748 cell
= evaluateExpression(params
);
4749 if(!isNil(cell
) && !isEmpty(cell
)) goto END_REPEAT
;
4750 cleanupResults(resultIdxSave
);
4751 result
= evaluateBlock(params
->next
);
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
);
4764 return(copyCell(result
));
4767 #ifdef from_8_8_4_to_9_0_10
4768 CELL
* repeat(CELL
* params
, int type
)
4774 resultIdxSave
= resultStackIdx
;
4781 cell
= evaluateExpression(params
);
4782 if(isNil(cell
) || isEmpty(cell
)) goto END_REPEAT
;
4783 cleanupResults(resultIdxSave
);
4785 result
= copyCell(evaluateBlock(params
->next
));
4787 case REPEAT_DOWHILE
:
4789 result
= copyCell(evaluateBlock(params
->next
));
4790 cell
= evaluateExpression(params
);
4791 if(isNil(cell
) || isEmpty(cell
)) goto END_REPEAT
;
4792 cleanupResults(resultIdxSave
);
4795 cell
= evaluateExpression(params
);
4796 if(!isNil(cell
) && !isEmpty(cell
)) goto END_REPEAT
;
4797 cleanupResults(resultIdxSave
);
4799 result
= copyCell(evaluateBlock(params
->next
));
4801 case REPEAT_DOUNTIL
:
4803 result
= copyCell(evaluateBlock(params
->next
));
4804 cell
= evaluateExpression(params
);
4805 if(!isNil(cell
) && !isEmpty(cell
)) goto END_REPEAT
;
4806 cleanupResults(resultIdxSave
);
4821 CELL
* getPushSymbolParam(CELL
* params
, SYMBOL
* * sym
)
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
;
4844 CELL
* loop(CELL
* params
, int forFlag
)
4847 CELL
* cond
= nilCell
;
4850 double fromFlt
, toFlt
, interval
, step
, cntFlt
;
4852 INT64 fromInt64
, toInt64
;
4856 cell
= getPushSymbolParam(params
, &symbol
);
4858 /* integer loops for dotimes and (for (i from to) ...) */
4859 if((intFlag
= ((CELL
*)cell
->next
)->next
== nilCell
))
4863 cell
= getInteger64(cell
, &fromInt64
);
4864 getInteger64(cell
, &toInt64
);
4865 stepCnt
= (toInt64
> fromInt64
) ? toInt64
- fromInt64
: fromInt64
- toInt64
;
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
;
4889 for(i
= 0; i
<= stepCnt
; i
++)
4891 if(!forFlag
&& i
== stepCnt
) break;
4892 deleteList((CELL
*)symbol
->contents
);
4896 (UINT
)stuffInteger64((fromInt64
> toInt64
) ? fromInt64
- i
:
4901 interval
= fromFlt
+ i
* step
;
4902 symbol
->contents
= (UINT
)stuffFloat(&interval
);
4904 cleanupResults(resultIdxSave
);
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();
4923 CELL
* p_dotimes(CELL
* params
)
4925 return(loop(params
, 0));
4928 CELL
* p_for(CELL
* params
)
4930 return(loop(params
, 1));
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
)
4956 CELL
* list
= nilCell
;
4961 CELL
* cond
= nilCell
;
4966 cell
= getPushSymbolParam(params
, &symbol
);
4968 pushEnvironment(dolistIdxSymbol
->contents
);
4969 pushEnvironment(dolistIdxSymbol
);
4970 cellIdx
= stuffInteger(0);
4971 dolistIdxSymbol
->contents
= (UINT
)cellIdx
;
4976 list
= copyCell(evaluateExpression(cell
));
4977 if(!isList(list
->type
))
4978 return(errorProcExt(ERR_LIST_EXPECTED
, cell
));
4982 list
= copyCell((CELL
*)argsSymbol
->contents
);
4986 getString(cell
, &str
);
4987 resultIdxSave
= resultStackIdx
;
4991 cleanupResults(resultIdxSave
);
4992 deleteList((CELL
*)symbol
->contents
);
4994 str
= utf8_wchar(str
, &chr
);
4995 symbol
->contents
= (UINT
)stuffInteger(chr
);
4997 symbol
->contents
= (UINT
)stuffInteger((int)*str
++);
5001 cell
= evaluateExpression(cond
);
5002 if(!isNil(cell
)) break;
5004 cell
= evaluateBlock(params
->next
);
5005 cellIdx
->contents
+= 1;
5011 /* make sure worklist gets destroyed */
5013 list
= (CELL
*)list
->contents
;
5015 resultIdxSave
= resultStackIdx
;
5017 while(list
!= nilCell
)
5019 cleanupResults(resultIdxSave
);
5020 deleteList((CELL
*)symbol
->contents
);
5021 symbol
->contents
= (UINT
)copyCell(list
);
5024 cell
= evaluateExpression(cond
);
5025 if(!isNil(cell
)) break;
5027 cell
= evaluateBlock(params
->next
);
5028 cellIdx
->contents
+= 1;
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();
5045 CELL
* p_evalBlock(CELL
* params
)
5047 return(copyCell(evaluateBlock(params
)));
5051 CELL
* p_silent(CELL
* params
)
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
)
5094 eval
= evaluateExpression(params
);
5095 if(isNil(eval
) || isEmpty(eval
))
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
)
5121 while(params
!= nilCell
)
5123 result
= evaluateExpression(params
);
5124 if(printCell(result
, 0, OUT_DEVICE
) == 0)
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
)
5146 CELL
* result
= nilCell
;
5151 /* get last parameter */
5152 if((next
= params
) == nilCell
)
5153 errorProc(ERR_MISSING_ARGUMENT
);
5154 while(next
->next
!= nilCell
)
5160 next
= evaluateExpression(next
);
5161 if(next
->type
== CELL_STRING
)
5164 context
= mainContext
;
5169 errorProcExt(ERR_STRING_EXPECTED
, next
);
5170 if((context
= getCreateContext(next
, FALSE
)) == NULL
)
5171 errorProcExt(ERR_SYMBOL_OR_CONTEXT_EXPECTED
, next
);
5177 /* if last arg was a string, avoid double evaluation */
5178 if(count
== 0 && next
!= NULL
)
5179 getStringSize(next
, &fileName
, NULL
, FALSE
);
5181 params
= getString(params
, &fileName
);
5183 result
= loadFile(fileName
, 0, 0, context
);
5186 return(errorProcExt2(ERR_ACCESSING_FILE
, stuffString(fileName
)));
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
)
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
5236 && type
!= CELL_IMPORT_DLL
5239 if(*sPtr
->name
!= '$') printSymbol(sPtr
, device
);
5240 saveSymbols(sPtr
->right
, device
);
5245 CELL
* p_save(CELL
* params
)
5249 UINT printDeviceSave
;
5251 SYMBOL
* contextSave
;
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
);
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
;
5286 void serializeSymbols(CELL
* params
, UINT device
)
5290 if(params
->type
== CELL_NIL
)
5291 saveSymbols((SYMBOL
*)((CELL
*)currentContext
->contents
)->aux
, device
);
5293 while(params
!= nilCell
)
5295 params
= getSymbol(params
, &sPtr
);
5296 if(symbolType(sPtr
) == CELL_CONTEXT
)
5297 saveContext((SYMBOL
*)((CELL
*)sPtr
->contents
)->contents
, device
);
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
)
5318 if(firstFreeCell
== NULL
) allocBlock();
5319 newCell
= firstFreeCell
;
5320 firstFreeCell
= newCell
->next
;
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
)
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
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
);
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
);
5375 CELL
* copyContextList(CELL
* cell
)
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
;
5394 UINT
* copyContextArray(CELL
* array
)
5401 addr
= newAddr
= (CELL
* *)callocMemory(array
->aux
);
5403 size
= (array
->aux
- 1) / sizeof(UINT
);
5404 orgAddr
= (CELL
* *)array
->contents
;
5407 *(newAddr
++) = copyContextCell(*(orgAddr
++));
5409 return((UINT
*)addr
);
5413 void iterateSymbols(SYMBOL
* sPtr
)
5415 int type
, newFlag
= FALSE
;
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
);
5434 if((newPtr
= lookupSymbol(sPtr
->name
, newContext
)) == NULL
)
5436 newPtr
= translateCreateSymbol(sPtr
->name
, type
, newContext
, 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
)
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
;
5468 params
= evaluateExpression(params
);
5469 if(params
->type
== CELL_CONTEXT
|| params
->type
== CELL_SYMBOL
)
5470 newContext
= (SYMBOL
*)params
->contents
;
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
)
5505 params
= getSymbol(params
, &sourcePtr
);
5506 if(params
!= nilCell
)
5508 params
= getSymbol(params
, &targetPtr
);
5509 name
= targetPtr
->name
;
5510 newContext
= targetPtr
->context
;
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
)))
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)
5555 else return(nilCell
);
5558 if(!isList(cell
->type
))
5559 return(errorProcExt(ERR_LIST_OR_STRING_EXPECTED
, cell
));
5560 if(cell
->contents
== (UINT
)nilCell
)
5565 CELL
* isZero(CELL
* cell
)
5568 if(cell
->type
== CELL_INT64
)
5570 if(*(INT64
*)&cell
->aux
== 0)
5577 if(cell
->type
== CELL_FLOAT
)
5580 if(*(double *)&cell
->aux
== 0.0)
5582 if(*(double *)&cell
->contents
== 0.0)
5589 if(cell
->type
== CELL_LONG
)
5591 if(cell
->contents
== 0)
5599 CELL
* p_isNull(CELL
* params
)
5603 cell
= evaluateExpression(params
);
5607 if( (cell
->type
== CELL_STRING
|| isList(cell
->type
)))
5608 return(isEmptyFunc(cell
));
5611 if(cell
->type
== CELL_FLOAT
&& (isnan(*(double *)&cell
->aux
)) )
5613 if(cell
->type
== CELL_FLOAT
&& (isnan(*(double *)&cell
->contents
)))
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
))
5637 CELL
* p_isInteger(CELL
* params
)
5639 params
= evaluateExpression(params
);
5640 if((params
->type
& COMPARE_TYPE_MASK
) == CELL_INT
)
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
);
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
)
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
))
5691 CELL
* p_isProtected(CELL
* params
)
5693 params
= evaluateExpression(params
);
5694 if(isSymbol(params
->type
) && isProtected(((SYMBOL
*)params
->contents
)->flags
))
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
);
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
)
5727 if(params
== nilCell
)
5728 return(errorProc(ERR_MISSING_ARGUMENT
));
5729 params
= evaluateExpression(params
);
5730 if((UINT
)operand
== params
->type
) return(trueCell
);
5733 case CELL_PRIMITIVE
:
5734 if(params
->type
== CELL_IMPORT_CDECL
5736 || params
->type
== CELL_IMPORT_DLL
5741 case CELL_EXPRESSION
:
5742 if(isList(params
->type
)) return(trueCell
);
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
))
5764 CELL
* p_isLegal(CELL
* params
)
5768 getString(params
, &symStr
);
5770 if(isLegalSymbol(symStr
)) return(trueCell
);
5776 int isLegalSymbol(char * source
)
5779 char token
[MAX_SYMBOL
+ 1];
5782 if(*source
== (char)'"' || *source
== (char)'{' || *source
== (char)'['
5783 || (unsigned char)*source
<= (unsigned char)' ' || *source
== (char)';' || *source
== (char)'#')
5786 makeStreamFromString(&stream
, source
);
5788 return( (getToken(&stream
, token
, &tklen
) == TKN_SYMBOL
) && tklen
== strlen(source
));
5792 CELL
* p_exit(CELL
* params
)
5802 longjmp(errorJump
, ERR_USER_RESET
);
5805 if(params
!= nilCell
) getInteger(params
, (UINT
*)&result
);
5813 CELL
* p_reset(CELL
* params
)
5817 if (getFlag(params
))
5818 execv(MainArgs
[0], MainArgs
);
5822 longjmp(errorJump
, ERR_USER_RESET
);
5827 CELL
* p_errorEvent(CELL
* params
)
5831 if(params
!= nilCell
) getCreateSymbol(params
, &errorEvent
, "$error-event");
5832 symCell
= getCell(CELL_SYMBOL
);
5833 symCell
->contents
= (UINT
)errorEvent
;
5839 CELL
* p_timerEvent(CELL
* params
)
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
);
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)
5863 return(stuffInteger(0));
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
;
5878 CELL
* p_signal(CELL
* params
)
5881 SYMBOL
* signalEvent
;
5885 params
= getInteger(params
, (UINT
*)&sig
);
5886 if(sig
> 32 || sig
< 1) return(nilCell
);
5888 if(params
!= nilCell
)
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
;
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
)
5910 symCell
= getCell(CELL_SYMBOL
);
5911 symCell
->contents
= (UINT
)symHandler
[sig
- 1];
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
));
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
)
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
);
5969 blockPtr
= blockPtr
->next
;
5975 CELL
* p_mainArgs(CELL
* params
)
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
)
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
;
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)
6036 return(setDefine(sPtr
, params
->next
, TYPE_SET
));
6040 SYMBOL
* getCreateContext(CELL
* cell
, int evaluate
)
6042 SYMBOL
* contextSymbol
;
6045 cell
= evaluateExpression(cell
);
6047 if(cell
->type
== CELL_SYMBOL
|| cell
->type
== CELL_CONTEXT
)
6048 contextSymbol
= (SYMBOL
*)cell
->contents
;
6053 if(symbolType(contextSymbol
) != CELL_CONTEXT
)
6055 if(isProtected(contextSymbol
->flags
))
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
;
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
;
6122 params
= params
->next
;
6123 while(params
!= nilCell
)
6125 cell
->next
= copyCell(params
);
6127 params
= params
->next
;
6131 return(copyCell(evaluateExpression(proc
)));
6135 CELL
* p_systemSymbol(CELL
* params
)
6139 getInteger(params
, &idx
);
6141 if(idx
> 15 || idx
< 0) return(nilCell
);
6143 return(copyCell((CELL
*)sysSymbol
[idx
]->contents
));