-int qcomp(const void*, const void*);
-
-/* Directory Listing Stack
- FILO Stack for keeping an open DIR* at each directory depth for treewalk.
- This stack is depth-safe, checking its depth during push operations, but not
- during pop operations, to ensure the thread doesn't open too many files at
- once (512 in c runtime), or traverse too far through symbolic links.
- A directory listing includes a DIR* and all DIR-typed entity in the directory
- as recognized by dirent, populated externally (and optionally).
- This stack behaves abnormally by incrementing its PUSH operation prior to
- evaluation, and the POP operations after evaluation. This behavior allows
- the 'DL_CURDEPTH' operation to map to the current element in the 'dl_stack'
- array, and it is always treated as the "current depth". This also allows us
- to init the root directory to 'directory_list_stack'[0] and pop it in a safe
- and explicit manner.
-*/
-#define S(S)#S
-#ifndef DL_DEPTHMAX
-#define DL_DEPTHMAX 64
-#endif
-#ifndef DL_CHILDMAX
-#define DL_CHILDMAX DL_DEPTHMAX //square tree
-#endif
-#define DL_STACK (directory_list_stack)
-#define DL_STACKP (dls)
-#define DL_STACKSIZE (DL_DEPTHMAX + 1) //+1 because push increments early
-#define DL_LEN (DL_STACKP - DL_STACK)
-#define DL_CURDEPTH (DL_LEN)
-#define DL_CD_STACK ((*DL_STACKP).child_entity_stack)
-#define DL_CD_STACKP ((*DL_STACKP).cds)
-#define DL_CD_STACKSIZE (DL_DEPTHMAX) //square tree
-#define DL_CD_LEN (DL_CD_STACKP - DL_CD_STACK)
-#define ERR_CHILD "Fatal: Maximum of " S(MAX_CHILD) \
- " child directories exceeded for directory %s at depth %i\n" \
- ,DL_STACK[DL_DEPTH()].label,DL_DEPTH()
-#define ERR_DEPTH "Fatal: Maximum directory depth of " S(DL_DEPTHMAX) \
- " exceeded during directory scan\n"
-#define DL_INIT() (DL_STACKP = DL_STACK)
-#define DL_CD_INIT() (DL_CD_STACKP = DL_CD_STACK)
-#define DL_POP() ((DIR*)(*DL_STACKP--))
-#define DL_CD_POP() (*--DL_CD_STACKP)
-#define DL_PUSH(D) (*(DIR**)(++DL_STACKP) = DIRP)
-#define DL_CD_PUSH(E) (*DL_CD_STACKP++ = E)
-#define DL_SAFEPUSH(D) \
- do { \
- if (DL_DEPTH() >= DL_DEPTHMAX) \
- { fprintf(stderr, ERR_DEPTH); \
- exit(EXIT_FAILURE); \
- } \
- if ((*(DIR**)(++DL_STACKP) = D) == NULL) \
- { perror("DL_SAFEPUSH"); \
- exit(EXIT_FAILURE); \
- } \
- } while(0)
-#define DL_CD_POPULATE() \
- do { \
- DL_CD_INIT(); \
- while ((*DL_CD_STACKP = readdir(*DL_STACKP)) != NULL) \
- { switch((*DL_CD_STACKP)->d_type) \
- { case DT_REG: \
- case DT_DIR: \
- DL_CD_STACKP++; \
- break; \
- default: \
- } \
- } \
- qsort(DL_CD_STACKP, DL_CD_LEN, sizeof *DL_CD_STACKP, qcomp); \
- } while (0)
-