Esempio n. 1
0
void CharacterState_setCurrentScheme (SCharacterState *characterState, unsigned value) {
	assert(characterState != NULL);
	if (value >= characterState->schemeSize) {
		Log_output(1, "Error: Attempt to set %u value to current index of a %u-sized table\n",
				   value, characterState->schemeSize);
		exit (EXIT_FAILURE);
	}
	characterState->currentScheme = value;
}
Esempio n. 2
0
static void Log_posttrace(int log_level, traceEntry* cur_entry)
{
	if (((trace_output_level == -1) ? log_level >= trace_settings.trace_level : log_level >= trace_output_level))
	{
		char* msg = NULL;

		if (trace_destination || trace_callback)
			msg = &Log_formatTraceEntry(cur_entry)[7];

		Log_output(log_level, msg);
	}
}
Esempio n. 3
0
int Log_initialize(Log_nameValue* info)
{
	int rc = -1;
	char* envval = NULL;

	if ((trace_queue = malloc(sizeof(traceEntry) * trace_settings.max_trace_entries)) == NULL)
		return rc;
	trace_queue_size = trace_settings.max_trace_entries;

	if ((envval = getenv("MQTT_C_CLIENT_TRACE")) != NULL && strlen(envval) > 0)
	{
		if (strcmp(envval, "ON") == 0 || (trace_destination = fopen(envval, "w")) == NULL)
			trace_destination = stdout;
		else
		{
			trace_destination_name = malloc(strlen(envval) + 1);
			strcpy(trace_destination_name, envval);
			trace_destination_backup_name = malloc(strlen(envval) + 3);
			sprintf(trace_destination_backup_name, "%s.0", trace_destination_name);
		}
	}
	if ((envval = getenv("MQTT_C_CLIENT_TRACE_MAX_LINES")) != NULL && strlen(envval) > 0)
	{
		max_lines_per_file = atoi(envval);
		if (max_lines_per_file <= 0)
			max_lines_per_file = 1000;
	}
	if ((envval = getenv("MQTT_C_CLIENT_TRACE_LEVEL")) != NULL && strlen(envval) > 0)
	{
		if (strcmp(envval, "MAXIMUM") == 0 || strcmp(envval, "TRACE_MAXIMUM") == 0)
			trace_settings.trace_level = TRACE_MAXIMUM;
		else if (strcmp(envval, "MEDIUM") == 0 || strcmp(envval, "TRACE_MEDIUM") == 0)
			trace_settings.trace_level = TRACE_MEDIUM;
		else if (strcmp(envval, "MINIMUM") == 0 || strcmp(envval, "TRACE_MEDIUM") == 0)
			trace_settings.trace_level = TRACE_MINIMUM;
		else if (strcmp(envval, "PROTOCOL") == 0  || strcmp(envval, "TRACE_PROTOCOL") == 0)
			trace_output_level = TRACE_PROTOCOL;
		else if (strcmp(envval, "ERROR") == 0  || strcmp(envval, "TRACE_ERROR") == 0)
			trace_output_level = LOG_ERROR;
	}
	Log_output(TRACE_MINIMUM, "=========================================================");
	Log_output(TRACE_MINIMUM, "                   Trace Output");
	if (info)
	{
		while (info->name)
		{
			sprintf(msg_buf, "%s: %s", info->name, info->value);
			Log_output(TRACE_MINIMUM, msg_buf);
			info++;
		}
	}
#if !defined(WIN32)
	struct stat buf;
	if (stat("/proc/version", &buf) != -1)
	{
		FILE* vfile;

		if ((vfile = fopen("/proc/version", "r")) != NULL)
		{
			int len;

			strcpy(msg_buf, "/proc/version: ");
			len = strlen(msg_buf);
			if (fgets(&msg_buf[len], sizeof(msg_buf) - len, vfile))
				Log_output(TRACE_MINIMUM, msg_buf);
			fclose(vfile);
		}
	}
#endif
	Log_output(TRACE_MINIMUM, "=========================================================");

	return rc;
}
Esempio n. 4
0
/**
 * @brief Main function
 * @param argc Number of arguments
 * @param **argv The arguments
 * @return EXIT_SUCCESS on success, EXIT_FAILURE on failure
 */
