コード例 #1
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
void add_iteration_lists(Graph g)
{
    Node node,child,parent,child1,child2;
    int i,j,k,l;

    MARKED_1(g -> source) = TRUE;

    for(node = g -> source->next; node != NULL; node = node -> next) {
        for(i = 0; i < ListSize(node -> predecessors); i++) {
	    parent = (Node) ListIndex(node -> predecessors,i);
	    if (MARKED_1(parent) == FALSE) {
	        for(j=0; j < ListSize(parent -> successors); j++) {
		    child = (Node) ListIndex(parent->successors,j);
		    if ((strcmp(child->name,node->name) != 0) && (ORDER(child) > ORDER(parent)))
		    {
                         ListPut(ITER_END_NODES(node),child);
		    }
		}
	     }
	}
	MARKED_1(node) = TRUE;
        for(k = 0; k < ListSize(node -> successors); k++) {
            child1 = (Node) ListIndex(node -> successors,k);
	    if (MARKED_1(child1) == TRUE) {
	        for(l = 0; l < ListSize(node -> successors); l++) {
	            child2 = (Node) ListIndex(node -> successors,l);
		    if (MARKED_1(child2) == FALSE) {
		        ListPut(ITER_START_NODES(child2),child1);
		    }
	        }
	    }
	 }
    }
}
コード例 #2
0
ファイル: gena_device.c プロジェクト: mrjimenez/pupnp
/*
 * This gets called before queuing a new event.
 * - The list size can never go over MAX_SUBSCRIPTION_QUEUED_EVENTS so we
 *   discard the oldest non-active event if it is already at the max
 * - We also discard any non-active event older than MAX_SUBSCRIPTION_EVENT_AGE.
 * non-active: any but the head of queue, which is already copied to
 * the thread pool
 */
