diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..2e6afb4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +# To stay consistent with the V formatting style, we use tabs +UseTab: Always +IndentWidth: 4 +TabWidth: 4 diff --git a/Makefile b/Makefile index cbf0fe9..57b89a7 100644 --- a/Makefile +++ b/Makefile @@ -70,22 +70,42 @@ man: vieter # =====OTHER===== +# Linting .PHONY: lint -lint: +lint: lint-v lint-c + +.PHONY: lint-v +lint-v: $(V) fmt -verify $(SRC_DIR) $(V) vet -W $(SRC_DIR) $(V_PATH) missdoc -p $(SRC_DIR) @ [ $$($(V_PATH) missdoc -p $(SRC_DIR) | wc -l) = 0 ] -# Format the V codebase +.PHONY: lint-c +lint-c: + clang-format --Werror -n $(SRCS_C) $(SRCS_H) + + +# Formatting .PHONY: fmt -fmt: +fmt: fmt-v fmt-c + +.PHONY: fmt-v +fmt-v: $(V) fmt -w $(SRC_DIR) +.PHONY: fmt-c +fmt-c: + clang-format -i $(SRCS_C) $(SRCS_H) + + +# Testing .PHONY: test test: $(V) -g test $(SRC_DIR) + +# Cleaning .PHONY: clean clean: rm -rf 'data' 'vieter' 'dvieter' 'pvieter' 'vieter.c' 'pkg' 'src/vieter' *.pkg.tar.zst 'suvieter' 'afvieter' '$(SRC_DIR)/_docs' 'docs/public' diff --git a/src/cron/c/expression.c b/src/cron/c/expression.c index 4e1ca3c..7d27be6 100644 --- a/src/cron/c/expression.c +++ b/src/cron/c/expression.c @@ -3,9 +3,7 @@ const uint8_t month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -cron_expression *ce_init() { - return malloc(sizeof(cron_expression)); -} +cron_expression *ce_init() { return malloc(sizeof(cron_expression)); } void ce_free(cron_expression *ce) { free(ce->months); @@ -15,7 +13,8 @@ void ce_free(cron_expression *ce) { free(ce); } -void ce_next(cron_simple_time *out, cron_expression *ce, cron_simple_time *ref) { +void ce_next(cron_simple_time *out, cron_expression *ce, + cron_simple_time *ref) { // For all of these values, the rule is the following: if their value is // the length of their respective array in the CronExpression object, that // means we've looped back around. This means that the "bigger" value has @@ -30,25 +29,30 @@ void ce_next(cron_simple_time *out, cron_expression *ce, cron_simple_time *ref) // value loops around, then the smaller value will always reset as well. // For example, if we're going to a new day, the hour & minute will always // be their smallest value again. - while (month_index < ce->month_count && ref->month > ce->months[month_index]) { + while (month_index < ce->month_count && + ref->month > ce->months[month_index]) { month_index++; } - if (month_index < ce->month_count && ref->month == ce->months[month_index]) { + if (month_index < ce->month_count && + ref->month == ce->months[month_index]) { while (day_index < ce->day_count && ref->day > ce->days[day_index]) { day_index++; } if (day_index < ce->day_count && ref->day == ce->days[day_index]) { - while (hour_index < ce->hour_count && ref->hour > ce->hours[hour_index]) { + while (hour_index < ce->hour_count && + ref->hour > ce->hours[hour_index]) { hour_index++; } - if (hour_index < ce->hour_count && ref->hour == ce->hours[hour_index]) { + if (hour_index < ce->hour_count && + ref->hour == ce->hours[hour_index]) { // Minute is the only value where we explicitely make sure we // can't match sref's value exactly. This is to ensure we only // return values in the future. - while (minute_index < ce->minute_count && ref->minute >= ce->minutes[minute_index]) { + while (minute_index < ce->minute_count && + ref->minute >= ce->minutes[minute_index]) { minute_index++; } } @@ -82,7 +86,8 @@ void ce_next(cron_simple_time *out, cron_expression *ce, cron_simple_time *ref) out->day = ce->days[0]; month_index++; - while (out->day > month_days[ce->months[month_index % ce->month_count] - 1]) { + while (out->day > + month_days[ce->months[month_index % ce->month_count] - 1]) { month_index++; } } @@ -101,15 +106,13 @@ void ce_next_from_now(cron_simple_time *out, cron_expression *ce) { struct tm gm; gmtime_r(&t, &gm); - cron_simple_time ref = { - // tm_year contains years since 1900 - .year = 1900 + gm.tm_year, - // tm_mon goes from 0 to 11 - .month = gm.tm_mon + 1, - .day = gm.tm_mday, - .hour = gm.tm_hour, - .minute = gm.tm_min - }; + cron_simple_time ref = {// tm_year contains years since 1900 + .year = 1900 + gm.tm_year, + // tm_mon goes from 0 to 11 + .month = gm.tm_mon + 1, + .day = gm.tm_mday, + .hour = gm.tm_hour, + .minute = gm.tm_min}; ce_next(out, ce, &ref); } diff --git a/src/cron/c/expression.h b/src/cron/c/expression.h index c599e4e..4b40a96 100644 --- a/src/cron/c/expression.h +++ b/src/cron/c/expression.h @@ -1,10 +1,10 @@ #ifndef VIETER_CRON #define VIETER_CRON -#include #include #include #include +#include typedef enum cron_parse_error { cron_parse_ok = 0, @@ -37,7 +37,8 @@ cron_expression *ce_init(); void cron_ce_free(cron_expression *ce); -void cron_ce_next(cron_simple_time *out, cron_expression *ce, cron_simple_time *ref); +void cron_ce_next(cron_simple_time *out, cron_expression *ce, + cron_simple_time *ref); void cron_ce_next_from_now(cron_simple_time *out, cron_expression *ce); diff --git a/src/cron/c/parse.c b/src/cron/c/parse.c index 097a08d..bb54191 100644 --- a/src/cron/c/parse.c +++ b/src/cron/c/parse.c @@ -1,7 +1,8 @@ #include "expression.h" // This prefix is needed to properly compile -const uint8_t parse_month_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +const uint8_t parse_month_days[] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; // Allowed value ranges for the minute, hour, day and month field const uint8_t min[4] = {0, 0, 1, 1}; @@ -12,15 +13,15 @@ const uint8_t max_parts = 4; // Convert a string into a uint8_t value by parsing it using atoi and checking // whether it's contained within the given range -#define SAFE_ATOI(v,s,min,max) \ - int _##v = atoi(s); \ - if ((_##v) == 0 && strcmp((s), "0") != 0) { \ - return cron_parse_invalid_number; \ - } \ - if (((_##v) < (min)) || ((_##v) > (max))) { \ - return cron_parse_out_of_range; \ - } \ - v = (uint8_t) (_##v); +#define SAFE_ATOI(v, s, min, max) \ + int _##v = atoi(s); \ + if ((_##v) == 0 && strcmp((s), "0") != 0) { \ + return cron_parse_invalid_number; \ + } \ + if (((_##v) < (min)) || ((_##v) > (max))) { \ + return cron_parse_out_of_range; \ + } \ + v = (uint8_t)(_##v); #define MAX(x, y) (((x) > (y)) ? (x) : (y)) @@ -40,7 +41,8 @@ const uint8_t max_parts = 4; * - a/c * - a-b/c */ -cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, uint8_t max) { +cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, + uint8_t max) { size_t slash_index = 0; size_t dash_index = 0; size_t i = 0; @@ -75,7 +77,7 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, uint8_t max } else { return cron_parse_invalid_expression; } - }else { + } else { SAFE_ATOI(start, s, min, max); if (dash_index > 0) { @@ -89,10 +91,10 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, uint8_t max } if (interval == 0) { - *out |= ((uint64_t) 1) << (start - min); + *out |= ((uint64_t)1) << (start - min); } else { while (start <= end) { - *out |= ((uint64_t) 1) << (start - min); + *out |= ((uint64_t)1) << (start - min); start += interval; } } @@ -105,7 +107,8 @@ cron_parse_error ce_parse_range(uint64_t *out, char *s, uint8_t min, uint8_t max * min-max range the part represents. A part consists of one or more range * expressions, separated by commas. */ -cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min, uint8_t max) { +cron_parse_error ce_parse_part(uint64_t *out, char *s, uint8_t min, + uint8_t max) { *out = 0; char *next; @@ -149,9 +152,9 @@ uint8_t uint64_t_popcount(uint64_t n) { */ uint8_t bf_to_nums(uint8_t **out, uint64_t bf, uint8_t min, uint8_t max) { // Each bit field only has `max - min + 1` meaningful bits. All other bits - // should be ignored, and can be any value. By shifting the bit field back and - // forth, we set these excessive bits to zero, ensuring popcount returns the - // correct value. + // should be ignored, and can be any value. By shifting the bit field back + // and forth, we set these excessive bits to zero, ensuring popcount returns + // the correct value. uint8_t excess_bits = 64 - (max - min + 1); bf = (bf << excess_bits) >> excess_bits; uint8_t size = uint64_t_popcount(bf); @@ -230,12 +233,11 @@ enum cron_parse_error ce_parse_expression(cron_expression *out, char *s) { part_count++; } - // We now parse the parts in reverse. This is because the month part // determines the maximum value of the day part. - + uint64_t bit_field = 0; - + // Months if (part_count >= 4) { res = ce_parse_part(&bit_field, parts[3], min[3], max[3]); @@ -255,9 +257,10 @@ enum cron_parse_error ce_parse_expression(cron_expression *out, char *s) { uint8_t max_day_value = 0; for (uint8_t i = 0; i < out->month_count; i++) { - max_day_value = MAX(max_day_value, parse_month_days[out->months[i] - 1]); + max_day_value = + MAX(max_day_value, parse_month_days[out->months[i] - 1]); } - + // Days if (part_count >= 3) { bit_field = 0; @@ -268,7 +271,8 @@ enum cron_parse_error ce_parse_expression(cron_expression *out, char *s) { goto end; } - out->day_count = bf_to_nums(&out->days, bit_field, min[2], max_day_value); + out->day_count = + bf_to_nums(&out->days, bit_field, min[2], max_day_value); } // If days aren't provided, they're replaced with a * else { diff --git a/src/cron/parse_test.v b/src/cron/parse_test.v index eb78c19..a44dffd 100644 --- a/src/cron/parse_test.v +++ b/src/cron/parse_test.v @@ -20,6 +20,10 @@ fn test_not_allowed() { res = false parse_expression('0 0 30 2 0') or { res = true } assert res + + res = false + parse_expression('0 /5') or { res = true } + assert res } fn test_leading_star() {