int 
main (int argc, char ** argv)
{
    unsigned i;
    int *process_pinning = NULL;
	int status;
	pid_t pid;
	unsigned nbprocess;
	SPipe *pipes;
	int res;
	int isOpenMP = 0;
	int iterationsDoneAlready = 0;
	unsigned currentExecRepet;
	unsigned execRepets, kernelId, nbKernels;
	
	printf("*************************************************************************************************\n");
	printf("* |\\   /|   '    ____  ____   ____          ____                    ____           ____  ____\t*\n");
	printf("* | \\ / |   |   |     |____| |    | |      |____|  |    |  | \\  |  |      |____|  |____ |____|\t*\n");
	printf("* |  '  |   |   |____ |   \\  |____| |____  |    |  |____|  |  \\ |  |____  |    |  |____ |   \\\t*\n");
	printf("*\t\t\t\t\t\t\t\t\t\t\t\t*\n");
	printf("*************************************************************************************************\n");

    /* Handle options */
    if (Option_handleHelpRequest (argc, argv) == 0)
    {
        return EXIT_SUCCESS;
	}

    /* Before anything, handle signal */
    pushSignalHandler (SignalHandler_microlauncher);
    
    fprintf (stderr, "ML Start %d\n", getpid ());
    Log_setOutput (stderr);
    Log_setVerbosity (8);
	
	/* Then, we need to generate the program data description */
    SDescription *desc = Description_create ();
    /* Next set Log to stderr */

    // Handle options
    Option_handleCommandLine (desc, argc, argv);
    
    /* Now that we have handled user customed values, let's set unset values to our defaults */
    Description_setDefaults (desc);
	
    // Arguments verification
    if (Description_AssertValues (desc) == -1) {
    	Log_output (-1, "Error: Exiting Microlauncher now...\n");
    	exit (EXIT_FAILURE);
    }
    
    // Warn the user
    Description_ShowWarnings (desc);

    // If the file PATH_TO_KILL exists, cancel the program (sleep_tight.h)
    escape_from_scary_killers ();
    
    /* If current architecture isn't good for us */
    if (sizeof (unsigned long long) != 8)
    {
        Log_output (-1, "Error: Unsigned long long size != 64 bit ! Exiting...\n");
        exit (EXIT_FAILURE);
    }

	/* Prepare the sleep tight signals */
	if (sleep_tight_preparesignals() != 0)
	{
		Log_output (-1, "Error! Could not prepare Sleep Tight's signals! Aborting.\n");
		exit(EXIT_FAILURE);
	}

	/* Now that the desc values have been all handled, we save them for possible resuming request */
	resumeSave (desc);

	/* Allocate data for the pipes and process pinning */
	nbprocess = Description_getNbProcess (desc);
	pipes = malloc (sizeof (*pipes) * nbprocess);
	assert (pipes != NULL);
	memset (pipes, 0, sizeof (*pipes) * nbprocess);
	
	/* Allocate process pinning table only if we're not in OpenMP mode as this mode doesn't pin CPUs */
	isOpenMP = Description_getOmpPath (desc) != NULL;
	if (!isOpenMP)
	{
		process_pinning = malloc (sizeof (*process_pinning) * nbprocess);
		assert(process_pinning != NULL);
		memset (process_pinning, 0, sizeof (*process_pinning) * nbprocess);
		/* Process pinning initialization */
		for (i = 0; i < nbprocess ; i++)
		{
            Log_output (-1, "Getting pinning %d: %d\n", i, Description_getPinningAt (desc, i));
            process_pinning[i] = Description_getPinningAt (desc, i);
		}
	}
	
	/* Get the father aware of the number of experiments to be done by its children */
	Description_setExperimentNumber (desc, getExperimentNumber (desc));
	
	execRepets = Description_getExecuteRepets (desc);
	if (Description_getExecFileName (desc) != NULL)
	{
		nbKernels = 1;
	}
	else
	{
		nbKernels = Description_getKernelFileNamesTabSize (desc);
	}
	
	/* Multiple kernels handling */
	for (kernelId = 0; kernelId < nbKernels; kernelId++)
	{
		if (Description_getExecFileName (desc) == NULL)
		{
			/* Setting the current kernel name to the current id we're running */
			Description_setKernelCurrentFileId (desc, kernelId);
			Log_output (-1, "Current Kernel Execution : %s\n", Description_getKernelFileName (desc));
		}
		
		/* Re-init to last known currentExecRepet value if we're resuming */
		if (resumeInitCounter (&currentExecRepet, desc->temp_values.current_execute_repet))
		{
			Log_output (-1, "Note: Resuming to last --executerepet value : %d\n", currentExecRepet);
		}
		else
		{
			currentExecRepet = 0;
		}
		
		/* Repeats Microlauncher --executerepet (argument) times */
		for (; currentExecRepet < execRepets; currentExecRepet++)
		{
			if (resumeIsResuming ())
			{
				resumeLoadCounters (desc);
			}
		
			/* If more than 1 execution repeat, get the user aware of current iteration */
			if (execRepets > 1)
			{
				Log_output (-1, "\n\nMicrolaunch Repeat #%d\n", currentExecRepet+1);
			}
		
			/* Input file compilation */
			compileInputFile (desc);
		
			/* Processes launch */
            fprintf (stderr, "ML: %d -> Creating %d\n", getpid (), nbprocess);
			for (i = 0; i < nbprocess ; i++)
			{
				Pipe_generate (&pipes[i]);
				pid = fork ();

				if (pid == 0)
				{
                    fprintf (stderr, "ML: %d: Creating son: %d\n", getppid (), getpid ());
                    //Start formatting strings: for the moment just exec arguments, exec name, and exec path
                    Description_reformatStrings (desc, i);

                    //If we must change directory
                    char *res = Description_getExecPath (desc);

                    if (res != NULL)
                    {
                        int chroot_res = chdir (res);
                        if (chroot_res != 0)
                        {
                            perror ("");
                            exit (EXIT_FAILURE);
                        }
                    }

					/* Push the signal handler : We're now in the child function */
					pushSignalHandler (SignalHandler_child);

					/* Defines the process Id */
					Description_setProcessId (desc, i);
				
					/* By default, we enable the printing and eval handling stuff for the first child */
					if(i == 0 || Description_getAllPrintOut (desc) != 0)
					{
					    Description_printingProcessEnable (desc);
						Description_processEvalHandlerEnable (desc);
					}

					/* If we have allprocess-output argument, then every process compute its counters */
					if (Description_isAllProcessOutputEnabled (desc))
					{
						Description_processEvalHandlerEnable (desc);
					}
			
					/* If we're not in OpenMP mode and we do pin the threads, we pin the processes on the machine's cores */
					if (isOpenMP == 0 && Description_isThreadPinningEnabled (desc) != 0)
					{
						if (!Description_isCpuPinDefined (desc))
						{
							Description_setCPUDest (desc, process_pinning[i]);
						}

						//Pin CPU
						if (Description_pinCPU (desc) == -1)
						{
							abort ();
						}
					}
			
					/* We save the pipes in the description for barrierS future calls (see benchmark.c) */
					Description_setTubeSF (desc,pipes[i].sf);
					Description_setTubeFS (desc,pipes[i].fs);

					//Close the unused sides of pipes
					Pipe_closeChildUnusedSide ( &pipes[i] );
			
					/* Are we launching an executable or do we want to launch a function in
						a dynamic library ? */
					switch (Description_getSourceType (desc))
					{
						case EXECUTABLE_FILE: /* EXEC MODE */
						{
							Pipe_closeChildUnusedSide ( &pipes[i] );
							status = Benchmark_Exec (desc, currentExecRepet);
							if (status != EXIT_SUCCESS)
							{
								abort ();
							}
			
							break;
						}
						case LIBRARY_FILE:
						case SOURCE_FILE:
						case ASSEMBLY_FILE:
						case OBJECT_FILE: /* KERNEL MODE */
						{
							status = Benchmark_Wrapper (desc, currentExecRepet);
							if (status != EXIT_SUCCESS)
							{
								abort ();
							}
					
							break;
						}
						default:
							Log_output (-1, "Error: Unknown File source type, cannot launch benchmark, code %d\n", Description_getSourceType (desc));
							exit (EXIT_FAILURE);
					}
					//We have finished, close the rest
					Pipe_closeChildUsedSide ( &pipes[i] );

					// Take away the signal handler (child)
					popSignalHandler ();
			
					/* Son free stuff */
					if (!isOpenMP)
					{
						free(process_pinning), process_pinning = NULL;
					}
					free(pipes), pipes = NULL;

					int isPrintingProcess = Description_isPrintingProcess (desc);
					//Destroy description
					Description_destroy (desc), desc = NULL;

					if (isPrintingProcess)
					{
						Log_output (-1, "Child process exiting now...\n");
					}
				
					// Take away the signal handler (father)
					popSignalHandler ();
					exit (EXIT_SUCCESS);
				}
				else if(pid < 0)
				{
					perror("fork");
					exit(EXIT_FAILURE);
				}
				else
				{
					/* Close non-used side of each pipe */
					Pipe_closeFatherUnusedSide ( &pipes[i] );
				}
			}
	
			if (resumeIsResuming ())
			{
				iterationsDoneAlready = desc->temp_values.curruns;
			}
			else
			{
				iterationsDoneAlready = 0;
			}

			/* Setting up the father Barrier */
			unsigned max = benchmarkIterationsNumber (desc, iterationsDoneAlready);
			for (i = 0 ; i < max ; i++)
			{
				barrierF (pipes, nbprocess);
			}

			/* Close the rest of the pipes */
			for (i = 0 ; i < nbprocess ; i++)
			{
				Pipe_closeFatherUsedSide ( &pipes[i] );
			}
	
			/* Child processes wait */
			for (i = 0 ; i < nbprocess ; i++)
			{
				waitpid (-1, &status, 0);
				res = WEXITSTATUS(status);
				if(res != EXIT_SUCCESS)
				{
					Log_output (-1, "Child exited with status %d, an error occured.\n", res);
				}
				if (WIFEXITED(status) == 0)
				{
					char buf[512];
			
					snprintf (buf, 512, "Error: Child %d received a signal ", i);
					psignal (WTERMSIG (status), buf);
				}
			}
			desc->temp_values.current_execute_repet++;
			/*	Disabling resume in the innermost loop of the father process
				because resuming has to be done just for the first iteration of each process loops */
			resumeDisableResuming ();
		}
	}
	
	/* Job is done, let's create a file to tell the user so */
	resumeSignalJobDone (desc);
	
	/* Free data */
	free (pipes), pipes = NULL;
	if (!isOpenMP)
	{
		free (process_pinning), process_pinning = NULL;
	}
	
	if (Description_isSummaryEnabled (desc))
	{
		if (generateSummary (desc) != -1) {
			Log_output (-1, "Info: A summary.xls file has been created in the %s folder.\n", Description_getOutputPath (desc));
		} else {
			Log_output (-1, "Error: An error occured while creating summary file.\n");
		}
	}
	
	Description_destroy ( desc );
	
	Log_output(-1, "Father process exiting now...\n");
	
	//Take away the signal handler
	popSignalHandler ();

	return EXIT_SUCCESS;
}
Esempio n. 5
0
/**
 * @brief Arguments handling : All the parameters of the program are handled here (expect from the special arguments which are handled before)
 *
 * @param desc the Description we are about to change to handle the special args
 * @param argc the number of arguments passed to the program
 * @param argv the strings table of arguments passed to the program
 */
