/* MISSING.C Implementation for standard and semi-standard C library calls missing in WinCE environment. by Vasyl Tsvirkunov */ #include #include #include #include #include "sys/stat.h" #include "sys/time.h" #include "time.h" #include "dirent.h" /* forward declaration */ #if _WIN32_WCE < 300 #define _STDAFX_H #include "portdefs.h" #else char *strdup(const char *strSource); #endif /* Limited dirent implementation. Used by UI.C and DEVICES.C */ static WIN32_FIND_DATA wfd; DIR* opendir(const char* fname) { DIR* pdir; char fnameMask[MAX_PATH+1]; TCHAR fnameUnc[MAX_PATH+1]; char nameFound[MAX_PATH+1]; if(fname == NULL) return NULL; strcpy(fnameMask, fname); if(!strlen(fnameMask) || fnameMask[strlen(fnameMask)-1] != '\\') strncat(fnameMask, "\\", MAX_PATH-strlen(fnameMask)-1); strncat(fnameMask, "*.*", MAX_PATH-strlen(fnameMask)-4); pdir = (DIR*)malloc(sizeof(DIR)+strlen(fname)); pdir->dd_dir.d_ino = 0; pdir->dd_dir.d_reclen = 0; pdir->dd_dir.d_name = 0; pdir->dd_dir.d_namlen = 0; pdir->dd_handle = 0; pdir->dd_stat = 0; strcpy(pdir->dd_name, fname); /* it has exactly enough space for fname and nul char */ MultiByteToWideChar(CP_ACP, 0, fnameMask, -1, fnameUnc, MAX_PATH); if((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE) { free(pdir); return NULL; } else { WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL); pdir->dd_dir.d_name = strdup(nameFound); pdir->dd_dir.d_namlen = strlen(nameFound); } return pdir; } struct dirent* readdir(DIR* dir) { char nameFound[MAX_PATH+1]; static struct dirent dummy; if(dir->dd_stat == 0) { dummy.d_name = "."; dummy.d_namlen = 1; dir->dd_stat ++; return &dummy; } else if(dir->dd_stat == 1) { dummy.d_name = ".."; dummy.d_namlen = 2; dir->dd_stat ++; return &dummy; } else if(dir->dd_stat == 2) { dir->dd_stat++; return &dir->dd_dir; } else { if(FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0) { dir->dd_stat = -1; return NULL; } WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL); if(dir->dd_dir.d_name) free(dir->dd_dir.d_name); dir->dd_dir.d_name = strdup(nameFound); dir->dd_dir.d_namlen = strlen(nameFound); dir->dd_stat ++; return &dir->dd_dir; } } int closedir(DIR* dir) { if(dir == NULL) return 0; if(dir->dd_handle) FindClose((HANDLE)dir->dd_handle); if(dir->dd_dir.d_name) free(dir->dd_dir.d_name); free(dir); return 1; } /* Very limited implementation of stat. Used by UI.C, MEMORY-P.C (latter is not critical) */ int stat(const char *fname, struct stat *ss) { TCHAR fnameUnc[MAX_PATH+1]; HANDLE handle; int len; if(fname == NULL || ss == NULL) return -1; /* Special case (dummy on WinCE) */ len = strlen(fname); if(len >= 2 && fname[len-1] == '.' && fname[len-2] == '.' && (len == 2 || fname[len-3] == '\\')) { /* That's everything implemented so far */ memset(ss, 0, sizeof(struct stat)); ss->st_size = 1024; ss->st_mode |= S_IFDIR; return 0; } MultiByteToWideChar(CP_ACP, 0, fname, -1, fnameUnc, MAX_PATH); handle = FindFirstFile(fnameUnc, &wfd); if(handle == INVALID_HANDLE_VALUE) return -1; else { /* That's everything implemented so far */ memset(ss, 0, sizeof(struct stat)); ss->st_size = wfd.nFileSizeLow; if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ss->st_mode |= S_IFDIR; FindClose(handle); } return 0; } /* Remove file by name */ int remove(const char* path) { TCHAR pathUnc[MAX_PATH+1]; MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); return !DeleteFile(pathUnc); } /* in our case unlink is the same as remove */ int unlink(const char* path) { return remove(path); } /* Make directory, Unix style */ void mkdir(char* dirname, int mode) { char path[MAX_PATH+1]; TCHAR pathUnc[MAX_PATH+1]; char* ptr; strncpy(path, dirname, MAX_PATH); if(*path == '/') *path = '\\'; /* Run through the string and attempt creating all subdirs on the path */ for(ptr = path+1; *ptr; ptr ++) { if(*ptr == '\\' || *ptr == '/') { *ptr = 0; MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); CreateDirectory(pathUnc, 0); *ptr = '\\'; } } MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); CreateDirectory(pathUnc, 0); } /* Used in DEVICES.C and UI.C for some purpose. Not critical in this port */ int system(const char* path) { return 0; } #if 0 char *tmpnam(char *string) { TCHAR pTemp[MAX_PATH+1]; static char buffer[MAX_PATH+1]; GetTempFileName(TEXT("."), TEXT("A8_"), 0, pTemp); WideCharToMultiByte(CP_ACP, 0, pTemp, -1, buffer, MAX_PATH, NULL, NULL); if(string) { strcpy(string, buffer); return string; } else return buffer; } FILE *tmpfile() { TCHAR pTemp[MAX_PATH+1]; if(!GetTempFileName(TEXT("."), TEXT("A8_"), 0, pTemp)) return _wfopen(pTemp, TEXT("w+b")); else return 0; } #endif void rewind(FILE *stream) { fseek(stream, 0, SEEK_SET); } #if _WIN32_WCE < 300 int isalnum(int c) { return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')); } char *_strdup(const char *strSource) #else char *strdup(const char *strSource) #endif { char* buffer; buffer = (char*)malloc(strlen(strSource)+1); if(buffer) strcpy(buffer, strSource); return buffer; } /* Used in UI.C */ char cwd[MAX_PATH+1] = ""; char *getcwd(char *buffer, int maxlen) { TCHAR fileUnc[MAX_PATH+1]; char* plast; if(cwd[0] == 0) { GetModuleFileName(NULL, fileUnc, MAX_PATH); WideCharToMultiByte(CP_ACP, 0, fileUnc, -1, cwd, MAX_PATH, NULL, NULL); plast = strrchr(cwd, '\\'); if(plast) *plast = 0; /* Special trick to keep start menu clean... */ if(_stricmp(cwd, "\\windows\\start menu") == 0) strcpy(cwd, "\\Apps"); } if(buffer) strncpy(buffer, cwd, maxlen); return cwd; } /* Limited implementation of time.h. time_t formula is possibly incorrect. */ time_t time(time_t* res) { time_t t; SYSTEMTIME st; GetLocalTime(&st); t = (time_t)(((((((st.wYear-1970)*12+st.wMonth)*31+st.wDay)*7+st.wDayOfWeek)*24+st.wHour)*60+st.wMinute)*60+st.wSecond); if(res) *res = t; return t; } struct tm* localtime(time_t* timer) { static struct tm tmLocalTime; unsigned long rem = *timer; tmLocalTime.tm_sec = (short)(rem % 60); rem /= 60; tmLocalTime.tm_min = (short)(rem % 60); rem /= 60; tmLocalTime.tm_hour = (short)(rem % 24); rem /= 24; tmLocalTime.tm_mday = (short)(rem % 7); rem /= 7; tmLocalTime.tm_mday = (short)(rem % 31); rem /= 31; tmLocalTime.tm_mon = (short)(rem % 12); rem /= 12; tmLocalTime.tm_year = (short)(rem+1970); return &tmLocalTime; } /* Very limited implementation of sys/time.h */ void gettimeofday(struct timeval* tp, void* dummy) { DWORD dt = GetTickCount(); tp->tv_sec = dt/1000; tp->tv_usec = dt*1000; } void usleep(long usec) { long msec = usec/1000; if(msec <= 0) Sleep(0); else Sleep(msec); } /* Windows CE fopen has non-standard behavior -- not fully qualified paths refer to root folder rather than current folder (concept not implemented in CE). */ #undef fopen FILE* wce_fopen(const char* fname, const char* fmode) { char fullname[MAX_PATH+1]; if(!fname || fname[0] == '\0') return NULL; if(fname[0] != '\\' && fname[0] != '/') { getcwd(fullname, MAX_PATH); strncat(fullname, "\\", MAX_PATH-strlen(fullname)-1); strncat(fullname, fname, MAX_PATH-strlen(fullname)-strlen(fname)); return fopen(fullname, fmode); } else return fopen(fname, fmode); } /* This may provide for better sync mechanism */ unsigned int clock() { return GetTickCount(); } /* And why do people use this? */ #if _WIN32_WCE >= 300 void abort() { exit(1); } #endif /* IMHO, no project should use this one, it is not portable at all. This implementation at least allows some projects to work. */ char* getenv(char* name) { static char buffer[MAX_PATH+1]; if(strcmp(name, "HOME") == 0 || strcmp(name, "HOMEDIR") == 0) { getcwd(buffer, MAX_PATH); return buffer; } else return ""; } void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { size_t i; for (i=0; i='0' && c <= '9'); } int isprint(int c) { return (c >= ' ' && c <= '~'); } int isspace(int c) { return (c == ' '); } #endif #ifndef WIN32_PLATFORM_HPCPRO int printf(const char *format, ...) { // useless anyway :) return 0; } FILE *fopen(const char *path, const char *mode) { TCHAR tempo[MAX_PATH]; HANDLE result; bool writeAccess = (mode[0] == 'W' || mode[0] == 'w'); MultiByteToWideChar(CP_ACP, 0, path, strlen(path) + 1, tempo, sizeof(tempo)); result = CreateFile(tempo, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL); if (result == INVALID_HANDLE_VALUE) return NULL; else return (FILE*)result; } FILE * _wfopen(const TCHAR *path, const TCHAR *mode) { HANDLE result; bool writeAccess = (mode[0] == 'W' || mode[0] == 'w'); result = CreateFile(path, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL); if (result == INVALID_HANDLE_VALUE) return NULL; else return (FILE*)result; } FILE *_wfreopen(const TCHAR *path, const TCHAR *mode, FILE *stream) { fclose(stream); stream = _wfopen(path, mode); return stream; } int fclose(FILE *stream) { CloseHandle((HANDLE)stream); return 1; } int fseek(FILE *stream, long offset, int whence) { SetFilePointer((HANDLE)stream, offset, NULL, (whence == SEEK_CUR ? FILE_CURRENT : whence == SEEK_END ? FILE_END : FILE_BEGIN)); return 0; } long ftell(FILE *stream) { return (SetFilePointer((HANDLE)stream, 0, NULL, FILE_CURRENT)); } size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { DWORD sizeWritten; WriteFile((HANDLE)stream, ptr, size * nmemb, &sizeWritten, NULL); if (size != 0) return sizeWritten / size; else return 0; } size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { DWORD sizeRead; ReadFile((HANDLE)stream, ptr, size * nmemb, &sizeRead, NULL); if (size != 0) return sizeRead / size; else return 0; } int fgetc(FILE *stream) { unsigned char c; if (fread(&c, 1, 1, stream) != 1) return -1; else return c; } char *fgets(char *s, int size, FILE *stream) { int i = 0; char tempo[1]; memset(s, 0, size); while (fread(tempo, 1, 1, stream)) { //if (tempo[0] == '\r') // break; if (tempo[0] == '\r') continue; s[i++] = tempo[0]; if (tempo[0] == '\n') break; if (i == size) break; } if (!i) return NULL; else return s; } int feof(FILE *stream) { DWORD fileSize; DWORD filePos; fileSize = GetFileSize((HANDLE)stream, NULL); filePos = SetFilePointer((HANDLE)stream, 0, 0, FILE_CURRENT); return (filePos == 0xFFFFFFFF || filePos > (fileSize - 1)); } int ferror(FILE *stream) { return 0; // FIXME ! } int fprintf(FILE *stream, const char *format, ...) { char buf[1024]; va_list va; va_start(va, format); vsnprintf(buf, 1024, format, va); va_end(va); if (buf[strlen(buf) - 1] == '\n') { int i = strlen(buf) - 1; buf[i] = '\r'; buf[i + 1] = '\n'; buf[i + 2] = 0; } return fwrite(buf, 1, strlen(buf), stream); } FILE* _getstdfilex(int) { return NULL; } void clearerr(FILE *stream) { } int fflush(FILE *stream) { return 0; } #endif int stricmp( const char *string1, const char *string2 ) { char src[4096]; char dest[4096]; int i; for (i=0; i= 'A' && string1[i] <= 'Z') src[i] = string1[i] + 32; else src[i] = string1[i]; src[i] = 0; for (i=0; i= 'A' && string2[i] <= 'Z') dest[i] = string2[i] + 32; else dest[i] = string2[i]; dest[i] = 0; return strcmp(src, dest); } char *strrchr(const char *s, int c) { int i; for (i = strlen(s) - 1; i > 0; i--) if (s[i] == c) return (char*)(s + i); return NULL; } long int strtol(const char *nptr, char **endptr, int base) { // not correct but that's all we are using long int result; sscanf(nptr, "%ld", &result); return result; } #endif