command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_arg) { size_t count = 0; size_t buffer_size = 1000; char* buffer = checked_malloc(buffer_size); //create a buffer of charactors to store the readin chars // create buffer of input with comments stripped out char ch; do { ch = get_next_byte(get_next_byte_arg); if (ch == '#') // for comments: ignore everything until '\n' or EOF { ch = get_next_byte(get_next_byte_arg); while(ch != EOF && ch!='\n') ch = get_next_byte(get_next_byte_arg); } //skip all the words until \n if (ch!= -1) { // load into buffer buffer[count] = ch; count++; // expand buffer if necessary //if (count == INT_MAX) //{ // error(1, 0, "Line -1: Input size over INT_MAX."); //} if (count == buffer_size) { buffer_size = buffer_size * 2; buffer = checked_grow_alloc (buffer, &buffer_size); } } } while(ch != -1); token_stream_t return_point = convert_buffer_to_token_stream(buffer,count); //build command_tree //nuild the first command_tree //command_stream_t command_stream_first = init_command_stream (); command_t new_command_t = make_command_tree (return_point); add_command_to_stream(new_command_t ); //build the rest command_tree while (return_point->next != NULL) { //make return_point point to next token stream token_stream_t temp = return_point->next; //free(return_point); return_point = temp; new_command_t = make_command_tree (return_point); add_command_to_stream(new_command_t); } return command_stream_head; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { //current character char curr; int tree_number = 1; char prev_char_stored = '\0'; int consecutive_newlines = 0; //buffer size = 1KB int BUFFER_SIZE = 1024; //buffer to read characters into; buffer can hold 1024 chars at once char *buffer = (char *) checked_malloc(BUFFER_SIZE * sizeof(char)); //int to count how many chars are in buffer int numChars = 0; //int to count which line we are on //int syntax_line_counter = 0; int invalid_char_line_counter = 1; //if this is true, we are searching for the right operand of an operator bool found_AND_OR_PIPE_SEQUENCE = false; //looking for operand //declare command stream and allocate space //maybe dont need to allocate space because initStream() already does? command_stream_t theStream; // = (command_stream_t) checked_malloc(sizeof(struct command_stream)); //initialize command_stream theStream = initStream(); //start reading the chars from the input while ((curr = get_next_byte(get_next_byte_argument)) != EOF ) { if (numChars > 0){ //only stores previous meaningful character, i.e. not whitespace if ((buffer[numChars-1] != ' ' && buffer[numChars-1] != '#')){ prev_char_stored = buffer[numChars-1]; } } if (prev_char_stored == '&' || prev_char_stored == '|' || prev_char_stored == ';'){ found_AND_OR_PIPE_SEQUENCE = true; } //////////////////////////////////////////////////////////// ////////////////// NEWLINE CHAR //////////////////// //////////////////////////////////////////////////////////// /* New variables introduced: char prev_char_stored; int consecutive_newlines; bool command_has_ended; //haven't needed to use yet */ if (identify_char_type(curr) == NEWLINE_CHAR || identify_char_type(curr) == HASHTAG_CHAR){ //found a newline, increment counter consecutive_newlines++; //hit second (or more) newline if (consecutive_newlines > 1){ //not looking for an operator and if (!found_AND_OR_PIPE_SEQUENCE){ if (identify_char_type(curr) == NEWLINE_CHAR) { //add second newline to buffer buffer[numChars] = '\n'; numChars++; curr = get_next_byte(get_next_byte_argument); } /* check for newlines, whitespaces, and hashtags after second newline Store newlines on the buffer, ignore white spaces, and for hashtags: put hashtag and newline on the buffer */ while (identify_char_type(curr) == NEWLINE_CHAR || identify_char_type(curr) == WHITESPACE_CHAR || identify_char_type(curr) == HASHTAG_CHAR){ if (curr == '\n'){ buffer[numChars] = '\n'; numChars++; } else if (curr == '#'){ //add hashtag to buffer consecutive_newlines++; buffer[numChars] = '#'; numChars++; //go to end of comment while (identify_char_type(curr) != NEWLINE_CHAR){ if ((curr = get_next_byte(get_next_byte_argument)) == EOF) { break; } } //broke out of loop, curr is now a newline char; add to buffer buffer[numChars] = '\n'; numChars++; } if ((curr = get_next_byte(get_next_byte_argument)) == EOF) { break; } } consecutive_newlines = 0; //create temporary array with size of numChars; char* buffer_no_whitespaces = checked_malloc(BUFFER_SIZE * (sizeof(char))); //the correct syntaxed command memset(buffer_no_whitespaces, '\0', BUFFER_SIZE * sizeof(char)); //run validation, then parse if correct eatWhiteSpaces(buffer, numChars, buffer_no_whitespaces); int pos = 0; while (buffer_no_whitespaces[pos] != '\0'){ if (identify_char_type(buffer_no_whitespaces[pos]) == NEWLINE_CHAR){ invalid_char_line_counter++; } if (identify_char_type(buffer_no_whitespaces[pos]) == INVALID_CHAR){ identify_char_type(buffer_no_whitespaces[pos]); fprintf(stderr, "%d: Invalid character: %c <---", invalid_char_line_counter, buffer_no_whitespaces[pos]); exit(1); } pos++; } checkAndSyntax(buffer_no_whitespaces); checkForConsecutiveTokens(buffer_no_whitespaces); checkIfOperatorsHaveOperands(buffer_no_whitespaces); validParentheses(buffer_no_whitespaces); /* int i; for (i= 0; i<numChars; i++){ printf("%c", buffer_no_whitespaces[i]); } //this just separates commands printf("\n"); */ commandNode_t root = createNodeFromCommand(make_command_tree(buffer_no_whitespaces)); //printf("adding command node to stream: %s\n", root->cmd->u.word[0]); write_list_t write_list = init_write_list(); //printf("adding command node to stream: %s\n", root->cmd->u.word[0]); root->write_list = make_write_list(write_list, root->cmd); read_list_t read_list = init_read_list(); root->read_list = make_read_list(read_list, root->cmd); root->tree_number=tree_number; root->dependency_list = (commandNode_t*)(checked_realloc(root->dependency_list, (tree_number) * sizeof(commandNode_t))); memset (root -> dependency_list, '\0', (tree_number) * sizeof(commandNode_t)); //printf("adding command node to stream: %s\n", root->cmd->u.word[0]); addNodeToStream(theStream, root); //reset everything with memset memset(buffer, '\0', BUFFER_SIZE * sizeof(char)); free(buffer_no_whitespaces); numChars = 0; consecutive_newlines = 0; tree_number++; if (curr == EOF) break; /* We are now at a new command. Add first character to buffer, whether valid or invalid. Will check syntax later. */ if (identify_char_type(curr) != HASHTAG_CHAR){ buffer[numChars] = curr; numChars++; } else { //add a hashtag and newline to the buffer buffer[numChars] = '#'; numChars++; //get to the end of the line while (identify_char_type(curr) != NEWLINE_CHAR){ if ((curr = get_next_byte(get_next_byte_argument)) == EOF) { break; } } //now we have a newline; add newline to buffer buffer[numChars]=curr; numChars++; consecutive_newlines++; } continue; } else { //if we are looking for operand, don't end the commmand while (identify_char_type(curr) == NEWLINE_CHAR || identify_char_type(curr) == WHITESPACE_CHAR || identify_char_type(curr) == HASHTAG_CHAR){ if (curr == '\n'){ buffer[numChars] = '\n'; numChars++; } else if (curr == '#'){ //add hashtag to buffer buffer[numChars] = '#'; numChars++; while (identify_char_type(curr) != NEWLINE_CHAR){ if ((curr = get_next_byte(get_next_byte_argument)) == EOF) { break; } } //broke out of loop, curr is now a newline char; add to buffer buffer[numChars] = '\n'; numChars++; } if ((curr = get_next_byte(get_next_byte_argument)) == EOF) { break; } } //broken out of while loop, we now have a regular character; add to buffer if (curr == EOF) break; buffer[numChars] = curr; numChars++; found_AND_OR_PIPE_SEQUENCE = false; consecutive_newlines = 0; continue; } } else { //add newline to buffer; this is when number of newlines equals one if (identify_char_type(curr) == HASHTAG_CHAR) { buffer[numChars] = '#'; numChars++; while (identify_char_type(curr) != NEWLINE_CHAR){ if ((curr = get_next_byte(get_next_byte_argument)) == EOF) { break; } } } buffer[numChars] = '\n'; numChars++; continue; } } //end newline case else { if (!found_AND_OR_PIPE_SEQUENCE && consecutive_newlines == 1) { buffer[numChars] = ';'; numChars++; } buffer[numChars] = curr; numChars++; consecutive_newlines = 0; //if we are here we no longer skip lines found_AND_OR_PIPE_SEQUENCE = false; } } char* buffer_no_whitespaces = checked_malloc(BUFFER_SIZE * (sizeof(char))); //the correct syntaxed command memset(buffer_no_whitespaces, '\0', BUFFER_SIZE * sizeof(char)); //run validation, then parse if correct //void eatWhiteSpaces(char *buffer, int bufferSize, char *newArray) eatWhiteSpaces(buffer, numChars, buffer_no_whitespaces); int pos = 0; while (buffer_no_whitespaces[pos] != '\0'){ if (identify_char_type(buffer_no_whitespaces[pos]) == NEWLINE_CHAR){ invalid_char_line_counter++; } if (identify_char_type(buffer_no_whitespaces[pos]) == INVALID_CHAR){ identify_char_type(buffer_no_whitespaces[pos]); fprintf(stderr, "%d: Invalid character: %c <---", invalid_char_line_counter, buffer_no_whitespaces[pos]); exit(1); } pos++; } checkAndSyntax(buffer_no_whitespaces); checkForConsecutiveTokens(buffer_no_whitespaces); checkIfOperatorsHaveOperands(buffer_no_whitespaces); validParentheses(buffer_no_whitespaces); /* if (buffer_no_whitespaces[0] != '\0') { int i; for (i= 0; i<numChars; i++){ printf("%c", buffer_no_whitespaces[i]); } printf("\n"); }*/ //make sure buffer_no_whitespace is not empty if (buffer_no_whitespaces[0] != '\0') { commandNode_t root = createNodeFromCommand(make_command_tree(buffer_no_whitespaces)); write_list_t write_list = init_write_list(); root->write_list = make_write_list(write_list, root->cmd); read_list_t read_list = init_read_list(); root->read_list = make_read_list(read_list, root->cmd); root->tree_number=tree_number; root->dependency_list = (commandNode_t*)(checked_realloc(root->dependency_list, (tree_number) * sizeof(commandNode_t))); memset (root -> dependency_list, '\0', (tree_number) * sizeof(commandNode_t)); //printf("adding command node to stream: %s\n", root->cmd->u.word[0]); addNodeToStream(theStream, root); } free(buffer); free(buffer_no_whitespaces); theStream->blocked_commands = (commandNode_t*)checked_realloc(theStream->blocked_commands, theStream->num_nodes * sizeof(commandNode_t)); memset(theStream->blocked_commands, '\0', theStream->num_nodes * sizeof(commandNode_t)); return theStream; }
command_stream_t main() { char* script_name = "test.sh"; FILE *script_stream = fopen (script_name, "r"); int buffer_size=1000; char* buffer = (char* )malloc(buffer_size); size_t count = 0; char ch; do { ch = get_next_byte(script_stream); if (ch == '#') // for comments: ignore everything until '\n' or EOF { ch = get_next_byte(script_stream); while(ch != EOF && ch!='\n') ch = get_next_byte(script_stream); } //skip all the words until \n if (ch!= -1) { // load into buffer buffer[count] = ch; count++; // expand buffer if necessary //if (count == INT_MAX) //{ // error(1, 0, "Line -1: Input size over INT_MAX."); //} if (count == buffer_size) { buffer_size = buffer_size * 2; buffer = (char*)realloc (buffer, buffer_size); } } } while(ch != -1); //token_stream_t return_point =convert_buffer_to_token_stream(buffer, count); //printf("convert end\n"); token_stream_t return_token_stream = convert_buffer_to_token_stream(buffer, count); /* if(return_token_stream==NULL) printf("NULL pointer\n"); else { if(return_token_stream->head == NULL) printf("NULL head\n"); else { printf("head is not null\n" ); printf("%d\n",return_token_stream->head->t_type); printf("%c\n",return_token_stream->head->next->text[0]); if(return_token_stream->head->next->next != NULL) { printf("linked"); printf("%d\n",return_token_stream->head->next->next->t_type); } } } if(return_token_stream->next==NULL) printf("NEXT is NULL pointer\n"); else { if(return_token_stream->next->head == NULL) printf("NEXT NULL head\n"); else { printf("head is not null\n" ); printf("%d\n",return_token_stream->next->head->t_type); printf("%c\n",return_token_stream->next->head->next->text[0]); if(return_token_stream->next->head->next->next->next == NULL) printf("YEAH"); } } printf("main end");*/ command_t new_command_t = make_command_tree (return_token_stream); printf("make tree end\n"); add_command_to_stream(new_command_t ); while (return_token_stream->next != NULL) { //make return_point point to next token stream return_token_stream = return_token_stream->next; //free(return_point); //return_token_stream = temp; new_command_t = make_command_tree (return_token_stream); add_command_to_stream(new_command_t); } return command_stream_head; }
command_t make_command_tree(token_stream_t t) { if(t==NULL) printf("NULL pointer\n"); else { if(t->head == NULL) printf("NULL head\n"); else { printf("head is not null\n" ); printf("%d\n",t->head->t_type); printf("%c\n",t->head->next->text[0]); /*if(return_token_stream->head->next->next != NULL) { printf("linked"); printf("%d\n",return_token_stream->head->next->next->t_type); }*/ } } token_t sub_head = t->head;//the sub_head is t->head token_t token_now = sub_head; stack_t operators = initStack();//(stack_t)malloc(sizeof(Stack)); stack_t operands = initStack();//(stack_t)malloc(sizeof(Stack));//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)malloc(sizeof( struct command )); } 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**)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; i++; //if(i == num_words) } comm->u.word[num_words] = NULL; push(operators,comm); token_now = token_now->next; break; case SUBSHELL: comm->type = SUBSHELL_COMMAND; // process subshell command tree comm->u.subshell_command = make_command_tree( convert_buffer_to_token_stream(token_now->text, strlen(token_now->text)) ); // push SUBSHELL tree to operands push(operands, comm); 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; } else { // error(2, 0, "Line %d: Syntax error. Redirects must be followed by words.", line); return NULL; } // 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; } else { //error(2, 0, "Line %d: Syntax error. Redirects must be followed by words.", line); return NULL; } // no pushing required break; default: token_now = token_now->next; break; }; // prev = comm; } 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;*/ }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { /* FIXME: Replace this with your implementation. You may need to add auxiliary functions and otherwise modify the source code. You can also use external functions defined in the GNU C Library. */ size_t buffer_size=1000; char* buffer = (char* )checked_malloc(buffer_size); size_t count = 0; char ch; do { ch = get_next_byte(get_next_byte_argument); if (ch == '#') // for comments: ignore everything until '\n' or EOF { ch = get_next_byte(get_next_byte_argument); while(ch != EOF && ch!='\n') ch = get_next_byte(get_next_byte_argument); } //skip all the words until \n if (ch!= -1) { // load into buffer buffer[count] = ch; count++; // expand buffer if necessary //if (count == INT_MAX) //{ // error(1, 0, "Line -1: Input size over INT_MAX."); //} if (count == buffer_size) { buffer_size = buffer_size * 2; buffer = (char*)checked_realloc (buffer, buffer_size); } } } while(ch != -1); token_stream_t return_token_stream = convert_buffer_to_token_stream(buffer, count); command_t new_command_t = make_command_tree (return_token_stream); // printf("make tree end\n"); add_command_to_stream(new_command_t ); // printf("add first command to stream\n"); // printf("command type : %d\n", new_command_t->type); //if(new_command_t == NULL) // printf("HAHA"); // print_command(new_command_t); while (return_token_stream->next != NULL) { //make return_point point to next token stream return_token_stream = return_token_stream->next; //free(return_point); //return_token_stream = temp; new_command_t = make_command_tree (return_token_stream); add_command_to_stream(new_command_t); // printf("add another command to stream\n"); //print_command(new_command_t); } // printf("return to main\n"); // print_command() return command_stream_head; }