Première version
This commit is contained in:
529
util/dsbench.c
Normal file
529
util/dsbench.c
Normal file
@@ -0,0 +1,529 @@
|
||||
#define DS_MODE 2
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdarg.h>
|
||||
#include <node.h>
|
||||
#include <datastr.h>
|
||||
|
||||
extern char * strdup ( const char *);
|
||||
|
||||
#define QUIT 0
|
||||
#define CREATE_STRUCT 1
|
||||
#define OPEN_STRUCT 2
|
||||
#define CLOSE_STRUCT 3
|
||||
#define DELETE_STRUCT 4
|
||||
#define ADD_VALUE 5
|
||||
#define REMOVE_VALUE 6
|
||||
#define FIND_VALUE 7
|
||||
#define CHG_LIST_TYPE 8
|
||||
#define CONVERT_TO_TREE 9
|
||||
#define CONVERT_TO_LIST 10
|
||||
#define REORG 11
|
||||
#define INFO 12
|
||||
#define SHOW 13
|
||||
#define CHECK 14
|
||||
|
||||
#define MANAGER_FILE_NAME "dsbench.so"
|
||||
|
||||
char DataStruct_Name [100];
|
||||
char menu [1000];
|
||||
char buf [100];
|
||||
long int random ( void );
|
||||
NDT_Status Module_Manager (va_list Args);
|
||||
void init_menu ( NDT_Root *);
|
||||
int print_menu ( NDT_Root *);
|
||||
|
||||
/* Mesure des temps d'exécution */
|
||||
|
||||
typedef struct {
|
||||
double sec;
|
||||
struct timeval start;
|
||||
struct timeval stop;
|
||||
} T_Cpt;
|
||||
|
||||
#define t_start(x) {gettimeofday (&(x.start), NULL);}
|
||||
#define t_stop(x) {gettimeofday (&(x.stop), NULL); x.sec = (double)(x.stop.tv_sec) - (double)(x.start.tv_sec) + ((double)(x.stop.tv_usec) - (double)(x.start.tv_usec)) / 1000000;}
|
||||
|
||||
T_Cpt t_exec;
|
||||
|
||||
/* Définition des valeurs attachées aux noeuds de la structure */
|
||||
|
||||
typedef struct {
|
||||
int Id;
|
||||
char * Nom;
|
||||
} T_Module;
|
||||
|
||||
int main (int argc, char ** argv)
|
||||
{
|
||||
NDT_Root * Root = NULL;
|
||||
char * tmp;
|
||||
int n, m, i, j;
|
||||
int choice, Nb_Removed, Locked;
|
||||
int Nb_Detected, Nb_Corrected;
|
||||
T_Module * Module, Ref_Module;
|
||||
NDT_Node * Node;
|
||||
|
||||
if (argc > 1 && !strcmp (argv[1], "-h"))
|
||||
{
|
||||
fprintf (stdout, "Usage : %s [-h] [instance [context]]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (DS_Library_Open (0, NULL, DSD_DEBUG_ALL) != NDS_OK) return 0;
|
||||
|
||||
choice = print_menu (Root);
|
||||
|
||||
while (choice != QUIT)
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
case CREATE_STRUCT:
|
||||
fprintf (stdout, "\nNom de la structure à créer ? ");
|
||||
gets (DataStruct_Name);
|
||||
|
||||
if (DS_DataStruct_Open (DataStruct_Name, &Root, NDD_DS_LIST | NDD_MN_FIFO, \
|
||||
MANAGER_FILE_NAME, 0, DSD_CREATE, TRUE) != DSS_OK)
|
||||
printf ("\nNOK\n");
|
||||
else
|
||||
{
|
||||
strcpy (Root->Manager, "Module_Manager");
|
||||
printf ("\nStructure créée : OK\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DELETE_STRUCT:
|
||||
if (DS_DataStruct_Close (Root, DSD_DESTROY) == DSS_KO) printf ("\nNOK\n");
|
||||
else
|
||||
{
|
||||
printf ("\nStructure détruite : OK\n");
|
||||
Root = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OPEN_STRUCT:
|
||||
fprintf (stdout, "\nNom de la structure à ouvrir ? ");
|
||||
gets (DataStruct_Name);
|
||||
|
||||
if (DS_DataStruct_Open (DataStruct_Name, &Root, 0, NULL, 0, DSD_OPEN, TRUE) == NDS_KO)
|
||||
printf ("\nNOK\n");
|
||||
else
|
||||
printf ("\nStructure ouverte : OK\n");
|
||||
|
||||
break;
|
||||
|
||||
case CLOSE_STRUCT:
|
||||
if (DS_DataStruct_Close (Root, DSD_CLOSE) == DSS_KO) printf ("\nNOK\n");
|
||||
else
|
||||
{
|
||||
printf ("\nStructure fermée : OK\n");
|
||||
Root = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FIND_VALUE:
|
||||
fprintf (stdout, "\nPlage de recherche (?->?) : ");
|
||||
gets (buf);
|
||||
tmp = strstr (buf, "->");
|
||||
if (tmp != NULL)
|
||||
{
|
||||
* tmp = '\0';
|
||||
n = atoi (buf);
|
||||
tmp++;
|
||||
tmp++;
|
||||
m = atoi (tmp);
|
||||
if (m < n)
|
||||
{
|
||||
printf ("\nEntrées non valides\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("\nEntrées non valides\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DS_DataStruct_Lock (Root, DSD_READ, &Locked);
|
||||
|
||||
i = n;
|
||||
j = m + 1;
|
||||
t_start (t_exec);
|
||||
while (i < j)
|
||||
{
|
||||
Module->Id = n + (random () % m);
|
||||
DS_Node_Find (Root, &Node, Module, NULL);
|
||||
i++;
|
||||
}
|
||||
t_stop (t_exec);
|
||||
|
||||
DS_DataStruct_Unlock (Root);
|
||||
|
||||
fprintf (stdout, "\n%d valeur(s) recherchée(s) en %.4f sec (%.2f select/sec)\n", \
|
||||
m - n + 1, t_exec.sec, (m - n + 1) / t_exec.sec);
|
||||
break;
|
||||
|
||||
case ADD_VALUE:
|
||||
fprintf (stdout, "\nPlage des valeurs à ajouter (?->?) : ");
|
||||
gets (buf);
|
||||
tmp = strstr (buf, "->");
|
||||
if (tmp != NULL)
|
||||
{
|
||||
* tmp = '\0';
|
||||
n = atoi (buf);
|
||||
tmp++;
|
||||
tmp++;
|
||||
m = atoi (tmp);
|
||||
if (m < n)
|
||||
{
|
||||
printf ("\nEntrées non valides\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("\nEntrées non valides\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DS_DataStruct_Lock (Root, DSD_WRITE, &Locked);
|
||||
|
||||
fprintf (stdout, "\nOrdre d'ajout (croissant=0 décroissant=1) ? ");
|
||||
gets (buf);
|
||||
choice = atoi (buf);
|
||||
if (choice == 0)
|
||||
{
|
||||
i = n;
|
||||
j = m + 1;
|
||||
t_start (t_exec);
|
||||
while (i < j)
|
||||
{
|
||||
if (DS_Value_Alloc (Root, (void **)&Module, "x", i) == NDS_OK) DS_Value_Add (Root, Module);
|
||||
i++;
|
||||
}
|
||||
t_stop (t_exec);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = m;
|
||||
j = n - 1;
|
||||
t_start (t_exec);
|
||||
while (i > j)
|
||||
{
|
||||
if (DS_Value_Alloc (Root, (void **)&Module, "x", i) == NDS_OK) DS_Value_Add (Root, Module);
|
||||
i--;
|
||||
}
|
||||
t_stop (t_exec);
|
||||
}
|
||||
|
||||
DS_DataStruct_Unlock (Root);
|
||||
|
||||
fprintf (stdout, "\n%d valeur(s) ajoutée(s) en %.4f sec (%.2f ajouts/sec)\n", m - n + 1, \
|
||||
t_exec.sec, (m - n + 1) / t_exec.sec);
|
||||
break;
|
||||
|
||||
case REMOVE_VALUE:
|
||||
Nb_Removed = 0;
|
||||
fprintf (stdout, "\nPlage des valeurs à supprimer (?->?) : ");
|
||||
gets (buf);
|
||||
tmp = strstr (buf, "->");
|
||||
if (tmp != NULL)
|
||||
{
|
||||
* tmp = '\0';
|
||||
n = atoi (buf);
|
||||
tmp++;
|
||||
tmp++;
|
||||
m = atoi (tmp);
|
||||
if (m < n)
|
||||
{
|
||||
printf ("\nEntrées non valides\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("\nEntrées non valides\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DS_DataStruct_Lock (Root, DSD_WRITE, &Locked);
|
||||
|
||||
fprintf (stdout, "\nOrdre de suppression (croissant=0 décroissant=1) ? ");
|
||||
gets (buf);
|
||||
choice = atoi (buf);
|
||||
if (choice == 0)
|
||||
{
|
||||
i = n;
|
||||
j = m + 1;
|
||||
t_start (t_exec);
|
||||
while (i < j)
|
||||
{
|
||||
Ref_Module.Id = i;
|
||||
if (DS_Value_Remove (Root, &Ref_Module, (void **)&Module) == NDS_OK)
|
||||
{
|
||||
DS_Value_Free (Root, Module);
|
||||
Nb_Removed++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
t_stop (t_exec);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = m;
|
||||
j = n - 1;
|
||||
t_start (t_exec);
|
||||
while (i > j)
|
||||
{
|
||||
Ref_Module.Id = i;
|
||||
if (DS_Value_Remove (Root, &Ref_Module, (void **)&Module) == NDS_OK)
|
||||
{
|
||||
DS_Value_Free (Root, Module);
|
||||
Nb_Removed++;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
t_stop (t_exec);
|
||||
}
|
||||
|
||||
DS_DataStruct_Unlock (Root);
|
||||
|
||||
fprintf (stdout, "\n%d valeur(s) supprimée(s) en %.4f sec (%.2f suppressions/sec)\n",\
|
||||
Nb_Removed, t_exec.sec, (m - n + 1) / t_exec.sec);
|
||||
break;
|
||||
|
||||
case CHG_LIST_TYPE:
|
||||
fprintf (stdout, "\nType de liste (FIFO=0 ; FILO=1 ; triée=2) ? ");
|
||||
gets (buf);
|
||||
choice = atoi (buf);
|
||||
DS_DataStruct_Lock (Root, DSD_WRITE, &Locked);
|
||||
switch (choice)
|
||||
{
|
||||
case 0:
|
||||
Root->Type = NDD_DS_LIST | NDD_MN_FIFO;
|
||||
break;
|
||||
case 1:
|
||||
Root->Type = NDD_DS_LIST | NDD_MN_FILO;
|
||||
break;
|
||||
case 2:
|
||||
Root->Type = NDD_DS_LIST | NDD_MN_ORDERED;
|
||||
break;
|
||||
default:
|
||||
printf ("\nChoix non valide\n");
|
||||
break;
|
||||
}
|
||||
DS_DataStruct_Unlock (Root);
|
||||
break;
|
||||
|
||||
case REORG:
|
||||
t_start (t_exec);
|
||||
DS_DataStruct_Lock (Root, DSD_WRITE, &Locked);
|
||||
DS_DataStruct_Reorg (Root);
|
||||
DS_DataStruct_Unlock (Root);
|
||||
t_stop (t_exec);
|
||||
fprintf (stdout, "\nRéorganisation de la structure en %.4f sec\n", t_exec.sec);
|
||||
break;
|
||||
|
||||
case CONVERT_TO_LIST:
|
||||
t_start (t_exec);
|
||||
DS_DataStruct_Lock (Root, DSD_WRITE, &Locked);
|
||||
DS_DataStruct_Convert (Root, NDD_DS_LIST | NDD_MN_ORDERED);
|
||||
DS_DataStruct_Unlock (Root);
|
||||
t_stop (t_exec);
|
||||
fprintf (stdout, "\nConversion arbre vers liste en %.4f sec\n", t_exec.sec);
|
||||
break;
|
||||
|
||||
case CONVERT_TO_TREE:
|
||||
t_start (t_exec);
|
||||
DS_DataStruct_Lock (Root, DSD_WRITE, &Locked);
|
||||
DS_DataStruct_Convert (Root, NDD_DS_TREE | NDD_MN_AUTO_EQU);
|
||||
DS_DataStruct_Unlock (Root);
|
||||
t_stop (t_exec);
|
||||
fprintf (stdout, "\nConversion liste vers arbre en %.4f sec\n", t_exec.sec);
|
||||
break;
|
||||
|
||||
case INFO:
|
||||
DS_DataStruct_Lock (Root, DSD_READ, &Locked);
|
||||
DS_DataStruct_Info_Print (Root, stdout);
|
||||
DS_DataStruct_Unlock (Root);
|
||||
break;
|
||||
|
||||
case SHOW:
|
||||
DS_DataStruct_Lock (Root, DSD_READ, &Locked);
|
||||
DS_DataStruct_Dump (Root, stdout);
|
||||
DS_DataStruct_Unlock (Root);
|
||||
break;
|
||||
|
||||
case CHECK:
|
||||
Nb_Corrected = Nb_Detected = 0;
|
||||
ND_DataStruct_Check (Root, &Nb_Detected, &Nb_Corrected, stderr);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (stdout, "\nChoix %d non défini\n", choice);
|
||||
}
|
||||
choice = print_menu (Root);
|
||||
}
|
||||
DS_Library_Close ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
NDT_Status Module_Manager (va_list Args)
|
||||
{
|
||||
NDT_Command Command = (NDT_Command) va_arg (Args, NDT_Command);
|
||||
|
||||
if (Command == NDD_CMD_MAKE_VALUE)
|
||||
{
|
||||
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
||||
T_Module ** Module = va_arg (Args, T_Module **);
|
||||
va_list Value_Args = va_arg (Args, va_list);
|
||||
char * Nom = va_arg (Value_Args, char *);
|
||||
int Id = va_arg (Value_Args, int);
|
||||
if (DS_Alloc (Root, sizeof (T_Module) + strlen (Nom) + 1, (void **)Module) == DSS_OK)
|
||||
{
|
||||
(* Module)->Id = Id;
|
||||
(* Module)->Nom = (char *)((size_t)(*Module) + sizeof (T_Module));
|
||||
strcpy ((* Module)->Nom, Nom);
|
||||
}
|
||||
return (NDS_OK);
|
||||
}
|
||||
|
||||
if (Command == NDD_CMD_PRINT_VALUE)
|
||||
{
|
||||
T_Module * Module = (T_Module *) va_arg (Args, void *);
|
||||
FILE * Out = va_arg (Args, FILE *);
|
||||
fprintf (Out, "Id Module=%d Nom Module='%s'", Module->Id, Module->Nom);
|
||||
return (NDS_OK);
|
||||
}
|
||||
|
||||
if (Command == NDD_CMD_DELETE_VALUE)
|
||||
{
|
||||
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
||||
T_Module * value = (T_Module *) va_arg (Args, void *);
|
||||
DS_Free (Root, value);
|
||||
return (NDS_OK);
|
||||
}
|
||||
|
||||
if (Command == NDD_CMD_PRINT_INFO)
|
||||
{
|
||||
NDT_Root * Root = va_arg (Args, NDT_Root *);
|
||||
FILE * Out = va_arg (Args, FILE *);
|
||||
char * Root_Type;
|
||||
DST_RootDesc * RootDesc;
|
||||
|
||||
switch ((int)(Root->Type & NDD_DS_MSK))
|
||||
{
|
||||
case NDD_DS_LIST :
|
||||
switch ((int)(Root->Type & NDD_MN_MSK))
|
||||
{
|
||||
case NDD_MN_ORDERED : Root_Type = strdup ("liste triée"); break;
|
||||
case NDD_MN_FILO : Root_Type = strdup ("liste FILO"); break;
|
||||
case NDD_MN_FIFO : Root_Type = strdup ("liste FIFO"); break;
|
||||
default: Root_Type = strdup ("inconnu"); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NDD_DS_TREE :
|
||||
switch ((int)(Root->Type & NDD_MN_MSK))
|
||||
{
|
||||
case NDD_MN_AUTO_EQU : Root_Type = strdup ("arbre auto-équilibré"); break;
|
||||
default: Root_Type = strdup ("arbre non auto-équilibré"); break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: Root_Type = strdup ("inconnu"); break;
|
||||
}
|
||||
|
||||
RootDesc = (DST_RootDesc *)(Root->User);
|
||||
fprintf (Out, \
|
||||
"\nStructure de type %s :\n\t- Nom = %s\n\t- Manager = %s\n\t- Nombre de modules = %ld\n", \
|
||||
Root_Type, RootDesc->Heap_Name, RootDesc->Manager_FileName, Root->Node_Number);
|
||||
|
||||
if ((Root->Type & NDD_DS_MSK) == NDD_DS_TREE)
|
||||
fprintf (Out, "\t- Profondeur maxi = %ld\n\t- Profondeur mini = %ld\n\t- Différence maximale autorisée = %ld\n\t- Nombre d'équilibrages = %ld\n", \
|
||||
Root->Max_Depth, Root->Min_Depth, Root->Max_Dif, Root->Nb_Equ);
|
||||
|
||||
if (Root_Type) free (Root_Type);
|
||||
|
||||
return (NDS_OK);
|
||||
}
|
||||
|
||||
if (Command == NDD_CMD_COMP_VALUE)
|
||||
{
|
||||
T_Module * Value1, * Value2;
|
||||
long comp;
|
||||
|
||||
Value1 = (T_Module *) va_arg (Args, void *);
|
||||
Value2 = (T_Module *) va_arg (Args, void *);
|
||||
va_end (Args);
|
||||
comp = Value1->Id - Value2->Id;
|
||||
if (comp < 0) return NDS_LOWER;
|
||||
if (comp > 0) return NDS_GREATER;
|
||||
return NDS_EQUAL;
|
||||
}
|
||||
return (NDS_OK);
|
||||
}
|
||||
|
||||
void init_menu ( NDT_Root * Root )
|
||||
{
|
||||
sprintf (menu, "Menu :\n");
|
||||
sprintf (buf, " - %d) %-30s\n", QUIT, "Quitter");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s", CREATE_STRUCT, "Création de structure");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", OPEN_STRUCT, "Ouverture de structure");
|
||||
strcat (menu, buf);
|
||||
if (Root != NULL)
|
||||
{
|
||||
sprintf (buf, " - %d) %-30s", CLOSE_STRUCT, "Fermer la structure");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", DELETE_STRUCT, "Détruire la structure");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s", ADD_VALUE, "Ajout de valeurs");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", REMOVE_VALUE, "Suppression de valeurs");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", FIND_VALUE, "Recherche de valeurs aléatoires");
|
||||
strcat (menu, buf);
|
||||
if (ND_IS_LIST(Root))
|
||||
{
|
||||
sprintf (buf, " - %d) %-30s", CHG_LIST_TYPE, "Changement de type de liste");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", CONVERT_TO_TREE, "Conversion en arbre");
|
||||
strcat (menu, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (buf, " - %d) %-30s", CONVERT_TO_LIST, "Conversion en liste triée");
|
||||
strcat (menu, buf);
|
||||
}
|
||||
sprintf (buf, " - %d) %-30s\n", REORG, "Réorganisation");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s", INFO, "Informations sur la structure");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", SHOW, "Affichage de la structure");
|
||||
strcat (menu, buf);
|
||||
sprintf (buf, " - %d) %-30s\n", CHECK, "Vérification de la structure");
|
||||
strcat (menu, buf);
|
||||
}
|
||||
}
|
||||
|
||||
int print_menu ( NDT_Root * Root )
|
||||
{
|
||||
init_menu (Root);
|
||||
fprintf (stdout, "\n---------------------------------------------------------\n");
|
||||
fprintf (stdout, menu);
|
||||
buf [0] = '\0';
|
||||
while (buf [0] == '\0')
|
||||
{
|
||||
printf ("\nChoice ? ");
|
||||
gets (buf);
|
||||
}
|
||||
return atoi (buf);
|
||||
}
|
||||
BIN
util/dsbench.xls
Normal file
BIN
util/dsbench.xls
Normal file
Binary file not shown.
51
util/dsdump.c
Normal file
51
util/dsdump.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#define SM_MODE 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <node.h>
|
||||
#include <shmem.h>
|
||||
#include <datastr.h>
|
||||
|
||||
int main (int argc, char ** argv)
|
||||
{
|
||||
NDT_Node * Node;
|
||||
|
||||
SM_Library_Open (0, NULL, SMD_OPEN | SMD_DEBUG_ALL);
|
||||
|
||||
ND_Node_First_Get (SM_Base->MHR, &Node);
|
||||
|
||||
while (Node)
|
||||
{
|
||||
char * ptr;
|
||||
SMT_MHH * MHH = ( SMT_MHH *)(Node->Value);
|
||||
|
||||
if ((ptr = strstr (MHH->Name, "DATASTR/")) != NULL)
|
||||
{
|
||||
int Locked;
|
||||
SMT_Heap * Heap;
|
||||
SMT_DSH * DSH;
|
||||
NDT_Root * Root;
|
||||
DST_RootDesc * RootDesc;
|
||||
|
||||
SM_Heap_Open (ptr, &Heap, 0, SMD_OPEN | SMD_READ, &Locked);
|
||||
|
||||
DSH = ( SMT_DSH *)(MHH->DSR->Head->Value);
|
||||
|
||||
Root = ( NDT_Root *)((size_t)(DSH->Start) + sizeof (NDT_Node) + sizeof (SMT_Chunk));
|
||||
RootDesc = (DST_RootDesc *)(Root->User);
|
||||
|
||||
fprintf (stdout, "Data Structure \"%s\":\n\t- Manager = %s\n\t- Open semaphore = %d\n", ptr + strlen ("datastr/"), RootDesc->Manager_FileName, RootDesc->OpenSemID);
|
||||
|
||||
SM_Heap_Close (Heap);
|
||||
}
|
||||
|
||||
ND_Node_Next_Get (Node, &Node);
|
||||
}
|
||||
|
||||
SM_Library_Close (SMD_CLOSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user