diff options
-rw-r--r-- | src/arg.h | 2 | ||||
-rw-r--r-- | src/coopgammad.c | 89 | ||||
-rw-r--r-- | src/filter.c | 10 | ||||
-rw-r--r-- | src/filter.h | 19 | ||||
-rw-r--r-- | src/message.c | 50 | ||||
-rw-r--r-- | src/message.h | 31 | ||||
-rw-r--r-- | src/output.c | 20 | ||||
-rw-r--r-- | src/output.h | 48 | ||||
-rw-r--r-- | src/ramps.c | 9 | ||||
-rw-r--r-- | src/ramps.h | 20 | ||||
-rw-r--r-- | src/ring.c | 16 | ||||
-rw-r--r-- | src/ring.h | 36 | ||||
-rw-r--r-- | src/server.c | 89 | ||||
-rw-r--r-- | src/server.h | 20 | ||||
-rw-r--r-- | src/util.c | 11 | ||||
-rw-r--r-- | src/util.h | 29 |
16 files changed, 311 insertions, 188 deletions
@@ -6,7 +6,7 @@ #ifndef ARG_H__ #define ARG_H__ -extern char *argv0; +extern char *restrict argv0; /* use main(int argc, char *argv[]) */ #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ diff --git a/src/coopgammad.c b/src/coopgammad.c index 9374dc9..7e6422e 100644 --- a/src/coopgammad.c +++ b/src/coopgammad.c @@ -45,18 +45,28 @@ -extern char* argv0_real; -extern struct output* outputs; +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + +extern char* restrict argv0_real; +extern struct output* restrict outputs; extern size_t outputs_n; extern int socketfd; -extern char* pidpath; -extern char* socketpath; +extern char* restrict pidpath; +extern char* restrict socketpath; extern int gerror; extern int method; -extern char* sitename; +extern char* restrict sitename; extern libgamma_site_state_t site; -extern libgamma_partition_state_t* partitions; -extern libgamma_crtc_state_t* crtcs; +extern libgamma_partition_state_t* restrict partitions; +extern libgamma_crtc_state_t* restrict crtcs; extern volatile sig_atomic_t reexec; extern volatile sig_atomic_t terminate; extern volatile sig_atomic_t connection; @@ -66,18 +76,18 @@ extern volatile sig_atomic_t connection; /** * The name of the process */ -char* argv0; +char* restrict argv0; /** * The real pathname of the process's binary, * `NULL` if `argv0` is satisfactory */ -char* argv0_real = NULL; +char* restrict argv0_real = NULL; /** * Array of all outputs */ -struct output* outputs = NULL; +struct output* restrict outputs = NULL; /** * The nubmer of elements in `outputs` @@ -92,12 +102,12 @@ int socketfd = -1; /** * The pathname of the PID file */ -char* pidpath = NULL; +char* restrict pidpath = NULL; /** * The pathname of the socket */ -char* socketpath = NULL; +char* restrict socketpath = NULL; /** * Error code returned by libgamma @@ -112,7 +122,7 @@ int method = -1; /** * The site's name, may be `NULL` */ -char* sitename = NULL; +char* restrict sitename = NULL; /** * The libgamma site state @@ -122,12 +132,12 @@ libgamma_site_state_t site; /** * The libgamma partition states */ -libgamma_partition_state_t* partitions = NULL; +libgamma_partition_state_t* restrict partitions = NULL; /** * The libgamma CRTC states */ -libgamma_crtc_state_t* crtcs = NULL; +libgamma_crtc_state_t* restrict crtcs = NULL; /** * Has the process receive a signal @@ -196,14 +206,15 @@ static void sig_connection(int signo) * @param suffix The suffix for the file * @return The pathname of the file, `NULL` on error */ -static char* get_pathname(const char* suffix) +GCC_ONLY(__attribute__((malloc, nonnull))) +static char* get_pathname(const char* restrict suffix) { - const char* rundir = getenv("XDG_RUNTIME_DIR"); - const char* username = ""; + const char* restrict rundir = getenv("XDG_RUNTIME_DIR"); + const char* restrict username = ""; char* name = NULL; char* p; - char* rc; - struct passwd* pw; + char* restrict rc; + struct passwd* restrict pw; size_t n; int saved_errno; @@ -260,6 +271,7 @@ static char* get_pathname(const char* suffix) * * @return The pathname of the socket, `NULL` on error */ +GCC_ONLY(__attribute__((malloc))) static inline char* get_socket_pathname(void) { return get_pathname(".socket"); @@ -271,6 +283,7 @@ static inline char* get_socket_pathname(void) * * @return The pathname of the PID file, `NULL` on error */ +GCC_ONLY(__attribute__((malloc))) static inline char* get_pidfile_pathname(void) { return get_pathname(".pid"); @@ -282,6 +295,7 @@ static inline char* get_pidfile_pathname(void) * * @return The pathname of the state file, `NULL` on error */ +GCC_ONLY(__attribute__((malloc))) static inline char* get_state_pathname(void) { return get_pathname(".state"); @@ -294,13 +308,14 @@ static inline char* get_state_pathname(void) * @param arg The adjustment method name (or stringised number) * @return The adjustment method, -1 (negative) on error */ -static int get_method(char* arg) +GCC_ONLY(__attribute__((nonnull))) +static int get_method(const char* restrict arg) { #if LIBGAMMA_METHOD_MAX > 5 # warning libgamma has added more adjustment methods #endif - char* p; + const char* restrict p; if (!strcmp(arg, "dummy")) return LIBGAMMA_METHOD_DUMMY; if (!strcmp(arg, "randr")) return LIBGAMMA_METHOD_X_RANDR; @@ -331,7 +346,9 @@ static int get_method(char* arg) * @param crtc libgamma's state for the CRTC * @return The name of the CRTC, `NULL` on error */ -static char* get_crtc_name(libgamma_crtc_information_t* info, libgamma_crtc_state_t* crtc) +GCC_ONLY(__attribute__((nonnull))) +static char* get_crtc_name(const libgamma_crtc_information_t* restrict info, + const libgamma_crtc_state_t* restrict crtc) { if ((info->edid_error == 0) && (info->edid != NULL)) return libgamma_behex_edid(info->edid, info->edid_length); @@ -362,7 +379,8 @@ static char* get_crtc_name(libgamma_crtc_information_t* info, libgamma_crtc_stat * 0: The service is already running * 1: The PID file is outdated */ -static int is_pidfile_reusable(const char* pidfile, const char* token) +GCC_ONLY(__attribute__((nonnull))) +static int is_pidfile_reusable(const char* restrict pidfile, const char* restrict token) { /* PORTERS: /proc/$PID/environ is Linux specific */ @@ -456,11 +474,12 @@ static int is_pidfile_reusable(const char* pidfile, const char* token) * @return Zero on success, -1 on error, * -2 if the service is already running */ +GCC_ONLY(__attribute__((nonnull))) static int create_pidfile(char* pidfile) { int fd, r, saved_errno; char* p; - char* token; + char* restrict token; /* Create token used to validate the service. */ token = malloc(sizeof("COOPGAMMAD_PIDFILE_TOKEN=") + strlen(pidfile)); @@ -543,7 +562,7 @@ static int initialise(int full, int preserve, int foreground, int keep_stderr, i struct rlimit rlimit; size_t i, j, n, n0; sigset_t mask; - char* sitename_dup = NULL; + char* restrict sitename_dup = NULL; int r; /* Zero out some memory so it can be destoried safely. */ @@ -966,10 +985,10 @@ static void destroy(int full) * buffer needs to be * @return The number of marshalled bytes */ -static size_t marshal(void* buf) +static size_t marshal(void* restrict buf) { size_t off = 0, i, n; - char* bs = buf; + char* restrict bs = buf; if (bs != NULL) *(int*)(bs + off) = MARSHAL_VERSION; @@ -1041,10 +1060,11 @@ static size_t marshal(void* buf) * @param buf Buffer with the marshalled data * @return The number of marshalled bytes, 0 on error */ -static size_t unmarshal(void* buf) +GCC_ONLY(__attribute__((nonnull))) +static size_t unmarshal(void* restrict buf) { size_t off = 0, i, n; - char* bs = buf; + char* restrict bs = buf; if (*(int*)(bs + off) != MARSHAL_VERSION) { @@ -1125,10 +1145,11 @@ static size_t unmarshal(void* buf) * @param statefile The state file * @return Zero on success, -1 on error */ -static int unmarshal_and_merge_state(const char* statefile) +GCC_ONLY(__attribute__((nonnull))) +static int unmarshal_and_merge_state(const char* restrict statefile) { - struct output* new_outputs = outputs; - struct output* old_outputs = NULL; + struct output* restrict new_outputs = outputs; + struct output* restrict old_outputs = NULL; size_t new_outputs_n = outputs_n; size_t old_outputs_n = 0; size_t i, j, k; @@ -1221,7 +1242,7 @@ static int unmarshal_and_merge_state(const char* statefile) */ static int print_method_and_site(int query) { - const char* methodname = NULL; + const char* restrict methodname = NULL; char* p; if (query == 1) diff --git a/src/filter.c b/src/filter.c index 943401e..c335e0b 100644 --- a/src/filter.c +++ b/src/filter.c @@ -29,7 +29,7 @@ * * @param this The filter */ -void filter_destroy(struct filter* this) +void filter_destroy(struct filter* restrict this) { free(this->class); free(this->ramps); @@ -52,11 +52,11 @@ void filter_destroy(struct filter* this) * @param ramps_size The byte-size of `this->ramps` * @return The number of marshalled byte */ -size_t filter_marshal(const struct filter* this, void* buf, size_t ramps_size) +size_t filter_marshal(const struct filter* restrict this, void* restrict buf, size_t ramps_size) { size_t off = 0, n; char nonnulls = 0; - char* bs = buf; + char* restrict bs = buf; if (bs != NULL) { @@ -101,11 +101,11 @@ size_t filter_marshal(const struct filter* this, void* buf, size_t ramps_size) * @param ramps_size The byte-size of `this->ramps` * @return The number of unmarshalled bytes, 0 on error */ -size_t filter_unmarshal(struct filter* this, const void* buf, size_t ramps_size) +size_t filter_unmarshal(struct filter* restrict this, const void* restrict buf, size_t ramps_size) { size_t off = 0, n; char nonnulls = 0; - const char* bs = buf; + const char* restrict bs = buf; nonnulls = *(bs + off); off += 1; diff --git a/src/filter.h b/src/filter.h index 385ec56..5691f6c 100644 --- a/src/filter.h +++ b/src/filter.h @@ -20,6 +20,16 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * The lifespan of a filter */ @@ -91,7 +101,8 @@ struct filter * * @param this The filter */ -void filter_destroy(struct filter* this); +GCC_ONLY(__attribute__((nonnull))) +void filter_destroy(struct filter* restrict this); /** * Marshal a filter @@ -103,7 +114,8 @@ void filter_destroy(struct filter* this); * @param ramps_size The byte-size of `filter->ramps` * @return The number of marshalled byte */ -size_t filter_marshal(const struct filter* this, void* buf, size_t ramps_size); +GCC_ONLY(__attribute__((nonnull(1)))) +size_t filter_marshal(const struct filter* restrict this, void* restrict buf, size_t ramps_size); /** * Unmarshal a filter @@ -114,5 +126,6 @@ size_t filter_marshal(const struct filter* this, void* buf, size_t ramps_size); * @param ramps_size The byte-size of `filter->ramps` * @return The number of unmarshalled bytes, 0 on error */ -size_t filter_unmarshal(struct filter* this, const void* buf, size_t ramps_size); +GCC_ONLY(__attribute__((nonnull))) +size_t filter_unmarshal(struct filter* restrict this, const void* restrict buf, size_t ramps_size); diff --git a/src/message.c b/src/message.c index 619ae25..48bdbff 100644 --- a/src/message.c +++ b/src/message.c @@ -33,7 +33,7 @@ * @param this Memory slot in which to store the new message * @return Non-zero on error, `errno` will be set accordingly */ -int message_initialise(struct message* this) +int message_initialise(struct message* restrict this) { this->headers = NULL; this->header_count = 0; @@ -56,7 +56,7 @@ int message_initialise(struct message* this) * * @param this The message */ -void message_destroy(struct message* this) +void message_destroy(struct message* restrict this) { size_t i; if (this->headers != NULL) @@ -85,7 +85,7 @@ void message_destroy(struct message* this) * needs to be * @return The number of marshalled byte */ -size_t message_marshal(const struct message* this, void* buf) +size_t message_marshal(const struct message* restrict this, void* restrict buf) { size_t i, n, off = 0; char* bs = buf; @@ -137,7 +137,7 @@ size_t message_marshal(const struct message* this, void* buf) * @param buf In buffer with the marshalled data * @return The number of unmarshalled bytes, 0 on error */ -size_t message_unmarshal(struct message* this, const void* buf) +size_t message_unmarshal(struct message* restrict this, const void* restrict buf) { size_t i, n, off = 0, header_count; const char* bs = buf; @@ -236,7 +236,8 @@ size_t message_unmarshal(struct message* this, const void* buf) * @param extent The number of additional entries * @return Zero on success, -1 on error */ -static int extend_headers(struct message* this, size_t extent) +GCC_ONLY(__attribute__((nonnull))) +static int extend_headers(struct message* restrict this, size_t extent) { char** new; if (!(new = realloc(this->headers, (this->header_count + extent) * sizeof(char*)))) @@ -252,9 +253,10 @@ static int extend_headers(struct message* this, size_t extent) * @param this The message * @return Zero on success, -1 on error */ -static int extend_buffer(struct message* this) +GCC_ONLY(__attribute__((nonnull))) +static int extend_buffer(struct message* restrict this) { - char* new; + char* restrict new; if (!(new = realloc(this->buffer, (this->buffer_size << 1) * sizeof(char)))) return -1; this->buffer = new; @@ -268,7 +270,8 @@ static int extend_buffer(struct message* this) * * @param this The message */ -static void reset_message(struct message* this) +GCC_ONLY(__attribute__((nonnull))) +static void reset_message(struct message* restrict this) { size_t i; if (this->headers != NULL) @@ -291,10 +294,8 @@ static void reset_message(struct message* this) * @param this The message * @return Zero on success, negative on error (malformated message: unrecoverable state) */ -#if defined(__GNUC__) -__attribute__((pure)) -#endif -static int get_payload_length(struct message* this) +GCC_ONLY(__attribute__((pure, nonnull))) +static int get_payload_length(struct message* restrict this) { char* header; size_t i; @@ -326,12 +327,10 @@ static int get_payload_length(struct message* this) * @param length The length of the header * @return Zero if valid, negative if invalid (malformated message: unrecoverable state) */ -#if defined(__GNUC__) -__attribute__((pure)) -#endif -static int validate_header(const char* header, size_t length) +GCC_ONLY(__attribute__((pure, nonnull))) +static int validate_header(const char* restrict header, size_t length) { - char* p = memchr(header, ':', length * sizeof(char)); + char* restrict p = memchr(header, ':', length * sizeof(char)); if (verify_utf8(header, 0) < 0) /* Either the string is not UTF-8, or your are under an UTF-8 attack, @@ -353,7 +352,8 @@ static int validate_header(const char* header, size_t length) * @param length The number of characters to remove * @param update_ptr Whether to update the buffer pointer */ -static void unbuffer_beginning(struct message* this, size_t length, int update_ptr) +GCC_ONLY(__attribute__((nonnull))) +static void unbuffer_beginning(struct message* restrict this, size_t length, int update_ptr) { memmove(this->buffer, this->buffer + length, (this->buffer_ptr - length) * sizeof(char)); if (update_ptr) @@ -368,7 +368,8 @@ static void unbuffer_beginning(struct message* this, size_t length, int update_p * @param this The message * @return The return value follows the rules of `message_read` */ -static int initialise_payload(struct message* this) +GCC_ONLY(__attribute__((nonnull))) +static int initialise_payload(struct message* restrict this) { /* Remove the \n (end of empty line) we found from the buffer. */ unbuffer_beginning(this, 1, 1); @@ -393,9 +394,10 @@ static int initialise_payload(struct message* this) * @param length The length of the header, including LF-termination * @return The return value follows the rules of `message_read` */ -static int store_header(struct message* this, size_t length) +GCC_ONLY(__attribute__((nonnull))) +static int store_header(struct message* restrict this, size_t length) { - char* header; + char* restrict header; /* Allocate the header. */ if (!(header = malloc(length))) /* Last char is a LF, which is substituted with NUL. */ @@ -430,7 +432,8 @@ static int store_header(struct message* this, size_t length) * @param fd The file descriptor of the socket * @return The return value follows the rules of `message_read` */ -static int continue_read(struct message* this, int fd) +GCC_ONLY(__attribute__((nonnull))) +static int continue_read(struct message* restrict this, int fd) { size_t n; ssize_t got; @@ -480,7 +483,8 @@ static int continue_read(struct message* this, int fd) * Other: Failure * -2: Corrupt message (unrecoverable) */ -int message_read(struct message* this, int fd) +GCC_ONLY(__attribute__((nonnull))) +int message_read(struct message* restrict this, int fd) { size_t header_commit_buffer = 0; int r; diff --git a/src/message.h b/src/message.h index d6447f1..15a9330 100644 --- a/src/message.h +++ b/src/message.h @@ -20,6 +20,16 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * Message passed between a server and a client */ @@ -33,7 +43,7 @@ struct message * but `headers` itself is `NULL` if there are no headers. * The "Length" header should be included in this list. */ - char** headers; + char** restrict headers; /** * The number of headers in the message @@ -43,7 +53,7 @@ struct message /** * The payload of the message, `NULL` if none (of zero-length) */ - char* payload; + char* restrict payload; /** * The size of the payload @@ -58,7 +68,7 @@ struct message /** * Internal buffer for the reading function (internal data) */ - char* buffer; + char* restrict buffer; /** * The size allocated to `buffer` (internal data) @@ -90,7 +100,8 @@ struct message * @param this Memory slot in which to store the new message * @return Non-zero on error, `errno` will be set accordingly */ -int message_initialise(struct message* this); +GCC_ONLY(__attribute__((nonnull))) +int message_initialise(struct message* restrict this); /** * Release all resources in a message, should @@ -98,7 +109,8 @@ int message_initialise(struct message* this); * * @param this The message */ -void message_destroy(struct message* this); +GCC_ONLY(__attribute__((nonnull))) +void message_destroy(struct message* restrict this); /** * Marshal a message for state serialisation @@ -109,7 +121,8 @@ void message_destroy(struct message* this); * needs to be * @return The number of marshalled byte */ -size_t message_marshal(const struct message* this, void* buf); +GCC_ONLY(__attribute__((nonnull(1)))) +size_t message_marshal(const struct message* restrict this, void* restrict buf); /** * Unmarshal a message for state deserialisation @@ -118,7 +131,8 @@ size_t message_marshal(const struct message* this, void* buf); * @param buf In buffer with the marshalled data * @return The number of unmarshalled bytes, 0 on error */ -size_t message_unmarshal(struct message* this, const void* buf); +GCC_ONLY(__attribute__((nonnull))) +size_t message_unmarshal(struct message* restrict this, const void* restrict buf); /** * Read the next message from a file descriptor @@ -134,5 +148,6 @@ size_t message_unmarshal(struct message* this, const void* buf); * Other: Failure * -2: Corrupt message (unrecoverable) */ -int message_read(struct message* this, int fd); +GCC_ONLY(__attribute__((nonnull))) +int message_read(struct message* restrict this, int fd); diff --git a/src/output.c b/src/output.c index 264ad9b..e8913dd 100644 --- a/src/output.c +++ b/src/output.c @@ -29,7 +29,7 @@ /** * The name of the process */ -extern char* argv0; +extern char* restrict argv0; @@ -40,7 +40,7 @@ extern char* argv0; * * @param this The output */ -void output_destroy(struct output* this) +void output_destroy(struct output* restrict this) { size_t i; @@ -106,7 +106,7 @@ void output_destroy(struct output* this) * needs to be * @return The number of marshalled byte */ -size_t output_marshal(const struct output* this, void* buf) +size_t output_marshal(const struct output* restrict this, void* restrict buf) { size_t off = 0, i, n; char* bs = buf; @@ -163,7 +163,7 @@ size_t output_marshal(const struct output* this, void* buf) * @param buf Buffer with the marshalled output * @return The number of unmarshalled bytes, 0 on error */ -size_t output_unmarshal(struct output* this, const void* buf) +size_t output_unmarshal(struct output* restrict this, const void* restrict buf) { size_t off = 0, i, n; const char* bs = buf; @@ -240,7 +240,7 @@ size_t output_unmarshal(struct output* this, const void* buf) * @return See description of `a` and `b`, * 0 if returned if they are the same */ -int output_cmp_by_name(const void* a, const void* b) +int output_cmp_by_name(const void* restrict a, const void* restrict b) { const char* an = ((const struct output*)a)->name; const char* bn = ((const struct output*)b)->name; @@ -256,7 +256,7 @@ int output_cmp_by_name(const void* a, const void* b) * @param n The number of elements in `base` * @return Output find in `base`, `NULL` if not found */ -struct output* output_find_by_name(const char* key, struct output* base, size_t n) +struct output* output_find_by_name(const char* restrict key, struct output* restrict base, size_t n) { struct output k; @@ -280,7 +280,7 @@ struct output* output_find_by_name(const char* key, struct output* base, size_t * @param filter The filter * @return The index of the filter, `out->table_size` if not found */ -static ssize_t remove_filter(struct output* out, struct filter* filter) +static ssize_t remove_filter(struct output* restrict out, struct filter* restrict filter) { size_t i, n = out->table_size; @@ -314,7 +314,7 @@ static ssize_t remove_filter(struct output* out, struct filter* filter) * @param filter The filter * @return The index given to the filter, -1 on error */ -ssize_t add_filter(struct output* out, struct filter* filter) +ssize_t add_filter(struct output* restrict out, struct filter* restrict filter) { size_t i, n = out->table_size; int r = -1; @@ -389,7 +389,7 @@ ssize_t add_filter(struct output* out, struct filter* filter) * @param first_updated The index of the first added or removed filter * @return Zero on success, -1 on error */ -int flush_filters(struct output* output, size_t first_updated) +int flush_filters(struct output* restrict output, size_t first_updated) { union gamma_ramps plain; union gamma_ramps* last; @@ -439,7 +439,7 @@ int flush_filters(struct output* output, size_t first_updated) * @param output The output for which the ramps shall be configured * @return Zero on success, -1 on error */ -int make_plain_ramps(union gamma_ramps* ramps, struct output* output) +int make_plain_ramps(union gamma_ramps* restrict ramps, struct output* restrict output) { COPY_RAMP_SIZES(&(ramps->u8), output); switch (output->depth) diff --git a/src/output.h b/src/output.h index ef4172b..08978b5 100644 --- a/src/output.h +++ b/src/output.h @@ -24,6 +24,16 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * Copy the ramp sizes * @@ -91,12 +101,12 @@ struct output * followed by a dot and the name of the * connector */ - char* name; + char* restrict name; /** * The libgamma state for the output */ - libgamma_crtc_state_t* crtc; + libgamma_crtc_state_t* restrict crtc; /** * Saved gamma ramps @@ -106,7 +116,7 @@ struct output /** * The table of all applied filters */ - struct filter* table_filters; + struct filter* restrict table_filters; /** * `.table_sums[i]` is the resulting @@ -115,7 +125,7 @@ struct output * including `.table_filters[i]` has * been applied */ - union gamma_ramps* table_sums; + union gamma_ramps* restrict table_sums; /** * The number of elements allocated @@ -140,7 +150,8 @@ struct output * * @param this The output */ -void output_destroy(struct output* this); +GCC_ONLY(__attribute__((nonnull))) +void output_destroy(struct output* restrict this); /** * Marshal an output @@ -151,7 +162,8 @@ void output_destroy(struct output* this); * needs to be * @return The number of marshalled byte */ -size_t output_marshal(const struct output* this, void* buf); +GCC_ONLY(__attribute__((nonnull(1)))) +size_t output_marshal(const struct output* restrict this, void* restrict buf); /** * Unmarshal an output @@ -160,7 +172,8 @@ size_t output_marshal(const struct output* this, void* buf); * @param buf Buffer with the marshalled output * @return The number of unmarshalled bytes, 0 on error */ -size_t output_unmarshal(struct output* this, const void* buf); +GCC_ONLY(__attribute__((nonnull))) +size_t output_unmarshal(struct output* restrict this, const void* restrict buf); /** * Compare to outputs by the names of their respective CRTC:s @@ -170,10 +183,8 @@ size_t output_unmarshal(struct output* this, const void* buf); * @return See description of `a` and `b`, * 0 if returned if they are the same */ -#if defined(__GNUC__) -__attribute__((pure)) -#endif -int output_cmp_by_name(const void* a, const void* b); +GCC_ONLY(__attribute__((pure, nonnull))) +int output_cmp_by_name(const void* restrict a, const void* restrict b); /** * Find an output by its name @@ -183,10 +194,8 @@ int output_cmp_by_name(const void* a, const void* b); * @param n The number of elements in `base` * @return Output find in `base`, `NULL` if not found */ -#if defined(__GNUC__) -__attribute__((pure)) -#endif -struct output* output_find_by_name(const char* key, struct output* base, size_t n); +GCC_ONLY(__attribute__((pure, nonnull))) +struct output* output_find_by_name(const char* restrict key, struct output* restrict base, size_t n); /** * Add a filter to an output @@ -195,7 +204,8 @@ struct output* output_find_by_name(const char* key, struct output* base, size_t * @param filter The filter * @return The index given to the filter, -1 on error */ -ssize_t add_filter(struct output* output, struct filter* filter); +GCC_ONLY(__attribute__((nonnull))) +ssize_t add_filter(struct output* restrict output, struct filter* restrict filter); /** * Recalculate the resulting gamma and @@ -205,7 +215,8 @@ ssize_t add_filter(struct output* output, struct filter* filter); * @param first_updated The index of the first added or removed filter * @return Zero on success, -1 on error */ -int flush_filters(struct output* output, size_t first_updated); +GCC_ONLY(__attribute__((nonnull))) +int flush_filters(struct output* restrict output, size_t first_updated); /** * Make identity mapping ramps @@ -214,5 +225,6 @@ int flush_filters(struct output* output, size_t first_updated); * @param output The output for which the ramps shall be configured * @return Zero on success, -1 on error */ -int make_plain_ramps(union gamma_ramps* ramps, struct output* output); +GCC_ONLY(__attribute__((nonnull))) +int make_plain_ramps(union gamma_ramps* restrict ramps, struct output* restrict output); diff --git a/src/ramps.c b/src/ramps.c index f17f917..2b855a4 100644 --- a/src/ramps.c +++ b/src/ramps.c @@ -28,7 +28,7 @@ /** * The name of the process */ -extern char* argv0; +extern char* restrict argv0; @@ -42,7 +42,7 @@ extern char* argv0; * @param ramps_size The byte-size of ramps * @return The number of marshalled byte */ -size_t gamma_ramps_marshal(const union gamma_ramps* this, void* buf, size_t ramps_size) +size_t gamma_ramps_marshal(const union gamma_ramps* restrict this, void* restrict buf, size_t ramps_size) { if (buf != NULL) memcpy(buf, this->u8.red, ramps_size); @@ -59,7 +59,7 @@ size_t gamma_ramps_marshal(const union gamma_ramps* this, void* buf, size_t ramp * @param ramps_size The byte-size of ramps * @return The number of unmarshalled bytes, 0 on error */ -size_t gamma_ramps_unmarshal(union gamma_ramps* this, const void* buf, size_t ramps_size) +size_t gamma_ramps_unmarshal(union gamma_ramps* restrict this, const void* restrict buf, size_t ramps_size) { size_t depth = ramps_size / (this->u8.red_size + this->u8.green_size + this->u8.blue_size); int r = 0; @@ -109,7 +109,8 @@ size_t gamma_ramps_unmarshal(union gamma_ramps* this, const void* buf, size_t ra * @param base The CLUT on top of which the new filter should be applied, * this can be the same pointer as `dest` */ -void apply(union gamma_ramps* dest, void* application, int depth, union gamma_ramps* base) +void apply(union gamma_ramps* restrict dest, void* restrict application, + int depth, union gamma_ramps* restrict base) { union gamma_ramps app; size_t bytedepth; diff --git a/src/ramps.h b/src/ramps.h index d6c53cf..0ba8579 100644 --- a/src/ramps.h +++ b/src/ramps.h @@ -19,6 +19,16 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * Gamma ramps union for all * lbigamma gamma ramps types @@ -69,7 +79,8 @@ union gamma_ramps * @param ramps_size The byte-size of ramps * @return The number of marshalled byte */ -size_t gamma_ramps_marshal(const union gamma_ramps* this, void* buf, size_t ramps_size); +GCC_ONLY(__attribute__((nonnull(1)))) +size_t gamma_ramps_marshal(const union gamma_ramps* restrict this, void* restrict buf, size_t ramps_size); /** * Unmarshal a ramp trio @@ -79,7 +90,8 @@ size_t gamma_ramps_marshal(const union gamma_ramps* this, void* buf, size_t ramp * @param ramps_size The byte-size of ramps * @return The number of unmarshalled bytes, 0 on error */ -size_t gamma_ramps_unmarshal(union gamma_ramps* this, const void* buf, size_t ramps_size); +GCC_ONLY(__attribute__((nonnull))) +size_t gamma_ramps_unmarshal(union gamma_ramps* restrict this, const void* restrict buf, size_t ramps_size); /** * Apply a ramp-trio on top of another ramp-trio @@ -93,5 +105,7 @@ size_t gamma_ramps_unmarshal(union gamma_ramps* this, const void* buf, size_t ra * @param base The CLUT on top of which the new filter should be applied, * this can be the same pointer as `dest` */ -void apply(union gamma_ramps* dest, void* application, int depth, union gamma_ramps* base); +GCC_ONLY(__attribute__((nonnull))) +void apply(union gamma_ramps* restrict dest, void* restrict application, + int depth, union gamma_ramps* restrict base); @@ -27,7 +27,7 @@ * * @param this The ring buffer */ -void ring_initialise(struct ring* this) +void ring_initialise(struct ring* restrict this) { this->start = 0; this->end = 0; @@ -41,7 +41,7 @@ void ring_initialise(struct ring* this) * * @param this The ring buffer */ -void ring_destroy(struct ring* this) +void ring_destroy(struct ring* restrict this) { free(this->buffer); } @@ -63,7 +63,7 @@ void ring_destroy(struct ring* this) * is needed * @return The number of marshalled bytes */ -size_t ring_marshal(const struct ring* this, void* buf) +size_t ring_marshal(const struct ring* restrict this, void* restrict buf) { size_t off = 0, n = this->end - this->start; char* bs = buf; @@ -87,7 +87,7 @@ size_t ring_marshal(const struct ring* this, void* buf) * @param buf Buffer with the marshalled data * @return The number of unmarshalled bytes, 0 on error */ -size_t ring_unmarshal(struct ring* this, const void* buf) +size_t ring_unmarshal(struct ring* restrict this, const void* restrict buf) { size_t off = 0; const char* bs = buf; @@ -124,7 +124,7 @@ size_t ring_unmarshal(struct ring* this, const void* buf) * @param n The number of bytes in `data` * @return Zero on success, -1 on error */ -int ring_push(struct ring* this, void* data, size_t n) +int ring_push(struct ring* restrict this, void* restrict data, size_t n) { size_t used = 0; @@ -140,7 +140,7 @@ int ring_push(struct ring* this, void* data, size_t n) if (used + n > this->size) { - char* new = malloc(used + n); + char* restrict new = malloc(used + n); if (new == NULL) return -1; if (this->buffer) @@ -189,7 +189,7 @@ int ring_push(struct ring* this, void* data, size_t n) * @return The beginning of the queued data, * `NULL` if there is nothing more */ -void* ring_peek(struct ring* this, size_t* n) +void* ring_peek(struct ring* restrict this, size_t* restrict n) { if (this->buffer == NULL) return *n = 0, NULL; @@ -208,7 +208,7 @@ void* ring_peek(struct ring* this, size_t* n) * @param this The ring buffer * @param n The number of bytes to dequeue */ -void ring_pop(struct ring* this, size_t n) +void ring_pop(struct ring* restrict this, size_t n) { this->start += n; this->start %= this->size; @@ -19,6 +19,16 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * Ring buffer */ @@ -27,7 +37,7 @@ struct ring /** * Buffer for the data */ - char* buffer; + char* restrict buffer; /** * The first set byte in `.buffer` @@ -52,14 +62,16 @@ struct ring * * @param this The ring buffer */ -void ring_initialise(struct ring* this); +GCC_ONLY(__attribute__((nonnull))) +void ring_initialise(struct ring* restrict this); /** * Release resource allocated to a ring buffer * * @param this The ring buffer */ -void ring_destroy(struct ring* this); +GCC_ONLY(__attribute__((nonnull))) +void ring_destroy(struct ring* restrict this); /** * Marshal a ring buffer @@ -70,7 +82,8 @@ void ring_destroy(struct ring* this); * is needed * @return The number of marshalled bytes */ -size_t ring_marshal(const struct ring* this, void* buf); +GCC_ONLY(__attribute__((nonnull(1)))) +size_t ring_marshal(const struct ring* restrict this, void* restrict buf); /** * Unmarshal a ring buffer @@ -79,7 +92,8 @@ size_t ring_marshal(const struct ring* this, void* buf); * @param buf Buffer with the marshalled data * @return The number of unmarshalled bytes, 0 on error */ -size_t ring_unmarshal(struct ring* this, const void* buf); +GCC_ONLY(__attribute__((nonnull))) +size_t ring_unmarshal(struct ring* restrict this, const void* restrict buf); /** * Append data to a ring buffer @@ -89,7 +103,8 @@ size_t ring_unmarshal(struct ring* this, const void* buf); * @param n The number of bytes in `data` * @return Zero on success, -1 on error */ -int ring_push(struct ring* this, void* data, size_t n); +GCC_ONLY(__attribute__((nonnull(1)))) +int ring_push(struct ring* restrict this, void* restrict data, size_t n); /** * Get queued data from a ring buffer @@ -103,7 +118,8 @@ int ring_push(struct ring* this, void* data, size_t n); * @return The beginning of the queued data, * `NULL` if there is nothing more */ -void* ring_peek(struct ring* this, size_t* n); +GCC_ONLY(__attribute__((nonnull))) +void* ring_peek(struct ring* restrict this, size_t* restrict n); /** * Dequeue data from a ring bubber @@ -111,7 +127,8 @@ void* ring_peek(struct ring* this, size_t* n); * @param this The ring buffer * @param n The number of bytes to dequeue */ -void ring_pop(struct ring* this, size_t n); +GCC_ONLY(__attribute__((nonnull))) +void ring_pop(struct ring* restrict this, size_t n); /** * Check whether there is more data waiting @@ -120,7 +137,8 @@ void ring_pop(struct ring* this, size_t n); * @param this The ring buffer * @return 1 if there is more data, 0 otherwise */ -static inline int ring_have_more(struct ring* this) +GCC_ONLY(__attribute__((nonnull))) +static inline int ring_have_more(struct ring* restrict this) { return this->buffer != NULL; } diff --git a/src/server.c b/src/server.c index 9544bad..2705f4e 100644 --- a/src/server.c +++ b/src/server.c @@ -43,7 +43,7 @@ * Unused slots, with index less than `connections_used`, * should have the value -1 (negative) */ -int* connections = NULL; +int* restrict connections = NULL; /** * The number of elements allocated for `connections` @@ -63,18 +63,18 @@ size_t connections_used = 0; /** * The clients' connections' inbound-message buffers */ -struct message* inbound = NULL; +struct message* restrict inbound = NULL; /** * The clients' connections' outbound-message buffers */ -struct ring* outbound = NULL; +struct ring* restrict outbound = NULL; /** * The name of the process */ -extern char* argv0; +extern char* restrict argv0; /** * The server socket's file descriptor @@ -104,7 +104,7 @@ extern volatile sig_atomic_t connection; /** * Array of all outputs */ -extern struct output* outputs; +extern struct output* restrict outputs; /** * The nubmer of elements in `outputs` @@ -177,10 +177,10 @@ void server_destroy(int disconnect) * this buffer needs * @return The number of marshalled bytes */ -size_t server_marshal(void* buf) +size_t server_marshal(void* restrict buf) { size_t i, off = 0; - char* bs = buf; + char* restrict bs = buf; if (bs != NULL) *(size_t*)(bs + off) = connections_ptr; @@ -211,10 +211,10 @@ size_t server_marshal(void* buf) * @param buf Buffer for the marshalled data * @return The number of unmarshalled bytes, 0 on error */ -size_t server_unmarshal(const void* buf) +size_t server_unmarshal(const void* restrict buf) { size_t off = 0, i, n; - const char* bs = buf; + const char* restrict bs = buf; connections = NULL; inbound = NULL; @@ -265,7 +265,8 @@ size_t server_unmarshal(const void* buf) * @param fds The file descritor set * @return The highest set file descritor plus 1 */ -static int update_fdset(fd_set* fds) +GCC_ONLY(__attribute__((nonnull))) +static int update_fdset(fd_set* restrict fds) { int fdmax = socketfd; size_t i; @@ -403,9 +404,9 @@ static int connection_closed(int client) * as success (ECONNRESET cause 1 to be returned), * and are handled appropriately. */ -static int send_message(size_t conn, char* buf, size_t n) +static int send_message(size_t conn, char* restrict buf, size_t n) { - struct ring* ring = outbound + conn; + struct ring* restrict ring = outbound + conn; int fd = connections[conn]; int saved_errno; size_t ptr = 0; @@ -519,9 +520,10 @@ static inline int continue_send(size_t conn) * 0: Success (possibily delayed) * -1: An error occurred */ -static int (send_error)(size_t conn, const char* message_id, const char* desc) +GCC_ONLY(__attribute__((nonnull))) +static int (send_error)(size_t conn, const char* restrict message_id, const char* restrict desc) { - char* buf; + char* restrict buf; size_t n; MAKE_MESSAGE(&buf, &n, 0, @@ -558,9 +560,10 @@ static int (send_error)(size_t conn, const char* message_id, const char* desc) * 0: Success (possibily delayed) * -1: An error occurred */ -static int (send_errno)(size_t conn, const char* message_id, int number) +GCC_ONLY(__attribute__((nonnull))) +static int (send_errno)(size_t conn, const char* restrict message_id, int number) { - char* buf; + char* restrict buf; size_t n; MAKE_MESSAGE(&buf, &n, 0, @@ -582,10 +585,11 @@ static int (send_errno)(size_t conn, const char* message_id, int number) * @return Zero on success (even if ignored), -1 on error, * 1 if connection closed */ -static int enumerate_crtcs(size_t conn, char* message_id) +GCC_ONLY(__attribute__((nonnull))) +static int enumerate_crtcs(size_t conn, const char* restrict message_id) { size_t i, n = 0, len; - char* buf; + char* restrict buf; for (i = 0; i < outputs_n; i++) n += strlen(outputs[i].name) + 1; @@ -618,10 +622,11 @@ static int enumerate_crtcs(size_t conn, char* message_id) * @return Zero on success (even if ignored), -1 on error, * 1 if connection closed */ -static int get_gamma_info(size_t conn, char* message_id, char* crtc) +GCC_ONLY(__attribute__((nonnull(2)))) +static int get_gamma_info(size_t conn, const char* restrict message_id, const char* restrict crtc) { - struct output* output; - char* buf; + struct output* restrict output; + char* restrict buf; char depth[3]; const char* supported; size_t n; @@ -676,13 +681,15 @@ static int get_gamma_info(size_t conn, char* message_id, char* crtc) * @return Zero on success (even if ignored), -1 on error, * 1 if connection closed */ -static int get_gamma(size_t conn, char* message_id, char* crtc, char* coalesce, - char* high_priority, char* low_priority) +GCC_ONLY(__attribute__((nonnull(2)))) +static int get_gamma(size_t conn, const char* restrict message_id, const char* restrict crtc, + const char* restrict coalesce, const char* restrict high_priority, + const char* restrict low_priority) { - struct output* output; + struct output* restrict output; int64_t high, low; int coal; - char* buf; + char* restrict buf; size_t start, end, len, n, i; char depth[3]; char tables[sizeof("Tables: \n") + 3 * sizeof(size_t)]; @@ -806,13 +813,15 @@ static int get_gamma(size_t conn, char* message_id, char* crtc, char* coalesce, * @return Zero on success (even if ignored), -1 on error, * 1 if connection closed */ -static int set_gamma(size_t conn, char* message_id, char* crtc, char* priority, char* class, char* lifespan) +GCC_ONLY(__attribute__((nonnull(2)))) +static int set_gamma(size_t conn, const char* restrict message_id, const char* restrict crtc, + const char* restrict priority, const char* restrict class, const char* restrict lifespan) { - struct message* msg = inbound + conn; - struct output* output = NULL; + struct message* restrict msg = inbound + conn; + struct output* restrict output = NULL; struct filter filter; - char* p; - char* q; + char* restrict p; + char* restrict q; int saved_errno; ssize_t r; @@ -898,17 +907,17 @@ static int set_gamma(size_t conn, char* message_id, char* crtc, char* priority, */ static int handle_connection(size_t conn) { - struct message* msg = inbound + conn; + struct message* restrict msg = inbound + conn; int r, fd = connections[conn]; - char* command = NULL; - char* crtc = NULL; - char* coalesce = NULL; - char* high_priority = NULL; - char* low_priority = NULL; - char* priority = NULL; - char* class = NULL; - char* lifespan = NULL; - char* message_id = NULL; + const char* command = NULL; + const char* crtc = NULL; + const char* coalesce = NULL; + const char* high_priority = NULL; + const char* low_priority = NULL; + const char* priority = NULL; + const char* class = NULL; + const char* lifespan = NULL; + const char* message_id = NULL; size_t i; again: diff --git a/src/server.h b/src/server.h index 617b489..adf4c36 100644 --- a/src/server.h +++ b/src/server.h @@ -22,13 +22,23 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * List of all client's file descriptors * * Unused slots, with index less than `connections_used`, * should have the value -1 (negative) */ -extern int* connections; +extern int* restrict connections; /** * The number of elements allocated for `connections` @@ -48,12 +58,12 @@ extern size_t connections_used; /** * The clients' connections' inbound-message buffers */ -extern struct message* inbound; +extern struct message* restrict inbound; /** * The clients' connections' outbound-message buffers */ -extern struct ring* outbound; +extern struct ring* restrict outbound; @@ -72,7 +82,7 @@ void server_destroy(int disconnect); * this buffer needs * @return The number of marshalled bytes */ -size_t server_marshal(void* buf); +size_t server_marshal(void* restrict buf); /** * Unmarshal the state of the connections @@ -80,7 +90,7 @@ size_t server_marshal(void* buf); * @param buf Buffer for the marshalled data * @return The number of unmarshalled bytes, 0 on error */ -size_t server_unmarshal(const void* buf); +size_t server_unmarshal(const void* restrict buf); /** * The program's main loop @@ -34,7 +34,7 @@ * @return The duplicate of the memory segment, * `NULL` on error */ -void* memdup(const void* src, size_t n) +void* memdup(const void* restrict src, size_t n) { void* dest = malloc(n); if (dest == NULL) @@ -52,7 +52,7 @@ void* memdup(const void* src, size_t n) * @return The read content, plus a NUL byte at * the end (not counted in `*n`) */ -void* nread(int fd, size_t* n) +void* nread(int fd, size_t* restrict n) { size_t size = 32; ssize_t got; @@ -113,9 +113,9 @@ void* nread(int fd, size_t* n) * @return The number of written bytes, less than `n` * on error, cannot exceed `n` */ -size_t nwrite(int fd, const void* buf, size_t n) +size_t nwrite(int fd, const void* restrict buf, size_t n) { - const char* bs = buf; + const char* restrict bs = buf; ssize_t wrote; size_t ptr = 0; @@ -189,6 +189,7 @@ void msleep(int ms) nanosleep(&ts, NULL); } + /** * Check whether a NUL-terminated string is encoded in UTF-8 * @@ -196,7 +197,7 @@ void msleep(int ms) * @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL * @return Zero if good, -1 on encoding error */ -int verify_utf8(const char* string, int allow_modified_nul) +int verify_utf8(const char* restrict string, int allow_modified_nul) { static long BYTES_TO_MIN_BITS[] = {0, 0, 8, 12, 17, 22, 37}; static long BYTES_TO_MAX_BITS[] = {0, 7, 11, 16, 21, 26, 31}; @@ -19,6 +19,16 @@ +#ifndef GCC_ONLY +# if defined(__GNUC__) && !defined(__clang__) +# define GCC_ONLY(...) __VA_ARGS__ +# else +# define GCC_ONLY(...) /* nothing */ +# endif +#endif + + + /** * Duplicate a memory segment * @@ -27,8 +37,8 @@ * @return The duplicate of the memory segment, * `NULL` on error */ -void* memdup(const void* src, size_t n); - +GCC_ONLY(__attribute__((malloc, nonnull))) +void* memdup(const void* restrict src, size_t n); /** * Read an entire file @@ -40,8 +50,8 @@ void* memdup(const void* src, size_t n); * @return The read content, plus a NUL byte at * the end (not counted in `*n`) */ -void* nread(int fd, size_t* n); - +GCC_ONLY(__attribute__((malloc))) +void* nread(int fd, size_t* restrict n); /** * Write an entire buffer to a file @@ -54,8 +64,7 @@ void* nread(int fd, size_t* n); * @return The number of written bytes, less than `n` * on error, cannot exceed `n` */ -size_t nwrite(int fd, const void* buf, size_t n); - +size_t nwrite(int fd, const void* restrict buf, size_t n); /** * Duplicate a file descriptor an make sure @@ -68,7 +77,6 @@ size_t nwrite(int fd, const void* buf, size_t n); */ int dup2atleast(int fd, int atleast); - /** * Perform a timed suspention of the process. * The process resumes when the timer expires, @@ -79,7 +87,6 @@ int dup2atleast(int fd, int atleast); */ void msleep(int ms); - /** * Check whether a NUL-terminated string is encoded in UTF-8 * @@ -87,8 +94,6 @@ void msleep(int ms); * @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL * @return Zero if good, -1 on encoding error */ -#if defined(__GNUC__) -__attribute__((pure)) -#endif -int verify_utf8(const char* string, int allow_modified_nul); +GCC_ONLY(__attribute__((pure, nonnull))) +int verify_utf8(const char* restrict string, int allow_modified_nul); |