// rl_input puts upto MAX characters into BUF with the number put in // BUF placed in *RESULT. static void lexer_input (char *buf, unsigned long int *result, int max, void* yyscanner) { if (yyget_in(yyscanner) != rl_instream) { //not stdin so read as usual while ( (*result = read( fileno(yyget_in(yyscanner)), buf, max )) < 0 ) { if (errno != EINTR) { std::cerr << "read() in flex scanner failed" << std::endl; exit (1); } } return; } if (rl_len == 0) { //Do we need a new string? if (rl_start) { free(rl_start); } unsigned short scopes = yyget_extra(yyscanner)->indents.size(); std::string prompt = "sugar"; if(yyget_extra(yyscanner)->pendingEndInstr){ prompt += "*"; } if(scopes > 1){ prompt += "("+std::to_string(scopes)+")"; } prompt += "> "; #if SHELL_USE_COLOR prompt = "\x1b[33m"+prompt+"\x1b[0m"; #endif rl_start = readline (prompt.c_str()); if (rl_start == NULL) { //end of file *result = 0; rl_len = 0; return; } rl_line = rl_start; rl_len = strlen (rl_line)+1; if (rl_len != 1) { add_history (rl_line); } rl_line[rl_len-1] = '\n'; fflush (stdout); } if (rl_len <= max) { strncpy (buf, rl_line, rl_len); *result = rl_len; rl_len = 0; } else { strncpy (buf, rl_line, max); *result = max; rl_line += max; rl_len -= max; } }
/*Thread task function for reentrant scanner*/ void *lex_thread_task(void *arg) { lex_thread_arg *ar = (lex_thread_arg*) arg; FILE * f = fopen(ar->file_name, "r"); if (f == NULL) { DEBUG_STDOUT_PRINT("ERROR> Lexing thread %d could not open input file. Aborting.\n", ar->id); exit(1); } lex_token *flex_token; int8_t end_of_chunk = 0; yyscan_t scanner; //reentrant flex instance data int32_t flex_return_code; token_node *token_builder = NULL; token_node_stack stack; sem_value_stack stack_char; sem_value_stack stack_int; uint32_t alloc_size = 0, realloc_size = 0; uint32_t chunk_length = ar->cut_point_dx - ar->cut_point_sx; par_compute_alloc_realloc_size((ar->cut_point_dx - ar->cut_point_sx), &alloc_size, &realloc_size); DEBUG_STDOUT_PRINT("LEXER %d > alloc_size %d, realloc_size %d\n", ar->id, alloc_size, realloc_size) /*Initialization flex_token*/ flex_token = (lex_token*) malloc(sizeof(lex_token)); if (flex_token == NULL) { DEBUG_STDOUT_PRINT("ERROR> could not complete malloc flex_token. Aborting.\n"); exit(1); } flex_token->chunk_length = chunk_length; flex_token->num_chars = 0; flex_token->chunk_ended = 0; //Initialize stack for semantic values. //Since the possible semantic values are only char or int, we can allocate two different stacks, one for each type, avoiding to waste memory. init_sem_value_stack(&stack_char, alloc_size, 0); init_sem_value_stack(&stack_int, alloc_size, 1); flex_token->stack_char = &stack_char; flex_token->stack_int = &stack_int; flex_token->realloc_size = realloc_size; fseek(f, ar->cut_point_sx, SEEK_SET); if(yylex_init_extra(flex_token, &scanner)) { DEBUG_STDOUT_PRINT("ERROR> yylex_init_extra failed.\n") exit(1); } yyset_in(f, scanner); ar->list_begin = NULL; init_token_node_stack(&(stack), alloc_size); flex_return_code = yylex(scanner); /*The procedure to find cut points cannot cut a single token in two parts.*/ while(!end_of_chunk && flex_return_code != __END_OF_CHUNK && flex_return_code != __END_OF_FILE) { if(flex_return_code == __LEX_CORRECT) { //append a token par_append_token_node(flex_token->token, flex_token->semantic_value, &token_builder, &(ar->list_begin), &stack, realloc_size); ar->lex_token_list_length++; } else { //flex_return_code is __ERROR) DEBUG_STDOUT_PRINT("Lexing thread %d scanned erroneous input. Abort.\n", ar->id) ar->result = 1; /*Signal error by returning result!=0.*/ fclose(yyget_in(scanner)); yylex_destroy(scanner); fclose(f); pthread_exit(NULL); } if (flex_token->chunk_ended) end_of_chunk = 1; else { //Continue to scan the chunk flex_return_code = yylex(scanner); } } ar->list_end = token_builder; fclose(yyget_in(scanner)); yylex_destroy(scanner); fclose(f); pthread_exit(NULL); }