TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream* a, TPpToken* ppToken, bool newLineOkay) { int token; TokenStream *n; RewindTokenStream(a); do { token = ReadToken(a, ppToken); if (token == PpAtomIdentifier && LookUpSymbol(ppToken->atom)) break; } while (token != EndOfInput); if (token == EndOfInput) return a; n = new TokenStream; pushInput(new tMarkerInput(this)); pushTokenStreamInput(a); while ((token = scanToken(ppToken)) != tMarkerInput::marker) { if (token == PpAtomIdentifier && MacroExpand(ppToken->atom, ppToken, false, newLineOkay) != 0) continue; RecordToken(n, token, ppToken); } popInput(); delete a; return n; }
Compiler::~Compiler() { while( inFiles.size() ) popInput(); for( FileNameIter iter = fileNames.begin(); iter != fileNames.end(); ++iter) delete *iter; }
// Macro-expand a macro argument 'arg' to create 'expandedArg'. // Does not replace 'arg'. // Returns nullptr if no expanded argument is created. TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken* ppToken, bool newLineOkay) { // expand the argument TokenStream* expandedArg = new TokenStream; pushInput(new tMarkerInput(this)); pushTokenStreamInput(arg); int token; while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) { token = tokenPaste(token, *ppToken); if (token == tMarkerInput::marker || token == EndOfInput) break; if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0) continue; expandedArg->putToken(token, ppToken); } if (token == EndOfInput) { // MacroExpand ate the marker, so had bad input, recover delete expandedArg; expandedArg = nullptr; } else { // remove the marker popInput(); } return expandedArg; }
TPpContext::~TPpContext() { for (TSymbolMap::iterator it = symbols.begin(); it != symbols.end(); ++it) delete it->second->mac.body; mem_FreePool(pool); delete [] preamble; // free up the inputStack while (! inputStack.empty()) popInput(); }
Lexer::Token Compiler::getNextToken() { Lexer::Token tok( lexer->lex( inFiles[inFiles.size() - 1] )); if( parseContinuously ) { while( tok == Lexer::END ) { popInput(); if( inFiles.empty() ) break; tok = lexer->lex( inFiles[inFiles.size() - 1] ); } } return tok; }
int main(int argc, char **argv){ int inputsNumber = 0; int stdIn = 0;//stdIn pas utilise input* listOfInputs = NULL;// liste des entrees a traiter int maxThreads = 0; int i; //Parcoure tous les arguments de lancement du programme for(i = 1; i < argc; i++){ char* in = argv[i]; if(strcmp(in, MAX_THREADS_TK) == 0){ //maxthreads maxThreads = atoi(argv[i+1]); i++; //on passe 2 arguments puisqu'on a deja utilise le nombre // de threads max printf("Maxthreads set to %d\n",maxThreads); } else if (strcmp(in, STDIN_TK) == 0){ //stdIn stdIn = 1; // stdIn utilise inputsNumber++; printf("Stdin set \n"); } else if (strcmp(in, FILE_TK) == 0){ //fichier if(pushInput(&listOfInputs, argv[i+1]) != 0){ //probleme de malloc, arrete le programme exit(errno); } else{ printf("Added %s to inputs\n", argv[i+1]); i++; inputsNumber++; } } else if(strstr(in, URL_TK) != NULL){ //URL if(pushInput(&listOfInputs, argv[i]) != 0){ //probleme de malloc, arrete le programme exit(errno); } else{ printf("Added %s to inputs\n", argv[i]); inputsNumber++; } } else{ //erreur de format fprintf(stderr, "Erreur: mauvais format"); exit(-1); } } printf("Number of inputs %d\n", inputsNumber); if(maxThreads == 0){ /// a voir maxThreads = 10; printf("maxthread was 0, assigned to %d\n", maxThreads); } //initialisation des threads et semaphores pthread_t* threads; //threads utilises threads = (pthread_t*) malloc(sizeof(pthread_t) * maxThreads); sem_init(&available_switching, 0, 1); //switching disponible sem_init(&available_thread, 0, 0); // aucun thread n'a termine available_thread_index = -1; //lance tous les threads int err = launchAllThreads(maxThreads, &stdIn, &inputsNumber, &listOfInputs, &threads); if(err){ fprintf(stderr, "Erreur dans launchAllThreads: %d\n", err); exit(err); } printf("All threads launched, inputs left: %d\n", inputsNumber); setbuf(stdout, NULL); // stoppe le buffer while(inputsNumber > 0){ printf("Rentre ici \n"); sem_wait(&available_thread); // attend qu'un thread ait termine //zone critique printf("Zone critique\n"); err = pthread_join(threads[available_thread_index], NULL); if(err){ fprintf(stderr, "Erreur dans pthread_join: %d\n", err); exit(err); } char* file = popInput(&listOfInputs); printf("filename: %s\n", file); if (file == NULL){ fprintf(stderr, "Erreur dans popInput\n"); exit(-1); } thread_arg t_arg; t_arg.file = file; t_arg.fileType = getFileType(file); t_arg.threadIndex = available_thread_index; printf("switching producer number: %d , now on %s \n", available_thread_index, file); err = pthread_create(&threads[available_thread_index], NULL, &threadLauncher, &t_arg); if(err){ fprintf(stderr, "Erreur dans pthread_create: %d\n", errno); exit(errno); } available_thread_index = -1; // pas necessaire mais plus prudent inputsNumber--; sem_post(&available_switching); //permet aux thread de signaler //qu'ils ont fini } ///TODO every producer to consumer //free(threads); //ne pas oublier ! exit(EXIT_SUCCESS); }
/** * launchAllThreads * Cette fonction lance maxthreads threads en alternant entre producteur * et consommteur * @param: maxThreads, nombre max de threads a lancer * @param: stdIn, pointeur vers un entier indiquant si l'entree standard * est utilisee * @param: inputsNumber, pointeur vers un entier indiquant le nombre * d'entree restant a traiter * @param: listOfInputs, pointeur vers une liste contenant les fichiers * d'entree * @param: threads, pointeur vers un tableau de threads * @return: 0 si pas d'erreur, valeur differente de 0 sinon **/ int launchAllThreads(int maxThreads, int* stdIn, int* inputsNumber, input** listOfInputs, pthread_t** threads){ const int ALT_PRODUCER = 1; const int ALT_CONSUMER = 0; int alternator = ALT_PRODUCER; //lance les threads alternativement (producteur, consommateur, // producteur...) int threadIndex; for(threadIndex = 0; threadIndex < maxThreads; threadIndex++){ //lance tous les threads if(alternator == ALT_PRODUCER && *inputsNumber > 0){ //mode producteur thread_arg t_arg; if(*stdIn == 1){ //on traite toujoours stdin en premier, cela permet //a l'utilisateur de ne pas attendre un thread disponible //pour les entrees via la console t_arg.file = NULL; *stdIn = 0; //stdIn traite printf("stdIn bien lance\n"); } else{ char* file = popInput(listOfInputs); if(file != NULL){ t_arg.file = file; printf("file bien lance\n"); } else { fprintf(stderr, "Erreur, plus de fichier a traiter\n"); return(-1); } } t_arg.fileType = getFileType(t_arg.file); t_arg.threadIndex = threadIndex; //lance le thread if(pthread_create(threads[threadIndex], NULL, &threadLauncher, &t_arg)){ fprintf(stderr, "Error creating thread: %d\n", errno); return(errno); } (*inputsNumber)--; //passe en mode consommateur pour le prochain thread alternator = ALT_CONSUMER; } else { //mode consommateur //lance le thread if(pthread_create(threads[threadIndex], NULL, &threadLauncher, NULL)){ fprintf(stderr, "Error creating thread: %d\n", errno); return(errno); } //passe en mode producteur pour le prochain thread printf("consommateur bien lance\n"); alternator = ALT_PRODUCER; } }/// fin du for qui lance tous les threads return 0; }