void print_oplist (void) { int i; struct q_elem *qe; // traverse through every table for(i=0; i<__TABLE_SIZE; ++i) { printf("%d : ", i); if (!q_empty(&oplist[i])) { qe = q_begin (&oplist[i]); struct op_elem *oe = q_entry (qe, struct op_elem, elem); printf ("[%s:%02X] ", oe->opcode, oe->code); for(qe = q_next(qe); qe != q_end(&oplist[i]); qe = q_next(qe)) { oe = q_entry (qe, struct op_elem, elem); printf ("-> [%s:%02X] ", oe->opcode, oe->code); } } puts(""); }
/*=========================================================================== FUNCTION Q_LINEAR_SEARCH DESCRIPTION Given a comparison function, this function traverses the elements in a queue, calls the compare function on each item, and returns a pointer to the current element's link if the user passed compare function returns non-zero on that element. The user compare function should return 0 if the current element is not the element in which the compare function is interested. The user compare function SHOULD NOT dequeue a node. DEPENDENCIES The specified queue should have been initialized previously via a call to q_init. RETURN VALUE A pointer to the found element's queue link. SIDE EFFECTS A pointer to a linked element's link is returned without de-queuing the item. ===========================================================================*/ void *q_linear_search ( q_type *q_ptr, /* Queue to be traversed */ q_compare_func_type compare_func, /* Compare function to be called */ void *compare_val /* Cookie to pass to compare_func */ ) { q_link_type *link_ptr = NULL; /* Link to be returned */ /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*------------------------------------------------------------------------- Verify parameters. -------------------------------------------------------------------------*/ ASSERT( NULL != q_ptr ); ASSERT( NULL != compare_func ); /*------------------------------------------------------------------------- Check that the queue is initialized. Works if FEATURE_QUEUE_NO_STRICT_CHECK is turned off. -------------------------------------------------------------------------*/ QUEUE_CHECK_INIT( q_ptr ); link_ptr = q_check( q_ptr ); while( NULL != link_ptr ) { if( 0 != compare_func( link_ptr, compare_val ) ) { break; } link_ptr = q_next( q_ptr, link_ptr ); } /* while */ return link_ptr; } /* q_linear_search() */
unsigned int q_size (struct queue *q) { unsigned int i = 0; struct q_elem *e = q_begin(q); for (; e != q_end(q); e = q_next(e)) i++; return i; }
int main() { os_init(); collect_init("", "", 0); q_next(); q_next(); q_next(); receive_init("", ""); receive_input(); q_next(); send_init("", "", "", 0); q_next(); q_next(); q_next(); q_next(); return 0; }
/*=========================================================================== FUNCTION Q_LINEAR_SEARCH DESCRIPTION Given a comparison function, this function traverses the elements in a queue, calls the compare function, and returns a pointer to the current element being compared if the user passed compare function returns non zero. The user compare function should return 0 if the current element is not the element in which the compare function is interested. DEPENDENCIES The specified queue should have been initialized previously via a call to q_init. The user's queue elements must have q_link_type as the first element of the queued structure. RETURN VALUE A pointer to the found element SIDE EFFECTS None. ===========================================================================*/ void* q_linear_search( q_type *q_ptr, q_compare_func_type compare_func, void *compare_val ) { q_generic_item_type *item_ptr = NULL; item_ptr = (q_generic_item_type*)q_check( q_ptr ); while( item_ptr != NULL ) { if( compare_func( item_ptr, compare_val ) != 0 ) { return item_ptr; } item_ptr = (q_generic_item_type*)q_next( q_ptr, &item_ptr->link ); } /* END while traversing the queue */ return NULL; } /* END q_linear_search */
int main(void) { // INITIALIZING struct queue cmd_queue; q_init (&cmd_queue); uint8_t *mem = calloc (__MEMORY_SIZE, sizeof(uint8_t)); struct queue *oplist = malloc (sizeof(struct queue) * __TABLE_SIZE); char *input = malloc (sizeof(char)*__INPUT_SIZE); char *cmd = malloc (sizeof(char)*__CMD_SIZE); if (mem == NULL || input == NULL || cmd == NULL || oplist == NULL) { puts("MEMORY INSUFFICIENT"); goto memory_clear; } // OPCODE READ int i; for (i=0; i<__TABLE_SIZE; ++i) q_init (&oplist[i]); // Open file for opcode reference FILE * fp = fopen(__OPCODE_FILENAME, "r"); if (fp == NULL) { printf("%s NOT FOUND\n", __OPCODE_FILENAME); goto memory_clear; } // Formatting string i = snprintf((char *) __CMD_FORMAT, __CMD_FORMAT_SIZE, "%%hhx %%%ds %%s", __CMD_SIZE - 1); if (i < 0 || i > __CMD_FORMAT_SIZE) { puts("COMMAND SIZE IS TOO BIG"); goto memory_clear; } // opcode hash table generation while (fgets(input, __INPUT_SIZE, fp) != NULL) { uint8_t code; char form[__OPCODE_FORMAT_SIZE]; if (sscanf(input, (const char *) __CMD_FORMAT, &code, cmd, &form) != 3) { printf("%s IS BROKEN\n", __OPCODE_FILENAME); goto memory_clear; } // Saving opcode struct op_elem *oe = malloc(sizeof(struct op_elem)); if (oe == NULL) { puts("MEMORY INSUFFICIENT"); goto memory_clear; } oe->opcode = malloc(sizeof(char)*(strlen(cmd)+1)); if(oe->opcode == NULL) { puts("MEMORY INSUFFICIENT"); goto memory_clear; } strcpy(oe->opcode, cmd); strcpy(oe->format, form); oe->code = code; code = str_hash (cmd) % __TABLE_SIZE; q_insert (&oplist[code], &(oe->elem)); } // COMMAND PROCESSING while (true) { struct q_elem *qe; uint8_t value; uint32_t start, end; DIR *dirp = NULL; struct dirent *dir = NULL; char check[2]; bool is_valid_cmd = false; printf("%s", __SHELL_FORM); if (!get_chars(input, __INPUT_SIZE)) goto memory_clear; // Processing input string snprintf((char *) __CMD_FORMAT, __CMD_FORMAT_SIZE, "%%%ds", __CMD_SIZE - 1); if (sscanf(input, (const char *) __CMD_FORMAT, cmd)!=1) cmd[0] = '\0'; // Switching with commands switch(get_cmd_index(cmd)) { case CMD_HELP: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } puts(__HELP_FORM); is_valid_cmd = true; break; case CMD_DIR: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } // open directory and read through all elem. i = 1; dirp = opendir("."); dir = readdir(dirp); for(; dir!=NULL; dir = readdir(dirp)) { struct stat st; if(stat((const char*) dir->d_name, &st)!=0) { puts("FILE NOT FOUND"); goto memory_clear; } // FIX: ignore . and .. if(_SAME_STR(dir->d_name, ".") || _SAME_STR(dir->d_name, "..")) continue; printf("%20s", dir->d_name); if(S_ISDIR(st.st_mode)) // is Directory? putchar('/'); else if( (st.st_mode & S_IXUSR) // is exe? || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) putchar('*'); putchar('\t'); // print newline after 3 elements if((i++)%3==0) putchar('\n'); } if((i-1)%3!=0) putchar('\n'); is_valid_cmd = true; break; case CMD_QUIT: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } is_valid_cmd = true; goto memory_clear; case CMD_HISTORY: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } qe = q_begin (&cmd_queue); i = 1; // print every formatted history for (; qe!=q_end(&cmd_queue); qe=q_next(qe)) printf("%-4d %s\n", i++, q_entry(qe, struct cmd_elem, elem)->cmd); printf("%-4d %s\n", i, input); is_valid_cmd = true; break; case CMD_DUMP: switch(sscanf(input, "%s %x , %x", cmd, &start, &end)) { case 1: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } start = get_location (0, false); end = start + 0x10 * 10 - 1; // if end is too large, point to end and go 0 if ( end >= __MEMORY_SIZE ) end = __MEMORY_SIZE - 1; hexdump (mem, start, end); if ( end == __MEMORY_SIZE - 1) get_location (0, true); else get_location (end + 1, true); is_valid_cmd = true; break; case 2: if(sscanf(input, "%*s %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } if (start >= __MEMORY_SIZE) { puts("OUT OF MEMORY BOUNDS."); break; } end = start + 0x10 * 10 - 1; // if end is too large, point to end and go 0 if ( end >= __MEMORY_SIZE ) end = __MEMORY_SIZE - 1; hexdump (mem, start, end); if ( end == __MEMORY_SIZE - 1) get_location (0, true); else get_location (end + 1, true); is_valid_cmd = true; break; case 3: if(sscanf(input, "%*s %*x , %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } if (!(start<=end && end<__MEMORY_SIZE)) { puts("OUT OF MEMORY BOUNDS."); break; } hexdump (mem, start, end); // if end is too large, point to end and go 0 if ( end == __MEMORY_SIZE - 1) get_location (0, true); else get_location (end + 1, true); is_valid_cmd = true; break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_EDIT: switch(sscanf(input, "%s %x , %hhx", cmd, &start, &value)) { case 3: if(sscanf(input, "%*s %*x , %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } hexfill (mem, __MEMORY_SIZE, start, start, value); is_valid_cmd = true; break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_FILL: switch(sscanf(input, "%s %x , %x , %hhx", cmd, &start, &end, &value)) { case 4: if(sscanf(input, "%*s %*x , %*x , %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } hexfill (mem, __MEMORY_SIZE, start, end, value); is_valid_cmd = true; break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_RESET: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } // equivalent to fill 0, __MEMORY_SIZE-1 hexfill (mem, __MEMORY_SIZE, 0, __MEMORY_SIZE - 1, 0); is_valid_cmd = true; break; case CMD_OPCODE: switch(sscanf(input, "%*s %s", cmd)) { case 1: if(sscanf(input, "%*s %*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } // look for opcode in hash table i = str_hash(cmd) % __TABLE_SIZE; if (!q_empty(&oplist[i])) { bool found = false; qe = q_begin (&oplist[i]); for(; qe != q_end(&oplist[i]); qe = q_next(qe)) { struct op_elem *oe = q_entry (qe, struct op_elem, elem); if (_SAME_STR(cmd, oe->opcode)) { printf("opcode is %2X\n", oe->code); found = true; break; } } if (found) { is_valid_cmd = true; break; } } printf("%s: NO SUCH OPCODE\n", cmd); break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_OPCODELIST: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } // traverse through every table for(i=0; i<__TABLE_SIZE; ++i) { printf("%d : ", i); if (!q_empty(&oplist[i])) { qe = q_begin (&oplist[i]); struct op_elem *oe = q_entry (qe, struct op_elem, elem); printf ("[%s:%02X] ", oe->opcode, oe->code); for(qe = q_next(qe); qe != q_end(&oplist[i]); qe = q_next(qe)) { oe = q_entry (qe, struct op_elem, elem); printf ("-> [%s:%02X] ", oe->opcode, oe->code); } } puts(""); } is_valid_cmd = true; break; default: if(sscanf(input, "%1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } }
/*=========================================================================== FUNCTION Q_LINEAR_DELETE DESCRIPTION Given a comparison function, this function traverses the elements in a queue, calls the compare function, and returns a pointer to the current element being compared if the user passed compare function returns non zero. In addition, the item will be removed from the queue. The user compare function should return 0 if the current element is not the element in which the compare function is interested. DEPENDENCIES The specified queue should have been initialized previously via a call to q_init. The user's queue elements must have q_link_type as the first element of the queued structure. The user's compare function will be passed NULL for the compare value. RETURN VALUE None SIDE EFFECTS None. ===========================================================================*/ void q_linear_delete( q_type *q_ptr, q_compare_func_type compare_func, void *param, q_action_func_type action_func ) { q_generic_item_type *item_ptr = NULL; /* Used in the traversal to point to the current item */ q_generic_item_type *prev_ptr = NULL; /* Used in the traversal to point to the item previous to ** the current item. This makes removing the current item ** a constant time operation */ /* User must provide a compare function, otherwise, this is ** meaningless. */ if( compare_func == NULL ) { return; } q_lock( q_ptr ); /* item_ptr points to the first item on the list */ item_ptr = (q_generic_item_type*)q_check( q_ptr ); prev_ptr = NULL; while( item_ptr != NULL ) { if( compare_func( item_ptr, NULL ) != 0 ) { /* Remove the item */ if( prev_ptr != NULL ) { /* Remove from the middle or tail */ prev_ptr->link.next_ptr = item_ptr->link.next_ptr; item_ptr->link.next_ptr = NULL; } else { /* Remove from the head */ q_get( q_ptr ); } /* Call the action function if there is one */ if( action_func ) { action_func( item_ptr, param ); } break; } /* Move on to the next item */ prev_ptr = item_ptr; item_ptr = (q_generic_item_type*)q_next( q_ptr, &item_ptr->link ); } /* END while traversing the queue */ q_free( q_ptr ); return; } /* END q_linear_delete */
int main(void) { // INITIALIZING struct queue cmd_queue; q_init (&cmd_queue); uint8_t *mem = calloc (__MEMORY_SIZE, sizeof(uint8_t)); char *input = malloc (sizeof(char)*__INPUT_SIZE); char *cmd = malloc (sizeof(char)*__CMD_SIZE); char *filename = malloc (sizeof(char)*__FILENAME_SIZE); if (mem == NULL || input == NULL || filename == NULL || cmd == NULL) { puts("MEMORY INSUFFICIENT"); goto memory_clear; } if (!init_oplist (__OPCODE_FILENAME)) { puts("OPCODE LIST INITIALIZATION FAILED."); goto memory_clear; } // COMMAND PROCESSING while (true) { int i; struct q_elem *qe; uint8_t value; uint32_t start, end; DIR *dirp = NULL; struct dirent *dir = NULL; char check[2]; bool is_valid_cmd = false; char *tok = NULL; printf("%s", __SHELL_FORM); if (!get_chars(input, __INPUT_SIZE)) goto memory_clear; // Processing input string snprintf((char *) __CMD_FORMAT, __CMD_FORMAT_SIZE, "%%%ds", __CMD_SIZE - 1); if (sscanf(input, (const char *) __CMD_FORMAT, cmd)!=1) cmd[0] = '\0'; // Switching with commands switch(get_cmd_index(cmd)) { case CMD_HELP: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } puts(__HELP_FORM); is_valid_cmd = true; break; case CMD_DIR: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } // open directory and read through all elem. i = 1; dirp = opendir("."); dir = readdir(dirp); for(; dir!=NULL; dir = readdir(dirp)) { struct stat st; if(stat((const char*) dir->d_name, &st)!=0) { puts("FILE NOT FOUND"); goto memory_clear; } // FIX: ignore . and .. if(_SAME_STR(dir->d_name, ".") || _SAME_STR(dir->d_name, "..")) continue; printf("%20s", dir->d_name); if(S_ISDIR(st.st_mode)) // is Directory? putchar('/'); else if( (st.st_mode & S_IXUSR) // is exe? || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) putchar('*'); putchar('\t'); // print newline after 3 elements if((i++)%3==0) putchar('\n'); } if((i-1)%3!=0) putchar('\n'); is_valid_cmd = true; break; case CMD_QUIT: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } is_valid_cmd = true; goto memory_clear; case CMD_HISTORY: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } qe = q_begin (&cmd_queue); i = 1; // print every formatted history for (; qe!=q_end(&cmd_queue); qe=q_next(qe)) printf("%-4d %s\n", i++, q_entry(qe, struct cmd_elem, elem)->cmd); printf("%-4d %s\n", i, input); is_valid_cmd = true; break; case CMD_DUMP: switch(sscanf(input, "%s %x , %x", cmd, &start, &end)) { case 1: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } start = get_location (0, false); end = start + 0x10 * 10 - 1; // if end is too large, point to end and go 0 if ( end >= __MEMORY_SIZE ) end = __MEMORY_SIZE - 1; hexdump (mem, start, end); if ( end == __MEMORY_SIZE - 1) get_location (0, true); else get_location (end + 1, true); is_valid_cmd = true; break; case 2: if(sscanf(input, "%*s %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } if (start >= __MEMORY_SIZE) { puts("OUT OF MEMORY BOUNDS."); break; } end = start + 0x10 * 10 - 1; // if end is too large, point to end and go 0 if ( end >= __MEMORY_SIZE ) end = __MEMORY_SIZE - 1; hexdump (mem, start, end); if ( end == __MEMORY_SIZE - 1) get_location (0, true); else get_location (end + 1, true); is_valid_cmd = true; break; case 3: if(sscanf(input, "%*s %*x , %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } if (!(start<=end && end<__MEMORY_SIZE)) { puts("OUT OF MEMORY BOUNDS."); break; } hexdump (mem, start, end); // if end is too large, point to end and go 0 if ( end == __MEMORY_SIZE - 1) get_location (0, true); else get_location (end + 1, true); is_valid_cmd = true; break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_EDIT: switch(sscanf(input, "%s %x , %hhx", cmd, &start, &value)) { case 3: if(sscanf(input, "%*s %*x , %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } hexfill (mem, __MEMORY_SIZE, start, start, value); is_valid_cmd = true; break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_FILL: switch(sscanf(input, "%s %x , %x , %hhx", cmd, &start, &end, &value)) { case 4: if(sscanf(input, "%*s %*x , %*x , %*x %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } hexfill (mem, __MEMORY_SIZE, start, end, value); is_valid_cmd = true; break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_RESET: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } // equivalent to fill 0, __MEMORY_SIZE-1 hexfill (mem, __MEMORY_SIZE, 0, __MEMORY_SIZE - 1, 0); is_valid_cmd = true; break; case CMD_OPCODE: switch(sscanf(input, "%*s %s", cmd)) { case 1: if(sscanf(input, "%*s %*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } i = find_oplist (cmd); if (i != -1) printf("opcode is %02X\n", i); else { printf("%s: NO SUCH OPCODE\n", cmd); is_valid_cmd = false; } break; default: puts("WRONG INSTRUCTION"); break; } break; case CMD_OPCODELIST: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } print_oplist (); is_valid_cmd = true; break; case CMD_ASSEMBLE: // Processing input string snprintf((char *) __CMD_FORMAT, __CMD_FORMAT_SIZE, "%%%ds %%%ds %%1s", __CMD_SIZE - 1, __FILENAME_SIZE - 1); if (sscanf(input, (const char *) __CMD_FORMAT, cmd, filename, check)!=2) { puts("WRONG INSTRUCTION"); break; } if (!is_file((const char*)filename)) { puts("FILE NOT FOUND"); break; } is_valid_cmd = assemble_file (filename); break; case CMD_TYPE: // Processing input string snprintf((char *) __CMD_FORMAT, __CMD_FORMAT_SIZE, "%%%ds %%%ds %%1s", __CMD_SIZE - 1, __FILENAME_SIZE - 1); if (sscanf(input, (const char *) __CMD_FORMAT, cmd, filename, check)!=2) { puts("WRONG INSTRUCTION"); break; } if (!is_file((const char*)filename)) { puts("FILE NOT FOUND"); break; } else { print_file((const char*)filename); is_valid_cmd = true; } break; case CMD_SYMBOL: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } print_symbol_table (); is_valid_cmd = true; break; case CMD_PROGADDR: if(sscanf(input, "%*s %*x %1s", check) == 1 || sscanf(input, "%*s %x", &i) != 1) { puts("WRONG INSTRUCTION"); break; } if (i < 0 || i >= __MEMORY_SIZE - 1) { puts("INVALID PROGRAM ADDRESS"); break; } set_progaddr ((uint32_t) i); is_valid_cmd = true; break; case CMD_LOADER: init_loader (); tok = strtok (input, " "); while ( (tok = strtok (NULL, " ")) != NULL) { if (!is_file (tok)) { printf ("[%s]: INVALID FILE\n", tok); free_loader (); break; } if (!add_obj_loader (tok)) { printf ("[%s]: LOADER FAILED\n", tok); free_loader (); break; } } // if normally added if (tok == NULL) { // address __MEMORY_SIZE is reserved for boot if (get_proglen()+get_progaddr()>=__MEMORY_SIZE-1) { puts ("PROGRAM IS TOO BIG: LOADER FAILED"); free_loader (); break; } if (!run_loader (mem)) { puts ("LOADER FAILED"); free_loader (); break; } print_load_map (); } free_loader (); is_valid_cmd = true; break; case CMD_RUN: if(sscanf(input, "%*s %1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } if (!init_run ()) { puts ("RUN FAILED"); free_run (); break; } run (mem); free_run (); is_valid_cmd = true; break; case CMD_BP: if(sscanf(input, "%*s %1s", check) != 1) { print_bp (); is_valid_cmd = true; break; } if(sscanf(input, "%*s %6s %1s", cmd, check) == 2 || sscanf(input, "%*s %6s", cmd) != 1) { puts("WRONG INSTRUCTION"); break; } if (_SAME_STR(cmd, "clear")) { puts ("\t[ok] clear all breakpoints"); free_bp (); is_valid_cmd = true; break; } if(sscanf(input, "%*s %*x %1s", check) == 1 || sscanf(input, "%*s %x", &start) != 1) { puts("WRONG INSTRUCTION"); break; } if (start >= __MEMORY_SIZE - 1) { puts ("INVALID BREAKPOINT ADDRESS"); break; } if (add_bp (start)) printf ("\t[ok] create breakpoint %x\n", start); is_valid_cmd = true; break; default: if(sscanf(input, "%1s", check) == 1) { puts("WRONG INSTRUCTION"); break; } } if (is_valid_cmd) { // Saving commands struct cmd_elem *e = malloc(sizeof(struct cmd_elem)); if (e == NULL) { puts("MEMORY INSUFFICIENT."); goto memory_clear; } e->cmd = malloc(sizeof(char)*(strlen(input)+1)); if (e->cmd == NULL) { puts("MEMORY INSUFFICIENT."); goto memory_clear; } strcpy(e->cmd, input); q_insert (&cmd_queue, &(e->elem)); } } memory_clear: if (mem != NULL) free (mem); if (input != NULL) free (input); if (cmd != NULL) free (cmd); while (!q_empty(&cmd_queue)) { struct q_elem *e = q_delete(&cmd_queue); struct cmd_elem *ce = q_entry(e, struct cmd_elem, elem); if (ce->cmd != NULL) free(ce->cmd); free(ce); } free_oplist (); free_loader (); free_bp (); free_run (); return 0; }