3 * - Script AST Manipulator
11 tAST_Script *AST_NewScript(void)
13 tAST_Script *ret = malloc( sizeof(tAST_Script) );
15 ret->Functions = NULL;
16 ret->LastFunction = NULL;
22 * \brief Append a function to a script
24 tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name)
28 ret = malloc( sizeof(tAST_Function) + strlen(Name) + 1 );
30 strcpy(ret->Name, Name);
32 ret->Arguments = NULL;
34 if(Script->LastFunction == NULL) {
35 Script->Functions = Script->LastFunction = ret;
38 Script->LastFunction->Next = ret;
39 Script->LastFunction = ret;
45 void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Node)
47 if( !Function->Arguments ) {
48 Function->Arguments_Last = Function->Arguments = Node;
51 Function->Arguments_Last->NextSibling = Node;
52 Function->Arguments_Last = Node;
57 * \brief Set the code for a function
59 void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
61 Function->Code = Root;
65 * \name Node Manipulation
69 * \brief Get the in-memory size of a node
71 size_t AST_GetNodeSize(tAST_Node *Node)
79 ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
80 + sizeof(const char *) + sizeof(int);
86 ret += sizeof(Node->Block);
87 for( node = Node->Block.FirstChild; node; )
89 ret += AST_GetNodeSize(node);
90 node = node->NextSibling;
95 case NODETYPE_FUNCTIONCALL:
96 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
97 for( node = Node->FunctionCall.FirstArg; node; )
99 ret += AST_GetNodeSize(node);
100 node = node->NextSibling;
106 ret += sizeof(Node->If);
107 ret += AST_GetNodeSize(Node->If.Condition);
108 ret += AST_GetNodeSize(Node->If.True);
109 ret += AST_GetNodeSize(Node->If.False);
112 // Looping Construct (For loop node)
114 ret += sizeof(Node->For);
115 ret += AST_GetNodeSize(Node->For.Init);
116 ret += AST_GetNodeSize(Node->For.Condition);
117 ret += AST_GetNodeSize(Node->For.Increment);
118 ret += AST_GetNodeSize(Node->For.Code);
122 case NODETYPE_ASSIGN:
123 ret += sizeof(Node->Assign);
124 ret += AST_GetNodeSize(Node->Assign.Dest);
125 ret += AST_GetNodeSize(Node->Assign.Value);
130 ret += sizeof(Node->Cast);
131 ret += AST_GetNodeSize(Node->Cast.Value);
135 case NODETYPE_DEFVAR:
136 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
137 for( node = Node->DefVar.LevelSizes; node; )
139 ret += AST_GetNodeSize(node);
140 node = node->NextSibling;
145 case NODETYPE_RETURN:
146 ret += sizeof(Node->UniOp);
147 ret += AST_GetNodeSize(Node->UniOp.Value);
153 case NODETYPE_SUBTRACT:
154 case NODETYPE_MULTIPLY:
155 case NODETYPE_DIVIDE:
156 case NODETYPE_MODULO:
157 case NODETYPE_BITSHIFTLEFT:
158 case NODETYPE_BITSHIFTRIGHT:
159 case NODETYPE_BITROTATELEFT:
160 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
161 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
162 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
163 case NODETYPE_EQUALS:
164 case NODETYPE_LESSTHAN:
165 case NODETYPE_GREATERTHAN:
166 ret += sizeof(Node->BinOp);
167 ret += AST_GetNodeSize( Node->BinOp.Left );
168 ret += AST_GetNodeSize( Node->BinOp.Right );
171 // Node types with no children
174 case NODETYPE_VARIABLE:
175 case NODETYPE_CONSTANT:
176 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
178 case NODETYPE_STRING:
179 ret += sizeof(Node->String) + Node->String.Length;
181 case NODETYPE_INTEGER:
182 ret += sizeof(Node->Integer);
185 ret += sizeof(Node->Real);
193 #define WRITE_N(_buffer, _offset, _len, _dataptr) do { \
194 if(_buffer) memcpy((char*)_buffer + _offset, _dataptr, _len);\
198 #define WRITE_8(_buffer, _offset, _val) do {\
200 WRITE_N(_buffer, _offset, 1, &v);\
202 #define WRITE_16(_buffer, _offset, _val) do {\
203 uint16_t v = (_val);\
204 WRITE_N(_buffer, _offset, 2, &v);\
206 #define WRITE_32(_buffer, _offset, _val) do {\
207 uint32_t v = (_val);\
208 WRITE_N(_buffer, _offset, 4, &v);\
210 #define WRITE_64(_buffer, _offset, _val) do {\
211 uint64_t v = (_val);\
212 WRITE_N(_buffer, _offset, 8, &v);\
214 #define WRITE_REAL(_buffer, _offset, _val) do {\
216 WRITE_N(_buffer, _offset, sizeof(double), &v);\
219 #define WRITE_STR(_buffer, _offset, _string) do {\
220 int len = strlen(_string);\
221 WRITE_16(_buffer, _offset, len);\
222 WRITE_N(_buffer, _offset, len, _string);\
224 #define WRITE_NODELIST(_buffer, _offset, _listHead) do {\
227 for(node=(_listHead); node; node = node->NextSibling) {\
229 _offset += AST_WriteNode(_buffer, _offset, node); \
230 WRITE_32(_buffer, ptr, ptr); \
232 if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \
236 * \brief Writes a script dump to a buffer
237 * \return Size of encoded data
238 * \note If \a Buffer is NULL, no write is done, but the size is still returned
240 size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
245 for( fcn = Script->Functions; fcn; fcn = fcn->Next )
248 WRITE_32(Buffer, ret, 0); // Next
249 WRITE_STR(Buffer, ret, fcn->Name);
250 WRITE_NODELIST(Buffer, ret, fcn->Arguments); // TODO: Cheaper way
251 ret += AST_WriteNode(Buffer, ret, fcn->Code);
252 WRITE_32(Buffer, ptr, ret); // Actually set next
255 WRITE_32(Buffer, ptr, 0); // Clear next for final
261 * \brief Write a node to a file
263 size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
266 typeof(Offset) baseOfs = Offset;
269 fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n");
273 WRITE_32(Buffer, Offset, 0); // Next
274 WRITE_8(Buffer, Offset, Node->Type);
275 //WRITE_32(Buffer, Offset, 0); // File
276 WRITE_16(Buffer, Offset, Node->Line); // Line
282 WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild);
286 case NODETYPE_FUNCTIONCALL:
287 WRITE_STR(Buffer, Offset, Node->FunctionCall.Name);
288 WRITE_NODELIST(Buffer, Offset, Node->FunctionCall.FirstArg);
294 WRITE_32(Buffer, Offset, 0); // Condition
295 WRITE_32(Buffer, Offset, 0); // True
296 WRITE_32(Buffer, Offset, 0); // False
298 Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition);
299 WRITE_32(Buffer, ptr, Offset);
300 Offset += AST_WriteNode(Buffer, Offset, Node->If.True);
301 WRITE_32(Buffer, ptr, Offset);
302 Offset += AST_WriteNode(Buffer, Offset, Node->If.False);
303 WRITE_32(Buffer, ptr, Offset);
306 // Looping Construct (For loop node)
308 WRITE_8(Buffer, Offset, Node->For.bCheckAfter);
310 WRITE_32(Buffer, Offset, 0); // Init
311 WRITE_32(Buffer, Offset, 0); // Condition
312 WRITE_32(Buffer, Offset, 0); // Increment
313 WRITE_32(Buffer, Offset, 0); // Code
315 Offset += AST_WriteNode(Buffer, Offset, Node->For.Init);
316 WRITE_32(Buffer, ptr, Offset);
317 Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition);
318 WRITE_32(Buffer, ptr, Offset);
319 Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment);
320 WRITE_32(Buffer, ptr, Offset);
321 Offset += AST_WriteNode(Buffer, Offset, Node->For.Code);
322 WRITE_32(Buffer, ptr, Offset);
326 case NODETYPE_ASSIGN:
327 WRITE_8(Buffer, Offset, Node->Assign.Operation);
329 WRITE_32(Buffer, Offset, 0); // Dest
330 WRITE_32(Buffer, Offset, 0); // Value
332 Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest);
333 WRITE_32(Buffer, ptr, Offset);
334 Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value);
335 WRITE_32(Buffer, ptr, Offset);
340 WRITE_8(Buffer, Offset, Node->Cast.DataType);
342 WRITE_32(Buffer, Offset, 0);
344 Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value);
345 WRITE_32(Buffer, ptr, Offset);
349 case NODETYPE_DEFVAR:
350 WRITE_8(Buffer, Offset, Node->DefVar.DataType);
351 WRITE_8(Buffer, Offset, Node->DefVar.Depth);
352 WRITE_STR(Buffer, Offset, Node->DefVar.Name);
354 WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes);
358 case NODETYPE_RETURN:
360 WRITE_32(Buffer, Offset, 0);
361 Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
362 WRITE_32(Buffer, ptr, Offset);
368 case NODETYPE_SUBTRACT:
369 case NODETYPE_MULTIPLY:
370 case NODETYPE_DIVIDE:
371 case NODETYPE_MODULO:
372 case NODETYPE_BITSHIFTLEFT:
373 case NODETYPE_BITSHIFTRIGHT:
374 case NODETYPE_BITROTATELEFT:
375 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
376 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
377 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
378 case NODETYPE_EQUALS:
379 case NODETYPE_LESSTHAN:
380 case NODETYPE_GREATERTHAN:
382 WRITE_32(Buffer, Offset, 0); // Left
383 WRITE_32(Buffer, Offset, 0); // Right
384 Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left);
385 WRITE_32(Buffer, ptr, Offset);
386 Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right);
387 WRITE_32(Buffer, ptr, Offset);
390 // Node types with no children
393 case NODETYPE_VARIABLE:
394 case NODETYPE_CONSTANT:
395 WRITE_STR(Buffer, Offset, Node->Variable.Name);
397 case NODETYPE_STRING:
398 WRITE_32(Buffer, Offset, Node->String.Length);
399 WRITE_N(Buffer, Offset, Node->String.Length, Node->String.Data);
401 case NODETYPE_INTEGER:
402 WRITE_64(Buffer, Offset, Node->Integer);
405 WRITE_REAL(Buffer, Offset, Node->Real);
409 fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type);
413 return Offset - baseOfs;
417 * \brief Write a node to a file
419 void AST_WriteNode(FILE *FP, tAST_Node *Node)
427 ptr = ftell(FP) + AST_GetNodeSize(Node);
428 fwrite(&ptr, sizeof(ptr), 1, FP);
429 fwrite(&Node->Type, sizeof(Node->Type), 1, FP);
430 ptr = 0; fwrite(&ptr, sizeof(ptr), 1, FP); // File
431 fwrite(&Node->Line, sizeof(Node->Line), 1, FP);
433 ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
434 + sizeof(const char *) + sizeof(int);
440 ret += sizeof(Node->Block);
441 for( node = Node->Block.FirstChild; node; )
443 ret += AST_GetNodeSize(node);
444 node = node->NextSibling;
449 case NODETYPE_FUNCTIONCALL:
450 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
451 for( node = Node->FunctionCall.FirstArg; node; )
453 ret += AST_GetNodeSize(node);
454 node = node->NextSibling;
460 ret += sizeof(Node->If);
461 ret += AST_GetNodeSize(Node->If.Condition);
462 ret += AST_GetNodeSize(Node->If.True);
463 ret += AST_GetNodeSize(Node->If.False);
466 // Looping Construct (For loop node)
468 ret += sizeof(Node->For);
469 ret += AST_GetNodeSize(Node->For.Init);
470 ret += AST_GetNodeSize(Node->For.Condition);
471 ret += AST_GetNodeSize(Node->For.Increment);
472 ret += AST_GetNodeSize(Node->For.Code);
476 case NODETYPE_ASSIGN:
477 ret += sizeof(Node->Assign);
478 ret += AST_GetNodeSize(Node->Assign.Dest);
479 ret += AST_GetNodeSize(Node->Assign.Value);
484 ret += sizeof(Node->Cast);
485 ret += AST_GetNodeSize(Node->Cast.Value);
489 case NODETYPE_DEFVAR:
490 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
491 for( node = Node->DefVar.LevelSizes; node; )
493 ret += AST_GetNodeSize(node);
494 node = node->NextSibling;
499 case NODETYPE_RETURN:
500 ret += sizeof(Node->UniOp);
501 ret += AST_GetNodeSize(Node->UniOp.Value);
507 case NODETYPE_SUBTRACT:
508 case NODETYPE_MULTIPLY:
509 case NODETYPE_DIVIDE:
510 case NODETYPE_MODULO:
511 case NODETYPE_BITSHIFTLEFT:
512 case NODETYPE_BITSHIFTRIGHT:
513 case NODETYPE_BITROTATELEFT:
514 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
515 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
516 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
517 case NODETYPE_EQUALS:
518 case NODETYPE_LESSTHAN:
519 case NODETYPE_GREATERTHAN:
520 ret += sizeof(Node->BinOp);
521 ret += AST_GetNodeSize( Node->BinOp.Left );
522 ret += AST_GetNodeSize( Node->BinOp.Right );
525 // Node types with no children
528 case NODETYPE_VARIABLE:
529 case NODETYPE_CONSTANT:
530 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
532 case NODETYPE_STRING:
533 ret += sizeof(Node->String) + Node->String.Length;
535 case NODETYPE_INTEGER:
536 ret += sizeof(Node->Integer);
539 ret += sizeof(Node->Real);
547 * \brief Free a node and all subnodes
549 void AST_FreeNode(tAST_Node *Node)
559 for( node = Node->Block.FirstChild; node; )
561 tAST_Node *savedNext = node->NextSibling;
568 case NODETYPE_FUNCTIONCALL:
569 for( node = Node->FunctionCall.FirstArg; node; )
571 tAST_Node *savedNext = node->NextSibling;
579 AST_FreeNode(Node->If.Condition);
580 AST_FreeNode(Node->If.True);
581 AST_FreeNode(Node->If.False);
584 // Looping Construct (For loop node)
586 AST_FreeNode(Node->For.Init);
587 AST_FreeNode(Node->For.Condition);
588 AST_FreeNode(Node->For.Increment);
589 AST_FreeNode(Node->For.Code);
593 case NODETYPE_ASSIGN:
594 AST_FreeNode(Node->Assign.Dest);
595 AST_FreeNode(Node->Assign.Value);
600 AST_FreeNode(Node->Cast.Value);
604 case NODETYPE_DEFVAR:
605 for( node = Node->DefVar.LevelSizes; node; )
607 tAST_Node *savedNext = node->NextSibling;
614 case NODETYPE_RETURN:
615 AST_FreeNode(Node->UniOp.Value);
621 case NODETYPE_SUBTRACT:
622 case NODETYPE_MULTIPLY:
623 case NODETYPE_DIVIDE:
624 case NODETYPE_MODULO:
625 case NODETYPE_BITSHIFTLEFT:
626 case NODETYPE_BITSHIFTRIGHT:
627 case NODETYPE_BITROTATELEFT:
628 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
629 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
630 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
631 case NODETYPE_EQUALS:
632 case NODETYPE_LESSTHAN:
633 case NODETYPE_GREATERTHAN:
634 AST_FreeNode( Node->BinOp.Left );
635 AST_FreeNode( Node->BinOp.Right );
638 // Node types with no children
639 case NODETYPE_NOP: break;
640 case NODETYPE_VARIABLE: break;
641 case NODETYPE_CONSTANT: break;
642 case NODETYPE_STRING: break;
643 case NODETYPE_INTEGER: break;
644 case NODETYPE_REAL: break;
649 tAST_Node *AST_NewCodeBlock(void)
651 tAST_Node *ret = malloc( sizeof(tAST_Node) );
653 ret->NextSibling = NULL;
654 //ret->Line = Parser->CurLine;
655 ret->Type = NODETYPE_BLOCK;
656 ret->Block.FirstChild = NULL;
657 ret->Block.LastChild = NULL;
662 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
664 Child->NextSibling = NULL;
665 switch( Parent->Type )
668 if(Parent->Block.FirstChild == NULL) {
669 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
672 Parent->Block.LastChild->NextSibling = Child;
673 Parent->Block.LastChild = Child;
676 case NODETYPE_DEFVAR:
677 if(Parent->DefVar.LevelSizes == NULL) {
678 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
681 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
682 Parent->DefVar.LevelSizes_Last = Child;
686 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
691 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
693 tAST_Node *ret = malloc( sizeof(tAST_Node) );
694 ret->NextSibling = NULL;
695 ret->Line = Parser->CurLine;
696 ret->Type = NODETYPE_IF;
697 ret->If.Condition = Condition;
699 ret->If.False = False;
703 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
705 tAST_Node *ret = malloc( sizeof(tAST_Node) );
706 ret->NextSibling = NULL;
707 ret->Line = Parser->CurLine;
708 ret->Type = NODETYPE_LOOP;
709 ret->For.Init = Init;
710 ret->For.bCheckAfter = !!bPostCheck;
711 ret->For.Condition = Condition;
712 ret->For.Increment = Increment;
713 ret->For.Code = Code;
717 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
719 tAST_Node *ret = malloc( sizeof(tAST_Node) );
721 ret->NextSibling = NULL;
722 ret->Line = Parser->CurLine;
723 ret->Type = NODETYPE_ASSIGN;
724 ret->Assign.Operation = Operation;
725 ret->Assign.Dest = Dest;
726 ret->Assign.Value = Value;
731 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
733 tAST_Node *ret = malloc( sizeof(tAST_Node) );
735 ret->NextSibling = NULL;
736 ret->Line = Parser->CurLine;
737 ret->Type = NODETYPE_CAST;
738 ret->Cast.DataType = Target;
739 ret->Cast.Value = Value;
744 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
746 tAST_Node *ret = malloc( sizeof(tAST_Node) );
748 ret->NextSibling = NULL;
749 ret->Line = Parser->CurLine;
750 ret->Type = Operation;
751 ret->BinOp.Left = Left;
752 ret->BinOp.Right = Right;
759 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
761 tAST_Node *ret = malloc( sizeof(tAST_Node) );
763 ret->NextSibling = NULL;
764 ret->Line = Parser->CurLine;
765 ret->Type = Operation;
766 ret->UniOp.Value = Value;
772 * \brief Create a new string node
774 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
776 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
778 ret->NextSibling = NULL;
779 ret->Line = Parser->CurLine;
780 ret->Type = NODETYPE_STRING;
781 ret->String.Length = Length;
782 memcpy(ret->String.Data, String, Length);
783 ret->String.Data[Length] = '\0';
789 * \brief Create a new integer node
791 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
793 tAST_Node *ret = malloc( sizeof(tAST_Node) );
794 ret->NextSibling = NULL;
795 ret->Line = Parser->CurLine;
796 ret->Type = NODETYPE_INTEGER;
797 ret->Integer = Value;
802 * \brief Create a new variable reference node
804 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
806 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
807 ret->NextSibling = NULL;
808 ret->Line = Parser->CurLine;
809 ret->Type = NODETYPE_VARIABLE;
810 strcpy(ret->Variable.Name, Name);
815 * \brief Create a new variable definition node
817 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
819 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
820 ret->NextSibling = NULL;
821 ret->Line = Parser->CurLine;
822 ret->Type = NODETYPE_DEFVAR;
823 ret->DefVar.DataType = Type;
824 ret->DefVar.LevelSizes = NULL;
825 strcpy(ret->DefVar.Name, Name);
830 * \brief Create a new runtime constant reference node
832 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
834 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
835 ret->NextSibling = NULL;
836 ret->Line = Parser->CurLine;
837 ret->Type = NODETYPE_CONSTANT;
838 strcpy(ret->Variable.Name, Name);
843 * \brief Create a function call node
844 * \note Argument list is manipulated using AST_AppendFunctionCallArg
846 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
848 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
850 ret->NextSibling = NULL;
851 ret->Line = Parser->CurLine;
852 ret->Type = NODETYPE_FUNCTIONCALL;
853 ret->FunctionCall.FirstArg = NULL;
854 ret->FunctionCall.LastArg = NULL;
855 strcpy(ret->FunctionCall.Name, Name);
860 * \brief Append an argument to a function call
862 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
864 if( Node->Type != NODETYPE_FUNCTIONCALL ) return ;
866 if(Node->FunctionCall.LastArg) {
867 Node->FunctionCall.LastArg->NextSibling = Arg;
868 Node->FunctionCall.LastArg = Arg;
871 Node->FunctionCall.FirstArg = Arg;
872 Node->FunctionCall.LastArg = Arg;