more function attribute updates
This commit is contained in:
57
buffer.h
57
buffer.h
@@ -15,17 +15,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* dietlibc defines these in sys/cdefs.h, which is included from stddef.h */
|
||||
#ifndef __writememsz__
|
||||
#define __writememsz__(a,b)
|
||||
#endif
|
||||
#ifndef __readmemsz__
|
||||
#define __readmemsz__(a,b)
|
||||
#endif
|
||||
#ifndef __readmem__
|
||||
#define __readmem__(a)
|
||||
#endif
|
||||
|
||||
typedef struct buffer {
|
||||
char *x; /* actual buffer space */
|
||||
size_t p; /* current position */
|
||||
@@ -45,22 +34,22 @@ typedef struct buffer {
|
||||
|
||||
/* Initialize a buffer with an existing memory area, which the buffer
|
||||
* will NOT take ownership of (i.e. won't free the memory when it's done) */
|
||||
att_writen(4,5)
|
||||
__bufout(4,5)
|
||||
void buffer_init(buffer* b, ssize_t (*op)(), int fd, char* y, size_t ylen);
|
||||
|
||||
/* Initialize a buffer with an existing memory area, which the buffer
|
||||
* WILL take ownership of (it will call free() on it when it's done) */
|
||||
att_writen(4,5)
|
||||
__bufout(4,5)
|
||||
void buffer_init_free(buffer* b,ssize_t (*op)(),int fd,char* y,size_t ylen);
|
||||
|
||||
/* Call buffer_init with op=read(), return 0.
|
||||
* If fd==-1, return -1 instead, leaving b untouched. */
|
||||
att_writen(3,4)
|
||||
__bufout(3,4)
|
||||
int buffer_init_read(buffer* b, int fd, char* y, size_t ylen);
|
||||
|
||||
/* Call buffer_init with op=write(), return 0.
|
||||
* If fd==-1, return -1 instead, leaving b untouched. */
|
||||
att_writen(3,4)
|
||||
__bufout(3,4)
|
||||
int buffer_init_write(buffer* b, int fd, char* y, size_t ylen);
|
||||
|
||||
/* Will allocate a buffer of size ylen and then call
|
||||
@@ -83,12 +72,12 @@ int buffer_init_write_allocbuf(buffer* b, int fd, size_t ylen);
|
||||
* that memory area. If it reaches the end, it will signal EOF and never
|
||||
* actually attempt to read from any actual file.
|
||||
* Does not take ownership. Useful for testing. */
|
||||
att_readn(2,3)
|
||||
__bufin(2,3)
|
||||
void buffer_init_staticcontents(buffer* b,char* y,size_t ylen);
|
||||
|
||||
/* Same but the buffer takes ownership of the static buffer and frees it
|
||||
* in buffer_close. */
|
||||
att_readn(2,3)
|
||||
__bufin(2,3)
|
||||
void buffer_init_staticcontents_free(buffer* b,char* y,size_t ylen);
|
||||
|
||||
|
||||
@@ -102,7 +91,7 @@ void buffer_munmap(void* buf);
|
||||
|
||||
/* Initialize a buffer so it will read from this file by memory mapping
|
||||
* the whole thing. */
|
||||
att_read(2)
|
||||
__strin(2)
|
||||
int buffer_mmapread(buffer* b,const char* filename);
|
||||
|
||||
/* Indicate you are done with a buffer.
|
||||
@@ -115,22 +104,22 @@ void buffer_close(buffer* b);
|
||||
* the data in the buffer. */
|
||||
int buffer_flush(buffer* b);
|
||||
|
||||
att_readn(2,3)
|
||||
__bufin(2,3)
|
||||
int buffer_put(buffer* b,const char* x,size_t len);
|
||||
|
||||
att_readn(2,3)
|
||||
__bufin(2,3)
|
||||
int buffer_putalign(buffer* b,const char* x,size_t len);
|
||||
|
||||
att_readn(2,3)
|
||||
__bufin(2,3)
|
||||
int buffer_putflush(buffer* b,const char* x,size_t len);
|
||||
|
||||
att_read(2)
|
||||
__strin(2)
|
||||
int buffer_puts(buffer* b,const char* x);
|
||||
|
||||
att_read(2)
|
||||
__strin(2)
|
||||
int buffer_putsalign(buffer* b,const char* x);
|
||||
|
||||
att_read(2)
|
||||
__strin(2)
|
||||
int buffer_putsflush(buffer* b,const char* x);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__LIBOWFAT_INTERNAL)
|
||||
@@ -155,22 +144,24 @@ int buffer_putnlflush(buffer* b); /* put \n and flush */
|
||||
: buffer_put((s),&(c),1) \
|
||||
)
|
||||
|
||||
att_writen(2,3)
|
||||
__bufout(2,3)
|
||||
ssize_t buffer_get(buffer* b,char* x,size_t len);
|
||||
ssize_t buffer_feed(buffer* b);
|
||||
att_write(2) att_nonnull(2)
|
||||
ssize_t buffer_getc(buffer* b,char* x);
|
||||
att_write(2) att_nonnull(2)
|
||||
ssize_t buffer_peekc(buffer* b,char* x);
|
||||
att_writen(2,3)
|
||||
__bufout(2,3)
|
||||
ssize_t buffer_getn(buffer* b,char* x,size_t len);
|
||||
|
||||
/* read bytes until the destination buffer is full (len bytes), end of
|
||||
* file is reached or the read char is in charset (setlen bytes). An
|
||||
* empty line when looking for \n will write '\n' to x and return 0. If
|
||||
* EOF is reached, \0 is written to the buffer */
|
||||
att_writen(2,3)
|
||||
att_readn(4,5)
|
||||
__bufout(2,3)
|
||||
__bufin(4,5)
|
||||
ssize_t buffer_get_token(buffer* b,char* x,size_t len,const char* charset,size_t setlen);
|
||||
att_writen(2,3)
|
||||
__bufout(2,3)
|
||||
ssize_t buffer_getline(buffer* b,char* x,size_t len);
|
||||
|
||||
/* this predicate is given the string as currently read from the buffer
|
||||
@@ -178,7 +169,7 @@ ssize_t buffer_getline(buffer* b,char* x,size_t len);
|
||||
typedef int (*string_predicate)(const char* x,size_t len);
|
||||
|
||||
/* like buffer_get_token but the token ends when your predicate says so */
|
||||
att_writen(2,3)
|
||||
__bufout(2,3)
|
||||
ssize_t buffer_get_token_pred(buffer* b,char* x,size_t len,string_predicate p);
|
||||
|
||||
char *buffer_peek(buffer* b);
|
||||
@@ -228,13 +219,13 @@ int buffer_putsaflush(buffer* b,const stralloc* sa);
|
||||
* data is available. */
|
||||
|
||||
/* read token from buffer to stralloc */
|
||||
att_readn(3,4)
|
||||
__bufin(3,4)
|
||||
int buffer_get_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen);
|
||||
/* read line from buffer to stralloc */
|
||||
int buffer_getline_sa(buffer* b,stralloc* sa);
|
||||
|
||||
/* same as buffer_get_token_sa but empty sa first */
|
||||
att_readn(3,4)
|
||||
__bufin(3,4)
|
||||
int buffer_get_new_token_sa(buffer* b,stralloc* sa,const char* charset,size_t setlen);
|
||||
/* same as buffer_getline_sa but empty sa first */
|
||||
int buffer_getnewline_sa(buffer* b,stralloc* sa);
|
||||
@@ -252,7 +243,7 @@ void buffer_fromsa(buffer* b,const stralloc* sa); /* read from sa */
|
||||
int buffer_tosa(buffer*b,stralloc* sa); /* write to sa, auto-growing it */
|
||||
#endif
|
||||
|
||||
att_readn(2,3)
|
||||
__bufin(2,3)
|
||||
void buffer_frombuf(buffer* b,const char* x,size_t l); /* buffer reads from static buffer */
|
||||
|
||||
#ifdef ARRAY_H
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
#include <errno.h>
|
||||
#include "array.h"
|
||||
#include "buffer.h"
|
||||
|
||||
static ssize_t fail() {
|
||||
errno=EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void buffer_fromarray(buffer* b,array* a) {
|
||||
if (array_failed(a))
|
||||
buffer_frombuf(b,NULL,0);
|
||||
else
|
||||
if (array_failed(a)) {
|
||||
memset(b,0,sizeof *b);
|
||||
b->op=fail;
|
||||
} else
|
||||
buffer_frombuf(b,array_start(a),a->initialized);
|
||||
}
|
||||
|
||||
16
case.h
16
case.h
@@ -10,29 +10,23 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* turn upper case letters to lower case letters, ASCIIZ */
|
||||
att_mangle(1)
|
||||
__strinout(1)
|
||||
void case_lowers(char *s);
|
||||
|
||||
/* turn upper case letters to lower case letters, binary */
|
||||
att_manglen(1,2)
|
||||
__strninout(1,2)
|
||||
void case_lowerb(void *buf,size_t len);
|
||||
|
||||
/* like str_diff, ignoring case */
|
||||
att_pure
|
||||
att_read(1)
|
||||
att_read(2)
|
||||
att_pure __strin(1) __strin(2)
|
||||
int case_diffs(const char *,const char *);
|
||||
|
||||
/* like byte_diff, ignoring case */
|
||||
att_pure
|
||||
att_readn(1,2)
|
||||
att_readn(3,2)
|
||||
att_pure __strnin(1,2) __strnin(3,2)
|
||||
int case_diffb(const void *,size_t ,const void *);
|
||||
|
||||
/* like str_start, ignoring case */
|
||||
att_pure
|
||||
att_read(1)
|
||||
att_read(2)
|
||||
att_pure __strin(1) __strin(2)
|
||||
int case_starts(const char *,const char *);
|
||||
|
||||
#define case_equals(s,t) (!case_diffs((s),(t)))
|
||||
|
||||
98
compiler.h
98
compiler.h
@@ -1,7 +1,7 @@
|
||||
#ifndef LIBOWFAT_ATTRIBUTES_H
|
||||
#define LIBOWFAT_ATTRIBUTES_H
|
||||
|
||||
|
||||
// This is here so you can use inline with older gcc versions
|
||||
#if __GNUC__ && (__STDC_VERSION__ < 199901L)
|
||||
#define inline __inline__
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#define __extension__
|
||||
#endif
|
||||
|
||||
// This is here so we can put noexcept on function declarations in headers
|
||||
#ifndef __cplusplus
|
||||
#define noexcept
|
||||
#endif
|
||||
@@ -24,6 +25,9 @@
|
||||
#define restrict
|
||||
#endif
|
||||
|
||||
// Use this to tell the compiler something is likely to be true or false
|
||||
// The compiler can use that to give hints to the CPU and group error
|
||||
// handling code to "cold" pages that never get paged in by the OS
|
||||
#if GCC_VERSION_ATLEAST(3,0)
|
||||
#define likely(a) __builtin_expect((a), 1)
|
||||
#define unlikely(a) __builtin_expect((a), 0)
|
||||
@@ -32,30 +36,49 @@
|
||||
#define unlikely(a) (a)
|
||||
#endif
|
||||
|
||||
// Function attribute for functions like abs() that depend only on the
|
||||
// arguments and does not access any other memory in the program. The
|
||||
// compiler can then optimize multiple calls on the same value into just
|
||||
// one call.
|
||||
#if GCC_VERSION_ATLEAST(2, 5)
|
||||
#define att_const __attribute__((__const__))
|
||||
#else
|
||||
#define att_const
|
||||
#endif
|
||||
|
||||
// Function attribute. Tells the compiler the function has no effect on
|
||||
// the state of the program except for the return value, but unlike
|
||||
// att_const the function can read other global state in the program,
|
||||
// like the memory pointer arguments point to.
|
||||
#if GCC_VERSION_ATLEAST(2, 96)
|
||||
#define att_pure __attribute__((__pure__))
|
||||
#else
|
||||
#define att_pure
|
||||
#endif
|
||||
|
||||
// Function attribute for functions that return freshly allocated
|
||||
// memory. The compiler then knows the pointer does not alias with other
|
||||
// pointers, which enables several optimizations.
|
||||
#if GCC_VERSION_ATLEAST(3, 0)
|
||||
#define att_malloc __attribute__((__malloc__))
|
||||
#else
|
||||
#define att_malloc
|
||||
#endif
|
||||
|
||||
// Function attribute for functions that return an important value, like
|
||||
// an error code, where it would be a security issue not to check the
|
||||
// return value, for example link or rename. The compiler will then warn
|
||||
// if the caller ignores the return value.
|
||||
#if GCC_VERSION_ATLEAST(3, 4)
|
||||
#define att_warn_unused_result __attribute__((__warn_unused_result__))
|
||||
#else
|
||||
#define att_warn_unused_result
|
||||
#endif
|
||||
|
||||
// Function attributes. The compiler will put hot and cold functions
|
||||
// adjacent in memory. If you mark error handling functions as
|
||||
// cold, the compiler can arrange the binary so the operating system
|
||||
// never reads those pages into main memory from disk.
|
||||
#if GCC_VERSION_ATLEAST(4, 3)
|
||||
#define att_hot __attribute__((__hot__))
|
||||
#define att_cold __attribute__((__cold__))
|
||||
@@ -64,6 +87,13 @@
|
||||
#define att_cold
|
||||
#endif
|
||||
|
||||
// Function attributes. att_alloc tells the compiler that the compiler
|
||||
// returns a buffer of the size given in the function argument x
|
||||
// (as an index, counted left to right, starting at 1). att_calloc says
|
||||
// the buffer size is a*b (both again as an function argument index,
|
||||
// counted from left to right, starting at 1)
|
||||
// If we tell the compiler the buffer size, it can detect if we access
|
||||
// values outside the buffer area.
|
||||
#if GCC_VERSION_ATLEAST(4, 3)
|
||||
#define att_alloc(x) __attribute__((alloc_size(x)))
|
||||
#define att_calloc(x,y) __attribute__((alloc_size(x,y)))
|
||||
@@ -72,6 +102,13 @@
|
||||
#define att_calloc
|
||||
#endif
|
||||
|
||||
// Function attributes.
|
||||
// att_read(1) says the function reads from the first function argument.
|
||||
// att_readn(1,2) is like att_read but the buffer size is given as the second argument.
|
||||
// att_write(1) says the function writes to the first function argument.
|
||||
// att_writen(1) is like att_write but the buffer size is given as the second argument.
|
||||
// att_mangle(1) says the function read/writes to the first function argument.
|
||||
// att_manglen(1) is like att_mangle but the buffer size is given as the second argument.
|
||||
#if GCC_VERSION_ATLEAST(10, 0)
|
||||
#define att_read(argno_ptr) __attribute__((access(read_only, argno_ptr)))
|
||||
#define att_readn(argno_ptr, argno_size) __attribute__((access(read_only, argno_ptr, argno_size)))
|
||||
@@ -88,18 +125,24 @@
|
||||
#define att_manglen(argno_ptr, argno_size)
|
||||
#endif
|
||||
|
||||
// Function attribute. The compiler will warn if you call this function.
|
||||
#if GCC_VERSION_ATLEAST(3, 2)
|
||||
#define att_dontuse __attribute__((__deprecated__))
|
||||
#else
|
||||
#define att_dontuse
|
||||
#endif
|
||||
|
||||
// Function attribute. Tells the compiler that the param's function
|
||||
// argument can not be NULL (given as index of function arguments,
|
||||
// counted left to right from 1)
|
||||
#if GCC_VERSION_ATLEAST(3, 3)
|
||||
#define att_nonnull(params) __attribute__((__nonnull__(params)))
|
||||
#else
|
||||
#define att_nonnull(params)
|
||||
#endif
|
||||
|
||||
// Function attribute. Makes the compiler emit a warning or an error,
|
||||
// abort compilation on error.
|
||||
#if GCC_VERSION_ATLEAST(4, 3)
|
||||
#define att_warn(message) __attribute__((__warning__(message)))
|
||||
#define att_error(message) __attribute__((__warning__(message)))
|
||||
@@ -108,8 +151,61 @@
|
||||
#define att_error(message)
|
||||
#endif
|
||||
|
||||
// __builtin_constant_p is a GCC extension used in macros to handle
|
||||
// cases differently where a macro argument is a constant
|
||||
#ifndef __GNUC__
|
||||
#define __builtin_constant_p(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if __has_attribute(null_terminated_string_arg)
|
||||
// Function arguments.
|
||||
// __strin: Argument idx (counted left to right from 1) is a non-NULL string the function reads
|
||||
#define __strin(idx) __attribute__((nonnull(idx),access(read_only,idx),null_terminated_string_arg(idx)))
|
||||
// __strnin: Argument idx (counted left to right from 1) is a non-NULL string the function reads, length limit in array elements given in the szidx'th argument
|
||||
#define __strnin(idx,szidx) __attribute__((nonnull(idx),access(read_only,idx,szidx),null_terminated_string_arg(idx)))
|
||||
// __bufin: Argument idx (counted left to right from 1) is a non-NULL buffer the function reads from, length limit in array elements given in the szidx'th argument
|
||||
#define __bufin(bufidx,szidx) __attribute__((nonnull(bufidx),access(read_only,bufidx,szidx)))
|
||||
// __strout: Argument idx (counted left to right from 1) is a non-NULL string the function writes
|
||||
// Currently we can't tell the compiler that the output will be 0-terminated.
|
||||
#define __strout(idx) __attribute__((nonnull(idx),access(write_only,idx)))
|
||||
// __strnout: Argument idx (counted left to right from 1) is a non-NULL string the function writes, buffer size given in szidx'th function argument (in array elements, not necessarily bytes)
|
||||
// Currently we can't tell the compiler that the output will be 0-terminated.
|
||||
#define __strnout(idx,szidx) __attribute__((nonnull(idx),access(write_only,idx,szidx)))
|
||||
// __bufout: Argument idx (counted left to right from 1) is a non-NULL buffer the function writes, buffer size given in szidx'th function argument (in array elements, not necessarily bytes)
|
||||
#define __bufout(bufidx,szidx) __attribute__((nonnull(bufidx),access(write_only,bufidx,szidx)))
|
||||
// __strinout: Argument idx (counted left to right from 1) is a non-NULL string the function reads and writes
|
||||
// Currently we can't tell the compiler that the output will be 0-terminated.
|
||||
#define __strinout(idx) __attribute__((nonnull(idx),access(read_write,idx),null_terminated_string_arg(idx)))
|
||||
// __strninout: Argument idx (counted left to right from 1) is a non-NULL string the function reads and writes, buffer size in szidx'th function argument (in array elements, not necessarily bytes)
|
||||
// Currently we can't tell the compiler that the output will be 0-terminated.
|
||||
#define __strninout(idx,szidx) __attribute__((nonnull(idx),access(read_write,idx,szidx),null_terminated_string_arg(idx)))
|
||||
// __bufinout: Argument idx (counted left to right from 1) is a non-NULL buffer the function reads and writes, buffer size in szidx'th function argument (in array elements, not necessarily bytes)
|
||||
#define __bufinout(bufidx,szidx) __attribute__((nonnull(bufidx),access(read_write,bufidx,szidx)))
|
||||
#elif GCC_VERSION_ATLEAST(10, 0)
|
||||
#define __strin(idx) __attribute__((nonnull(idx),access(read_only,idx)))
|
||||
#define __strnin(idx,szidx) __attribute__((nonnull(idx),access(read_only,idx,szidx)))
|
||||
#define __bufin(bufidx,szidx) __attribute__((nonnull(bufidx),access(read_only,bufidx,szidx)))
|
||||
#define __strout(idx) __attribute__((nonnull(idx),access(write_only,idx)))
|
||||
#define __strnout(idx,szidx) __attribute__((nonnull(idx),access(write_only,idx,szidx)))
|
||||
#define __bufout(bufidx,szidx) __attribute__((nonnull(bufidx),access(write_only,bufidx,szidx)))
|
||||
#define __strinout(idx) __attribute__((nonnull(idx),access(read_write,idx)))
|
||||
#define __strninout(idx,szidx) __attribute__((nonnull(idx),access(read_write,idx,szidx)))
|
||||
#define __bufinout(bufidx,szidx) __attribute__((nonnull(bufidx),access(read_write,bufidx,szidx)))
|
||||
|
||||
#elif GCC_VERSION_ATLEAST(3, 3)
|
||||
|
||||
#define __strin(idx) __attribute__((nonnull(idx)))
|
||||
#define __strnin(idx,szidx) __attribute__((nonnull(idx)))
|
||||
#define __bufin(bufidx,szidx) __attribute__((nonnull(bufidx)))
|
||||
#define __strout(idx) __attribute__((nonnull(idx)))
|
||||
#define __strnout(idx,szidx) __attribute__((nonnull(idx)))
|
||||
#define __bufout(bufidx,szidx) __attribute__((nonnull(bufidx)))
|
||||
#define __strinout(idx) __attribute__((nonnull(idx)))
|
||||
#define __strninout(idx,szidx) __attribute__((nonnull(idx)))
|
||||
#define __bufinout(bufidx,szidx) __attribute__((nonnull(bufidx)))
|
||||
|
||||
#endif
|
||||
#endif // !defined(__GNUC__)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user