| File: | libs/apr-util/hooks/apr_hooks.c |
| Location: | line 183, column 17 |
| Description: | Access to field 'pNext' results in a dereference of a null pointer (loaded from variable 'pTail') |
| 1 | /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as | |||
| 2 | * applicable. | |||
| 3 | * | |||
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| 5 | * you may not use this file except in compliance with the License. | |||
| 6 | * You may obtain a copy of the License at | |||
| 7 | * | |||
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | |||
| 9 | * | |||
| 10 | * Unless required by applicable law or agreed to in writing, software | |||
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | |||
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| 13 | * See the License for the specific language governing permissions and | |||
| 14 | * limitations under the License. | |||
| 15 | */ | |||
| 16 | ||||
| 17 | #include <assert.h> | |||
| 18 | #include <stdio.h> | |||
| 19 | #include <stdlib.h> | |||
| 20 | ||||
| 21 | #include "apr_pools.h" | |||
| 22 | #include "apr_tables.h" | |||
| 23 | #include "apr.h" | |||
| 24 | #include "apr_hooks.h" | |||
| 25 | #include "apr_hash.h" | |||
| 26 | #include "apr_optional_hooks.h" | |||
| 27 | #include "apr_optional.h" | |||
| 28 | #define APR_WANT_MEMFUNC | |||
| 29 | #define APR_WANT_STRFUNC | |||
| 30 | #include "apr_want.h" | |||
| 31 | ||||
| 32 | #if 0 | |||
| 33 | #define apr_palloc(pool,size) malloc(size) | |||
| 34 | #endif | |||
| 35 | ||||
| 36 | APU_DECLARE_DATA apr_pool_t *apr_hook_global_pool = NULL((void*)0); | |||
| 37 | APU_DECLARE_DATA int apr_hook_debug_enabled = 0; | |||
| 38 | APU_DECLARE_DATA const char *apr_hook_debug_current = NULL((void*)0); | |||
| 39 | ||||
| 40 | /** @deprecated @see apr_hook_global_pool */ | |||
| 41 | APU_DECLARE_DATA apr_pool_t *apr_global_hook_pool = NULL((void*)0); | |||
| 42 | ||||
| 43 | /** @deprecated @see apr_hook_debug_enabled */ | |||
| 44 | APU_DECLARE_DATA int apr_debug_module_hooks = 0; | |||
| 45 | ||||
| 46 | /** @deprecated @see apr_hook_debug_current */ | |||
| 47 | APU_DECLARE_DATA const char *apr_current_hooking_module = NULL((void*)0); | |||
| 48 | ||||
| 49 | /* NB: This must echo the LINK_##name structure */ | |||
| 50 | typedef struct | |||
| 51 | { | |||
| 52 | void (*dummy)(void *); | |||
| 53 | const char *szName; | |||
| 54 | const char * const *aszPredecessors; | |||
| 55 | const char * const *aszSuccessors; | |||
| 56 | int nOrder; | |||
| 57 | } TSortData; | |||
| 58 | ||||
| 59 | typedef struct tsort_ | |||
| 60 | { | |||
| 61 | void *pData; | |||
| 62 | int nPredecessors; | |||
| 63 | struct tsort_ **ppPredecessors; | |||
| 64 | struct tsort_ *pNext; | |||
| 65 | } TSort; | |||
| 66 | ||||
| 67 | #ifdef NETWARE | |||
| 68 | #include "apr_private.h" | |||
| 69 | #define get_apd APP_DATA* apd = (APP_DATA*)get_app_data(gLibId); | |||
| 70 | #define s_aHooksToSort ((apr_array_header_t *)(apd->gs_aHooksToSort)) | |||
| 71 | #define s_phOptionalHooks ((apr_hash_t *)(apd->gs_phOptionalHooks)) | |||
| 72 | #define s_phOptionalFunctions ((apr_hash_t *)(apd->gs_phOptionalFunctions)) | |||
| 73 | #endif | |||
| 74 | ||||
| 75 | static int crude_order(const void *a_,const void *b_) | |||
| 76 | { | |||
| 77 | const TSortData *a=a_; | |||
| 78 | const TSortData *b=b_; | |||
| 79 | ||||
| 80 | return a->nOrder-b->nOrder; | |||
| 81 | } | |||
| 82 | ||||
| 83 | static TSort *prepare(apr_pool_t *p,TSortData *pItems,int nItems) | |||
| 84 | { | |||
| 85 | TSort *pData=apr_palloc(p,nItems*sizeof *pData); | |||
| 86 | int n; | |||
| 87 | ||||
| 88 | qsort(pItems,nItems,sizeof *pItems,crude_order); | |||
| 89 | for(n=0 ; n < nItems ; ++n) { | |||
| 90 | pData[n].nPredecessors=0; | |||
| 91 | pData[n].ppPredecessors=apr_pcalloc(p,nItems*sizeof *pData[n].ppPredecessors)memset(apr_palloc(p, nItems*sizeof *pData[n].ppPredecessors), 0, nItems*sizeof *pData[n].ppPredecessors); | |||
| 92 | pData[n].pNext=NULL((void*)0); | |||
| 93 | pData[n].pData=&pItems[n]; | |||
| 94 | } | |||
| 95 | ||||
| 96 | for(n=0 ; n < nItems ; ++n) { | |||
| 97 | int i,k; | |||
| 98 | ||||
| 99 | for(i=0 ; pItems[n].aszPredecessors && pItems[n].aszPredecessors[i] ; ++i) | |||
| 100 | for(k=0 ; k < nItems ; ++k) | |||
| 101 | if(!strcmp(pItems[k].szName,pItems[n].aszPredecessors[i])__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (pItems[k].szName) && __builtin_constant_p (pItems[n ].aszPredecessors[i]) && (__s1_len = __builtin_strlen (pItems[k].szName), __s2_len = __builtin_strlen (pItems[n].aszPredecessors [i]), (!((size_t)(const void *)((pItems[k].szName) + 1) - (size_t )(const void *)(pItems[k].szName) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((pItems[n].aszPredecessors[i]) + 1 ) - (size_t)(const void *)(pItems[n].aszPredecessors[i]) == 1 ) || __s2_len >= 4)) ? __builtin_strcmp (pItems[k].szName, pItems[n].aszPredecessors[i]) : (__builtin_constant_p (pItems [k].szName) && ((size_t)(const void *)((pItems[k].szName ) + 1) - (size_t)(const void *)(pItems[k].szName) == 1) && (__s1_len = __builtin_strlen (pItems[k].szName), __s1_len < 4) ? (__builtin_constant_p (pItems[n].aszPredecessors[i]) && ((size_t)(const void *)((pItems[n].aszPredecessors[i]) + 1) - (size_t)(const void *)(pItems[n].aszPredecessors[i]) == 1) ? __builtin_strcmp (pItems[k].szName, pItems[n].aszPredecessors [i]) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (pItems[n].aszPredecessors[i]); int __result = (((const unsigned char *) (const char *) (pItems[k].szName ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (pItems [k].szName))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( pItems[k].szName))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (pItems[k].szName))[3] - __s2[3]); } } __result; }))) : ( __builtin_constant_p (pItems[n].aszPredecessors[i]) && ((size_t)(const void *)((pItems[n].aszPredecessors[i]) + 1) - (size_t)(const void *)(pItems[n].aszPredecessors[i]) == 1) && (__s2_len = __builtin_strlen (pItems[n].aszPredecessors[i]), __s2_len < 4) ? (__builtin_constant_p (pItems[k].szName) && ((size_t)(const void *)((pItems[k].szName) + 1) - (size_t)(const void *)(pItems[k].szName) == 1) ? __builtin_strcmp (pItems[k ].szName, pItems[n].aszPredecessors[i]) : (- (__extension__ ( { const unsigned char *__s2 = (const unsigned char *) (const char *) (pItems[k].szName); int __result = (((const unsigned char *) (const char *) (pItems[n].aszPredecessors[i]))[0] - __s2[ 0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (pItems[n].aszPredecessors [i]))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (pItems [n].aszPredecessors[i]))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (pItems[n].aszPredecessors[i]))[3] - __s2[3]); } } __result ; })))) : __builtin_strcmp (pItems[k].szName, pItems[n].aszPredecessors [i])))); })) { | |||
| 102 | int l; | |||
| 103 | ||||
| 104 | for(l=0 ; l < pData[n].nPredecessors ; ++l) | |||
| 105 | if(pData[n].ppPredecessors[l] == &pData[k]) | |||
| 106 | goto got_it; | |||
| 107 | pData[n].ppPredecessors[pData[n].nPredecessors]=&pData[k]; | |||
| 108 | ++pData[n].nPredecessors; | |||
| 109 | got_it: | |||
| 110 | break; | |||
| 111 | } | |||
| 112 | for(i=0 ; pItems[n].aszSuccessors && pItems[n].aszSuccessors[i] ; ++i) | |||
| 113 | for(k=0 ; k < nItems ; ++k) | |||
| 114 | if(!strcmp(pItems[k].szName,pItems[n].aszSuccessors[i])__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (pItems[k].szName) && __builtin_constant_p (pItems[n ].aszSuccessors[i]) && (__s1_len = __builtin_strlen ( pItems[k].szName), __s2_len = __builtin_strlen (pItems[n].aszSuccessors [i]), (!((size_t)(const void *)((pItems[k].szName) + 1) - (size_t )(const void *)(pItems[k].szName) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((pItems[n].aszSuccessors[i]) + 1) - (size_t)(const void *)(pItems[n].aszSuccessors[i]) == 1) || __s2_len >= 4)) ? __builtin_strcmp (pItems[k].szName, pItems[n].aszSuccessors [i]) : (__builtin_constant_p (pItems[k].szName) && (( size_t)(const void *)((pItems[k].szName) + 1) - (size_t)(const void *)(pItems[k].szName) == 1) && (__s1_len = __builtin_strlen (pItems[k].szName), __s1_len < 4) ? (__builtin_constant_p (pItems[n].aszSuccessors[i]) && ((size_t)(const void *)((pItems[n].aszSuccessors[i]) + 1) - (size_t)(const void * )(pItems[n].aszSuccessors[i]) == 1) ? __builtin_strcmp (pItems [k].szName, pItems[n].aszSuccessors[i]) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (pItems[n].aszSuccessors[i]); int __result = (((const unsigned char *) (const char *) (pItems[k].szName))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (pItems[k].szName))[1] - __s2 [1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (pItems[k].szName ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (pItems [k].szName))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (pItems[n].aszSuccessors[i]) && ((size_t)(const void *)((pItems[n].aszSuccessors[i]) + 1) - (size_t)(const void * )(pItems[n].aszSuccessors[i]) == 1) && (__s2_len = __builtin_strlen (pItems[n].aszSuccessors[i]), __s2_len < 4) ? (__builtin_constant_p (pItems[k].szName) && ((size_t)(const void *)((pItems [k].szName) + 1) - (size_t)(const void *)(pItems[k].szName) == 1) ? __builtin_strcmp (pItems[k].szName, pItems[n].aszSuccessors [i]) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (pItems[k].szName); int __result = (((const unsigned char *) (const char *) (pItems[n].aszSuccessors [i]))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (pItems [n].aszSuccessors[i]))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (pItems[n].aszSuccessors[i]))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (pItems[n].aszSuccessors[i]))[3] - __s2 [3]); } } __result; })))) : __builtin_strcmp (pItems[k].szName , pItems[n].aszSuccessors[i])))); })) { | |||
| 115 | int l; | |||
| 116 | ||||
| 117 | for(l=0 ; l < pData[k].nPredecessors ; ++l) | |||
| 118 | if(pData[k].ppPredecessors[l] == &pData[n]) | |||
| 119 | goto got_it2; | |||
| 120 | pData[k].ppPredecessors[pData[k].nPredecessors]=&pData[n]; | |||
| 121 | ++pData[k].nPredecessors; | |||
| 122 | got_it2: | |||
| 123 | break; | |||
| 124 | } | |||
| 125 | } | |||
| 126 | ||||
| 127 | return pData; | |||
| 128 | } | |||
| 129 | ||||
| 130 | /* Topologically sort, dragging out-of-order items to the front. Note that | |||
| 131 | this tends to preserve things that want to be near the front better, and | |||
| 132 | changing that behaviour might compromise some of Apache's behaviour (in | |||
| 133 | particular, mod_log_forensic might otherwise get pushed to the end, and | |||
| 134 | core.c's log open function used to end up at the end when pushing items | |||
| 135 | to the back was the methedology). Also note that the algorithm could | |||
| 136 | go back to its original simplicity by sorting from the back instead of | |||
| 137 | the front. | |||
| 138 | */ | |||
| 139 | static TSort *tsort(TSort *pData,int nItems) | |||
| 140 | { | |||
| 141 | int nTotal; | |||
| 142 | TSort *pHead=NULL((void*)0); | |||
| 143 | TSort *pTail=NULL((void*)0); | |||
| 144 | ||||
| 145 | for(nTotal=0 ; nTotal < nItems ; ++nTotal) { | |||
| 146 | int n,i,k; | |||
| 147 | ||||
| 148 | for(n=0 ; ; ++n) { | |||
| 149 | if(n == nItems) | |||
| 150 | assert(0)((0) ? (void) (0) : __assert_fail ("0", "hooks/apr_hooks.c", 150 , __PRETTY_FUNCTION__)); /* we have a loop... */ | |||
| 151 | if(!pData[n].pNext) { | |||
| 152 | if(pData[n].nPredecessors) { | |||
| 153 | for(k=0 ; ; ++k) { | |||
| 154 | assert(k < nItems)((k < nItems) ? (void) (0) : __assert_fail ("k < nItems" , "hooks/apr_hooks.c", 154, __PRETTY_FUNCTION__)); | |||
| 155 | if(pData[n].ppPredecessors[k]) | |||
| 156 | break; | |||
| 157 | } | |||
| 158 | for(i=0 ; ; ++i) { | |||
| 159 | assert(i < nItems)((i < nItems) ? (void) (0) : __assert_fail ("i < nItems" , "hooks/apr_hooks.c", 159, __PRETTY_FUNCTION__)); | |||
| 160 | if(&pData[i] == pData[n].ppPredecessors[k]) { | |||
| 161 | n=i-1; | |||
| 162 | break; | |||
| 163 | } | |||
| 164 | } | |||
| 165 | } else | |||
| 166 | break; | |||
| 167 | } | |||
| 168 | } | |||
| 169 | if(pTail) | |||
| 170 | pTail->pNext=&pData[n]; | |||
| 171 | else | |||
| 172 | pHead=&pData[n]; | |||
| 173 | pTail=&pData[n]; | |||
| 174 | pTail->pNext=pTail; /* fudge it so it looks linked */ | |||
| 175 | for(i=0 ; i < nItems ; ++i) | |||
| 176 | for(k=0 ; k < nItems ; ++k) | |||
| 177 | if(pData[i].ppPredecessors[k] == &pData[n]) { | |||
| 178 | --pData[i].nPredecessors; | |||
| 179 | pData[i].ppPredecessors[k]=NULL((void*)0); | |||
| 180 | break; | |||
| 181 | } | |||
| 182 | } | |||
| 183 | pTail->pNext=NULL((void*)0); /* unfudge the tail */ | |||
| ||||
| 184 | return pHead; | |||
| 185 | } | |||
| 186 | ||||
| 187 | static apr_array_header_t *sort_hook(apr_array_header_t *pHooks, | |||
| 188 | const char *szName) | |||
| 189 | { | |||
| 190 | apr_pool_t *p; | |||
| 191 | TSort *pSort; | |||
| 192 | apr_array_header_t *pNew; | |||
| 193 | int n; | |||
| 194 | ||||
| 195 | apr_pool_create(&p, apr_hook_global_pool)apr_pool_create_ex(&p, apr_hook_global_pool, ((void*)0), ( (void*)0)); | |||
| 196 | pSort=prepare(p,(TSortData *)pHooks->elts,pHooks->nelts); | |||
| 197 | pSort=tsort(pSort,pHooks->nelts); | |||
| 198 | pNew=apr_array_make(apr_hook_global_pool,pHooks->nelts,sizeof(TSortData)); | |||
| 199 | if(apr_hook_debug_enabled) | |||
| 200 | printf("Sorting %s:",szName); | |||
| 201 | for(n=0 ; pSort ; pSort=pSort->pNext,++n) { | |||
| 202 | TSortData *pHook; | |||
| 203 | assert(n < pHooks->nelts)((n < pHooks->nelts) ? (void) (0) : __assert_fail ("n < pHooks->nelts" , "hooks/apr_hooks.c", 203, __PRETTY_FUNCTION__)); | |||
| 204 | pHook=apr_array_push(pNew); | |||
| 205 | memcpy(pHook,pSort->pData,sizeof *pHook); | |||
| 206 | if(apr_hook_debug_enabled) | |||
| 207 | printf(" %s",pHook->szName); | |||
| 208 | } | |||
| 209 | if(apr_hook_debug_enabled) | |||
| 210 | fputc('\n',stdoutstdout); | |||
| 211 | return pNew; | |||
| 212 | } | |||
| 213 | ||||
| 214 | #ifndef NETWARE | |||
| 215 | static apr_array_header_t *s_aHooksToSort; | |||
| 216 | #endif | |||
| 217 | ||||
| 218 | typedef struct | |||
| 219 | { | |||
| 220 | const char *szHookName; | |||
| 221 | apr_array_header_t **paHooks; | |||
| 222 | } HookSortEntry; | |||
| 223 | ||||
| 224 | APU_DECLARE(void)void apr_hook_sort_register(const char *szHookName, | |||
| 225 | apr_array_header_t **paHooks) | |||
| 226 | { | |||
| 227 | #ifdef NETWARE | |||
| 228 | get_apd | |||
| 229 | #endif | |||
| 230 | HookSortEntry *pEntry; | |||
| 231 | ||||
| 232 | if(!s_aHooksToSort) | |||
| 233 | s_aHooksToSort=apr_array_make(apr_hook_global_pool,1,sizeof(HookSortEntry)); | |||
| 234 | pEntry=apr_array_push(s_aHooksToSort); | |||
| 235 | pEntry->szHookName=szHookName; | |||
| 236 | pEntry->paHooks=paHooks; | |||
| 237 | } | |||
| 238 | ||||
| 239 | APU_DECLARE(void)void apr_hook_sort_all(void) | |||
| 240 | { | |||
| 241 | #ifdef NETWARE | |||
| 242 | get_apd | |||
| 243 | #endif | |||
| 244 | int n; | |||
| 245 | ||||
| 246 | for(n=0 ; n < s_aHooksToSort->nelts ; ++n) { | |||
| ||||
| 247 | HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n]; | |||
| 248 | *pEntry->paHooks=sort_hook(*pEntry->paHooks,pEntry->szHookName); | |||
| 249 | } | |||
| 250 | } | |||
| 251 | ||||
| 252 | #ifndef NETWARE | |||
| 253 | static apr_hash_t *s_phOptionalHooks; | |||
| 254 | static apr_hash_t *s_phOptionalFunctions; | |||
| 255 | #endif | |||
| 256 | ||||
| 257 | APU_DECLARE(void)void apr_hook_deregister_all(void) | |||
| 258 | { | |||
| 259 | #ifdef NETWARE | |||
| 260 | get_apd | |||
| 261 | #endif | |||
| 262 | int n; | |||
| 263 | ||||
| 264 | for(n=0 ; n < s_aHooksToSort->nelts ; ++n) { | |||
| 265 | HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n]; | |||
| 266 | *pEntry->paHooks=NULL((void*)0); | |||
| 267 | } | |||
| 268 | s_aHooksToSort=NULL((void*)0); | |||
| 269 | s_phOptionalHooks=NULL((void*)0); | |||
| 270 | s_phOptionalFunctions=NULL((void*)0); | |||
| 271 | } | |||
| 272 | ||||
| 273 | APU_DECLARE(void)void apr_hook_debug_show(const char *szName, | |||
| 274 | const char * const *aszPre, | |||
| 275 | const char * const *aszSucc) | |||
| 276 | { | |||
| 277 | int nFirst; | |||
| 278 | ||||
| 279 | printf(" Hooked %s",szName); | |||
| 280 | if(aszPre) { | |||
| 281 | fputs(" pre(",stdoutstdout); | |||
| 282 | nFirst=1; | |||
| 283 | while(*aszPre) { | |||
| 284 | if(!nFirst) | |||
| 285 | fputc(',',stdoutstdout); | |||
| 286 | nFirst=0; | |||
| 287 | fputs(*aszPre,stdoutstdout); | |||
| 288 | ++aszPre; | |||
| 289 | } | |||
| 290 | fputc(')',stdoutstdout); | |||
| 291 | } | |||
| 292 | if(aszSucc) { | |||
| 293 | fputs(" succ(",stdoutstdout); | |||
| 294 | nFirst=1; | |||
| 295 | while(*aszSucc) { | |||
| 296 | if(!nFirst) | |||
| 297 | fputc(',',stdoutstdout); | |||
| 298 | nFirst=0; | |||
| 299 | fputs(*aszSucc,stdoutstdout); | |||
| 300 | ++aszSucc; | |||
| 301 | } | |||
| 302 | fputc(')',stdoutstdout); | |||
| 303 | } | |||
| 304 | fputc('\n',stdoutstdout); | |||
| 305 | } | |||
| 306 | ||||
| 307 | /* Optional hook support */ | |||
| 308 | ||||
| 309 | APR_DECLARE_EXTERNAL_HOOK(apr,APU,void,_optional,(void))typedef void apr_HOOK__optional_t (void); void apr_hook__optional (apr_HOOK__optional_t *pf, const char * const *aszPre, const char * const *aszSucc, int nOrder); void apr_run__optional (void) ; apr_array_header_t * apr_hook_get__optional(void); typedef struct apr_LINK__optional_t { apr_HOOK__optional_t *pFunc; const char *szName; const char * const *aszPredecessors; const char * const *aszSuccessors; int nOrder; } apr_LINK__optional_t; | |||
| 310 | ||||
| 311 | APU_DECLARE(apr_array_header_t *)apr_array_header_t * apr_optional_hook_get(const char *szName) | |||
| 312 | { | |||
| 313 | #ifdef NETWARE | |||
| 314 | get_apd | |||
| 315 | #endif | |||
| 316 | apr_array_header_t **ppArray; | |||
| 317 | ||||
| 318 | if(!s_phOptionalHooks) | |||
| 319 | return NULL((void*)0); | |||
| 320 | ppArray=apr_hash_get(s_phOptionalHooks,szName,strlen(szName)); | |||
| 321 | if(!ppArray) | |||
| 322 | return NULL((void*)0); | |||
| 323 | return *ppArray; | |||
| 324 | } | |||
| 325 | ||||
| 326 | APU_DECLARE(void)void apr_optional_hook_add(const char *szName,void (*pfn)(void), | |||
| 327 | const char * const *aszPre, | |||
| 328 | const char * const *aszSucc,int nOrder) | |||
| 329 | { | |||
| 330 | #ifdef NETWARE | |||
| 331 | get_apd | |||
| 332 | #endif | |||
| 333 | apr_array_header_t *pArray=apr_optional_hook_get(szName); | |||
| 334 | apr_LINK__optional_t *pHook; | |||
| 335 | ||||
| 336 | if(!pArray) { | |||
| 337 | apr_array_header_t **ppArray; | |||
| 338 | ||||
| 339 | pArray=apr_array_make(apr_hook_global_pool,1, | |||
| 340 | sizeof(apr_LINK__optional_t)); | |||
| 341 | if(!s_phOptionalHooks) | |||
| 342 | s_phOptionalHooks=apr_hash_make(apr_hook_global_pool); | |||
| 343 | ppArray=apr_palloc(apr_hook_global_pool,sizeof *ppArray); | |||
| 344 | *ppArray=pArray; | |||
| 345 | apr_hash_set(s_phOptionalHooks,szName,strlen(szName),ppArray); | |||
| 346 | apr_hook_sort_register(szName,ppArray); | |||
| 347 | } | |||
| 348 | pHook=apr_array_push(pArray); | |||
| 349 | pHook->pFunc=pfn; | |||
| 350 | pHook->aszPredecessors=aszPre; | |||
| 351 | pHook->aszSuccessors=aszSucc; | |||
| 352 | pHook->nOrder=nOrder; | |||
| 353 | pHook->szName=apr_hook_debug_current; | |||
| 354 | if(apr_hook_debug_enabled) | |||
| 355 | apr_hook_debug_show(szName,aszPre,aszSucc); | |||
| 356 | } | |||
| 357 | ||||
| 358 | /* optional function support */ | |||
| 359 | ||||
| 360 | APU_DECLARE(apr_opt_fn_t *)apr_opt_fn_t * apr_dynamic_fn_retrieve(const char *szName) | |||
| 361 | { | |||
| 362 | #ifdef NETWARE | |||
| 363 | get_apd | |||
| 364 | #endif | |||
| 365 | if(!s_phOptionalFunctions) | |||
| 366 | return NULL((void*)0); | |||
| 367 | return (void(*)(void))apr_hash_get(s_phOptionalFunctions,szName,strlen(szName)); | |||
| 368 | } | |||
| 369 | ||||
| 370 | /* Deprecated */ | |||
| 371 | APU_DECLARE_NONSTD(void)void apr_dynamic_fn_register(const char *szName, | |||
| 372 | apr_opt_fn_t *pfn) | |||
| 373 | { | |||
| 374 | #ifdef NETWARE | |||
| 375 | get_apd | |||
| 376 | #endif | |||
| 377 | if(!s_phOptionalFunctions) | |||
| 378 | s_phOptionalFunctions=apr_hash_make(apr_hook_global_pool); | |||
| 379 | apr_hash_set(s_phOptionalFunctions,szName,strlen(szName),(void *)pfn); | |||
| 380 | } | |||
| 381 | ||||
| 382 | #if 0 | |||
| 383 | void main() | |||
| 384 | { | |||
| 385 | const char *aszAPre[]={"b","c",NULL((void*)0)}; | |||
| 386 | const char *aszBPost[]={"a",NULL((void*)0)}; | |||
| 387 | const char *aszCPost[]={"b",NULL((void*)0)}; | |||
| 388 | TSortData t1[]= | |||
| 389 | { | |||
| 390 | { "a",aszAPre,NULL((void*)0) }, | |||
| 391 | { "b",NULL((void*)0),aszBPost }, | |||
| 392 | { "c",NULL((void*)0),aszCPost } | |||
| 393 | }; | |||
| 394 | TSort *pResult; | |||
| 395 | ||||
| 396 | pResult=prepare(t1,3); | |||
| 397 | pResult=tsort(pResult,3); | |||
| 398 | ||||
| 399 | for( ; pResult ; pResult=pResult->pNext) | |||
| 400 | printf("%s\n",pResult->pData->szName); | |||
| 401 | } | |||
| 402 | #endif |