unsigned long long perft(Board *board, int depth) { if (is_illegal(board)) { return 0L; } if (depth == 0) { return 1L; } int index = board->hash & MASK; Entry *entry = &TABLE[index]; if (entry->key == board->hash && entry->depth == depth) { hits += entry->value; return entry->value; } unsigned long long result = 0; Undo undo; Move moves[MAX_MOVES]; int count = gen_moves(board, moves); for (int i = 0; i < count; i++) { do_move(board, &moves[i], &undo); result += perft(board, depth - 1); undo_move(board, &moves[i], &undo); } entry->key = board->hash; entry->value = result; entry->depth = depth; return result; }
command_stream_t make_command_stream (int (*get_next_byte) (void *), void *get_next_byte_argument) { char** commandStrings = (char**)checked_malloc(sizeof(char*)); commandStrings[0] = NULL; char** temp = NULL; char c; char effective_prev = '\0'; char prev ='\0'; int count = 1; // Keeps count of complete commands bool sub = false; //To see if we are within a subshell int open_par = 0; int closed_par = 0; int curr_line = 1; int* line_nums = (int*)checked_malloc(sizeof(int)); line_nums[0] = 1; while((c = get_next_byte(get_next_byte_argument)) != EOF) { if(is_illegal(c)) // Check for illegal tokens { error(1,0,"%d: Invalid token '%c'.",curr_line,c); return 0; } if((c == ';') && (!sub)) { if(effective_prev =='\n' || effective_prev =='\0') error(1,0, "%d: Can't start line with '%c'", curr_line, c); if(effective_prev == ';') error(1,0, "%d: Too many '%c' tokens", curr_line, c); count++; temp = (char**)checked_realloc(commandStrings,sizeof(char*)*count); commandStrings = temp; commandStrings[count-1] = NULL; int* temp_int = (int*)checked_realloc(line_nums,sizeof(int)*count); line_nums = temp_int; prev = c; effective_prev = c; continue; } if(c == '#') // Take care of comments be ignoring everything up to newline { if((is_special(prev)) || (isblank((unsigned char)prev) != 0) // changed from unsigned char type to char || (prev == '\n') ||(prev == '\0')) { while((c = get_next_byte(get_next_byte_argument)) != EOF) if( c == '\n') break; if(c == EOF) break; if((prev == '\0') && (c == '\n')) // Case if script starts with # { //If I don't include this an empty string is made prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; curr_line++; continue; } } else { error(1,0,"Line %d: Invalid use of '#' token.",curr_line); return 0; } } if(c != '\n') { if((isblank((unsigned char)c) != 0) && (effective_prev == '\0')) continue; // Check that that only paranthesis are preceded by newline(and words of course) if(effective_prev == '\n') { if((c == '|') || (c == '&') || (c == '>') || (c == '<')) { error(1,0,"%d: Unexpected newline before '%c' token",curr_line,c); return 0; } } if(c == '(') { sub = true; open_par++; } else if(c == ')') { closed_par++; if(open_par == closed_par) { sub = false; open_par = 0; closed_par = 0; } } if(((c == '|') && (effective_prev == '&')) || ((c == '&') && (effective_prev == '|'))) { error(1,0,"%d: Invalid AND-OR.",curr_line); return 0; } if(commandStrings[count-1] == NULL) { line_nums[count-1] = curr_line; } add_char(commandStrings,count-1,c); } else { if((effective_prev == '|') || (effective_prev == '&') || sub) { prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; if(commandStrings[count-1] == NULL) { line_nums[count-1] = curr_line; } add_char(commandStrings,count-1,c); curr_line++; continue; } if(prev == '\n' || effective_prev == '\0') { prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; curr_line++; continue; } // Gotta also check for < or > cases if((effective_prev == '<') || (effective_prev == '>')) { error(1,0,"%d: Cannot end line in < or >",curr_line); return 0; } if(!sub && (prev != ';')) { count++; temp = (char**)checked_realloc(commandStrings,sizeof(char*)*count); commandStrings = temp; commandStrings[count-1] = NULL; int* temp_int = (int*)checked_realloc(line_nums,sizeof(int)*count); line_nums = temp_int; } curr_line++; } prev = c; if(isblank((unsigned char)c) == 0) effective_prev = c; } if((commandStrings[0] == NULL) && count == 1) count = 0; if(open_par != closed_par) // Check to see if paranthesis are all good { error(1,0,"%d: Missing a paranthesis",curr_line); return 0; } if(prev == '\n' && (commandStrings[count-1] == NULL)) count--; command_stream_t stream = stringsToStream(commandStrings, line_nums, count); /* Free Data Allocated Dynamically int j; for(j = 0; j < count; j++) free(commandStrings[j]); free(commandStrings); free(line_nums); */ // BUILD READ/WRITE LISTS (add as a member of command_stream_t) // BUILD DEPENDENCY LISTS (lists of integer indices of commands that must // finish before this one does) stream->pidList = checked_malloc(count * sizeof(pid_t)); // 0 out all pid's. This will give them all integer values of NOT_YET_RUN. memset(stream->pidList, 0, count * sizeof(pid_t)); make_dep_lists(stream); return stream; }