diff --git a/src/picom.c b/src/picom.c index a46ae92f70..c66f940a70 100644 --- a/src/picom.c +++ b/src/picom.c @@ -68,6 +68,7 @@ #include "utils/list.h" #include "utils/misc.h" #include "utils/statistics.h" +#include "utils/str.h" #include "utils/uthash_extra.h" #include "vblank.h" #include "wm/defs.h" @@ -1150,10 +1151,7 @@ static int register_cm(session_t *ps) { xcb_atom_t atom; char *buf = NULL; - if (asprintf(&buf, "%s%d", register_prop, ps->c.screen) < 0) { - log_fatal("Failed to allocate memory"); - return -1; - } + casprintf(&buf, "%s%d", register_prop, ps->c.screen); atom = get_atom_with_nul(ps->atoms, buf, ps->c.c); free(buf); diff --git a/src/transition/curve.c b/src/transition/curve.c index 28f12e6eba..5323c7db59 100644 --- a/src/transition/curve.c +++ b/src/transition/curve.c @@ -126,7 +126,7 @@ struct curve parse_steps(const char *input_str, const char **out_end, char **err const char *str = input_str; *err = NULL; if (*str != '(') { - asprintf(err, "Invalid steps %s.", str); + casprintf(err, "Invalid steps %s.", str); return CURVE_INVALID_INIT; } str += 1; @@ -134,12 +134,12 @@ struct curve parse_steps(const char *input_str, const char **out_end, char **err char *end; auto steps = strtol(str, &end, 10); if (end == str || steps > INT_MAX) { - asprintf(err, "Invalid step count at \"%s\".", str); + casprintf(err, "Invalid step count at \"%s\".", str); return CURVE_INVALID_INIT; } str = skip_space(end); if (*str != ',') { - asprintf(err, "Invalid steps argument list \"%s\".", input_str); + casprintf(err, "Invalid steps argument list \"%s\".", input_str); return CURVE_INVALID_INIT; } str = skip_space(str + 1); @@ -148,13 +148,13 @@ struct curve parse_steps(const char *input_str, const char **out_end, char **err bool jump_end = starts_with(str, "jump-end", true) || starts_with(str, "jump-both", true); if (!jump_start && !jump_end && !starts_with(str, "jump-none", true)) { - asprintf(err, "Invalid jump setting for steps \"%s\".", str); + casprintf(err, "Invalid jump setting for steps \"%s\".", str); return CURVE_INVALID_INIT; } str += jump_start ? (jump_end ? 9 : 10) : (jump_end ? 8 : 9); str = skip_space(str); if (*str != ')') { - asprintf(err, "Invalid steps argument list \"%s\".", input_str); + casprintf(err, "Invalid steps argument list \"%s\".", input_str); return CURVE_INVALID_INIT; } *out_end = str + 1; @@ -165,7 +165,7 @@ struct curve parse_cubic_bezier(const char *input_str, const char **out_end, cha double numbers[4]; const char *str = input_str; if (*str != '(') { - asprintf(err, "Invalid cubic-bazier %s.", str); + casprintf(err, "Invalid cubic-bazier %s.", str); return CURVE_INVALID_INIT; } str += 1; @@ -175,13 +175,13 @@ struct curve parse_cubic_bezier(const char *input_str, const char **out_end, cha const char *end = NULL; numbers[i] = strtod_simple(str, &end); if (end == str) { - asprintf(err, "Invalid number %s.", str); + casprintf(err, "Invalid number %s.", str); return CURVE_INVALID_INIT; } str = skip_space(end); const char expected = i == 3 ? ')' : ','; if (*str != expected) { - asprintf(err, "Invalid cubic-bazier argument list %s.", input_str); + casprintf(err, "Invalid cubic-bazier argument list %s.", input_str); return CURVE_INVALID_INIT; } str += 1; @@ -209,7 +209,7 @@ struct curve curve_parse(const char *str, const char **end, char **err) { return curve_parsers[i].parse(str + name_len, end, err); } } - asprintf(err, "Unknown curve type \"%s\".", str); + casprintf(err, "Unknown curve type \"%s\".", str); return CURVE_INVALID_INIT; } diff --git a/src/transition/script.c b/src/transition/script.c index 3cf107ea78..7a2c478550 100644 --- a/src/transition/script.c +++ b/src/transition/script.c @@ -143,7 +143,7 @@ static char parse_op(const char *input_str, const char **end, char **err) { return input_str[0]; } - asprintf(err, "Expected one of \"%s\", got '%c'.", operators, input_str[0]); + casprintf(err, "Expected one of \"%s\", got '%c'.", operators, input_str[0]); *end = input_str; return 0; } @@ -198,7 +198,7 @@ parse_raw_operand(struct expression_parser_context *ctx, const char *str, const } } if (!succeeded) { - asprintf(err, "Expected a number or a variable name, got \"%s\".", str); + casprintf(err, "Expected a number or a variable name, got \"%s\".", str); *end = str; return; } @@ -219,7 +219,7 @@ parse_raw_operand(struct expression_parser_context *ctx, const char *str, const }; ctx->need_context = true; } else { - asprintf(err, "variable name \"%.*s\" is not defined", (int)(*end - str), str); + casprintf(err, "variable name \"%.*s\" is not defined", (int)(*end - str), str); *end = str; return; } @@ -245,8 +245,8 @@ static inline double op_eval(double l, enum op op, double r) { } static bool pop_op(const char *input_str, struct expression_parser_context *ctx, char **err) { if (ctx->operand_top < 2) { - asprintf(err, "Missing operand for operator %c, in expression %s", - ctx->op_stack[ctx->op_top - 1], input_str); + casprintf(err, "Missing operand for operator %c, in expression %s", + ctx->op_stack[ctx->op_top - 1], input_str); return false; } auto f = ctx->entry->entry_point; @@ -298,7 +298,7 @@ static bool parse_operand_or_paren(struct expression_parser_context *ctx, } } if (ctx->op_top == 0) { - asprintf(err, "Unmatched ')' in expression \"%s\"", input_str); + casprintf(err, "Unmatched ')' in expression \"%s\"", input_str); return false; } ctx->op_top -= 1; @@ -379,7 +379,7 @@ static bool expression_compile(struct compilation_stack **stack_entry, const cha } } if (ctx.operand_top != 1) { - asprintf(err, "excessive operand on stack %s", input_str); + casprintf(err, "excessive operand on stack %s", input_str); goto end; } succeeded = true; @@ -439,8 +439,8 @@ transition_compile(struct compilation_stack **stack_entry, config_setting_t *set if (config_setting_lookup_string(setting, "curve", &str)) { curve = curve_parse(str, &str, &err); if (curve.type == CURVE_INVALID) { - asprintf(out_err, "Cannot parse curve at line %d: %s", - config_setting_source_line(setting), err); + casprintf(out_err, "Cannot parse curve at line %d: %s", + config_setting_source_line(setting), err); free(err); return false; } @@ -467,14 +467,14 @@ transition_compile(struct compilation_stack **stack_entry, config_setting_t *set if (config_setting_lookup_float(setting, "start", &number)) { start = make_imm_stack_entry(ctx, number, start_slot, true); } else if (!config_setting_lookup_string(setting, "start", &str)) { - asprintf(out_err, - "Transition definition does not contain a start value or " - "expression. Line %d.", - config_setting_source_line(setting)); + casprintf(out_err, + "Transition definition does not contain a start value or " + "expression. Line %d.", + config_setting_source_line(setting)); return false; } else if (!expression_compile(&start, str, ctx, start_slot, !reset, &err)) { - asprintf(out_err, "transition has an invalid start expression: %s Line %d.", - err, config_setting_source_line(setting)); + casprintf(out_err, "transition has an invalid start expression: %s Line %d.", + err, config_setting_source_line(setting)); free(err); return false; } @@ -487,18 +487,18 @@ transition_compile(struct compilation_stack **stack_entry, config_setting_t *set .imm = number, }; } else if (!config_setting_lookup_string(setting, "end", &str)) { - asprintf(out_err, - "Transition definition does not contain a end value or " - "expression. Line %d.", - config_setting_source_line(setting)); + casprintf(out_err, + "Transition definition does not contain a end value or " + "expression. Line %d.", + config_setting_source_line(setting)); return false; } else { BUG_ON(ctx->allocated_slots > UINT_MAX - 1); auto end_slot = ctx->allocated_slots++; if (!expression_compile(&end, str, ctx, end_slot, false, &err)) { - asprintf(out_err, - "Transition has an invalid end expression: %s. Line %d", - err, config_setting_source_line(setting)); + casprintf(out_err, + "Transition has an invalid end expression: %s. Line %d", + err, config_setting_source_line(setting)); free(err); return false; } @@ -510,8 +510,8 @@ transition_compile(struct compilation_stack **stack_entry, config_setting_t *set if (config_setting_lookup_float(setting, "duration", &number)) { if (number == 0) { - asprintf(out_err, "Duration must be greater than 0. Line %d.", - config_setting_source_line(setting)); + casprintf(out_err, "Duration must be greater than 0. Line %d.", + config_setting_source_line(setting)); return false; } load_parameters[1] = (struct instruction){ @@ -519,17 +519,19 @@ transition_compile(struct compilation_stack **stack_entry, config_setting_t *set .imm = number, }; } else if (!config_setting_lookup_string(setting, "duration", &str)) { - asprintf(out_err, - "Transition definition does not contain a duration value or " - "expression. Line %d.", - config_setting_source_line(setting)); + casprintf(out_err, + "Transition definition does not contain a duration value or " + "expression. Line %d.", + config_setting_source_line(setting)); return false; } else { BUG_ON(ctx->allocated_slots > UINT_MAX - 1); auto duration_slot = ctx->allocated_slots++; if (!expression_compile(&end, str, ctx, duration_slot, false, &err)) { - asprintf(out_err, "Transition has an invalid duration expression: %s. Line %d", - err, config_setting_source_line(setting)); + casprintf(out_err, + "Transition has an invalid duration expression: %s. " + "Line %d", + err, config_setting_source_line(setting)); free(err); return false; } @@ -553,8 +555,8 @@ transition_compile(struct compilation_stack **stack_entry, config_setting_t *set BUG_ON(ctx->allocated_slots > UINT_MAX - 1); auto delay_slot = ctx->allocated_slots++; if (!expression_compile(&end, str, ctx, delay_slot, false, &err)) { - asprintf(out_err, "Transition has an invalid delay expression: %s. Line %d", - err, config_setting_source_line(setting)); + casprintf(out_err, "Transition has an invalid delay expression: %s. Line %d", + err, config_setting_source_line(setting)); free(err); return false; } @@ -730,18 +732,19 @@ static bool script_compile_one(struct compilation_stack **stack_entry, config_se bool succeeded = expression_compile(stack_entry, str, ctx, alloc->slot, false, &tmp_err); if (!succeeded) { - asprintf(err, "Failed to parse expression at line %d. %s", - config_setting_source_line(var), tmp_err); + casprintf(err, "Failed to parse expression at line %d. %s", + config_setting_source_line(var), tmp_err); free(tmp_err); } return succeeded; } if (!config_setting_is_group(var)) { - asprintf(err, - "Invalid variable \"%s\", it must be either a number, a string, " - "or a config group defining a transition.", - config_setting_name(var)); + casprintf(err, + "Invalid variable \"%s\", it must be either a number, a " + "string, " + "or a config group defining a transition.", + config_setting_name(var)); return false; } return transition_compile(stack_entry, var, ctx, alloc->slot, err); @@ -772,8 +775,8 @@ static void report_cycle(struct compilation_stack **stack, unsigned top, unsigne } strcpy(pos, last_name); - asprintf(err, "Cyclic references detected in animation script defined at line %d: %s", - config_setting_source_line(setting), buf); + casprintf(err, "Cyclic references detected in animation script defined at line %d: %s", + config_setting_source_line(setting), buf); free(buf); } diff --git a/src/utils/str.h b/src/utils/str.h index 546d0c9535..61afea592c 100644 --- a/src/utils/str.h +++ b/src/utils/str.h @@ -42,6 +42,18 @@ static inline int uitostr(unsigned int n, char *buf) { return ret; } +/// Like `asprintf`, but it aborts the program if memory allocation fails. +static inline size_t __attribute__((format(printf, 2, 3))) +casprintf(char **strp, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int ret = vasprintf(strp, fmt, ap); + va_end(ap); + + BUG_ON(ret < 0); + return (size_t)ret; +} + /// Convert a double into a string. Avoid using *printf functions to print floating points /// directly because they are locale dependent. static inline void dtostr(double n, char **buf) { @@ -49,14 +61,14 @@ static inline void dtostr(double n, char **buf) { BUG_ON(safe_isinf(n)); if (fabs(n) > 1e9) { // The number is so big that it's not meaningful to keep decimal places. - asprintf(buf, "%.0f", n); + casprintf(buf, "%.0f", n); return; } if (n > 0) { - asprintf(buf, "%.0f.%03d", floor(n), (int)(fmod(n, 1) * 1000)); + casprintf(buf, "%.0f.%03d", floor(n), (int)(fmod(n, 1) * 1000)); } else { - asprintf(buf, "-%.0f.%03d", floor(-n), (int)(fmod(-n, 1) * 1000)); + casprintf(buf, "-%.0f.%03d", floor(-n), (int)(fmod(-n, 1) * 1000)); } } @@ -94,15 +106,3 @@ static inline bool starts_with(const char *str, const char *needle, bool ignore_ /// reallocates it if it's not big enough. int asnprintf(char **strp, size_t *capacity, const char *fmt, ...) __attribute__((format(printf, 3, 4))); - -/// Like `asprintf`, but it aborts the program if memory allocation fails. -static inline size_t __attribute__((format(printf, 2, 3))) -casprintf(char **strp, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int ret = vasprintf(strp, fmt, ap); - va_end(ap); - - BUG_ON(ret < 0); - return (size_t)ret; -}