Compare commits
3 Commits
e0fc631761
...
5b47ec6b07
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b47ec6b07 | |||
| b8538fbc4d | |||
| 06c5dc7fef |
+1
-1
@@ -610,7 +610,7 @@ int HawkStd::open_pio (Pipe& io)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pio = hawk_pio_open((hawk_gem_t*)*this, 0, io.getName(), flags);
|
pio = hawk_pio_open((hawk_gem_t*)*this, 0, io.getName(), flags, HAWK_NULL, HAWK_NULL);
|
||||||
if (!pio) return -1;
|
if (!pio) return -1;
|
||||||
|
|
||||||
#if defined(HAWK_OOCH_IS_UCH)
|
#if defined(HAWK_OOCH_IS_UCH)
|
||||||
|
|||||||
+9
-2
@@ -250,6 +250,7 @@ struct hawk_htb_t
|
|||||||
hawk_oow_t size;
|
hawk_oow_t size;
|
||||||
hawk_oow_t capa;
|
hawk_oow_t capa;
|
||||||
hawk_oow_t threshold;
|
hawk_oow_t threshold;
|
||||||
|
hawk_oow_t rev;
|
||||||
|
|
||||||
hawk_htb_pair_t** bucket;
|
hawk_htb_pair_t** bucket;
|
||||||
};
|
};
|
||||||
@@ -284,13 +285,15 @@ typedef struct hawk_htb_itr_t hawk_htb_itr_t;
|
|||||||
/**
|
/**
|
||||||
* The HAWK_HTB_SIZE() macro returns the number of pairs in a hash table.
|
* The HAWK_HTB_SIZE() macro returns the number of pairs in a hash table.
|
||||||
*/
|
*/
|
||||||
#define HAWK_HTB_SIZE(m) (*(const hawk_oow_t*)&(m)->size)
|
#define HAWK_HTB_SIZE(m) ((const hawk_oow_t)(m)->size)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The HAWK_HTB_CAPA() macro returns the maximum number of pairs that can be
|
* The HAWK_HTB_CAPA() macro returns the maximum number of pairs that can be
|
||||||
* stored in a hash table without further reorganization.
|
* stored in a hash table without further reorganization.
|
||||||
*/
|
*/
|
||||||
#define HAWK_HTB_CAPA(m) (*(const hawk_oow_t*)&(m)->capa)
|
#define HAWK_HTB_CAPA(m) ((const hawk_oow_t)(m)->capa)
|
||||||
|
|
||||||
|
#define HAWK_HTB_REV(m) ((const hawk_oow_t)(m)->rev)
|
||||||
|
|
||||||
#define HAWK_HTB_FACTOR(m) (*(const int*)&(m)->factor)
|
#define HAWK_HTB_FACTOR(m) (*(const int*)&(m)->factor)
|
||||||
#define HAWK_HTB_KSCALE(m) (*(const int*)&(m)->scale[HAWK_HTB_KEY])
|
#define HAWK_HTB_KSCALE(m) (*(const int*)&(m)->scale[HAWK_HTB_KEY])
|
||||||
@@ -406,6 +409,10 @@ HAWK_EXPORT hawk_oow_t hawk_htb_getcapa (
|
|||||||
const hawk_htb_t* htb /**< hash table */
|
const hawk_htb_t* htb /**< hash table */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
HAWK_EXPORT hawk_oow_t hawk_htb_getrev (
|
||||||
|
const hawk_htb_t* htb /**< hash table */
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hawk_htb_search() function searches a hash table to find a pair with a
|
* The hawk_htb_search() function searches a hash table to find a pair with a
|
||||||
* matching key. It returns the pointer to the pair found. If it fails
|
* matching key. It returns the pointer to the pair found. If it fails
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
# define hawk_map_getxtn(map) hawk_htb_getxtn(map)
|
# define hawk_map_getxtn(map) hawk_htb_getxtn(map)
|
||||||
# define hawk_map_getsize(map) hawk_htb_getsize(map)
|
# define hawk_map_getsize(map) hawk_htb_getsize(map)
|
||||||
# define hawk_map_getcapa(map) hawk_htb_getcapa(map)
|
# define hawk_map_getcapa(map) hawk_htb_getcapa(map)
|
||||||
|
# define hawk_map_getrev(map) hawk_htb_getrev(map)
|
||||||
# define hawk_map_getstyle(map) hawk_htb_getstyle(map)
|
# define hawk_map_getstyle(map) hawk_htb_getstyle(map)
|
||||||
# define hawk_map_setstyle(map,cbs) hawk_htb_setstyle(map,cbs)
|
# define hawk_map_setstyle(map,cbs) hawk_htb_setstyle(map,cbs)
|
||||||
# define hawk_map_search(map,kptr,klen) hawk_htb_search(map,kptr,klen)
|
# define hawk_map_search(map,kptr,klen) hawk_htb_search(map,kptr,klen)
|
||||||
@@ -80,6 +81,7 @@
|
|||||||
# define HAWK_MAP_SIZER_DEFAULT HAWK_HTB_SIZER_DEFAULT
|
# define HAWK_MAP_SIZER_DEFAULT HAWK_HTB_SIZER_DEFAULT
|
||||||
# define HAWK_MAP_HASHER_DEFAULT HAWK_HTB_HASHER_DEFAULT
|
# define HAWK_MAP_HASHER_DEFAULT HAWK_HTB_HASHER_DEFAULT
|
||||||
# define HAWK_MAP_SIZE(map) HAWK_HTB_SIZE(map)
|
# define HAWK_MAP_SIZE(map) HAWK_HTB_SIZE(map)
|
||||||
|
# define HAWK_MAP_REV(map) HAWK_HTB_REV(map)
|
||||||
# define HAWK_MAP_KCOPIER(map) HAWK_HTB_KCOPIER(map)
|
# define HAWK_MAP_KCOPIER(map) HAWK_HTB_KCOPIER(map)
|
||||||
# define HAWK_MAP_VCOPIER(map) HAWK_HTB_VCOPIER(map)
|
# define HAWK_MAP_VCOPIER(map) HAWK_HTB_VCOPIER(map)
|
||||||
# define HAWK_MAP_KFREEER(map) HAWK_HTB_KFREEER(map)
|
# define HAWK_MAP_KFREEER(map) HAWK_HTB_KFREEER(map)
|
||||||
@@ -108,6 +110,7 @@
|
|||||||
# define hawk_map_getxtn(map) hawk_rbt_getxtn(map)
|
# define hawk_map_getxtn(map) hawk_rbt_getxtn(map)
|
||||||
# define hawk_map_getsize(map) hawk_rbt_getsize(map)
|
# define hawk_map_getsize(map) hawk_rbt_getsize(map)
|
||||||
# define hawk_map_getcapa(map) hawk_rbt_getsize(map)
|
# define hawk_map_getcapa(map) hawk_rbt_getsize(map)
|
||||||
|
# define hawk_map_getrev(map) hawk_rbt_getrev(map)
|
||||||
# define hawk_map_getstyle(map) hawk_rbt_getstyle(map)
|
# define hawk_map_getstyle(map) hawk_rbt_getstyle(map)
|
||||||
# define hawk_map_setstyle(map,cbs) hawk_rbt_setstyle(map,cbs)
|
# define hawk_map_setstyle(map,cbs) hawk_rbt_setstyle(map,cbs)
|
||||||
# define hawk_map_search(map,kptr,klen) hawk_rbt_search(map,kptr,klen)
|
# define hawk_map_search(map,kptr,klen) hawk_rbt_search(map,kptr,klen)
|
||||||
@@ -143,6 +146,7 @@
|
|||||||
# define HAWK_MAP_SIZER_DEFAULT (HAWK_NULL)
|
# define HAWK_MAP_SIZER_DEFAULT (HAWK_NULL)
|
||||||
# define HAWK_MAP_HASHER_DEFAULT (HAWK_NULL)
|
# define HAWK_MAP_HASHER_DEFAULT (HAWK_NULL)
|
||||||
# define HAWK_MAP_SIZE(map) HAWK_RBT_SIZE(map)
|
# define HAWK_MAP_SIZE(map) HAWK_RBT_SIZE(map)
|
||||||
|
# define HAWK_MAP_REV(map) HAWK_RBT_REV(map)
|
||||||
# define HAWK_MAP_KCOPIER(map) HAWK_RBT_KCOPIER(map)
|
# define HAWK_MAP_KCOPIER(map) HAWK_RBT_KCOPIER(map)
|
||||||
# define HAWK_MAP_VCOPIER(map) HAWK_RBT_VCOPIER(map)
|
# define HAWK_MAP_VCOPIER(map) HAWK_RBT_VCOPIER(map)
|
||||||
# define HAWK_MAP_KFREEER(map) HAWK_RBT_KFREEER(map)
|
# define HAWK_MAP_KFREEER(map) HAWK_RBT_KFREEER(map)
|
||||||
|
|||||||
+22
-9
@@ -120,8 +120,21 @@ enum hawk_pio_hid_t
|
|||||||
};
|
};
|
||||||
typedef enum hawk_pio_hid_t hawk_pio_hid_t;
|
typedef enum hawk_pio_hid_t hawk_pio_hid_t;
|
||||||
|
|
||||||
|
enum hawk_pio_env_mk_type_t
|
||||||
|
{
|
||||||
|
HAWK_PIO_ENV_MK_BCH_PP, /* P1 ... PN HAWK_NUL where P1 .. PN points to K=V */
|
||||||
|
HAWK_PIO_ENV_MK_BCH_PN, /* K1=V\0K2=V\0\0 */
|
||||||
|
HAWK_PIO_ENV_MK_UCH_PP,
|
||||||
|
};
|
||||||
|
|
||||||
typedef int (*hawk_pio_fncptr_t) (void* ctx, char** envp);
|
typedef enum hawk_pio_env_mk_type_t hawk_pio_env_mk_type_t;
|
||||||
|
|
||||||
|
typedef void* (*hawk_pio_env_mk_t) (
|
||||||
|
hawk_pio_env_mk_type_t type,
|
||||||
|
void* ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef int (*hawk_pio_fncptr_t) (void* ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hawk_pio_fnc_t type defines a structure to point to the function
|
* The hawk_pio_fnc_t type defines a structure to point to the function
|
||||||
@@ -170,7 +183,6 @@ struct hawk_pio_pin_t
|
|||||||
hawk_pio_t* self;
|
hawk_pio_t* self;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hawk_pio_t type defines a structure to store status for piped I/O
|
* The hawk_pio_t type defines a structure to store status for piped I/O
|
||||||
* to a child process. The hawk_pio_xxx() funtions are written around this
|
* to a child process. The hawk_pio_xxx() funtions are written around this
|
||||||
@@ -198,18 +210,17 @@ extern "C" {
|
|||||||
* pipes to it. #HAWK_PIO_SHELL causes the function to execute \a cmd via
|
* pipes to it. #HAWK_PIO_SHELL causes the function to execute \a cmd via
|
||||||
* the default shell of an underlying system: /bin/sh on *nix, cmd.exe on win32.
|
* the default shell of an underlying system: /bin/sh on *nix, cmd.exe on win32.
|
||||||
* On *nix systems, a full path to the command is needed if it is not specified.
|
* On *nix systems, a full path to the command is needed if it is not specified.
|
||||||
* If \a env is #HAWK_NULL, the environment of \a cmd inherits that of the
|
* If #HAWK_PIO_BCSTRCMD is specified in \a flags, \a cmd is treated as a
|
||||||
* calling process. If you want to pass an empty environment, you can pass
|
* multi-byte string whose character type is #hawk_bch_t.
|
||||||
* an empty \a env object with no items inserted. If #HAWK_PIO_BCSTRCMD is
|
|
||||||
* specified in \a flags, \a cmd is treated as a multi-byte string whose
|
|
||||||
* character type is #hawk_bch_t.
|
|
||||||
* \return #hawk_pio_t object on success, #HAWK_NULL on failure
|
* \return #hawk_pio_t object on success, #HAWK_NULL on failure
|
||||||
*/
|
*/
|
||||||
HAWK_EXPORT hawk_pio_t* hawk_pio_open (
|
HAWK_EXPORT hawk_pio_t* hawk_pio_open (
|
||||||
hawk_gem_t* gem, /**< gem */
|
hawk_gem_t* gem, /**< gem */
|
||||||
hawk_oow_t ext, /**< extension size */
|
hawk_oow_t ext, /**< extension size */
|
||||||
const hawk_ooch_t* cmd, /**< command to execute */
|
const hawk_ooch_t* cmd, /**< command to execute */
|
||||||
int flags /**< 0 or a number OR'ed of the #hawk_pio_flag_t enumerators*/
|
int flags, /**< 0 or a number OR'ed of the #hawk_pio_flag_t enumerators*/
|
||||||
|
hawk_pio_env_mk_t env_mk,
|
||||||
|
void* env_cx
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,7 +241,9 @@ HAWK_EXPORT int hawk_pio_init (
|
|||||||
hawk_pio_t* pio, /**< pio object */
|
hawk_pio_t* pio, /**< pio object */
|
||||||
hawk_gem_t* gem, /**< gem */
|
hawk_gem_t* gem, /**< gem */
|
||||||
const hawk_ooch_t* cmd, /**< command to execute */
|
const hawk_ooch_t* cmd, /**< command to execute */
|
||||||
int flags /**< 0 or a number OR'ed of the #hawk_pio_flag_t enumerators*/
|
int flags, /**< 0 or a number OR'ed of the #hawk_pio_flag_t enumerators*/
|
||||||
|
hawk_pio_env_mk_t env_mk,
|
||||||
|
void* env_cx
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ struct hawk_rbt_t
|
|||||||
hawk_rbt_pair_t xnil; /**< internal nil node */
|
hawk_rbt_pair_t xnil; /**< internal nil node */
|
||||||
hawk_oow_t size; /**< number of pairs */
|
hawk_oow_t size; /**< number of pairs */
|
||||||
hawk_rbt_pair_t* root; /**< root pair */
|
hawk_rbt_pair_t* root; /**< root pair */
|
||||||
|
hawk_oow_t rev; /**< revision */
|
||||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||||
hawk_rbt_itr_t _prot_itr; /**< protected iterators */
|
hawk_rbt_itr_t _prot_itr; /**< protected iterators */
|
||||||
#endif
|
#endif
|
||||||
@@ -280,6 +281,7 @@ struct hawk_rbt_t
|
|||||||
* The HAWK_RBT_SIZE() macro returns the number of pairs in red-black tree.
|
* The HAWK_RBT_SIZE() macro returns the number of pairs in red-black tree.
|
||||||
*/
|
*/
|
||||||
#define HAWK_RBT_SIZE(m) ((const hawk_oow_t)(m)->size)
|
#define HAWK_RBT_SIZE(m) ((const hawk_oow_t)(m)->size)
|
||||||
|
#define HAWK_RBT_REV(m) ((const hawk_oow_t)(m)->rev)
|
||||||
#define HAWK_RBT_KSCALE(m) ((const int)(m)->scale[HAWK_RBT_KEY])
|
#define HAWK_RBT_KSCALE(m) ((const int)(m)->scale[HAWK_RBT_KEY])
|
||||||
#define HAWK_RBT_VSCALE(m) ((const int)(m)->scale[HAWK_RBT_VAL])
|
#define HAWK_RBT_VSCALE(m) ((const int)(m)->scale[HAWK_RBT_VAL])
|
||||||
|
|
||||||
|
|||||||
@@ -311,6 +311,7 @@ int hawk_htb_init (hawk_htb_t* htb, hawk_gem_t* gem, hawk_oow_t capa, int factor
|
|||||||
htb->capa = capa;
|
htb->capa = capa;
|
||||||
htb->threshold = htb->capa * htb->factor / 100;
|
htb->threshold = htb->capa * htb->factor / 100;
|
||||||
if (htb->capa > 0 && htb->threshold <= 0) htb->threshold = 1;
|
if (htb->capa > 0 && htb->threshold <= 0) htb->threshold = 1;
|
||||||
|
htb->rev = 0;
|
||||||
|
|
||||||
htb->style = &style[0];
|
htb->style = &style[0];
|
||||||
return 0;
|
return 0;
|
||||||
@@ -343,6 +344,11 @@ hawk_oow_t hawk_htb_getcapa (const hawk_htb_t* htb)
|
|||||||
return htb->capa;
|
return htb->capa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hawk_oow_t hawk_htb_getrev (const hawk_htb_t* htb)
|
||||||
|
{
|
||||||
|
return htb->rev;
|
||||||
|
}
|
||||||
|
|
||||||
pair_t* hawk_htb_search (const hawk_htb_t* htb, const void* kptr, hawk_oow_t klen)
|
pair_t* hawk_htb_search (const hawk_htb_t* htb, const void* kptr, hawk_oow_t klen)
|
||||||
{
|
{
|
||||||
pair_t* pair;
|
pair_t* pair;
|
||||||
@@ -451,7 +457,7 @@ static HAWK_INLINE pair_t* insert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen,
|
|||||||
case UPSERT:
|
case UPSERT:
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
p = change_pair_val(htb, pair, vptr, vlen);
|
p = change_pair_val(htb, pair, vptr, vlen);
|
||||||
if (p == HAWK_NULL)
|
if (!p)
|
||||||
{
|
{
|
||||||
/* error in changing the value */
|
/* error in changing the value */
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
@@ -465,6 +471,7 @@ static HAWK_INLINE pair_t* insert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen,
|
|||||||
else NEXT(prev) = p;
|
else NEXT(prev) = p;
|
||||||
NEXT(p) = next;
|
NEXT(p) = next;
|
||||||
}
|
}
|
||||||
|
htb->rev++;
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
case ENSERT:
|
case ENSERT:
|
||||||
@@ -507,6 +514,7 @@ static HAWK_INLINE pair_t* insert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen,
|
|||||||
htb->bucket[hc] = pair;
|
htb->bucket[hc] = pair;
|
||||||
htb->size++;
|
htb->size++;
|
||||||
|
|
||||||
|
htb->rev++;
|
||||||
return pair; /* new key added */
|
return pair; /* new key added */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +533,6 @@ pair_t* hawk_htb_insert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen, void* vpt
|
|||||||
return insert(htb, kptr, klen, vptr, vlen, INSERT);
|
return insert(htb, kptr, klen, vptr, vlen, INSERT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pair_t* hawk_htb_update (hawk_htb_t* htb, void* kptr, hawk_oow_t klen, void* vptr, hawk_oow_t vlen)
|
pair_t* hawk_htb_update (hawk_htb_t* htb, void* kptr, hawk_oow_t klen, void* vptr, hawk_oow_t vlen)
|
||||||
{
|
{
|
||||||
return insert(htb, kptr, klen, vptr, vlen, UPDATE);
|
return insert(htb, kptr, klen, vptr, vlen, UPDATE);
|
||||||
@@ -548,7 +555,7 @@ pair_t* hawk_htb_cbsert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen, cbserter_
|
|||||||
{
|
{
|
||||||
/* found a pair with a matching key */
|
/* found a pair with a matching key */
|
||||||
p = cbserter(htb, pair, kptr, klen, ctx);
|
p = cbserter(htb, pair, kptr, klen, ctx);
|
||||||
if (p == HAWK_NULL)
|
if (!p)
|
||||||
{
|
{
|
||||||
/* error returned by the callback function */
|
/* error returned by the callback function */
|
||||||
return HAWK_NULL;
|
return HAWK_NULL;
|
||||||
@@ -562,6 +569,7 @@ pair_t* hawk_htb_cbsert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen, cbserter_
|
|||||||
else NEXT(prev) = p;
|
else NEXT(prev) = p;
|
||||||
NEXT(p) = next;
|
NEXT(p) = next;
|
||||||
}
|
}
|
||||||
|
htb->rev++;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,6 +595,7 @@ pair_t* hawk_htb_cbsert (hawk_htb_t* htb, void* kptr, hawk_oow_t klen, cbserter_
|
|||||||
NEXT(pair) = htb->bucket[hc];
|
NEXT(pair) = htb->bucket[hc];
|
||||||
htb->bucket[hc] = pair;
|
htb->bucket[hc] = pair;
|
||||||
htb->size++;
|
htb->size++;
|
||||||
|
htb->rev++;
|
||||||
|
|
||||||
return pair; /* new key added */
|
return pair; /* new key added */
|
||||||
}
|
}
|
||||||
@@ -610,6 +619,7 @@ int hawk_htb_delete (hawk_htb_t* htb, const void* kptr, hawk_oow_t klen)
|
|||||||
|
|
||||||
hawk_htb_freepair(htb, pair);
|
hawk_htb_freepair(htb, pair);
|
||||||
htb->size--;
|
htb->size--;
|
||||||
|
htb->rev++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -624,14 +634,15 @@ int hawk_htb_delete (hawk_htb_t* htb, const void* kptr, hawk_oow_t klen)
|
|||||||
|
|
||||||
void hawk_htb_clear (hawk_htb_t* htb)
|
void hawk_htb_clear (hawk_htb_t* htb)
|
||||||
{
|
{
|
||||||
hawk_oow_t i;
|
hawk_oow_t i, sz;
|
||||||
pair_t* pair, * next;
|
pair_t* pair, * next;
|
||||||
|
|
||||||
|
sz = htb->size;
|
||||||
for (i = 0; i < htb->capa; i++)
|
for (i = 0; i < htb->capa; i++)
|
||||||
{
|
{
|
||||||
pair = htb->bucket[i];
|
pair = htb->bucket[i];
|
||||||
|
|
||||||
while (pair != HAWK_NULL)
|
while (pair)
|
||||||
{
|
{
|
||||||
next = NEXT(pair);
|
next = NEXT(pair);
|
||||||
hawk_htb_freepair(htb, pair);
|
hawk_htb_freepair(htb, pair);
|
||||||
@@ -641,6 +652,9 @@ void hawk_htb_clear (hawk_htb_t* htb)
|
|||||||
|
|
||||||
htb->bucket[i] = HAWK_NULL;
|
htb->bucket[i] = HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HAWK_ASSERT(htb->size == 0);
|
||||||
|
if (sz) htb->rev++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hawk_htb_walk (hawk_htb_t* htb, walker_t walker, void* ctx)
|
void hawk_htb_walk (hawk_htb_t* htb, walker_t walker, void* ctx)
|
||||||
|
|||||||
+3
-1
@@ -6688,15 +6688,17 @@ static int unsetenv(const char *name)
|
|||||||
/* check if the entry starts with name + '=' */
|
/* check if the entry starts with name + '=' */
|
||||||
if (hawk_comp_bcstr_limited(*ep, name, len, 0) == 0 && (*ep)[len] == '=')
|
if (hawk_comp_bcstr_limited(*ep, name, len, 0) == 0 && (*ep)[len] == '=')
|
||||||
{
|
{
|
||||||
|
char* old;
|
||||||
/* found it. shift remaining pointers down. */
|
/* found it. shift remaining pointers down. */
|
||||||
char** next = ep;
|
char** next = ep;
|
||||||
|
old = *ep;
|
||||||
while (*next)
|
while (*next)
|
||||||
{
|
{
|
||||||
*next = *(next + 1);
|
*next = *(next + 1);
|
||||||
next++;
|
next++;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(*ep);
|
free(old);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,14 +191,14 @@ static int close_open_fds_using_proc (hawk_pio_t* pio, int* excepts, hawk_oow_t
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hawk_pio_t* hawk_pio_open (hawk_gem_t* gem, hawk_oow_t xtnsize, const hawk_ooch_t* cmd, int flags)
|
hawk_pio_t* hawk_pio_open (hawk_gem_t* gem, hawk_oow_t xtnsize, const hawk_ooch_t* cmd, int flags, hawk_pio_env_mk_t env_mk, void* env_ctx)
|
||||||
{
|
{
|
||||||
hawk_pio_t* pio;
|
hawk_pio_t* pio;
|
||||||
|
|
||||||
pio = (hawk_pio_t*)hawk_gem_allocmem(gem, HAWK_SIZEOF(hawk_pio_t) + xtnsize);
|
pio = (hawk_pio_t*)hawk_gem_allocmem(gem, HAWK_SIZEOF(hawk_pio_t) + xtnsize);
|
||||||
if (pio)
|
if (pio)
|
||||||
{
|
{
|
||||||
if (hawk_pio_init(pio, gem, cmd, flags) <= -1)
|
if (hawk_pio_init(pio, gem, cmd, flags, env_mk, env_ctx) <= -1)
|
||||||
{
|
{
|
||||||
hawk_gem_freemem(gem, pio);
|
hawk_gem_freemem(gem, pio);
|
||||||
pio = HAWK_NULL;
|
pio = HAWK_NULL;
|
||||||
@@ -458,16 +458,10 @@ static HAWK_INLINE int is_fd_valid_and_nocloexec (int fd)
|
|||||||
return !(flags & FD_CLOEXEC)? 1: 0;
|
return !(flags & FD_CLOEXEC)? 1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], param_t* param, char** envp)
|
static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], param_t* param, char*const* envp)
|
||||||
{
|
{
|
||||||
hawk_pio_pid_t pid;
|
hawk_pio_pid_t pid;
|
||||||
|
|
||||||
#if defined(HAVE_CRT_EXTERNS_H)
|
|
||||||
# define environ (*(_NSGetEnviron()))
|
|
||||||
#else
|
|
||||||
extern char** environ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pid = HAWK_FORK();
|
pid = HAWK_FORK();
|
||||||
if (pid <= -1)
|
if (pid <= -1)
|
||||||
{
|
{
|
||||||
@@ -574,7 +568,6 @@ static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], para
|
|||||||
if (pio->flags & HAWK_PIO_DROPOUT) HAWK_CLOSE(1);
|
if (pio->flags & HAWK_PIO_DROPOUT) HAWK_CLOSE(1);
|
||||||
if (pio->flags & HAWK_PIO_DROPERR) HAWK_CLOSE(2);
|
if (pio->flags & HAWK_PIO_DROPERR) HAWK_CLOSE(2);
|
||||||
|
|
||||||
|
|
||||||
if (pio->flags & HAWK_PIO_FNCCMD)
|
if (pio->flags & HAWK_PIO_FNCCMD)
|
||||||
{
|
{
|
||||||
/* -----------------------------------------------
|
/* -----------------------------------------------
|
||||||
@@ -583,7 +576,10 @@ static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], para
|
|||||||
hawk_pio_fnc_t* fnc = (hawk_pio_fnc_t*)param;
|
hawk_pio_fnc_t* fnc = (hawk_pio_fnc_t*)param;
|
||||||
int retx;
|
int retx;
|
||||||
|
|
||||||
retx = fnc->ptr(fnc->ctx, envp);
|
/* when the function pointer is a worker function,
|
||||||
|
* the function must use the context(fnc->ctx) passed
|
||||||
|
* in as a paramter to find out actual environmen values (e.g. ENVIRON) */
|
||||||
|
retx = fnc->ptr(fnc->ctx);
|
||||||
if (devnull >= 0) HAWK_CLOSE(devnull);
|
if (devnull >= 0) HAWK_CLOSE(devnull);
|
||||||
HAWK_EXIT(retx);
|
HAWK_EXIT(retx);
|
||||||
}
|
}
|
||||||
@@ -619,7 +615,7 @@ static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int flags)
|
int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int flags, hawk_pio_env_mk_t env_mk, void* env_ctx)
|
||||||
{
|
{
|
||||||
hawk_pio_hnd_t handle[6] /*=
|
hawk_pio_hnd_t handle[6] /*=
|
||||||
{
|
{
|
||||||
@@ -673,29 +669,14 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
|
|||||||
posix_spawnattr_t psattr;
|
posix_spawnattr_t psattr;
|
||||||
hawk_pio_pid_t pid;
|
hawk_pio_pid_t pid;
|
||||||
param_t param;
|
param_t param;
|
||||||
#if defined(HAVE_CRT_EXTERNS_H)
|
|
||||||
#define environ (*(_NSGetEnviron()))
|
|
||||||
#else
|
|
||||||
extern char** environ;
|
|
||||||
#endif
|
|
||||||
#elif defined(HAWK_SYSCALL0) && defined(SYS_vfork)
|
#elif defined(HAWK_SYSCALL0) && defined(SYS_vfork)
|
||||||
hawk_pio_pid_t pid;
|
hawk_pio_pid_t pid;
|
||||||
param_t param;
|
param_t param;
|
||||||
#if defined(HAVE_CRT_EXTERNS_H)
|
|
||||||
#define environ (*(_NSGetEnviron()))
|
|
||||||
#else
|
|
||||||
extern char** environ;
|
|
||||||
#endif
|
|
||||||
int highest_fd;
|
int highest_fd;
|
||||||
int dummy;
|
int dummy;
|
||||||
#else
|
#else
|
||||||
hawk_pio_pid_t pid;
|
hawk_pio_pid_t pid;
|
||||||
param_t param;
|
param_t param;
|
||||||
#if defined(HAVE_CRT_EXTERNS_H)
|
|
||||||
#define environ (*(_NSGetEnviron()))
|
|
||||||
#else
|
|
||||||
extern char** environ;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HAWK_MEMSET(pio, 0, HAWK_SIZEOF(*pio));
|
HAWK_MEMSET(pio, 0, HAWK_SIZEOF(*pio));
|
||||||
@@ -1276,7 +1257,7 @@ create_process:
|
|||||||
HAWK_SIZEOF(load_error),
|
HAWK_SIZEOF(load_error),
|
||||||
EXEC_ASYNCRESULT,
|
EXEC_ASYNCRESULT,
|
||||||
cmd_line,
|
cmd_line,
|
||||||
HAWK_NULL,
|
HAWK_NULL, /* environment - e.g. "PATH=/bin\0HOME=/tmp\0FOO=bar\0\0" */
|
||||||
&child_rc,
|
&child_rc,
|
||||||
cmd_file
|
cmd_file
|
||||||
);
|
);
|
||||||
@@ -1307,7 +1288,6 @@ create_process:
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (flags & HAWK_PIO_WRITEIN)
|
if (flags & HAWK_PIO_WRITEIN)
|
||||||
{
|
{
|
||||||
if (HAWK_PIPE(&handle[0]) <= -1)
|
if (HAWK_PIPE(&handle[0]) <= -1)
|
||||||
@@ -1350,12 +1330,32 @@ create_process:
|
|||||||
{
|
{
|
||||||
/* i know i'm abusing typecasting here.
|
/* i know i'm abusing typecasting here.
|
||||||
* cmd is supposed to be hawk_pio_fnc_t*, anyway */
|
* cmd is supposed to be hawk_pio_fnc_t*, anyway */
|
||||||
pid = standard_fork_and_exec(pio, handle, (param_t*)cmd, environ);
|
pid = standard_fork_and_exec(pio, handle, (param_t*)cmd, HAWK_NULL);
|
||||||
if (pid <= -1) goto oops;
|
if (pid <= -1) goto oops;
|
||||||
pio->child = pid;
|
pio->child = pid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char*const* envp;
|
||||||
|
|
||||||
|
if (env_mk)
|
||||||
|
{
|
||||||
|
envp = (char*const*)env_mk(HAWK_PIO_ENV_MK_BCH_PP, env_ctx);
|
||||||
|
if (HAWK_UNLIKELY(!envp)) goto oops;
|
||||||
|
/* pio doesn't free the memory block returned by the callback function.
|
||||||
|
* there is no callback triggered for dealloction either.
|
||||||
|
* the caller side must do track heap memory chunks allocated for this environment */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(HAVE_CRT_EXTERNS_H)
|
||||||
|
#define environ (*(_NSGetEnviron()))
|
||||||
|
#else
|
||||||
|
extern char** environ;
|
||||||
|
#endif
|
||||||
|
envp = environ;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(HAVE_POSIX_SPAWN) && !(defined(HAWK_SYSCALL0) && defined(SYS_vfork))
|
#if defined(HAVE_POSIX_SPAWN) && !(defined(HAWK_SYSCALL0) && defined(SYS_vfork))
|
||||||
|
|
||||||
if ((pserr = posix_spawn_file_actions_init(&fa)) != 0)
|
if ((pserr = posix_spawn_file_actions_init(&fa)) != 0)
|
||||||
@@ -1531,7 +1531,7 @@ create_process:
|
|||||||
posix_spawnattr_setflags (&psattr, POSIX_SPAWN_USEVFORK);
|
posix_spawnattr_setflags (&psattr, POSIX_SPAWN_USEVFORK);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pserr = posix_spawn(&pid, param.argv[0], &fa, &psattr, param.argv, environ);
|
pserr = posix_spawn(&pid, param.argv[0], &fa, &psattr, param.argv, envp);
|
||||||
|
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
posix_spawnattr_destroy (&psattr);
|
posix_spawnattr_destroy (&psattr);
|
||||||
@@ -1683,7 +1683,7 @@ create_process:
|
|||||||
if (flags & HAWK_PIO_DROPOUT) HAWK_SYSCALL1(dummy, SYS_close, 1);
|
if (flags & HAWK_PIO_DROPOUT) HAWK_SYSCALL1(dummy, SYS_close, 1);
|
||||||
if (flags & HAWK_PIO_DROPERR) HAWK_SYSCALL1(dummy, SYS_close, 2);
|
if (flags & HAWK_PIO_DROPERR) HAWK_SYSCALL1(dummy, SYS_close, 2);
|
||||||
|
|
||||||
HAWK_SYSCALL3(dummy, SYS_execve, param.argv[0], param.argv, environ);
|
HAWK_SYSCALL3(dummy, SYS_execve, param.argv[0], param.argv, envp);
|
||||||
/*free_param(pio, ¶m); don't free this in the vfork version */
|
/*free_param(pio, ¶m); don't free this in the vfork version */
|
||||||
|
|
||||||
child_oops:
|
child_oops:
|
||||||
@@ -1696,7 +1696,6 @@ create_process:
|
|||||||
pio->child = pid;
|
pio->child = pid;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (make_param(pio, cmd, flags, ¶m) <= -1) goto oops;
|
if (make_param(pio, cmd, flags, ¶m) <= -1) goto oops;
|
||||||
|
|
||||||
/* check if the command(the command requested or /bin/sh) is
|
/* check if the command(the command requested or /bin/sh) is
|
||||||
@@ -1708,7 +1707,7 @@ create_process:
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = standard_fork_and_exec(pio, handle, ¶m, environ);
|
pid = standard_fork_and_exec(pio, handle, ¶m, envp);
|
||||||
if (pid <= -1)
|
if (pid <= -1)
|
||||||
{
|
{
|
||||||
free_param(pio, ¶m);
|
free_param(pio, ¶m);
|
||||||
@@ -1719,7 +1718,6 @@ create_process:
|
|||||||
free_param(pio, ¶m);
|
free_param(pio, ¶m);
|
||||||
pio->child = pid;
|
pio->child = pid;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & HAWK_PIO_WRITEIN)
|
if (flags & HAWK_PIO_WRITEIN)
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ int hawk_rbt_init (hawk_rbt_t* rbt, hawk_gem_t* gem, int kscale, int vscale)
|
|||||||
rbt->scale[HAWK_RBT_KEY] = (kscale < 1)? 1: kscale;
|
rbt->scale[HAWK_RBT_KEY] = (kscale < 1)? 1: kscale;
|
||||||
rbt->scale[HAWK_RBT_VAL] = (vscale < 1)? 1: vscale;
|
rbt->scale[HAWK_RBT_VAL] = (vscale < 1)? 1: vscale;
|
||||||
rbt->size = 0;
|
rbt->size = 0;
|
||||||
|
rbt->rev = 0;
|
||||||
|
|
||||||
rbt->style = &style[0];
|
rbt->style = &style[0];
|
||||||
|
|
||||||
@@ -262,6 +263,11 @@ hawk_oow_t hawk_rbt_getsize (const hawk_rbt_t* rbt)
|
|||||||
return rbt->size;
|
return rbt->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hawk_oow_t hawk_rbt_getrev (const hawk_rbt_t* rbt)
|
||||||
|
{
|
||||||
|
return rbt->rev;
|
||||||
|
}
|
||||||
|
|
||||||
hawk_rbt_pair_t* hawk_rbt_search (const hawk_rbt_t* rbt, const void* kptr, hawk_oow_t klen)
|
hawk_rbt_pair_t* hawk_rbt_search (const hawk_rbt_t* rbt, const void* kptr, hawk_oow_t klen)
|
||||||
{
|
{
|
||||||
hawk_rbt_pair_t* pair = rbt->root;
|
hawk_rbt_pair_t* pair = rbt->root;
|
||||||
@@ -506,7 +512,9 @@ static hawk_rbt_pair_t* insert (hawk_rbt_t* rbt, void* kptr, hawk_oow_t klen, vo
|
|||||||
{
|
{
|
||||||
case UPSERT:
|
case UPSERT:
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
return change_pair_val(rbt, x_cur, vptr, vlen);
|
x_cur = change_pair_val(rbt, x_cur, vptr, vlen);
|
||||||
|
if (HAWK_LIKELY(x_cur)) rbt->rev++;
|
||||||
|
return x_cur;
|
||||||
|
|
||||||
case ENSERT:
|
case ENSERT:
|
||||||
/* return existing pair */
|
/* return existing pair */
|
||||||
@@ -561,6 +569,7 @@ static hawk_rbt_pair_t* insert (hawk_rbt_t* rbt, void* kptr, hawk_oow_t klen, vo
|
|||||||
|
|
||||||
rbt->root->color = HAWK_RBT_BLACK;
|
rbt->root->color = HAWK_RBT_BLACK;
|
||||||
rbt->size++;
|
rbt->size++;
|
||||||
|
rbt->rev++;
|
||||||
return x_new;
|
return x_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,6 +648,7 @@ hawk_rbt_pair_t* hawk_rbt_cbsert (hawk_rbt_t* rbt, void* kptr, hawk_oow_t klen,
|
|||||||
if (x_cur == rbt->root) rbt->root = x_new;
|
if (x_cur == rbt->root) rbt->root = x_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rbt->rev++;
|
||||||
return x_new;
|
return x_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,6 +688,7 @@ hawk_rbt_pair_t* hawk_rbt_cbsert (hawk_rbt_t* rbt, void* kptr, hawk_oow_t klen,
|
|||||||
|
|
||||||
rbt->root->color = HAWK_RBT_BLACK;
|
rbt->root->color = HAWK_RBT_BLACK;
|
||||||
rbt->size++;
|
rbt->size++;
|
||||||
|
rbt->rev++;
|
||||||
return x_new;
|
return x_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,6 +848,7 @@ static void delete_pair (hawk_rbt_t* rbt, hawk_rbt_pair_t* pair)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rbt->size--;
|
rbt->size--;
|
||||||
|
rbt->rev++;
|
||||||
|
|
||||||
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
#if defined(HAWK_ENABLE_RBT_ITR_PROTECTION)
|
||||||
/* an iterator set by hawk_rbt_getfirstpair() or hawk_rbt_getnextpair(), if deleted, gets invalidated.
|
/* an iterator set by hawk_rbt_getfirstpair() or hawk_rbt_getnextpair(), if deleted, gets invalidated.
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ typedef struct rxtn_t
|
|||||||
hawk_htb_t cmgrtab;
|
hawk_htb_t cmgrtab;
|
||||||
|
|
||||||
hawk_rtx_ecb_t ecb;
|
hawk_rtx_ecb_t ecb;
|
||||||
|
|
||||||
|
void* envp; /* cached environment value */
|
||||||
|
hawk_map_t* env_map;
|
||||||
|
hawk_oow_t env_map_rev;
|
||||||
} rxtn_t;
|
} rxtn_t;
|
||||||
|
|
||||||
typedef struct ioattr_t
|
typedef struct ioattr_t
|
||||||
@@ -208,6 +212,14 @@ static HAWK_INLINE rxtn_t* GET_RXTN(hawk_rtx_t* rtx) { return (rxtn_t*)((hawk_ui
|
|||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
/* TODO: use wenviron where it's available */
|
||||||
|
typedef hawk_bch_t env_char_t;
|
||||||
|
#define ENV_CHAR_IS_BCH
|
||||||
|
|
||||||
|
|
||||||
|
static env_char_t** commit_environ (hawk_rtx_t* rtx, int gbl_id);
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
static void* sys_alloc (hawk_mmgr_t* mmgr, hawk_oow_t size)
|
static void* sys_alloc (hawk_mmgr_t* mmgr, hawk_oow_t size)
|
||||||
{
|
{
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
@@ -2036,6 +2048,58 @@ static int parse_rwpipe_uri (const hawk_ooch_t* uri, int* flags, hawk_nwad_t* nw
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void* envp_maker (hawk_pio_env_mk_type_t env_mk_type, void* ctx)
|
||||||
|
{
|
||||||
|
hawk_rtx_t* rtx = ctx;
|
||||||
|
hawk_t* hawk = hawk_rtx_gethawk(rtx);
|
||||||
|
|
||||||
|
if (env_mk_type == HAWK_PIO_ENV_MK_BCH_PP)
|
||||||
|
{
|
||||||
|
hawk_val_t* v_env;
|
||||||
|
hawk_map_t* env_map;
|
||||||
|
hawk_oow_t env_map_rev;
|
||||||
|
env_char_t** envp;
|
||||||
|
xtn_t* xtn;
|
||||||
|
rxtn_t* rxtn;
|
||||||
|
|
||||||
|
xtn = GET_XTN(hawk);
|
||||||
|
rxtn = GET_RXTN(rtx);
|
||||||
|
v_env = hawk_rtx_getgbl(rtx, xtn->gbl_environ);
|
||||||
|
HAWK_ASSERT(v_env != HAWK_NULL);
|
||||||
|
|
||||||
|
if (HAWK_RTX_GETVALTYPE(rtx, v_env) == HAWK_VAL_MAP)
|
||||||
|
{
|
||||||
|
env_map = ((hawk_val_map_t*)v_env)->map;
|
||||||
|
HAWK_ASSERT(env_map != HAWK_NULL);
|
||||||
|
env_map_rev = HAWK_MAP_REV(env_map);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
env_map = HAWK_NULL;
|
||||||
|
env_map_rev = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rxtn->envp ||
|
||||||
|
rxtn->env_map != env_map ||
|
||||||
|
(env_map && rxtn->env_map_rev != env_map_rev))
|
||||||
|
{
|
||||||
|
envp = commit_environ(rtx, xtn->gbl_environ);
|
||||||
|
if (!envp) return HAWK_NULL;
|
||||||
|
|
||||||
|
if (rxtn->envp) hawk_rtx_freemem(rtx, rxtn->envp);
|
||||||
|
rxtn->envp = envp;
|
||||||
|
rxtn->env_map = env_map;
|
||||||
|
rxtn->env_map_rev = env_map_rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rxtn->envp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: support more types */
|
||||||
|
/* unsupported env_mk_type */
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static hawk_ooi_t pio_handler_open (hawk_rtx_t* rtx, hawk_rio_arg_t* riod)
|
static hawk_ooi_t pio_handler_open (hawk_rtx_t* rtx, hawk_rio_arg_t* riod)
|
||||||
{
|
{
|
||||||
hawk_pio_t* handle;
|
hawk_pio_t* handle;
|
||||||
@@ -2074,9 +2138,11 @@ static hawk_ooi_t pio_handler_open (hawk_rtx_t* rtx, hawk_rio_arg_t* riod)
|
|||||||
hawk_rtx_getgem(rtx),
|
hawk_rtx_getgem(rtx),
|
||||||
0,
|
0,
|
||||||
riod->name,
|
riod->name,
|
||||||
flags | HAWK_PIO_SHELL | HAWK_PIO_TEXT | HAWK_PIO_IGNOREECERR
|
flags | HAWK_PIO_SHELL | HAWK_PIO_TEXT | HAWK_PIO_IGNOREECERR,
|
||||||
|
envp_maker,
|
||||||
|
rtx
|
||||||
);
|
);
|
||||||
if (handle == HAWK_NULL) return -1;
|
if (!handle) return -1;
|
||||||
|
|
||||||
#if defined(HAWK_OOCH_IS_UCH)
|
#if defined(HAWK_OOCH_IS_UCH)
|
||||||
{
|
{
|
||||||
@@ -2776,6 +2842,14 @@ static void fini_rxtn (hawk_rtx_t* rtx, void* ctx)
|
|||||||
hawk_htb_fini(&rxtn->cmgrtab);
|
hawk_htb_fini(&rxtn->cmgrtab);
|
||||||
rxtn->cmgrtab_inited = 0;
|
rxtn->cmgrtab_inited = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rxtn->envp)
|
||||||
|
{
|
||||||
|
hawk_rtx_freemem(rtx, rxtn->envp);
|
||||||
|
rxtn->envp = HAWK_NULL;
|
||||||
|
}
|
||||||
|
rxtn->env_map = HAWK_NULL;
|
||||||
|
rxtn->env_map_rev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int build_argcv (hawk_rtx_t* rtx, int argc_id, int argv_id, const hawk_ooch_t* id, hawk_ooch_t* icf[])
|
static int build_argcv (hawk_rtx_t* rtx, int argc_id, int argv_id, const hawk_ooch_t* id, hawk_ooch_t* icf[])
|
||||||
@@ -2876,16 +2950,6 @@ static int build_argcv (hawk_rtx_t* rtx, int argc_id, int argv_id, const hawk_oo
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: use wenviron where it's available */
|
|
||||||
typedef hawk_bch_t env_char_t;
|
|
||||||
#define ENV_CHAR_IS_BCH
|
|
||||||
|
|
||||||
#if defined(HAVE_CRT_EXTERNS_H)
|
|
||||||
#define environ (*(_NSGetEnviron()))
|
|
||||||
#else
|
|
||||||
extern char** environ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int build_environ (hawk_rtx_t* rtx, int gbl_id, env_char_t* envarr[])
|
static int build_environ (hawk_rtx_t* rtx, int gbl_id, env_char_t* envarr[])
|
||||||
{
|
{
|
||||||
hawk_val_t* v_env;
|
hawk_val_t* v_env;
|
||||||
@@ -3015,8 +3079,179 @@ static int build_environ (hawk_rtx_t* rtx, int gbl_id, env_char_t* envarr[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static env_char_t** commit_environ (hawk_rtx_t* rtx, int gbl_id)
|
||||||
|
{
|
||||||
|
hawk_val_t* v_env;
|
||||||
|
hawk_map_t* map;
|
||||||
|
hawk_map_itr_t itr;
|
||||||
|
hawk_map_pair_t* pair;
|
||||||
|
env_char_t** envp;
|
||||||
|
env_char_t* ptr;
|
||||||
|
hawk_oow_t count, ptr_bytes, str_bytes;
|
||||||
|
|
||||||
|
v_env = hawk_rtx_getgbl(rtx, gbl_id);
|
||||||
|
HAWK_ASSERT(v_env != HAWK_NULL);
|
||||||
|
|
||||||
|
if (HAWK_RTX_GETVALTYPE(rtx, v_env) != HAWK_VAL_MAP)
|
||||||
|
{
|
||||||
|
/* it may be nil. but we can't prevent ENVIRON from being set to
|
||||||
|
* other scalar types, we should handle this case gracefully */
|
||||||
|
envp = (env_char_t**)hawk_rtx_allocmem(rtx, HAWK_SIZEOF(*envp) * 1);
|
||||||
|
if (HAWK_UNLIKELY(!envp)) return HAWK_NULL;
|
||||||
|
envp[0] = HAWK_NULL;
|
||||||
|
return envp;
|
||||||
|
}
|
||||||
|
|
||||||
|
map = ((hawk_val_map_t*)v_env)->map;
|
||||||
|
HAWK_ASSERT(map != HAWK_NULL);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
str_bytes = 0;
|
||||||
|
|
||||||
|
hawk_init_map_itr(&itr, 0);
|
||||||
|
pair = hawk_map_getfirstpair(map, &itr);
|
||||||
|
while (pair)
|
||||||
|
{
|
||||||
|
hawk_oow_t klen, vlen;
|
||||||
|
|
||||||
|
klen = HAWK_MAP_KLEN(pair);
|
||||||
|
#if defined(ENV_CHAR_IS_BCH) && defined(HAWK_OOCH_IS_UCH)
|
||||||
|
{
|
||||||
|
hawk_oow_t tmp_ulen, tmp_blen;
|
||||||
|
tmp_ulen = klen;
|
||||||
|
if (hawk_rtx_convutobchars(rtx, HAWK_MAP_KPTR(pair), &tmp_ulen, HAWK_NULL, &tmp_blen) <= -1) return HAWK_NULL;
|
||||||
|
klen = tmp_blen;
|
||||||
|
}
|
||||||
|
#elif defined(ENV_CHAR_IS_UCH) && defined(HAWK_OOCH_IS_BCH)
|
||||||
|
{
|
||||||
|
hawk_oow_t tmp_blen, tmp_ulen;
|
||||||
|
tmp_blen = klen;
|
||||||
|
if (hawk_rtx_convbtouchars(rtx, HAWK_MAP_KPTR(pair), &tmp_blen, HAWK_NULL, &tmp_ulen, 1) <= -1) return HAWK_NULL;
|
||||||
|
klen = tmp_ulen;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENV_CHAR_IS_BCH)
|
||||||
|
{
|
||||||
|
hawk_bch_t* vptr;
|
||||||
|
vptr = hawk_rtx_getvalbcstr(rtx, HAWK_MAP_VPTR(pair), &vlen);
|
||||||
|
if (HAWK_UNLIKELY(!vptr)) return HAWK_NULL;
|
||||||
|
hawk_rtx_freevalbcstr(rtx, HAWK_MAP_VPTR(pair), vptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
hawk_uch_t* vptr;
|
||||||
|
vptr = hawk_rtx_getvalucstr(rtx, HAWK_MAP_VPTR(pair), &vlen);
|
||||||
|
if (HAWK_UNLIKELY(!vptr)) return HAWK_NULL;
|
||||||
|
hawk_rtx_freevalucstr(rtx, HAWK_MAP_VPTR(pair), vptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
str_bytes += klen + 1 + vlen + 1;
|
||||||
|
count++;
|
||||||
|
pair = hawk_map_getnextpair(map, &itr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_bytes = HAWK_SIZEOF(*envp) * (count + 1);
|
||||||
|
envp = (env_char_t**)hawk_rtx_allocmem(rtx, ptr_bytes + (str_bytes * HAWK_SIZEOF(*ptr)));
|
||||||
|
if (HAWK_UNLIKELY(!envp)) return HAWK_NULL;
|
||||||
|
|
||||||
|
ptr = (env_char_t*)((hawk_uint8_t*)envp + ptr_bytes);
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
hawk_init_map_itr(&itr, 0);
|
||||||
|
pair = hawk_map_getfirstpair(map, &itr);
|
||||||
|
while (pair)
|
||||||
|
{
|
||||||
|
hawk_oow_t klen, vlen;
|
||||||
|
|
||||||
|
envp[count++] = ptr;
|
||||||
|
klen = HAWK_MAP_KLEN(pair);
|
||||||
|
|
||||||
|
#if ((defined(ENV_CHAR_IS_BCH) && defined(HAWK_OOCH_IS_BCH)) || \
|
||||||
|
(defined(ENV_CHAR_IS_UCH) && defined(HAWK_OOCH_IS_UCH)))
|
||||||
|
HAWK_MEMCPY(ptr, HAWK_MAP_KPTR(pair), klen);
|
||||||
|
ptr += klen;
|
||||||
|
#elif defined(ENV_CHAR_IS_BCH)
|
||||||
|
{
|
||||||
|
hawk_oow_t tmp_ulen, tmp_blen;
|
||||||
|
|
||||||
|
tmp_ulen = klen;
|
||||||
|
tmp_blen = str_bytes;
|
||||||
|
if (hawk_rtx_convutobchars(rtx, HAWK_MAP_KPTR(pair), &tmp_ulen, ptr, &tmp_blen) <= -1)
|
||||||
|
{
|
||||||
|
hawk_rtx_freemem(rtx, envp);
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
ptr += tmp_blen;
|
||||||
|
klen = tmp_blen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
hawk_oow_t tmp_blen, tmp_ulen;
|
||||||
|
|
||||||
|
tmp_blen = klen;
|
||||||
|
tmp_ulen = str_bytes;
|
||||||
|
if (hawk_rtx_convbtouchars(rtx, HAWK_MAP_KPTR(pair), &tmp_blen, ptr, &tmp_ulen, 1) <= -1)
|
||||||
|
{
|
||||||
|
hawk_rtx_freemem(rtx, envp);
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
ptr += tmp_ulen;
|
||||||
|
klen = tmp_ulen;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*ptr++ = '=';
|
||||||
|
|
||||||
|
#if defined(ENV_CHAR_IS_BCH)
|
||||||
|
{
|
||||||
|
hawk_bch_t* vptr;
|
||||||
|
|
||||||
|
vptr = hawk_rtx_getvalbcstr(rtx, HAWK_MAP_VPTR(pair), &vlen);
|
||||||
|
if (HAWK_UNLIKELY(!vptr))
|
||||||
|
{
|
||||||
|
hawk_rtx_freemem(rtx, envp);
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HAWK_MEMCPY(ptr, vptr, vlen);
|
||||||
|
ptr += vlen;
|
||||||
|
hawk_rtx_freevalbcstr(rtx, HAWK_MAP_VPTR(pair), vptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
hawk_uch_t* vptr;
|
||||||
|
|
||||||
|
vptr = hawk_rtx_getvalucstr(rtx, HAWK_MAP_VPTR(pair), &vlen);
|
||||||
|
if (HAWK_UNLIKELY(!vptr))
|
||||||
|
{
|
||||||
|
hawk_rtx_freemem(rtx, envp);
|
||||||
|
return HAWK_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HAWK_MEMCPY(ptr, vptr, vlen);
|
||||||
|
ptr += vlen;
|
||||||
|
hawk_rtx_freevalucstr(rtx, HAWK_MAP_VPTR(pair), vptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*ptr++ = '\0';
|
||||||
|
pair = hawk_map_getnextpair(map, &itr);
|
||||||
|
}
|
||||||
|
|
||||||
|
envp[count] = HAWK_NULL;
|
||||||
|
return envp;
|
||||||
|
}
|
||||||
|
|
||||||
static int make_additional_globals (hawk_rtx_t* rtx, xtn_t* xtn, const hawk_ooch_t* id, hawk_ooch_t* icf[])
|
static int make_additional_globals (hawk_rtx_t* rtx, xtn_t* xtn, const hawk_ooch_t* id, hawk_ooch_t* icf[])
|
||||||
{
|
{
|
||||||
|
#if defined(HAVE_CRT_EXTERNS_H)
|
||||||
|
#define environ (*(_NSGetEnviron()))
|
||||||
|
#else
|
||||||
|
extern char** environ;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (build_argcv(rtx, xtn->gbl_argc, xtn->gbl_argv, id, icf) <= -1 ||
|
if (build_argcv(rtx, xtn->gbl_argc, xtn->gbl_argv, id, icf) <= -1 ||
|
||||||
build_environ(rtx, xtn->gbl_environ, environ) <= -1) return -1;
|
build_environ(rtx, xtn->gbl_environ, environ) <= -1) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ check_SCRIPTS += h-003.hawk h-004.hawk h-009.hawk h-010.hawk \
|
|||||||
h-016.hawk h-017.hawk h-018.hawk h-019.hawk h-020.hawk \
|
h-016.hawk h-017.hawk h-018.hawk h-019.hawk h-020.hawk \
|
||||||
h-021.hawk h-022.hawk h-023.hawk h-024.hawk
|
h-021.hawk h-022.hawk h-023.hawk h-024.hawk
|
||||||
|
|
||||||
check_SCRIPTS += regress-filename.sh regress-extra-info.sh
|
check_SCRIPTS += regress-filename.sh regress-extra-info.sh regress-environ.sh
|
||||||
|
|
||||||
check_ERRORS = e-001.err
|
check_ERRORS = e-001.err
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -659,7 +659,7 @@ check_SCRIPTS = $(am__append_1) h-003.hawk h-004.hawk h-009.hawk \
|
|||||||
h-010.hawk h-011.hawk h-012.hawk h-013.hawk h-014.hawk \
|
h-010.hawk h-011.hawk h-012.hawk h-013.hawk h-014.hawk \
|
||||||
h-015.hawk h-016.hawk h-017.hawk h-018.hawk h-019.hawk \
|
h-015.hawk h-016.hawk h-017.hawk h-018.hawk h-019.hawk \
|
||||||
h-020.hawk h-021.hawk h-022.hawk h-023.hawk h-024.hawk \
|
h-020.hawk h-021.hawk h-022.hawk h-023.hawk h-024.hawk \
|
||||||
regress-filename.sh regress-extra-info.sh
|
regress-filename.sh regress-extra-info.sh regress-environ.sh
|
||||||
check_ERRORS = e-001.err
|
check_ERRORS = e-001.err
|
||||||
EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
|
EXTRA_DIST = $(check_SCRIPTS) $(check_ERRORS) tap.inc err.sh \
|
||||||
journal-toc.hawk journal-toc.in journal-toc.out journal-toc-html.out \
|
journal-toc.hawk journal-toc.in journal-toc.out journal-toc-html.out \
|
||||||
|
|||||||
Executable
+130
@@ -0,0 +1,130 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
[ $# -ge 1 ] && HAWK_BIN="$1"
|
||||||
|
[ -z "$HAWK_BIN" ] && HAWK_BIN="hawk"
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
tmp_prog="/tmp/hawk-regress-environ-$$.hawk"
|
||||||
|
tmp_pipe="/tmp/hawk-regress-environ-$$.pipe"
|
||||||
|
trap 'rm -f "$tmp_prog" "$tmp_pipe"' EXIT
|
||||||
|
|
||||||
|
cat > "$tmp_prog" <<'EOF'
|
||||||
|
function emit_env(tag, cmd)
|
||||||
|
{
|
||||||
|
cmd = "sh -c 'printf \"" tag ":%s\\n\" \"${HAWK_TEST_ENV_PIPE-unset}\" >&3'"
|
||||||
|
print "" | cmd
|
||||||
|
close(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_INT"]) ":" ENVIRON["HAWK_TEST_ENV_INT"];
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_NEG"]) ":" ENVIRON["HAWK_TEST_ENV_NEG"];
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_FLT"]) ":" sprintf("%.2f", ENVIRON["HAWK_TEST_ENV_FLT"]);
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_STR"]) ":" ENVIRON["HAWK_TEST_ENV_STR"];
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_EMPTY"]) ":" length(ENVIRON["HAWK_TEST_ENV_EMPTY"]);
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_MISSING"]) ":" hawk::isnil(ENVIRON["HAWK_TEST_ENV_MISSING"]);
|
||||||
|
|
||||||
|
ENVIRON["HAWK_TEST_ENV_NEW"] = 456;
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_NEW"]) ":" ENVIRON["HAWK_TEST_ENV_NEW"];
|
||||||
|
|
||||||
|
ENVIRON["HAWK_TEST_ENV_NEW"] = 7.5;
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_NEW"]) ":" sprintf("%.1f", ENVIRON["HAWK_TEST_ENV_NEW"]);
|
||||||
|
|
||||||
|
ENVIRON["HAWK_TEST_ENV_NEW"] = "xyz";
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_NEW"]) ":" ENVIRON["HAWK_TEST_ENV_NEW"];
|
||||||
|
|
||||||
|
delete ENVIRON["HAWK_TEST_ENV_STR"];
|
||||||
|
print hawk::typename(ENVIRON["HAWK_TEST_ENV_STR"]) ":" hawk::isnil(ENVIRON["HAWK_TEST_ENV_STR"]);
|
||||||
|
|
||||||
|
emit_env("initial");
|
||||||
|
ENVIRON["HAWK_TEST_ENV_PIPE"] = "changed";
|
||||||
|
emit_env("changed");
|
||||||
|
delete ENVIRON["HAWK_TEST_ENV_PIPE"];
|
||||||
|
emit_env("deleted");
|
||||||
|
ENVIRON = @{};
|
||||||
|
ENVIRON["HAWK_TEST_ENV_PIPE"] = "replaced";
|
||||||
|
emit_env("replaced");
|
||||||
|
ENVIRON = 123;
|
||||||
|
emit_env("scalar");
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_no=0
|
||||||
|
failed=0
|
||||||
|
|
||||||
|
ok() {
|
||||||
|
test_no=$((test_no + 1))
|
||||||
|
echo "ok $test_no - $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
not_ok() {
|
||||||
|
test_no=$((test_no + 1))
|
||||||
|
failed=1
|
||||||
|
echo "not ok $test_no - $1"
|
||||||
|
echo "# expected: $2"
|
||||||
|
echo "# actual: $3"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_eq() {
|
||||||
|
desc="$1"
|
||||||
|
expected="$2"
|
||||||
|
actual="$3"
|
||||||
|
if [ "x$actual" = "x$expected" ]
|
||||||
|
then
|
||||||
|
ok "$desc"
|
||||||
|
else
|
||||||
|
not_ok "$desc" "$expected" "$actual"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "1..16"
|
||||||
|
|
||||||
|
if out=$(env -i \
|
||||||
|
HAWK_TEST_ENV_INT=123 \
|
||||||
|
HAWK_TEST_ENV_NEG=-7 \
|
||||||
|
HAWK_TEST_ENV_FLT=1.25 \
|
||||||
|
HAWK_TEST_ENV_STR=abc123 \
|
||||||
|
HAWK_TEST_ENV_EMPTY= \
|
||||||
|
HAWK_TEST_ENV_PIPE=initial \
|
||||||
|
"$HAWK_BIN" -f "$tmp_prog" 3>"$tmp_pipe" 2>&1)
|
||||||
|
then
|
||||||
|
ok "run environ regression"
|
||||||
|
else
|
||||||
|
not_ok "run environ regression" "exit code 0" "command failed: $out"
|
||||||
|
out=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
line1=$(printf '%s\n' "$out" | sed -n '1p')
|
||||||
|
line2=$(printf '%s\n' "$out" | sed -n '2p')
|
||||||
|
line3=$(printf '%s\n' "$out" | sed -n '3p')
|
||||||
|
line4=$(printf '%s\n' "$out" | sed -n '4p')
|
||||||
|
line5=$(printf '%s\n' "$out" | sed -n '5p')
|
||||||
|
line6=$(printf '%s\n' "$out" | sed -n '6p')
|
||||||
|
line7=$(printf '%s\n' "$out" | sed -n '7p')
|
||||||
|
line8=$(printf '%s\n' "$out" | sed -n '8p')
|
||||||
|
line9=$(printf '%s\n' "$out" | sed -n '9p')
|
||||||
|
line10=$(printf '%s\n' "$out" | sed -n '10p')
|
||||||
|
pipe1=$(sed -n '1p' "$tmp_pipe")
|
||||||
|
pipe2=$(sed -n '2p' "$tmp_pipe")
|
||||||
|
pipe3=$(sed -n '3p' "$tmp_pipe")
|
||||||
|
pipe4=$(sed -n '4p' "$tmp_pipe")
|
||||||
|
pipe5=$(sed -n '5p' "$tmp_pipe")
|
||||||
|
|
||||||
|
check_eq "int env imported as int" "int:123" "$line1"
|
||||||
|
check_eq "negative int env imported as int" "int:-7" "$line2"
|
||||||
|
check_eq "float env imported as flt" "flt:1.25" "$line3"
|
||||||
|
check_eq "string env imported as str" "str:abc123" "$line4"
|
||||||
|
check_eq "empty env imported as empty string" "str:0" "$line5"
|
||||||
|
check_eq "missing env yields nil" "nil:1" "$line6"
|
||||||
|
check_eq "assigned int remains int" "int:456" "$line7"
|
||||||
|
check_eq "assigned float remains flt" "flt:7.5" "$line8"
|
||||||
|
check_eq "assigned string remains str" "str:xyz" "$line9"
|
||||||
|
check_eq "deleted env entry becomes nil" "nil:1" "$line10"
|
||||||
|
check_eq "pipe sees initial imported env" "initial:initial" "$pipe1"
|
||||||
|
check_eq "pipe sees in-place env update" "changed:changed" "$pipe2"
|
||||||
|
check_eq "pipe sees deleted env entry" "deleted:unset" "$pipe3"
|
||||||
|
check_eq "pipe sees replaced environ map" "replaced:replaced" "$pipe4"
|
||||||
|
check_eq "pipe sees scalar environ as empty" "scalar:unset" "$pipe5"
|
||||||
|
|
||||||
|
exit "$failed"
|
||||||
Reference in New Issue
Block a user