summaryrefslogblamecommitdiffstats
path: root/libsyscalls.h
blob: df4de6904b64a0444e49cd0c1a7066a066e68eb8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                                         



                                                                                
   













                                                                                                              

                                                                        


















                                                                               

                                  
                               








                                                                  
                              









                                                                    

                                   







                                          

                                 

                                                         
                                  

                                     
                              

                                   

  












                                                           








                                                                                                      








                                                                                                        

                                                            

                                                          


                                                                         

                                                               
                                                                








                                                                 




















































                                                                                                             
                                                                            



                                                                          
                                                                           





                                                                          
                                                                    
                                                                     
                                                                       
                                                                        
                                                                               



























                                                                                
                                                                        












                                                                           
                                                                   






                                                                   

                                                                     










                                                                   


                                                                                                                                   








                                                   
                                                                      



















                                                                                             


                                       
                                   




                                                       
                                        












                                                              
                                        
 










                                                                                                                 

  












                                                                   
                                                          



















                                                             
                                                      








                                                             
                                                      










                                                             
                                                    













                                                                  
                                                       







                                                            


                                                   



                                                      
                                          

























                                                                
                                                  












                                                                
                                                   






























                                                                           
                                      






                                                          
                                      



                                                                
                                           









                                                                      
                                                                 



                                                                       


                                                                










                                                               
                                                 





                                                              
                                           






                                                                
                                             



















                                                                 
                                           







                                                              
                                             









                                                             
                                                     






















                                                            
                                                 








                                                           
                                             















                                                           
                                            

























                                                         
                                               











                                                          
                                              










                                                        


                                           






                                                           
                                                       






                                                      
                                                 







                                                      
                                                   




















                                                            
                                                             




































                                                          
                                                 


























                                                            
                                                           










                                                            
                                                           










                                                            
                                                                   














                                                                   
                                                                  







                                                            
                                                   







                                                      
                                                   








                                                           
                                                        




















                                                            

  






                                              
                                                






                                                         
                                          








                                                          
                                               





















                                                           
                                                









                                                            
                                                        







                                                      
                                           







                                                    
                                          







                                                         
                                           







                                                        
                                            








                                                         

  





                                                         
                                              






                                                         


                                            


                                                       
                                           








                                                            
                                           








                                                          
                                    








                                                          
                                    







                                                          
                                           







                                                          
                                               




                                                       
                                               




                                                       
                                      











                                                         
                                                    







                                                       
                                                    






                                                          
                                           










                                                          
                                                         







                                                          
                                                         






                                                          
                                                












                                                           
                                               









                                                           
                                               









                                                          


                                     


                                                  
                                              













                                                         
                                         






                                                       


                                       



                                                 
                                             













                                                            
                                           












                                                        
                                        




                                                    
                                         









                                                             
                                                  







                                                     
                                       







                                                       
                                         

















                                                       

  



                                           
                                             





                                                          
                                       










                                                           
                                         











                                                           
                                           









                                                          
                                           











                                                          
                                       










                                                          
                                         









                                                        


                                             


                                             
                                                 


















                                                           
                                          









                                                            
                                          



















                                                          


                                                










                                                                     
                                       










                                                                                                                                    





















                                                             
                                 









                                                           
                               
















































                                                             

                                                                             

           
                                                                            










                                                                        

                                                                   

































































































































                                                                                     


                                                                                              























                                                               

                                                                                             



















































                                                                         

                                                     

















































                                                                   

                                                          
           




                                                          





                                                 


                                                       



                                  

                                                          
           


                                                        




                                   

                                                


                                   

                                                     









                                                           
           


                                                             




                                                             




































































































                                                                       
           


                                                                




                                                             
























































                                                                          





                                                             
           



                                                                





                                                     

















































                                                                                                        




























                                                                      

                                                                    
                                                                   



                                                                  





                                                                      
                                                                       





                                        


                                                                       







                                                             
                                                                        









                                                                      



                                                                         



























                                                                     

                                                                           





                                             
                                                                              



                                                                 
                                                            



                                                           
                                                       

           


                                                               










                                                               


                                                             
          









                                                             


                                                          

                                    

           





                                                       
           

                                                                      

                                                  

                                             

                                                                        

                                             

                                                                        
      





                                                     

                                                                                       

  













































                                                           












































                                                            


















                                                           









                                                          






                                                                                                          























                                                                      






























                                                                   





                                            












                                                                         




                                                                       
                                                                    










































                                                                                                          

                                                                    







                                                                                    




                                              

                                                      


                                                                                   

                                                   









                                                                      

                                                                   



                                          












                                                                                  
   



                                                          



                                                                         


                                                          
                      


                                                                                 



                                       















                                                                                            



                                                          
   

                                                          
                      



                                                                           









                                                            
















                                                                                           



                                                                
   


                                                          
                      



                                                                                  









                                                         
















                                                                                             



                                                                
   


                                                          
                      





































































                                                                                              





                                                             




















                                                                                          
   


                                                                
                      





                                                                                         

   






                                                              
   

















                                                                                       




                                                       

                                                          
                      



                                                                                               
 













                                                                    




















                                                                                    




                                                              

                                                          
                      


                                                                                     
 





                                                             











                                                                                   
   

                                                          
                      



                                                                                                    






                                                             









                                                                                   


                                                          



                                                                                             









                                                    









                                                                                   


                                                          



                                                                         






                                                    









                                                                                   


                                                          



                                                                       



                                                                   








                                                                           
   



                                                          
                      



                                                                                 



                                                                   










                                                                        
   


                                                          
                      



                                                                                 








                                                                        























                                                                                        





                                                       


                                                            
                      



                                                                                               

      

                                                  


                                     
/* See LICENSE file for copyright and license details. */
#ifndef LIBSYSCALLS_H
#define LIBSYSCALLS_H

#include "libsyscalls/internal-begin.h"
#include "libsyscalls/short-enums.h"
#include "libsyscalls/advanced.h"


/**
 * Macro for enumerating libsyscall error numbers
 * 
 * The numbers are stored in `libsyscalls_error`
 * 
 * @param  X:macro(NAME, STR)  Macro that expands, will be given two arguments:
 *                             the enum value name of the error (identifier),
 *                             and the description of the error (string literal)
 * @param  D:code              Macro that expands between each expansion of X
 * 
 * The primary purpose of the existance of this macro
 * is to ease implementation of the library; it will
 * probably not disappear (no promises)
 */
#define LIBSYSCALLS_LIST_ERRORS(X, D)\
	X(LIBSYSCALLS_E_OK, "Success") D\
	X(LIBSYSCALLS_E_OSNOSUP, "Operating system not supported") D\
	X(LIBSYSCALLS_E_ARCHNOSUP, "Architecture not supported for selected operating system") D\
	X(LIBSYSCALLS_E_NOSUCHSYSCALL, "No such system call") D\
	X(LIBSYSCALLS_E_NOERRORS, "There is no error listing for selected operating system") D\
	X(LIBSYSCALLS_E_NOSIGNALS, "There is no signal listing for selected operating system") D\
	X(LIBSYSCALLS_E_NOMEM, "Failed to allocate required memory") D\
	X(LIBSYSCALLS_E_INVAL, "Invalid arguments passed to function") D\
	X(LIBSYSCALLS_E_NOSUCHTYPE, "Type does not exist on the selected operating system or architecture") D\
	X(LIBSYSCALLS_E_ISSTRUCT, "Type is a structure or union") D\
	X(LIBSYSCALLS_E_ISNOTSTRUCT, "Type is not a structure or union")

/**
 * libsyscall error numbers
 */
enum libsyscalls_error {
	LIBSYSCALLS_LIST_ERRORS(LIBSYSCALLS_LIST_ERRORS_X_, LIBSYSCALLS_COMMA_)
};

/**
 * Operating systems
 */
enum libsyscalls_os {
	LIBSYSCALLS_OS_LINUX
};

/**
 * Architectures
 */
enum libsyscalls_arch {
	LIBSYSCALLS_ARCH_ALPHA_LE,
	LIBSYSCALLS_ARCH_ALPHA_BE,
	LIBSYSCALLS_ARCH_AMD64,
	LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI on 64-bit ISA */
	LIBSYSCALLS_ARCH_ARM_OABI_LE,
	LIBSYSCALLS_ARCH_ARM_OABI_BE,
	LIBSYSCALLS_ARCH_ARM_EABI_LE,
	LIBSYSCALLS_ARCH_ARM_EABI_BE,
	LIBSYSCALLS_ARCH_IA64_LE, /* 64-bit pointers */
	LIBSYSCALLS_ARCH_IA64_BE, /* 64-bit pointers */
	LIBSYSCALLS_ARCH_IA64_P32_LE, /* 32-bit pointers */
	LIBSYSCALLS_ARCH_IA64_P32_BE, /* 32-bit pointers */
	LIBSYSCALLS_ARCH_M68K,
	LIBSYSCALLS_ARCH_MICROBLAZE_32_LE,
	LIBSYSCALLS_ARCH_MICROBLAZE_32_BE,
	LIBSYSCALLS_ARCH_MICROBLAZE_64_LE,
	LIBSYSCALLS_ARCH_MICROBLAZE_64_BE,
	LIBSYSCALLS_ARCH_MIPS_O32_LE,
	LIBSYSCALLS_ARCH_MIPS_O32_BE,
	LIBSYSCALLS_ARCH_MIPS_N32_LE, /* 32-bit ABI on 64-bit ISA */
	LIBSYSCALLS_ARCH_MIPS_N32_BE, /* 32-bit ABI on 64-bit ISA */
	LIBSYSCALLS_ARCH_MIPS_N64_LE,
	LIBSYSCALLS_ARCH_MIPS_N64_BE,
	LIBSYSCALLS_ARCH_PARISC_32,
	LIBSYSCALLS_ARCH_PARISC_64,
	LIBSYSCALLS_ARCH_POWERPC_32_LE,
	LIBSYSCALLS_ARCH_POWERPC_32_BE,
	LIBSYSCALLS_ARCH_POWERPC_64_LE,
	LIBSYSCALLS_ARCH_POWERPC_64_BE,
	LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE,
	LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE,
	LIBSYSCALLS_ARCH_POWERPC_SPU_LE,
	LIBSYSCALLS_ARCH_POWERPC_SPU_BE,
	LIBSYSCALLS_ARCH_S390_32,
	LIBSYSCALLS_ARCH_S390_64,
	LIBSYSCALLS_ARCH_SH_LE, /* does not cover SH-5 */
	LIBSYSCALLS_ARCH_SH_BE, /* does not cover SH-5 */
	LIBSYSCALLS_ARCH_SPARC_32,
	LIBSYSCALLS_ARCH_SPARC_64_LE,
	LIBSYSCALLS_ARCH_SPARC_64_BE,
	LIBSYSCALLS_ARCH_I386,
	LIBSYSCALLS_ARCH_XTENSA_LE,
	LIBSYSCALLS_ARCH_XTENSA_BE
};

/**
 * Data types
 * 
 * Be aware that some values in this enumeration may have
 * multiple names, especially structs and unions: up to
 * one name per combination of operating system and
 * architecture. Each value may have very different
 * meaning per name. This may be done because the number
 * of available values is limited. Also note that functions
 * may return values that do not have a name at all, these
 * are anonymous structs and unions whose definitions also
 * depend on the operating system and architecture.
 */
enum libsyscalls_datatype {

	/* Type renaming, these macros will be undefined later */
#define LIBSYSCALLS_TYPE_CHAR_ARRAY              LIBSYSCALLS_TYPE_BUFFER
#define LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL

