#pragma once #include #include #include #include #include #include #include #include int bvr_commands_check_for_command(char * input_char, char ** value, int *i, FILE * input, int * value_size) { if((*input_char) == LINE_COMMAND_CHAR) { FILE * command_return; size_t buf_size; char * command_output; command_return = open_memstream(&command_output, &buf_size); if(bvr_command_processor(input, command_return) != SUCCESS) { fprintf(stderr, "[bvrcommands.c] bvr_commands_check_for_command: command, passed as argument, didn't return success. Going on.\n"); } fflush(command_return); while((*value_size) < ((*i)+buf_size)) { // make room in chunks for command_output (*value) = realloc((*value), (*value_size)+BVR_VALUE_CHUNK_SIZE); if((*value) == NULL) { fprintf(stderr, "[bvrcommands.c] bvr_commands_check_for_command: CRITICAL OUT-OF-MEMORY.\n"); } (*value_size) = (*value_size)+BVR_VALUE_CHUNK_SIZE; } for(int j = 0; j < buf_size; j++) { /// fprintf(stderr, "debug: \"%c\", %ld\n", command_output[j], buf_size); (*value)[(*i)++] = command_output[j]; } (*input_char) = CLOSING_COMMAND_TAG_CHAR_1; // da zaključimo loop (drugače ostane notri ?) //\\ zelo slabo. znak, ki ga najde izveden ukaz, se izgubi. rešitev bi bila dobiti zadnji input char, ki triggera break // prejšnjega ukaza, kar pa je nemogoče. fflush(command_return); fclose(command_return); free(command_output); command_output == NULL; // the address/pointer, lost for ever! return BVR_CONTINUE; } return BVR_KEEPGOING; } char bvr_commands_skip_separator_chars(FILE * input) { char input_char = fgetc(input); while(input_char == ' ' || input_char == CLOSING_COMMAND_TAG_CHAR_1 || input_char == ',' || input_char == ';' || input_char == EOF || input_char == '\0' || input_char == '\n') { input_char = fgetc(input); } return input_char; } char * bvr_commands_get_value(FILE * input, char * yeetus_chars) { int value_size = BVR_VALUE_CHUNK_SIZE; char * value = (char*) malloc(value_size); char input_char = bvr_commands_skip_separator_chars(input); int i = 0; while(1) { // i == napisali smo že toliko znakov if(i >= value_size) { // <-- todo: uncomment after done debugging value = realloc(value, (value_size) * BVR_VALUE_CHUNK_SIZE); if(value == NULL) { fprintf(stderr, "[bvrcommands.c] bvr_commands_get_value: CRITICAL OUT-OF-MEMORY, FUCK!\n"); } value_size = value_size + BVR_VALUE_CHUNK_SIZE; } if(char_in_array(input_char, yeetus_chars)) { value[i++] = '\0'; return value; // or yeet! } if(bvr_commands_check_for_command(&(input_char), &(value), &(i), input, &(value_size)) == BVR_CONTINUE) { continue; } (value)[(i)++] = input_char; input_char = fgetc(input); } // we should not get here! } char * bvr_commands_get_string(FILE * input) { int value_size = BVR_VALUE_CHUNK_SIZE; char * value = (char*) malloc(value_size); char input_char = fgetc(input); char previous_char = 'a'; // please don't make a an escape char int i = 0; while(1) { // i == napisali smo že toliko znakov if(i >= value_size) { // <-- todo: uncomment after done debugging value = realloc(value, (value_size) * BVR_VALUE_CHUNK_SIZE); if(value == NULL) { fprintf(stderr, "[bvrcommands.c] bvr_commands_get_value: CRITICAL OUT-OF-MEMORY, FUCK!\n"); } value_size = value_size + BVR_VALUE_CHUNK_SIZE; } if(input_char == BVR_BREAK_STRING_CHAR) { if(previous_char != BVR_ESCAPE_CHAR) { value[i++] = '\0'; return value; } else { i--; // da zamenjamo prejšnji ESCAPE_CHAR z BREAK_STRING charom (value)[(i)++] = BVR_BREAK_STRING_CHAR; } } else { (value)[(i)++] = input_char; } previous_char = input_char; input_char = fgetc(input); } // we should not get here! } int bvr_handle_substring(FILE * input, FILE * output) { // acts like https://www.php.net/manual/en/function.substr.php char chars_to_break_value[69] = ",; "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * offset = bvr_commands_get_value(input, chars_to_break_value); char * length = bvr_commands_get_value(input, chars_to_break_value); char * string = bvr_commands_get_value(input, BVR_CHARS_TO_BREAK_VALUE); int return_status = SUCCESS; int real_offset = atoi(offset); if(real_offset < 0) { real_offset = strlen(string)-abs(real_offset); } if(strlen(string) < real_offset) { // catch errors fprintf(stderr, "[bvrcommands.c] bvr_handle_substring: string lenght (%ld) is less than offset (%d). fuck you.\n", strlen(string), real_offset); fprintf(output, "\nbVerbose substring: string length of %ld is less than offset of %d.\n", strlen(string), real_offset); return_status = FAILURE; goto cleanup_and_return; } if(real_offset < 0) { // catch errors fprintf(stderr, "[bvrcommands.c] bvr_handle_substring: supplied negative offset after calculation (%d) is negative. failing...\n", real_offset); fprintf(output, "\nbVerbose substring: supplied negative offset after calculation (%d) is negative.\n", real_offset); return_status = FAILURE; goto cleanup_and_return; } if(atoi(length) < 0) { string[strlen(string)-abs(atoi(length))] = '\0'; fprintf(output, "%s", string+real_offset); } else { fprintf(output, "%.*s", atoi(length), string+real_offset); } cleanup_and_return: fflush(output); free(offset); free(length); free(string); offset = NULL; length = NULL; string = NULL; return return_status; } int bvr_handle_get(FILE * input, FILE * output) { char chars_to_break_value[69] = ",; "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); fprintf(output, "%s", bvr_var_get(item)); fflush(output); free(item); item = NULL; return SUCCESS; } int bvr_handle_set(FILE * input, FILE * output) { char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); char * value = bvr_commands_get_value(input, BVR_CHARS_TO_BREAK_VALUE); int return_value = bvr_var_set(item, value); fflush(output); free(item); free(value); item = NULL; value = NULL; return return_value; } int bvr_handle_include(FILE * input, FILE * output) { char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); FILE * stream; char * cp; int return_status = SUCCESS; // fprintf(stderr, "debug: %s\n", item); if (strncmp(item, "bvr://", strlen("bvr://")) == 0) { switch (item[6]) { case 'v': /* ar */ cp = strchr(item+6, '/'); if (cp == NULL) goto sike_this_actually_is_a_file; cp = bvr_var_get(cp+1); if (cp == NULL || 0 == strncmp(cp, "BVR_UNDEFINED", strlen("BVR_UNDEFINED"))) goto sike_this_actually_is_a_file; stream = fmemopen(cp, strlen(cp), "r"); if (stream == NULL) goto sike_this_actually_is_a_file; break; default: goto sike_this_actually_is_a_file; break; /* unreachable "code" */ } } else { sike_this_actually_is_a_file: stream = fopen(item, "r"); char notgoodatnamingvariables[PATH_MAX]; char * path = bvr_var_get(BVR_INCLUDE_PATH_VAR_NAME); if(stream == NULL) { strcpy(notgoodatnamingvariables, item); strcat(notgoodatnamingvariables, BVR_COMMAND_FILE_EXT); stream = fopen(notgoodatnamingvariables, "r"); if(strcmp(path, BVR_UNDEFINED) == 0 && stream == NULL) { fprintf(output, "\nbVerbose include error. File \"%s\" not found. Path is undefined.\n", item); fprintf(stderr, "[bvrcommands.c] bvr_handle_include: File \"%s\" not found. Path is undefined.\n", item); return_status = FAILURE; goto returncleanly; } } char * singlepath; while(stream == NULL) { singlepath = strrchr(path, BVR_PATH_SEPARATOR); if(singlepath == NULL) { strcpy(notgoodatnamingvariables, path); strcat(notgoodatnamingvariables, item); stream = fopen(notgoodatnamingvariables, "r"); // ob1 fuckery if(stream == NULL) { strcpy(notgoodatnamingvariables, path); strcat(notgoodatnamingvariables, item); strcat(notgoodatnamingvariables, BVR_COMMAND_FILE_EXT); stream = fopen(notgoodatnamingvariables, "r"); // ob1 fuckery if(stream == NULL) { fprintf(output, "\nbVerbose include error. File \"%s\" not found.\n", item); fprintf(stderr, "[bvrcommands.c] bvr_handle_include: File \"%s\" not found.\n", item); return_status = FAILURE; goto returncleanly; } break; } break; } strcpy(notgoodatnamingvariables, singlepath); strcat(notgoodatnamingvariables, item); stream = fopen(notgoodatnamingvariables+1, "r"); // ob1 fuckery if(stream == NULL) { strcat(notgoodatnamingvariables, BVR_COMMAND_FILE_EXT); stream = fopen(notgoodatnamingvariables+1, "r"); // ob1 fuckery if(stream != NULL) { break; } } *singlepath = '\0'; } } return_status = bvr_compose_stream(stream, output); fclose(stream); returncleanly: fflush(output); free(item); item = NULL; return return_status; fflush(output); // kja? } int bvr_handle_move(FILE * input, FILE * output) { char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); char * value = bvr_commands_get_value(input, chars_to_break_value); int return_value = bvr_var_mv(item, value); free(item); free(value); value = NULL; item = NULL; fflush(output); return return_value; } int bvr_handle_string(FILE * input, FILE * output) { char * item = bvr_commands_get_string(input); char * uuid = randstring(37); strcpy(uuid, "BVR_STRING"); uuid[10] = '_'; int return_value = bvr_var_set(uuid, item); free(item); item = NULL; fprintf(output, "%s", uuid); free(uuid); uuid = NULL; fflush(output); return return_value; } int bvr_handle_equals(FILE * input, FILE * output) { char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); char * value = bvr_commands_get_value(input, chars_to_break_value); int return_value = 0; char * string1 = bvr_var_get(item); char * string2 = bvr_var_get(value); char out; if(strcmp(string1, string2) == 0) { out = '1'; } else { out = '0'; } fprintf(output, "?\"%c\"", out); free(item); free(value); item = NULL; value = NULL; fflush(output); return return_value; } int bvr_handle_if(FILE * input, FILE * output) { // ?f 1 <@this is all executed@> // first argument must *POINT* to a string which evaluates to 1, the second argument is the value of the endif string, spaces // are argument delimeters. endif is only used for skipping forward if if should not execute. char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); int return_value = 0; if(strcmp(bvr_var_get(item), "1") == 0) { char chars_to_break_value[3] = {OPENING_COMMAND_TAG_CHAR_2, EOF, '\0'}; char * temp = bvr_commands_get_value(input, chars_to_break_value); free(temp); temp = NULL; char copy_buffer[BVR_COPY_BUFFER_SIZE]; init_tape_copy_buffer(copy_buffer, COPY_BUFFER_SIZE); return_value = bvr_inline_command_processor(input, output, copy_buffer); } else { char input_char = fgetc(input); char previous_char = 'a'; int depth = -1; // to increase to 0 after first <@ int we_re_in_a_comment = 0; while(1) { if((input_char == BVR_CLOSING_COMMAND_TAG_CHAR_2 && previous_char == BVR_CLOSING_COMMAND_TAG_CHAR_1 && depth == 0 && we_re_in_a_comment == 0)) { break; } if(previous_char == BVR_OPENING_COMMAND_TAG_CHAR_1 && input_char == BVR_OPENING_COMMAND_TAG_CHAR_2) { depth++; } // this šubidubi doesn't account for <@ and @> in strings. if(previous_char == BVR_CLOSING_COMMAND_TAG_CHAR_1 && input_char== BVR_CLOSING_COMMAND_TAG_CHAR_2) { depth--; } if(previous_char == LINE_COMMAND_CHAR && input_char == BVR_BREAK_STRING_CHAR) { char * temp = bvr_commands_get_string(input); free(temp); temp = NULL; } if(previous_char == BVR_NEWLINE_CHAR && input_char == LINE_COMMENT_CHAR) { we_re_in_a_comment = 1; } if(we_re_in_a_comment && input_char == BVR_NEWLINE_CHAR) { we_re_in_a_comment = 0; } previous_char = input_char; input_char = fgetc(input); } } free(item); item = NULL; if(return_value != 0) { fprintf(stderr, "bvrcommands.c: bvr_handle_if: bvr_compose_stream returned an error status!\n"); } return return_value; } int bvr_handle_while(FILE * input, FILE * output) { char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); int return_value = 0; char input_char = fgetc(input); char previous_char = 'a'; char * string1 = bvr_var_get(item); FILE * codestream; int depth = -1; // to increase to 0 after first <@ int we_re_in_a_comment = 0; char * code = malloc(sizeof(char)*2); size_t code_index = 0; size_t read_index = 0; int in_string = 0; while(1) { if((input_char == BVR_CLOSING_COMMAND_TAG_CHAR_2 && previous_char == BVR_CLOSING_COMMAND_TAG_CHAR_1 && depth == 0 && we_re_in_a_comment == 0 && in_string == 0)) { break; } if(previous_char == BVR_OPENING_COMMAND_TAG_CHAR_1 && input_char == BVR_OPENING_COMMAND_TAG_CHAR_2) { depth++; } // this šubidubi doesn't account for <@ and @> in strings. if(previous_char == BVR_CLOSING_COMMAND_TAG_CHAR_1 && input_char== BVR_CLOSING_COMMAND_TAG_CHAR_2) { depth--; } if(previous_char == LINE_COMMAND_CHAR && input_char == BVR_BREAK_STRING_CHAR) { in_string = 1; } if (previous_char != BVR_ESCAPE_CHAR && input_char == BVR_BREAK_STRING_CHAR && in_string == 1) { in_string = 0; } if(previous_char == BVR_NEWLINE_CHAR && input_char == LINE_COMMENT_CHAR) { we_re_in_a_comment = 1; } if(we_re_in_a_comment && input_char == BVR_NEWLINE_CHAR) { we_re_in_a_comment = 0; } previous_char = input_char; input_char = fgetc(input); read_index++; if (read_index >= 2) { code[code_index++] = input_char; code[code_index] = '\0'; } code = realloc(code, sizeof(char)*(2+code_index)); if (code == NULL) { fprintf(stderr, "segmentation fault caught (?) in bvr_handle_while, expect killing of the process soon. there was also a memory leak of around %lu bytes.\n", code_index+2); return_value = FAILURE; goto criticalfuckery; } } code[strlen(code)-2] = '\0'; code_index -= 2; codestream = fmemopen(code, code_index, "r"); while (atoi(string1) > 0) { /* basically the whole logic */ rewind(codestream); // fprintf(stderr, "debug: %s\n", code); return_value = return_value != SUCCESS ? return_value : bvr_compose_stream(codestream, output); string1 = bvr_var_get(item); } fclose(codestream); criticalfuckery: free(item); item = NULL; fflush(output); return return_value; } int bvr_handle_join(FILE * input, FILE * output) { char operation = fgetc(input); int return_value = SUCCESS; char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); char * value = bvr_commands_get_value(input, chars_to_break_value); char * stvar1 = bvr_var_get(item); char * stvar2 = bvr_var_get(value); char * temp = malloc(sizeof(char)*(strlen(stvar1)+strlen(stvar2)+1)); sprintf(temp, "%s%s", stvar1, stvar2); return_value = bvr_var_set(item, temp); free(item); free(value); free(temp); temp = NULL; item = NULL; value = NULL; return return_value; } int bvr_handle_math(FILE * input, FILE * output) { char operation = fgetc(input); int return_value = SUCCESS; char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); char * value = bvr_commands_get_value(input, chars_to_break_value); long long int stvar1 = strtoll(bvr_var_get(item), NULL, 10); long long int stvar2 = strtoll(bvr_var_get(value), NULL, 10); char numberplaceholder[69]; switch (operation) { case '+': stvar1 += stvar2; break; case '-': stvar1 -= stvar2; break; case '*': stvar1 *= stvar2; break; case '/': if (stvar2 == 0) { return_value = FAILURE; fprintf(stderr, "division with zero is illegal, prevented, but raised an error. setting to highest value possible.\n"); stvar1 = LLONG_MAX; } else { stvar1 /= stvar2; } break; default: return_value = FAILURE; break; } snprintf(numberplaceholder, 69-1, "%lld", stvar1); return_value = bvr_var_set(item, numberplaceholder); free(item); free(value); item = NULL; value = NULL; return return_value; } int bvr_handle_explode(FILE * input, FILE * output) { char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); char * value = bvr_commands_get_value(input, chars_to_break_value); int return_value = SUCCESS; char * string1 = bvr_var_get(item); char * string2 = bvr_var_get(value); char * token; char * rest = malloc(sizeof(char)*(strlen(string1)+1)); strcpy(rest, string1); char * charpointer; int index = strlen(item); size_t len = 0; char lenst[69]; item[index++] = '['; item[index] = '\0'; index = 0; while ((token = strsep(&rest, string2))) { // strsep handles empty strings as well charpointer = strrchr(item, BVR_ARRAY_INDEX_CHAR); sprintf(charpointer+1, "%d" BVR_ARRAY_AFTER_INDEX, index++); /* keys must always have 128 bytes more space allocated */ return_value = return_value != SUCCESS ? return_value : bvr_var_set(item, token); // če je bila prej napaka pač ne poskušamo več! len++; } charpointer = strrchr(item, BVR_ARRAY_INDEX_CHAR); sprintf(charpointer+1, "#" BVR_ARRAY_AFTER_INDEX, index++); snprintf(lenst, 69-1, "%lu", len); return_value = return_value != SUCCESS ? return_value : bvr_var_set(item, lenst); free(item); free(value); item = NULL; value = NULL; fflush(output); return return_value; } int bvr_handle_info(FILE * input, FILE * output) { // fprintf(stderr, "[bvrcommands.c] bvr_handle_info: bvr bVerbose HTPCMS %d.%d.%d\n", BVR_VER_MAJOR, BVR_VER_MINOR, BVR_VER_PATCH); char chars_to_break_value[69] = " "; strlcat(chars_to_break_value, BVR_CHARS_TO_BREAK_VALUE, sizeof(chars_to_break_value)); char * item = bvr_commands_get_value(input, chars_to_break_value); switch(item[0]) { case 'c': fprintf(output, "%lu", bvr_variables_count); break; default: fprintf(output, "\nbvr bVerbose HTPCMS %d.%d.%d\n", BVR_VER_MAJOR, BVR_VER_MINOR, BVR_VER_PATCH); break; } free(item); item = NULL; return SUCCESS; }