#ifndef _NSLCD_COMMON_H
#define _NSLCD_COMMON_H 1
#include <stdio.h>
#ifdef DEBUG_PROT
#include <string.h>
#include <errno.h>
#define DEBUG_PRINT(fmt,arg) \
fprintf(stderr,"%s:%d:%s: " fmt "\n",__FILE__,__LINE__,__PRETTY_FUNCTION__,arg);
#else
#define DEBUG_PRINT(fmt,arg)
#endif
#ifdef DEBUG_PROT_DUMP
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
static void debug_dump(const void *ptr,size_t size)
{
int i;
for (i=0;i<size;i++)
fprintf(stderr," %02x",((const uint8_t *)ptr)[i]);
fprintf(stderr,"\n");
}
#define DEBUG_DUMP(ptr,size) \
fprintf(stderr,"%s:%d:%s:",__FILE__,__LINE__,__PRETTY_FUNCTION__); \
debug_dump(ptr,size);
#else
#define DEBUG_DUMP(ptr,size)
#endif
#define WRITE(fp,ptr,size) \
DEBUG_PRINT("WRITE : var="__STRING(ptr)" size=%d",(int)size); \
DEBUG_DUMP(ptr,size); \
if (tio_write(fp,ptr,(size_t)size)) \
{ \
DEBUG_PRINT("WRITE : var="__STRING(ptr)" error: %s",strerror(errno)); \
ERROR_OUT_WRITEERROR(fp); \
}
#define WRITE_TYPE(fp,field,type) \
WRITE(fp,&(field),sizeof(type))
#define WRITE_INT32(fp,i) \
DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%d",(int)i); \
tmpint32=(int32_t)(i); \
WRITE_TYPE(fp,tmpint32,int32_t)
#define WRITE_STRING(fp,str) \
DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"",str); \
if (str==NULL) \
{ \
WRITE_INT32(fp,0); \
} \
else \
{ \
WRITE_INT32(fp,strlen(str)); \
if (tmpint32>0) \
{ WRITE(fp,str,tmpint32); } \
}
#define WRITE_FLUSH(fp) \
if (tio_flush(fp)<0) \
{ \
DEBUG_PRINT("WRITE_FLUSH : error: %s",strerror(errno)); \
ERROR_OUT_WRITEERROR(fp); \
}
#define WRITE_STRINGLIST(fp,arr) \
\
for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
; \
\
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
WRITE_TYPE(fp,tmp3int32,int32_t); \
\
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
{ \
WRITE_STRING(fp,(arr)[tmp2int32]); \
}
#define WRITE_STRINGLIST_EXCEPT(fp,arr,not) \
\
for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
; \
\
tmp3int32--; \
DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
WRITE_TYPE(fp,tmp3int32,int32_t); \
tmp3int32++; \
\
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
{ \
if (strcmp((arr)[tmp2int32],(not))!=0) \
{ \
WRITE_STRING(fp,(arr)[tmp2int32]); \
} \
}
#define READ(fp,ptr,size) \
if (tio_read(fp,ptr,(size_t)size)) \
{ \
DEBUG_PRINT("READ : var="__STRING(ptr)" error: %s",strerror(errno)); \
ERROR_OUT_READERROR(fp); \
} \
DEBUG_PRINT("READ : var="__STRING(ptr)" size=%d",(int)size); \
DEBUG_DUMP(ptr,size);
#define READ_TYPE(fp,field,type) \
READ(fp,&(field),sizeof(type))
#define READ_INT32(fp,i) \
READ_TYPE(fp,tmpint32,int32_t); \
i=tmpint32; \
DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32=%d",(int)i);
#define BUF_CUR \
(buffer+bufptr)
#define BUF_CHECK(fp,sz) \
if ((bufptr+(size_t)(sz))>buflen) \
{ \
\
DEBUG_PRINT("READ : buffer error: %d bytes too small",(bufptr+(sz)-(buflen))); \
ERROR_OUT_BUFERROR(fp); \
}
#define BUF_SKIP(sz) \
bufptr+=(size_t)(sz);
#define BUF_ALIGN(fp,type) \
\
tmp2int32=(sizeof(type)-((BUF_CUR-(char *)NULL)%sizeof(type)))%sizeof(type); \
\
BUF_CHECK(fp,tmp2int32); \
BUF_SKIP(tmp2int32);
#define BUF_ALLOC(fp,ptr,type,num) \
\
BUF_ALIGN(fp,type); \
\
BUF_CHECK(fp,(size_t)(num)*sizeof(type)); \
\
(ptr)=(type *)BUF_CUR; \
\
BUF_SKIP((size_t)(num)*sizeof(type));
#define READ_STRING_BUF(fp,field) \
\
READ_TYPE(fp,tmpint32,int32_t); \
DEBUG_PRINT("READ_STRING: var="__STRING(field)" strlen=%d",tmpint32); \
\
BUF_CHECK(fp,tmpint32+1); \
\
if (tmpint32>0) \
{ READ(fp,BUF_CUR,(size_t)tmpint32); } \
\
BUF_CUR[tmpint32]='\0'; \
DEBUG_PRINT("READ_STRING: var="__STRING(field)" string=\"%s\"",BUF_CUR); \
\
(field)=BUF_CUR; \
BUF_SKIP(tmpint32+1);
#define READ_STRING_BUF2(fp,buffer,buflen) \
\
READ_TYPE(fp,tmpint32,int32_t); \
DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d",tmpint32); \
\
if (((size_t)tmpint32)>=(buflen)) \
{ \
\
DEBUG_PRINT("READ : buffer error: %d bytes too large",(tmpint32-(buflen))+1); \
ERROR_OUT_BUFERROR(fp); \
} \
\
if (tmpint32>0) \
{ READ(fp,buffer,(size_t)tmpint32); } \
\
buffer[tmpint32]='\0'; \
DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"",buffer);
#define READ_BUF(fp,ptr,sz) \
\
BUF_CHECK(fp,sz); \
READ(fp,BUF_CUR,(size_t)sz); \
\
(ptr)=BUF_CUR; \
BUF_SKIP(sz);
#define READ_STRINGLIST_NUM(fp,arr,num) \
\
READ_INT32(fp,(num)); \
DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)(num)); \
\
BUF_ALLOC(fp,arr,char *,tmpint32); \
\
for (tmp2int32=0;tmp2int32<(int32_t)(num);tmp2int32++) \
{ \
READ_STRING_BUF(fp,(arr)[tmp2int32]); \
}
#define READ_STRINGLIST_NULLTERM(fp,arr) \
\
READ_TYPE(fp,tmp3int32,int32_t); \
DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
\
BUF_ALLOC(fp,arr,char *,tmp3int32+1); \
\
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
{ \
READ_STRING_BUF(fp,(arr)[tmp2int32]); \
} \
\
(arr)[tmp2int32]=NULL;
#define SKIP(fp,sz) \
DEBUG_PRINT("READ : skip %d bytes",(int)(sz)); \
\
if (tio_skip(fp,sz)) \
{ \
DEBUG_PRINT("READ : skip error: %s",strerror(errno)); \
ERROR_OUT_READERROR(fp); \
}
#define SKIP_STRING(fp) \
\
READ_TYPE(fp,tmpint32,int32_t); \
DEBUG_PRINT("READ_STRING: skip %d bytes",(int)tmpint32); \
\
SKIP(fp,tmpint32);
#define SKIP_STRINGLIST(fp) \
\
READ_TYPE(fp,tmp3int32,int32_t); \
DEBUG_PRINT("READ_STRLST: skip %d strings",(int)tmp3int32); \
\
for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
{ \
SKIP_STRING(fp); \
}
#endif