static void maybeDiscardEvents(LinkedList *listp)
{
	time_t now = time(0L);

	while (ListSize(listp) > 1) {
		ListNode *node = ListHead(listp);
		/* The first candidate is the second event: first non-active */
		if (node == 0 || (node = node->next) == 0) {
			/* Major inconsistency, really, should abort here. */
			fprintf(stderr, "gena_device: maybeDiscardEvents: "
					"list is inconsistent\n");
			break;
		}

		notify_thread_struct *ntsp =
			(notify_thread_struct *)(((ThreadPoolJob *)node->item)->arg);
		if (ListSize(listp) > g_UpnpSdkEQMaxLen ||
			now - ntsp->ctime > g_UpnpSdkEQMaxAge) {
			free_notify_struct(ntsp);
			free(node->item);
			ListDelNode(listp, node, 0);
		} else {
			/* If the list is smaller than the max and the oldest
			 * task is young enough, stop pruning */
			break;
		}
	}
}
コード例 #3
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
int set_rendezvous_state(Node n)
{
    int error;
    int i;
    Node child,parent;
    int status = 1;
    if (n -> type == RENDEZVOUS) {
        for(i = 0; i < ListSize(n -> predecessors); i++) {
            parent = (Node) ListIndex(n -> predecessors,i);
            if (STATE(parent) != ACT_DONE) {
                status = 0;
            }
        }
        if (status == 1) {
            set_node_state(n, ACT_DONE, &error); //only raise error when Node type is ACTION
            set_node_state(n -> matching, ACT_DONE, &error);
            for(i = 0; i< ListSize(n -> successors); i++) {
                child = (Node) ListIndex(n -> successors,i);
                if (child -> type == JOIN) {
                    propogate_join_done(child, ACT_DONE);
                }
                mark_successors(child,ACT_READY);
                set_rendezvous_state(child);
            }
        }
    }
    return 1;
}
コード例 #4
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
void set_iter_none(Node n, Node original)
{
    Node iter_start_node,iter_end_node;
    int i;

    for(i = 0; i < ListSize(ITER_START_NODES(n)); i++) {
        iter_start_node = (Node) ListIndex(ITER_START_NODES(n),i);
        if ((iter_start_node->type == SELECTION) || (iter_start_node->type == BRANCH) ||(iter_start_node->type == ACTION)) {
	    if ((strcmp(iter_start_node -> name, original -> name) != 0) && (MARKED_2(iter_start_node) == FALSE)) {
	        MARKED_2(iter_start_node) = TRUE;
                mark_successors(iter_start_node,ACT_NONE);
                set_iter_none(iter_start_node,original);
	    }
        }
    }


    for(i = 0; i < ListSize(ITER_END_NODES(n)); i++) {
        iter_end_node = (Node) ListIndex(ITER_END_NODES(n),i);
	if ((iter_end_node->type == SELECTION) || (iter_end_node->type == BRANCH) ||(iter_end_node->type == ACTION)) {
	    if ((strcmp(iter_end_node -> name, original -> name) != 0) && (MARKED_2(iter_end_node) == FALSE)) {	     
	        MARKED_2(iter_end_node) = TRUE;
	        mark_successors(iter_end_node,ACT_NONE);
	        set_iter_none(iter_end_node,original);
	    }
	}
    }
	
}
コード例 #5
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
void handle_selection(Node n)
{
    int i,j;
    Node parent;
    Node child;
 
    if ((n -> predecessors == NULL) || (MARKED_3(n) == TRUE))
        return;
		                                                                         
    MARKED_3(n) = TRUE;
 
    for(i = 0; i < ListSize(n -> predecessors); i++) {
        parent = (Node) ListIndex(n -> predecessors,i);
        if ((parent -> type) == SELECTION) {
            for(j=0; j < ListSize(parent -> successors); j++) {
                child = (Node) ListIndex(parent -> successors,j);
                if (strcmp((child->name),n->name) != 0) {
                    mark_successors(child,ACT_NONE);
                }
	     }
	}
	if (ORDER(n) >  ORDER(parent))  
        handle_selection(parent);
    }
    return;
}
コード例 #6
0
ファイル: ThreadPool.c プロジェクト: philippe44/pupnp
int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats)
{
	if (tp == NULL || stats == NULL)
		return EINVAL;
	/* if not shutdown then acquire mutex */
	if (!tp->shutdown)
		ithread_mutex_lock(&tp->mutex);

	*stats = tp->stats;
	if (stats->totalJobsHQ > 0)
		stats->avgWaitHQ = stats->totalTimeHQ / (double)stats->totalJobsHQ;
	else
		stats->avgWaitHQ = 0.0;
	if (stats->totalJobsMQ > 0)
		stats->avgWaitMQ = stats->totalTimeMQ / (double)stats->totalJobsMQ;
	else
		stats->avgWaitMQ = 0.0;
	if (stats->totalJobsLQ > 0)
		stats->avgWaitLQ = stats->totalTimeLQ / (double)stats->totalJobsLQ;
	else
		stats->avgWaitLQ = 0.0;
	stats->totalThreads = tp->totalThreads;
	stats->persistentThreads = tp->persistentThreads;
	stats->currentJobsHQ = (int)ListSize(&tp->highJobQ);
	stats->currentJobsLQ = (int)ListSize(&tp->lowJobQ);
	stats->currentJobsMQ = (int)ListSize(&tp->medJobQ);

	/* if not shutdown then release mutex */
	if (!tp->shutdown)
		ithread_mutex_unlock(&tp->mutex);

	return 0;
}
コード例 #7
0
ファイル: snake_and_food.c プロジェクト: RekiLiu/samples
// 判断蛇是否死了。
// 返回0 蛇没有死 else 蛇死了。
int IsSnakeDead()
{
	PGAME_COORD posBody;
	PGAME_COORD posHead;

	int i;
	int size = ListSize(snake_list);


	// 判断是否死亡
	/// 判断是否碰到墙
	posHead = (PGAME_COORD)ListGetAt(snake_list, 0);

	if (posHead->x < 0 || posHead->x > boundary.x ||
		posHead->y < 0 || posHead->y > boundary.y)
	{
		return SNAKE_DEAD;
	}
	/// 判断是否碰到自己
	//// 从第二个节点开始,逐一和头节点比较。
	size = ListSize(snake_list);

	for (i = 1; i < size; i++)
	{
		posBody = (PGAME_COORD)ListGetAt(snake_list, i);
		if (CoordEqual(posHead, posBody))
		{
			return SNAKE_DEAD;
		}
	}
	return SNAKE_MOVED;
}
コード例 #8
0
void TestRemove( void )
{
    UInt16* item1;
    UInt16* item2;

    ASSERT( ListIsEmpty( list ));

    AddTwoItems();

    item1 = ListFirst( list );
    ListTakeOut( list, item1 );
    ASSERT( ListSize( list ) == 1 );

    MemPtrFree( item1 );

    item1 = ListFirst( list );
    item2 = ListLast( list );
    ASSERT_UINT16_EQUAL_MSG( "First item: ", 10, *item1 );
    ASSERT_UINT16_EQUAL_MSG( "Last item: ", 10, *item2 );

    ListTakeOut( list, item2 );
    ASSERT( ListSize( list ) == 0 );
    ASSERT( ListFirst( list ) == NULL );
    ASSERT( ListLast( list ) == NULL );

    MemPtrFree( item2 );
}
コード例 #9
0
void TestAppendItem( void )
{
    UInt16* item1;
    UInt16* item2;
    UInt16* data1;
    UInt16* data2;

    ASSERT( ListIsEmpty( list ));

    data1 = MemPtrNew( sizeof *data1 );
    *data1 = 6;
    ListAppend( list, data1 );
    ASSERT( ListSize( list ) == 1 );
    ASSERT( ! ListIsEmpty( list ));

    data2 = MemPtrNew( sizeof *data2 );
    *data2 = 10;
    ListAppend( list, data2 );
    ASSERT( ListSize( list ) == 2 );

    item1 = ListGet( list, 1 );
    item2 = ListGet( list, 2 );
    ASSERT_UINT16_EQUAL_MSG( "First item: ", 6, *item1 );
    ASSERT_UINT16_EQUAL_MSG( "Second item: ", 10, *item2 );
}
コード例 #10
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
int mark_successors(Node n, vm_act_state state)
{
    int error;
    int i;
    Node child;
    if (n -> type == ACTION) {
        set_node_state(n, state, &error);
        if (error)
            return 0;
        mark_iter_nodes(n);
        return 1;
    }
    else if ((n -> type == BRANCH) || (n -> type == SELECTION) || (n -> type == JOIN)) {
        if ((n->type == BRANCH) || (n->type == SELECTION)) {
            set_node_state(n, state, &error);
            if (error)
                return 0;
            mark_iter_nodes(n);
            set_node_state(n -> matching, state, &error);
            if (error)
                return 0;
        }
        for(i = 0; i < ListSize(n -> successors); i++) {
            child = (Node) ListIndex(n -> successors, i);
            mark_successors(child,state);
        }
    }
    return 1;
}
コード例 #11
0
ファイル: Symbol.cpp プロジェクト: usnistgov/QIF
ISymbol::ISymbol()
{
	Parsed()=0; 
	Visited()=0; 
	Type()=(SymbolType) -1; 
	ListType()=unknown_; 
	Dimension()=0;
	SimpleType()=true;
	Required()=false;
	Abstract()=false;
	Compositor()=0;
	DerivedType() = XercesAdditions::DERIVATION_NONE;
	XercesType() = XercesAdditions::NO_DECLARATION;
	Global()=false;
	SqlCount()=0;
	SubstitutionGroupAffiliation().clear();
	symbols.push_back(this);
	Variable()=NULL;
	SimpleContent()=false;
	List()=false;
	Atomic()=false;
	Level()=0;
	ListSize()=0;
	intrusive_ptr_add_ref((IExpress *) symbols.back().get());
}
コード例 #12
0
ファイル: font.c プロジェクト: TimofonicJunkRoom/plucker
static void SortAndMakeUserFontNameList( void )
{
    UInt16        i;
    DBEntryType*  dbListEntry;
    DBEntryType** userFontArray;

    currentUserFontNumber = NO_SUCH_USER_FONT;
    ClearUserFontNameList();
    if ( userFontDBList == NULL )
        return;

    numberOfUserFonts = ListSize( userFontDBList );
    if ( numberOfUserFonts == 0 )
        return;

    userFontArray   = SafeMemPtrNew( numberOfUserFonts * sizeof( DBEntryType* ) );
    userFontNames   = SafeMemPtrNew( numberOfUserFonts * sizeof( Char* ) );
    dbListEntry     = ListFirst( userFontDBList );
    for ( i = 0; i < numberOfUserFonts ; i++ ) {
        userFontArray[ i ] = dbListEntry;
        dbListEntry        = ListNext( userFontDBList, dbListEntry );
    }
    SysQSort( userFontArray, numberOfUserFonts, sizeof( DBEntryType* ),
        DBEntryCompare, 0 );
    ListDelete( userFontDBList );
    userFontDBList = ListCreate();
    for ( i = 0 ; i < numberOfUserFonts ; i++ ) {
        ListAppend( userFontDBList, userFontArray[ i ] );
        userFontNames[ i ] = userFontArray[ i ]->name;
    }
    SafeMemPtrFree( userFontArray );
}
コード例 #13
0
ファイル: FileSystem.c プロジェクト: ColumPaget/Movgrab
int FindFilesInPath(const char *File, const char *Path, ListNode *Files)
{
char *Tempstr=NULL, *CurrPath=NULL, *ptr;
int i;
glob_t Glob;

if (*File=='/')
{
	CurrPath=CopyStr(CurrPath,"");
	ptr=""; //so we execute once below
}
else ptr=GetToken(Path,":",&CurrPath,0);
while (ptr)
{
CurrPath=SlashTerminateDirectoryPath(CurrPath);
Tempstr=MCopyStr(Tempstr,CurrPath,File,NULL);

glob(Tempstr,0,0,&Glob);
for (i=0; i < Glob.gl_pathc; i++) ListAddItem(Files,CopyStr(NULL,Glob.gl_pathv[i]));
globfree(&Glob);

ptr=GetToken(ptr,":",&CurrPath,0);
}

DestroyString(Tempstr);
DestroyString(CurrPath);

return(ListSize(Files));
}
コード例 #14
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
ListNode *CreateList()
{   ListNode *list = HEAP(ListNode);

    ListSize(list) = 0;
    ListHead(list) = ListTail(list) = NULL;
    return(list);
}
コード例 #15
0
ファイル: snake_and_food.c プロジェクト: RekiLiu/samples
// 生成新的食物。
int CreateFood()
{
	PGAME_COORD posbody;
	int i;
	int size = ListSize(snake_list);

new_food:

	// 随机生成食物的坐标。
	food.x = rand() % boundary.x;
	food.y = rand() % boundary.y;

	// 判断是否和蛇重叠了,否则重新生成食物坐标,知道不重叠。

	for (i = 0; i < size; i++)
	{
		posbody = (PGAME_COORD)ListGetAt(snake_list, i);
		if (CoordEqual(posbody, &(food)))
		{
			goto new_food;
		}
	}
	return 1;

}
コード例 #16
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
void set_process_state(Graph g)
{
    Node parent;
    int i;
    int status = 1;

    for(i = 0; i < ListSize(g -> sink -> predecessors); i++) {
        parent = (Node) ListIndex(g -> sink -> predecessors,i);
        if ((ListSize(parent -> successors) > 1) || (STATE(parent) != ACT_DONE))
	    status = 0;
    }
    
    if (status == 1) {
	STATE(g -> source) = ACT_DONE;
        STATE(g -> sink) =  ACT_DONE;	
    }
}
コード例 #17
0
off_t STREAMSendFile(STREAM *In, STREAM *Out, off_t Max)
{
char *Buffer=NULL;
int BuffSize=BUFSIZ;
off_t val, result=SENDFILE_FAILED;

#ifdef USE_SENDFILE

//if we are not using ssl and not using processor modules, we can use 
//kernel-level copy!

#include <sys/sendfile.h>

val=In->Flags | Out->Flags;
if ((! (val & SF_SSL)) && (ListSize(In->ProcessingModules)==0) && (ListSize(Out->ProcessingModules)==0))
{
	val=0;
	STREAMFlush(Out);
	result=sendfile(Out->out_fd, In->in_fd,0,BUFSIZ);
	while (result > 0)
	{
		val+=result;
		if ((Max > 0) && (val >= Max)) break;
		result=sendfile(Out->out_fd, In->in_fd,0,BUFSIZ);
	}
}

#endif

if (result==SENDFILE_FAILED)
{
	val=0;
	Buffer=SetStrLen(Buffer,BuffSize);
	result=STREAMReadBytes(In,Buffer,BuffSize);
	while (result >=0)
	{
		val+=STREAMWriteBytes(Out,Buffer,result);
		if ((Max > 0) && (val >= Max)) break;
		result=STREAMReadBytes(In,Buffer,BuffSize);
	}
}

DestroyString(Buffer);

return(val);
}
コード例 #18
0
ファイル: snake_and_food.c プロジェクト: RekiLiu/samples
// 按照序号获得蛇的节点的坐标,不能超过蛇的长度,否则返回NULL
PGAME_COORD GetSnakeAt(int n)
{
	if (n < ListSize(snake_list))
		return (PGAME_COORD)ListGetAt(snake_list, n);
	else
		return NULL;

}
コード例 #19
0
int ThreadPoolGetStats( ThreadPool *tp, ThreadPoolStats *stats )
{
	assert(tp != NULL);
	assert(stats != NULL);
	if (tp == NULL || stats == NULL) {
		return EINVAL;
	}

	//if not shutdown then acquire mutex
	if (!tp->shutdown) {
		ithread_mutex_lock(&tp->mutex);
	}

	*stats = tp->stats;
	if (stats->totalJobsHQ > 0) {
		stats->avgWaitHQ = stats->totalTimeHQ / stats->totalJobsHQ;
	} else {
		stats->avgWaitHQ = 0;
	}
	
	if( stats->totalJobsMQ > 0 ) {
		stats->avgWaitMQ = stats->totalTimeMQ / stats->totalJobsMQ;
	} else {
		stats->avgWaitMQ = 0;
	}
	
	if( stats->totalJobsLQ > 0 ) {
		stats->avgWaitLQ = stats->totalTimeLQ / stats->totalJobsLQ;
	} else {
		stats->avgWaitLQ = 0;
	}

	stats->totalThreads = tp->totalThreads;
	stats->persistentThreads = tp->persistentThreads;
	stats->currentJobsHQ = ListSize( &tp->highJobQ );
	stats->currentJobsLQ = ListSize( &tp->lowJobQ );
	stats->currentJobsMQ = ListSize( &tp->medJobQ );

	//if not shutdown then release mutex
	if( !tp->shutdown ) {
		ithread_mutex_unlock( &tp->mutex );
	}

	return 0;
}
コード例 #20
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void AddToMacroList( Macros *item, ListNode *list )
{  if (MacrosTail(list) == NULL)
   {  list->head = item;
   }
   else
   {  MacroNext(MacrosTail(list)) = item;
   }
   list->tail = item;
   ListSize(list)++;
}
コード例 #21
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void AddToStructList( Structs *item, ListNode *list )
{  if( StructsTail(list) == NULL)
   {  list->head = item;
   }
   else
   {  StructNext(StructsTail(list)) = item;
   }
   list->tail = item;
   ListSize(list)++;
}
コード例 #22
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void AddToPrimitiveList( Primitives *item, ListNode *list )
{  if (PrimitivesTail(list) == NULL)
   {  list->head = item;
   }
   else
   {  PrimitiveNext(PrimitivesTail(list)) = item;
   }
   list->tail = item;
   ListSize(list)++;
}
コード例 #23
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void AddToEnumeratedList( Enumerateds *item, ListNode *list )
{  if (EnumeratedsTail(list) == NULL)
   {  list->head = item;
   }
   else
   {  EnumeratedNext(EnumeratedsTail(list)) = item;
   }
   list->tail = item;
   ListSize(list)++;
}
コード例 #24
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void AddToUnionList( Unions *item, ListNode *list )
{  if( UnionsTail(list) == NULL )
   {  list->head = item;
   }
   else
   {  UnionNext(UnionsTail(list)) = item;
   }
   list->tail = item;
   ListSize(list)++;
}
コード例 #25
0
// The kax_block_group_c objects are stored in counted_ptrs outside of
// the cluster structure as well. KaxSimpleBlock objects are deleted
// when they're replaced with kax_block_group_c. All other object
// types must be deleted explicitely. This applies to
// e.g. KaxClusterTimecodes.
void
kax_cluster_c::delete_non_blocks() {
  unsigned idx;
  for (idx = 0; ListSize() > idx; ++idx) {
    EbmlElement *e = (*this)[idx];
    if ((NULL == dynamic_cast<kax_block_group_c *>(e)) && (NULL == dynamic_cast<KaxSimpleBlock *>(e)))
      delete e;
  }

  RemoveAll();
}
コード例 #26
0
ファイル: List.c プロジェクト: ColumPaget/Crayonizer
void MapDumpSizes(ListNode *Head)
{
    int i;
		ListNode *Chain;

    for (i=0; i < MapChainCount(Head); i++)
    {
        Chain=MapGetNthChain(Head, i);
        printf("%d %lu\n",i, ListSize(Chain));
    }
}
コード例 #27
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void WriteStructTokens( FILE *outfile, char *table, ListNode *list)
{  Structs *pos = StructsHead(list);

   fprintf( outfile, "#define %s_%s %d\n",
                     table, STRUCT_QTY_FRMT, ListSize(list));
   while( pos != NULL)
   {  fprintf( outfile, "#define %s_%s %d\n",
                        table, StructName(pos), StructToken(pos));
      pos = StructNext(pos);
   }
   fprintf( outfile, "\n" );
}
コード例 #28
0
ファイル: generator.c プロジェクト: NevilleDNZ/ella2000
void WriteUnionTokens( FILE *outfile, char *table, ListNode *list)
{  Unions *pos = UnionsHead(list);

   fprintf( outfile, "#define %s_%s %d\n",
                     table, UNION_QTY_FRMT, ListSize(list));
   while( pos != NULL)
   {  fprintf( outfile, "#define %s_%s %d\n",
                        table, UnionName(pos), UnionToken(pos));
      pos = UnionNext(pos);
   }
   fprintf( outfile, "\n" );
}
コード例 #29
0
ファイル: graph_engine.c プロジェクト: jimiszm/peos
vm_exit_code action_done(Graph g, char *act_name)
{
    int error;
    Node n;
    Node child;
    int i,num_successors;
    vm_act_state state_set;

    if (action_run(g, act_name) == -1) return VM_INTERNAL_ERROR;
    n = find_node(g,act_name);
    if (n != NULL) {
        state_set = set_node_state(n, ACT_DONE, &error);
        if (error)
            return VM_INTERNAL_ERROR;
	num_successors = ListSize(n -> successors);
	for(i = 0; i < num_successors; i++) {
	    child = (Node) ListIndex(n -> successors, i);
	    /*
	     * (num_successors == 1) is a check to see that it is 
	     * not an iteration.
	     */
	    if (state_set == ACT_DONE) {
                if ((child -> type == JOIN) && (num_successors == 1)) {
	            propogate_join_done(child, state_set);
	        }
	    }
	    if (child -> type != RENDEZVOUS) {
		/* 
		 * if a child is not a rendezvous or a join, it has to 
		 * be a selection or branch or action, so mark it ready. If 
		 * its sink, that is handled again by set_process_state(..) 
		 */
	        mark_successors(child, ACT_READY);
	    }
	    else {
	        if (num_successors == 1)	
		set_rendezvous_state(child);
	    }
	}	    
	if (num_successors == 1)
	    set_process_state(g);
    }
    else {
        fprintf(stderr, "Error in action_done");
	return VM_INTERNAL_ERROR;
    }
    if (STATE(g->source) == ACT_DONE) {
        return VM_DONE;
    }
    else
        return VM_CONTINUE;
}
コード例 #30
0
ファイル: DataParser.c プロジェクト: ColumPaget/Crayonizer
const char *ParserAddNewStructure(int ParserType, const char *Data, ListNode *Parent, int Type, const char *Name, int IndentLevel)
{
    ListNode *Item, *Node;
    char *Token=NULL;
    const char *ptr;

    Item=ListCreate();
    Item->Tag=CopyStr(Item->Tag,Name);
    if (Name) Node=ListAddNamedItem(Parent, Name, Item);
    else
    {
        if (StrValid(Parent->Tag)) Token=FormatStr(Token, "%s:%d",Parent->Tag, ListSize(Parent));
        else Token=FormatStr(Token, "item:%d",ListSize(Parent));
        Node=ListAddNamedItem(Parent, Token, Item);
    }

    Node->ItemType=Type;
    ptr=ParserParseItems(ParserType, Data, Item, IndentLevel);

    DestroyString(Token);
    return(ptr);
}