diff options
author | Ash Wolf <ninji@wuffs.org> | 2022-10-12 18:07:57 +0100 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2022-10-12 18:07:57 +0100 |
commit | 945f73751630db0420522b5d6af0629d90376a45 (patch) | |
tree | 4b374c13d61dd0f54abefa49c6c348d6a56c6a52 | |
parent | f080c0e765878ae91949d91a0bc10b87e6c8269b (diff) | |
download | MWCC-945f73751630db0420522b5d6af0629d90376a45.tar.gz MWCC-945f73751630db0420522b5d6af0629d90376a45.zip |
almost finished OSLib
-rw-r--r-- | command_line/CmdLine/Src/OSLib/FileHandles.c | 101 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/Generic.c | 178 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/MacFileTypes.c | 97 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/MemUtils.c | 41 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/StringExtras.c | 32 | ||||
-rw-r--r-- | command_line/CmdLine/Src/OSLib/StringUtils.c | 116 | ||||
-rw-r--r-- | includes/common.h | 8 | ||||
-rw-r--r-- | includes/oslib.h | 10 |
8 files changed, 564 insertions, 19 deletions
diff --git a/command_line/CmdLine/Src/OSLib/FileHandles.c b/command_line/CmdLine/Src/OSLib/FileHandles.c index 4609d77..69b4b11 100644 --- a/command_line/CmdLine/Src/OSLib/FileHandles.c +++ b/command_line/CmdLine/Src/OSLib/FileHandles.c @@ -1,29 +1,128 @@ #include "oslib.h" +#include <errno.h> static int OS_LoadFileHandle(OSFileHandle *hand) { + int err; + int ref; + UInt32 sz; + void *buffer; + hand->loaded = 0; + + err = OS_Open(&hand->spec, OSReadOnly, &ref); + if (!err) { + err = OS_GetSize(ref, &sz); + if (!err) { + err = OS_ResizeHandle(&hand->hand, sz); + if (!err) { + buffer = OS_LockHandle(&hand->hand); + err = OS_Read(ref, buffer, &sz); + if (!err) { + hand->loaded = 1; + hand->changed = 0; + } + OS_UnlockHandle(&hand->hand); + } + } + OS_Close(ref); + } + + return err; } static int OS_WriteFileHandle(OSFileHandle *hand) { + int err; + int ref; + UInt32 sz; + void *buffer; + + if (!hand->loaded && !hand->changed) + return 0; + OS_Delete(&hand->spec); + err = OS_Create(&hand->spec, &OS_TEXTTYPE); + if (!err) { + err = OS_Open(&hand->spec, OSReadWrite, &ref); + if (!err) { + err = OS_GetHandleSize(&hand->hand, &sz); + if (!err) { + buffer = OS_LockHandle(&hand->hand); + err = OS_Write(ref, buffer, &sz); + if (!err) + hand->changed = 0; + OS_UnlockHandle(&hand->hand); + OS_Close(ref); + } + } + } + + return err; } int OS_NewFileHandle(const OSSpec *spec, OSHandle *src, Boolean writeable, OSFileHandle *hand) { + int err; + + if (!writeable && src) + return EACCES; + + hand->spec = *spec; + hand->writeable = writeable; + if (!src) { + err = OS_NewHandle(0, &hand->hand); + if (err) + return err; + err = OS_LoadFileHandle(hand); + } else { + err = OS_CopyHandle(src, &hand->hand); + if (err) + return err; + hand->changed = 1; + hand->loaded = 1; + } + + return err; } int OS_LockFileHandle(OSFileHandle *hand, Ptr *ptr, UInt32 *size) { + *size = 0; + + if (!OS_ValidHandle(&hand->hand)) + return ENOMEM; + *ptr = OS_LockHandle(&hand->hand); + OS_GetHandleSize(&hand->hand, size); + return 0; } int OS_UnlockFileHandle(OSFileHandle *hand) { + if (!OS_ValidHandle(&hand->hand)) + return ENOMEM; + OS_UnlockHandle(&hand->hand); + return 0; } int OS_FreeFileHandle(OSFileHandle *hand) { + int err; + + if (hand->writeable && hand->changed) { + err = OS_WriteFileHandle(hand); + if (err) + return err; + } + if (!OS_ValidHandle(&hand->hand)) + return ENOMEM; + + err = OS_FreeHandle(&hand->hand); + if (err) + return err; + + hand->loaded = 0; + return 0; } void OS_GetFileHandleSpec(const OSFileHandle *hand, OSSpec *spec) { - + *spec = hand->spec; } diff --git a/command_line/CmdLine/Src/OSLib/Generic.c b/command_line/CmdLine/Src/OSLib/Generic.c index 4430790..e95ebd5 100644 --- a/command_line/CmdLine/Src/OSLib/Generic.c +++ b/command_line/CmdLine/Src/OSLib/Generic.c @@ -1,4 +1,5 @@ #include "oslib.h" +#include <errno.h> static char wildname[63]; static char wilddir[255]; @@ -6,9 +7,48 @@ static OSOpenedDir wilddirref; static OSSpec wildmatch; char STSbuf[256]; -int WildCardMatch(const char *wild, const char *name) { +inline char dummyfunc(int ch) { + return ch; +} + +int WildCardMatch(char *wild, char *name) { char next; - const char *prev; + char *prev; + + if (!name[0]) + return 0; + + while (*wild) { + if (*wild == '*') { + wild++; + next = *wild; + prev = 0; + + while (*name) { + if (dummyfunc(*name) == dummyfunc(next)) + prev = name; + ++name; + } + + if (prev) + name = prev; + + if (dummyfunc(*name) != dummyfunc(next)) + return 0; + } else if (*wild == '?' && *name) { + wild++; + name++; + if (!*wild && *name) + return 0; + } else if (dummyfunc(*wild) == dummyfunc(*name)) { + wild++; + name++; + } else { + return 0; + } + } + + return !name[0] || (name[0] == '/' && !name[1]); } OSSpec *OS_MatchPath(const char *path) { @@ -16,15 +56,63 @@ OSSpec *OS_MatchPath(const char *path) { Boolean isfile; OSSpec spec; const char *nptr; + + if (path) { + nptr = strrchr(path, '/'); + if (!nptr) { + nptr = path; + strcpyn(wilddir, ".", -1, 256); + } else { + nptr = nptr + 1; + strcpyn(wilddir, path, nptr - path, 256); + } + + if (OS_MakePathSpec(0, wilddir, &spec.path)) + return 0; + + strcpyn(wildname, nptr, -1, 64); + if (OS_MakeNameSpec(wildname, &spec.name)) + return 0; + + if (OS_OpenDir(&spec.path, &wilddirref)) + return 0; + } + + while (!OS_ReadDir(&wilddirref, &wildmatch, filename, &isfile)) { + if (isfile && WildCardMatch(wildname, filename)) + return &wildmatch; + } + + OS_CloseDir(&wilddirref); + return 0; } char *OS_GetFileNamePtr(char *path) { char *ptr; + ptr = strrchr(path, '/'); + return !ptr ? path : (ptr + 1); } char *OS_GetDirName(const OSPathSpec *spec, char *buf, int size) { char *path; char *pptr; + + if (!spec || !buf || size <= 0) + return 0; + + path = OS_PathSpecToString(spec, STSbuf, 256); + pptr = path + strlen(path) - 1; + if (pptr > path && *pptr == '/') { + *pptr = 0; + --pptr; + } + + while (pptr >= path && *pptr != '/') + pptr--; + + strncpy(buf, pptr, size - 1); + buf[size - 1] = 0; + return buf; } int OS_MakeSpec2(const char *path, const char *filename, OSSpec *spec) { @@ -32,6 +120,24 @@ int OS_MakeSpec2(const char *path, const char *filename, OSSpec *spec) { char *eptr; int pthlen; int fnlen; + + if (!path) + path = ""; + if (!filename) + filename = ""; + + fnlen = strlen(filename); + pthlen = strlen(path); + if (fnlen + pthlen + 1 > 255) + return ENAMETOOLONG; + + strncpy(bpath, path, pthlen); + eptr = bpath + pthlen; + if (eptr[-1] != '/') + *(eptr++) = '/'; + strcpy(eptr, filename); + + return OS_MakeSpec(bpath, spec, 0); } int OS_MakeSpecWithPath(OSPathSpec *path, const char *filename, Boolean noRelative, OSSpec *spec) { @@ -39,16 +145,84 @@ int OS_MakeSpecWithPath(OSPathSpec *path, const char *filename, Boolean noRelati char buf[256]; char *mptr; char *eptr; + + relpath = filename && strpbrk(filename, "/\\:"); + + if (!filename) { + if (path) + spec->path = *path; + else + OS_GetCWD(&spec->path); + return OS_MakeNameSpec("", &spec->name); + } else { + if ((!noRelative || !relpath) && !OS_IsFullPath(filename)) { + if (path) + OS_PathSpecToString(path, buf, 256); + else + buf[0] = 0; + + mptr = &buf[255] - strlen(filename); + eptr = &buf[strlen(buf)]; + strcpy((eptr > mptr) ? mptr : eptr, filename); + return OS_MakeSpec(buf, spec, 0); + } else { + return OS_MakeSpec(filename, spec, 0); + } + } } int OS_NameSpecChangeExtension(OSNameSpec *spec, const char *ext, Boolean append) { char tmp[64]; char *per; + + OS_NameSpecToString(spec, tmp, 256); + if (!append) { + per = strrchr(tmp, '.'); + if (!per) + per = tmp + strlen(tmp); + } else { + per = tmp + strlen(tmp); + if (ext[0] != '.') { + per[0] = '.'; + per[1] = 0; + per += 1; + } + } + + if (strlen(tmp) + strlen(ext) > 64) + per = tmp + 63 - strlen(ext); + + strcpy(per, ext); + return OS_MakeNameSpec(tmp, spec); } int OS_NameSpecSetExtension(OSNameSpec *spec, const char *ext) { char tmp[64]; char *per; + + OS_NameSpecToString(spec, tmp, 256); + if (ext[0] != '.') { + per = strrchr(tmp, '.'); + if (!per) + per = tmp + strlen(tmp); + + if (ext[0]) { + if (strlen(tmp) + 1 >= 64) { + per[-1] = '.'; + } else { + per[0] = '.'; + per++; + } + } + } else { + per = tmp + strlen(tmp); + } + + if (strlen(tmp) + strlen(ext) > 64) + per = tmp + 63 - strlen(ext); + + strcpy(per, ext); + return OS_MakeNameSpec(tmp, spec); } char *OS_CompactPaths(char *buf, const char *p, const char *n, int size) { diff --git a/command_line/CmdLine/Src/OSLib/MacFileTypes.c b/command_line/CmdLine/Src/OSLib/MacFileTypes.c index 9d18723..5c9cb1c 100644 --- a/command_line/CmdLine/Src/OSLib/MacFileTypes.c +++ b/command_line/CmdLine/Src/OSLib/MacFileTypes.c @@ -1,29 +1,120 @@ #include "oslib.h" +#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0) + +static OSFileTypeMappings *defaultList; +static OSFileTypeMappings **fmList = &defaultList; +int (*__OS_ExtendedGetMacFileTypeHook)(const OSSpec *, OSType *); + void OS_AddFileTypeMappingList(OSFileTypeMappings **list, OSFileTypeMappingList *entry) { + OSFileTypeMappings **scan; + + if (!list) + list = fmList; + + scan = list; + while (*scan) + scan = &(*scan)->next; + *scan = malloc(sizeof(OSFileTypeMappings)); +#line 40 + OPTION_ASSERT(*scan != NULL); + (*scan)->mappingList = entry; + (*scan)->next = 0; } void OS_UseFileTypeMappings(OSFileTypeMappings *list) { - + fmList = list ? &list : &defaultList; } void OS_MacType_To_OSType(OSType mactype, uOSTypePair *type) { + OSFileTypeMappings *list; + OSFileTypeMappingList *scan; + int idx; + + for (list = *fmList; list; list = list->next) { + scan = list->mappingList; + for (idx = 0; idx < scan->numMappings; idx++) { + if (scan->mappings[idx].mactype == mactype) { + type->perm = scan->mappings[idx].executable ? 0777 : 0666; + return; + } + } + } + *type = OS_TEXTTYPE; } int OS_SetMacFileType(const OSSpec *spec, OSType mactype) { - + uOSTypePair type; + OS_MacType_To_OSType(mactype, &type); + return OS_SetFileType(spec, &type); } Boolean OS_GetMacFileTypeMagic(const char *buffer, int count, OSType *mactype) { + OSFileTypeMappings *list; + OSFileTypeMappingList *scan; + int idx; + + *mactype = 0; + for (list = *fmList; list; list = list->next) { + scan = list->mappingList; + for (idx = 0; idx < scan->numMappings; idx++) { + if (scan->mappings[idx].length <= count && scan->mappings[idx].magic && !memcmp(buffer, scan->mappings[idx].magic, scan->mappings[idx].length)) { + *mactype = scan->mappings[idx].mactype; + return 1; + } + } + } + + return 0; } int OS_GetMacFileType(const OSSpec *spec, OSType *mactype) { + int ref; + int err; + char buffer[32]; + UInt32 count; + UInt32 flen; + OSSpec rsrc; + UInt32 rsize; + + err = OS_Open(spec, OSReadOnly, &ref); + if (err < 0) + return err; + + OS_GetSize(ref, &flen); + count = sizeof(buffer); + err = OS_Read(ref, buffer, &count); + OS_Close(ref); + + if (err >= 0 && count) { + if (OS_GetMacFileTypeMagic(buffer, count, mactype)) + return 0; + } + if (!__OS_ExtendedGetMacFileTypeHook || !__OS_ExtendedGetMacFileTypeHook(spec, mactype)) { + if (flen == 0) { + if (!OS_GetRsrcOSSpec(spec, &rsrc, 0)) { + int ref; + if (!OS_Open(&rsrc, OSReadOnly, &ref)) { + OS_GetSize(ref, &rsize); + OS_Close(ref); + if (rsize) { + *mactype = 'rsrc'; + return 0; + } + } + } + } + + *mactype = 'TEXT'; + } + + return 0; } int OS_SetMacFileCreatorAndType(const OSSpec *spec, OSType creator, OSType mactype) { - + return OS_SetMacFileType(spec, mactype); } diff --git a/command_line/CmdLine/Src/OSLib/MemUtils.c b/command_line/CmdLine/Src/OSLib/MemUtils.c index 4eb611c..fcacd81 100644 --- a/command_line/CmdLine/Src/OSLib/MemUtils.c +++ b/command_line/CmdLine/Src/OSLib/MemUtils.c @@ -1,21 +1,54 @@ #include "oslib.h" void *xmalloc(const char *what, int size) { - + void *ret; + + ret = malloc(size ? size : 1); + if (!ret) { + fprintf( + stderr, + "*** Out of memory when allocating %d bytes%s%s", + size, + what ? " for " : "", + what ? what : ""); + exit(-23); + return 0; + } + + return ret; } void *xcalloc(const char *what, int size) { + void *ret; + ret = xmalloc(what, size); + memset(ret, 0, size); + return ret; } void *xrealloc(const char *what, void *old, int size) { - + void *ret; + + ret = realloc(old, size ? size : 1); + if (!ret) { + fprintf( + stderr, + "*** Out of memory when resizing buffer to %d bytes%s%s", + size, + what ? " for " : "", + what ? what : ""); + exit(-23); + return 0; + } + + return ret; } char *xstrdup(const char *str) { - + return strcpy(xmalloc(0, strlen(str) + 1), str); } void xfree(void *ptr) { - + if (ptr) + free(ptr); } diff --git a/command_line/CmdLine/Src/OSLib/StringExtras.c b/command_line/CmdLine/Src/OSLib/StringExtras.c index 04ef6b4..a4415ee 100644 --- a/command_line/CmdLine/Src/OSLib/StringExtras.c +++ b/command_line/CmdLine/Src/OSLib/StringExtras.c @@ -1,17 +1,49 @@ #include "oslib.h" char *strcatn(char *d, const char *s, SInt32 max) { + char *p; + p = d + strlen(d); + while (*s && (p - d) + 1 < max) + *(p++) = *(s++); + + *p = 0; + return d; } char *strcpyn(char *d, const char *s, SInt32 len, SInt32 max) { + char *p; + + p = d; + while (len-- && *s && (p - d) + 1 < max) + *(p++) = *(s++); + *p = 0; + return d; } int ustrcmp(const char *src, const char *dst) { + int x; + do { + x = tolower(*src) - tolower(*(dst++)); + if (x) + return x; + } while (*(src++)); + + return 0; } int ustrncmp(const char *src, const char *dst, UInt32 len) { + int x; + + while (len--) { + x = tolower(*src) - tolower(*(dst++)); + if (x) + return x; + if (!*(src++)) + return 0; + } + return 0; } diff --git a/command_line/CmdLine/Src/OSLib/StringUtils.c b/command_line/CmdLine/Src/OSLib/StringUtils.c index 5f0d5bd..4ede522 100644 --- a/command_line/CmdLine/Src/OSLib/StringUtils.c +++ b/command_line/CmdLine/Src/OSLib/StringUtils.c @@ -1,49 +1,151 @@ #include "oslib.h" +#include "macemul.h" -StringPtr _pstrcpy(StringPtr dst, ConstStringPtr src) { +#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0) + +static char pfbuf[256]; +StringPtr _pstrcpy(StringPtr dst, ConstStringPtr src) { + memcpy(dst, src, src[0] + 1); + return dst; } void _pstrcat(StringPtr dst, ConstStringPtr src) { - + int cnt = dst[0] + src[0]; + if (cnt > 255) + cnt = 255; + memcpy(dst + 1 + dst[0], src + 1, cnt - dst[0]); + dst[0] = cnt; } void _pstrcharcat(StringPtr to, char ch) { - + if (to[0] < 255) { + to[0]++; + to[to[0]] = ch; + } } void pstrncpy(StringPtr to, ConstStringPtr from, int max) { - + SInt16 i = (from[0] > max) ? max : from[0]; + while (i >= 0) { + *(to++) = *(from++); + --i; + } } void pstrncat(StringPtr to, ConstStringPtr append, int max) { - + SInt16 i; + SInt16 n; + + i = *(append++); + n = to[0]; + if (i + n > max) + i = max - n; + to[0] += i; + to += n + 1; + + while (i-- > 0) { + *(to++) = *(append++); + } } int pstrcmp(ConstStringPtr a, ConstStringPtr b) { + int d = *(b++), n = *(a++); + if (n - d) + return n - d; + + while (n-- > 0) { + d = *(a++) != *(b++); + if (d) + return d; + } + return 0; } int pstrchr(ConstStringPtr str, char find) { + int idx = 0; + while (idx++ < str[0]) { + if (find == str[idx]) + return idx; + } + + return 0; } void c2pstrcpy(StringPtr dst, const char *src) { + int len = strlen(src); + if (len > 255) + len = 255; + memmove(dst + 1, src, len); + dst[0] = len; } void p2cstrcpy(char *dst, ConstStringPtr src) { - + memcpy(dst, src + 1, src[0]); + dst[src[0]] = 0; } char *mvprintf(char *mybuf, unsigned int len, const char *format, va_list va) { - + int maxlen; + int ret; + char *buf; + +#line 134 + OPTION_ASSERT(mybuf != NULL); + + maxlen = len - 1; + buf = mybuf; + ret = vsnprintf(mybuf, maxlen, format, va); + if (ret < 0) { + do { + if (buf != mybuf) + free(buf); + maxlen <<= 1; + buf = malloc(maxlen); + if (!buf) + return strncpy(mybuf, "<out of memory>", len); + ret = vsnprintf(buf, maxlen, format, va); + } while (ret < 0); + } else if (ret > maxlen) { + maxlen = ret + 1; + buf = malloc(maxlen); + if (!buf) + return strncpy(mybuf, "<out of memory>", len); + vsnprintf(buf, maxlen, format, va); + } + + return buf; } char *mprintf(char *mybuf, unsigned int len, const char *format, ...) { + char *ret; + + va_list ap; + va_start(ap, format); + ret = mvprintf(mybuf, len, format, ap); + va_end(ap); + return ret; } int HPrintF(Handle text, const char *format, ...) { + char *buf; + int ret; + + va_list ap; + va_start(ap, format); + buf = mvprintf(pfbuf, sizeof(pfbuf), format, ap); + va_end(ap); + + ret = strlen(buf); + if (PtrAndHand(buf, text, strlen(buf))) + return 0; + + if (buf != pfbuf) + free(buf); + return ret; } diff --git a/includes/common.h b/includes/common.h index 8f9c346..809f99f 100644 --- a/includes/common.h +++ b/includes/common.h @@ -15,6 +15,14 @@ //#include <MacHeadersMach-O> #define CW_PASCAL pascal #undef toupper +#undef tolower + +// What the fuck is this haha +// typedef char * va_list; +#define va_start(a,b) (a = ((va_list) __builtin_next_arg(b))) +#define va_arg(a,b) (*(b *) (void *) ((a = (char *) (((((unsigned long)(a)) + ((__alignof__ (b) == 16) ? 15 : 3)) & ~((__alignof__ (b) == 16) ? 15 : 3)) + ((sizeof (b) + 3) & ~3))) - ((sizeof (b) + 3) & ~3))) +#define va_end(a) ((void)0) + #else #include <stdarg.h> // expand this to nothing diff --git a/includes/oslib.h b/includes/oslib.h index fa444a3..fadc81f 100644 --- a/includes/oslib.h +++ b/includes/oslib.h @@ -54,12 +54,15 @@ typedef struct { OSPathSpec spec; } OSOpenedDir; // assumed name, might be something like OSDirRef though? +#ifdef __MWERKS__ +#pragma options align=packed +#endif typedef struct OSFileTypeMapping { OSType mactype; const char *magic; char length; + char executable; const char *mimetype; - char executable; // not sure why this is rearranged } OSFileTypeMapping; typedef struct OSFileTypeMappingList { @@ -71,10 +74,13 @@ typedef struct OSFileTypeMappings { OSFileTypeMappingList *mappingList; struct OSFileTypeMappings *next; } OSFileTypeMappings; +#ifdef __MWERKS__ +#pragma options align=reset +#endif /********************************/ /* Generic */ -extern int WildCardMatch(const char *wild, const char *name); +extern int WildCardMatch(char *wild, char *name); extern OSSpec *OS_MatchPath(const char *path); extern char *OS_GetFileNamePtr(char *path); extern char *OS_GetDirName(const OSPathSpec *spec, char *buf, int size); |