token_stream_t convert_buffer_to_token_stream(char* buffer, size_t size) { //in this function convert buffer to the token stream, which is a linked list token_t head_token = create_token_with_type(HEAD, NULL, 0);//which created the dummy token token_t curr_token = head_token; token_t prev_token = NULL; token_stream_t head_stream = (token_stream_t)checked_malloc(sizeof(token_stream_t)); token_stream_t curr_stream = head_stream; curr_stream->head = head_token; curr_stream->tail = head_token;//now the head and tail both points to the head_token int line = 1; size_t index = 0; char c = *buffer; while(index<size) { //printf("index=%d, size = %d",(int)index,(int)size); if(isword(c) )//if c is word { size_t word_length = 5 ; size_t word_position = 0; char *word = (char*)checked_malloc(sizeof(word_length)); while(isword(c)) { word[word_position] = c;//assign the c to corresponding position // printf("test convert_buffer_to_token_stream1\n"); // printf("c=%c \n",c); if(word_position == word_length)//if reaches the length { word_length*=2; word = (char*)checked_realloc(word,word_length);//resize the word length } word_position++;index++;buffer++;c = *buffer;//update the char and index } token_t now = create_token_with_type(WORD,word,line); curr_token ->next = now; prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; } else if(c == '\n')//if c is the new line { line++; if(curr_token->t_type ==LEFT_DERCTION||curr_token->t_type ==RIGHT_DERCTION) //LEFT direction and right direction cannot be followed by new line { error(2, 0, "Line %d: Newline cannot follow redirects.", line); return NULL; } //if the current token type is word or subshell which indicated a new command index++; if (index == size) { // printf("break!" ); break; } else { buffer++;c = *buffer;} if(curr_token->t_type==WORD||curr_token->t_type==SUBSHELL) {//create a new token stream curr_stream->next = (token_stream_t)checked_malloc(sizeof(token_stream_t)); curr_stream = curr_stream->next; curr_stream->head = create_token_with_type(HEAD, NULL, -1); curr_token = curr_stream->head; } //else just treat is as white space // printf("test convert_buffer_to_token_stream2 \n"); //printf("c=%c \n",c); } else if(c == ' ' || c =='\t') { index++;buffer++;c = *buffer; //treated it as white space } else if(c == '<')//left direction { curr_token->next = create_token_with_type(LEFT_DERCTION,NULL,line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; // printf("test convert_buffer_to_token_stream3 \n"); // printf("c=%c \n",c); buffer++; index++; c = *buffer; } else if (c == '>') // RIGHT REDIRECT { curr_token->next = create_token_with_type(RIGHT_DERCTION, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; // printf("test convert_buffer_to_token_stream3 \n"); // printf("c=%c \n",c); buffer++; index++; c = *buffer; } else if (c == ';') // SEQUENCE command { curr_token->next = create_token_with_type(SEMICOLON, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; // printf("test convert_buffer_to_token_stream3 \n"); // printf("c=%c \n",c); buffer++; index++; c = *buffer; } else if (c == '&') // and { // printf("test convert_buffer_to_token_stream4 \n"); // printf("c=%c \n",c); buffer++; //my code index++; c=*buffer; if(buffer[0]!='&') { error(2, 0, "Line %d: Syntax error. & must be followed by &", line); return NULL; } else if(buffer[0]=='&') { curr_token->next = create_token_with_type(AND, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; // printf("test convert_buffer_to_token_stream4 \n"); // printf("c=%c \n",c); buffer++; index++; c = *buffer; } } else if (c == '|') // OR or PIPELINE { // printf("test convert_buffer_to_token_stream4 \n"); // printf("c=%c \n",c); buffer++; index++; c=*buffer; if(buffer[0]=='|') { curr_token->next = create_token_with_type(OR, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; // printf("test convert_buffer_to_token_stream5 \n"); // printf("c=%c \n",c); buffer++; index++; c = *buffer; } else { curr_token->next = create_token_with_type(PIPELINE, NULL, line); prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; //buffer++; index++; c = *buffer; } /* else { error(2, 0, "Line %d: Syntax error. | only can be followed by | or ", line); return NULL; }*/ } else if (c == '(') // SUBSHELL { int subshell_line = line; int nested = 1; size_t count = 0; size_t subshell_size = 64; char* subshell = (char*)checked_malloc(subshell_size); // grab contents until subshell is closed while (nested > 0) { buffer++; index++; c = *buffer; //to examine the next char if (index == size) { error(2, 0, "Line %d: Syntax error. EOF reached before subshell was closed.", subshell_line); return NULL; } if (c == '\n') { // consume all following whitespace while (buffer[1] == ' ' || buffer[1] == '\t' || buffer[1] == '\n') { if (buffer[1] == '\n') line++; buffer++; index++; } // pass semicolon c = ';'; line++; } else if (c == '(') // count for nested subshells nested++; else if (c == ')') // close subshell { nested--; if (nested == 0) // break if outermost subshell is closed { buffer++; index++; c = *buffer; // consume last close parens break; } } // printf("test convert_buffer_to_token_stream6 \n"); //printf("c=%c \n",c); // load into subshell buffer subshell[count] = c; count++; // expand subshell buffer if necessary if (count == subshell_size) { subshell_size = subshell_size * 2; subshell = (char*)checked_realloc (subshell, subshell_size); } // printf("test convert_buffer_to_token_stream7 \n"); // printf("c=%c \n",c); } // create subshell token curr_token->next = create_token_with_type(SUBSHELL, subshell, subshell_line); // curr_token = curr_token->next; prev_token = curr_token;//assign the previous token to now curr_token = curr_token->next; curr_token->prev = prev_token; prev_token->next = curr_token; curr_token->next = NULL; } else if (c == ')') // CLOSE PARENS { error(2, 0, "Line %d: Syntax error. Close parens found without matching open parens.", line); return NULL; } else { error(2, 0, "Line %d: Syntax error. Unrecognized character in script. ", line); return NULL; } } // printf("return headstream"); return head_stream; }
command_t make_command_tree(token_stream_t t) { token_t sub_head = t->head;//the sub_head is t->head token_t token_now = sub_head->next; Stack_t operators =initStack(); Stack_t operands =initStack();//build two stacks to hold operands and operators command_t comm;//one command command_t prev = NULL; int line = token_now->line; int counter=0; //if(token_now->next == NULL) // printf("Heere\n"); while(token_now!=NULL) { counter++; // printf("the %d time loop, the type is %d", counter,token_now->t_type); if( !(token_now->t_type == LEFT_DERCTION || token_now->t_type == RIGHT_DERCTION) ) { // make new command comm = (command_t)checked_malloc(sizeof( struct command )); // add_filename_to_dependlist(token_now->text,comm); } switch(token_now->t_type) { case AND: comm->type = AND_COMMAND; while ( !is_empty(operators) &&( top(operators)->type == PIPE_COMMAND || top(operators)->type == OR_COMMAND || top(operators)->type == AND_COMMAND )) { command_t pop_ops = pop(operators);//pop until the top ops has smaller presendence than if (!make_command_branch(pop_ops, operands)) { error(2, 0, "Line %d: Syntax error. Not enough children to create new tree.", line); return NULL; } } push(operators,comm);//push ADD command to ops token_now = token_now->next; break; case OR: comm->type = OR_COMMAND; while ( !is_empty(operators) &&( top(operators)->type == PIPE_COMMAND || top(operators)->type == OR_COMMAND || top(operators)->type == AND_COMMAND )) { command_t pop_ops = pop(operators);//pop until the top ops has smaller presendence than if (!make_command_branch(pop_ops, operands)) { error(2, 0, "Line %d: Syntax error. Not enough children to create new tree.", line); return NULL; } } push(operators,comm);//push ADD command to ops token_now = token_now->next; break; // push OR to ops push(operators,comm); break; case PIPELINE: comm->type = PIPE_COMMAND; while ( !is_empty(operators) && top(operators)->type == PIPE_COMMAND ) { command_t pop_ops = pop(operators);//pop until the top ops has smaller presendence than if (!make_command_branch(pop_ops, operands)) { error(2, 0, "Line %d: Syntax error. Not enough children to create new tree.", line); return NULL; } } push(operators,comm);//push PIPE command to ops token_now = token_now->next; break; case SEMICOLON: comm->type = SEQUENCE_COMMAND; // always pop since SEMICOLON <= all ops while (!is_empty(operators)) { command_t pop_ops = pop(operators); if (!make_command_branch(pop_ops, operands)) { error(2, 0, "Line %d: Syntax error. Not enough children to create new tree.", line); return NULL; } } // push SEMICOLON to ops push(operators,comm); token_now = token_now->next; break; case WORD: comm->type = SIMPLE_COMMAND; //seprated by word int num_words = 1; token_t count = token_now; while(count!=NULL&&count->next!=NULL&&count->next->t_type==WORD)//while next is still word { count = count ->next; num_words++; } comm->u.word = (char**)checked_malloc((num_words+1)*sizeof(char**)); comm->u.word[0] = token_now->text; int i =1; while(i< num_words) { token_now = token_now->next; comm->u.word[i] = token_now->text; // add_filename_to_dependlist(comm->u.word[i],comm); i++; //if(i == num_words) } comm->u.word[num_words] = NULL; push(operands,comm); token_now = token_now->next; break; case SUBSHELL: comm->type = SUBSHELL_COMMAND; // process subshell command tree token_stream_t subshell_token = convert_buffer_to_token_stream(token_now->text, strlen(token_now->text)); command_t subshell_command = make_command_tree(subshell_token); comm->u.subshell_command = subshell_command; // push SUBSHELL tree to operands push(operands, comm); token_now = token_now->next; break; case LEFT_DERCTION: // check that previous command is a subshell or word if (prev== NULL || !(prev->type == SIMPLE_COMMAND || prev->type == SUBSHELL_COMMAND)) { error(2, 0, "Line %d: Syntax error. ONLY words and SUBSHELL can follow redirection", line); return NULL; } /* else if (prev->output != NULL) { error(2, 0, "Line %d: Syntax error. Previous command already has output. ", line); return NULL; }*/ else if (prev->input != NULL) { error(2, 0, "Line %d: Syntax error. Previous command already has input.", line); return NULL; } token_now= token_now->next; if (token_now->t_type == WORD) // followed by a word { //which is valid input prev->input = token_now->text; // add_filename_to_dependlist(prev->input,comm); } else { error(2, 0, "Line %d: Syntax error. Redirects must be followed by words.", line); return NULL; } token_now= token_now->next; // no pushing required break; case RIGHT_DERCTION: // check that previous command is a subshell or word if (prev== NULL || !(prev->type == SIMPLE_COMMAND || prev->type == SUBSHELL_COMMAND)) { error(2, 0, "Line %d: Syntax error. ONLY words and SUBSHELL can follow redirection", line); return NULL; } else if (prev->output != NULL) { error(2, 0, "Line %d: Syntax error. Previous command already has output. ", line); return NULL; } /*else if (prev->input != NULL) { //error(2, 0, "Line %d: Syntax error. Previous command already has input.", line); return NULL; }*/ token_now= token_now->next; if (token_now->t_type == WORD) // followed by a word { //which is valid output prev->output = token_now->text; //add output word to outfile_list // outfile_t new_outfile = add_out_list (prev); // prev->outfile_ptr = new_outfile; } else { error(2, 0, "Line %d: Syntax error. Redirects must be followed by words.", line); return NULL; } // no pushing required token_now= token_now->next; break; default: token_now = token_now->next; break; }; prev = comm; // printf("the previous command is: %d\n", prev->type); } //printf("end first while"); while(size(operators) > 0) { command_t pop_ops = pop(operators); if (!make_command_branch(pop_ops, operands)) { error(2, 0, "Line %d: Syntax error. Not enough children to create new tree.", line); return NULL; } } // check for single root if (size(operands) != 1) { error(2, 0, "Line %d: Syntax error. Tree did not converge into single root.", line); return NULL; } command_t root = pop(operands); // the root should be the final tree left in operands return root; }
static void *SzAlloc(void *, size_t size) { return checked_malloc(size,-1); }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { char** commandStrings = (char**)checked_malloc(sizeof(char*)); commandStrings[0] = NULL; char** temp = NULL; char c; char effective_prev = '\0'; char prev ='\0'; int count = 1; // Keeps count of complete commands bool sub = false; //To see if we are within a subshell int open_par = 0; int closed_par = 0; int curr_line = 1; int* line_nums = (int*)checked_malloc(sizeof(int)); line_nums[0] = 1; while((c = get_next_byte(get_next_byte_argument)) != EOF) { if(is_illegal(c)) // Check for illegal tokens { error(1,0,"%d: Invalid token '%c'.",curr_line,c); return 0; } if((c == ';') && (!sub)) { if(effective_prev =='\n' || effective_prev =='\0') error(1,0, "%d: Can't start line with '%c'", curr_line, c); if(effective_prev == ';') error(1,0, "%d: Too many '%c' tokens", curr_line, c); count++; temp = (char**)checked_realloc(commandStrings,sizeof(char*)*count); commandStrings = temp; commandStrings[count-1] = NULL; int* temp_int = (int*)checked_realloc(line_nums,sizeof(int)*count); line_nums = temp_int; prev = c; effective_prev = c; continue; } if(c == '#') // Take care of comments be ignoring everything up to newline { if((is_special(prev)) || (isblank((unsigned char)prev) != 0) // changed from unsigned char type to char || (prev == '\n') ||(prev == '\0')) { while((c = get_next_byte(get_next_byte_argument)) != EOF) if( c == '\n') break; if(c == EOF) break; if((prev == '\0') && (c == '\n')) // Case if script starts with # { //If I don't include this an empty string is made prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; curr_line++; continue; } } else { error(1,0,"Line %d: Invalid use of '#' token.",curr_line); return 0; } } if(c != '\n') { if((isblank((unsigned char)c) != 0) && (effective_prev == '\0')) continue; // Check that that only paranthesis are preceded by newline(and words of course) if(effective_prev == '\n') { if((c == '|') || (c == '&') || (c == '>') || (c == '<')) { error(1,0,"%d: Unexpected newline before '%c' token",curr_line,c); return 0; } } if(c == '(') { sub = true; open_par++; } else if(c == ')') { closed_par++; if(open_par == closed_par) { sub = false; open_par = 0; closed_par = 0; } } if(((c == '|') && (effective_prev == '&')) || ((c == '&') && (effective_prev == '|'))) { error(1,0,"%d: Invalid AND-OR.",curr_line); return 0; } if(commandStrings[count-1] == NULL) { line_nums[count-1] = curr_line; } add_char(commandStrings,count-1,c); } else { if((effective_prev == '|') || (effective_prev == '&') || sub) { prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; if(commandStrings[count-1] == NULL) { line_nums[count-1] = curr_line; } add_char(commandStrings,count-1,c); curr_line++; continue; } if(prev == '\n' || effective_prev == '\0') { prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; curr_line++; continue; } // Gotta also check for < or > cases if((effective_prev == '<') || (effective_prev == '>')) { error(1,0,"%d: Cannot end line in < or >",curr_line); return 0; } if(!sub && (prev != ';')) { count++; temp = (char**)checked_realloc(commandStrings,sizeof(char*)*count); commandStrings = temp; commandStrings[count-1] = NULL; int* temp_int = (int*)checked_realloc(line_nums,sizeof(int)*count); line_nums = temp_int; } curr_line++; } prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; } if((commandStrings[0] == NULL) && count == 1) count = 0; if(open_par != closed_par) // Check to see if paranthesis are all good { error(1,0,"%d: Missing a paranthesis",curr_line); return 0; } if(prev == '\n' && (commandStrings[count-1] == NULL)) count--; command_stream_t stream = stringsToStream(commandStrings, line_nums, count); /* Free Data Allocated Dynamically int j; for(j = 0; j < count; j++) free(commandStrings[j]); free(commandStrings); free(line_nums); */ // BUILD READ/WRITE LISTS (add as a member of command_stream_t) // BUILD DEPENDENCY LISTS (lists of integer indices of commands that must // finish before this one does) stream->pidList = checked_malloc(count * sizeof(pid_t)); // 0 out all pid's. This will give them all integer values of NOT_YET_RUN. memset(stream->pidList, 0, count * sizeof(pid_t)); make_dep_lists(stream); return stream; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { char *operators[] = { "&&", "||", "|", "(", ")", ";" };//, "\n" }; int precedences[] = { 1, 1, 2, 4, -1, 0, 0 }; int i, j, isOperator, numChars = 0, inComment = 0; int operatorNumber = 0; int possibleNewCommand = 0; unsigned int currentWordSize = 16 * sizeof(char); int lastOperatorWasRightP = 0; char *operand, *lastCommand, *currentWord = checked_malloc(16 * sizeof(char)); char c = (char) get_next_byte(get_next_byte_argument); command_t operand1, operand2; // Initialize command stream command_stream_t commandStream = checked_malloc(10 * sizeof(struct command)); commandStream->currentStreamSize = 10 * sizeof(struct command); commandStream->numCommands = 0; commandStream->currentCommand = 0; g_lineNumber = 0; init_stacks(); while(c != EOF) { //printf("loop entered\n"); if( c == '\n') { g_lineNumber++; } if(inComment) { if( c == '\n' ) { inComment = 0; c = get_next_byte(get_next_byte_argument); continue; } else { c = get_next_byte(get_next_byte_argument); continue; } } else if( c == '#' ) { inComment = 1; c = get_next_byte(get_next_byte_argument); continue; } /** * Basically if there is a non-operator followed by a newline, there is a possibility * that the current command is done. The current command will be over if the newline * is then followed by another non-operator. Also ignore newlines inside commands. */ //printf("possible New COmmand is set to %i\n",possibleNewCommand); if ( (!isOperator || lastOperatorWasRightP) && c == '\n') { possibleNewCommand = 1; //printf("PossibleNewCommand set to 1 char is %c\n",c); // Used if a new command is actually started to finish the current one lastCommand = currentWord; fpos_t pos; fgetpos(get_next_byte_argument, &pos); c = get_next_byte(get_next_byte_argument); if (c != '\n') { //printf("continuing after setting possibleNewCommand to 1\n"); // if(c == EOF) // printf("new character is EOF and num of operands left is %i\n",g_iOperand_stack_size); fsetpos(get_next_byte_argument, &pos); lastOperatorWasRightP = 0; continue; } else { g_lineNumber++; } } else if (c == '\n') { c = get_next_byte(get_next_byte_argument); //printf("Operator followed by newlien detected. continiuing\n"); lastOperatorWasRightP = 0; continue; } //printf("Checkpoint 2\n"); /** * This loop checks if the current char is an operator. If it is, we create the operator word * and then we check the next char in case of double char operators such as || or && */ lastOperatorWasRightP = 0; isOperator = 0; for (i = 0; i < 6; i++) { // check if start of an operator if (c == operators[i][0]) { isOperator = 1; operand = currentWord; // Save old operand before creating operator currentWord = checked_malloc(3 * sizeof(char)); // Create the operator word currentWord[0] = c; fpos_t pos; fgetpos(get_next_byte_argument, &pos); if (c == '|' || c == '&') { if(g_iOperand_stack_size <= 0 && numChars <= 0) error(1,0,"%i: Did not expect binary operator",g_lineNumber); char current_char = c; c = get_next_byte(get_next_byte_argument); currentWord[1] = c; currentWord[2] = '\0'; if (c == '|' && c == current_char) { i = OR; } else if (c == '&' && c == current_char) { i = AND; } else if( current_char == '&' && c != current_char) { //TODO: Throw syntax error here. Single &! //fprintf(stderr,"%i: Isolated & found. Not a valid word character, and it is not an &&",lineNumber); error(1,0,"%i: Isolated & found",g_lineNumber); } else { i = PIPE; currentWord[1] = '\0'; fsetpos(get_next_byte_argument, &pos); } } else if( c == '(') { //printf("Found leftP\n"); i = LEFTP; currentWord[1] = '\0'; fsetpos(get_next_byte_argument, &pos); } else if( c == ')') { //printf("Found rightP\n"); lastOperatorWasRightP = 1; i = RIGHTP; currentWord[1] = '\0'; fsetpos(get_next_byte_argument, &pos); } else if( c == ';') { if(g_iOperand_stack_size <= 0 && numChars <= 0) error(1,0,"%i: Did not expect binary operator",g_lineNumber); currentWord[1] = '\0'; fsetpos(get_next_byte_argument, &pos); } else { currentWord[1] = '\0'; fsetpos(get_next_byte_argument, &pos); } break; } } /** * When we encounter an operator, we can create a simple command out of the previous word * if there was a word (operand) there. This should always happen?? */ if (isOperator) { //printf("isOperator\n"); if (numChars > 0) { operand[numChars] = '\0'; //printf("Pushed %s on operand stack\n", operand); //get rid of whitespaces in operand here. int onlyWhite = getRidOfExtraWhitespaces(operand); if(onlyWhite == 0) push_operand(createSimpleCommand(operand)); // printf("simple out of operand %s\n", operand); numChars = 0; } /** * While the top of the stack contains an operator with equal or higher precedance than the * operator we are currently dealing with, keeping popping one operator and two operands, * creating a command out of them, and pushing it onto the operand stack. */ //printf("Charly:top of stack is %i\n",operator_stack_top()); // if(operator_stack_top() == RIGHTP ) //eval stack until a LEFTP is found if(i == RIGHTP) { //printf("EvalStackuntilLeftP found. possibleNewCommand is %i\n",possibleNewCommand); evalStackUntilLeftP(); //printf("current char is %c\n",c); c = get_next_byte(get_next_byte_argument); //printf("nextchar is %c\n",c); continue; } while(g_iOperator_stack_size > 0 && g_iOperand_stack_size > 1 && (precedences[operator_stack_top()] >= precedences[i]) && ((operator_stack_top() != LEFTP) && i != RIGHTP )) { operand2 = pop_operand(); operand1 = pop_operand(); operatorNumber = pop_operator(); //printf("popped operands types %d %d\n", operand1->type, operand2->type); //printf("popped operator %s\n", operators[operatorNumber]); //printf("pushed type %d operand on stack\n", operatorNumber); push_operand(createCommand(operand1, operand2, operatorNumber)); } // Get the operator number for the current word for (j = 0; j < 6; j++) { if (strcmp(currentWord, operators[j]) == 0) { break; } } //printf("pushed operators %s %d on stack\n", currentWord, j); push_operator(j); currentWord = checked_malloc(3 * sizeof(char)); } else if (!possibleNewCommand) { //if last operator was rightP. do not run this. //printf("not a new command. new char is %c, numChars is %i, currentWordSize is %i\n",c,numChars,currentWordSize); if(c != ' ' || numChars > 0) { //printf("growing current word %s currentWordSize is %i and numChars is %i\n",currentWord,currentWordSize,numChars); // Grow current word which is an operand if necessary if ((numChars * sizeof(char)) >= currentWordSize) { //printf("doubling size of word %s\n",currentWord); currentWordSize *= 2; //char * buffer = checked_malloc(currentWordSize); //strncpy(buffer,currentWord,numChars); //free((void *)currentWord); //currentWord = checked_malloc(currentWordSize); //strncpy(currentWord,buffer,numChars); currentWord = checked_realloc(currentWord, currentWordSize );// for some reason this was messing up //printf("it is now %s\n",currentWord); } currentWord[numChars] = c; numChars++; } } else { //printf("Going to new command. operand stack size is %i\n",g_iOperand_stack_size); //printf("Operator stack size is %i. numChars is %i\n",g_iOperator_stack_size,numChars); //if(g_iOperand_stack_size <= 0) //{ // c = get_next_byte(get_next_byte_argument); // possibleNewCommand = 0; //continue; //} /** * This means that we are about to go onto a new command. We stop the current command and * finish building it with the lastCommand variable, and an operand/operator if necessary. * This command is then put into the command stream. */ lastCommand[numChars] = '\0'; //printf("Last Command getting rid of whites\n"); if(numChars > 0) { //printf("numchars is > 0 so word is %s\n",lastCommand); getRidOfExtraWhitespaces(lastCommand); push_operand(createSimpleCommand(lastCommand)); } else if(g_iOperand_stack_size <= 0) { c = get_next_byte(get_next_byte_argument); possibleNewCommand = 0; continue; } //else //{ // printf("numChars == 0 so we are continuing\n"); //continue // c = get_next_byte(get_next_byte_argument); // possibleNewCommand = 0; // continue; //} evalStack(); //printf("%s\n", "Finished one command"); if ((commandStream->numCommands * sizeof(struct command)) == commandStream->currentStreamSize) { commandStream->currentStreamSize *= 2; commandStream = checked_realloc(commandStream, commandStream->currentStreamSize); } command_t commandToPushToStream = pop_operand(); commandToPushToStream->status = -1; commandStream->stream[commandStream->numCommands] = commandToPushToStream; // TODO: if stack not empty, there was an error? commandStream->numCommands++; numChars = 0; currentWord = checked_malloc(3 * sizeof(char)); // prevent overwriting } //printf("PossibleNewCOmmand set to 0 right before checkpoint1\n"); c = get_next_byte(get_next_byte_argument); possibleNewCommand = 0; } //printf("Checkpoint1. possibleNEwCommand is %i num of operands is %i\n",possibleNewCommand,g_iOperand_stack_size); // Push last word onto operand stack and evaluate the rest if (!isOperator) { currentWord[numChars] = '\0'; //printf("pushed simple word %s with word count %i strlen is %i\n", currentWord,numChars,(int)strlen(currentWord)); getRidOfExtraWhitespaces(currentWord); if(strlen(currentWord) > 0) push_operand(createSimpleCommand(currentWord)); } else { // if a semicolon, valid? } //printf("evalstack at the end of loop\n"); evalStack(); // Put last command in command stream // if there is one! if(operand_stack_top() != NULL) { command_t commandToPushToStream = pop_operand(); commandToPushToStream->status = -1; commandStream->stream[commandStream->numCommands] = commandToPushToStream; commandStream->numCommands++; } //printf("Stack sizes: %d, %d\n", g_iOperator_stack_size, g_iOperand_stack_size); //printf("Final command type is %d\n", commandStream->stream[0]->type); return commandStream; }
// Extracts the word, and input/output(if applicable) into the command void extractWordInputOutput(char* currentWord, command_t command) { int i = 0, j = 0, expectAnotherRedir = 0; int currentWord_size = strlen(currentWord); int output_size, input_size; command->type = SIMPLE_COMMAND; switch(isRedirectionCommand(currentWord)) { // case 2: //TODO ERASE THIS LINE!!!! THIS WILL BREAK SHIT case 0: // this command is not a redirection command. command->u.word = createWordArray(currentWord); break; case 2: // this command has two redirections expectAnotherRedir = 1; case 1:// this command has one redirection while(currentWord[i] != '\0') { if(currentWord[i] == '>') { output_size = currentWord_size - i;// includes null byte char *outputBuffer = checked_malloc(sizeof(char)*output_size); strcpy(outputBuffer, ¤tWord[i+1]); command->output = outputBuffer; currentWord[i] = '\0'; command->u.word = createWordArray(currentWord); break; } else if(currentWord[i] == '<') { if(expectAnotherRedir == 0) { input_size = currentWord_size - i;//includes null byte char *inputBuffer = checked_malloc(sizeof(char)*input_size); strcpy(inputBuffer, ¤tWord[i+1]); command->input = inputBuffer; currentWord[i] = '\0'; command->u.word = createWordArray(currentWord); } else { j = i + 1; while(currentWord[j] != '>') { if(currentWord[j] == '\0') error(1,0,"%i: Syntax error. Ambiguous redirections.", g_lineNumber); j++; } input_size = j - i; // includes null byte output_size = currentWord_size - j; char *inputBuffer = checked_malloc(sizeof(char)*input_size); char *outputBuffer= checked_malloc(sizeof(char)*output_size); strncpy(inputBuffer,¤tWord[i+1], input_size - 1); inputBuffer[input_size - 1] = '\0'; strcpy(outputBuffer, ¤tWord[j+1]); command->output = outputBuffer; command->input = inputBuffer; currentWord[i] = '\0'; command->u.word = createWordArray(currentWord); } break; } i++; } break; default: //throw error here break; } }
string String(char *s) {string p = checked_malloc(strlen(s)+1); strcpy(p,s); return p; }
U_boolList U_BoolList(bool head, U_boolList tail) { U_boolList list = checked_malloc(sizeof(*list)); list->head = head; list->tail = tail; return list; }
command_t makeCommandStreamUtil(int (*get_next_byte) (void *), void *get_next_byte_argument, STATE *state) { char **tokenPTR = checked_malloc(sizeof(char**)); char *token = NULL; int len = 0; TOKENTYPE type; command_t command = NULL; char *input = NULL, *output = NULL; type = readNextToken(tokenPTR, &len, get_next_byte, get_next_byte_argument); if (type == NOT_DEFINED) { free(tokenPTR); return NULL; } else if (type == O_PAR) { token = "("; } else { token = *tokenPTR; } command = AllocateCommand(); if (!command) { return NULL; } if (!strncmp(token, "then", 4)) { if (!(pop() == IF)) { printErr(); } push(THEN); *state = THEN; goto ret_null; } else if (!strncmp(token, "done", 4)) { if (!(pop() == DO)) { printErr(); } *state = DONE; CScount--; goto ret_null; } else if (!strncmp(token, "do", 4)) { STATE tmp = pop(); if (!((tmp == WHILE) || (tmp == UNTIL))) { printErr(); } push(DO); *state = DO; goto ret_null; } else if (!strncmp(token, "else", 4)) { if (!(pop() == THEN)) { printErr(); } push(ELSE); *state = ELSE; goto ret_null; } else if (!strncmp(token, "fi", 4)) { STATE tmp = pop(); if (!((tmp == THEN) || (tmp == ELSE))) { printErr(); } CScount--; *state = FI; goto ret_null; } else if (!strncmp(token, ")", 1)) { CScount--; *state = CLOSE_PAR; goto ret_null; } else if (!strncmp(token, "if", 2)) { push(IF); CScount++; command = makeCommand(command, NULL, IF_COMMAND, input, output); free(tokenPTR); command->u.command[0] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); while (*state != THEN) { if (!makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state)) { type = NOT_DEFINED; break; } } if (type == NOT_DEFINED && *state != THEN) { return NULL; } command->u.command[1] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (*state != ELSE && *state != FI) { // HANDLE error; ; } else if (*state == ELSE || (*state == FI && CScount)) { command->u.command[2] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); } else { command->u.command[2] = NULL; } } else if (!strncmp(token, "while", 5)) { push(WHILE); (CScount)++; command = makeCommand(command, NULL, WHILE_COMMAND, input, output); free(tokenPTR); command->u.command[0] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (*state != DO) { // Handle Error ; } command->u.command[1] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (*state != DONE) { // HANDLE error; ; } else if (*state == DONE) { if (checkRedirection(get_next_byte, get_next_byte_argument)) { fillRedirectionOperands(&command->input, &command->output, get_next_byte, get_next_byte_argument); } command->u.command[2] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); /* if (command->u.command[2]) { */ /* command_t newCommand = makeCommand(NULL, NULL, SEQUENCE_COMMAND, */ /* NULL, NULL); */ /* newCommand->u.command[0] = command->u.command[1]; */ /* newCommand->u.command[1] = command->u.command[2]; */ /* command->u.command[1] = newCommand; */ /* command->u.command[2] = NULL; */ /* } */ } else { command->u.command[2] = NULL; } } else if (!strncmp(token, "until", 5)) { push(UNTIL); (CScount)++; command = makeCommand(command, NULL, UNTIL_COMMAND, input, output); free(tokenPTR); command->u.command[0] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (*state != DO) { // Handle Error ; } command->u.command[1] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (*state != DONE) { // HANDLE error; ; } else if (*state == DONE) { if (checkRedirection(get_next_byte, get_next_byte_argument)) { fillRedirectionOperands(&command->input, &command->output, get_next_byte, get_next_byte_argument); } command->u.command[2] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); /* if (command->u.command[2]) { */ /* command_t newCommand = makeCommand(NULL, NULL, SEQUENCE_COMMAND, */ /* NULL, NULL); */ /* newCommand->u.command[0] = command->u.command[1]; */ /* newCommand->u.command[1] = command->u.command[2]; */ /* command->u.command[1] = newCommand; */ /* command->u.command[2] = NULL; */ /* } */ } else { command->u.command[2] = NULL; } } else if (!strncmp(token, "(", 1)) { CScount++; command = makeCommand(command, NULL, SUBSHELL_COMMAND, input, output); free(tokenPTR); command->u.command[0] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (*state != CLOSE_PAR) { // Handle Error } else if (*state == CLOSE_PAR && CScount) { command->u.command[0] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); } } else { // SIMPLE_COMMAND while (1) { STATE prevState = *state; if (isKeyWordUpdate(token, state) && (prevState == COMMAND)) { removeWhiteSpace(token); command = makeSimpleCommand(command, tokenPTR, input, output); break; } if (type == REDIRECTION1 || type == REDIRECTION2) { type = fillRedirectionOperands(&input, &output, get_next_byte, get_next_byte_argument); // command = makeSimpleCommand(command, tokenPTR, input, output); // break; // type = readNextToken(tokenPTR, &len, get_next_byte, get_next_byte_argument); } else if (type == SPACE) { appendChar(token, ' '); type = readNextToken(tokenPTR, &len, get_next_byte, get_next_byte_argument); } else if (type == NEWLINE && !CScount) { command = makeSimpleCommand(command, tokenPTR, input, output); break; } else if (type == PIPE || type == SEMICOLON || type == NEWLINE) { removeWhiteSpace(token); if (((type == PIPE) || (type == SEMICOLON)) && !strlen(token)) { printErr(); } command = makeCommand(command, tokenPTR, type == PIPE ? PIPE_COMMAND : SEQUENCE_COMMAND, input, output); command->u.command[1] = makeCommandStreamUtil(get_next_byte, get_next_byte_argument, state); if (!command->u.command[1]) { command = convertToSimple(command); } break; } *state = COMMAND; } } return command; ret_null: free(command); free(tokenPTR); return NULL; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { //create a command stream struct command_stream_t stream = (command_stream_t)checked_malloc(sizeof(struct command_stream)); struct node* head; struct node* current; current = (struct node *)checked_malloc(sizeof(struct node)); head = current; int current_byte; char* str = (char*)checked_malloc(sizeof(char)); int wordSize=0; char current_char; int line = 1; int foundComment = 0; while((current_byte = get_next_byte(get_next_byte_argument))!= EOF){ current_char = current_byte; if(current_char == '#') { foundComment = 1; continue; } if(isOperator(current_char)) { if(!(str[0]=='\0')) { current = saveToNode(str, current, OPERATOR, wordSize); str[0]='\0'; memset(str,0,strlen(str)); wordSize = 0; } wordSize++; str = (char*)realloc(str,wordSize*sizeof(char)); str[wordSize-1] = current_byte; current = saveToNode(str, current, OPERATOR, wordSize); str[0]='\0'; memset(str,0,strlen(str)); wordSize=0; continue; } if(isalphaNum(current_char) || current_char==' ') { if(foundComment) { continue; } wordSize++; str = (char*)realloc(str,wordSize*sizeof(char)); str[wordSize-1] = current_byte; } if((strncmp(str,"if",2)==0) || (strncmp(str,"while",5)==0) || (strncmp(str,"until",2)==0) || (strncmp(str,"else",4)==0) || (strncmp(str,"done",4)==0)) { current = saveToNode(str, current, COMPOUND, wordSize); str[0]='\0'; memset(str,0,strlen(str)); wordSize = 0; continue; } if(current_char=='\n' || current_char==';') { if(foundComment) { foundComment = 0; continue; } if(!(str[0]=='\0')) { current = saveToNode(str, current, COMMAND, wordSize); str[0]='\0'; memset(str,0,strlen(str)); wordSize = 0; } wordSize++; current = saveToNode(str, current, NEWLINE_SEMICOLON, wordSize); str[0]='\0'; memset(str,0,strlen(str)); wordSize = 0; continue; } } current = head; command_node* c_node = checked_malloc(sizeof(struct command_node)); stream->commands = checked_malloc(sizeof(struct command_node)); while(current->next != NULL) { printf("Node: "); printf(current->word); printf(", Operator: "); printf("%i", current->flag); printf("\n"); current = current->next; } return *stream; }
//All the dependencies are added to the node and all the dependencies of the subcommand are added to the node. void add_dependencies(command_node_t node, command_t command) { //We get the command node and the command here. //First lets check if the input is not = 0, if not that means it is a command with an input and we need to take care of it. if(command->input != 0) { if(node->inputs == NULL) { int size = sizeof(node_t); node_t head = checked_malloc(size); //We assign the head of our node_t struct to the input head->word = command->input; //Next is set to null head->next = NULL; node->inputs = head; } else // This means that input is not null { //We need to add the word to the list. We iterate through the noed struct till we reach the //same input as the command input while(strcmp(node->inputs->word, command->input) == 0) { if(node->inputs->next == NULL) { node->inputs->next = checked_malloc(sizeof(node_t)); node->inputs->next->word = command->input; // Word getting added node->inputs->next->next = NULL; } else //continue to loop with the next word in the node node->inputs=node->inputs->next; } } } //Time for output. check if the command has an output if(command->output != 0) { if(node->outputs == NULL) { int size = sizeof(node_t); node_t head = checked_malloc(size); head->word = command->output; head->next = NULL; node->outputs = head; } else // This means that input is not null { //We need to add the word to the list. We iterate through the noed struct till we reach the //same input as the command input while(strcmp(node->outputs->word, command->output) == 0) { if(node->outputs->next == NULL) { node->outputs->next = checked_malloc(sizeof(node_t)); node->outputs->next->word = command->output; // Word getting added node->outputs->next->next = NULL; } else //continue to loop with the next word in the node node->outputs=node->outputs->next; } } } int temp = 0; //At this point we are done adding the input and output of the command to the structs. Let's see what kind of command it is //and do things accordingly if(command->type == AND_COMMAND || command->type == OR_COMMAND || command->type == SEQUENCE_COMMAND || command->type == PIPE_COMMAND) { add_dependencies(node, command->u.command[0]); //Above mentioned commands could have input and out, so have to //to add dependencies both for input and output. That is the left side of a pipe could itself be command. //So we need to take care of those dependecies as well. add_dependencies(node, command->u.command[1]); } //If the command is a simple command then it is a different case. we do not need to call the add dependencies function again //Because simple command will not have a subcommand if(command->type == SIMPLE_COMMAND ) { temp = 1; while(command->u.word[temp] != NULL) { if(node->inputs == NULL) { //Making the input of the node point to the head of node_t int size = sizeof(node_t); node_t head = checked_malloc(size); head->word = command->u.word[temp]; head->next = NULL; node->inputs = head; } else { //We need to add the word to the list. We iterate through the noed struct till we reach the //same input as the command input while(strcmp(node->inputs->word, command->u.word[temp]) == 0) { if(node->inputs->next == NULL) { node->inputs->next = checked_malloc(sizeof(node_t)); node->inputs->next->word = command->u.word[temp]; // Word getting added node->inputs->next->next = NULL; } else //traverse the list( node struct) node->inputs = node->inputs->next; } if(node->outputs == NULL) { //Making the input of the node point to the head of node_t int size = sizeof(node_t); node_t head = checked_malloc(size); head->word = command->u.word[temp]; head->next = NULL; node->outputs = head; } else { //We need to add the word to the list. We iterate through the noed struct till we reach the //same input as the command input while(strcmp(node->outputs->word, command->u.word[temp]) == 0) { if(node->outputs->next == NULL) { node->outputs->next = checked_malloc(sizeof(node_t)); node->outputs->next->word = command->u.word[temp]; // Word getting added node->outputs->next->next = NULL; } else //traverse the list( node struct) node->outputs = node->outputs->next; } } } temp++; } } }
void add_dependencies(command_t c, pthread_t tid) { file_node_t f_root = extract_dependencies(c); dependency_node_t d_node = dependency_root; dependency_node_t d_prev = d_node; while(d_node != NULL) { file_node_t f_node = f_root; while(f_node != NULL) { if(strcmp(d_node->file_name, f_node->file_name) == 0) { enum dependency_type type = f_node->type; if(f_node == f_root) f_root = f_node->next; tid_node_t t_node = d_node->waiting_list; tid_node_t t_prev = t_node; if(t_node == NULL) { t_node = checked_malloc(sizeof(struct tid_node)); goto make_node; } while(t_node != NULL) { t_prev = t_node; t_node = t_node->next; } t_node = checked_malloc(sizeof(struct tid_node)); make_node:; t_node->tid = tid; t_node->type = type; t_node->next = NULL; if(d_node->waiting_list != NULL) t_prev->next = t_node; else d_node->waiting_list = t_node; if(f_node->prev != NULL) f_node->prev->next = f_node->next; if(f_node->next != NULL) f_node->next->prev = f_node->prev; if(f_node->next == NULL && f_node->prev == NULL) break; file_node_t temp = f_node; f_node = f_node->next; free(temp); } else f_node = f_node->next; } d_prev = d_node; d_node = d_node->next; } if(f_root != NULL) { file_node_t f_node = f_root; dependency_node_t d_tail = checked_malloc(sizeof(struct dependency_node)); dependency_node_t tail_node = d_tail; dependency_node_t tail_prev = tail_node; while(f_node != NULL) { tail_node->file_name = f_node->file_name; tail_node->waiting_list = checked_malloc(sizeof(struct tid_node)); tail_node->waiting_list->tid = tid; tail_node->waiting_list->type = f_node->type; tail_node->waiting_list->next = NULL; tail_node->next = checked_malloc(sizeof(struct dependency_node)); tail_prev = tail_node; tail_node = tail_node->next; f_node = f_node->next; } free(tail_node); tail_prev->next = NULL; if(d_prev != NULL) d_prev->next = d_tail; else dependency_root = d_tail; } }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { //=========Let's just try to read the input in first.============// size_t bufferSize = 1024; size_t bufferIterator = 0; char value; char* buffer = (char*) checked_malloc(bufferSize); while ((value = get_next_byte(get_next_byte_argument)) != EOF) //store into value while it isn't EOF { buffer[bufferIterator++] = value; // printf("looped once: %c \n", value); // printf("bufferSize: %d \n", (int) bufferSize); if (bufferSize == bufferIterator){ buffer = (char*) checked_grow_alloc(buffer, &bufferSize); //printf("called checked_realloc: %d\n", (int) bufferSize); } } if (bufferSize == bufferIterator){ buffer = (char*) checked_grow_alloc(buffer, &bufferSize); //printf("called checked_realloc: %d\n", (int) bufferSize); } buffer[bufferIterator] = '\0'; //printf("bufferIterator: %d \n", (int) bufferIterator); //puts(buffer); //will output to stdout //=========Let's tokenize the stream============// //we need to do the same thing as before, except instead of taking from the filestream and putting it into the array. //Now take the array and put it into a token stream. //Could never get the outside function working due to all that referential bullshit. Let's just do it inline. token_stream* tstream = (token_stream*) checked_malloc(sizeof(token_stream*)); token_stream* trackend = tstream; int bufferIteratorT = 0; int comment = 0; int linNumber = 1; token_type type; //do a dual parsing here where we handle two characters at the same time. This makes the && and || and comments easy //Need to check if the buffer is completely empty (has '\0' as the only character). Then we don't do anything so we //can just return if (buffer[bufferIteratorT] == '\0') { command_stream_t empty = (command_stream_t) checked_malloc(sizeof(command_stream_t)); empty->size = 0; return empty; } char first; char second; while (buffer[bufferIteratorT+1] != '\0') { first = buffer[bufferIteratorT]; second = buffer[bufferIteratorT+1]; //Check for && if (first == '&') { if (second == '&') { type = AND_TOKEN; bufferIteratorT++;//deals with the fact that && is two chars } else { type = MISC_TOKEN; //We can test for MISC_TOKEN later, this is an invalid input, only 1 & } } //Check for || else if (first == '|') { if (second == '|') { type = OR_TOKEN; bufferIteratorT++; } else { type = PIPE_TOKEN; } } else if (first == '#') { if (bufferIteratorT != 0 && isWordChar(buffer[bufferIteratorT-1])) { //if BIT is not 0 , then check if prior is a word, definitely a comment fprintf(stderr,"%i: problem at this line in script\n", linNumber); exit(0); } type = COMMENTS_TOKEN; comment = 1; } else if (first == ';') { type = SEMICOLON_TOKEN; } else if (first == '(') { type = LEFT_PAREN_TOKEN; } else if (first == ')') { type = RIGHT_PAREN_TOKEN; } else if (first == '<') { type = LESS_TOKEN; } else if (first == '>') { type = GREATER_TOKEN; } else if (first == '\n') { type = NEWLINE_TOKEN; linNumber++; comment = 0; } else //unknown character { type = MISC_TOKEN; } //idea is to figure out how long the word length is and then use token adding part to figure out how far to add the words. Also, make sure you move ahead in the outer loop. This will also overwrite MISC_TOKEN if word is found int wordlength = 1; int placeholder = bufferIteratorT; if (isWordChar(first)) { type = WORD_TOKEN; while (isWordChar(buffer[bufferIteratorT+wordlength])) { wordlength++; } bufferIteratorT += wordlength-1; // printf("placeholder: %d + \n" , placeholder); //printf("end: %d \n", bufferIteratorT); } //token insertion here. if (first == ' ' || first == '\t' || comment == 1) { //Don't insert } else { token temp; temp.type = type; temp.linNum = linNumber; if ( type == WORD_TOKEN) { temp.words = (char*) checked_malloc ((sizeof(char)*wordlength)+1); int i = 0; for (; i != wordlength;i++) { temp.words[i] = buffer[placeholder+i]; } temp.words[i] = '\0'; } else { temp.words = NULL; } //now insert into token stream token_stream* temp_ts = (token_stream*) checked_malloc(sizeof(token_stream*)); temp_ts->m_token = temp; //might have a serious problem here because if m_token is just a copy of //temp and temp gets erased because temp goes out of scope (e.g. out of this function), //temp might get erased and that also deletes our character array for words, leaving a dangling pointer. temp_ts->next = NULL; temp_ts->prev = trackend; trackend->next = temp_ts; trackend = temp_ts; } bufferIteratorT++; } //now tstream should point to the beginning of a token stream //the issue is we initialize the tstream to a blank token so happens is the first token_stream in tstream is empty so we skip it. tstream = tstream->next; //=========Code that outputs the tokens so we can test them============// puts("WORD_TOKEN: 0 \nSEMICOLON_TOKEN: 1 \nPIPE_TOKEN: 2 \nAND_TOKEN: 3 \nOR_TOKEN: 4 \nLEFT_PAREN_TOKEN: 5 \nRIGHT_PAREN_TOKEN: 6 \nGREATER_TOKEN: 7 \nLESS_TOKEN: 8 \nCOMMENTS_TOKEN: 9 \nNEWLINE_TOKEN: 10 \nMISC_TOKEN: 11 \n"); //puts(tstream->m_token.words); /* while (tstream->next != NULL) { //printf("%d \n", tstream->m_token.type); //the above line works to display just the tokens, the below doesn't work because there's a segfault on accessing the token words if (tstream->m_token.type == WORD_TOKEN) { printf("%d:%i: ", tstream->m_token.type, tstream->m_token.linNum); puts(tstream->m_token.words); //puts("\n"); } else printf("%d:%i \n", tstream->m_token.type, tstream->m_token.linNum); tstream = tstream->next; } printf("%d \n", tstream->m_token.type); */ //=========Code that checks for input errors and validates the tokens before parsing tokens into commands============// int leftParenCount = 0; int rightParenCount = 0; while (tstream != NULL) { //MISC_TOKENS find inputs not in our subset syntax if (tstream->m_token.type == MISC_TOKEN) { fprintf(stderr,"%i: problem at this line in script\n", tstream->m_token.linNum); exit(0); } //Do count of parentheses if (tstream->m_token.type == LEFT_PAREN_TOKEN) leftParenCount++; if (tstream->m_token.type == RIGHT_PAREN_TOKEN) rightParenCount++; if (tstream->next == NULL && leftParenCount != rightParenCount) { fprintf(stderr,"%i: Unmatching Parentheses\n", tstream->m_token.linNum); //not sure about this exit(0); } //Redirec always followed by a word. if (tstream->m_token.type == LESS_TOKEN || tstream->m_token.type == GREATER_TOKEN) { if (tstream->next == NULL) { fprintf(stderr,"%i: Redirect Needs a word following it.\n", tstream->m_token.linNum); exit(0); } else if (tstream->next->m_token.type != WORD_TOKEN) { fprintf(stderr,"%i: Need word after redirect\n", tstream->m_token.linNum); exit(0); } } //Newlines have some specific places they can appear in. if (tstream->m_token.type == NEWLINE_TOKEN) { //check the ones after it for ( ) or words if (tstream->next != NULL) { if (tstream->next->m_token.type == LEFT_PAREN_TOKEN || tstream->next->m_token.type == RIGHT_PAREN_TOKEN || tstream->next->m_token.type == WORD_TOKEN) {} else { fprintf(stderr,"%i: newline is followed by (,), or words\n", tstream->m_token.linNum); exit(0); } } } tstream = tstream->next; } // idea here it to represent problems parsing the code with MISC_TOKEN and have code up in the tokenization part where if the //token is a MISC token, store the line number into the char* words array and if we detect it here, then output it with the line number. //=========Changes the tokens into commands============// command_stream_t fake = (command_stream_t) checked_malloc(sizeof(command_stream_t)); fake->size = 1; fake->iterator = 0; return fake; }