From cffcac1c8491e699bbac1212205a0eaef8d04fb8 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Mon, 26 Jan 2009 16:13:57 +0000 Subject: [PATCH] 2009-01-26 17:10 UTC+0100 Viktor Szakats (harbour.01 syenar hu) * common.mak * include/hbextern.ch * source/rtl/Makefile + source/rtl/strxor.c + Added HB_STRXOR() (work of Mindaugas Kavaliauskas) * common.mak * source/common/Makefile + source/common/hbprintf.c + Added hb_snprintf_c() (temp name, untested) (work of Przemyslaw Czerpak) [ I've added a normal Harbour license, as per your permission on the list. Pls give me feedback is this is wrong. ] * source/rdd/usrrdd/example/exlog.prg ! Fixed missing #includes. * source/rdd/usrrdd/example/hbmk_b32.bat + source/rdd/usrrdd/example/hbmk_vc.bat + Added MSVC make file. ! Added EOL to the last line to hbmk_b32.bat. ! xhb.lib dependency removed. It was not needed anyway. ; TOFIX: When compiling exhsx.prg, this happens: exhsx.obj : error LNK2001: unresolved external symbol _HB_FUN_HSXRDD * contrib/hbssl/sslsess.c * contrib/hbssl/sslctx.c * contrib/hbssl/sslciph.c * Minor changes. --- harbour/ChangeLog | 30 + harbour/common.mak | 2 + harbour/contrib/hbssl/sslciph.c | 5 +- harbour/contrib/hbssl/sslctx.c | 32 +- harbour/contrib/hbssl/sslsess.c | 5 +- harbour/include/hbextern.ch | 1 + harbour/source/common/Makefile | 1 + harbour/source/common/hbprintf.c | 1059 +++++++++++++++++ harbour/source/rdd/usrrdd/example/exlog.prg | 5 +- .../source/rdd/usrrdd/example/hbmk_b32.bat | 5 +- harbour/source/rdd/usrrdd/example/hbmk_vc.bat | 14 + harbour/source/rtl/Makefile | 1 + harbour/source/rtl/strxor.c | 116 ++ 13 files changed, 1249 insertions(+), 27 deletions(-) create mode 100644 harbour/source/common/hbprintf.c create mode 100644 harbour/source/rdd/usrrdd/example/hbmk_vc.bat create mode 100644 harbour/source/rtl/strxor.c diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b56296407d..47f167cf41 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,36 @@ 2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-01-26 17:10 UTC+0100 Viktor Szakats (harbour.01 syenar hu) + * common.mak + * include/hbextern.ch + * source/rtl/Makefile + + source/rtl/strxor.c + + Added HB_STRXOR() (work of Mindaugas Kavaliauskas) + + * common.mak + * source/common/Makefile + + source/common/hbprintf.c + + Added hb_snprintf_c() (temp name, untested) (work of Przemyslaw Czerpak) + [ I've added a normal Harbour license, as per your permission + on the list. Pls give me feedback is this is wrong. ] + + * source/rdd/usrrdd/example/exlog.prg + ! Fixed missing #includes. + + * source/rdd/usrrdd/example/hbmk_b32.bat + + source/rdd/usrrdd/example/hbmk_vc.bat + + Added MSVC make file. + ! Added EOL to the last line to hbmk_b32.bat. + ! xhb.lib dependency removed. It was not needed anyway. + ; TOFIX: When compiling exhsx.prg, this happens: + exhsx.obj : error LNK2001: unresolved external symbol _HB_FUN_HSXRDD + + * contrib/hbssl/sslsess.c + * contrib/hbssl/sslctx.c + * contrib/hbssl/sslciph.c + * Minor changes. + 2009-01-26 16:53 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/config/darwin/gcc.cf ! changed CCACHE to HB_CCACHE diff --git a/harbour/common.mak b/harbour/common.mak index 2d9dadb919..c883d1490d 100644 --- a/harbour/common.mak +++ b/harbour/common.mak @@ -372,6 +372,7 @@ COMMON_LIB_OBJS = \ $(OBJ_DIR)\hbgete$(OBJEXT) \ $(OBJ_DIR)\hbhash$(OBJEXT) \ $(OBJ_DIR)\hbmem$(OBJEXT) \ + $(OBJ_DIR)\hbprintf$(OBJEXT) \ $(OBJ_DIR)\hbstr$(OBJEXT) \ $(OBJ_DIR)\hbtrace$(OBJEXT) \ $(OBJ_DIR)\hbver$(OBJEXT) \ @@ -621,6 +622,7 @@ RTL_LIB_OBJS = \ $(OBJ_DIR)\strpeek$(OBJEXT) \ $(OBJ_DIR)\strtoexp$(OBJEXT) \ $(OBJ_DIR)\strtran$(OBJEXT) \ + $(OBJ_DIR)\strxor$(OBJEXT) \ $(OBJ_DIR)\strzero$(OBJEXT) \ $(OBJ_DIR)\stuff$(OBJEXT) \ $(OBJ_DIR)\substr$(OBJEXT) \ diff --git a/harbour/contrib/hbssl/sslciph.c b/harbour/contrib/hbssl/sslciph.c index 69e376923a..fa24d892c4 100644 --- a/harbour/contrib/hbssl/sslciph.c +++ b/harbour/contrib/hbssl/sslciph.c @@ -75,10 +75,7 @@ HB_FUNC( SSL_CIPHER_GET_BITS ) { int alg_bits = 0; - if( hb_parptr( 1 ) ) - hb_retni( SSL_CIPHER_get_bits( ( SSL_CIPHER * ) hb_parptr( 1 ), &alg_bits ) ); - else - hb_retni( 0 ); + hb_retni( hb_parptr( 1 ) ? SSL_CIPHER_get_bits( ( SSL_CIPHER * ) hb_parptr( 1 ), &alg_bits ) : 0 ); hb_storni( alg_bits, 2 ); } diff --git a/harbour/contrib/hbssl/sslctx.c b/harbour/contrib/hbssl/sslctx.c index 16058d2765..f3b506ca76 100644 --- a/harbour/contrib/hbssl/sslctx.c +++ b/harbour/contrib/hbssl/sslctx.c @@ -575,9 +575,23 @@ X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); void SSL_CTX_set_cert_store(SSL_CTX *,X509_STORE *); int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x); long SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509); +void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *cs); +void SSL_CTX_set_app_data(SSL_CTX *ctx, void *arg); +int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, char *arg); +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, char *str); +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, unsigned char *d, long len); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type); +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type); +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type); +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint); long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, char *parg); -X509_STORE *SSL_CTX_get_cert_store(SSL_CTX *ctx); STACK *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx); + int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, EVP_PKEY **pkey); int SSL_CTX_get_ex_new_index(long argl, char *argp, int (*new_func);(void), int (*dup_func)(void), void (*free_func)(void)) void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(SSL *ssl, int cb, int ret); @@ -590,14 +604,10 @@ void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*cb)(SSL *ssl, unsigned void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, SSL_SESSION *sess)); void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)); LHASH *SSL_CTX_sessions(SSL_CTX *ctx); -void SSL_CTX_set_app_data(SSL_CTX *ctx, void *arg); -void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *cs); void SSL_CTX_set_cert_verify_cb(SSL_CTX *ctx, int (*cb)(), char *arg) -int SSL_CTX_set_cipher_list(SSL_CTX *ctx, char *str); void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK *list); void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)); void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, int (*cb);(void)) -int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, char *arg); void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(SSL *ssl, int cb, int ret)); void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); void SSL_CTX_set_msg_callback_arg(SSL_CTX *ctx, void *arg); @@ -606,23 +616,11 @@ long SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*cb)(void)); long SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, RSA *rsa); SSL_CTX_set_tmp_rsa_callback long SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int export, int keylength)); - Sets the callback which will be called when a temporary private key is required. The export flag will be set if the reason for needing a temp key is that an export ciphersuite is in use, in which case, keylength will contain the required keylength in bits. Generate a key of appropriate size (using ???) and return it. SSL_set_tmp_rsa_callback long SSL_set_tmp_rsa_callback(SSL *ssl, RSA *(*cb)(SSL *ssl, int export, int keylength)); - The same as SSL_CTX_set_tmp_rsa_callback, except it operates on an SSL session instead of a context. void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*cb);(void)) -int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); -int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, unsigned char *d, long len); -int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, char *file, int type); -int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); -int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len); -int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, char *file, int type); -int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); -int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d); -int SSL_CTX_use_certificate_file(SSL_CTX *ctx, char *file, int type); void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, unsigned int (*callback)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len)); -int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint); void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, unsigned int (*callback)(SSL *ssl, const char *identity, unsigned char *psk, int max_psk_len)); */ diff --git a/harbour/contrib/hbssl/sslsess.c b/harbour/contrib/hbssl/sslsess.c index be3a701311..9d36dd6085 100644 --- a/harbour/contrib/hbssl/sslsess.c +++ b/harbour/contrib/hbssl/sslsess.c @@ -175,10 +175,11 @@ HB_FUNC( SSL_SESSION_HASH ) } /* -void SSL_SESSION_set_app_data(SSL_SESSION *s, char *a); char *SSL_SESSION_get_app_data(SSL_SESSION *s); -int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, char *arg); char *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx); +void SSL_SESSION_set_app_data(SSL_SESSION *s, char *a); +int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, char *arg); + int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(void), int (*dup_func)(void), void (*free_func)(void)) int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x); int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x); diff --git a/harbour/include/hbextern.ch b/harbour/include/hbextern.ch index a3c132cedd..4d97842b9e 100644 --- a/harbour/include/hbextern.ch +++ b/harbour/include/hbextern.ch @@ -892,6 +892,7 @@ EXTERNAL HB_HEXTOSTR EXTERNAL HB_STRTOHEX EXTERNAL HB_STRDECODESCAPE EXTERNAL HB_STRCDECODE +EXTERNAL HB_STRXOR EXTERNAL HB_ISPRINTER EXTERNAL HB_GETENV EXTERNAL HB_USERNAME diff --git a/harbour/source/common/Makefile b/harbour/source/common/Makefile index 5e7d601687..8520ce9606 100644 --- a/harbour/source/common/Makefile +++ b/harbour/source/common/Makefile @@ -10,6 +10,7 @@ C_SOURCES=\ hbgete.c \ hbwince.c \ hbhash.c \ + hbprintf.c \ hbstr.c \ hbdate.c \ hbmem.c \ diff --git a/harbour/source/common/hbprintf.c b/harbour/source/common/hbprintf.c new file mode 100644 index 0000000000..9ad34a79c6 --- /dev/null +++ b/harbour/source/common/hbprintf.c @@ -0,0 +1,1059 @@ +/* + * $Id: dbfnsx1.c 10062 2009-01-17 02:35:29Z druzus $ + */ + +/* + * Harbour Project source code: + * hb_sprintf() function. + * + * Copyright 2008 Przemyslaw Czerpak + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* +patterm format: + '%' [*] [] [.] [] + + */ + +/* +The folowwing conversions are not explicitly supported: + A, a + E, e + G, g + These are (long) double conversions. If necessary they can be easy added. + Now they are simply redirected to F, f conversions. + + C (or Lc) + S (or Ls) + These are wide character conversions and needs locale settings. + +double conversion if not necessary can be disabled to not create unnencessary +overhead and/or references to math library by + #define __NO_DOUBLE__ +It can be also greatly optimized anyhow it will increase dependences list and +reduce portability. +Internally 'long double' is used for all calculations. If some platforms do +not support it then it can be eliminated by + #define __NO_LONGDOUBLE__ + +If positional parameters are not necessary then support for them can be +diabled by + #define __NO_ARGPOS__ +In such case this code neither allocates memory nor extensively use stack +as memory buffer. All conversions are done "on the fly". If memory +allocations or stack size is not a problem then some parts can be easy +optimized. +*/ + +/* #define __NO_DOUBLE__ */ +/* #define __NO_LONGDOUBLE__ */ +/* #define __NO_ARGPOS__ */ +/* #define __NO_LONGLONG__ */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#ifndef __NO_ARGPOS__ +# include /* malloc()/realloc()/free() */ +#endif + +#if defined(__cplusplus) +# define _EXTERN_C extern "C" +#else +# define _EXTERN_C extern +#endif + +_EXTERN_C int hb_snprintf_c( char *buffer, size_t bufsize, const char *format, ... ) + __attribute__ (( format (printf, 3, 4))); + + +#define _F_ALTERNATE 0x01 /* only for: o xX aA eE fF gG */ +#define _F_ZEROPADED 0x02 /* only for: d i o u xX aA eE fF gG */ +#define _F_LEFTADJUSTED 0x04 /* clears _F_ZEROPADED */ +#define _F_SPACE 0x08 /* only for signed num conversions: d i fF aA eE gG */ +#define _F_SIGN 0x10 /* only for signed num conversions: d i fF aA eE gG, clears _F_SPACE */ + +#define _ARGBUF_SIZE 16 + +#define _L_UNDEF_ 0 +#define _L_CHAR_ 1 +#define _L_SHORT_ 2 +#define _L_LONG_ 3 +#define _L_LONGLONG_ 4 +#define _L_INTMAX_ 5 +#define _L_SIZE_ 6 +#define _L_PTRDIFF_ 7 +#define _L_DOUBLE_ 8 +#define _L_LONGDOUBLE_ 9 + +#ifndef __NO_DOUBLE__ +# ifndef __NO_LONGDOUBLE__ +# define _x_long_dbl long double +# define _POWD( x, y ) powl( x, y ) +# define _MODFD( x, p ) modfl( x, p ) +# else +# define _x_long_dbl double +# define _POWD( x, y ) pow( x, y ) +# define _MODFD( x, p ) modf( x, p ) +# endif +# define _x_double double +#else +# define _x_long_dbl int +# define _x_double int +#endif +#ifndef __NO_LONGLONG__ +# define _x_longlong long long +# define _x_ulonglong unsigned long long +#else +# define _x_longlong long +# define _x_ulonglong unsigned long +#endif +#define _x_int int +#define _x_uint unsigned int +#define _x_ulong unsigned long +#define _x_long long +#define _x_intmax_t intmax_t +#define _x_uintmax_t uintmax_t +#define _x_size_t size_t +#define _x_ptrdiff_t ptrdiff_t +#define _x_ptr void * +#define _x_str char * +#define _x_intptr int * + +#define v_x_int 1 +#define v_x_uint 2 +#define v_x_long 3 +#define v_x_ulong 4 +#define v_x_longlong 5 +#define v_x_ulonglong 6 +#define v_x_intmax_t 7 +#define v_x_uintmax_t 8 +#define v_x_size_t 9 +#define v_x_ptrdiff_t 10 +#define v_x_ptr 11 +#define v_x_str 12 +#define v_x_intptr 13 +#define v_x_double 14 +#define v_x_long_dbl 15 + +typedef union { + _x_int as_x_int; + _x_uint as_x_uint; + _x_long as_x_long; + _x_ulong as_x_ulong; + _x_longlong as_x_longlong; + _x_ulonglong as_x_ulonglong; + _x_intmax_t as_x_intmax_t; + _x_uintmax_t as_x_uintmax_t; + _x_size_t as_x_size_t; + _x_ptrdiff_t as_x_ptrdiff_t; + _x_ptr as_x_ptr; + _x_str as_x_str; + _x_intptr as_x_intptr; + _x_double as_x_double; + _x_long_dbl as_x_long_dbl; +} x_type; + +typedef struct { + int id; + x_type value; +} v_param; + +#ifdef __NO_ARGPOS__ + +/* this version does not support positional parameters (f.e. '%1$d') + * they can be added but it will force allocating additional + * memory block in heap or stack and making second pass for + * format decoding/coping. + * so we will use only this simple macro which ignores parameter + * positions. + */ +#define va_arg_n( va, type, n ) va_arg( va, type ) + +/* on some systems where each parameter allocates memory with + * the same size in function stack frame this simple macro can + * be used. + */ + +/* +#define va_arg_n( va, type, n ) \ + ( { \ + type result; \ + if( n == 0 ) \ + result = va_arg( va, type ); \ + else \ + { \ + int count = (n); \ + va_list ap; \ + va_start( ap, format ); \ + do \ + result = va_arg( ap, type ); \ + while( --count > 0 ); \ + va_end( ap ); \ + } \ + result; \ + } ) +*/ + +#else + +#define va_arg_n( va, type, n ) \ + ( { \ + type result; \ + if( n == 0 ) \ + { \ + result = va_arg( va, type ); \ + } \ + else \ + { \ + if( maxarg == 0 ) \ + { \ + repeat = 1; \ + memset( argbuf, 0, sizeof( argbuf ) ); \ + } \ + if( repeat ) \ + { \ + if( n > maxarg ) \ + maxarg = n; \ + if( n > argbuf_size ) \ + { \ + int prev_size = argbuf_size; \ + argbuf_size = n + _ARGBUF_SIZE; \ + if( argbuf_size == _ARGBUF_SIZE ) \ + arglst = memcpy( malloc( argbuf_size * sizeof( v_param ) ), \ + argbuf, sizeof( argbuf ) ); \ + else \ + arglst = realloc( arglst, argbuf_size * sizeof( v_param ) ); \ + memset( &arglst[ prev_size ], 0, ( argbuf_size - prev_size ) * \ + sizeof( v_param ) ); \ + argbuf_size += _ARGBUF_SIZE; \ + } \ + arglst[ n - 1 ].id = (v##type); \ + result = ( type ) 0; \ + } \ + else \ + { \ + result = arglst[ n - 1 ].value.as##type; \ + } \ + } \ + result; \ + } ) + +#define va_arg_fill( va ) \ + do { \ + int iArg; \ + va_start( va, format ); \ + for( iArg = 0; iArg < maxarg; ++iArg ) \ + { \ + switch( arglst[ iArg ].id ) \ + { \ + case v_x_uint: \ + arglst[ iArg ].value.as_x_uint = va_arg( va, _x_uint ); \ + break; \ + case v_x_long: \ + arglst[ iArg ].value.as_x_long = va_arg( va, _x_long ); \ + break; \ + case v_x_ulong: \ + arglst[ iArg ].value.as_x_ulong = va_arg( va, _x_ulong ); \ + break; \ + case v_x_longlong: \ + arglst[ iArg ].value.as_x_longlong = va_arg( va, _x_longlong ); \ + break; \ + case v_x_ulonglong: \ + arglst[ iArg ].value.as_x_ulonglong = va_arg( va, _x_ulonglong ); \ + break; \ + case v_x_intmax_t: \ + arglst[ iArg ].value.as_x_intmax_t = va_arg( va, _x_intmax_t ); \ + break; \ + case v_x_uintmax_t: \ + arglst[ iArg ].value.as_x_uintmax_t = va_arg( va, _x_uintmax_t ); \ + break; \ + case v_x_size_t: \ + arglst[ iArg ].value.as_x_size_t = va_arg( va, _x_size_t ); \ + break; \ + case v_x_ptrdiff_t: \ + arglst[ iArg ].value.as_x_ptrdiff_t = va_arg( va, _x_ptrdiff_t ); \ + break; \ + case v_x_ptr: \ + arglst[ iArg ].value.as_x_ptr = va_arg( va, _x_ptr ); \ + break; \ + case v_x_str: \ + arglst[ iArg ].value.as_x_str = va_arg( va, _x_str ); \ + break; \ + case v_x_intptr: \ + arglst[ iArg ].value.as_x_intptr = va_arg( va, _x_intptr ); \ + break; \ + case v_x_double: \ + arglst[ iArg ].value.as_x_double = va_arg( va, _x_double ); \ + break; \ + case v_x_long_dbl: \ + arglst[ iArg ].value.as_x_long_dbl = va_arg( va, _x_long_dbl ); \ + break; \ + default: \ + arglst[ iArg ].value.as_x_int = va_arg( va, _x_int ); \ + break; \ + } \ + } \ + va_end( va ); \ + } while( 0 ) + +#endif + +static char get_decimal( char c, const char **format, int *result ) +{ + *result = c - '0'; + while( ( c = *(*format)++ ) >= '0' && c <= '9' ) + *result = *result * 10 + ( c - '0' ); + + return c; +} + +static size_t put_octal( char *buffer, size_t bufsize, size_t size, + uintmax_t value, int flags, int width, int precision ) +{ + uintmax_t v = value; + int nums = 0, n; + char c; + + while( v ) + { + ++nums; + v >>= 3; + } + if( precision > nums ) + nums = precision; + else if( flags & _F_ALTERNATE ) + ++nums; + else if( nums == 0 && precision != 0 ) + ++nums; + width -= nums; + + if( ( flags & _F_LEFTADJUSTED ) == 0 ) + { + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ( flags & _F_ZEROPADED ) ? '0' : ' '; + ++size; + --width; + } + } + if( nums ) + { + n = nums; + do + { + c = ( char ) ( value & 0x7 ) + '0'; + value >>= 3; + --n; + if( size + n < bufsize ) + buffer[ size + n ] = c; + } + while( n ); + size += nums; + } + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + + return size; +} + +static size_t put_dec( char *buffer, size_t bufsize, size_t size, + uintmax_t value, int flags, int width, int precision, + int sign ) +{ + uintmax_t v = value; + int nums = 0, n; + char c; + + while( v ) + { + ++nums; + v /= 10; + } + if( precision > nums ) + nums = precision; + else if( nums == 0 && precision != 0 ) + ++nums; + if( ( flags & ( _F_SPACE | _F_SIGN ) ) || sign ) + width--; + if( ( flags & ( _F_LEFTADJUSTED | _F_ZEROPADED ) ) == _F_ZEROPADED && + width > nums ) + nums = width; + width -= nums; + + if( ( flags & _F_LEFTADJUSTED ) == 0 ) + { + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + } + if( ( flags & ( _F_SPACE | _F_SIGN ) ) || sign ) + { + if( size < bufsize ) + buffer[ size ] = sign ? '-' : ( flags & _F_SIGN ? '+' : ' ' ); + ++size; + } + if( nums ) + { + n = nums; + do + { + c = ( char ) ( value % 10 ) + '0'; + value /= 10; + --n; + if( size + n < bufsize ) + buffer[ size + n ] = c; + } + while( n ); + size += nums; + } + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + + return size; +} + +#ifndef __NO_DOUBLE__ +static size_t put_dbl( char *buffer, size_t bufsize, size_t size, + _x_long_dbl value, int flags, int width, int precision ) +{ + _x_long_dbl dInt, dFract; + int sign, nums = 0, n; + char c; + + if( precision < 0 ) + precision = 6; + /* signbit() needs _GNU_SOURCE defined. If it's not available on given + * platform then it can be replaced by 'value < 0' but in such case + * -0.0 will be shown as 0.0 + */ + sign = signbit( value ); + if( sign ) + value = - value; + + /* Round the number to given precision. + * powl() is of course faster when precision is big but it is libm + * (-lm link switch) function so we will make small trick here and + * calculate it in a loop + */ +#if 0 + value += _POWD( 10, -precision ) / 2; +#else + n = precision; + dFract = 1; + while( --n >= 0 ) + dFract /= 10; + value += dFract / 2; +#endif + + dFract = _MODFD( value, &dInt ); + width -= precision; + if( ( flags & ( _F_SPACE | _F_SIGN ) ) || sign ) + width--; + if( precision > 0 || ( flags & _F_ALTERNATE ) ) + width--; + value = dInt; + do + { + ++nums; + _MODFD( value / 10 + 0.01, &value ); + } + while( value >= 1 ); + width -= nums; + c = ( ( flags & ( _F_SPACE | _F_SIGN ) ) || sign ) ? + ( buffer[ size ] = sign ? '-' : ( flags & _F_SIGN ? '+' : ' ' ) ) : 0; + if( ( flags & _F_LEFTADJUSTED ) == 0 && width > 0 ) + { + if( c && ( flags & _F_ZEROPADED ) ) + { + if( size < bufsize ) + buffer[ size ] = c; + ++size; + c = 0; + } + do + { + if( size < bufsize ) + buffer[ size ] = ( flags & _F_ZEROPADED ) ? '0' : ' '; + ++size; + } + while( --width > 0 ); + } + if( c ) + { + if( size < bufsize ) + buffer[ size ] = sign ? '-' : ( flags & _F_SIGN ? '+' : ' ' ); + ++size; + } + + n = nums; + do + { + value = _MODFD( dInt / 10 + 0.01, &dInt ) * 10; + c = '0' + ( char ) ( value + 0.01 ); + --n; + if( size + n < bufsize ) + buffer[ size + n ] = c; + } + while( n ); + size += nums; + + if( precision > 0 || ( flags & _F_ALTERNATE ) ) + { + if( size < bufsize ) + buffer[ size ] = '.'; + ++size; + while( precision > 0 ) + { + dFract = _MODFD( dFract * 10, &dInt ); + c = '0' + ( char ) ( dInt + 0.01 ); + if( size < bufsize ) + buffer[ size ] = c; + ++size; + --precision; + } + } + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + + return size; +} +#endif + +static size_t put_hex( char *buffer, size_t bufsize, size_t size, + uintmax_t value, int flags, int width, int precision, + int upper ) +{ + uintmax_t v = value; + int nums = 0, n; + char c; + + while( v ) + { + ++nums; + v >>= 4; + } + if( precision > nums ) + nums = precision; + else if( nums == 0 && precision != 0 ) + ++nums; + if( ( flags & _F_ALTERNATE ) && value ) + width -= 2; + width -= nums; + + if( ( flags & _F_LEFTADJUSTED ) == 0 ) + { + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ( flags & _F_ZEROPADED ) ? '0' : ' '; + ++size; + --width; + } + } + if( ( flags & _F_ALTERNATE ) && value ) + { + if( size < bufsize ) + buffer[ size ] = '0'; + ++size; + if( size < bufsize ) + buffer[ size ] = upper ? 'X' : 'x'; + ++size; + } + if( nums ) + { + n = nums; + do + { + c = ( char ) ( value & 0x0f ) + '0'; + if( c > '9' ) + c += upper ? 'A' - '9' - 1 : 'a' - '9' - 1; + value >>= 4; + --n; + if( size + n < bufsize ) + buffer[ size + n ] = c; + } + while( n ); + size += nums; + } + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + + return size; +} + +static size_t put_str( char *buffer, size_t bufsize, size_t size, + const char * str, int flags, int width, int precision ) +{ + if( !str ) + str = "(null)"; + if( precision < 0 ) + precision = ( int ) strlen( str ); + else if( precision > 0 ) + /* strnlen() is GNU extension. It needs _GNU_SOURCE + * macro defined before including header files. If this + * function does not exist on some platform then can be + * easy replaced by this macro: + * #define strnlen( s, maxlen ) \ + * ( { size_t n = maxlen, size = 0; \ + * while( n < maxlen && s[ size ] ) \ + * ++size; \ + * size; \ + * } ) + */ + precision = ( int ) strnlen( str, precision ); + + width -= precision; + if( ( flags & _F_LEFTADJUSTED ) == 0 ) while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + while( precision > 0 ) + { + if( size < bufsize ) + buffer[ size ] = *str++; + ++size; + --precision; + } + while( width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + --width; + } + + return size; +} + +int hb_snprintf_c( char * buffer, size_t bufsize, const char * format, ... ) +{ + va_list args; + size_t size; + char c; +#ifndef __NO_ARGPOS__ + const char * fmt_start = format; + v_param argbuf[ _ARGBUF_SIZE ]; + v_param * arglst = argbuf; + int argbuf_size = _ARGBUF_SIZE; + int repeat = 1; + int maxarg = 0; +#endif + + +#ifndef __NO_ARGPOS__ + while( repeat ) + { + repeat = 0; + if( maxarg > 0 ) + va_arg_fill( args ); + format = fmt_start; +#endif + va_start( args, format ); + size = 0; + + do + { + c = *format++; + if( c == '%' ) + { + const char * pattern = format; + + c = *format++; + if( c != 0 && c != '%' ) + { + /* decode pattern */ + int param = 0, flags = 0, width = -1, precision = -1, length, + value = 0, stop = 0; + v_param argval; + + /* parameter position */ + if( c >= '1' && c <= '9' ) + { + c = get_decimal( c, &format, &value ); + if( c == '$' ) + { + param = value; + value = 0; + c = *format++; + } + else + stop = 1; + } + + /* flags */ + while( !stop ) switch( c ) + { + case '#': + flags |= _F_ALTERNATE; + c = *format++; + break; + case '0': + flags |= _F_ZEROPADED; + c = *format++; + break; + case '-': + flags |= _F_LEFTADJUSTED; + c = *format++; + break; + case ' ': + flags |= _F_SPACE; + c = *format++; + break; + case '+': + flags |= _F_SIGN; + c = *format++; + break; +#if _SUSV2_COMPAT_ + case '\'': /* group with locale thousands' grouping characters */ + c = *format++; + break; +#endif + default: + stop = 1; + break; + } + + /* field width */ + if( value != 0 ) + width = value; + else if( c == '*' ) + { + c = *format++; + if( c >= '0' && c <= '9' ) + { + c = get_decimal( c, &format, &value ); + if( c == '$' ) + { + width = va_arg_n( args, _x_int, value ); + c = *format++; + } + /* else error, wrong format */ + } + else + width = va_arg( args, int ); + } + else if( c >= '0' && c <= '9' ) + c = get_decimal( c, &format, &width ); + + /* precision */ + if( c == '.' ) + { + precision = 0; + c = *format++; + if( c == '*' ) + { + c = *format++; + if( c >= '0' && c <= '9' ) + { + c = get_decimal( c, &format, &value ); + if( c == '$' ) + { + precision = va_arg_n( args, _x_int, value ); + c = *format++; + } + /* else error, wrong format */ + } + else + precision = va_arg( args, int ); + } + else if( c >= '0' && c <= '9' ) + c = get_decimal( c, &format, &precision ); + } + + /* length modifier */ + switch( c ) + { + case 'h': + c = *format++; + if( c == 'h' ) + { + length = _L_CHAR_; + c = *format++; + } + else + length = _L_SHORT_; + break; + case 'l': + c = *format++; + if( c == 'l' ) + { + length = _L_LONGLONG_; + c = *format++; + } + else + length = _L_LONG_; + break; + case 'L': + length = _L_LONGDOUBLE_; + c = *format++; + break; + case 'j': + length = _L_INTMAX_; + c = *format++; + break; + case 'z': + length = _L_SIZE_; + c = *format++; + break; + case 't': + length = _L_PTRDIFF_; + c = *format++; + break; + default: + length = _L_UNDEF_; + break; + } + + /* conversion specifier */ + + switch( c ) + { +#ifndef __NO_DOUBLE__ + case 'a': + case 'A': + case 'e': + case 'E': + case 'g': + case 'G': + /* redirect above conversion to 'f' or 'F' type to keep + * valid parameters order + */ + c = ( c == 'a' || c == 'e' || c == 'g' ) ? 'f' : 'F'; + /* no break; */ + case 'f': /* double decimal notation */ + case 'F': /* double decimal notation */ + if( length == _L_LONGDOUBLE_ ) + argval.value.as_x_long_dbl = va_arg_n( args, _x_long_dbl, param ); + else + argval.value.as_x_long_dbl = va_arg_n( args, _x_double, param ); + if( isnan( argval.value.as_x_long_dbl ) ) + size = put_str( buffer, bufsize, size, + c == 'f' ? + ( flags & _F_SIGN ? "+nan": "nan" ) : + ( flags & _F_SIGN ? "+NAN": "NAN" ) , + flags, width, -1 ); + else if( isinf( argval.value.as_x_long_dbl ) > 0 ) + size = put_str( buffer, bufsize, size, + c == 'f' ? + ( flags & _F_SIGN ? "+inf": "inf" ) : + ( flags & _F_SIGN ? "+INF": "INF" ), + flags, width, -1 ); + else if( isinf( argval.value.as_x_long_dbl ) < 0 ) + size = put_str( buffer, bufsize, size, + c == 'f' ? "-inf" : "-INF", + flags, width, -1 ); + else + size = put_dbl( buffer, bufsize, size, argval.value.as_x_long_dbl, + flags, width, precision ); + continue; +#endif + case 'd': + case 'i': /* signed int decimal conversion */ + if( length == _L_CHAR_ ) + argval.value.as_x_intmax_t = ( unsigned char ) va_arg_n( args, _x_int, param ); + else if( length == _L_SHORT_ ) + argval.value.as_x_intmax_t = ( unsigned short ) va_arg_n( args, _x_int, param ); + else if( length == _L_LONG_ ) + argval.value.as_x_intmax_t = va_arg_n( args, _x_long, param ); + else if( length == _L_LONGLONG_ ) + argval.value.as_x_intmax_t = va_arg_n( args, _x_longlong, param ); + else if( length == _L_INTMAX_ ) + argval.value.as_x_intmax_t = va_arg_n( args, _x_intmax_t, param ); + else if( length == _L_SIZE_ ) + argval.value.as_x_intmax_t = va_arg_n( args, _x_size_t, param ); + else if( length == _L_PTRDIFF_ ) + argval.value.as_x_intmax_t = va_arg_n( args, _x_ptrdiff_t, param ); + else + argval.value.as_x_intmax_t = va_arg_n( args, _x_int, param ); + argval.value.as_x_uintmax_t = argval.value.as_x_intmax_t < 0 + ? -argval.value.as_x_intmax_t : argval.value.as_x_intmax_t; + size = put_dec( buffer, bufsize, size, argval.value.as_x_uintmax_t, + flags, width, precision, argval.value.as_x_intmax_t < 0 ); + continue; + case 'o': /* unsigned int octal conversion */ + case 'u': /* unsigned int decimal conversion */ + case 'x': /* unsigned int hexadecimal conversion */ + case 'X': /* unsigned int hexadecimal conversion */ + if( length == _L_CHAR_ ) + argval.value.as_x_uintmax_t = ( unsigned char ) va_arg_n( args, _x_int, param ); + else if( length == _L_SHORT_ ) + argval.value.as_x_uintmax_t = ( unsigned short ) va_arg_n( args, _x_int, param ); + else if( length == _L_LONG_ ) + argval.value.as_x_uintmax_t = va_arg_n( args, _x_ulong, param ); + else if( length == _L_LONGLONG_ ) + argval.value.as_x_uintmax_t = va_arg_n( args, _x_ulonglong, param ); + else if( length == _L_INTMAX_ ) + argval.value.as_x_uintmax_t = va_arg_n( args, _x_uintmax_t, param ); + else if( length == _L_SIZE_ ) + argval.value.as_x_uintmax_t = va_arg_n( args, _x_size_t, param ); + else if( length == _L_PTRDIFF_ ) + argval.value.as_x_uintmax_t = va_arg_n( args, _x_ptrdiff_t, param ); + else + argval.value.as_x_uintmax_t = va_arg_n( args, _x_uint, param ); + + if( c == 'o' ) + size = put_octal( buffer, bufsize, size, argval.value.as_x_uintmax_t, + flags, width, precision ); + else if( c == 'u' ) + size = put_dec( buffer, bufsize, size, argval.value.as_x_uintmax_t, + flags & ~( _F_SPACE | _F_SIGN ), + width, precision, 0 ); + else + size = put_hex( buffer, bufsize, size, argval.value.as_x_uintmax_t, + flags, width, precision, c == 'X' ); + continue; + case 'p': /* void * pointer */ + argval.value.as_x_ptr = va_arg_n( args, _x_ptr, param ); + if( argval.value.as_x_ptr ) + size = put_hex( buffer, bufsize, size, ( unsigned long ) argval.value.as_x_ptr, + flags | _F_ALTERNATE, width, precision, 0 ); + else + size = put_str( buffer, bufsize, size, "(nil)", + flags, width, -1 ); + continue; + case 'c': /* signed int casted to unsigned char */ + if( ( flags & _F_LEFTADJUSTED ) == 0 ) while( --width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + } + c = ( unsigned char ) va_arg_n( args, _x_int, param ); + if( size < bufsize ) + buffer[ size ] = c; + ++size; + while( --width > 0 ) + { + if( size < bufsize ) + buffer[ size ] = ' '; + ++size; + } + continue; + case 's': /* const char * */ + argval.value.as_x_str = va_arg_n( args, _x_str, param ); + size = put_str( buffer, bufsize, size, argval.value.as_x_str, + flags, width, precision ); + continue; + case 'n': /* store current result size in int * arg */ + /* This is very danger feature in *printf() functions + * family very often used by hackers to create buffer + * overflows. It can also cause unintentional memory + * corruption by programmers typo in pattern so if it's + * not strictly necessary it's good to disable it. + */ + *( va_arg_n( args, _x_intptr, param ) ) = ( int ) size; + continue; + case '%': /* store % consuming arguments % */ + break; + default: /* error, wrong format, store pattern */ + format = pattern; + c = '%'; + break; + } + } + } + + /* ISO C99 defines that when size is 0 and buffer is NULL we should + * return number of characters that would have been written in case + * the output string has been large enough without trailing 0. + * Many implementations always returns number of characters necessary + * to hold the string even if the above condition is not true so the + * returned value can be used to check if buffer was large enough + * and if not to allocate bigger buffer. Let's do the same. + */ + if( size < bufsize ) + buffer[ size ] = c; + ++size; + } + while( c != 0 ); + + va_end( args ); + +#ifndef __NO_ARGPOS__ + } + if( arglst != argbuf ) + free( argbuf ); +#endif + + /* always set trailing \0 !!! */ + if( bufsize ) + buffer[ bufsize - 1 ] = 0; + + return ( int ) size; +} diff --git a/harbour/source/rdd/usrrdd/example/exlog.prg b/harbour/source/rdd/usrrdd/example/exlog.prg index 552172513c..3d018f4d27 100644 --- a/harbour/source/rdd/usrrdd/example/exlog.prg +++ b/harbour/source/rdd/usrrdd/example/exlog.prg @@ -2,7 +2,9 @@ * $Id: exfcm.prg 9551 2008-10-05 18:13:15Z vszakats $ */ +#include "common.ch" #include "dbinfo.ch" +#include "hbusrrdd.ch" // Request for LOGRDD rdd driver REQUEST LOGRDD @@ -40,7 +42,8 @@ PROCEDURE Main() CLOSE // Open a table without logging - USE test DRIVER "DBFCDX" + + USE test VIA "DBFCDX" APPEND BLANK field->name := "Francesco" diff --git a/harbour/source/rdd/usrrdd/example/hbmk_b32.bat b/harbour/source/rdd/usrrdd/example/hbmk_b32.bat index 0fbde07d75..6ea6bb28a9 100644 --- a/harbour/source/rdd/usrrdd/example/hbmk_b32.bat +++ b/harbour/source/rdd/usrrdd/example/hbmk_b32.bat @@ -9,7 +9,6 @@ if "%HB_INC_INSTALL%" == "" set HB_INC_INSTALL=..\..\..\..\include set HB_ARCHITECTURE=w32 set HB_COMPILER=bcc32 -set HB_USER_LIBS=hbuddall.lib hbusrrdd.lib xhb.lib -rem set PRG_USR=-p +set HB_USER_LIBS=hbuddall.lib hbusrrdd.lib -call %HB_BIN_INSTALL%\hbmk.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 \ No newline at end of file +call %HB_BIN_INSTALL%\hbmk.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/harbour/source/rdd/usrrdd/example/hbmk_vc.bat b/harbour/source/rdd/usrrdd/example/hbmk_vc.bat new file mode 100644 index 0000000000..bb09a2f68c --- /dev/null +++ b/harbour/source/rdd/usrrdd/example/hbmk_vc.bat @@ -0,0 +1,14 @@ +@echo off +rem +rem $Id$ +rem + +if "%HB_BIN_INSTALL%" == "" set HB_BIN_INSTALL=..\..\..\..\bin +if "%HB_LIB_INSTALL%" == "" set HB_LIB_INSTALL=..\..\..\..\lib +if "%HB_INC_INSTALL%" == "" set HB_INC_INSTALL=..\..\..\..\include + +set HB_ARCHITECTURE=w32 +set HB_COMPILER=msvc +set HB_USER_LIBS=hbuddall.lib hbusrrdd.lib + +call %HB_BIN_INSTALL%\hbmk.bat %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/harbour/source/rtl/Makefile b/harbour/source/rtl/Makefile index 14ce2345f4..f6f885e139 100644 --- a/harbour/source/rtl/Makefile +++ b/harbour/source/rtl/Makefile @@ -138,6 +138,7 @@ C_SOURCES=\ strpeek.c \ strtoexp.c \ strtran.c \ + strxor.c \ strzero.c \ stuff.c \ substr.c \ diff --git a/harbour/source/rtl/strxor.c b/harbour/source/rtl/strxor.c new file mode 100644 index 0000000000..4a13a88d99 --- /dev/null +++ b/harbour/source/rtl/strxor.c @@ -0,0 +1,116 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * HB_STRXOR() + * + * Copyright 2009 Mindaugas Kavaliauskas + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +#include "hbapi.h" +#include "hbapierr.h" +#include "hbapiitm.h" + +HB_FUNC( HB_STRXOR ) +{ + PHB_ITEM pItem = hb_param( 1, HB_IT_STRING ); + + if( pItem ) + { + PHB_ITEM pItem2; + ULONG ulLen1, ulLen2, ul, ul2; + const char * pStr1; + const char * pStr2; + char * pRet; + + pStr1 = hb_itemGetCPtr( pItem ); + ulLen1 = hb_itemGetCLen( pItem ); + + if( ( pItem2 = hb_param( 2, HB_IT_STRING ) ) != NULL ) + { + ulLen2 = hb_itemGetCLen( pItem2 ); + if( ulLen2 ) + { + pStr2 = hb_itemGetCPtr( pItem2 ); + + pRet = ( char * ) hb_xgrab( ulLen1 + 1 ); + memcpy( pRet, pStr1, ulLen1 + 1 ); + ul2 = 0; + for( ul = 0; ul < ulLen1; ul++ ) + { + pRet[ ul ] ^= pStr2[ ul2 ]; + if( ++ul2 == ulLen2 ) + ul2 = 0; + } + hb_retclen_buffer( pRet, ulLen1 ); + } + else + hb_itemReturn( pItem ); + + return; + } + else if( ( pItem2 = hb_param( 2, HB_IT_NUMERIC ) ) != NULL ) + { + char bChar = ( char ) hb_itemGetNI( pItem2 ); + + if( bChar ) + { + pRet = ( char * ) hb_xgrab( ulLen1 + 1 ); + memcpy( pRet, pStr1, ulLen1 + 1 ); + for( ul = 0; ul < ulLen1; ul++ ) + pRet[ ul ] ^= bChar; + + hb_retclen_buffer( pRet, ulLen1 ); + } + else + hb_itemReturn( pItem ); + + return; + } + } + + hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +}