1.2. glob

Start cpp section to unixem/flx_glob.hpp[1 /1 ]
     1: #line 635 "./lpsrc/flx_glob.pak"
     2: #ifndef __FLX_GLOB_H__
     3: #define __FLX_GLOB_H__
     4: #include <flx_glob_config.hpp>
     5: 
     6: #if !FLX_WIN32
     7: #include <glob.h>
     8: #else
     9: 
    10: /* Error codes */
    11: #define GLOB_NOSPACE    (1)             /*!< \brief (Error result code:) An attempt to allocate memory failed, or if errno was 0 GLOB_LIMIT was specified in the flags and ARG_MAX patterns were matched. */
    12: #define GLOB_ABORTED    (2)             /*!< \brief (Error result code:) The scan was stopped because an error was encountered and either GLOB_ERR was set or (*errfunc)() returned non-zero. */
    13: #define GLOB_NOMATCH    (3)             /*!< \brief (Error result code:) The pattern does not match any existing pathname, and GLOB_NOCHECK was not set int flags. */
    14: #define GLOB_NOSYS      (4)             /*!< \brief (Error result code:) . */
    15: #define GLOB_ABEND      GLOB_ABORTED    /*!< \brief (Error result code:) . */
    16: 
    17: /* Flags */
    18: #define GLOB_ERR            0x00000001  /*!< \brief Return on read errors. */
    19: #define GLOB_MARK           0x00000002  /*!< \brief Append a slash to each name. */
    20: #define GLOB_NOSORT         0x00000004  /*!< \brief Don't sort the names. */
    21: #define GLOB_DOOFFS         0x00000008  /*!< \brief Insert PGLOB->gl_offs NULLs. Supported from version 1.6 of UNIXEm. */
    22: #define GLOB_NOCHECK        0x00000010  /*!< \brief If nothing matches, return the pattern. Supported from version 1.6 of UNIXEm. */
    23: #define GLOB_APPEND         0x00000020  /*!< \brief Append to results of a previous call. Not currently supported in this implementation. */
    24: #define GLOB_NOESCAPE       0x00000040  /*!< \brief Backslashes don't quote metacharacters. Has no effect in this implementation, since escaping is not supported. */
    25: 
    26: #define GLOB_PERIOD         0x00000080  /*!< \brief Leading `.' can be matched by metachars. Supported from version 1.6 of UNIXEm. */
    27: #define GLOB_MAGCHAR        0x00000100  /*!< \brief Set in gl_flags if any metachars seen. Supported from version 1.6 of UNIXEm. */
    28: /* #define GLOB_ALTDIRFUNC     0x00000200 */  /*!< \brief Use gl_opendir et al functions. Not currently supported in this implementation. */
    29: /* #define GLOB_BRACE          0x00000400 */  /*!< \brief Expand "{a,b}" to "a" "b". Not currently supported in this implementation. */
    30: #define GLOB_NOMAGIC        0x00000800  /*!< \brief If no magic chars, return the pattern. Supported from version 1.6 of UNIXEm. */
    31: #define GLOB_TILDE          0x00001000  /*!< \brief Expand ~user and ~ to home directories. Partially supported from version 1.6 of UNIXEm: leading ~ is expanded to %HOMEDRIVE%%HOMEPATH%. */
    32: #define GLOB_ONLYDIR        0x00002000  /*!< \brief Match only directories. This implementation guarantees to only return directories when this flag is specified. */
    33: #define GLOB_TILDE_CHECK    0x00004000  /*!< \brief Like GLOB_TILDE but return an GLOB_NOMATCH even if GLOB_NOCHECK specified. Supported from version 1.6 of UNIXEm. */
    34: #define GLOB_ONLYFILE       0x00008000  /*!< \brief Match only files. Supported from version 1.6 of UNIXEm. */
    35: #define GLOB_NODOTSDIRS     0x00010000  /*!< \brief Elide "." and ".." directories from wildcard searches. Supported from version 1.6 of UNIXEm. */
    36: #define GLOB_LIMIT          0x00020000  /*!< \brief Limits the search to the number specified by the caller in gl_matchc. Supported from version 1.6 of UNIXEm. */
    37: 
    38: typedef struct
    39: {
    40:   int   gl_pathc;   /*!< count of total paths so far */
    41:   int   gl_matchc;  /*!< count of paths matching pattern */
    42:   int   gl_offs;    /*!< reserved at beginning of gl_pathv */
    43:   int   gl_flags;   /*!< returned flags */
    44:   char  **gl_pathv; /*!< list of paths matching pattern */
    45: } glob_t;
    46: 
    47: int GLOB_EXTERN glob( char const  *pattern
    48:         , int         flags
    49:         , int       (*errfunc)(char const *, int)
    50:         , glob_t      *pglob);
    51: 
    52: void GLOB_EXTERN globfree(glob_t *pglob);
    53: 
    54: #endif
    55: #endif
    56: 
