G:/ScriptBasic/source/command.c

Go to the documentation of this file.
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*/

Generated on Sun Mar 12 23:56:26 2006 for ScriptBasic by  doxygen 1.4.6-NO