/** * Mark a single dependency on the list_node LIST by adding a pointer (to char * WORD) * to LIST->write_list (if WRITE) or LIST->read_list (if not WRITE). **/ void mark_read_write(list_node *list, char *word, bool write) { // ignore options char first = word[0]; if (first == '-') { return; } if (write) { // write list->write_size++; if (list->write_list) { list->write_list = (char **)checked_realloc(list->write_list, list->write_size*sizeof(char*)); } else { list->write_list = (char **)checked_malloc(list->write_size*sizeof(char*)); } list->write_list[list->write_size-1] = word; } else { // read list->read_size++; if (list->read_list) { list->read_list = (char **)checked_realloc(list->read_list, list->read_size*sizeof(char*)); } else { list->read_list = (char **)checked_malloc(list->read_size*sizeof(char*)); } list->read_list[list->read_size-1] = word; } }
void get_files(command_t cmd, char ***ip_array, char ***op_array, int *input_size, int *output_size) { if(cmd == NULL) { return; } switch(cmd->type) { case AND_COMMAND: case SEQUENCE_COMMAND: case OR_COMMAND: case PIPE_COMMAND: get_files(cmd->u.command[0],ip_array,op_array,input_size,output_size); get_files(cmd->u.command[1],ip_array,op_array,input_size,output_size); break; case SUBSHELL_COMMAND: if(cmd->input != NULL) { *ip_array = (char**)checked_realloc(*ip_array,(*input_size+1)*sizeof(char*)); copy_file(*ip_array,cmd->input,input_size); } if(cmd->output != NULL) { *op_array = (char**)checked_realloc(*op_array,(*output_size+1)*sizeof(char*)); copy_file(*op_array,cmd->output,output_size); } get_files(cmd->u.subshell_command,ip_array,op_array,input_size,output_size); break; case SIMPLE_COMMAND: if(cmd->input != NULL) { *ip_array = (char**)checked_realloc(*ip_array,(*input_size+1)*sizeof(char*)); copy_file(*ip_array,cmd->input,input_size); } if(cmd->output != NULL) { *op_array = (char**)checked_realloc(*op_array,(*output_size+1)*sizeof(char*)); copy_file(*op_array,cmd->output,output_size); } char **w = cmd->u.word; /*start at the second word, first word is the command */ w++; while(*w) { *ip_array = (char**)checked_realloc(*ip_array,(*input_size+1)*sizeof(char*)); copy_file(*ip_array,*w,input_size); w++; } break; default: return; } return; }
void _bdd_mgr_double_capacity (bdd_mgr_t *mgr) { unsigned old_capacity = mgr->capacity; fprintf (stderr, "!!! begin double\n"); mgr->capacity *= 2; mgr->nodes = (node_t *) checked_realloc (mgr->nodes, mgr->capacity * sizeof (node_t)); _initialize_nodes (mgr->nodes, old_capacity, mgr->capacity); mgr->nodes_hash = (unsigned *) checked_realloc (mgr->nodes_hash, _bdd_mgr_num_hash_buckets (mgr) * sizeof (unsigned)); _bdd_mgr_rehash (mgr); fprintf (stderr, "!!! end double\n"); }
command_t get_simple_command(command_stream_t buff) { int numofchar = 0; int word_size = 20; int current_line; int i = 0; command_t s = checked_malloc(sizeof(struct command)); s->u.word = checked_malloc(sizeof(char*) * word_size); buff = get_token(buff); if(buff->current_token != WORD_T) error (1, 0, "Line %d: syntax error near unexpected token %s, it needs to be a WORD" , buff->linenum, buff->next_string); s->u.word[i] = checked_malloc(sizeof(char*) * strlen(buff->current_string)); strcpy(s->u.word[i++], buff->current_string); while(buff->next_token == WORD_T && (buff = get_token(buff))) { s->u.word[i] = checked_malloc(sizeof(char*) * strlen(buff->current_string)); strcpy(s->u.word[i++], buff->current_string); if(i >= word_size) { word_size += 20; s->u.word = checked_realloc(s->u.word, sizeof(char*)* word_size); } } s->u.word[i] = '\0'; s->type = SIMPLE_COMMAND; s->canfork = 1; return s; }
// increase array size for dep node output files void grow_out_ptr(dep_node_t dn) { dep_node_out_array_size += DEP_NODE_IO_ARRAY_GROW; char **temp = checked_realloc(dn->out, dep_node_out_array_size * sizeof(char**)); if (temp == NULL) error(1, 0, "Error with memory reallocation\n"); dn->out = temp; }
void * checked_grow_alloc (void *ptr, size_t *size) { size_t max = -1; if (*size == max) memory_exhausted (0); *size = *size < max / 2 ? 2 * *size : max; return checked_realloc (ptr, *size); }
/** * Check for dependencies on a list_node LIST by checking list_nodes which have already * been checked and processed. Will compare LIST.read_list and LIST.write_list to the read * and write lists of all list_nodes attached to global variable depend_head (which have already * been processed). **/ void check_dependencies(list_node *list) { list_node *others = depend_head; while (others) { // if others is a dependency of list bool dependency = false; int other_read_idx = 0; int other_write_idx = 0; int list_read_idx = 0; int list_write_idx = 0; // check list's WL against other RLs for (other_read_idx = 0; other_read_idx < others->read_size && !dependency; other_read_idx++) { for (list_write_idx = 0; list_write_idx < list->write_size; list_write_idx++) { if (strcmp(others->read_list[other_read_idx], list->write_list[list_write_idx]) == 0) { dependency = true; break; } } } // check list's RL & WL against other WLs for (other_write_idx = 0; other_write_idx < others->write_size && !dependency; other_write_idx++) { // check list's RL for (list_read_idx = 0; list_read_idx < list->read_size; list_read_idx++) { if (strcmp(others->write_list[other_write_idx], list->read_list[list_read_idx]) == 0) { dependency = true; break; } } // check list's WL for (list_write_idx = 0; list_write_idx < list->write_size; list_write_idx++) { if (strcmp(others->write_list[other_write_idx], list->write_list[list_write_idx]) == 0) { dependency = true; break; } } } // add others as a dependency on list if (dependency) { graph_node *node = list->node; node->before_size++; if (node->before) { node->before = (graph_node **)checked_realloc(node->before, node->before_size*sizeof(graph_node*)); } else { node->before = (graph_node **)checked_malloc(node->before_size*sizeof(graph_node*)); } node->before[node->before_size-1] = others->node; } others = others->next; } }
static void vector_resize(vector* vec) { if (vec->length == vec->max_length) { vec->array = checked_realloc(vec->array, vec->max_length * vec->element_size *2); vec->max_length *= 2; } }
void append_arvore_vec(arvore_vec* v, arvore a) { if (v->size == v->capacity) { v->array = (arvore*) checked_realloc(v->array, sizeof(arvore) * (v->capacity *= 2)); } v->array[v->size++] = a; }
void add_char(char** list, int curr, char c) { /* This function adds a character to a current complete command"*/ char* str = list[curr]; char* tmp = NULL; int length = 0; if(str == NULL) { tmp = (char*)checked_realloc(str,sizeof(char)*2); tmp[0] = c; tmp[1] = '\0'; list[curr] = tmp; return; } length = strlen(str); tmp = (char*)checked_realloc(str,sizeof(char)*(2+length)); tmp[length] = c; tmp[length+1] = '\0'; list[curr] = tmp; return; }
VOID reallocate_writeArray_stride(){ ADDRINT* ptr; numWrite *= 2; ptr = (ADDRINT*) checked_realloc(instrWrite, numWrite * sizeof(ADDRINT)); /*if (ptr == (ADDRINT*) NULL) { cerr << "Not enough memory (in reallocate_writeArray_stride)" << endl; exit(1); }*/ instrWrite = ptr; }
//auxiliary function for make_command int getNextWord(int start, char *token, char **word){ int bufferSize = 50; int i; (*word)[0] = '\0'; for(i = 0; !isEndOfWord(token[start]); i++){ if(i > bufferSize){ bufferSize += 10; *word = checked_realloc(word, bufferSize); } (*word)[i] = token[start]; start++; //test 4 if((*word)[i] == '>' || (*word)[i] == '<'){ break; } } return start; }
char* makeInputStream(int (*get_next_byte) (void *), void *get_next_byte_argument) { int inputStreamSize = 100; int byteCount = 0; int c; char *inputStream = (char*)checked_malloc(inputStreamSize*sizeof(char)); while ((c = get_next_byte(get_next_byte_argument)) != EOF) { inputStream[byteCount] = c; byteCount++; if (byteCount == inputStreamSize) { inputStreamSize += 100; inputStream = checked_realloc(inputStream, inputStreamSize*sizeof(char)); } } inputStream[byteCount] = EOF; byteCount++; return inputStream; }
//auxiliary function purely to grab input/output files int getInputOutput(int start, char *token, char**word){ while(isWhiteSpace(token[start])){ start++; } if(isOperator(token[start]) || token[start] == '\0'){ fprintf(stderr, "%d: Incorrect Syntax1 \n", line_number); exit(1); } int bufferSize = 50; int i = 0; while(!isWhiteSpace(token[start]) && token[start]!='\0'){ if(i > bufferSize){ bufferSize += 50; *word = checked_realloc(word, bufferSize); } (*word)[i] = token[start]; start++; i++; } (*word)[i] = '\0'; return start; }
void process_file_list_file(char *filename) { FILE *fp; char *line; fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "%s: error opening file `%s': %s\n", MR_progname, filename, strerror(errno)); num_errors++; return; } /* initialize the files structure, if required */ if (files == NULL) { num_files = 0; size_of_files = NUMFILES; files = (char **) checked_malloc(sizeof(char *) * NUMFILES); } while ((line = read_line(filename, fp, MAXFILENAME)) != NULL) { /* Ignore blank lines */ if (line[0] != '\0') { if (num_files >= size_of_files) { size_of_files *= FACTOR; files = (char **) checked_realloc(files, size_of_files * sizeof(char *)); if (files == NULL) { fprintf(stderr, "%s: unable to realloc\n", MR_progname); exit(EXIT_FAILURE); } } files[num_files] = line; num_files++; } } }
// create dependency list for time traveling void setup_new_dep_node(command_t c) { dep_node_in_array_size = DEP_NODE_IO_ARRAY_GROW; // reset IO memory allocations dep_node_out_array_size = DEP_NODE_IO_ARRAY_GROW; if(numOfDepNodes == 0) // haven't created Dependency Node Tree yet { dep_access = checked_malloc(dep_node_array_size * sizeof(dep_node_t)); if (dep_access == NULL) error(1, 0, "Error with memory allocation\n"); } if(numOfDepNodes == dep_node_array_size) // need to grow array for more dep nodes { dep_node_array_size += DEP_NODE_ARRAY_GROW; dep_node_t *temp = checked_realloc(dep_access, dep_node_array_size * sizeof(dep_node_t)); if (temp == NULL) error(1, 0, "Error with memory reallocation\n"); dep_access = temp; } dep_access[numOfDepNodes] = checked_malloc(sizeof(struct dep_node)); if (dep_access[numOfDepNodes] == NULL) error(1, 0, "Error with memory allocation\n"); init_dep_node(c, dep_access[numOfDepNodes]); // initialize dep node }
command_stream_t make_command_stream(int (*get_next_byte) (void *), void *get_next_byte_argument) { //building the stream string int lineNum = 1; ////printf("Step 1: Building the buffer string.\n"); char currChar; char* buffer = (char*) checked_malloc(sizeof(char)); int bufferSize = 0; while((currChar = get_next_byte(get_next_byte_argument)) != EOF) { if(currChar == '\n') { lineNum++; } if(!isCharValid(currChar)) { error(1,0,"%d: Syntax error (Illegal character %c found.) \n", lineNum, currChar); } else if (currChar == '#') { //while(currChar != '\n' && currChar != EOF) while((currChar = get_next_byte(get_next_byte_argument)) != EOF && currChar != '\n') { } if(feof(get_next_byte_argument)) { error(1,0,"%d: Syntax error (Comments need to be terminated with new line)\n", lineNum); } else { lineNum++; } } buffer[bufferSize] = currChar; bufferSize++; buffer = (char*)checked_realloc(buffer, bufferSize+1); } buffer[bufferSize] = '\0'; ////printf("Step 1: Buffer Built \n%s\n Strlen(buffer) = %d, bufferSize = %d\n", buffer, strlen(buffer), bufferSize); ////printf("Step 2: Clean up iteration started.\n"); lineNum = 1; int prev = -1; int n; //next nonwhite space index int curr = nextIndex(buffer, bufferSize, -1); int next = nextIndex(buffer, bufferSize, curr); while (curr < bufferSize) { ////printf("Step 2: prev = %d, curr = %d, next = %d.\n", prev, curr, next); switch (buffer[curr]) { case ';': n = nextNonwhitespace(buffer, bufferSize, curr); if ((prev==-1) || (n == bufferSize) || !(isWordChar(buffer[prev])||buffer[prev] == ')') //(;) );( || !(isWordChar(buffer[n])||buffer[n] == '(')) { error(1,0,"%d: Syntax error (Incomplete operators %c found)\n", lineNum, buffer[curr]); } break; case '>': case '<': //if ((prev==-1) || (nextNonwhitespace(buffer, bufferSize, curr) == bufferSize) // ||(isOperator(buffer[prev])) || (isOperator(buffer[next]))) if ((prev==-1) || (nextNonwhitespace(buffer, bufferSize, curr) == bufferSize) || !isWordChar(buffer[prev]) || !isWordChar(buffer[next])) { error(1,0,"%d: Syntax error (Incomplete operators %c found)\n", lineNum, buffer[curr]); } break; case '&': if (buffer[next] == '&' && next-curr == 1) { buffer[curr] = '*'; buffer[next] = ' '; next = nextIndex(buffer, bufferSize, curr); n = nextNonwhitespace(buffer, bufferSize, curr); if ((prev==-1) || (n==bufferSize) || !(isWordChar(buffer[prev])||buffer[prev] == ')') //(;) );( || !(isWordChar(buffer[n])||buffer[n] == '(')) { error(1,0,"%d: Syntax error (Incomplete operators %c found)\n", lineNum, buffer[curr]); } } else { error(1,0,"%d: Syntax error (Incomplete operators %c found)\n", lineNum, buffer[curr]); } break; case '|': if (buffer[next] == '|' && next-curr == 1) { buffer[curr] = '$'; buffer[next] = ' '; next = nextIndex(buffer, bufferSize, curr); } n = nextNonwhitespace(buffer, bufferSize, curr); if ((prev==-1) || (n==bufferSize) || !(isWordChar(buffer[prev])||buffer[prev] == ')') //(;) );( || !(isWordChar(buffer[n])||buffer[n] == '(')) { error(1,0,"%d: Syntax error (Incomplete operators %c found)\n", lineNum, buffer[curr]); } break; case '\n': if ((prev!=-1) && (buffer[prev] == '<' || buffer[prev] == '>')) { error(1,0,"%d: Syntax error (New line character can only follow tokens other than < >.)\n", lineNum); } if (buffer[next] == '\n') { if(buffer[prev] != '$' && buffer[prev] != '*' && buffer[prev] != '|') { buffer[curr] = '@'; } else { buffer[curr] = ' '; } buffer[next] = ' '; lineNum++; next = nextIndex(buffer, bufferSize, next); while (buffer[next] == '\n') { buffer[next] = ' '; next = nextIndex(buffer, bufferSize, next); lineNum++; } } else if ((prev!=-1) && (next!=bufferSize) && ((isOperator(buffer[prev])) || (buffer[prev]=='('))) { buffer[curr] = ' '; } else if ((prev!=-1) && (next!=bufferSize) && ((isWordChar(buffer[prev])) || (buffer[prev]==')'))) { buffer[curr] = ';'; } if ((next!=bufferSize) && (!(buffer[next] == '(' || buffer[next]==')' || isWordChar(buffer[next])))) { error(1,0,"%d, Syntax error (New line character can only be followed by (, ), or Words.)\n", lineNum); } lineNum++; break; } prev = curr; curr = next; next = nextIndex(buffer, bufferSize, curr); } ////printf("Step 2: Buffer cleaned \n%s\n Strlen(buffer) = %d, bufferSize = %d\n", buffer, strlen(buffer), bufferSize); ////printf("Step 3: Parenthesis check start.\n"); int stackSize = 0; int i; for (i = 0; i < bufferSize; i++) { if (buffer[i] == '(') { stackSize++; } else if (buffer[i] == ')') { if(stackSize > 0) { stackSize--; } else { error(1,0,"Syntax error (Unbalanced parenthesis found)\n"); } } } if (stackSize > 0) { error(1,0,"Syntax error (Unbalanced parenthesis found)"); } ////printf("Step 3: Parenthesis check complete.\n"); ////printf("Step 4: Outputting\n"); command_stream_t cstream = (command_stream_t) checked_malloc(sizeof(struct command_stream)); cstream->stream = buffer; cstream->index = 0; if (debug) printf("Buffer: \"%s\"\n", buffer); return cstream; }
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; }
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_head= (token_stream_t)checked_malloc(sizeof(token_stream_t)); token_stream_t curr_stream = token_stream_head; 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 token_stream_head; }
void increase_file_array(FileArray* n) { n->size *=2; n->files = checked_realloc(n->files, n->size*sizeof(*n->files)); }
command_t parse_token_to_command(token_stream_t tst) { token_t next_token = token_stream_current(tst); if (!next_token) return NULL; command_t head; command_t cur = NULL; command_t prev; while (next_token) { char *current_token_char = next_token->string; int current_token_type = next_token->type; int num_words = 1; int phrase_index = 0; int status = -1; char **phrase = checked_malloc((num_words + 1) * sizeof(char*)); char *input = NULL, *output= NULL; command_t temp = checked_malloc(sizeof(struct command)); command_t temp_sub; phrase[phrase_index + 1] = NULL; switch (next_token->type) { case WORD: { phrase[phrase_index] = next_token->string; phrase_index++; token_stream_read(tst); free(next_token); next_token = token_stream_current(tst); while (next_token && next_token->type == WORD) { num_words++; phrase = checked_realloc(phrase, (num_words + 1) * sizeof(char*)); phrase[phrase_index + 1] = NULL; phrase[phrase_index] = next_token->string; phrase_index++; token_stream_read(tst); free(next_token); next_token = token_stream_current(tst); } if (next_token && next_token->type == IN) { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); input = next_token->string; token_stream_read(tst); free(next_token); next_token = token_stream_current(tst); } if (next_token && next_token->type == OUT) { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); output = next_token->string; token_stream_read(tst); free(next_token); next_token = token_stream_current(tst); } temp->type = SIMPLE_COMMAND; temp->status = status; temp->input = input; temp->output = output; temp->u.word = phrase; break; } case OPEN_PAREN: { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); temp_sub = parse_token_to_command(tst); next_token = token_stream_current(tst); current_token_char = next_token->string; current_token_type = next_token->type; if (next_token && next_token->type == IN) { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); input = next_token->string; token_stream_read(tst); free(next_token); next_token = token_stream_current(tst); } if (next_token && next_token->type == OUT) { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); output = next_token->string; token_stream_read(tst); free(next_token); next_token = token_stream_current(tst); } temp->type = SUBSHELL_COMMAND; temp->status = status; temp->input = input; temp->output = output; temp->u.subshell_command = temp_sub; break; } case CLOSE_PAREN: { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); return head; } case PIPE: { temp->type = PIPE_COMMAND; temp->status = status; token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); break; } case OR: { temp->type = OR_COMMAND; temp->status = status; token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); break; } case AND: { temp->type = AND_COMMAND; temp->status = status; token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); break; } case SEQ: { temp->type = SEQUENCE_COMMAND; temp->status = status; token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); if (!next_token || next_token->type == NEWLINE || next_token->type == CLOSE_PAREN) { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); return head; } break; } case NEWLINE: { token_stream_read(tst); free_token(next_token); next_token = token_stream_current(tst); return head; break; } } if (!cur) { cur = temp; head = cur; } else if (precedence_command(temp) <= precedence_command(cur)) { if (head != cur) cur = head; prev = cur; cur = temp; head = cur; cur->u.command[0] = prev; } else if (precedence_command(temp) > precedence_command(cur)) { if (!cur->u.command[1]) cur->u.command[1] = temp; else { temp->u.command[0] = cur->u.command[1]; cur->u.command[1] = temp; prev = cur; cur = temp; } } } return head; }
/* FIXME: Define the type 'struct command_stream' here. This should complete the incomplete type declaration in command.h. */ 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. */ if (DEBUG) printf("291 Begin make_command_stream\n"); initStream(); size_t sizeofBuffer = 1024; char* buffer = (char*)checked_malloc(sizeofBuffer); char curr; size_t filled = 0; while ((curr = get_next_byte(get_next_byte_argument)) != EOF) { buffer[filled] = curr; filled++; if (filled == sizeofBuffer) { sizeofBuffer *= 2; buffer = (char*)checked_grow_alloc(buffer, &sizeofBuffer); } } //***For the parser: //Word int bufferWordSize = 10; int currWord = 0; //char ** wordElement; char** wordElement = checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); int usedWord = 0; //Input int bufferInputSize = 10; char* inputElement = (char*)checked_malloc(bufferInputSize); int usedInput = 0; //Output int bufferOutputSize = 10; char* outputElement = (char*)checked_malloc(bufferOutputSize); int usedOutput = 0; //***Initialize operator and command stacks initStacks(); if (DEBUG) printf("333 Buffer created, initStacks()\n"); int i = 0; while (i < (int)filled) { if (DEBUG) printf("on buffer %d\n", i); //***When you want to add a character*************************// int op = -1; int openCount = 0; int closedCount = 0; if (buffer[i] == '`') error(1, 0, "Line %d: %c", __LINE__, buffer[i]); if (buffer[i] == '(') { openCount = 1; closedCount = 0; int x = i; while (x < (int) filled) { x++; if (buffer[x] == '(') openCount++; if (buffer[x] == ')') closedCount++; if (closedCount == openCount) break; } if (closedCount != openCount) error(1, 0, "Line %d: Expected ')' for end of subshell", __LINE__); } if(buffer[i] == ')') { if(openCount == 0) error(1, 0, "Line %d: Expected '(' before ')'", __LINE__); } if(buffer[i] = '(') { op = numberOfOper(&buffer[i]); processOperator(op); } //Case of ' ' while (buffer[i] == ' ' && usedWord == 0) i++; if (buffer[i] == ' ' && usedWord != 0) { if (usedWord >= bufferWordSize) { bufferWordSize += 10; wordElement[currWord] = (char*)checked_realloc(wordElement[currWord], bufferWordSize); } //i++; wordElement[currWord][usedWord] = '\0'; while (buffer[i + 1] == ' ') i++; usedWord = 0; bufferWordSize = 10; currWord++; wordElement[currWord] = (char*)checked_malloc(bufferWordSize); //wordElement[currWord][usedWord] = buffer[i]; //usedWord++; } //Case of carrots //WHAT IF a<b>c>d<a....?! You're making a simple command out of a<b>c which then // must also be the word of >d<a //Case of '<' first else if (buffer[i] == '<') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if (wordElement[0][0] == '\0') error(1, 0, "Line %d: No command given to '<'", __LINE__); i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("378 Complete command, free buffer bc EOF\n"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } inputElement[usedInput] = buffer[i]; usedInput++; i++; } } if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } if (usedInput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); inputElement[usedInput] = '\0'; usedInput++; if (buffer[i] == '>') { i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("413 Complete command, free buffer at EOF\n"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } outputElement[usedOutput] = buffer[i]; usedOutput++; i++; } } if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } if (usedOutput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); outputElement[usedOutput] = '\0'; usedOutput++; //i--; //Check logic } i--; } /////CHECK FOR EXTRA i++!!!!! //Case of '>' first else if (buffer[i] == '>') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if (wordElement[0][0] == '\0') error(1, 0, "Line %d: No command given to '<'", __LINE__); i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("471 Complete Command, free buffer at EOF"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } outputElement[usedOutput] = buffer[i]; usedOutput++; i++; } } if (usedOutput >= bufferOutputSize) { bufferOutputSize += 10; outputElement = (char*)checked_realloc(outputElement, bufferOutputSize); } if (usedOutput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); outputElement[usedOutput] = '\0'; usedOutput++; if (buffer[i] == '<') { i++; while (buffer[i] != '<' && buffer[i] != '>' && buffer[i] != '&' && buffer[i] != '|' && buffer[i] != '(' && buffer[i] != ')' && buffer[i] != ';' && buffer[i] != '\n') { if (i == filled) { if (DEBUG) printf("505 Complete Command, free buffer at EOF"); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); //free(buffer); return headStream; } if (buffer[i] == ' ') i++; else { if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } inputElement[usedInput] = buffer[i]; usedInput++; i++; } } if (usedInput >= bufferInputSize) { bufferInputSize += 10; inputElement = (char*)checked_realloc(inputElement, bufferInputSize); } if (usedInput == 0) error(1, 0, "Line %d: No input after '<'", __LINE__); inputElement[usedInput] = '\0'; usedInput++; } wordElement[currWord + 1] = '\0'; /*if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if(DEBUG) printf("makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize);*/ i--; } //Operators //After every operator is encountered, use makeSimpleCommand to push the command on the stack //Case of '|' else if (buffer[i] == '|') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if (buffer[i+1] == '|' && operatorStack == NULL) error(1, 0, "Line %d: Missing pipe for '||'", __LINE__); if (wordElement[0][0] == '\0') error(1, 0, "Line %d: Nothing for '|'", __LINE__); //if (commandStack == NULL) // error(1, 0, "Line %d: Nothing to run '|' on"); if (buffer[i + 1] == '|' && buffer[i+2] == '|') error(1, 0, "Line %d: Invalid Command, too many '|'", i); op = numberOfOper(&buffer[i]); //error(1, 0, "Line %d: Nothing to pipe", __LINE__); if (buffer[i-1] != ' ') currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf(" 566 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); if (DEBUG) printf("577 Process operator %d\n", op); processOperator(op); if (op == 3) i++; if (buffer[i + 1] == ' ') i++; //i++; } //Case of '&' else if (buffer[i] == '&') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } //if (buffer[i] == '&' && operatorStack == NULL) // error(1, 0, "Line %d: Missing pipe for '&&'", __LINE__); if (wordElement[0][0] == '\0') error(1, 0, "Line %d: Nothing for '|'", __LINE__); if (buffer[i + 1] == '&' && buffer[i+2] == '&') error(1, 0, "Line %d: Invalid Command, too many '&'", i); op = numberOfOper(&buffer[i]); if (buffer[i-1] != ' ') currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("592 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; usedWord = 0; currWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); processOperator(op); i++; if (buffer[i + 1] == ' ') i++; } //Case of ';' else if (buffer[i] == ';') { int k = i; while (buffer[k-1] == ' ') { k--; if(buffer[k-1] == '\n') error(1, 0, "Line %d: Operator and word on diff lines", __LINE__); } if(wordElement[0][0] == '\0') error(1, 0, "Line %d: Nothing before sequence", i); op = numberOfOper(&buffer[i]); currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("617 makeSimpleCommand %s\n", wordElement[0]); if ((currWord = 0) || (currWord == 1)) error(1, 0, "Line %d: Nothing to run ';' on", i); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; usedWord = 0; currWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); processOperator(op); //i++; } //Case of '\n' else if (buffer[i] == '\n' && i != 0) { /*int scChecker = i; while (buffer[i + 1] == ' ') { scChecker++; if (buffer[scChecker + 1] == ';') error(1, 0, "Line %d: Newline followed by ';'"); }*/ if (buffer[i+1] == ';') error(1, 0, "Line %d: Newline followed by ';'", i); if ((i + 1) == (int)filled) { currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("654 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); completeCommand(); free(buffer); return headStream; } char lastC; int back = 1; while (buffer[i - back] == ' ' && i - back >= 0) { //lastC = buffer[i - back]; back++; } lastC = buffer[i - back]; if (buffer[i + 1] == '\n') { while (buffer[i + 1] == '\n') i++; if (lastC != '|' && lastC != '&') { currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf("654 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); completeCommand(); } } else { if (lastC == '|' || lastC == '&' || lastC == '<' || lastC || '>') { while (buffer[i + 1] == '\n') i++;//////SPIT ERROR? } else { char swap = ';'; op = numberOfOper(&swap); wordElement[currWord + 1] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; if (DEBUG) printf(" 679 makeSimpleCommand %s\n", wordElement[0]); makeSimpleCommand(wordElement, inputElement, outputElement); bufferWordSize = 10; currWord = 0; usedWord = 0; usedInput = 0; usedOutput = 0; wordElement = (char**)checked_malloc(sizeof(char*)); wordElement[currWord] = (char*)checked_malloc(bufferWordSize); inputElement = (char*)checked_malloc(bufferInputSize); outputElement = (char*)checked_malloc(bufferOutputSize); processOperator(op); } } } //Case of # (comment) else if (buffer[i] == '#') { if (DEBUG) printf("698 Got a comment!\n"); while (buffer[i] != '\n') i++; } //Else else { if (buffer[i] == '\'') { if (buffer[i + 1] == 'E' && buffer[i + 2] == 'O' && buffer[i + 3] == 'F') break; } //if (buffer[i] != ' ') wordElement[currWord][usedWord] = buffer[i]; usedWord++; if (i + 1 == filled) { currWord++; wordElement[currWord] = '\0'; if (usedInput == 0) inputElement = NULL; if (usedOutput == 0) outputElement = NULL; makeSimpleCommand(wordElement, inputElement, outputElement); completeCommand(); } } i++; } free(buffer); return headStream; }
bool increaseSize(char* element, int used, int* bufferSize) { *bufferSize += 10; element = (char*)checked_realloc(element, 10 * (*bufferSize)); return true; }
//creates the command struct based on tokens passed in command_t make_command(char *token, command_t subcommand) { //checks for more than one <, > containsCarrot(token); command_t cmdStruct = checked_malloc(sizeof(struct command)); //for subshell if(token == NULL){ cmdStruct->type = SUBSHELL_COMMAND; cmdStruct->input = 0; cmdStruct->output = 0; cmdStruct->u.subshell_command = subcommand; return cmdStruct; } int tokenTracker = 0; //if token starts with spaces... int i; for(i = 0; isWhiteSpace(token[i]); i++){ tokenTracker++; } int start = tokenTracker; char* command = checked_malloc(50); tokenTracker = getNextWord(tokenTracker, token, &command); if(command[0] == '&'){ cmdStruct->type = AND_COMMAND; cmdStruct->input = 0; cmdStruct->output = 0; } else if (command[0] == '|'){ if(command[1] == '|'){ cmdStruct->type = OR_COMMAND; } else { cmdStruct->type = PIPE_COMMAND; } cmdStruct->input = 0; cmdStruct->output = 0; } else if (command[0] == ';'){ cmdStruct->type = SEQUENCE_COMMAND; cmdStruct->input = 0; cmdStruct->output = 0; } else if (command[0] == '<' || command[0] == '>'){ fprintf(stderr, "%d: Incorrect syntax2 \n", line_number); exit(1); } else { cmdStruct->type = SIMPLE_COMMAND; int bufferSize = 10; char** wordArray = checked_malloc(sizeof(char*)*10); int numberOfWords = 0; wordArray[numberOfWords] = checked_malloc(tokenTracker+ 1); command[tokenTracker] = '\0'; if(containsCarrot(command)){ int buffSize = 50; char* com = checked_malloc(buffSize); int comstart = 0; while(command[comstart] != '<' && command[comstart]!= '>'){ if(comstart >= buffSize){ buffSize += 50; com = checked_realloc(com, sizeof(char*)*buffSize); } com[comstart] = command[comstart]; comstart++; } wordArray[numberOfWords] = com; tokenTracker = tokenTracker - 2 ; } else{ wordArray[numberOfWords] = command; } numberOfWords++; while(token[tokenTracker] != '\0'){ char* word = checked_malloc(50); tokenTracker++; start = tokenTracker; tokenTracker = getNextWord(tokenTracker, token, &word); if(word[0] != '<' && word[0] != '>' && (word[tokenTracker-start-1] == '<' || word[tokenTracker-start-1] == '>')){ word[tokenTracker-start-1] = '\0'; tokenTracker = tokenTracker-2; } else{ word[tokenTracker-start] = '\0'; } if(word[0] == '<'){ char* in = checked_malloc(50); tokenTracker = getInputOutput(tokenTracker, token, &in); cmdStruct->input = in; } else if (word[0] == '>'){ char* output = checked_malloc(50); tokenTracker = getInputOutput(tokenTracker, token, &output); cmdStruct->output = output; } else { if(numberOfWords >= bufferSize){ bufferSize += 50; wordArray = checked_realloc(wordArray, sizeof(char*)*bufferSize); } if(word[0] != '\0'){ wordArray[numberOfWords] = checked_malloc(tokenTracker-start); wordArray[numberOfWords] = word; numberOfWords++; cmdStruct->input = 0; cmdStruct->output = 0; } } } wordArray[numberOfWords] = '\0'; cmdStruct->u.word = wordArray; } return cmdStruct; }
command_t parseCmd(char *start, char *end) { if (start>end/* || iters++>MAXITER*/) return NULL; //trim the start and end pointers start=skipWs(start); if (*start=='\0') return NULL; while (*end == ' ' || *end == '\t' || *end == '\n') { end--; } if (debug) printf("parsing: \"%.*s\" start = \'%c\' end = \'%c\'\n", end-start+1, start, *start, *end); command_t t = (command_t) checked_malloc(sizeof(struct command)); char *ptr = start; //char *op = findNextOperator(ptr); char *op = strpbrk(skipSubshell(ptr), ";$*|"); char *next = op; ////printf("parsing: start = %c op = %c next = %c \n", *ptr, *op, *next); while (next && next <= end) { char * prec = ";$*|"; int opPrec = strchr(prec, *op) - prec; int nextPrec = strchr(prec, *next) - prec; //printf("parsing: [while] opPrec = %d nextPrec = %d \n", opPrec, nextPrec); if (((opPrec == 1 || opPrec == 2) && (nextPrec == 1 || nextPrec == 2)) || (nextPrec < opPrec)) { op = next; } //printf("parsing: [while] start = %c op = %c next = %c \n", *ptr, *op, *next); //next = findNextOperator(++next); next = strpbrk(skipSubshell(++next), ";$*|"); } if (op && op<end) { // if operator in expression //////printf("op: %c\n",*op); switch(*op) { case ';': t->type=SEQUENCE_COMMAND; break; case '$': t->type=OR_COMMAND; break; case '*': t->type=AND_COMMAND; break; case '|': t->type=PIPE_COMMAND; break; default: error(1,0,"illegal operator detected"); //should not get here break; } //printf("\ncomplex command type%d: %.*s,%.*s\n", t->type, op-start, start,end-op,op+1); //t->u.command=(command_t *) checked_malloc(sizeof(command_t)*2); t->u.command[0]=parseCmd(start,op-1); t->u.command[1]=parseCmd(op+1,end); } else if (*start == '(') { //if subshell //printf("subshell command\n"); ptr = skipSubshell(ptr); t->type=SUBSHELL_COMMAND; t->u.subshell_command=(command_t) checked_malloc(sizeof(command_t)); t->u.subshell_command=parseCmd(start+1,ptr-1); } else { //simple command with no op and no subshell //if (debug) printf("Building simple command\n"); t->type=SIMPLE_COMMAND; int wdct=0;//word count tracker //construct the simple command struct from str - check for redirections char* s = start; char* e; while (s) { if(*s == '<') { s = nextWordStart(s, end); e = currWordEnd(s, end); size_t wsize = e-s+1; t->input=(char *) checked_malloc(wsize+1); memcpy(t->input,s,wsize); t->input[wsize]='\0'; if(debug) printf("Building segments: \"%.*s\" -> \'%s\'\n", e-s+1, s, t->input); } else if(*s == '>') { s = nextWordStart(s, end); e = currWordEnd(s, end); size_t wsize = e-s+1; t->output=(char *) checked_malloc(wsize+1); memcpy(t->output,s,wsize); t->output[wsize]='\0'; if(debug) printf("Building segments: \"%.*s\" -> \'%s\'\n", e-s+1, s, t->output); } else { e = currWordEnd(s, end); size_t wsize = e-s+1; size_t asize = sizeof(char*) * (wdct+2); t->u.word = (char **) checked_realloc(t->u.word, asize); t->u.word[wdct] = (char *) checked_malloc(wsize+1); memcpy(t->u.word[wdct],s,wsize); t->u.word[wdct][wsize]='\0'; wdct++; if(debug) printf("Building segments: \"%.*s\" -> \'%s\'\n", e-s+1, s, t->u.word[wdct-1]); } s = nextWordStart(e, end); } *(t->u.word+wdct)=NULL; } return t; }
//reads entire command until operators char* read_token (int (*get_next_byte) (void *), void *get_next_byte_argument, int *pos, int check_newline) { char c; int tmp_pos = *pos; int tmpSize = 50; char *token = (char*)checked_malloc(sizeof(char)*tmpSize); c = get_next_byte(get_next_byte_argument); char *paren = (char*)checked_malloc(sizeof(char)); if(!isValid(c)){ fprintf(stderr, "%d: Invalid Syntax", line_number); exit(1); } if(check_newline == 0) { while(!isOperator(c) && c != EOF && c != '\n' && c !=')') { if (c == '('){ paren[0] = '('; return paren; } if(tmp_pos > tmpSize){ tmpSize += 50; token = (char*) checked_realloc(token, sizeof(char)*tmpSize); } token[tmp_pos] = c; tmp_pos++; c = get_next_byte(get_next_byte_argument); if(!isValid(c)){ fprintf(stderr, "%d: Invalid Syntax", line_number); exit(1); } } } else { while(!isOperator(c) && c != EOF && c != ')') { if (c == '(') { paren[0] = '('; return paren; } if(tmp_pos > tmpSize){ tmpSize += 50; token = (char*) checked_realloc(token, sizeof(char)*tmpSize); } if (c == '\n') line_number++; token[tmp_pos] = c; tmp_pos++; c = get_next_byte(get_next_byte_argument); if(!isValid(c)){ fprintf(stderr, "%d: Invalid Syntax", line_number); exit(1); } } } if(c == '\n'){ line_number++; } if (c == ')') paren_number--; if (paren_number < 0) { fprintf(stderr, "%d: Invalid Syntax", line_number); exit(1); } if(!isValid(c)){ fprintf(stderr, "%d: Invalid Syntax", line_number); exit(1); } if(tmp_pos > tmpSize){ tmpSize += 50; token = (char*) checked_realloc(token, sizeof(char)*tmpSize); } token[tmp_pos] = c; *pos = tmp_pos; return token; }
void increase_token_size(command_stream_t s) { s->token_size += 20; s->current_string = checked_realloc(s->current_string, sizeof(char*) * s->token_size); }
char* get_executable_path (char* bin_name) { if(bin_name == NULL) return NULL; // Check if this is a valid absolute price if (file_exists (bin_name)) return bin_name; // First, find the current working directory char *cwd = getcwd (NULL, 0); // Does it exist relative to the current directory? char *path = checked_malloc (sizeof(char) * (strlen(cwd) + strlen(bin_name) + 1 + 1)); // Add one char for '/' and one for NULL strcpy (path, cwd); strcat (path, "/"); strcat (path, bin_name); if (file_exists (path)) return path; // If not, let's try the system PATH variable and see if we have any matches there char *syspath = getenv ("PATH"); // "The application shall ensure that it does not modify the string pointed to by the getenv() function." // By definition of getenv, we copy the string and modify the copy with strtok char *syspath_copy = checked_malloc(sizeof (char) * (strlen (syspath) + 1 + 1)); // Add one char for '/' and one for NULL strcpy (syspath_copy, syspath); // Split the path char **path_elements = NULL; char *p = strtok (syspath_copy, ":"); int path_items = 0, i; while (p) { path_elements = checked_realloc (path_elements, sizeof (char*) * (path_items + 2)); path_elements[path_items] = p; path_items++; p = strtok (NULL, ":"); } path_elements[path_items] = NULL; // Make sure the last item is null for later looping // Now, let's iterate over each item in the path and see if it's a fit for (i = 0; path_elements[i] != NULL; i++) { size_t len = sizeof(char) * (strlen(bin_name) + strlen(path_elements[i]) + 1); path = checked_grow_alloc (path, &len); strcpy (path, path_elements[i]); strcat (path, "/"); strcat (path, bin_name); if (file_exists (path)) { free (path_elements); free (syspath_copy); return path; } } free (path_elements); free (syspath_copy); free (path); return NULL; // If we got this far, there's an error. }
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; }
int lexer(char* input, token** output, size_t* output_size) { // this regex will tokenize the input regex_t r; regcomp(&r, "[A-Za-z0-9!%+,-/:@^_.]+|[|]{2}|[&]{2}|[\n;|()<>#]{1}", REG_EXTENDED); size_t used = 0; char** toks = (char**) checked_malloc(sizeof(char*) * strlen(input)); regmatch_t m; size_t input_len = strlen(input); size_t i, j, k; int first_pass = 1; do { // delete leading whitespaces for (i = 0; input[i] == ' ' || input[i] == '\t' || (first_pass && input[i] == '\n'); i++) ; input = memmove(input, input + i, input_len - i + 1); input_len -= i; if (first_pass) first_pass = 0; // exit if nothing left if (input_len == 0) break; // match the regex int matched = !regexec(&r, input, 1, &m, 0); // if no match and input not empty, it's a parse error if (!matched && input_len > 0) error(1, 0, "Syntax error."); // it's a parse error if we skip any characters if (m.rm_so != 0) error(1, 0, "Syntax error."); // store the match result size_t len = m.rm_eo - m.rm_so; char* f = (char*) malloc(len + 1); memcpy(f, input + m.rm_so, len); f[len] = 0; toks[used++] = f; // delete consumed input input = memmove(input, input + m.rm_eo, input_len - len + 1); input_len -= len; } while (input_len > 0); // assign types to the tokens *output = (token*) checked_malloc(sizeof(token) * used); int comment = 0; for (i = 0, j = 0; i < used; i++) { token_type type = UNKNOWN_TOKEN; char* t = toks[i]; size_t len = strlen(t); if (len == 1) { char c = t[0]; switch (c) { case ';': type = SEMICOLON_TOKEN; break; case '(': type = OPEN_PAREN_TOKEN; break; case ')': type = CLOSE_PAREN_TOKEN; break; case '|': type = PIPE_TOKEN; break; case '<': type = L_REDIR_TOKEN; break; case '>': type = R_REDIR_TOKEN; break; case '\n': type = NEWLINE_TOKEN; comment = 0; break; case '#': comment = 1; break; default: type = WORD_TOKEN; break; } } else if (len == 2) { if (!strcmp(t, "||")) type = OR_TOKEN; else if (!strcmp(t, "&&")) type = AND_TOKEN; else { type = WORD_TOKEN; } } else if (len > 2) { type = WORD_TOKEN; } else { error(1, 0, "invalid token"); exit(1); } // drop all comment tokens, save the rest if (!comment) { (*output)[j].text = t; (*output)[j].type = type; j++; } else { free(t); } // debug /*char* type_names[11] = {"word", ";", "|", "&&", "||", "(", ")", "<", ">", "NL", "?"}; if(!comment){ if(t[0] != '\n') printf("%s\ttype: %s\n", t, type_names[type]); else printf("%s\n", "(NEWLINE)"); } else printf("<!-- %s -->\n", t);*/ } // delete meaningless newlines for (i = 0; i < j - 1; i++) { if ((*output)[i + 1].type == NEWLINE_TOKEN && ((*output)[i].type == SEMICOLON_TOKEN || (*output)[i].type == PIPE_TOKEN || (*output)[i].type == AND_TOKEN || (*output)[i].type == OR_TOKEN || (*output)[i].type == OPEN_PAREN_TOKEN || (*output)[i].type == CLOSE_PAREN_TOKEN || (*output)[i].type == NEWLINE_TOKEN)) { free((*output)[i + 1].text); for (k = i + 2; k < j; k++) { (*output)[k - 1] = (*output)[k]; } j--; i--; } } // delete trailing newline if ((*output)[j - 1].type == NEWLINE_TOKEN) j--; // delete leading newline if (j > 0 && (*output)[0].type == NEWLINE_TOKEN) { for (k = 1; k < j; k++) { (*output)[k - 1] = (*output)[k]; } j--; } // shrink the array down to the proper size *output_size = j; *output = (token*) checked_realloc(*output, sizeof(token) * j); // clean up regfree(&r); free(toks); return 0; }