/*:::::*/ FBCALL int fb_StrInstrRevAny ( FBSTRING *src, FBSTRING *patt, int start ) { int r = 0; if( (src != NULL) && (src->data != NULL) && (patt != NULL) && (patt->data != NULL) ) { size_t size_src = FB_STRSIZE(src); size_t size_patt = FB_STRSIZE(patt); if( (size_src != 0) && (size_patt != 0) && (start != 0) ) { if( start < 0 ) start = size_src; else if( start > size_src ) start = 0; while( start-- && (r == 0) ) { size_t i; for( i = 0; i != size_patt; ++i ) { if( src->data[start] == patt->data[i] ) { r = start + 1; break; } } } } } FB_STRLOCK(); /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( patt ); FB_STRUNLOCK(); return r; }
FBCALL FBSTRING *fb_StrUcase2( FBSTRING *src, int mode ) { FBSTRING *dst; ssize_t i, len = 0; int c; char *s, *d; if( src == NULL ) return &__fb_ctx.null_desc; FB_STRLOCK(); if( src->data ) { len = FB_STRSIZE( src ); /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); } else { dst = NULL; } if( dst ) { s = src->data; d = dst->data; if( mode == 1 ) { for( i = 0; i < len; i++ ) { c = *s++; if( (c >= 97) && (c <= 122) ) c -= 97 - 65; *d++ = c; } } else { for( i = 0; i < len; i++ ) { c = *s++; if( islower( c ) ) c = toupper( c ); *d++ = c; } } /* null char */ *d = '\0'; } else { dst = &__fb_ctx.null_desc; } /* del if temp */ fb_hStrDelTemp_NoLock( src ); FB_STRUNLOCK(); return dst; }
/*:::::*/ FBCALL FBSTRING *fb_RTRIM ( FBSTRING *src ) { FBSTRING *dst; int len; if( src == NULL ) return &__fb_ctx.null_desc; FB_STRLOCK(); len = 0; if( src->data != NULL ) { len = FB_STRSIZE( src ); if( len > 0 ) { char *src_ptr = fb_hStrSkipCharRev( src->data, len, 32 ); len = (int)(src_ptr - src->data) + 1; } } if( len > 0 ) { /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, src->data, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); FB_STRUNLOCK(); return dst; }
FBCALL FBSTRING *fb_LEFT( FBSTRING *src, ssize_t chars ) { FBSTRING *dst; ssize_t len, src_len; if( src == NULL ) return &__fb_ctx.null_desc; FB_STRLOCK(); src_len = FB_STRSIZE( src ); if( (src->data != NULL) && (chars > 0) && (src_len > 0) ) { if( chars > src_len ) len = src_len; else len = chars; /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, src->data, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); FB_STRUNLOCK(); return dst; }
/*:::::*/ FBCALL void fb_StrAssignMid ( FBSTRING *dst, int start, int len, FBSTRING *src ) { int src_len, dst_len; FB_STRLOCK(); if( (dst == NULL) || (dst->data == NULL) || (FB_STRSIZE( dst ) == 0) ) { fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( dst ); FB_STRUNLOCK(); return; } if( (src == NULL) || (src->data == NULL) || (FB_STRSIZE( src ) == 0) ) { fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( dst ); FB_STRUNLOCK(); return ; } src_len = FB_STRSIZE( src ); dst_len = FB_STRSIZE( dst ); if( (start > 0) && (start <= dst_len) && (len != 0) ) { --start; if( (len < 0) || (len > src_len) ) len = src_len; if( start + len > dst_len ) len = (dst_len - start); memcpy( dst->data + start, src->data, len ); } /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( dst ); FB_STRUNLOCK(); }
/*:::::*/ FBCALL int fb_ExecEx ( FBSTRING *program, FBSTRING *args, int do_fork ) { char buffer[MAX_PATH+1], *application, *arguments; int res = 0, got_program; size_t len_arguments; #ifndef HOST_MINGW size_t len_program; #endif got_program = (program != NULL) && (program->data != NULL); if( !got_program ) { fb_hStrDelTemp( args ); fb_hStrDelTemp( program ); return -1; } application = fb_hGetShortPath( program->data, buffer, MAX_PATH ); DBG_ASSERT( application!=NULL ); if( application==program->data ) { application = buffer; FB_MEMCPY(application, program->data, FB_STRSIZE( program ) ); } #ifdef HOST_MINGW if( args==NULL ) { arguments = ""; } else { len_arguments = FB_STRSIZE( args ); arguments = alloca( len_arguments + 1 ); DBG_ASSERT( arguments!=NULL ); if( len_arguments ) FB_MEMCPY( arguments, args->data, len_arguments ); arguments[len_arguments] = 0; } #else len_program = strlen( buffer ); len_arguments = ( ( args==NULL ) ? 0 : FB_STRSIZE( args ) ); arguments = alloca( len_program + len_arguments + 2 ); DBG_ASSERT( arguments!=NULL ); FB_MEMCPY( arguments, buffer, len_program ); arguments[len_program] = ' '; if( len_arguments!=0 ) FB_MEMCPY( arguments + len_program + 1, args->data, len_arguments ); arguments[len_program + len_arguments + 1] = 0; #endif FB_STRLOCK(); fb_hStrDelTemp_NoLock( args ); fb_hStrDelTemp_NoLock( program ); FB_STRUNLOCK(); FB_CON_CORRECT_POSITION(); { #ifdef HOST_MINGW if( do_fork ) res = _spawnl( _P_WAIT, buffer, buffer, arguments, NULL ); else res = _execl( buffer, buffer, arguments, NULL ); #else STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; memset( &StartupInfo, 0, sizeof(StartupInfo) ); StartupInfo.cb = sizeof(StartupInfo); if( !CreateProcess( NULL, /* application name - correct! */ arguments, /* command line */ NULL, NULL, /* default security descriptors */ FALSE, /* don't inherit handles */ CREATE_DEFAULT_ERROR_MODE, /* do we really need this? */ NULL, /* default environment */ NULL, /* current directory */ &StartupInfo, &ProcessInfo ) ) { res = -1; } else { /* Release main thread handle - we're not interested in it */ CloseHandle( ProcessInfo.hThread ); if( do_fork ) { DWORD dwExitCode; WaitForSingleObject( ProcessInfo.hProcess, INFINITE ); if( !GetExitCodeProcess( ProcessInfo.hProcess, &dwExitCode ) ) { res = -1; } else { res = (int) dwExitCode; } CloseHandle( ProcessInfo.hProcess ); } else { res = (int) ProcessInfo.hProcess; } } #endif } return res; }
FBCALL FBSTRING *fb_LTrimAny ( FBSTRING *src, FBSTRING *pattern ) { const char *pachText = NULL; FBSTRING *dst; ssize_t len; if( src == NULL ) { fb_hStrDelTemp( pattern ); return &__fb_ctx.null_desc; } FB_STRLOCK(); len = 0; if( src->data != NULL ) { ssize_t len_pattern = ((pattern != NULL) && (pattern->data != NULL)? FB_STRSIZE( pattern ) : 0); pachText = src->data; len = FB_STRSIZE( src ); if( len_pattern != 0 ) { while ( len != 0 ) { ssize_t i; for( i=0; i!=len_pattern; ++i ) { if( FB_MEMCHR( pattern->data, *pachText, len_pattern )!=NULL ) break; } if( i==len_pattern ) break; --len; ++pachText; } } } if( len > 0 ) { /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, pachText, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( pattern ); FB_STRUNLOCK(); return dst; }
/*:::::*/ FBCALL FBSTRING *fb_RTrimEx ( FBSTRING *src, FBSTRING *pattern ) { FBSTRING *dst; int len; if( src == NULL ) { fb_hStrDelTemp( pattern ); return &__fb_ctx.null_desc; } FB_STRLOCK(); if( src->data != NULL ) { size_t len_pattern = ((pattern != NULL) && (pattern->data != NULL)? FB_STRSIZE( pattern ) : 0); len = FB_STRSIZE( src ); if( len >= len_pattern ) { if( len_pattern==1 ) { char *src_ptr = fb_hStrSkipCharRev( src->data, len, FB_CHAR_TO_INT(pattern->data[0]) ); len = (int)(src_ptr - src->data) + 1; } else if( len_pattern != 0 ) { char *src_ptr = src->data; size_t test_index = len - len_pattern; while (len >= len_pattern ) { if( FB_MEMCMP( src_ptr + test_index, pattern->data, len_pattern )!=0 ) break; test_index -= len_pattern; } len = test_index + len_pattern; } } } else len = 0; if( len > 0 ) { /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, src->data, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( pattern ); FB_STRUNLOCK(); return dst; }
/*:::::*/ FBCALL int fb_ExecEx ( FBSTRING *program, FBSTRING *args, int do_fork ) { char buffer[MAX_PATH+1], *application, *arguments, **argv, *p; int i, argc = 0, res = -1, status, len_program, len_arguments; pid_t pid; if( (program == NULL) || (program->data == NULL) ) { fb_hStrDelTemp( args ); fb_hStrDelTemp( program ); return -1; } application = fb_hGetShortPath( program->data, buffer, MAX_PATH ); DBG_ASSERT( application!=NULL ); if( application==program->data ) { len_program = FB_STRSIZE( program ); application = buffer; FB_MEMCPY(application, program->data, len_program ); application[len_program] = 0; } fb_hConvertPath( application ); if( args==NULL ) { arguments = ""; } else { len_arguments = FB_STRSIZE( args ); arguments = alloca( len_arguments + 1 ); DBG_ASSERT( arguments!=NULL ); arguments[len_arguments] = 0; if( len_arguments ) argc = fb_hParseArgs( arguments, args->data, len_arguments ); } FB_STRLOCK(); fb_hStrDelTemp_NoLock( args ); fb_hStrDelTemp_NoLock( program ); FB_STRUNLOCK(); if( argc == -1 ) return -1; argc++; /* add 1 for program name */ argv = alloca( sizeof(char*) * (argc + 1 )); DBG_ASSERT( argv!=NULL ); argv[0] = application; /* scan the processed args and set pointers */ p = arguments; for( i=1 ; i<argc; i++) { argv[i] = p; /* set pointer to current argument */ while( *p++ ); /* skip to 1 char past next null char */ } argv[argc] = NULL; /* Launch */ fb_hExitConsole(); if( do_fork ) { pid = fork(); if( pid != -1 ) { if (pid == 0) { /* execvp() only returns if it failed */ execvp( application, argv ); /* HACK: execvp() failed, this must be communiated to the parent process *somehow*, so fb_ExecEx() can return -1 there */ exit( 255 ); /* FIXME: won't be able to tell the difference if the exec'ed program returned 255. Maybe a pipe could be used instead of the 255 exit code? Unless that's too slow/has side-effects */ } else if( (waitpid(pid, &status, 0) > 0) && WIFEXITED(status) ) { res = WEXITSTATUS(status); if( res == 255 ) { /* See the HACK above */ res = -1; } } } } else { res = execvp( application, argv ); } fb_hInitConsole(); return res; }
FBCALL FBSTRING *fb_Dir( FBSTRING *filespec, int attrib, int *out_attrib ) { FB_DIRCTX *ctx; FBSTRING *res; ssize_t len; int tmp_attrib; char *name, *p; struct stat info; if( out_attrib == NULL ) out_attrib = &tmp_attrib; len = FB_STRSIZE( filespec ); name = NULL; ctx = FB_TLSGETCTX( DIR ); if( len > 0 ) { /* findfirst */ if( ctx->in_use ) close_dir( ); if( strchr( filespec->data, '*' ) || strchr( filespec->data, '?' ) ) { /* we have a pattern */ p = strrchr( filespec->data, '/' ); if( p ) { strncpy( ctx->filespec, p + 1, MAX_PATH ); ctx->filespec[MAX_PATH-1] = '\0'; len = (p - filespec->data) + 1; if( len > MAX_PATH - 1 ) len = MAX_PATH - 1; memcpy( ctx->dirname, filespec->data, len ); ctx->dirname[len] = '\0'; } else { strncpy( ctx->filespec, filespec->data, MAX_PATH ); ctx->filespec[MAX_PATH-1] = '\0'; strcpy( ctx->dirname, "./"); } /* Make sure these patterns work just like on Win32/DOS */ if( (!strcmp( ctx->filespec, "*.*" )) || (!strcmp( ctx->filespec, "*." )) ) strcpy( ctx->filespec, "*" ); if( (attrib & 0x10) == 0 ) attrib |= 0x20; ctx->attrib = attrib; ctx->dir = opendir( ctx->dirname ); if( ctx->dir ) { name = find_next( out_attrib ); if( name ) ctx->in_use = TRUE; } } else { /* no pattern, use stat on single file */ if( !stat( filespec->data, &info ) ) { tmp_attrib = get_attrib( filespec->data, &info ); if( (tmp_attrib & ~attrib ) == 0 ) { name = strrchr( filespec->data, '/' ); if( !name ) name = filespec->data; else name++; *out_attrib = tmp_attrib; } } } } else { /* findnext */ if( ctx->in_use ) name = find_next( out_attrib ); } FB_STRLOCK(); /* store filename if found */ if( name ) { len = strlen( name ); res = fb_hStrAllocTemp_NoLock( NULL, len ); if( res ) fb_hStrCopy( res->data, name, len ); else res = &__fb_ctx.null_desc; } else { res = &__fb_ctx.null_desc; *out_attrib = 0; } fb_hStrDelTemp_NoLock( filespec ); FB_STRUNLOCK(); return res; }