static inline void Option_handleArguments (SDescription *desc, int argc, char *argv[])
{
	char *configFileName = Description_getConfigFile (desc);
	long val;
	int opt;
	FILE *f;
	unsigned m_nb_args;
	char **m_argv;
	
	// First, we have to parse the XML config file
	if (configFileName != NULL)
	{
		if (Config_parseXML (desc, configFileName) == -1)
		{
			Log_output (-1, "Error: An error occured while parsing the XML config file.\n");
			exit (EXIT_FAILURE);
		}
	}
	
	// Then, we can now handle other arguments in the command line
	optind = 1;

	/* Then, the final values have to be those of the command line */
	while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) {
		switch (opt) {
		case 'a': // --summary
			Description_enableSummary(desc);
			break;
		case 'A': // --alloclib
			Description_setDynAllocLib(desc, optarg);
			break;
		 case 'b': // --basename
			Description_setBaseName (desc, optarg);
			break;
		 case 'B': // --verifylib
			Description_setVerificationLibraryName (desc, optarg);
			break;
		case 'c': // --cpupin
            parseCPUPinning (desc, optarg);
			break;
		case 'd': // --sizedummy
			val = Option_transformArgument (optarg);
			Description_setDummySize (desc, val);
			break;
		case 'D': // --output-dir
			Description_setOutputPath (desc, optarg);
			break;
		case 'e': // --endvector
			val = Option_transformArgument (optarg);
			Description_setEndVectorSize (desc, val); 
			break;
		case 'f': // --kernelfunction
			Description_setDynamicFunctionName (desc, optarg);
			break;
		case 'F': // --no-eval-stack
			Description_disableEvalStack (desc);
			break;
		case 'g': // --output-same-dir
			Description_setOutputPath (desc, ".");
			break;
        case 'G':
            Description_setExecPath (desc, optarg);
            break;
		case 'i': // --stepvector
			val = Option_transformArgument (optarg);
			Description_setVectorSizeStep (desc, val);
			break;
		case 'I': // --info
			Description_parseInfoDisplayedInput (desc, optarg);
			break;
		case 'k': // --kernelname
			if (isFile (optarg))
			{
				Description_setKernelFileNamesTabSize (desc, 1);
				Description_setKernelFileNameAt (desc, optarg, 0);
			}
			else if (isDirectory (optarg))
			{
				parseDir (optarg, desc);
			}
			else
			{
				Log_output (-1, "Error: Cannot resolve kernel name filetype.\n");
				exit (EXIT_FAILURE);
			}
			Description_setKernelFileName (desc, optarg);
			break;
		case 'l': // --logverbosity
			val = Option_transformArgument (optarg);
			Log_setVerbosity (val);
			break;
		case 'm': // --metarepetition
			val = Option_transformArgument (optarg);
			Description_setMetaRepetition (desc, val);
			break;
		case 'M': // --vectorspacing
			val = Option_transformArgument (optarg);
			Description_setVectorSpacing (desc, val);
			break;
		case 'N': // --no-output
			Description_setPromptOutputCsv (desc, 0);
			break;
		case 'o': // --log-output
			f = fopen (optarg, "w");
			Log_setOutput (f);
			break;
		case 'O': // --nbprocess
			val = Option_transformArgument (optarg);

            if (Description_getNbProcess (desc) > 0 && Description_getNbProcess (desc) != val)
            {
                Log_output (-1, "Error: Number of processes already defined and not the same value\n");
                exit (EXIT_FAILURE);
            }
            else
            {
                if (Description_getNbProcess (desc) < 0)
                {
        			Description_setNbProcess (desc, val);
                }
            }
			break;
		case 'p': // --pagecollide
			val = Option_transformArgument (optarg);
				Description_setNbPagesForCollision (desc, val);
			break;
		case 'P': // --pagesize
			val = Option_transformArgument (optarg);
			Description_setPageSize (desc, val);
			break;
		case 'q': // --vectsurveyor
			parse_vect_surveyor (desc,optarg);
			break;	
		case 'Q': // --executerepetition
			val = Option_transformArgument (optarg);
			Description_setExecuteRepets (desc, val);
			break;
		case 'r': // --repetition
			val = Option_transformArgument (optarg);
			Description_setRepetition (desc, val);
			break;
		case 's': // --startvector
			val = Option_transformArgument (optarg);
			Description_setStartVectorSize (desc, val);
			break;
		case 'S': // --maxstride
			val = Option_transformArgument (optarg);
			Description_setMaxStride (desc, val);
			break;
		case 't': // --omppath
			Description_setOmpPath (desc, optarg);
			break;
		case 'T': // --execname
			Description_setExecFileName (desc, optarg);
			break;
		case 'u': // --execargs
			m_argv = getArgs (desc, optarg, &m_nb_args);
			Description_setExecArgc (desc, m_nb_args);
			Description_setExecArgv (desc, m_argv);
			break;
		case 'U': // --suppress-output
			Description_setSuppressOutput (desc, 1);
			break;
		case 'v': // --iteration-count
			val = Option_transformArgument (optarg);
			Description_setIterationCount (desc, val);
			Description_iterationCountEnable (desc);
			break;
		case 'V': // --execoutput
			Description_setOutputFileStream (desc, optarg);
			break;
		case 'w': // --initfunction
			Description_setKernelInitFunctionName (desc, optarg);
			break;
		case 'W': // --data-size
			/* If user specifies "float", let's allocate sizeof(float) */
			if (strncmp ("float", optarg, STRBUF_MAXLEN) == 0)
			{
				Description_setVectorElementSize (desc, sizeof (float));
			}
			/* If he specifies "double", let's allocate sizeof(double) */
			else if (strncmp ("double", optarg, STRBUF_MAXLEN) == 0)
			{
				Description_setVectorElementSize (desc, sizeof (double));
			}
			/* Else, he must have specified a numeric constant */
			else
			{
				val = Option_transformArgument (optarg);
				Description_setVectorElementSize (desc, val);
			}
			break;
		case 'x': // --nbsizes
			Description_nbSizesEnable (desc);
			parseVectorSizes (desc, optarg);
			break;
		case 'X': // --no-thread-pin
			Description_pinThreadDisable (desc);
			break;
		case 'y': // --all-print-out
			Description_setAllPrintOut (desc, 1);
			break;
		case 'Y': // --all-metric-output
			Description_allProcessOutputEnable (desc);
			break;
		case 'z': // --resumeid
			val = Option_transformArgument (optarg);
			Description_setResumeId (desc, val);
			break;
		default:
			assert (argv != NULL && argv[0] != 0);
			break;
		}
	}
}
Esempio n. 6
0
/**
 * @brief Some arguments must be handled before other, for allocation or specific purpose ; here is their handling
 *
 * @param desc the Description we are about to change to handle the special args
 * @param argc the number of arguments passed to the program
 * @param argv the strings table of arguments passed to the program
 * @return 1 if we have to abort the command line handling, 0 else
 */