End cpp section to unixem/flx_glob.hpp[1]
Start cpp section to unixem/flx_glob.cpp[1 /1 ]
     1: #line 692 "./lpsrc/flx_glob.pak"
     2: #include "flx_glob.hpp"
     3: #include "unixem_util.hpp"
     4: 
     5: #include <errno.h>
     6: #include <stdlib.h>
     7: #include <string.h>
     8: #include <windows.h>
     9: 
    10: static char const *strrpbrk(char const *string, char const *strCharSet)
    11: {
    12:     char const *part   =   NULL;
    13:     char const  *pch;
    14: 
    15:     for(pch = strCharSet; *pch; ++pch)
    16:     {
    17:         char const *p  =   strrchr(string, *pch);
    18: 
    19:         if(NULL != p)
    20:         {
    21:             if(NULL == part)
    22:             {
    23:                 part = p;
    24:             }
    25:             else
    26:             {
    27:                 if(part < p)
    28:                 {
    29:                     part = p;
    30:                 }
    31:             }
    32:         }
    33:     }
    34: 
    35:     return part;
    36: }
    37: 
    38: int glob(   char const  *pattern
    39:         ,   int         flags
    40:         , int         (*errfunc)(char const *, int)
    41:         ,   glob_t      *pglob)
    42: {
    43:     int                 result;
    44:     char                szRelative[1 + _MAX_PATH];
    45:     char const          *file_part;
    46:     WIN32_FIND_DATAA    find_data;
    47:     HANDLE              hFind;
    48:     char                *buffer;
    49:     char                szPattern2[1 + _MAX_PATH];
    50:     char                szPattern3[1 + _MAX_PATH];
    51:     char const          *effectivePattern   =   pattern;
    52:     char const          *leafMost;
    53:     const int           bMagic              =   (NULL != strpbrk(pattern, "?*"));
    54:     int                 bNoMagic            =   0;
    55:     int                 bMagic0;
    56:     size_t              maxMatches          =   ~(size_t)(0);
    57: 
    58:     if(flags & GLOB_NOMAGIC)
    59:     {
    60:         bNoMagic = !bMagic;
    61:     }
    62: 
    63:     if(flags & GLOB_LIMIT)
    64:     {
    65:         maxMatches = (size_t)pglob->gl_matchc;
    66:     }
    67: 
    68:     if(flags & GLOB_TILDE)
    69:     {
    70:         if( '~' == pattern[0] &&
    71:             (   '\0' == pattern[1] ||
    72:                 '/' == pattern[1] ||
    73:                 '\\' == pattern[1]))
    74:         {
    75:             DWORD   dw;
    76: 
    77:             (void)lstrcpyA(&szPattern2[0], "%HOMEDRIVE%%HOMEPATH%");
    78: 
    79:             dw = ExpandEnvironmentStringsA(&szPattern2[0], &szPattern3[0], UNIXEM_NUM_ELEMENTS(szPattern3) - 1);
    80: 
    81:             if(0 != dw)
    82:             {
    83:                 (void)lstrcpynA(&szPattern3[0] + dw - 1, &pattern[1], (int)(UNIXEM_NUM_ELEMENTS(szPattern3) - dw));
    84:                 szPattern3[UNIXEM_NUM_ELEMENTS(szPattern3) - 1] = '\0';
    85: 
    86:                 effectivePattern = szPattern3;
    87:             }
    88:         }
    89:     }
    90: 
    91:     file_part = strrpbrk(effectivePattern, "\\/");
    92: 
    93:     if(NULL != file_part)
    94:     {
    95:         leafMost = ++file_part;
    96: 
    97:         (void)lstrcpyA(szRelative, effectivePattern);
    98:         szRelative[file_part - effectivePattern] = '\0';
    99:     }
   100:     else
   101:     {
   102:         szRelative[0] = '\0';
   103:         leafMost = effectivePattern;
   104:     }
   105: 
   106:     bMagic0 =   (leafMost == strpbrk(leafMost, "?*"));
   107: 
   108:     hFind   =   FindFirstFileA(effectivePattern, &find_data);
   109:     buffer  =   NULL;
   110: 
   111:     pglob->gl_pathc = 0;
   112:     pglob->gl_pathv = NULL;
   113: 
   114:     if(0 == (flags & GLOB_DOOFFS))
   115:     {
   116:         pglob->gl_offs = 0;
   117:     }
   118: 
   119:     if(hFind == INVALID_HANDLE_VALUE)
   120:     {
   121:         if(NULL != errfunc)
   122:         {
   123:             (void)errfunc(effectivePattern, (int)GetLastError());
   124:         }
   125: 
   126:         result = GLOB_NOMATCH;
   127:     }
   128:     else
   129:     {
   130:         int     cbCurr      =   0;
   131:         size_t  cbAlloc     =   0;
   132:         size_t  cMatches    =   0;
   133: 
   134:         result = 0;
   135: 
   136:         do
   137:         {
   138:             int     cch;
   139:             size_t  new_cbAlloc;
   140: 
   141:             if( bMagic0 &&
   142:                 0 == (flags & GLOB_PERIOD))
   143:             {
   144:                 if('.' == find_data.cFileName[0])
   145:                 {
   146:                     continue;
   147:                 }
   148:             }
   149: 
   150:             if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
   151:             {
   152: #ifdef GLOB_ONLYFILE
   153:                 if(flags & GLOB_ONLYFILE)
   154:                 {
   155:                     continue;
   156:                 }
   157: #endif /* GLOB_ONLYFILE */
   158: 
   159:                 if( bMagic0 &&
   160:                     GLOB_NODOTSDIRS == (flags & GLOB_NODOTSDIRS))
   161:                 {
   162:                     /* Pattern must begin with '.' to match either dots directory */
   163:                     if( 0 == lstrcmpA(".", find_data.cFileName) ||
   164:                         0 == lstrcmpA("..", find_data.cFileName))
   165:                     {
   166:                         continue;
   167:                     }
   168:                 }
   169: 
   170:                 if(flags & GLOB_MARK)
   171:                 {
   172: #if 0
   173:                     if(find_data.cFileName[0] >= 'A' && find_data.cFileName[0] <= 'M')
   174: #endif /* 0 */
   175:                     (void)lstrcatA(find_data.cFileName, "/");
   176:                 }
   177:             }
   178:             else
   179:             {
   180:                 if(flags & GLOB_ONLYDIR)
   181:                 {
   182:                     /* Skip all further actions, and get the next entry */
   183: #if 0
   184:                     if(find_data.cFileName[0] >= 'A' && find_data.cFileName[0] <= 'M')
   185: #endif /* 0 */
   186:                     continue;
   187:                 }
   188:             }
   189: 
   190:             cch =   lstrlenA(find_data.cFileName);
   191:             if(NULL != file_part)
   192:             {
   193:                 cch +=  file_part - effectivePattern;
   194:             }
   195: 
   196:             new_cbAlloc = (size_t)cbCurr + cch + 1;
   197:             if(new_cbAlloc > cbAlloc)
   198:             {
   199:                 char    *new_buffer;
   200: 
   201:                 new_cbAlloc *= 2;
   202: 
   203:                 new_cbAlloc = (new_cbAlloc + 31) & ~(31);
   204: 
   205:                 new_buffer  = (char*)realloc(buffer, new_cbAlloc);
   206: 
   207:                 if(new_buffer == NULL)
   208:                 {
   209:                     result = GLOB_NOSPACE;
   210:                     free(buffer);
   211:                     buffer = NULL;
   212:                     break;
   213:                 }
   214: 
   215:                 buffer = new_buffer;
   216:                 cbAlloc = new_cbAlloc;
   217:             }
   218: 
   219:             (void)lstrcpynA(buffer + cbCurr, szRelative, 1 + (file_part - effectivePattern));
   220:             (void)lstrcatA(buffer + cbCurr, find_data.cFileName);
   221:             cbCurr += cch + 1;
   222: 
   223:             ++cMatches;
   224:         }
   225:         while(FindNextFile(hFind, &find_data) && cMatches != maxMatches);
   226: 
   227:         (void)FindClose(hFind);
   228: 
   229:         if(result == 0)
   230:         {
   231:             /* Now expand the buffer, to fit in all the pointers. */
   232:             size_t  cbPointers  =   (1 + cMatches + pglob->gl_offs) * sizeof(char*);
   233:             char    *new_buffer =   (char*)realloc(buffer, cbAlloc + cbPointers);
   234: 
   235:             if(new_buffer == NULL)
   236:             {
   237:                 result = GLOB_NOSPACE;
   238:                 free(buffer);
   239:             }
   240:             else
   241:             {
   242:                 char    **pp;
   243:                 char    **begin;
   244:                 char    **end;
   245:                 char    *next_str;
   246: 
   247:                 buffer = new_buffer;
   248: 
   249:                 (void)memmove(new_buffer + cbPointers, new_buffer, cbAlloc);
   250: 
   251:                 /* Handle the offsets. */
   252:                 begin =   (char**)new_buffer;
   253:                 end   =   begin + pglob->gl_offs;
   254: 
   255:                 for(; begin != end; ++begin)
   256:                 {
   257:                     *begin = NULL;
   258:                 }
   259: 
   260:                 /* Sort, or no sort. */
   261:                 pp    =   (char**)new_buffer + pglob->gl_offs;
   262:                 begin =   pp;
   263:                 end   =   begin + cMatches;
   264: 
   265:                 if(flags & GLOB_NOSORT)
   266:                 {
   267:                     /* The way we need in order to test the removal of dots in the findfile_sequence. */
   268:                     *end = NULL;
   269:                     for(begin = pp, next_str = buffer + cbPointers; begin != end; --end)
   270:                     {
   271:                         *(end - 1) = next_str;
   272: 
   273:                         /* Find the next string. */
   274:                         next_str += 1 + lstrlenA(next_str);
   275:                     }
   276:                 }
   277:                 else
   278:                 {
   279:                     /* The normal way. */
   280:                     for(begin = pp, next_str = buffer + cbPointers; begin != end; ++begin)
   281:                     {
   282:                         *begin = next_str;
   283: 
   284:                         /* Find the next string. */
   285:                         next_str += 1 + lstrlenA(next_str);
   286:                     }
   287:                     *begin = NULL;
   288:                 }
   289: 
   290:                 /* Return results to caller. */
   291:                 pglob->gl_pathc =   (int)cMatches;
   292:                 pglob->gl_matchc=   (int)cMatches;
   293:                 pglob->gl_flags =   0;
   294:                 if(bMagic)
   295:                 {
   296:                     pglob->gl_flags |= GLOB_MAGCHAR;
   297:                 }
   298:                 pglob->gl_pathv =   (char**)new_buffer;
   299:             }
   300:         }
   301: 
   302:         if(0 == cMatches)
   303:         {
   304:             result = GLOB_NOMATCH;
   305:         }
   306:     }
   307: 
   308:     if(GLOB_NOMATCH == result)
   309:     {
   310:         if( (flags & GLOB_TILDE_CHECK) &&
   311:             effectivePattern == szPattern3)
   312:         {
   313:             result = GLOB_NOMATCH;
   314:         }
   315:         else if(bNoMagic ||
   316:                 (flags & GLOB_NOCHECK))
   317:         {
   318:             size_t  cbNeeded    =   ((2 + pglob->gl_offs) * sizeof(char*)) + (1 + strlen(effectivePattern));
   319:             char    **pp        =   (char**)realloc(buffer, cbNeeded);
   320: 
   321:             if(NULL == pp)
   322:             {
   323:                 result = GLOB_NOSPACE;
   324:                 free(buffer);
   325:             }
   326:             else
   327:             {
   328:                 /* Handle the offsets. */
   329:                 char    **begin =   pp;
   330:                 char    **end   =   pp + pglob->gl_offs;
   331: 
   332:                 for(; begin != end; ++begin)
   333:                 {
   334:                     *begin = NULL;
   335:                 }
   336: 
   337:                 /* Synthesis the pattern result. */
   338:                 pp[0 + pglob->gl_offs]  =   strcpy((char*)(pp + 2 + pglob->gl_offs), effectivePattern);
   339:                 pp[1 + pglob->gl_offs]  =   NULL;
   340: 
   341:                 /* Return results to caller. */
   342:                 pglob->gl_pathc =   1;
   343:                 pglob->gl_matchc=   1;
   344:                 pglob->gl_flags =   0;
   345:                 if(bMagic)
   346:                 {
   347:                     pglob->gl_flags |= GLOB_MAGCHAR;
   348:                 }
   349:                 pglob->gl_pathv =   pp;
   350: 
   351:                 result = 0;
   352:             }
   353:         }
   354:     }
   355:     else if(0 == result)
   356:     {
   357:         if((size_t)pglob->gl_matchc == maxMatches)
   358:         {
   359:             result = GLOB_NOSPACE;
   360:         }
   361:     }
   362: 
   363:     return result;
   364: }
   365: 
   366: void globfree(glob_t *pglob)
   367: {
   368:     if(pglob != NULL)
   369:     {
   370:         free(pglob->gl_pathv);
   371:         pglob->gl_pathc = 0;
   372:         pglob->gl_pathv = NULL;
   373:     }
   374: }
   375: 
End cpp section to unixem/flx_glob.cpp[1]