|  | @@ -0,0 +1,175 @@
 | 
	
		
			
				|  |  | +/* 
 | 
	
		
			
				|  |  | + * File:   parser.c
 | 
	
		
			
				|  |  | + * Author: Arthur Brandao
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Created on 31 octobre 2018
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <stdio.h>
 | 
	
		
			
				|  |  | +#include <stdlib.h>
 | 
	
		
			
				|  |  | +#include "parser.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --- Fonctions privées --- */
 | 
	
		
			
				|  |  | +int nb_commands(char* line){
 | 
	
		
			
				|  |  | +    //Initialisation variable
 | 
	
		
			
				|  |  | +    int compteur = 0;
 | 
	
		
			
				|  |  | +    //Parcours chaine pour chercher séparateur et compter le nombre de commande
 | 
	
		
			
				|  |  | +    while(*line){
 | 
	
		
			
				|  |  | +        //Si un ;
 | 
	
		
			
				|  |  | +        if(*line == ';'){
 | 
	
		
			
				|  |  | +            compteur++;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //Si | ou ||
 | 
	
		
			
				|  |  | +        else if(*line == '|'){
 | 
	
		
			
				|  |  | +            //Verif que ce n'est pas le dernier carac
 | 
	
		
			
				|  |  | +            if(*(line + 1) == '\0'){
 | 
	
		
			
				|  |  | +                return SHELL_ERR;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            //Si un || on avance de 1 en plus
 | 
	
		
			
				|  |  | +            else if(*(line + 1) == '|'){
 | 
	
		
			
				|  |  | +                //Si à la fin de la chaine
 | 
	
		
			
				|  |  | +                if(*(line + 2) == '\0'){
 | 
	
		
			
				|  |  | +                    return SHELL_ERR;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                line++;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            compteur++;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //Si un &&
 | 
	
		
			
				|  |  | +        if(*line == '&'){
 | 
	
		
			
				|  |  | +            //Si celui d'apres est bien un &&
 | 
	
		
			
				|  |  | +            if(*(line + 1) == '&'){
 | 
	
		
			
				|  |  | +                line++;
 | 
	
		
			
				|  |  | +                compteur++;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            //Sinon il doit y avoir un vide pour etre le & du bck
 | 
	
		
			
				|  |  | +            else if(*(line + 1) != '\0'){
 | 
	
		
			
				|  |  | +                return SHELL_ERR;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        line++;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Ajoute la dernière commande
 | 
	
		
			
				|  |  | +    compteur++;
 | 
	
		
			
				|  |  | +    return compteur;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Recup la 1er commande
 | 
	
		
			
				|  |  | + * @param c Structure commande à initialiser
 | 
	
		
			
				|  |  | + * @param line Ligne avec la commande
 | 
	
		
			
				|  |  | + * @return int Le décallage à effectuer dans line
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int get_command(Command* c, char* line){
 | 
	
		
			
				|  |  | +    //Declaration variable
 | 
	
		
			
				|  |  | +    char* deb = line, * old;
 | 
	
		
			
				|  |  | +    int length = 0, separator = 0, next = SHELL_NONE;
 | 
	
		
			
				|  |  | +    //Parcours chaine pour chercher un séparateur
 | 
	
		
			
				|  |  | +    while(*line){
 | 
	
		
			
				|  |  | +        //Si un ;
 | 
	
		
			
				|  |  | +        if(*line == ';'){
 | 
	
		
			
				|  |  | +            separator = 1;
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //Si | ou ||
 | 
	
		
			
				|  |  | +        else if(*line == '|'){
 | 
	
		
			
				|  |  | +            //Si 1 ou 2 |
 | 
	
		
			
				|  |  | +            if(*(line + 1) == '|'){
 | 
	
		
			
				|  |  | +                separator = 2;
 | 
	
		
			
				|  |  | +                next = SHELL_ELSE;
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                separator = 1;
 | 
	
		
			
				|  |  | +                next = SHELL_PIPE;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            break;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //Si un &&
 | 
	
		
			
				|  |  | +        if(*line == '&'){
 | 
	
		
			
				|  |  | +            //Si celui d'apres est bien un &&
 | 
	
		
			
				|  |  | +            if(*(line + 1) == '&'){
 | 
	
		
			
				|  |  | +                separator = 2;
 | 
	
		
			
				|  |  | +                next = SHELL_IF;
 | 
	
		
			
				|  |  | +                break;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        length++;
 | 
	
		
			
				|  |  | +        line++;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Verif si c'est la dernière commande
 | 
	
		
			
				|  |  | +    if(!*line){
 | 
	
		
			
				|  |  | +        next = SHELL_END;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Allocation memoire et copie chaine
 | 
	
		
			
				|  |  | +    c->cmd = malloc(sizeof(char) * (length + 1));
 | 
	
		
			
				|  |  | +    strncpy(c->cmd, deb, length);
 | 
	
		
			
				|  |  | +    c->next = next;
 | 
	
		
			
				|  |  | +    c->argc = 0;
 | 
	
		
			
				|  |  | +    //Trim et supprime l'ancienne chaine
 | 
	
		
			
				|  |  | +    old = c->cmd;
 | 
	
		
			
				|  |  | +    c->cmd = rtrim(c->cmd, ' ');
 | 
	
		
			
				|  |  | +    free(old);
 | 
	
		
			
				|  |  | +    //Retour
 | 
	
		
			
				|  |  | +    return length + separator;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/* --- Fonctions publiques --- */
 | 
	
		
			
				|  |  | +int parse_line(CommandTab* ct, char* line){
 | 
	
		
			
				|  |  | +    //Declaration variable
 | 
	
		
			
				|  |  | +    int compteur, tmp;
 | 
	
		
			
				|  |  | +    //Nettoyage ligne
 | 
	
		
			
				|  |  | +    line = trim(mtrim(line, '\n'));
 | 
	
		
			
				|  |  | +    //Compte le nombre de commande dans la ligne
 | 
	
		
			
				|  |  | +    compteur = nb_commands(line);
 | 
	
		
			
				|  |  | +    if(compteur == SHELL_ERR){
 | 
	
		
			
				|  |  | +        return SHELL_ERR;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Initialisation structure
 | 
	
		
			
				|  |  | +    ct->cmd = malloc(sizeof(Command*) * compteur);
 | 
	
		
			
				|  |  | +    ct->length = compteur;
 | 
	
		
			
				|  |  | +    //Recupération de chaque commande
 | 
	
		
			
				|  |  | +    for(int i = 0; i < compteur; i++){
 | 
	
		
			
				|  |  | +        ct->cmd[i] = malloc(sizeof(Command));
 | 
	
		
			
				|  |  | +        tmp = get_command(ct->cmd[i], line);
 | 
	
		
			
				|  |  | +        line += tmp;
 | 
	
		
			
				|  |  | +        //Si pas dernière commande on trim
 | 
	
		
			
				|  |  | +        if(i + 1 < compteur){
 | 
	
		
			
				|  |  | +            line = ltrim(line, ' ');
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Retour
 | 
	
		
			
				|  |  | +    return SHELL_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int parse_command(Command* c){
 | 
	
		
			
				|  |  | +    return 1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int parse_all_command(CommandTab* ct){
 | 
	
		
			
				|  |  | +    int tmp;
 | 
	
		
			
				|  |  | +    for(int i = 0; i < ct->length; i++){
 | 
	
		
			
				|  |  | +        tmp = parse_command(ct->cmd[i]);
 | 
	
		
			
				|  |  | +        if(tmp != SHELL_OK){
 | 
	
		
			
				|  |  | +            return SHELL_FAIL;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return SHELL_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void clean_command(CommandTab* ct){
 | 
	
		
			
				|  |  | +    //Vide le tableau
 | 
	
		
			
				|  |  | +    for(int i = 0; i < ct->length; i++){
 | 
	
		
			
				|  |  | +        //Si la commande a été parsée on vide les arguments
 | 
	
		
			
				|  |  | +        if(ct->cmd[i]->argc > 0){
 | 
	
		
			
				|  |  | +            ct->cmd[i]->name = NULL;
 | 
	
		
			
				|  |  | +            for(int j = 0; j < ct->cmd[i]->argc; j++){
 | 
	
		
			
				|  |  | +                free(ct->cmd[i]->argv[j]);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //Supprime la ligne de commande
 | 
	
		
			
				|  |  | +        free(ct->cmd[i]->cmd);
 | 
	
		
			
				|  |  | +        //Supprime la structure
 | 
	
		
			
				|  |  | +        free(ct->cmd[i]);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    //Met à 0 la taille du tableau
 | 
	
		
			
				|  |  | +    ct->length = 0;
 | 
	
		
			
				|  |  | +}
 |