static inline int Option_handleSpecialArgs (SDescription *desc, int argc, char *argv[])
{
	int opt;
	long val;

    //By default set resume to 0
    Description_setResumeId (desc, 0);
	
	// First, we have to load resume stuff if any
	optind = 1;
	while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Is the resume id specified?
		if(opt == 'z')
		{
			val = Option_transformArgument (optarg);
			Description_setResumeId (desc, val);
		}
	}
	
	optind = 1;
	while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Are we resuming?
		if(opt == 'R')
		{
			if (resumeLoad (desc) == -1 || resumeLoadCounters (desc) == -1) // Failed to resume
			{
				Log_output(-1, "Error: Failed to resume.\n");
				exit(EXIT_FAILURE);
			}
			else	// Resumed successfully
			{
				resumeEnableResuming ();
				Description_setResuming (desc, 1);
				desc->number_of_resumes++;
				Log_output (-1, "Loaded resume values successfully. (%dnth resume)\n", desc->number_of_resumes);
			}

			return 1;
		}
	}
	
	/* Special argument : Config file ; if any, we have to load it before loading other command line arglist */
	optind = 1;
	while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Check in the command line arglist
		if(opt == 'C')
		{
			Description_setConfigFile (desc, optarg);
			
			/* Then, if any, we have to parse special args before those of the command line */
			if (Config_parseXMLSpecialArgs (desc, desc->configFileName) == -1) {
				Log_output (-1, "An error occured while parsing XML config file.\n");
				exit (EXIT_FAILURE);
			}
		}
	}
	
	/* Special argument : nbVectors : it must be allocated before dealing with anything else
		(calling setNbVectors () do a lot of allocation stuff) */
	optind = 1;
	while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Check in the command line arglist
		if(opt == 'n')
		{
			val = Option_transformArgument (optarg);
			Description_setNbVectors (desc, val);
		}
	}
	
	/* Special argument : nbEvalLib : it must be allocated before dealing with anything else
		(calling setNbEvalLib () do a lot of allocation stuff) */
	optind = 1;
	while ((opt = getopt_long (argc, argv, "", option_list, NULL)) != -1) { // Check in the command line arglist
		if(opt == 'E')
		{
			Description_parseEvaluationLibraryInput (desc, optarg);
		}
	}
	
	/* In the end, if anybody defined the nbVector argument, let's define it ourself */
	if (Description_getNbVectors (desc) == DEFAULT_NB_VECTORS)
	{
		Description_setNbVectors (desc, 1);
	}
	
	return 0;
}