00001 /* 00002 FILE: command.c 00003 HEADER: command.h 00004 00005 --GNU LGPL 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2.1 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with this library; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 00020 This is a C file that contains only header information. Use headerer.pl to 00021 create command.h 00022 00023 We do not created command.h using an editor because all .h files may be deleted 00024 in this project during cleanup and we may loose this file accidentally. 00025 00026 TO_HEADER: 00027 #include "errcodes.h" 00028 #include "report.h" 00029 #include "sym.h" 00030 #include "lexer.h" 00031 #include "expression.h" 00032 #include "builder.h" 00033 #include "memory.h" 00034 #include "syntax.h" 00035 #include "execute.h" 00036 #include "syntax.h" 00037 #include "myalloc.h" 00038 #include "filesys.h" 00039 #include "options.h" 00040 #include "hookers.h" 00041 00042 #include "notimp.h" 00043 00044 #define COMMAND(x) void COMMAND_##x(pExecuteObject pEo){\ 00045 MortalList _ThisCommandMortals=NULL;\ 00046 pMortalList _pThisCommandMortals = &_ThisCommandMortals;\ 00047 unsigned long _ActualNode=PROGRAMCOUNTER;\ 00048 int iErrorCode; 00049 00050 #define IDENTICAL_COMMAND(x) COMMAND_##x(pEo); 00051 00052 #define USE_CALLER_MORTALS (_pThisCommandMortals = pEo->pGlobalMortalList) 00053 00054 #define END goto _FunctionFinishLabel;\ // this is to avoid warnings on unrefereced labels 00055 _FunctionFinishLabel: \ 00056 memory_ReleaseMortals(pEo->pMo,&_ThisCommandMortals);\ 00057 iErrorCode = 0;\ // this is to avoid warnings on unreferenced variable 00058 FINISH;\ 00059 } 00060 // some commands may redefine this macro to execute some finishing code 00061 #define FINISH 00062 00063 #define RETURN goto _FunctionFinishLabel 00064 #ifdef ERROR 00065 #undef ERROR 00066 #endif 00067 #define ERROR(x) do{ pEo->ErrorCode = x; RETURN; }while(0) 00068 00069 #define NOTIMPLEMENTED ERROR(COMMAND_ERROR_NOTIMP) 00070 00071 #define DEREFERENCE(X) refcount = pEo->pMo->maxderef;\ 00072 while( *(X) && TYPE( *(X) ) == VTYPE_REF ){\ 00073 (X) = (*(X))->Value.aValue;\ 00074 if( ! refcount -- )ERROR(COMMAND_ERROR_CIRCULAR);\ 00075 } 00076 00077 // Raise error or return undef based on option setting. 00078 #define ERRORUNDEF if( (*RaiseError(pEo))&1 ){\ 00079 ERROR(COMMAND_ERROR_DIV);\ 00080 }\ 00081 RESULT = NULL; RETURN; 00082 00083 // Raise error or return undef if macro argument is NULL 00084 #define NONULOP(x) ASSERTOKE;if( memory_IsUndef(x) ){if((*RaiseError(pEo))&2 ){\ 00085 ERROR(COMMAND_ERROR_UNDEFOP);\ 00086 }\ 00087 RESULT = NULL; RETURN;} 00088 00089 // Raise error if macro argument is NULL for compare operators 00090 #define NONULOPE(x) ASSERTOKE;if( memory_IsUndef(x) ){if( (*RaiseError(pEo))&4 )ERROR(COMMAND_ERROR_UNDEFOP);} 00091 00092 // Return argument as a double or if this is a long value then as a long. 00093 #define RETURN_DOUBLE_VALUE_OR_LONG(x) \ 00094 dResult = (x);\ 00095 if( dResult == floor(dResult) && fabs(dResult) < LONG_MAX ){\ 00096 RESULT= NEWMORTALLONG;\ 00097 ASSERTNULL(RESULT);\ 00098 LONGVALUE(RESULT) = ((long)dResult);\ 00099 RETURN;\ 00100 }\ 00101 RESULT = NEWMORTALDOUBLE;\ 00102 ASSERTNULL(RESULT);\ 00103 DOUBLEVALUE(RESULT) = dResult;\ 00104 RETURN; 00105 00106 #define RETURN_DOUBLE_VALUE(x) \ 00107 RESULT = NEWMORTALDOUBLE;\ 00108 ASSERTNULL(RESULT);\ 00109 DOUBLEVALUE(RESULT) = (x);\ 00110 RETURN; 00111 00112 // Return argument as a long. 00113 #define RETURN_LONG_VALUE(x) \ 00114 RESULT= NEWMORTALLONG;\ 00115 ASSERTNULL(RESULT);\ 00116 LONGVALUE(RESULT) = (x);\ 00117 RETURN; 00118 00119 #define RETURN_UNDEF RESULT = NULL; RETURN 00120 00121 #define RETURN_TRUE \ 00122 RESULT= NEWMORTALLONG;\ 00123 ASSERTNULL(RESULT);\ 00124 LONGVALUE(RESULT) = -1L;\ 00125 RETURN; 00126 00127 #define RETURN_FALSE \ 00128 RESULT= NEWMORTALLONG;\ 00129 ASSERTNULL(RESULT);\ 00130 LONGVALUE(RESULT) = 0L;\ 00131 RETURN; 00132 00133 #define PROGRAMCOUNTER (pEo->CommandArray[pEo->ProgramCounter-1].Parameter.NodeList.actualm) 00134 #define SETPROGRAMCOUNTER(x) ( pEo->fNextPC=1 , pEo->NextProgramCounter = (x) ) 00135 00136 #define NEXTPARAMETER (_ActualNode = pEo->CommandArray[_ActualNode-1].Parameter.CommandArgument.next) 00137 #define PARAMETERNODE (pEo->CommandArray[_ActualNode-1].Parameter.CommandArgument.Argument.pNode) 00138 #define PARAMETERLONG (pEo->CommandArray[_ActualNode-1].Parameter.CommandArgument.Argument.lLongValue) 00139 #define PARAMETERDOUBLE (pEo->CommandArray[_ActualNode-1].Parameter.CommandArgument.Argument.dDoubleValue) 00140 #define PARAMETERSTRING (pEo->StringTable+pEo->CommandArray[_ActualNode-1].Parameter.CommandArgument.Argument.szStringValue) 00141 #define PARAMETERSTRLEN (*((long *)(pEo->StringTable+pEo->CommandArray[_ActualNode-1].Parameter.CommandArgument.Argument.szStringValue-sizeof(long)))) 00142 #define PARAMETEREXEC (pEo->InstructionParameter[_ActualNode-1]) 00143 00144 #define OPCODE(x) (pEo->CommandArray[x-1].OpCode) 00145 #define THISPARAMPTR (pEo->CommandParameter[pEo->CommandArray[_ActualNode-1].OpCode - START_CMD]) 00146 #define PARAMPTR(x) (pEo->CommandParameter[(x) - START_CMD]) 00147 #define FINALPTR(x) (pEo->Finaliser[(x) - START_CMD]) 00148 #define ALLOC(x) alloc_Alloc((x),pEo->pMemorySegment) 00149 #define FREE(x) alloc_Free((x),pEo->pMemorySegment) 00150 00151 #define PARAMETERLIST (pEo->CommandArray[pEo->OperatorNode-1].Parameter.Arguments.Argument) 00152 00153 #define NEWLONG memory_NewLong(pEo->pMo) 00154 #define NEWDOUBLE memory_NewDouble(pEo->pMo) 00155 #define NEWSTRING(length) memory_NewString(pEo->pMo,length) 00156 #define NEWARRAY(low,high) memory_NewArray(pEo->pMo,low,high) 00157 00158 #define NEWMORTALLONG memory_NewMortalLong(pEo->pMo,_pThisCommandMortals) 00159 #define NEWMORTALDOUBLE memory_NewMortalDouble(pEo->pMo,_pThisCommandMortals) 00160 #define NEWMORTALSTRING(length) memory_NewMortalString(pEo->pMo,length,_pThisCommandMortals) 00161 #define NEWMORTALARRAY(low,high) memory_NewArray(pEo->pMo,_pThisCommandMortals,low,high) 00162 00163 #define CONVERT2DOUBLE(x) execute_Convert2Double(pEo,x,_pThisCommandMortals) 00164 #define CONVERT2LONG(x) execute_Convert2Long(pEo,x,_pThisCommandMortals) 00165 #define CONVERT2STRING(x) execute_Convert2String(pEo,x,_pThisCommandMortals) 00166 #define CONVERT2NUMERIC(x) execute_Convert2Numeric(pEo,x,_pThisCommandMortals) 00167 00168 #define CONVERT2ZCHAR(x,y) (y) = ALLOC(STRLEN( (x) )+1);\ 00169 if( (y) == NULL )ERROR(COMMAND_ERROR_MEMORY_LOW);\ 00170 memcpy((y),STRINGVALUE( (x) ),STRLEN( (x) ));\ 00171 (y)[STRLEN( (x) )] = (char)0; 00172 00173 00174 #define ISSTRINGINTEGER(x) execute_IsStringInteger(x) 00175 #define ISINTEGER(x) execute_IsInteger(x) 00176 00177 #define RESULT pEo->pOpResult 00178 00179 #define CAR(x) (((x)>0) ? pEo->CommandArray[(x)-1].Parameter.NodeList.actualm : 0) 00180 #define CDR(x) (((x)>0) ? pEo->CommandArray[(x)-1].Parameter.NodeList.rest : 0) 00181 00182 #define EVALUATEEXPRESSION(x) memory_DupMortalize(pEo->pMo,\ 00183 execute_Dereference(pEo,\ 00184 execute_Evaluate(pEo,x,_pThisCommandMortals,&iErrorCode,0),&iErrorCode),\ 00185 _pThisCommandMortals,\ 00186 &iErrorCode) 00187 #define _EVALUATEEXPRESSION(x) execute_Dereference(pEo,execute_Evaluate(pEo,x,_pThisCommandMortals,&iErrorCode,0),&iErrorCode) 00188 #define _EVALUATEEXPRESSION_A(x) execute_Dereference(pEo,execute_Evaluate(pEo,x,_pThisCommandMortals,&iErrorCode,1),&iErrorCode) 00189 #define EVALUATELEFTVALUE(x) execute_LeftValue(pEo,x,_pThisCommandMortals,&iErrorCode,0) 00190 #define EVALUATELEFTVALUE_A(x) execute_LeftValue(pEo,x,_pThisCommandMortals,&iErrorCode,1) 00191 00192 #define ASSERTOKE if( iErrorCode )ERROR(iErrorCode); // use this macro after each EVAL to check that no error occured 00193 #define ASSERTNULL(X) if( (X) == NULL )ERROR(COMMAND_ERROR_MEMORY_LOW); 00194 00195 #define IMMORTALIZE(x) memory_Immortalize(x,_pThisCommandMortals) 00196 00197 typedef unsigned long NODE; 00198 typedef pFixSizeMemoryObject VARIABLE, *LEFTVALUE; 00199 #define TYPE(x) ((x)->vType) 00200 00201 #define OPTION(x) options_Get(pEo,(x)) 00202 #define OPTIONR(x) options_GetR(pEo,(x)) 00203 */ 00204 00205 /*POD 00206 =H Header file for command building 00207 00208 This file contains macros that help the command implementators to write easy, readable and 00209 compact code. The macros on one hand assume some variable naming, but on the other hand 00210 hide some details of the function calls. 00211 00212 For examples how to use these macros see the files in the T<commands> directory of the 00213 source files. Note that some command implementation do not use these macros, because they 00214 do sophisticated and low level operations that have to deal with the interpreted 00215 code in more detail. However such a programming should not be neccesary to implement 00216 a new command or function for extending the language. 00217 00218 To implement a new command or function do the following: 00219 00220 =itemize 00221 =item Read the definitions here. 00222 =item Read the macros and see the implemented functions and commands in the directory T<commands>. 00223 Try to get some understanding how it works. 00224 =item Take an already implemented function which is similar to the one that you want to implement. Copy 00225 it to a new file, give it a new name. 00226 =item Edit the T<syntax.def> file to include the new command or file and run T<syntaxer.pl syntax.def> 00227 to generate the files T<syntax.h> and T<syntax.def> 00228 =item Compile ScriptBasic to see that the function with the new name or the command has the same 00229 functionality as the old one that you have copied. 00230 =item Start modifying the code step by step. At each step compile the interpreter and check that the modified 00231 functionality exists. 00232 =item Debug, crosscheck the final code and document your new command or function for your project. 00233 =item Announce the new functionality in your project and be proud. 00234 =item Be happy. 00235 =noitemize 00236 00237 B<NOTE:> 00238 00239 This file is actually a header file. This is maintained in T<command.c> to avoid 00240 accidental deletion of the T<command.h> file. The file T<command.h> is an intermediate file 00241 created from T<command.c> using the Perl utility T<headerer.pl>. Because all T<*.h> files 00242 are intermediate it would have been dangerous to have T<command.h> to be a source file. 00243 00244 00245 00246 The macros and types defined in this file: 00247 00248 CUT*/ 00249 00250 /*POD 00251 =section COMMAND 00252 =H Start a command implementation 00253 00254 T<COMMAND> 00255 00256 This macro should be used to start a function that implements a command or built-in function. 00257 This actually generates the function header with some local variable declarations and some 00258 variable setting. 00259 00260 =verbatim 00261 COMMAND(FUNCTIONNAME) 00262 =noverbatim 00263 00264 in the current implementation generates: 00265 00266 =verbatim 00267 void COMMAND_FUNCTIONNAME(pExecuteObject pEo){ 00268 MortalList _ThisCommandMortals=NULL; 00269 pMortalList _pThisCommandMortals = &_ThisCommandMortals; 00270 unsigned long _ActualNode=PROGRAMCOUNTER; 00271 int iErrorCode; 00272 =noverbatim 00273 00274 Note that further implemenation changes may change the actual code generated not followed in this 00275 documentation. However the actual use of the macro should not change. 00276 00277 The function should be finished using the macro R<END> documented also in this documentation. 00278 00279 CUT*/ 00280 00281 /*POD 00282 =section END 00283 =H Finish a command implementation 00284 00285 This macro generates the finishing code that a function impementing a BASIC command or built-in function 00286 should have. 00287 00288 =verbatim 00289 END 00290 =noverbatim 00291 00292 in the current implementation generates the following code: 00293 00294 =verbatim 00295 goto _FunctionFinishLabel; 00296 _FunctionFinishLabel: 00297 memory_ReleaseMortals(pEo->pMo,&_ThisCommandMortals); 00298 iErrorCode = 0; 00299 } 00300 =noverbatim 00301 00302 Note that further implemenation changes may change the actual code generated not followed in this 00303 documentation. However the actual use of the macro should not change. 00304 00305 Some part of the code may seem unneccesary. The T<goto> just before the label, or the final assignment 00306 to a local variable. These are present to avoid some compiler warning and clever compilers should 00307 optimize out these constructs. 00308 00309 CUT*/ 00310 00311 /*POD 00312 =section IDENTICAL_COMMAND 00313 =H Implement a command that has identical functionality 00314 00315 This macro helps to implement a command that has identical functionality as 00316 another command. You can see examples for it in the looping construct. There is a wide 00317 variety of looping construct to implement all looping facilities that BASIC programmers 00318 got used to. However the loop closing commands more or less behave the same. For example 00319 the command T<next> behaves exactly the same as the command T<while> 00320 00321 Also note that the identical behaviour does not mean that one command can be used instead 00322 of the other. There are conventions that the BASIC language requires and the syntactical 00323 analyzer does nto allow to close a T<FOR> loop using a T<WEND> command. 00324 00325 To present an example on how to use this macro we have copied the code of the comman T<NEXT>: 00326 00327 =verbatim 00328 COMMAND(NEXT) 00329 00330 IDENTICAL_COMMAND(WEND) 00331 00332 END 00333 =noverbatim 00334 00335 CUT*/ 00336 00337 /*POD 00338 =section USE_CALLER_MORTALS 00339 =H Use the mortals of the caller 00340 00341 =verbatim 00342 USE_CALLER_MORTALS 00343 =noverbatim 00344 00345 You should use this macro when impementing a built-in function. The implementation 00346 of the commands use their own mortal list to collect mortal variables storing 00347 intermediate results. Built-in function implementations do NOT maintain their own 00348 collection of mortal variables. This macro sets some variables to collect mortal 00349 variables into the list of the calling modules. 00350 00351 To get a deeper understanding of mortals and variable handling see the documentation 00352 for the source file T<memory.c> 00353 00354 CUT*/ 00355 00356 /*POD 00357 =section RETURN 00358 =H Return from the function 00359 00360 =verbatim 00361 RETURN 00362 =noverbatim 00363 00364 When implementing a built-in function or command you should never ever T<return> from 00365 the function because that may avoid release of mortal variables and may not execute 00366 the final code which is needed to properly finish the function. Use the macro T<RETURN> 00367 instead. 00368 CUT*/ 00369 00370 /*POD 00371 =section ERROR 00372 =H Terminate a function with error 00373 00374 =verbatim 00375 ERROR(x) 00376 =noverbatim 00377 00378 Use this macro to terminate the execution of a commans or built-in function with some 00379 error. T<ERROR(0)> means no error, but this construct is not advisable, use R<RETURN> instead. 00380 Any other code value can be used to specify a special error. 00381 00382 CUT*/ 00383 00384 /*POD 00385 =section PROGRAMCOUNTER 00386 =H The value of the programcounter 00387 00388 =verbatim 00389 PROGRAMCOUNTER 00390 =noverbatim 00391 00392 This macro results the node id of the command, which is currently executed. Note that this is 00393 already the node that contains the command code and not the code that the class variable T<ProgramCounter> 00394 points. T<ProgramCounter> points to a list node. This list node points to the node returned by 00395 T<PROGRAMCOUNTER> and to the next command node. 00396 00397 CUT*/ 00398 00399 /*POD 00400 =section SETPROGRAMCOUNTER 00401 =H Implement jump instructions 00402 00403 =verbatim 00404 SETPROGRAMCOUNTER(x) 00405 =noverbatim 00406 00407 Use this macro when a command decides that the code interpretation should 00408 continue at a different location. The simplest example on how to use this 00409 macro is the implementation of the command T<goto>: 00410 00411 =verbatim 00412 COMMAND(GOTO) 00413 00414 SETPROGRAMCOUNTER(PARAMETERNODE); 00415 00416 END 00417 =noverbatim 00418 00419 See also R<PARAMETERNODE>. 00420 00421 CUT*/ 00422 00423 /*POD 00424 =section NEXTPARAMETER 00425 =H Get the next command parameter 00426 00427 =verbatim 00428 NEXTPARAMETER 00429 =noverbatim 00430 00431 This macro should be used to get access to the next command parameter. This macro should NOT be 00432 used in built-in function implemenation. The functions have only a single parameter, which is indeed 00433 an expression list. To access the parameters of a function use the macros R<PARAMETERLIST>, R<CAR> and 00434 R<CDR>. 00435 00436 When you implement a command you can get the first parameter of a command using the macro 00437 T<PARAMETERNODE>, T<PARAMETERLONG>, T<PARAMETERDOUBLE> or T<PARAMETERSTRING> (see R<PARAMETERXXX>). 00438 If the command has more than one parameters you should use the macro T<NEXTPARAMETER> 00439 to step to the next parameter. 00440 00441 CUT*/ 00442 /*POD 00443 =section PARAMETERXXX 00444 =H Access a command parameter 00445 00446 =verbatim 00447 PARAMETERNODE 00448 PARAMETERLONG 00449 PARAMETERDOUBLE 00450 PARAMETERSTRING 00451 =noverbatim 00452 00453 You should use these macros to get access to the command parameters. Usually these parameters are 00454 presented as "nodes". Syntax definition usually allows you to use expressions whenever a long, double 00455 or string is expected. Expressions are converted to "nodes" and therefore only a few commands may 00456 use the macros T<PARAMETERLONG>, T<PARAMETERDOUBLE> or T<PARAMETERSTRING>. These can be used when the 00457 parameter is a long number, double number or a contant string and NOT an expression or expression list. 00458 00459 When a command has more than one parameters you can access each, step by step using the macro R<NEXTPARAMETER>, 00460 which steps onto the next parameter of the command. 00461 00462 Do B<NOT> use any of the T<PARAMETERXXX> macro or the macro R<NEXTPARAMETER> in the implementation 00463 of a built-in function. 00464 CUT*/ 00465 /*POD 00466 =section OPCODE 00467 =H Get the opcode of a node 00468 00469 =verbatim 00470 OPCODE(x) 00471 =noverbatim 00472 00473 This macro results the opcode of the node T<x>. This macro can rarely be used by your extension. 00474 00475 CUT*/ 00476 00477 /*POD 00478 =section PARAMETERLIST 00479 =H Get the parameter list node for a function 00480 00481 =verbatim 00482 PARAMETERLIST 00483 =noverbatim 00484 00485 You should use this macro to get the parameter list for a built-in function or operator. 00486 Both built-in functions and operators get their parameter list as and expression list. This 00487 macro gets the first list node of the expression list. 00488 00489 The parameter is presented as an expression list even if there is only a single parameter 00490 for the function. 00491 00492 To access the parameters use the macros R<CAR> and R<CDR>. 00493 CUT*/ 00494 00495 /*POD 00496 =section CAR 00497 =H Get the car node of a list node 00498 00499 Expression lists and commands are stored using list nodes. A list node has an R<OPCODE> value 00500 T<eNTYPE_LST> defined in T<expression.c>, and has two node pointers. One points to the node 00501 that belongs to the list member and other points to the next list node. 00502 00503 If T<nItem> is a list node for an expression list then T<CAR(nItem)> is the root node of the 00504 expression, and T<CDR(nItem)> is the list node for the next expression. T<CAR(CDR(nItem))> is 00505 the root node of the second expression. 00506 00507 The nodes are indexed with T<unsigned long> values. T<NULL> pointer is a T<0L> value and list 00508 node lists are terminated with a node that has T<CDR(nItem)=0L>. 00509 00510 See also R<CDR>. 00511 CUT*/ 00512 00513 /*POD 00514 =section CDR 00515 =H Get the cdr node of a list node 00516 00517 Expression lists and commands are stored using list nodes. A list node has an R<OPCODE> value 00518 T<eNTYPE_LST> defined in T<expression.c>, and has two node pointers. One points to the node 00519 that belongs to the list member and other points to the next list node. 00520 00521 If T<nItem> is a list node for an expression list then T<CAR(nItem)> is the root node of the 00522 expression, and T<CDR(nItem)> is the list node for the next expression. T<CAR(CDR(nItem))> is 00523 the root node of the second expression. 00524 00525 The nodes are indexed with T<unsigned long> values. T<NULL> pointer is a T<0L> value and list 00526 node lists are terminated with a node that has T<CDR(nItem)=0L>. 00527 00528 See also R<CAR>. 00529 CUT*/ 00530 00531 /*POD 00532 =section RESULT 00533 =H Special variable to store the result 00534 00535 =verbatim 00536 RESULT 00537 =noverbatim 00538 00539 Use this macro to store the result of the operation. Usually a new mortal value should be 00540 allocated using R<NEWMORTALXXX> and the appropriate value of T<RESULT> should be then set. 00541 00542 See also R<NEWMORTALXXX>, R<XXXVALUE> 00543 00544 CUT*/ 00545 00546 /*POD 00547 =section XXXVALUE 00548 =H Access certain values of a memory object 00549 00550 =verbatim 00551 STRINGVALUE(x) 00552 LONGVALUE(x) 00553 DOUBLEVALUE(x) 00554 =noverbatim 00555 00556 These macros are actually defined in T<memory.c>, but we document them here because they play 00557 an important role when writing implementation code for functions and operators. 00558 00559 These macros get the string (car*), long or double value of a variable. The macros can also be 00560 used to assign value a long or double value to a variable. Do not forget to change the type of the 00561 variable. You usually should call the macro R<CONVERT2XXX>. 00562 00563 Note that you should NOT change the string value of a variable. The T<STRINGVALUE(x)> is a (char *) 00564 pointer to a string. You have to change the characters in this string, or you should allocate a new 00565 string with longer or shorter length and copy the characters, but never change the (char *) pointer. 00566 00567 CUT*/ 00568 00569 /*POD 00570 =section NEWMORTALXXX 00571 =H Create a new mortal value 00572 00573 =verbatim 00574 NEWMORTALLONG 00575 NEWMORTALDOUBLE 00576 NEWMORTALSTRING(length) 00577 =noverbatim 00578 00579 Use these macros to allocate a new mortal variable. In case of a string you have to give 00580 the length of the string. 00581 00582 =center 00583 INCLUDE THE TERMINATING ZERO IN THE LENGTH!!! 00584 =nocenter 00585 00586 Never allocate non-mortal values when implemenating operators or functions. 00587 00588 CUT*/ 00589 00590 /*POD 00591 =section EVALUATEEXPRESSION 00592 =H Evaluate an expression 00593 00594 =verbatim 00595 EVALUATEEXPRESSION(x) 00596 _EVALUATEEXPRESSION(x) 00597 =noverbatim 00598 00599 Use these macros to evaluate an expression. The argument is the root node of the expression. 00600 When a command has a parameter, which is an expression you should write: 00601 00602 =verbatim 00603 VARIABLE Param; 00604 00605 Param = EVALUATEEXPRESSION(PARAMETERNODE); 00606 =noverbatim 00607 00608 Implementing a function or operator you should write 00609 00610 =verbatim 00611 VARIABLE Param; 00612 00613 Param = EVALUATEEXPRESSION(CAR(PARAMETERLIST)); 00614 =noverbatim 00615 00616 For further details see examples in the source files T<commands/let.c>, T<commands/mathops.c>. 00617 00618 B<NOTE:> 00619 00620 When an expression is evaluated the returned pointer points to a struct which contains the value 00621 of the expression. This is usually a mortal variable which was created during expression evaluation. 00622 However in some cases this pointer points to a nonmortal variable. If the expression is a single 00623 global or local variable the result of the expression is the pointer to the variable value. 00624 00625 This helps writing for more efficient code. On ther other hand operators tend to convert the operands 00626 to long or double in case they expect a long or double but get a different type. The conversions, or 00627 other manipulations then change the original variable value, which is a side effect. For this reason 00628 the macro T<EVALUATEEXPRESSION> also calls T<memory_DupMortalize> which creates a new variable, and 00629 copies the content of the variable passed as argument if the variable is not a mortal. 00630 00631 T<_EVALUATEEXPRESSION> does not do this and therefore you can use it for more efficient memory 00632 handling avoiding the creation of unneccesary copies of variables. 00633 00634 If you are not sure whichone to use use the first one without the leading underscore. 00635 00636 CUT*/ 00637 /*POD 00638 =section EVALUATELEFTVALUE 00639 =H Evaluate a left value 00640 00641 =verbatim 00642 EVALUATELEFTVALUE(x) 00643 =noverbatim 00644 00645 Use this macro to evaluate a left value. This is done in the function T<commands/let.c> that implements 00646 the command LET. This command wasprogrammed with comments to help the learning how this works. 00647 00648 CUT*/ 00649 00650 /*POD 00651 =section IMMORTALIZE 00652 =H Immortalize a variable 00653 00654 =verbatim 00655 IMMORTALIZE(x) 00656 =noverbatim 00657 00658 Use this macro to immortalize a variable.You usually should avoid immortalizing values when implementing 00659 operators of functions. Immortalize a value when it is assigned to a variable. 00660 00661 CUT*/ 00662 00663 /*POD 00664 =section NEWXXX 00665 =H Create a new immortal value 00666 00667 =verbatim 00668 NEWLONG 00669 NEWDOUBLE 00670 NEWSTRING(length) 00671 =noverbatim 00672 00673 Use these macros to create a new long, double or string value. The created value is NOT mortal. 00674 You usually should avoid this when implementing functions or operators. However you may need in 00675 some command implementation. 00676 00677 CUT*/ 00678 00679 /*POD 00680 =section CONVERT2XXX 00681 =H Convert a value to other type 00682 00683 =verbatim 00684 CONVERT2DOUBLE(x) 00685 CONVERT2LONG(x) 00686 CONVERT2STRING(x) 00687 =noverbatim 00688 00689 Use these macros to convert a value to long, double or string. The macros return the pointer to the 00690 converted type. Note that conversion between long and double does not generate a new value. In such 00691 a conversion the argument pointer is returned and the value itself is converted from one type tp the 00692 other. This was programmed this way to avoid unneccesary creation of mortal values. However be sure 00693 that either the argument is a mortal value or you do not mind the conversion of the value and so the value 00694 of the variable that the value was assigned to. You need not worry about this when you use the macro 00695 T<EVALUATEEXPRESSION> and not T<_EVALUATEEXPRESSION>. 00696 00697 Also note that a conversion does not duplicate the value if the value already has the desired type. In such 00698 a case the argument pointer is returned. 00699 00700 On the other hand there is no guarantee that the conversion is done in-place. When conversion from 00701 string to anything else is done a new mortal variable is allocated and the pointer to that 00702 value is returned. 00703 00704 CUT*/ 00705 00706 /*POD 00707 =section PARAMPTR 00708 =H Parameter pointer 00709 00710 =verbatim 00711 PARAMPTR(x) 00712 THISPARAMPTR 00713 =noverbatim 00714 00715 Each command may need some parameters that are persistent during a program execution. For example 00716 the file handling routines need an array that associates the opened file handles with the integer 00717 values that the basic language uses. Each command may allocate storage and assign a pointer to 00718 T<THISPARAMPTR> to point to the allocated space. This is a void pointer initialized to T<NULL>. 00719 00720 A command may access a pointer of another command using the macro T<PARAMPTR(x)> supplying 00721 I<x> as the command code. This is usually T<CMD_XXX> with I<XXX> the name of the command, function or 00722 operator. 00723 00724 See also R<ALLOC> and R<FREE> 00725 CUT*/ 00726 00727 /*POD 00728 =section ALLOC 00729 =H Allocate memory 00730 00731 The T<ALLOC> and R<FREE> macros are provided to allocate general memory. They are not intended to create 00732 new variable storage. For that purpose the R<NEWXXX> and R<NEWMORTALXXX> macros should be 00733 used. 00734 00735 The memory allocated should usually be assigned to the T<THISPARAMPTR> pointer (see R<PARAMPTR>). 00736 00737 The macro T<ALLOC> behaves similar to the system function T<malloc> accepting the size of the required memory 00738 in bytes and returning a void pointer. 00739 00740 The macro R<FREE> accepts the pointer to the allocated memory and returns nothing. 00741 00742 There is no need to release the allocated memory. The memory allocated using T<ALLOC> is automatically 00743 release upon program termination. 00744 00745 CUT*/ 00746 00747 /*POD 00748 =section FREE 00749 =H Release memory 00750 00751 00752 The R<ALLOC> and T<FREE> macros are provided to allocate general memory. They are not intended to create 00753 new variable storage. For that purpose the R<NEWXXX> and R<NEWMORTALXXX> macros should be 00754 used. 00755 00756 The memory allocated should usually be assigned to the T<THISPARAMPTR> pointer (see R<PARAMPTR>). 00757 00758 The macro R<ALLOC> behaves similar to the system function T<malloc> accepting the size of the required memory 00759 in bytes and returning a void pointer. 00760 00761 The macro T<FREE> accepts the pointer to the allocated memory and returns nothing. 00762 00763 There is no need to release the allocated memory. The memory allocated using R<ALLOC> is automatically 00764 release upon program termination. 00765 CUT*/ 00766 00767 /*POD 00768 =section ISSTRINGINTEGER 00769 =H Decide if a string is integer or not 00770 00771 =verbatim 00772 ISSTRINGINTEGER(x) 00773 =noverbatim 00774 00775 Use this macro to decide that a string contains integer value or not. This can beuseful implementing 00776 operators that work with doubles as well as longs. When one of the operators is a string hopefully 00777 containing the decimal form of a number you have to convert the string to a long or double. This 00778 macro calls a function that decides whether the string contains an integer number convertible to 00779 long or contains a double. 00780 00781 For an example how to use it see the source file T<commands/mathops.c> 00782 CUT*/ 00783 00784 /*POD 00785 =section NODE 00786 =H Basic C variable types to be used 00787 00788 =verbatim 00789 NODE nNode; 00790 VARIABLE Variable; 00791 LEFTVALUE Lval; 00792 =noverbatim 00793 00794 These T<typedef>s can be used to declare C variables that are to hold value associated with nodes, 00795 variables (or values) and left values. For example how to use these T<typedef>s see the files 00796 T<commands/let.c>, T<commands/mathops.c> 00797 00798 CUT*/ 00799 00800 /*POD 00801 =section TYPE 00802 =H Get the actual type of a value 00803 00804 =verbatim 00805 TYPE(x) 00806 =noverbatim 00807 00808 Use this macro to access the type of a value. Values can hold long, double, string or reference types. 00809 This macro returns the type of the value. For comparision use the constants: 00810 00811 =itemize 00812 =item T<VTYPE_LONG> long value 00813 =item T<VTYPE_DOUBLE> double value 00814 =item T<VTYPE_STRING> string value 00815 =item T<VTYPE_REF> reference value 00816 =noitemize 00817 00818 CUT*/