//-------------------------------------------------------------------------------- // The main program. //-------------------------------------------------------------------------------- int main (int argc, char **argv) { int argn; char * arg; int Subdirs = 0; for (argn=1;argn<argc;argn++){ arg = argv[argn]; if (arg[0] != '-') break; // Filenames from here on. if (!strcmp(arg,"-r")){ printf("do recursive\n"); Subdirs = 1; }else{ fprintf(stderr, "Argument '%s' not understood\n",arg); } } if (argn == argc){ fprintf(stderr,"Error: Must supply a file name\n"); } for (;argn<argc;argn++){ MyGlob(argv[argn], ShowName); } return EXIT_SUCCESS; }
value myglob (value v_pat, value v_fun) { CAMLparam2(v_pat,v_fun); const char * pat = String_val(v_pat); MyGlob (pat, v_fun); CAMLreturn(Val_int(0)); }
//-------------------------------------------------------------------------------- // Decide how a particular pattern should be handled, and call function for each. //-------------------------------------------------------------------------------- void MyGlob(const char * Pattern , void (*FileFuncParm)(const char * FileName)) { char BasePattern[_MAX_PATH]; char MatchPattern[_MAX_PATH]; char PatCopy[_MAX_PATH*2+1]; int a; int MatchFiles, MatchDirs; int BaseEnd, PatternEnd; int SawPat; int RecurseAt; strcpy(PatCopy, Pattern); #ifdef DEBUGGING printf("Called with '%s'\n",Pattern); #endif DoRecursion: MatchFiles = FALSE; MatchDirs = TRUE; BaseEnd = 0; PatternEnd = 0; SawPat = FALSE; RecurseAt = -1; // Split the path into base path and pattern to match against using findfirst. for (a=0;;a++){ if (PatCopy[a] == '*' || PatCopy[a] == '?'){ SawPat = TRUE; } if (PatCopy[a] == '*' && PatCopy[a+1] == '*'){ if (a == 0 || PatCopy[a-1] == '\\' || PatCopy[a-1] == ':'){ if (PatCopy[a+2] == '\\' || PatCopy[a+2] == '\0'){ // x\**\y ---> x\y x\*\**\y RecurseAt = a; if (PatCopy[a+2]){ memcpy(PatCopy+a, PatCopy+a+3, strlen(PatCopy)-a-1); }else{ PatCopy[a+1] = '\0'; } } } } if (PatCopy[a] == '\\' || (PatCopy[a] == ':' && PatCopy[a+1] != '\\')){ PatternEnd = a; if (SawPat) break; // Findfirst can only match one level of wildcard at a time. BaseEnd = a+1; } if (PatCopy[a] == '\0'){ PatternEnd = a; MatchFiles = TRUE; MatchDirs = FALSE; break; } } if (!SawPat){ // No pattern. This should refer to a file. FileFuncParm(PatCopy); return; } strncpy(BasePattern, PatCopy, BaseEnd); BasePattern[BaseEnd] = 0; strncpy(MatchPattern, PatCopy, PatternEnd); MatchPattern[PatternEnd] = 0; #ifdef DEBUGGING printf("Base:%s Pattern:%s Files:%d dirs:%d\n",BasePattern, MatchPattern, MatchFiles, MatchDirs); #endif { FileEntry * FileList = NULL; int NumAllocated = 0; int NumHave = 0; struct _finddata_t finddata; long find_handle; find_handle = _findfirst(MatchPattern, &finddata); for (;;){ if (find_handle == -1) break; // Eliminate the obvious patterns. if (!memcmp(finddata.name, ".",2)) goto next_file; if (!memcmp(finddata.name, "..",3)) goto next_file; if (finddata.attrib & _A_SUBDIR){ if (!MatchDirs) goto next_file; }else{ if (!MatchFiles) goto next_file; } // Add it to the list. if (NumAllocated <= NumHave){ NumAllocated = NumAllocated+10+NumAllocated/2; FileList = realloc(FileList, NumAllocated * sizeof(FileEntry)); if (FileList == NULL) goto nomem; } a = strlen(finddata.name); FileList[NumHave].Name = malloc(a+1); if (FileList[NumHave].Name == NULL){ nomem: printf("malloc failure\n"); exit(-1); } memcpy(FileList[NumHave].Name, finddata.name, a+1); FileList[NumHave].attrib = finddata.attrib; NumHave++; next_file: if (_findnext(find_handle, &finddata) != 0) break; } _findclose(find_handle); // Sort the list... qsort(FileList, NumHave, sizeof(FileEntry), CompareFunc); // Use the list. for (a=0;a<NumHave;a++){ char CombinedName[_MAX_PATH*2+1]; if (FileList[a].attrib & _A_SUBDIR){ if (MatchDirs){ // Need more directories. SplicePath(CombinedName, BasePattern, FileList[a].Name); strncat(CombinedName, PatCopy+PatternEnd, _MAX_PATH*2-strlen(CombinedName)); MyGlob(CombinedName,FileFuncParm); } }else{ if (MatchFiles){ // We need files at this level. SplicePath(CombinedName, BasePattern, FileList[a].Name); FileFuncParm(CombinedName); } } free(FileList[a].Name); } free(FileList); } if(RecurseAt >= 0){ strcpy(MatchPattern, PatCopy+RecurseAt); PatCopy[RecurseAt] = 0; strncpy(PatCopy+RecurseAt, "*\\**\\", _MAX_PATH*2-RecurseAt); strncat(PatCopy, MatchPattern, _MAX_PATH*2-strlen(PatCopy)); #ifdef DEBUGGING printf("Recurse with '%s'\n",PatCopy); #endif // As this function context is no longer needed, we can just goto back // to the top of it to avoid adding another context on the stack. goto DoRecursion; } }