	/* You can use these macros classify and convert data types */
#define LIBSYSCALLS_TYPEBITSMASK                0xF000
#define LIBSYSCALLS_TYPEBITS_SCALAR             0x0000 /* predefined total width, even if aggregate */
#define LIBSYSCALLS_TYPEBITS_ARRAY              0x1000 /* count is stored in next parameter, and is
                                                        * updated with fill or returned if no outputable
                                                        * to the next parameter */
#define LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL 0x2000 /* count is stored in next parameter, fill is
                                                        * in no way returned, this chould either be
                                                        * because the array is always (unless an error
                                                        * is returned) entirely filled or because the
                                                        * end is inferred from the contents (e.g. null
                                                        * byte termination) */

#define LIBSYSCALLS_LIST_SPECIAL_TYPES(X, SUFFIX, D, FIRST)\
	/* the type used in the system call has not yet be
	 * added recorded in the library */\
	X(LIBSYSCALLS_TYPE_UNKNOWN ## SUFFIX, FIRST, "(unknown type)") D\
	/* the type depends on the system call input or output */\
	X(LIBSYSCALLS_TYPE_DYNAMIC ## SUFFIX,, "(undetermined type)") D\
	/* the system call should never returned to the calling
	 * process (return to tracer is usually expected) */\
	X(LIBSYSCALLS_TYPE_NO_RETURN ## SUFFIX,, "no_return") D\
	/* either used as return type, to skip a register in the
	 * parameters (do not dismiss this, on some architectures
	 * a system call may need padding with dummy arguments to
	 * align latter register pairs; an application printing
	 * the system call must choose between omitting, printing
	 * the argument, or indicating that there is a dummy
	 * parameter (of course the latter two can be combined)),
	 * or to add padding (or reserved space for future
	 * expansion) to a struct */\
	X(LIBSYSCALLS_TYPE_VOID ## SUFFIX,, "void")

#define LIBSYSCALLS_LIST_SPLIT_PRIMITIVES(X, SUFFIX, D, FIRST)\
	X(LIBSYSCALLS_TYPE_UINT64_HIGH_32 ## SUFFIX, FIRST, "uint64_t {. << 32}") D\
	X(LIBSYSCALLS_TYPE_UINT64_LOW_32 ## SUFFIX,, "uint64_t {. & 0xFFFFFFFF}") D\
	X(LIBSYSCALLS_TYPE_UINT64_FRONT_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[0]}") D\
	X(LIBSYSCALLS_TYPE_UINT64_BACK_32 ## SUFFIX,, "uint64_t {((uint32_t *)&.)[1]}") D\
	X(LIBSYSCALLS_TYPE_INT64_HIGH_32 ## SUFFIX,, "int64_t {. << 32}") D\
	X(LIBSYSCALLS_TYPE_INT64_LOW_32 ## SUFFIX,, "int64_t {. & 0xFFFFFFFF}") D\
	X(LIBSYSCALLS_TYPE_INT64_FRONT_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[0]}") D\
	X(LIBSYSCALLS_TYPE_INT64_BACK_32 ## SUFFIX,, "int64_t {((uint32_t *)&.)[1]}")

#define LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES(X, SUFFIX, D, FIRST)\
	X(LIBSYSCALLS_TYPE_STRING ## SUFFIX, FIRST, "const char *") D\
	X(LIBSYSCALLS_TYPE_STRINGS_THEN_NULL ## SUFFIX,, "const char **")

#define LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
	X(LIBSYSCALLS_TYPE_MEMORY_ADDRESS ## SUFFIX, FIRST, "void *") D\
	X(LIBSYSCALLS_TYPE_CHAR ## SUFFIX,, "char") D\
	X(LIBSYSCALLS_TYPE_SCHAR ## SUFFIX,, "signed char") D\
	X(LIBSYSCALLS_TYPE_UCHAR ## SUFFIX,, "unsigned char") D\
	X(LIBSYSCALLS_TYPE_SHORT ## SUFFIX,, "short int") D\
	X(LIBSYSCALLS_TYPE_USHORT ## SUFFIX,, "unsigned short int") D\
	X(LIBSYSCALLS_TYPE_INT ## SUFFIX,, "int") D\
	X(LIBSYSCALLS_TYPE_UINT ## SUFFIX,, "unsigned int") D\
	X(LIBSYSCALLS_TYPE_LONG ## SUFFIX,, "long int") D\
	X(LIBSYSCALLS_TYPE_ULONG ## SUFFIX,, "unsigned long int") D\
	X(LIBSYSCALLS_TYPE_LLONG ## SUFFIX,, "long long int") D\
	X(LIBSYSCALLS_TYPE_ULLONG ## SUFFIX,, "unsigned long long int") D\
	X(LIBSYSCALLS_TYPE_SSIZE ## SUFFIX,, "ssize_t") D\
	X(LIBSYSCALLS_TYPE_SIZE ## SUFFIX,, "size_t") D\
	X(LIBSYSCALLS_TYPE_PTRDIFF ## SUFFIX,, "ptrdiff_t") D\
	X(LIBSYSCALLS_TYPE_UPTRDIFF ## SUFFIX,, "uptrdiff_t") D\
	X(LIBSYSCALLS_TYPE_INTPTR ## SUFFIX,, "intptr_t") D\
	X(LIBSYSCALLS_TYPE_UINTPTR ## SUFFIX,, "uintptr_t") D\
	X(LIBSYSCALLS_TYPE_INT8 ## SUFFIX,, "int8_t") D\
	X(LIBSYSCALLS_TYPE_UINT8 ## SUFFIX,, "uint8_t") D\
	X(LIBSYSCALLS_TYPE_INT16 ## SUFFIX,, "int16_t") D\
	X(LIBSYSCALLS_TYPE_UINT16 ## SUFFIX,, "uint16_t") D\
	X(LIBSYSCALLS_TYPE_INT32 ## SUFFIX,, "int32_t") D\
	X(LIBSYSCALLS_TYPE_UINT32 ## SUFFIX,, "uint32_t") D\
	X(LIBSYSCALLS_TYPE_INT64 ## SUFFIX,, "int64_t") D\
	X(LIBSYSCALLS_TYPE_UINT64 ## SUFFIX,, "uint64_t")

#define LIBSYSCALLS_LIST_ANNOTATED_NUMERICALS(X, SUFFIX, D, FIRST)\
	X(LIBSYSCALLS_TYPE_INT_SIGNAL ## SUFFIX, FIRST, "int") D /* OS signal */\
     	X(LIBSYSCALLS_TYPE_INT_FD ## SUFFIX,, "int") D /* file descriptor */ \
	X(LIBSYSCALLS_TYPE_INT_ATFD ## SUFFIX,, "int") D /* file descriptor or current working directory */ \
	X(LIBSYSCALLS_TYPE_LONG_FD ## SUFFIX,, "long int") D\
	X(LIBSYSCALLS_TYPE_LONG_ATFD ## SUFFIX,, "long int")

#define LIBSYSCALLS_LIST_STRUCTS_AND_UNIONS(X, SUFFIX, D, FIRST)\
	X(LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET ## SUFFIX, FIRST, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_AIO_SIGSET ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OABI_EPOLL_EVENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_IOB ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_IOVEC ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_IO_EVENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_ITIMERVAL ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC64 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MMAP_ARG_STRUCT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MMSGHDR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MOUNT_ATTR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MQ_ATTR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MSGBUF ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MSGHDR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_MSQID_DS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_NEW_UTSNAME ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLDOLD_UTSNAME ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERSPEC32 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERVAL ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_LINUX_DIRENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_SIGACTION ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_STAT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMESPEC32 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL32 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEX32 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTIMBUF32 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OLD_UTSNAME ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_OPEN_HOW ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_PERF_EVENT_ATTR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_POLLFD ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT64 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_RLIMIT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_RSEQ ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_RUSAGE ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SCHED_ATTR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SCHED_PARAM ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SEL_ARG_STRUCT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SEMBUF ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SEMID_DS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SHMID_DS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SIGACTION ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SIGEVENT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SIGINFO ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SOCKADDR ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_STAT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_STAT64 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_STATFS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_STATFS64 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_STATX ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_SYSINFO ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC64 ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_TIMEVAL ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_TIMEX ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_TIMEZONE ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_TMS ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_USTAT ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_STRUCT_UTIMBUF ## SUFFIX,, "struct") D\
	X(LIBSYSCALLS_TYPE_UNION_BPF_ATTR ## SUFFIX,, "union")

#define LIBSYSCALLS_LIST_FIXED_ARRAYS(X, SUFFIX, D, FIRST)\
	X(LIBSYSCALLS_TYPE_2_INTS ## SUFFIX, FIRST, "int[2]") D\
	X(LIBSYSCALLS_TYPE_2_INTS_FD ## SUFFIX,, "int[2]") D\
	X(LIBSYSCALLS_TYPE_2_UINT32S ## SUFFIX,, "uint32[2]") D\
	X(LIBSYSCALLS_TYPE_FD_SET ## SUFFIX,, "unsigned long[]") /* size depends on OS, (1024/CHAR_BIT/sizeof(long)) in Linux */ D\
	X(LIBSYSCALLS_TYPE_BUFFER_9 ## SUFFIX,, "char[9]") D\
	X(LIBSYSCALLS_TYPE_BUFFER_65 ## SUFFIX,, "char[65]")

	/* these don't have any suffix */
	LIBSYSCALLS_MAKE_SPECIAL_TYPES_(),
	LIBSYSCALLS_MAKE_SPLIT_PRIMITIVES_(),
	LIBSYSCALLS_MAKE_COMPOSITE_PRIMITIVES_(),
	LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(),
	LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(),
	LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(),

	/* the following are always pointers if used as a parameter */

	/* size in next parameter (or the previous parameter if there is no next parameter),
	 * updated with fill if possible, otherwise returned (these use the suffix _ARRAY) */
	LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY),
	LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY),
	LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY),

	/* size in next parameter (or the previous parameter if there is no next parameter),
	 * fill is in no way returned (these use the suffix _ARRAY_UNKNOWN_FILL) */
	LIBSYSCALLS_MAKE_UNANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
	LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(_ARRAY_UNKNOWN_FILL),
	LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(_ARRAY_UNKNOWN_FILL),

	/* these don't have any suffix */
	LIBSYSCALLS_MAKE_FIXED_ARRAYS_()

#undef LIBSYSCALLS_TYPE_CHAR_ARRAY
#undef LIBSYSCALLS_TYPE_CHAR_ARRAY_UNKNOWN_FILL
};

/**
 * Broad classification on system calls
 */
enum libsyscalls_syscall_category {
	/**
	 * The library knows about the system calls but
	 * has not yet implemented detailed information
	 * about the system call
	 */
	LIBSYSCALLS_CAT_SUPPORT_PENDING,

	/**
	 * The system call has a name but is not implemented
	 * in the kernel, and thus does not have an ABI either
	 * 
	 * Be aware that this information may be outdated
	 * and that `LIBSYSCALLS_CAT_SUPPORT_PENDING` might
	 * actually be more appropriate
	 * 
	 * This value is not used for system calls that have
	 * be removed, those are still described as if still
	 * implemented by the kernel
	 */
	LIBSYSCALLS_CAT_NOT_IMPLEMENTED,

	LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC, /**< See enum libsyscalls_network_enabled_ipc_syscall_subcategory */
	LIBSYSCALLS_CAT_IPC,                 /**< See enum libsyscalls_ipc_syscall_subcategory */
	LIBSYSCALLS_CAT_FILESYSTEM,          /**< See enum libsyscalls_filesystem_syscall_subcategory */
	LIBSYSCALLS_CAT_FILE_DESCRIPTORS,    /**< See enum libsyscalls_file_descriptors_syscall_subcategory */
	LIBSYSCALLS_CAT_PROCESSES,           /**< See enum libsyscalls_processes_syscall_subcategory */
	LIBSYSCALLS_CAT_LOGGING,             /**< See enum libsyscalls_logging_syscall_subcategory */
	LIBSYSCALLS_CAT_TIME,                /**< See enum libsyscalls_time_syscall_subcategory */
	LIBSYSCALLS_CAT_SIGNALS,             /**< See enum libsyscalls_singals_syscall_subcategory */
	LIBSYSCALLS_CAT_MEMORY,              /**< See enum libsyscalls_memory_syscall_subcategory */
	LIBSYSCALLS_CAT_SYSTEM,              /**< See enum libsyscalls_system_syscall_subcategory */
	LIBSYSCALLS_CAT_SCHEDULING           /**< See enum libsyscalls_scheduling_syscall_subcategory */
};

/**
 * Interprocess communication system calls that may
 * either communicate other the a network or locally
 * on the machine
 * 
 * Generally these do not affect the filesystem, the only exception
 * is LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND may create index
 * nodes and LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT may
 * access the index nodes
 *
 * May system calls used for this class of communication
 * objects used LIBSYSCALLS_CAT_FILE_DESCRIPTORS system calls
 */
enum libsyscalls_network_enabled_ipc_syscall_subcategory {
	/**
	 * System calls that create a non-persistent
	 * communication object (such as a file descriptor)
	 * for this category of interprocess communication;
	 * meaning a file descriptor or similar object
	 * that causes the shared resource to be deallocated
	 * once all instances of the object has been released
	 * 
	 * socket(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CREATE,

	/**
	 * System calls that accept incoming connections and
	 * create a new communication object, or rejects them
	 * 
	 * accept(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT,

	/**
	 * System calls that enable a communication object to
	 * use LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_ACCEPT
	 * system calls
	 * 
	 * listen(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_LISTEN,

	/**
	 * System calls that assigns a communication object
	 * to an local address, this can be a filesystem path
	 * or a network address, or a local identifier; this
	 * system calls gives the communication an address,
	 * and may create an index node on the file system
	 * 
	 * bind(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND,

	/**
	 * System calls that attaches a communication object
	 * to an local address, this can be a filesystem path
	 * or a network address, or a local identifier; this
	 * system calls tells the kernel which other communication
	 * object the object shall communicate with, it does
	 * not give explicitly the communication object an
	 * address, however the kernel may give it one if one
	 * has not already be assigned
	 * 
	 * connect(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_CONNECT,

	/**
	 * System calls that inspect details about a
	 * communication object
	 * 
	 * getsockname(2), getpeername(2), and getsockopt(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_STAT
};

/**
 * Interprocess communication system calls that always
 * local to the machine or a networked filesystem
 */
enum libsyscalls_ipc_syscall_subcategory {
	/**
	 * System calls that create a non-persistent
	 * communication object (such as a file descriptor)
	 * for this category of interprocess communication;
	 * meaning a file descriptor or similar object
	 * that causes the shared resource to be deallocated
	 * once all instances of the object has been released
	 * 
	 * pipe(2) and socketpair(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_IPC_SUBCAT_CREATE,

	/**
	 * System calls that lock, unlock or inspects a lock
	 * on a file, for locks that are strictly advisory
	 * 
	 * Note this information can be out of date and the
	 * system call may deal with mandatory file locks,
	 * for example since Linux 5.5, flock(2) has mandatory
	 * on some network file systems; the library does not
	 * take into consideration which version of the kernel
	 * is used, but assumes the latest version (of course
	 * the library may be out of date in regard to this
	 * information even if it is build to the latest kernel)
	 */
	LIBSYSCALLS_IPC_SUBCAT_ADVISORY_FILE_LOCK,

	/**
	 * System calls that lock, unlock or inspects a lock
	 * on a file, for locks that are strictly mandatory
	 * 
	 * Note this information can be out of date and the
	 * system call may deal with advisory file locks; the
	 * library does not take into consideration which
	 * version of the kernel is used, but assumes the latest
	 * version (of course the library may be out of date in
	 * regard to this information even if it is build to the
	 * latest kernel)
	 */
	LIBSYSCALLS_IPC_SUBCAT_MANDATORY_FILE_LOCK,

	/**
	 * System calls that lock, unlock or inspects a lock
	 * on a file, for locks that may be either advisory
	 * or mandatory
	 * 
	 * flock(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_IPC_SUBCAT_FILE_LOCK,

	/**
	 * System calls that create or deletes communication
	 * objects, or inspects or changes details about such
	 * objects
	 * 
	 * Some system calls use LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE
	 * instead
	 * 
	 * shmget(2), shmctl(2), mq_open(2), mq_unlink(2),
	 * mq_notify(2), and mq_getsetattr(2) are examples of
	 * system calls in this category
	 */
	LIBSYSCALLS_IPC_SUBCAT_CONTROL,

	/**
	 * System calls that attach to an existing IPC object
	 * 
	 * shmat(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_IPC_SUBCAT_ATTACH,

	/**
	 * System calls that detach from an IPC object
	 * 
	 * shmdt(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_IPC_SUBCAT_DETACH,

	/**
	 * Communication system calls that do not have a timeout
	 */
	LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE,

	/**
	 * Communication system calls that may have a relative
	 * or absolute timeout
	 */
	LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_TIMEOUT,

	/**
	 * Communication system calls that may have a relative timeout
	 */
	LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_RELATIVE_TIMEOUT,

	/**
	 * Communication system calls that may have an absolute timeout
	 */
	LIBSYSCALLS_IPC_SUBCAT_COMMUNICATE_WITH_ABSOLUTE_TIMEOUT
};

/**
 * System calls that operate on the filesystem or can either
 * operate on a filesystem or a file descriptor that does
 * not involve the filesystem but is usually used with a
 * filesystem; this category also include system calls that
 * effect such systems but does not itself touch the filesystem
 * but rather the process
 * 
 * System calls in this category may have timeouts that may
 * use relative or absolute time
 */
enum libsyscalls_filesystem_syscall_subcategory {
	/**
	 * System calls that retrieve the metadata of file
	 * 
	 * stat(2) and fstatat(2) are examples of system calls
	 * in this category; fstat(2) however is not
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_STAT,

	/**
	 * System calls that motifies the metadata of file
	 * 
	 * chmod(2) and fchmodat(2) are examples of system calls
	 * in this category; fchmod(2) however is not
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_MODIFY,

	/**
	 * System calls that commit changes to one or more files
	 * to the filesystem or mmap(2)ed anonymous memory
	 * 
	 * sync(2), fsync(2), and msync(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_SYNC,

	/**
	 * System calls the create named index nodes (links)
	 * on a filesystem
	 * 
	 * Note that LIBSYSCALLS_NETWORK_ENABLED_IPC_SUBCAT_BIND
	 * system calls may also create links
	 * 
	 * linkat(2), link(2), symlink(2), mknod(2), and mkdir(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK,

	/**
	 * System calls the remove the path to an index node
	 * (removes a link) on a filesystem
	 * 
	 * unlink(2) and rmdir(2) are examples of system calls
	 * in this category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK,

	/**
	 * System calls that can operate both as
	 * LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK and
	 * LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK system calls,
	 * either one at a time or both at the same them
	 * 
	 * rename(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK_OR_UNLINK,

	/**
	 * System calls that inspects or changes (or both
	 * at the same time) the process's or thread's
	 * umask, which affects the permissions that shall
	 * be eliminated when an index node or IPC object
	 * is created
	 * 
	 * umask(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_UMASK,

	/**
	 * System calles that in some way operate on
	 * mountpoints
	 *
	 * Note that some system calls in the category takes
	 * file descriptors as input or outputs
	 * 
	 * mount(2), umount(2), and fsopen(2) are examples
	 * of system calls in this category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_MOUNTPOINT,

	/**
	 * System calls that retrieve the information about
	 * a mounted filesystem
	 * 
	 * statfs(2) and the hypothetical fstatfsat(2) are
	 * examples of system calls in this category;
	 * fstatfs(2) however is not
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_STATFS,

	/**
	 * System calls that make changes to a file
	 * content without requiring a file descriptor
	 * to it, however the system call may optionally
	 * accept a file descriptor
	 * 
	 * Hypothetically an operating system could provide
	 * system calls that fall under this category and
	 * could be used to change the target path of an
	 * existing symbolic link
	 * 
	 * truncate(2) and the hypothetical ftruncateat(2) 
	 * are examples of system calls in this category;
	 * ftruncate(2) however is not
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_WRITE,

	/**
	 * System calls that reads the contents of a file
	 * content without requiring a file descriptor
	 * to it, however the system call may optionally
	 * accept a file descriptor
	 * 
	 * There currently are not such system calls,
	 * however, an operating system could not only
	 * provide such system call to read the contents
	 * of a file, but the read the file listing in
	 * a directory or the target path of a symbolic
	 * link
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_READ,

	/**
	 * System calls that retrieves the target path
	 * of a symbolic link without requiring a file
	 * descriptor to it, however the system call
	 * may optionally accept a file descriptor
	 * 
	 * readlink(2) and the readlinkat(2) are examples
	 * of system calls in this category; the
	 * hypothetical freadlink(2) however is not
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_READLINK,

	/**
	 * System calls that are used to monitoring
	 * changes and accesses to a file or filesystem
	 * 
	 * This system calls may create file descriptors
	 * or use such file descriptors
	 * 
	 * All inotify(7) and fanotify(7) system calls are
	 * examples of system calls in this category;
	 * mq_notify(2) however is not
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_MONITOR,

	/**
	 * System calls that are used dealing with
	 * filesystem quotas
	 * 
	 * This system calls may create file descriptors
	 * or use such file descriptors
	 * 
	 * quotactl(2) is an example of system call in
	 * this category
	 */
	LIBSYSCALLS_FILESYSTEM_SUBCAT_QUOTA
};

/**
 * System calls that operate on or create a file descriptor
 * without fitting into a special category
 * 
 * System calls in this category may have timeouts that may
 * use relative or absolute time
 */
enum libsyscalls_file_syscall_descriptors_subcategory {
	/**
	 * System calls that retrieve metadata about a
	 * file through a file descriptor to it
	 * 
	 * fstat(2) is an example of system call in
	 * this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STAT,

	/**
	 * System calls that modifies metadata about a
	 * file through a file descriptor to it
	 * 
	 * fchmod(2) and fchown(2) are examples of
	 * system calls in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_MODIFY,

	/**
	 * System calls that duplicates or closes,
	 * possibly both at the same time, file descriptors,
	 * or closes the file descriptor in one or two
	 * directions
	 * 
	 * dup(2), dup2(2), close(2), and shutdown(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_DUP_OR_CLOSE,

	/**
	 * System calls that closes or unshares,
	 * possibly both at the same time, file descriptors,
	 * or closes the file descriptor in one or two
	 * directions
	 * 
	 * close_range(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CLOSE_OR_UNSHARE,

	/**
	 * System calls that read from a file descriptor
	 * and changes the file offset while doing so
	 * 
	 * For IPC objects that do not have a file offset
	 * (such as pipes and sockets) this means that
	 * read data is removed from the object
	 * 
	 * read(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ,

	/**
	 * System calls that read from a file descriptor
	 * without changing the file offset
	 * 
	 * For IPC objects that do not have a file offset
	 * (such as pipes and sockets) this means that
	 * read data will remain in the object, and if
	 * the system calls is made again, the same data
	 * will be read
	 * 
	 * pread(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK,

	/**
	 * System calls that changes the file offset for
	 * a file descriptor without changing reading
	 * or writing
	 * 
	 * lseek(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_SEEK,

	/**
	 * System calls that write to a file descriptor
	 * with or without changing the file offset
	 * 
	 * write(2), pwrite(2), send(2), and sendto(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE,

	/**
	 * System calls that read from a file descriptor
	 * with or without chaning the file offset
	 * 
	 * recv(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK,

	/**
	 * System calls that performs
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ actions
	 * on one file descriptor and
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE actions
	 * on another file descriptor, or possibly on the
	 * same file descriptor
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_AND_WRITE,

	/**
	 * System calls that performs
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK actions
	 * on one file descriptor and
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE actions
	 * on another file descriptor
	 * 
	 * tee(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_PEEK_AND_WRITE,

	/**
	 * System calls that performs
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK
	 * actions on one file descriptor and
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_WRITE actions
	 * on another file descriptor
	 * 
	 * splice(2) and sendfile(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_WRITE,

	/**
	 * System calls that performs
	 * LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK
	 * actions on a file descriptor while receiving
	 * metadata (this metadata does not need to fall
	 * under the category of LIBSYSCALLS_STAT_FILE_DESCRIPTORS,
	 * indeed it unlikely will)
	 * 
	 * System calls under this category may receive
	 * new file descriptors
	 * 
	 * recvfrom(2) and recvmsg(2) is an example of a
	 * system call in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_READ_OR_PEEK_AND_STAT,

	/**
	 * System calls that informs the kernel in what
	 * manner the process will use a file descriptor
	 * 
	 * posix_fadvise(2) and readahead(2) are examples of
	 * system calls in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_ADVISE,

	/**
	 * System calls that retrieve metadata about a
	 * filesystem through a file descriptor
	 * 
	 * fstatfs(2) is an example of system call in
	 * this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_STATFS,

	/**
	 * System calls that create a resource that is used
	 * for LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL
	 * actions
	 * 
	 * epoll_create(2) is an example of system call in
	 * this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CREATE_POLL,

	/**
	 * System calls that configure a resource that is
	 * used for LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL
	 * actions
	 * 
	 * epoll_ctl(2) is an example of system call in
	 * this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_CONFIGURE_POLL,

	/**
	 * System calls that wait until file descriptor
	 * are ready for writing or have data to read,
	 * or until some other event on the file descriptor
	 * has occurred
	 * 
	 * epoll_wait(2), poll(2) and pselect6(2) are
	 * examples of system calls in this category
	 */
	LIBSYSCALLS_FILE_DESCRIPTORS_SUBCAT_POLL
};

/**
 * System calls that affect a process itself
 *
 * Much of the information that can be queried
 * with system calls in this category may be
 * available through a virtual filesystem
 */
enum libsyscalls_processes_syscall_subcategory {
	/**
	 * System calls that causes the thread, process,
	 * process group, or session to exit
	 * 
	 * exit(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_EXIT,

	/**
	 * System calls that retrive information about
	 * the thread, process, process group, or session
	 * 
	 * gettid(2), getpid(2), getpgid(2), getsid(2),
	 * getuid(2), and getcwd(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_STAT_SELF,

	/**
	 * System calls that retrive information about the
	 * process's child processes, or other descendants,
	 * or itself
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_STAT_CHILD,

	/**
	 * System calls that retrive information about the
	 * process's parent or other ancestors, or itself
	 * or its descendants
	 * 
	 * getppid(2) and getxpid(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_STAT_PARENT,

	/**
	 * System calls that retrive information about any
	 * process
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_STAT_OTHER,

	/**
	 * System calls that change the process's privileges
	 *
	 * The system call may also retrieve information
	 * about the process
	 * 
	 * setuid(2) in an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_CHANGE_PERMISSIONS,

	/**
	 * System calls that forks the process, either
	 * the create a new process or a new thread
	 * 
	 * fork(2) and clone(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_CLONE,

	/**
	 * System calls that changes the program the
	 * process is executing
	 * 
	 * execve(2) and execveat(2) are examples of
	 * system calls in this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_EXEC,

	/**
	 * System calls that change the working directory
	 * of the process or thread
	 * 
	 * chdir(2) in an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_CHDIR,

	/**
	 * System calls that change the file system root
	 * of the process or thread
	 * 
	 * chroot(2) and pivot_root(2) are examples of
	 * system calls in this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_CHROOT,

	/**
	 * System calls that affect the process's session
	 * or process group
	 * 
	 * setsid(2), setpgid(2), and vhangup(2) are
	 * examples of system calls in this category
	 */
	LIBSYSCALLS_PROCESSES_SUBCAT_SESSION
};

/**
 * System calls that enables or disable system logging
 *
 * For each system call in this category, the system call
 * may use the filesystem or a file descriptor
 */
enum libsyscalls_logging_syscall_subcategory {
	/**
	 * System calls that turn on or off logging for
	 * processes
	 * 
	 * acct(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_LOGGING_SUBCAT_PROCESSES
};

/**
 * System calls whose primary function are time related
 */
enum libsyscalls_time_syscall_subcategory {
	/**
	 * System calls that can either get or set (or both)
	 * the current time or time zone information, or the
	 * time of a virtual clock such as a process's run
	 * time
	 * 
	 * adjtime(2), adjtimex(2), and clock_adjtime(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_GET_OR_SET,

	/**
	 * System calls that can get the current time or
	 * time zone information, or the time of a virtual
	 * clock
	 * 
	 * time(2), gettimeofday(2), and clock_gettime(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_GET,

	/**
	 * System calls that can set the current time or
	 * time zone information, or the time of a virtual
	 * clock
	 * 
	 * stime(2), settimeofday(2), and clock_settime(2)
	 * are examples of system calls in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_SET,

	/**
	 * System calls that receive metadata about a
	 * clock
	 * 
	 * clock_gettres(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_INTROSPECT,

	/**
	 * System calls that arm or disarm a timer that
	 * uses relative time
	 * 
	 * alarm(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE,

	/**
	 * System calls that arm or disarm a timer that
	 * uses absolute time
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE,

	/**
	 * System calls that arm or disarm a timer that
	 * can use either relative or absolute time
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER,

	/**
	 * System calls that read the amount of time
	 * remaining until a timer that uses relative
	 * time is run over (is triggered)
	 *
	 * These system calls may also retrieve a timer's
	 * overrun interval
	 * 
	 * getitimer(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ,

	/**
	 * System calls that read the time a timer that
	 * uses absolute time runs over (is triggered)
	 * 
	 * These system calls may also retrieve a
	 * timer's overrun interval
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ,

	/**
	 * System calls that act both as
	 * LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ
	 * and LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ
	 * system calls
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_READ,

	/**
	 * System calls that act both as
	 * LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE
	 * and LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ
	 * system calls and may more may not do both at
	 * the same time
	 * 
	 * setitimer(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_WITH_READ,

	/**
	 * System calls that act both as
	 * LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE
	 * and LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ
	 * system calls and may more may not do both at
	 * the same time
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_WITH_READ,

	/**
	 * System calls that act both as
	 * LIBSYSCALLS_TIME_SUBCAT_TIMER and
	 * LIBSYSCALLS_TIME_SUBCAT_TIMER_READ system calls
	 * and may more may not do both at the same time
	 */
	LIBSYSCALLS_TIME_SUBCAT_TIMER_WITH_READ,

	/**
	 * System calls that suspends the process until
	 * a relative point in time (this could be virtual
	 * time such as a process's run time)
	 * 
	 * The system call may return early for any reason,
	 * for example because the a signal was sent to
	 * the process
	 * 
	 * nanosleep(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_SLEEP_RELATIVE,

	/**
	 * System calls that suspends the process until
	 * an absolute point in time (this could be virtual
	 * time such as a process's run time)
	 * 
	 * The system call may return early for any reason,
	 * for example because the a signal was sent to the
	 * process or the time of the clock was modified
	 */
	LIBSYSCALLS_TIME_SUBCAT_SLEEP_ABSOLUTE,

	/**
	 * System calls that act both as
	 * LIBSYSCALLS_TIME_SUBCAT_TIMER_RELATIVE_READ
	 * and LIBSYSCALLS_TIME_SUBCAT_TIMER_ABSOLUTE_READ
	 * system calls
	 * 
	 * clock_nanosleep(2) is an example of a system
	 * call in this category
	 */
	LIBSYSCALLS_TIME_SUBCAT_SLEEP
};

/**
 * System calls that deal with signals (signal(7))
 */
enum libsyscalls_signals_syscall_subcategory {
	/**
	 * System calls that only causes the process
	 * to suspend until it receives a signal
	 * 
	 * Many system calls will be interrepted if
	 * there is a pending signal or one is received
	 * during the system call. There are also some
	 * system calls that can be used to emulating
	 * the behaviour of system calls in this category
	 * but that have another primary purpose.
	 * 
	 * pause(2) in example of a system call in this
	 * category
	 */
	LIBSYSCALLS_SIGNALS_SUBCAT_PAUSE,

	/**
	 * System calls that send a signal to a process
	 * 
	 * kill(2) in example of a system call in this
	 * category
	 */
	LIBSYSCALLS_SIGNALS_SUBCAT_KILL
};

/**
 * System calls that deal with memory allocations
 * including memory mapped files
 */
enum libsyscalls_memory_syscall_subcategory {
	/**
	 * System calls that allocate memory or change
	 * the allocation size of an allocated memory
	 * segment
	 * 
	 * The system calls may also return information
	 * about how much memory has allocated
	 * 
	 * These system calls may change the address of
	 * an allocated memory segment
	 * 
	 * brk(2), mmap(2), mremap(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_ALLOCATE,

	/**
	 * System calls that deallocate allocated memory
	 * segments
	 * 
	 * munmap(2) is an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_DEALLOCATE,

	/**
	 * System calls modifies memory
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_WRITE,

	/**
	 * System calls advises the kernel on issues
	 * regarding the process's memory
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_ADVISE,

	/**
	 * System calls that can operate both as
	 * LIBSYSCALLS_FILESYSTEM_SUBCAT_LINK and
	 * LIBSYSCALLS_FILESYSTEM_SUBCAT_UNLINK system calls,
	 * either one at a time or both at the same them
	 * 
	 * madvise(2) is an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_WRITE_OR_ADVISE,

	/**
	 * System calls that prevent memory to be
	 * paged out into the swap area
	 * 
	 * mlock(2) is an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_LOCK,

	/**
	 * System calls that enables memory to be
	 * paged out into the swap area
	 * 
	 * munlock(2) is an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_UNLOCK,

	/**
	 * System calls that retrieves details about
	 * memory allocated to the process
	 * 
	 * mincore(2) is an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_STAT,

	/**
	 * System calls that changes details about
	 * memory allocated to the process
	 * 
	 * mprotect(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_MEMORY_SUBCAT_MODIFY
};

/**
 * System calls that deal directly with the
 * operating system or machine
 */
enum libsyscalls_system_syscall_subcategory {
	/**
	 * System calls that deal set swap memory
	 * 
	 * swapon(2) and swapoff(2) are examples of system
	 * calls in this category
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_SWAP,

	/**
	 * System calls that poweroff, reboots, suspends
	 * the machine or live patches the kernel
	 * 
	 * Note that it is common to preform this task by
	 * communicating with the init system
	 * 
	 * reboot(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_REBOOT,

	/**
	 * System calls that get the name of the machine
	 * or the operating system, as well as version
	 * and CPU details
	 * 
	 * Note that this information may also be available
	 * through a virtual file system
	 * 
	 * uname(2) and gethostname(2) are examples of
	 * system calls in this category
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_GET_NAME,

	/**
	 * System calls that set the name of the machine
	 * 
	 * Note that this information may also be settable
	 * via a virtual file system
	 * 
	 * sethostname(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_SET_NAME,

	/**
	 * System calls that get runtime information about
	 * the system, such as CPU and memory usage and
	 * entropy
	 * 
	 * Note that this information may also be settable
	 * via a virtual file system
	 * 
	 * sysinfo(2) is an example of a system call
	 * in this category
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_STAT,

	/**
	 * System calls that get generate random data, and
	 * may thereby deplete the systems entropy pool
	 * 
	 * Note that this may also be possible to do via a
	 * virtual file system
	 * 
	 * getrandom(2) is an example of a system call in
	 * this category
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_RANDOM,

	/**
	 * System calls that are generally harmless and
	 * required for a process to perform important
	 * actions
	 *
	 * On Linux the following system calls have this
	 * classification:
	 * -   getpagesize(2)
	 */
	LIBSYSCALLS_SYSTEM_SUBCAT_FUNDAMENTAL
};

/**
 * System calls that affect process sheduling
 */
enum libsyscalls_scheduling_syscall_subcategory {
	/**
	 * System calls that causes the thread, process,
	 * process group, session, or user the give up it's
	 * allotted time
	 * 
	 * sched_yield(2) is an example of system call in
	 * this category
	 */
	LIBSYSCALLS_SCHEDULING_SUBCAT_YIELD,

	/**
	 * System calls that changes a thread's, process's
	 * process group's, session's, or user's, or the
	 * machines scheduling parameters
	 * 
	 * sched_setscheduler(2), sched_setaffinity(2),
	 * and setpriority(2) are examples of system calls
	 * in this category
	 */
	LIBSYSCALLS_SCHEDULING_SUBCAT_SET,

	/**
	 * System calls that retrieves a thread's, process's
	 * process group's, session's, or user's, or the
	 * machines scheduling parameters
	 * 
	 * sched_getscheduler(2), sched_getaffinity(2),
	 * and getpriority(2) are examples of system calls
	 * in this category
	 */
	LIBSYSCALLS_SCHEDULING_SUBCAT_GET,

	/**
	 * System calls that can operate both as
	 * LIBSYSCALLS_SCHEDULING_SUBCAT_GET and
	 * LIBSYSCALLS_SCHEDULING_SUBCAT_SET system calls,
	 * either one at a time or both at the same them
	 * 
	 * nice(2) is an example of a system call in this
	 * category
	 */
	LIBSYSCALLS_SCHEDULING_SUBCAT_GET_OR_SET,

	/**
	 * System calls the retrieve metadata for the
	 * scheduling options that are available on the
	 * system
	 * 
	 * sched_get_priority_max(2) is an example of
	 * a system call in this category
	 */
	LIBSYSCALLS_SCHEDULING_SUBCAT_INTROSPECT
};

/**
 * Less broad classification on system calls
 * 
 * Each value in `enum libsyscalls_syscall_category` have
 * its own field (enumeration of values) name after the
 * `enum` value; except that LIBSYSCALLS_CAT_SUPPORT_PENDING
 * and LIBSYSCALLS_CAT_NOT_IMPLEMENTED does not have any,
 * which also means that whereever this union is used, its
 * value is undefined, if the broad classification is either
 * LIBSYSCALLS_CAT_SUPPORT_PENDING or LIBSYSCALLS_CAT_NOT_IMPLEMENTED
 */
union libsyscalls_syscall_subcategory {
	enum_libsyscalls_network_enabled_ipc_syscall_subcategory network_enabled_ipc; /**< If LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC */
	enum_libsyscalls_ipc_syscall_subcategory ipc;                                 /**< If LIBSYSCALLS_CAT_IPC */
	enum_libsyscalls_filesystem_syscall_subcategory filesystem;                   /**< If LIBSYSCALLS_CAT_FILESYSTEM */
	enum_libsyscalls_file_descriptors_syscall_subcategory file_descriptors;       /**< If LIBSYSCALLS_CAT_FILE_DESCRIPTORS */
	enum_libsyscalls_processes_syscall_subcategory processes;                     /**< If LIBSYSCALLS_CAT_PROCESSES */
	enum_libsyscalls_logging_syscall_subcategory logging;                         /**< If LIBSYSCALLS_CAT_LOGGING */
	enum_libsyscalls_time_syscall_subcategory time;                               /**< If LIBSYSCALLS_CAT_TIME */
	enum_libsyscalls_signals_syscall_subcategory signals;                         /**< If LIBSYSCALLS_CAT_SIGNALS */
	enum_libsyscalls_memory_syscall_subcategory memory;                           /**< If LIBSYSCALLS_CAT_MEMORY */
	enum_libsyscalls_system_syscall_subcategory system;                           /**< If LIBSYSCALLS_CAT_SYSTEM */
	enum_libsyscalls_scheduling_syscall_subcategory scheduling;                   /**< If LIBSYSCALLS_CAT_SCHEDULING */
};

/**
 * System call interface
 */
struct libsyscalls_syscall_abi {
	/**
	 * Classification of what the system call does
	 * 
	 * Check `.category` to se which group of
	 * classifications to used
	 */
	union libsyscalls_syscall_subcategory subcategory;

	/**
	 * Broad classification of what the system calls does
	 */
	enum_libsyscalls_syscall_category category : 16;

	/**
	 * For set any bit indexed I (starting from 0), the
	 * system call parameter I is a pointer that the
	 * system call reads from
	 * 
	 * Note that there are types that fundamentally are
	 * pointers (such as strings), for these, this bit
	 * is not set unless it is a pointer to a string
	 */
	unsigned short int in_pointer_mask : 16;

	/**
	 * For set any bit indexed I (starting from 0), the
	 * system call parameter I is a pointer that the
	 * system call write to
	 * 
	 * Note that there are types that fundamentally are
	 * pointers (such as strings), for these, this bit
	 * is not set unless it is a pointer to a string
	 */
	unsigned short int out_pointer_mask : 16;

	/**
	 * For set any bit indexed I (starting from 0), the
	 * system call parameter I can be resolved into a
	 * symbolic string by the library
	 */
	unsigned short int symbolic_mask : 16;

	/**
	 * The minimum number of arguments that must be
	 * passed into the system call, -1 if unknown
	 */
	short int min_argument_count : 6;

	/**
	 * The maximum number of arguments that can be
	 * passed into the system call, -1 if unknown
	 */
	short int max_argument_count : 6;

	/**
	 * If set, the library can resolve the value the
	 * system call returns into a symbolic string
	 */
	unsigned short int symbolic_return : 1;

	/**
	 * If 1, the system call shall always either return
	 * an error, return the value 0, or not return at all
	 */
	unsigned short int expect_zero : 1;

	/**
	 * If 1, the system call invocation must be parsed
	 * especially as it is not does follow what is
	 * proscribed for the used data types
	 *
	 * The library may use this temporarily until it
	 * in a later version provides a convension that
	 * can be followed
	 */
	unsigned short int queer : 1;

	short int : LIBSYSCALLS_PAD_(sizeof(short int)/sizeof(char)*CHAR_BIT,
	                             4*16 + 2*6 + 3*1);

	/**
	 * This is used internally by `libsyscalls_get_syscall_display_info`
	 * to find out how values ought to be printed to be both human
	 * and machines friendly (symbolic names are indeed easier for
	 * the application to deal with as their values can depend on
	 * the architecture), and occasionally to determine what types
	 * are used for on arguments whose type is argument dependent,
	 * and to figure which optional arguments are included in the
	 * system call
	 * 
	 * If this is value is 0, `libsyscalls_get_syscall_display_info`
	 * will not be able to provide any useful information, which
	 * would either be because everything is provided here (in
	 * `struct libsyscalls_syscall_abi`) or because the library
	 * hasn't yet added full support for the system call
	 */
	LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16;

	/**
	 * The system call's return type
	 */
	enum_libsyscalls_datatype return_type : 16;

	/**
	 * The type of each of the systems call's parameter
	 * 
	 * The application must not read `.parameters_types[.max_argument_count]`
	 * or beyond, doing so will probably mean reading beyond the memory
	 * allocated for the instance of the structure
	 */
	enum_libsyscalls_datatype parameters_types[LIBSYSCALLS_FLEXABLE_OR_NPARAMS_];
};

/**
 * System call description
 */
struct libsyscalls_syscall {
	/**
	 * What system call is named
	 */
	const char *name;

	/**
	 * The ABI for the system call for architecture it was
	 * queried for
	 * 
	 * May or may not be `NULL` if the system call is defined
	 * but not implemented
	 */
	struct libsyscalls_syscall_abi *actual_syscall;

	/**
	 * Like .actual_syscall except this is used for example when
	 * a 32-bit process is running on a 64-bit operating system
	 *
	 * If `NULL` use .actual_syscall
	 */
	struct libsyscalls_syscall_abi *actual_compat_syscall;
};

/**
 * Named number (errors and signals)
 */
struct libsyscalls_named_number {
	/**
	 * The value if the number, it is up to the
	 * application select signess
	 *
	 * It is usually safe to use unsigned (.u)
	 * as the numbers are usually positive but
	 * not so large that the sign bit would be
	 * set, unless the numbers are supposted to
	 * be unsigned
	 */
	union {
		signed long long int s;
		unsigned long long int u;
	} number;

	/**
	 * The name of the number, including namespacing
	 * (e.g. "E" prefix for errno numbers and "SIG"
	 * or "_SIG" prefix for singals)
	 */
	const char *name;
};

/**
 * Function that returns a name for a value
 * 
 * This function is called multiple times to extract
 * names of multiple subvalues, for example, for
 * the system call access() second parameter, it
 * will return the string "X_OK", "W_OK", "R_OK",
 * and "F_OK", or a subset thereof; one per invocation
 * 
 * The proper way to use this function, is:
 * 
 *     static void
 *     print_unsigned(libsyscalls_symbol_printer_function *function,
 *                    LIBSYSCALLS_SYMBOL_PRINTER_DATA *data,
 *                    unsigned long long int value, FILE *output)
 *     {
 *             const char *sym, *prefix = "";
 *             char format[] = "%s%llu";
 *             char *fallback = strchr(format, '\0') - 1;
 *             do {
 *                     sym = (*function)(data, &value, &fallback);
 *                     if (!sym)
 *                             break;
 *                     fprintf(output, "%s%s", prefix, sym);
 *                     prefix = "|";
 *             } while (value);
 *             if (value || !*prefix)
 *                     fprintf(output, format, prefix, value);
 *     }
 * 
 * @param  data          Data passed to the function (which that function
 *                       has been paired with for the paramter/return),
 *                       which it may require to known exactly what to do
 * @param  valuep        The caller set a variable to the value pass in to
 *                       the system call parameter (or the system call's
 *                       return value), the value if any extract symbol
 *                       will removed from from the variable. If the function
 *                       return NULL, this value can be 0, in which case all
 *                       values have been extract, otherwise (which it is not
 *                       0) there is some value (either invalid or not known
 *                       to the library) that shall must be printed manually
 *                       by the application (see `fallback_out` parameter).
 *                       Note that, if the value 0 has a name, this function
 *                       never return NULL if the variable reaches 0, instead
 *                       it will repeated return the name of that value.
 * @param  fallback_out  The caller set a variable to 0 and pointer to it,
 *                       when this function return NULL, the variable MAY
 *                       (even before that) have been set to 'x', 'o', or
 *                       'd', indicating a suggestion how any value left
 *                       over in `*valuep` shall be displayed: 'x' for in
 *                       hexadecimal, 'o' for octal, and 'd' for decimal
 *                       (signness depends on the system call parameter's
 *                       type's (or as the case may be, the system call's
 *                       return type) signness).
 * @return               The name of some value in `*valuep`, or `NULL` if
 *                       none was found. The returned string may be stored
 *                       in `data` and those override at the next call.
 */
typedef const char *libsyscalls_symbol_printer_function(LIBSYSCALLS_SYMBOL_PRINTER_DATA *data,
                                                        unsigned long long int *valuep,
                                                        char *fallback_out);

/**
 * Information about a system call parameter or return value
 */
struct libsyscalls_syscall_type_info {
	/**
	 * Function for extracting names values from a variable
	 */
	libsyscalls_symbol_printer_function *function;

	/**
	 * First argument to pass to `.function`
	 */
	LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;

	/**
	 * The data type used for the parameter or return value
	 * in the specific invocation of the system call
	 *
	 * If set to LIBSYSCALLS_TYPE_VOID for an optional
	 * parameter, that parameter was not used
	 */
	enum_libsyscalls_datatype type;

	char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char),
	                                sizeof(enum_libsyscalls_datatype)/sizeof(char) + 1)];
	unsigned char : CHAR_BIT - 1;

	/**
	 * Only used for the return value
	 * 
	 * Same as `.expect_zero` in `struct libsyscalls_syscall_abi`,
	 * however if 0 in `struct libsyscalls_syscall_abi`, it can
	 * still be 1 here if if it is determined that for the specificly
	 * used system call arguments, the system call shall always
	 * return 0 (or not return) or an error
	 */
	unsigned char expect_zero : 1;
};

/**
 * System call information tweak for the arguments passed
 * to the system call, as well as information about how
 * to print named values in the arguments and return
 */
struct libsyscalls_syscall_display_info {
	/**
	 * The size of this structure, this can be used
	 * by the application to test what is available
	 * in the case it may have compiled against a
	 * newer version than used in the version of the
	 * library the application is linked with
	 * 
	 * Data is stored beyond this, do not try to make
	 * a copy; that will not go well
	 */
	size_t size;

	/**
	 * Information about each system call parameter
	 *
	 * All positive integer within [0, .max_argument_count]
	 * for the `struct libsyscalls_syscall_abi` are valid,
	 * but no index beyond `.max_argument_count` is valid
	 */
	struct libsyscalls_syscall_type_info *params;

	/**
	 * Information about the system call's return value
	 */
	struct libsyscalls_syscall_type_info *retvalue;
};

/**
 * Signed number representation
 */
enum libsyscalls_datatype_sign_representation {
	/**
	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN
	 * or LIBSYSCALLS_TYPE_DYNAMIC
	 */
	LIBSYSCALLS_SIGN_UNDETERMINED,

	/**
	 * Two's complement
	 * 
	 * -x is ~x + 1, -0 is +0
	 */
	LIBSYSCALLS_SIGN_TWOS_COMPLEMENT,

	/**
	 * One's cmplement
	 * 
	 * -x is ~x, -0 is not +0
	 */
	LIBSYSCALLS_SIGN_ONES_COMPLEMENT,

	/**
	 * Sign–magnitude
	 * 
	 * -x is (x | most significant bit), -0 is not +0
	 */
	LIBSYSCALLS_SIGN_SIGN_MAGNITUDE,

	/**
	 * Excess-K, with K being (unsigned maximum + 1)/2
	 * 
	 * 0 is represented with just the most significant bit set,
	 * any offset from 0 is added to this value, i.e., x is
	 * represented by ((unsigned maximum + 1)/2 + x); -0 is +0
	 */
	LIBSYSCALLS_SIGN_EXCESS_HALF
};

/**
 * Data type usage annotation
 */
enum libsyscalls_datatype_annotation {
	/**
	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN or
	 * LIBSYSCALLS_TYPE_DYNAMIC
	 */
	LIBSYSCALLS_ANNOTATION_UNDETERMINED,

	/**
	 * The value does not have usage annotation
	 */
	LIBSYSCALLS_ANNOTATION_NONE,

	/**
	 * The value represents an operating system signal
	 * (e.g. SIGKILL)
	 * 
	 * This affords the application the opportunity
	 * to print more detail information about a signal
	 * (such as when it is used, whether it is a
	 * realtime signal, default action, whether it
	 * can be caught, and what its normal usage is)
	 */
	LIBSYSCALLS_ANNOTATION_SIGNAL,

	/**
	 * The value represents a file descriptor
	 * 
	 * This affords the application the opportunity
	 * toprint file information (such as file name,
	 * address, file type, and offset)
	 */
	LIBSYSCALLS_ANNOTATION_FD,

	/**
	 * The value represents a file descriptor or a
	 * special value for a known file such as AT_FDCWD
	 * 
	 * This affords the application the opportunity
	 * to print file information (such as file name,
	 * address, file type, and offset)
	 */
	LIBSYSCALLS_ANNOTATION_ATFD
};

/**
 * Register-split/struct field-split information
 * for a data type
 */
enum libsyscalls_datatype_section {
	/**
	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN
	 * or LIBSYSCALLS_TYPE_DYNAMIC
	 */
	LIBSYSCALLS_SECTION_UNDETERMINED,

	/**
	 * The whole value is represented
	 * 
	 * The value is contained within a single parameter
	 */
	LIBSYSCALLS_SECTION_WHOLE,

	/**
	 * This whether a data type represents a half section
	 * of larger data type
	 * 
	 * @param   S:enum libsyscalls_datatype_section
	 *                  The data type section information
	 * 
	 * @return  :int    Whether the larger that type was
	 *                  split into two halves
	 */
#define LIBSYSCALLS_IS_SECTION_HALF(S)\
	(((S) >= LIBSYSCALLS_SECTION_UPPER_HALF) &&\
	 ((S) <= LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF))

	/**
	 * The most significant half of the value is represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0xFFFFFFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_LOWER_HALF)
	 */
	LIBSYSCALLS_SECTION_UPPER_HALF,

	/**
	 * The least significant half of the value is represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0x00000000FFFFFFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_UPPER_HALF)
	 */
	LIBSYSCALLS_SECTION_LOWER_HALF,

	/**
	 * The second most and second least significant quarters
	 * of the value represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0x0000FFFFFFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_OUTER_HALF)
	 */
	LIBSYSCALLS_SECTION_INNER_HALF,

	/**
	 * The most and least significant quarters of the value
	 * represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0xFFFF00000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_INNER_HALF)
	 */
	LIBSYSCALLS_SECTION_OUTER_HALF,

	/**
	 * The second most and least significant quarters of the
	 * value represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0x0000FFFF0000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF)
	 */
	LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF,

	/**
	 * The most and second least significant quarters of the
	 * value represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0xFFFF0000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF)
	 */
	LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF,

	/**
	 * The bytes that would be indexed (starting from 0) with
	 * an even number in big endian (how humans write numbers)
	 * are represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0x00FF00FF00FF00FF if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF)
	 */
	LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF,

	/**
	 * The bytes that would be indexed (starting from 0) with
	 * an odd number in big endian (how humans write numbers)
	 * are represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 32-bits —
	 * 0xFF00FF00FF00FF00 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with another neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF)
	 */
	LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF,

	/**
	 * This whether a data type represents a quarter section
	 * of larger data type
	 * 
	 * @param   S:enum libsyscalls_datatype_section
	 *                  The data type section information
	 * 
	 * @return  :int    Whether the larger that type was
	 *                  split into four quarters
	 */
#define LIBSYSCALLS_IS_SECTION_QUARTER(S)\
	(((S) >= LIBSYSCALLS_SECTION_UPPER_QUARTER) &&\
	 ((S) <= LIBSYSCALLS_SECTION_LOWER_QUARTER))

	/**
	 * The most significant quarter of the value is represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 16-bits —
	 * 0xFFFF000000000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with three neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,
	 * a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
	 * a LIBSYSCALLS_SECTION_LOWER_QUARTER)
	 */
	LIBSYSCALLS_SECTION_UPPER_QUARTER,

	/**
	 * The second most significant quarter of the value is represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 16-bits —
	 * 0x0000FFFF00000000 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with three neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
	 * a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER, and
	 * a LIBSYSCALLS_SECTION_LOWER_QUARTER)
	 */
	LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,

	/**
	 * The least most significant quarter of the value is represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 16-bits —
	 * 0x00000000FFFF0000 if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with three neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
	 * a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
	 * a LIBSYSCALLS_SECTION_LOWER_QUARTER)
	 */
	LIBSYSCALLS_SECTION_LOWER_MID_QUARTER,

	/**
	 * The least significant quarter of the value is represented
	 * 
	 * Example: if the data type is 64-bits, the value stored
	 * in parameter whose type was queried is just 16-bits —
	 * 0x000000000000FFFF if the whole value is 0xFFFFFFFFFFFFFFFF,
	 * — and most combined with three neighbouring parameter
	 * (a LIBSYSCALLS_SECTION_UPPER_QUARTER,
	 * a LIBSYSCALLS_SECTION_UPPER_MID_QUARTER, and
	 * a LIBSYSCALLS_SECTION_LOWER_MID_QUARTER)
	 */
	LIBSYSCALLS_SECTION_LOWER_QUARTER

	/**
	 * Get the number of registers/fields the data type
	 * was split into
	 * 
	 * @param   S:enum libsyscalls_datatype_section
	 *                  The data type section information
	 * 
	 * @return  :unsigned int
	 *                  The number registers/fields the data
	 *                  type was split into; invalid if `S`
	 *                  is LIBSYSCALLS_SECTION_UNDETERMINED
	 */
#define LIBSYSCALLS_GET_SECTION_FRACTION(S)\
	(LIBSYSCALLS_IS_SECTION_HALF(S) ? 2U :\
	 LIBSYSCALLS_IS_SECTION_QUARTER(S) ? 4U : 1U)
};


/**
 * Macro for enumerating type-split sections
 * 
 * The numbers are stored in `enum libsyscalls_datatype_section`
 * 
 * @param  X:macro(NAME, ...)  Macro that expands, will a number of arguments:
 *                             1) The name of the enum value
 *                             2) 1 if the section is both compatible with 16-bit
 *                                integers and is the first section with its
 *                                pattern of covered bits for 16-bit integers,
 *                                0 otherwise
 *                             3) Mask of bits the section covers for a 16-bit integer
 *                             4) 1 if the section is both compatible with 32-bit
 *                                integers and is the first section with its
 *                                pattern of covered bits for 32-bit integers,
 *                                0 otherwise
 *                             5) Mask of bits the section covers for a 32-bit integer
 *                             6) 1 if the section is both compatible with 64-bit
 *                                integers and is the first section with its
 *                                pattern of covered bits for 64-bit integers,
 *                                0 otherwise
 *                             7) Mask of bits the section covers for a 64-bit integer
 *                             Arguments 3, 5, and 7 are `0` when the section is not
 *                             compatible with the data type and otherwise a `0x`
 *                             prefixed uppercase hexadecimal number without any type
 *                             suffix.
 *                             Addition arguments may be added in the future.
 * @param  D:code              Macro that expands between each expansion of X
 * 
 * The primary purpose of the existance of this macro
 * is to ease implementation of the library; it will
 * probably not disappear (no promises)
 */
#define LIBSYSCALLS_LIST_SECTIONS(X, D)\
	X(LIBSYSCALLS_SECTION_WHOLE,                 1, 0xFFFF, 1, 0xFFFFFFFF, 1, 0xFFFFFFFFFFFFFFFF) D\
	X(LIBSYSCALLS_SECTION_UPPER_HALF,            1, 0xFF00, 1, 0xFFFF0000, 1, 0xFFFFFFFF00000000) D\
	X(LIBSYSCALLS_SECTION_LOWER_HALF,            1, 0x00FF, 1, 0x0000FFFF, 1, 0x00000000FFFFFFFF) D\
	X(LIBSYSCALLS_SECTION_INNER_HALF,            0, 0,      1, 0x00FFFF00, 1, 0x0000FFFFFFFF0000) D\
	X(LIBSYSCALLS_SECTION_OUTER_HALF,            0, 0,      1, 0xFF0000FF, 1, 0xFFFF00000000FFFF) D\
	X(LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF, 0, 0,      1, 0x00FF00FF, 1, 0x0000FFFF0000FFFF) D\
	X(LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF,  0, 0,      1, 0xFF00FF00, 1, 0xFFFF0000FFFF0000) D\
	X(LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF,    0, 0,      0, 0x00FF00FF, 1, 0x00FF00FF00FF00FF) D\
	X(LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF,     0, 0,      0, 0xFF00FF00, 1, 0xFF00FF00FF00FF00) D\
	X(LIBSYSCALLS_SECTION_UPPER_QUARTER,         0, 0,      1, 0xFF000000, 1, 0xFFFF000000000000) D\
	X(LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,     0, 0,      1, 0x00FF0000, 1, 0x0000FFFF00000000) D\
	X(LIBSYSCALLS_SECTION_LOWER_MID_QUARTER,     0, 0,      1, 0x0000FF00, 1, 0x00000000FFFF0000) D\
	X(LIBSYSCALLS_SECTION_LOWER_QUARTER,         0, 0,      1, 0x000000FF, 1, 0x000000000000FFFF)


/**
 * Information on how an instance of data type is to be parsed
 * 
 * Data types are usually either signed or unsigned, but there
 * are a few exceptions: LIBSYSCALLS_TYPE_UNKNOWN and
 * LIBSYSCALLS_TYPE_DYNAMIC are described as both signed and
 * unsigned as their signness is unknown and could be either,
 * or neither, which brings us to the next exception: some
 * data types are neither signed nor unsigned; these are types
 * that are not numerical, i.e. non-values (LIBSYSCALLS_TYPE_NO_RETURN
 * and LIBSYSCALLS_TYPE_VOID), memory addresses
 * (LIBSYSCALLS_TYPE_MEMORY_ADDRESS) and textual types
 * (LIBSYSCALLS_TYPE_CHAR, LIBSYSCALLS_TYPE_STRING, and
 * LIBSYSCALLS_TYPE_STRINGS_THEN_NULL), as well as arrays of
 * such types (including LIBSYSCALLS_TYPE_BUFFER and
 * LIBSYSCALLS_TYPE_BUFFER_UNKNOWN_FILL), and finally bitset
 * arrays (currently only LIBSYSCALLS_TYPE_FD_SET)
 */
struct libsyscalls_datatype_description {
	/**
	 * The number of bits used for the represented section
	 * of the data type
	 * 
	 * 0 for LIBSYSCALLS_TYPE_NO_RETURN and LIBSYSCALLS_TYPE_VOID
	 * 
	 * if .section is LIBSYSCALLS_SECTION_WHOLE, this is the
	 * number of bits in the entire data type, otherwise the data
	 * type may have been split (LIBSYSCALLS_SECTION_UNDETERMINED,
	 * guaranteed to be split otherwise) and this value is just
	 * the number of bits stored in the register or struct field
	 * 
	 * It is possible for the data type to contain unused dummy
	 * bits in order to make it a power of 2 or a multiple of
	 * a smaller data type. For example, on x86, `long double`
	 * uses 128 bits, even though the value only uses 80 bits.
	 * The dummy bits are included in the value on this field.
	 */
	unsigned width_in_bits;

	/**
	 * The size (in number of elements) of the array the data type
	 * is used in, or 1 if the data type was not an array or
	 * 0 if the array size is determined by another parameter/field
	 */
	unsigned array_size;

	/**
	 * Only used if .array_size is 0
	 * 
	 * The position of the array's size in the parameter/field list
	 * relative to the array, e.g. 1 for the next parameter/field
	 * or -1 for the previous parameter/field
	 * 
	 * If 0, use .absolute_position_of_array_size instead
	 */
	signed relative_position_of_array_size : 5;

	/**
	 * Only used if .array_size is 0
	 * 
	 * The position of the array's size in the parameter/field list,
	 * indexed starting from 0
	 * 
	 * If -1, use .relative_position_of_array_size instead
	 */
	signed absolute_position_of_array_size : 5;

	/**
	 * Only used if .array_size is 0
	 * 
	 * Assuming the kernel writes into the array, if 1, the number
	 * of elements written to the array (starting from its beginning)
	 * is writting into the array size parameter/field if it is
	 * marked as an output parameter/field and return otherwise;
	 * if 0, the number of bits written must be infered from its
	 * contents, e.g. via null byte termination (how this is done
	 * depends on the system call)
	 */
	unsigned fill_is_known : 1;

	/**
	 * Whether the data type is signed
	 */
	unsigned is_signed : 1;

	/**
	 * Whether the data type is unsigned
	 */
	unsigned is_unsigned : 1;

	/**
	 * Only used if .is_signed is 1 and .sign_representation
	 * is not LIBSYSCALLS_SIGN_UNDETERMINED
	 * 
	 * This value can be inferred from .sign_representation;
	 * its 1 if the data type's minimum value is the negative
	 * of its maximum value (which also means that -0 and +0
	 * are distinct), and 0 otherwise, which means that the
	 * minimum value is the negative of (the minimum value + 1)
	 * (it also means that -0 and +0 are the identical)
	 */
	unsigned min_is_minus_max : 1;

	int padding__ : LIBSYSCALLS_PAD_(sizeof(int)/sizeof(char)*CHAR_BIT,
	                                 2*5 + 4*1);

	/**
	 * Only used if .is_signed is 1
	 *
	 * How signed numbers are represented
	 */
	enum libsyscalls_datatype_sign_representation sign_representation : 8;

	/**
	 * Additional information about what the value represents
	 */
	enum libsyscalls_datatype_annotation annotation : 8;

	/**
	 * What part of the value is stored in the instance
	 */
	enum libsyscalls_datatype_section section : 16;

	/**
	 * This is a ~0 terminated array — but, it can also
	 * be terminated by the end of the array — describing
	 * the order of the bytes the the data type
	 *
	 * The lowest non-zero values contains the width of
	 * a byte (in bytes), however no such value exists
	 * in this array if the data type is just one byte
	 * (or none)
	 * 
	 * For each unsigned byte in the data type, indexed
	 * I from 0, it shall be shifted left .byteorder[i]
	 * bits; the bitwise OR of the results is the
	 * unsigned value used in the instance of the data type
	 *
	 * Data types for register-splits/struct field-splits
	 * ARE NOT shifted, there is always a value in
	 * .byteorder that is 0, unless .byteorder[0] is ~0
	 *
	 * To avoid problems checking for ~0, use the
	 * LIBSYSCALLS_IS_BYTEORDER_END macro; please also be
	 * aware that both the type and length can change in
	 * the future: do not assume it's `unsigned char`,
	 * and do not assume it has 32 elements, do not only
	 * `LIBSYSCALLS_IS_BYTEORDER_END` to detect ~0, but
	 * also check that no more than
	 * `sizeof(x.byteorder) / sizeof(*x.byteorder)`
	 * elements are read (where x is the instance of the
	 * structure) (you should definitely have your own
	 * macro for that one). As an alternative to
	 * `LIBSYSCALLS_IS_BYTEORDER_END`, you may use the
	 * LIBSYSCALLS_IS_BYTEORDER_END_AT macro
	 */
	unsigned char byteorder[32];

	/**
	 * Test whether a value in `struct
	 * libsyscalls_datatype_description.byteorder`
	 * marks the end of the byteorder's shift value
	 * (testing that the value is ~0). Using this
	 * macro helps avoiding bugs caused by integer
	 * type promotion.
	 * 
	 * @param   SHIFT  The value to test `struct
	 *                 libsyscalls_datatype_description.byteorder`
	 * @return  :int   Whether the value is ~0
	 */
#ifdef UINTMAX_C
# define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\
	(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(UINTMAX_C(1),\
		struct libsyscalls_datatype_description, byteorder[0])))
#else
# define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\
	(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(1ULL,\
		struct libsyscalls_datatype_description, byteorder[0])))
#endif

	/**
	 * Test whether `DESC->byteorder[INDEX]` is
	 * the (post-last) end of `DESC->byteorder`
	 */
#define LIBSYSCALLS_IS_BYTEORDER_END_AT(DESC, INDEX)\
	((size_t)(INDEX) == sizeof((DESC)->byteorder) / sizeof(*(DESC)->byteorder) || \
	 LIBSYSCALLS_IS_BYTEORDER_END((DESC)->byteorder[INDEX]))
};

/**
 * Details about of field in a `struct` or `union`
 */
struct libsyscalls_structure_field {
	/**
	 * The name of the field, or `NULL` if anonymous
	 */
	const char *name;

	/**
	 * The fields data type
	 */
	enum_libsyscalls_datatype type : 16;

	/**
	 * The number bytes from the data type that is used
	 * for the field, 0 if the field is not a bit field
	 */
	unsigned short int bitlength : 16;

	/**
	 * If 1, the field is expected to be populated
	 * before the system call is entered
	 */
	unsigned short int input_field : 1;

	/**
	 * If 1, the field is expected to be populated
	 * by the system call unless it returns an error
	 */
	unsigned short int output_field : 1;

	/**
	 * If 1, the field is expected to be populated
	 * by the system call provided that it returns
	 * an error
	 */
	unsigned short int error_field : 1;

	/**
	 * If 1, if the field's value can be resolved
	 * into a symbolic string by the library
	 */
	unsigned short int symbolic_field : 1;

	/**
	 * Only used with .input_field set to 1
	 * 
	 * If 1, it is probably not an error if the
	 * field is partially initialised as long as all
	 * its memory is allocated
	 * 
	 * In the case that a field is split using for
	 * example one field with the type
	 * LIBSYSCALLS_TYPE_UINT64_FRONT_32 and another
	 * field with the type
	 * LIBSYSCALLS_TYPE_UINT64_BACK_32 (these two
	 * (for some split types, their may be more than
	 * two fields) fields will have the same name),
	 * it is one is partially initialised and the
	 * other completely uninitialised. Generally,
	 * as long as at least one of the parts are
	 * partially initialised, the application should
	 * not, unless it has more detailed knowledge
	 * about the system call, assume that there is
	 * an error. This happens because kernel's version
	 * of the library uses a scalar field, where as
	 * the userspace version (usually libc's version)
	 * uses a union of differently sized field. It
	 * is not necessarily the case that it can be
	 * known which field in the union is used: for
	 * example in epoll_ctl(2), it is completely up
	 * to the application, and the application has
	 * no way of telling the kernel which is used,
	 * and the kernel will in epoll_wait(2) simply
	 * return the union's value as it was set, meaning
	 * that some bits may be effectively uninitialised.
	 * Even if the field is complete uninitialised,
	 * it may still be the case that this is not an
	 * error, however, it probably is an error; for
	 * example in the case of epoll(7), it is completely
	 * possible, albeit unlikely (because it's silly),
	 * that the user calls epoll_ctl(2) without the
	 * `.data` field set, because it doesn't look at
	 * in when epoll_wait(2) returns, but insteads
	 * just does unblocking I/O one each file
	 * descriptor it has added to the epoll(7).
	 */
	unsigned short int partial_init_ok : 1;

	/**
	 * If 1, the field is a pointer that the reads from
	 * 
	 * Note that there are types that fundamentally are
	 * pointers (such as strings), for these, this bit
	 * is not set unless it is a pointer to a string
	 *
	 * This field may always 0 when .input_field is 0
	 */
	unsigned short int input_pointer : 1;

	/**
	 * If 1, the field is a pointer that the writes to
	 * 
	 * Note that there are types that fundamentally are
	 * pointers (such as strings), for these, this bit
	 * is not set unless it is a pointer to a string
	 */
	unsigned short int output_pointer : 1;

	/**
	 * If 1, it has been determined that the field is
	 * not being used (usually because that it's not
	 * the active field in a `union` or because a
	 * flag somewhere in the `struct` is either set or
	 * cleared)
	 */
	unsigned short int unused : 1;

	unsigned short int padding1__ : 16 - (8*1);

#if LIBSYSCALLS_IS_PADDING_REQUIRED_(3, 16, LIBSYSCALLS_POINTER_BIT_)
# if !LIBSYSCALLS_CAN_ALIGN_(3, 16, CHAR_BIT)
#  error Sorry, we require that the a byte is no longer than (3*16) bits while evenly dividing (3*16) bits
# endif
	char padding2__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), (3*16)/CHAR_BIT)];
#endif

	/**
	 * Data type description
	 * 
	 * The application is free to make changes, however,
	 * however the pointers themselves must not be touched
	 */
	union {
		/**
		 * Description to use if `.type` refers to a
		 * `struct` or `union`; that is, if
		 * `(.type & ~LIBSYSCALLS_TYPEBITSMASK) >=
		 * LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS`
		 */
		struct libsyscalls_structure_description *structure;

		/**
		 * Description to use if `.type` does not refer
		 * to a `struct` or `union`; that is, if
		 * `(.type & ~LIBSYSCALLS_TYPEBITSMASK) <
		 * LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS`
		 */
		struct libsyscalls_datatype_description *nonstructure;
	} type_description;
};

/**
 * Details about a `struct` or `union`
 */
struct libsyscalls_structure_description {
	/**
	 * The alignment, in bits, that shall
	 * be used for the data type; never 0
	 */
	unsigned short int alignment : 16;

	/**
	 * The size of the data type, in bits
	 * 
	 * If 0, the data type's size is flexible and its
	 * size is determined by its content but not enough of
	 * it was provided to determine its size.
	 * .relative_position_of_size or .absolute_position_of_size
	 * may or may not be useful to determine the size of the
	 * data type, if .size is 0 (and .array_size is 1, which
	 * it in such case must be).
	 */
	unsigned short int size : 16;

	/**
	 * The number of fields in the `struct`/`union`
	 */
	unsigned short int num_fields : 14;

	/**
	 * If 1, the data type is a `union`,
	 * if 0, the data type is a `struct`
	 */
	unsigned short int is_union : 1;

	/**
	 * Only used if .array_size is 0
	 * 
	 * Assuming the kernel writes into the array, if 1, the number
	 * of elements written to the array (starting from its beginning)
	 * is writting into the array size parameter/field if it is
	 * marked as an output parameter/field and return otherwise;
	 * if 0, the number of bits written must be infered from its
	 * contents, e.g. via null byte termination (how this is done
	 * depends on the system call)
	 */
	unsigned short int fill_is_known : 1;

	/**
	 * The size (in number of elements) of the array the data type
	 * is used in, or 1 if the data type was not an array or
	 * 0 if the array size is determined by another parameter/field
	 * 
	 * If 1, .relative_position_of_size will be set to 0,
	 * and .absolute_position_of_size -1, however if that is not
	 * the case and this field is set to 1, then .size (which may
	 * or may not be 0 at this point) is determined by the indicated
	 * parameter
	 */
	unsigned short int array_size : 16;

	/**
	 * The position of the array's or structure's size in the
	 * parameter/field list relative to the array/structure,
	 * e.g. 1 for the next parameter/field or -1 for the previous
	 * parameter/field
	 * 
	 * If 0, use .absolute_position_of_size instead
	 */
	signed short int relative_position_of_size : 16;

	/**
	 * The position of the array's or structure's size in the
	 * parameter/field list, indexed starting from 0
	 * 
	 * If -1, use .relative_position_of_size instead
	 */
	signed short int absolute_position_of_size : 16;

	/**
	 * This is used internally by `libsyscalls_get_struct_display_info`
	 * to find out how values ought to be printed to be both human
	 * and machines friendly (symbolic names are indeed easier for
	 * the application to deal with as their values can depend on
	 * the architecture)
	 * 
	 * If this is value is 0, `libsyscalls_get_struct_display_info`
	 * will not be able to provide any useful information, which
	 * would either be because everything is provided here (in
	 * `struct libsyscalls_structure_description`) or because the
	 * library hasn't yet added full support for the structure
	 */
	LIBSYSCALLS_SYMBOL_PRINTER symbol_printer : 16;

#if LIBSYSCALLS_IS_PADDING_REQUIRED_(7, 16, LIBSYSCALLS_POINTER_BIT_)
# if !LIBSYSCALLS_CAN_ALIGN_(7, 16, CHAR_BIT)
#  error Sorry, we require that the a byte is no longer than (7*16) bits while evenly dividing (7*16) bits
# endif
	char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char),
	                                (7*16)/CHAR_BIT)];
#endif

	/**
	 * Information about each field in the `struct`/`union`
	 */
	struct libsyscalls_structure_field fields[LIBSYSCALLS_FLEXABLE_OR_NFIELDS_];
};


/**
 * Return a description of a libsyscalls error
 * 
 * @param   error  The libsyscalls error
 * @return         Description of the error, the first
 *                 character will be in uppercase
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__const__, __returns_nonnull__, __warn_unused_result__)
const char *
libsyscalls_strerror(enum libsyscalls_error error);


/**
 * Print a line with a description of a
 * libsyscalls error to standard error
 * 
 * @param   prefix  Unless NULL or the empty string, the description
 *                  will be prefixed with this string followed by ": "
 * @param   error   The libsyscalls error
 */
void
libsyscalls_perror(const char *prefix, enum libsyscalls_error err);


/**
 * Get the valid range system call numbers
 * 
 * @param  os       The operating system the range shall valid for
 * @param  arch     The architecture the range shall valid for
 * @param  min_out  Output parameter for the lowest used
 *                  system call number (may be NULL)
 * @param  max_out  Output parameter for the highest used
 *                  system call number (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK        - On success
 *          LIBSYSCALLS_E_OSNOSUP   - The library is not compiled with support for
 *                                    the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
 *                                    the selected architecture (`arch`) on the
 *                                    selected operating system (`os`)
 * 
 * This function always fails if the selected combination
 * of operating system (`os`) and architecture (`arch`) is
 * unsupported
 * 
 * Beware that range is used system call numbers are [*min_out, *max_out]
 * (not [*min_out, *max_out - 1]) but there may still be numbers within
 * this range that does not correspond to a system call
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
                            __access__(__write_only__, 3),
                            __access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_syscall_range(enum libsyscalls_os os, enum libsyscalls_arch arch,
                              long long int *min_out, long long int *max_out);


/**
 * Get the description of a system call
 * 
 * @param  os           The operating system the range shall valid for
 * @param  arch         The architecture the range shall valid for
 * @param  syscall_nr   The system call's number
 * @param  syscall_out  Output parameter for the system call description
 *                      (the argument may be NULL, *syscall_out will
 *                      never be set to NULL)
 * 
 * @return  LIBSYSCALLS_E_OK            - On success
 *          LIBSYSCALLS_E_OSNOSUP       - The library is not compiled with support for
 *                                        the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP     - The library is not compiled with support for
 *                                        the selected architecture (`arch`) on the
 *                                        selected operating system (`os`)
 *          LIBSYSCALLS_E_NOSUCHSYSCALL - `syscall_nr` does not correspond to a known
 *                                        system call for the selected architecture (`arch`)
 *                                        on the selected operating system (`os`)
 * 
 * This function always fails if the selected combination
 * of operating system (`os`) and architecture (`arch`) is
 * unsupported
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
                            __access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_syscall(enum libsyscalls_os os, enum libsyscalls_arch arch,
                        long long int syscall_nr,
                        const struct libsyscalls_syscall **syscall_out);


/**
 * Get the system call errors defined by an operating system
 * 
 * If an error has multiple names, it is only listed once
 * and the listed name is arbitrary
 * 
 * The returned listing will be sorted by the error numbers
 * in ascending order
 * 
 * @param  os              The operating system whose errors shall be returned
 * @param  arch            The architecture the error numbers shall be valid for
 * @param  errors_out      Output parameter for the error list
 *                         (may be NULL, never filled with NULL)
 * @param  num_errors_out  Output parameter for the number of errors returned
 *                         in `*errors_out` (may be NULL) (if `errors_out` is NULL,
 *                         the number that would be returned is stored)
 * @param  are_signed_out  Output parameter for whether the error numbers are
 *                         signed (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK        - On success
 *          LIBSYSCALLS_E_OSNOSUP   - The library is not compiled with support for
 *                                    the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for
 *                                    the selected architecture (`arch`) on the
 *                                    selected operating system (`os`)
 *          LIBSYSCALLS_E_NOERRORS  - The operating system does not use named error numbers
 *
 * This function will always fail if the operating system (`os`)
 * is not supported, however it may be successful even if the
 * architecture (`arch`) not supported
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3),
                            __access__(__write_only__, 4),
                            __access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_get_syscall_errors(enum libsyscalls_os os, enum libsyscalls_arch arch,
                               const struct libsyscalls_named_number **errors_out,
                               size_t *num_errors_out, int *are_signed_out);


/**
 * Get the system signals defined by an operating system
 * 
 * If a signal has multiple names, it is only listed once
 * and the listed name is arbitrary
 * 
 * The returned listing will be sorted by the signal
 * numbers in ascending order
 * 
 * @param  os               The operating system whose errors shall be returned
 * @param  arch             The architecture the error numbers shall be valid for
 * @param  signals_out      Output parameter for the signal list
 *                          (may be NULL, never filled with NULL)
 * @param  num_signals_out  Output parameter for the number of signals returned
 *                          in `*signals_out` (may be NULL) (if `signals_out` is
 *                          NULL, the number that would be returned is stored)
 * @param  are_signed_out   Output parameter for whether the signal numbers are
 *                          signed (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK         - On success
 *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for
 *                                     the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for
 *                                     the selected architecture (`arch`) on the
 *                                     selected operating system (`os`)
 *          LIBSYSCALLS_E_NOSIGNALS  - The operating system does not use named signal numbers
 *
 * This function will always fail if the operating system (`os`)
 * is not supported, however it may be successful even if the
 * architecture (`arch`) not supported
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3),
                            __access__(__write_only__, 4),
                            __access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_get_signals(enum libsyscalls_os os, enum libsyscalls_arch arch,
                        const struct libsyscalls_named_number **signals_out,
                        size_t *num_signals_out, int *are_signed_out);


/**
 * Finds a named number in a sorted array by its signed number
 * 
 * @param   key   The signed number of the named number to find
 * @param   base  The array of named numbers, sorted in ascending
 *                order by their signed numbers
 * @param   n     The number of elements in `base`
 * @return        The element in `base` whose signed number is `key`,
 *                `NULL` if not found
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__,
                            __access__(__read_only__, 2, 3))
const struct libsyscalls_named_number *
libsyscalls_find_signed_named_number(signed long long int key,
                                     const struct libsyscalls_named_number *base, size_t n);


/**
 * Finds a named number in a sorted array by its unsigned number
 * 
 * @param   key   The unsigned number of the named number to find
 * @param   base  The array of named numbers, sorted in ascending
 *                order by their unsigned numbers
 * @param   n     The number of elements in `base`
 * @return        The element in `base` whose unsigned number is `key`,
 *                `NULL` if not found
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__,
                            __access__(__read_only__, 2, 3))
const struct libsyscalls_named_number *
libsyscalls_find_unsigned_named_number(unsigned long long int key,
                                       const struct libsyscalls_named_number *base, size_t n);


/**
 * Finds a named number in a sorted array by its number
 * 
 * @param   key        The number of the named number to find
 * @param   is_signed  Whether the numbers are signed
 * @param   base       The array of named numbers, sorted in ascending
 *                     order by their numbers
 * @param   n          The number of elements in `base`
 * @return             The element in `base` whose number is `key`,
 *                     `NULL` if not found
 * 
 * If `is_signed` is non-zero, `key` is reinterpreted (not cast) as a signed number;
 * thus it is important that if `key` uses all bits in `long long int`,
 * would be an error to take a `int`, reinterpret it as an `unsigned int`,
 * and input it to as `key` casting it to `unsigned long long int`; rather
 * an `int` must first be cast to `long long int`, and then reinterpreted
 * as a `unsigned long long int` before it is input as `key`. Using
 * `libsyscalls_find_signed_named_number` instead removes this complication
 * in such a senario.
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__,
                            __access__(__read_only__, 3, 4))
inline const struct libsyscalls_named_number *
libsyscalls_find_named_number(unsigned long long int key, int is_signed,
                              const struct libsyscalls_named_number *base, size_t n)
{
	signed long long int skey = *(signed long long int *)&key;
	return is_signed ? libsyscalls_find_signed_named_number(skey, base, n)
	                 : libsyscalls_find_unsigned_named_number(key, base, n);
}


/**
 * Get system call information tweak for the arguments passed
 * to the system call, as well as information about how to
 * print named values in the arguments and return
 * 
 * @param  os                 The operating system the system call was invoked on
 * @param  arch               The architecture the system call was invoked on
 * @param  syscall            The ABI of the system call (see libsyscalls_get_syscall)
 * @param  syscall_number     The system call's number
 * @param  syscall_arguments  The values store in register (as upon system call entry)
 *                            the used for the system call, in the order the registers
 *                            are used as system call arguments
 * @param  info_out           Output parameter for the additional system call information;
 *                            the caller responsible for deallocating the `*info_out`
 *                            with free(3) when it is no longer needed. Be aware that
 *                            `*info_out` will only be set when LIBSYSCALLS_E_OK is
 *                            returned.
 * 
 * @return  LIBSYSCALLS_E_OK         - On success
 *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for
 *                                     the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for
 *                                     the selected architecture (`arch`) on the
 *                                     selected operating system (`os`)
 *          LIBSYSCALLS_E_NOMEM      - Failed to allocate memory for `*info_out`
 *          LIBSYSCALLS_E_INVAL      - One of the arguments was NULL
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __nonnull__,
                            __access__(__read_only__, 3),
                            __access__(__write_only__, 6))
enum libsyscalls_error
libsyscalls_get_syscall_display_info(enum libsyscalls_os os, enum libsyscalls_arch arch,
                                     const struct libsyscalls_syscall_abi *syscall,
                                     long long int syscall_number,
                                     const unsigned long long int *syscall_arguments,
                                     struct libsyscalls_syscall_display_info **info_out);


/**
 * Get information on how an instance of non-struct, non-union
 * data type is to be parsed
 * 
 * Do not use for data types inside structures,
 * instead, use `.type_description.nonstructure`
 * in the structure's field, as it may contain
 * important adjustments
 * 
 * @param  os               The operating system the data type is used on
 * @param  arch             The architecture the data type is used on
 * @param  datatype         The data type, `LIBSYSCALLS_TYPE_DYNAMIC` can
 *                          be used to get the size of the registers used
 *                          as system call parameters
 * @param  description_out  Output parameter for the type description
 * 
 * @return  LIBSYSCALLS_E_OK         - On success
 *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for
 *                                     the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for
 *                                     the selected architecture (`arch`) on the
 *                                     selected operating system (`os`)
 *          LIBSYSCALLS_E_INVAL      - `datatype` is not a valid data type
 *          LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected
 *                                     operating system (`os`) or architecture (`arch`)
 *          LIBSYSCALLS_E_ISSTRUCT   - `datatype` represents a structure or union,
 *                                     or an array of a structure or union
 * 
 * The function may complete successfully for some data
 * types even if it for other data types would return
 * LIBSYSCALLS_E_OSNOSUP or LIBSYSCALLS_E_ARCHNOSUP
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
                            __access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_arch arch,
                                     enum libsyscalls_datatype datatype,
                                     struct libsyscalls_datatype_description *description_out);


/**
 * Get the alignment used for or a scalar integer data type
 * 
 * This function does not discriminate between optimal and mandatory
 * alignment; some CPUs operate on misalign data for some types,
 * whereas other CPUs cannot, but even if it can operate on misalign
 * data it will be less efficient. This function returns (into
 * `*alignment_out` the optional (default) alignment even there is
 * a mandatory alignment that is smaller. As a caveat, the operating
 * system may proscribe an multiple of the optimal alignment
 * (usually this would be the size of the data type instead of the
 * optimal alignment), in such cases, that proscribed alignment will
 * be returned instead.
 * 
 * @param  os             The operating system the data type is used on
 * @param  arch           The architecture the data type is used on
 * @param  width_in_bits  The width of the integer, in bits
 * @param  alignment_out  Output parameter for the alignment, in bits
 *                        (may be NULL, will never be filled with 0)
 * 
 * @return  LIBSYSCALLS_E_OK         - On success
 *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for
 *                                     the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for
 *                                     the selected architecture (`arch`) on the
 *                                     selected operating system (`os`)
 *          LIBSYSCALLS_E_INVAL      - `width_in_bits` is 0
 *          LIBSYSCALLS_E_NOSUCHTYPE - The selected architecture (`arch`) does not
 *                                     support any integer width the specified
 *                                     width (`width_in_bits`), or the operating
 *                                     system (`os`) does not support the data type
 *                                     (that would only be the case if the data type
 *                                     uses a new register that must be specifically
 *                                     supported in the operating system's context
 *                                     switching)
 * 
 * The function may complete successfully even if out ought to
 * return LIBSYSCALLS_E_ARCHNOSUP, in such cases, the result
 * is indeed reliable
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
                            __access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_get_integer_alignment(enum libsyscalls_os os, enum libsyscalls_arch arch,
                                  unsigned width_in_bits, unsigned *alignment_out);


/**
 * Parse a string of bits as a signed integer
 * 
 * In case `representation` is LIBSYSCALLS_SIGN_UNDETERMINED,
 * the bits are parsed as an unsigned integer
 * 
 * @param  value_in        The bits to parse as a signed integer
 * @param  representation  The sign representation used on the interger
 * @param  bits            The number of bits in the integer
 * @param  value_out       Output parameter for the absolute value
 *                         of the signed integer (may be NULL)
 * @param  negative_out    Output parameter for whether the signed
 *                         integer is negative (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK    - On success
 *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
 *          LIBSYSCALLS_E_INVAL - `bits` is 0
 *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4),
                            __access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_parse_signed_integer(unsigned long long int value_in,
                                 enum libsyscalls_datatype_sign_representation representation,
                                 size_t bits, unsigned long long int *value_out, int *negative_out);


/**
 * Create a string of bits representing a signed integer
 * 
 * In case `representation` is LIBSYSCALLS_SIGN_UNDETERMINED,
 * the bit string will represent an unsigned integer
 * 
 * @param  value_in        The absolute value if the signed integer
 * @param  negative        Whether the signed integer is negative
 * @param  representation  The sign representation used on the interger
 * @param  bits            The number of bits in the integer
 * @param  value_out       Output parameter for the bit string (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK    - On success
 *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
 *          LIBSYSCALLS_E_INVAL - `bits` is 0
 *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 5))
enum libsyscalls_error
libsyscalls_make_signed_integer(unsigned long long int value_in, int negative,
                                enum libsyscalls_datatype_sign_representation representation,
                                size_t bits, unsigned long long int *value_out);


/**
 * Take bits from a section of a split value
 * and shift its bit into place, so that the OR
 * of the result for each section creates the
 * original unsplit value
 * 
 * If `section` is LIBSYSCALLS_SECTION_UNDETERMINED,
 * no changes will be made
 * 
 * @param  value_in   The contiguous bits in the section of the value
 * @param  bits       The number of bits in the section of the value
 * @param  section    The section of the value
 * @param  value_out  Output parameter for the value with its
 *                    bits shifted into place (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK    - On success
 *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
 *          LIBSYSCALLS_E_INVAL - `bits` is invalid for `section`
 *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_unsection_value(unsigned long long int value_in, size_t bits,
                            enum libsyscalls_datatype_section section,
                            unsigned long long int *value_out);


/**
 * Create a split section from a value
 * 
 * If `section` is LIBSYSCALLS_SECTION_UNDETERMINED,
 * no changes will be made
 * 
 * @param  value_in   The whole value
 * @param  bits       The number of bits in the whole value
 * @param  section    The section of the value to return
 * @param  value_out  Output parameter for bits in the section
 *                    value shifted into contiguity (may be NULL)
 * 
 * @return  LIBSYSCALLS_E_OK    - On success
 *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library
 *          LIBSYSCALLS_E_INVAL - `bits` is invalid for `section`
 *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_section_value(unsigned long long int value_in, size_t bits,
                          enum libsyscalls_datatype_section section,
                          unsigned long long int *value_out);


/**
 * Converts a value from the tracee's endian to the tracer's endian
 * 
 * @param  value_in   Buffer containing the value to convert
 *                    (does not need to be aligned)
 * @param  offset_in  Offset in `value_in`, in bits
 * @param  type       Details about the data type
 * @param  value_out  Output parameter for the value in the tracer's endian
 * 
 * @return  LIBSYSCALLS_E_OK    - On success
 *          LIBSYSCALLS_E_INVAL - Either parameter is NULL
 *          LIBSYSCALLS_E_INVAL - The data type is too wide
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__,
                            __access__(__read_only__, 1),
                            __access__(__read_only__, 3),
                            __access__(__write_only__, 4))
enum libsyscalls_error
libsyscalls_to_tracer_endian(const void *value_in, size_t offset_in,
                             const struct libsyscalls_datatype_description *type,
                             unsigned long long int *value_out);


/**
 * Converts a value from the tracer's endian to the tracee's endian
 * 
 * @param  value_in    Buffer containing the value to convert
 * @param  type        Details about the data type
 * @param  value_out   Output parameter for the value in the tracee's
 *                     endian (does not need to be aligned); preexisting
 *                     bits that do not overlap with the position of the
 *                     value will be retained
 * @param  out_offset  Offset in `value_out`, in bits
 * 
 * @return  LIBSYSCALLS_E_OK    - On success
 *          LIBSYSCALLS_E_INVAL - Either parameter is NULL
 *          LIBSYSCALLS_E_INVAL - The data type is too wide
 */
LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__,
                            __access__(__read_only__, 2),
                            __access__(__read_write__, 3))
enum libsyscalls_error
libsyscalls_to_tracee_endian(unsigned long long int value_in,
                             const struct libsyscalls_datatype_description *type,
                             void *value_out, size_t out_offset);


/**
 * Get information on how an instance of struct or union is to be parsed
 * 
 * Do not use for structures inside other structures,
 * instead, use `.type_description.structure` in the
 * structure's field, as it may contain important
 * adjustments
 * 
 * @param  os               The operating system the data type is used on
 * @param  arch             The architecture the data type is used on
 * @param  datatype         The data type
 * @param  data             The data that is to be parsed
 *                          (may be `NULL` if `data_size` is 0)
 * @param  data_size        The number of bytes available in `data`,
 *                          may be short or in excess
 * @param  description_out  Output parameter for the type description;
 *                          the caller responsible for deallocating the `*info_out`
 *                          with free(3) when it is no longer needed. Be aware that
 *                          `*info_out` will only be set when LIBSYSCALLS_E_OK is
 *                          returned.
 * 
 * @return  LIBSYSCALLS_E_OK          - On success
 *          LIBSYSCALLS_E_OSNOSUP     - The library is not compiled with support for
 *                                      the selected operating system (`os`)
 *          LIBSYSCALLS_E_ARCHNOSUP   - The library is not compiled with support for
 *                                      the selected architecture (`arch`) on the
 *                                      selected operating system (`os`)
 *          LIBSYSCALLS_E_INVAL       - `datatype` is not a valid data type
 *          LIBSYSCALLS_E_NOSUCHTYPE  - `datatype` does not exist on the selected
 *                                      operating system (`os`) or architecture (`arch`)
 *          LIBSYSCALLS_E_ISNOTSTRUCT - `datatype` does not represent a structure or
 *                                      union, nor an array of structure or union
 * 
 * The function may complete successfully for some data
 * types even if it for other data types would return
 * LIBSYSCALLS_E_ARCHNOSUP
 */
#if 0 /* work in progress */
LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__,
                            __access__(__read_only__, 4, 5),
                            __access__(__write_only__, 6))
enum libsyscalls_error
libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch,
                                   enum libsyscalls_datatype datatype,
                                   const void *data, size_t data_size,
                                   struct libsyscalls_structure_description **description_out);
#endif

/* TODO add libsyscalls_get_struct_display_info */


#include "libsyscalls/internal-end.h"
#endif