diff options
author | Chris Apers | 2006-02-25 20:34:13 +0000 |
---|---|---|
committer | Chris Apers | 2006-02-25 20:34:13 +0000 |
commit | 1d09fb169b45671e47586e9d0ed811212dd9ba74 (patch) | |
tree | a55584aaf2deaf2634927921e96aa31198e9df30 /backends/PalmOS/Src/missing/ext_stdio.c | |
parent | 544438b01e0827bb223f22276edc9fe1344735a7 (diff) | |
download | scummvm-rg350-1d09fb169b45671e47586e9d0ed811212dd9ba74.tar.gz scummvm-rg350-1d09fb169b45671e47586e9d0ed811212dd9ba74.tar.bz2 scummvm-rg350-1d09fb169b45671e47586e9d0ed811212dd9ba74.zip |
Rename those files so that:
- fucntions can also be used in C projects
- functions really replace same functions from MSL instead of having multiple definitions for C and C++
svn-id: r20887
Diffstat (limited to 'backends/PalmOS/Src/missing/ext_stdio.c')
-rw-r--r-- | backends/PalmOS/Src/missing/ext_stdio.c | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/backends/PalmOS/Src/missing/ext_stdio.c b/backends/PalmOS/Src/missing/ext_stdio.c new file mode 100644 index 0000000000..c973e64552 --- /dev/null +++ b/backends/PalmOS/Src/missing/ext_stdio.c @@ -0,0 +1,645 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001-2006 The ScummVM project + * Copyright (C) 2002-2006 Chris Apers - PalmOS Backend + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <PmPalmOSNVFS.h> + +#define CACHE_SIZE 1024 +enum { + MODE_BUFREAD = 1, + MODE_BUFWRITE, + MODE_BUFNONE +}; + +FILE gStdioOutput = {0,0,0,0,0,0}; +static void dummy(Boolean) {}; + +static LedProc gStdioLedProc = dummy; +static UInt16 gStdioVolRefNum = vfsInvalidVolRef; +static UInt32 gCacheSize = CACHE_SIZE; + +// TODO : implement "errno" + +void StdioInit(UInt16 volRefNum, const Char *output) { // DONE + gStdioVolRefNum = volRefNum; + gStdioOutput.mode = MODE_BUFWRITE; + + VFSFileDelete(gStdioVolRefNum, output); + VFSFileCreate(gStdioVolRefNum, output); + VFSFileOpen (gStdioVolRefNum, output,vfsModeWrite, &gStdioOutput.fileRef); +} + +void StdioSetLedProc(LedProc ledProc) { // DONE + if (ledProc) + gStdioLedProc = ledProc; + else + gStdioLedProc = dummy; +} + +void StdioSetCacheSize(UInt32 s) { // DONE + gCacheSize = s; +} + +void StdioRelease() { // DONE + // there is no cache on stdout/stderr + VFSFileClose(gStdioOutput.fileRef); +} + +UInt16 fclose(FILE *stream) { // DONE + UInt32 numBytesWritten; + Err e; + + if (stream->cacheSize) { + if (stream->bufSize > 0 && stream->mode == MODE_BUFWRITE) + VFSFileWrite(stream->fileRef, stream->bufSize, stream->cache, &numBytesWritten); + + MemPtrFree(stream->cache); + } + + e = VFSFileClose(stream->fileRef); + e = MemPtrFree(stream); + + return e; +} + +UInt16 feof(FILE *stream) { // DONE + Err e; + + if (stream->cacheSize) { + switch (stream->mode) { + case MODE_BUFWRITE: + return 0; // never set in this mode + case MODE_BUFREAD: + if (stream->bufSize > 0) + return 0; + break; + } + } + + e = VFSFileEOF(stream->fileRef); + return e; +} + +UInt16 ferror(FILE *stream) { + return (stream->err); +} + +Int16 fgetc(FILE *stream) { + UInt32 numBytesRead; + Char c; + + numBytesRead = fread(&c, 1, 1, stream); + return (int)(numBytesRead == 1 ? c : EOF); +} + +Char *fgets(Char *s, UInt32 n, FILE *stream) { + UInt32 numBytesRead; + + numBytesRead = fread(s, n, 1, stream); + if (numBytesRead) { + UInt32 reset = 0; + Char *endLine = StrChr(s, '\n'); + + if (endLine >= s) { + reset = (endLine - s); + s[reset] = 0; + reset = numBytesRead - (reset + 1); + fseek(stream, -reset, SEEK_CUR); + } + + return s; + } + + return NULL; +} + +FILE *fopen(const Char *filename, const Char *type) { // DONE + Err err; + UInt16 openMode; + Boolean cache = true; + FILE *fileP = (FILE *)MemPtrNew(sizeof(FILE)); + + if (!fileP) + return NULL; + + MemSet(fileP, sizeof(FILE), 0); + + if (StrCompare(type,"r")==0 || StrCompare(type,"rb")==0) { + fileP->mode = MODE_BUFREAD; + openMode = vfsModeRead; + + } else if (StrCompare(type,"w")==0 || StrCompare(type,"wb")==0) { + fileP->mode = MODE_BUFWRITE; + openMode = vfsModeCreate|vfsModeWrite; + + } else { + cache = false; + fileP->mode = MODE_BUFNONE; + openMode = vfsModeReadWrite; + } + + if (cache) { + fileP->cacheSize = gCacheSize; + if (gCacheSize) fileP->cache = (UInt8 *)malloc(gCacheSize); // was MemGluePtrNew + if (!fileP->cache) fileP->cacheSize = 0; + } + + if (openMode & vfsModeRead) { + // if read file : + // first try to load from the specfied card + err = VFSFileOpen (gStdioVolRefNum, filename, openMode, &fileP->fileRef); + //if err (not found ?) parse each avalaible card for the specified file + if (err) { + UInt16 volRefNum; + UInt32 volIterator = vfsIteratorStart|vfsIncludePrivateVolumes; + while (volIterator != vfsIteratorStop) { + err = VFSVolumeEnumerate(&volRefNum, &volIterator); + + if (!err) { + err = VFSFileOpen (volRefNum, filename, openMode, &fileP->fileRef); + if (!err) + return fileP; + } + } + } else { + return fileP; + } + } else { + // if write file : + // use only the specified card + err = VFSFileDelete(gStdioVolRefNum, filename); // delete it if exists + err = VFSFileCreate(gStdioVolRefNum, filename); + openMode = vfsModeWrite; + if (!err) { + err = VFSFileOpen (gStdioVolRefNum, filename, openMode, &fileP->fileRef); + if (!err) + return fileP; + } + } + + if (fileP->cacheSize) + MemPtrFree(fileP->cache); + + MemPtrFree(fileP); // prevent memory leak + return NULL; +} + +UInt32 fread(void *ptr, UInt32 size, UInt32 nitems, FILE *stream) { // DONE + Err e = errNone; + UInt32 numBytesRead, rsize = (size * nitems); + + // try to read on a write only stream ? + if (stream->mode == MODE_BUFWRITE || !rsize) + return 0; + + // cached ? + if (stream->cacheSize) { + // empty buffer ? fill it if required + if (stream->bufSize == 0 && rsize < stream->cacheSize) { + gStdioLedProc(true); + e = VFSFileRead(stream->fileRef, stream->cacheSize, stream->cache, &numBytesRead); + gStdioLedProc(false); + stream->bufSize = numBytesRead; + stream->bufPos = 0; + } + + // we have the data in the cache + if (stream->bufSize >= rsize) { + MemMove(ptr, (stream->cache + stream->bufPos), rsize); + stream->bufPos += rsize; + stream->bufSize -= rsize; + numBytesRead = rsize; + + // not enough but something ? + } else if (stream->bufSize > 0) { + UInt8 *next = (UInt8 *)ptr; + MemMove(ptr, (stream->cache + stream->bufPos), stream->bufSize); + rsize -= stream->bufSize; + gStdioLedProc(true); + e = VFSFileRead(stream->fileRef, rsize, (next + stream->bufSize), &numBytesRead); + gStdioLedProc(false); + numBytesRead += stream->bufSize; + stream->bufSize = 0; + stream->bufPos = 0; + + // nothing in the cache ? + } else { + gStdioLedProc(true); + e = VFSFileRead(stream->fileRef, rsize, ptr, &numBytesRead); + gStdioLedProc(false); + } + + // no ? direct read + } else { + gStdioLedProc(true); + e = VFSFileRead(stream->fileRef, rsize, ptr, &numBytesRead); + gStdioLedProc(false); + } + + if (e == errNone || e == vfsErrFileEOF) + return (UInt32)(numBytesRead / size); + + return 0; +} + +UInt32 fwrite(const void *ptr, UInt32 size, UInt32 nitems, FILE *stream) { // DONE + Err e = errNone; + UInt32 numBytesWritten = (size * nitems); + + // try to write on a read only stream ? + if (stream->mode == MODE_BUFREAD || !numBytesWritten) + return 0; + + // cached ? + if (stream->cacheSize) { + // can cache it ? + if ((stream->bufSize + numBytesWritten) <= stream->cacheSize) { + MemMove((stream->cache + stream->bufSize), ptr, numBytesWritten); + stream->bufSize += numBytesWritten; + + // not enough room ? write cached data and new data + } else { + gStdioLedProc(true); + e = VFSFileWrite(stream->fileRef, stream->bufSize, stream->cache, &numBytesWritten); + e = VFSFileWrite(stream->fileRef, (size * nitems), ptr, &numBytesWritten); + gStdioLedProc(false); + stream->bufSize = 0; + } + + // no ? direct write + } else { + gStdioLedProc(true); + e = VFSFileWrite(stream->fileRef, (size * nitems), ptr, &numBytesWritten); + gStdioLedProc(false); + } + + if ((e == errNone || e == vfsErrFileEOF)) { + return (UInt32)(numBytesWritten / size); + } + + return 0; +} + +Int16 fseek(FILE *stream, Int32 offset, Int32 whence) { // DONE + UInt32 numBytesWritten; + Err e; + + if (stream->cacheSize) { + switch (stream->mode) { + case MODE_BUFWRITE: + e = VFSFileWrite(stream->fileRef, stream->bufSize, stream->cache, &numBytesWritten); + stream->bufSize = 0; + break; + + case MODE_BUFREAD: + // reposition file postion if needed + if (whence == SEEK_CUR) + e = VFSFileSeek(stream->fileRef, vfsOriginCurrent, -stream->bufSize); + stream->bufSize = 0; + stream->bufPos = 0; + break; + } + } + + e = VFSFileSeek(stream->fileRef, whence, offset); + return (e ? -1 : 0); +} + +Int32 ftell(FILE *stream) { // DONE + Err e; + UInt32 filePos; + + e = VFSFileTell(stream->fileRef ,&filePos); + + if (stream->cacheSize) { + switch (stream->mode) { + case MODE_BUFWRITE: + filePos += stream->bufSize; + break; + + case MODE_BUFREAD: + filePos -= stream->bufSize; + break; + } + } + + if (e) return -1; // errno = ? + return filePos; +} + +Int32 fprintf(FILE *stream, const Char *formatStr, ...) { // DONE + UInt32 numBytesWritten; + Char buf[256]; + va_list va; + + if (!stream->fileRef) + return 0; + + va_start(va, formatStr); + vsprintf(buf, formatStr, va); + va_end(va); + + numBytesWritten = fwrite(buf, StrLen(buf), 1, stream); + return numBytesWritten; +} + +Int32 printf(const Char *format, ...) { // DONE + UInt32 numBytesWritten; + Char buf[256]; + va_list va; + + if (!stdout->fileRef) + return 0; + + va_start(va, format); + vsprintf(buf, format, va); + va_end(va); + + numBytesWritten = fwrite(buf, StrLen(buf), 1, stdout); + return numBytesWritten; +} + +Int32 sprintf(Char* s, const Char* formatStr, ...) { + Int16 count; + va_list va; + + va_start(va, formatStr); + count = vsprintf(s, formatStr, va); + va_end(va); + + return count; +} + +Int32 snprintf(Char* s, UInt32 len, const Char* formatStr, ...) { + // len is ignored + Int16 count; + va_list va; + + va_start(va, formatStr); + count = vsprintf(s, formatStr, va); + va_end(va); + + return count; +} + + +/* WARNING : vsprintf + * ------- + * This function can handle only %[+- ][.0][field length][sxXdoiucp] format strings + * compiler option : 4byte int mode only ! + * + * TODO : check http://www.ijs.si/software/snprintf/ for a portable implementation of vsnprintf + * This one make use of sprintf so need to check if it works with PalmOS. + */ + +static Char *StrIToBase(Char *s, Int32 i, UInt8 b) { + const Char *conv = "0123456789ABCDEF"; + Char o; + Int16 c, n = 0; + Int32 div, mod; + + do { + div = i / b; + mod = i % b; + + s[n++] = *(conv + mod); + i = div; + + } while (i >= b); + + if (i > 0) { + s[n + 0] = *(conv + i); + s[n + 1] = 0; + } else { + s[n + 0] = 0; + n--; + } + + for (c=0; c <= (n >> 1); c++) { + o = s[c]; + s[c] = s[n - c]; + s[n - c]= o; + } + + return s; +} + +static void StrProcC_(Char *ioStr, UInt16 maxLen) { + Char *found; + Int16 length; + + while (found = StrStr(ioStr, "`c`")) { + if (found[3] == 0) { // if next char is NULL + length = maxLen - (found - ioStr + 2); + MemMove(found, found + 4, length); + maxLen -= 2; + } + } +} + +static void StrProcXO(Char *ioStr, UInt16 maxLen, Char *tmp) { + Char *found, *last, mod, fill; + Int16 len, count, next; + Int32 val; + + while (found = StrChr(ioStr, '`')) { + last = StrChr(found + 1, '`'); + + if (!last) + return; + + *last = 0; + next = 0; + fill = *(found + 1); + mod = *(found + 2); + count = StrAToI(found + 3); + + len = maxLen - (last - ioStr); + MemMove(found, (last + 1), len); + + // x and X always 8char on palmos ... o set to 8char (not supported on palmos) + while ((found[next] == '0' || found[next] == ' ') && next < 8) // WARNING : reduce size only (TODO ?) + next++; + + // convert to base 8 + if (mod == 'o') { + StrNCopy(tmp, found + next, 8 - next); + tmp[8 - next] = 0; + val = StrAToI(tmp); + StrIToBase(tmp, val, 8); // now we have the same but in octal + next = 8 - StrLen(tmp); + MemMove(found + next, tmp, StrLen(tmp)); + } else { + // if val is 0, keep last 0 + if (next == 8) + next = 7; + } + + if ((8 - next) > count) + count = 8 - next; + + if (count == 0) + count = 1; + + len = maxLen - (found - ioStr) - (8 - count); + MemSet(found, next, fill); + MemMove(found, found + (8 - count), len); + + // ... and upper case + if (mod == 'x') { + while (count--) { + if (*found >='A' && *found <='F') + *found = (*found + 32); + found++; + } + } + } +} + +Int32 vsprintf(Char* s, const Char* formatStr, _Palm_va_list argParam) { + Char format[256], result[256], tmp[32]; + + Char *found, *mod, *num; + UInt32 next; + Boolean zero; + Int16 count, len; + + MemSet(format, sizeof(format), 'x'); + MemSet(result, sizeof(result), 'y'); + MemSet(tmp, sizeof(tmp), 'z'); + + StrCopy(format,formatStr); // copy actual formatStr to temp buffer + next = 0; // start of the string + + while (found = StrChr(format + next, '%')) { + mod = found + 1; + + if (*mod == '%') { // just a % ? + mod++; + + } else { + if (*mod == '+' || + *mod == '-' || + *mod == ' ' ) // skip + mod++; + + if (*mod == '0' || + *mod == '.' ) { + *mod++ = '0'; + zero = true; + } else { + zero = false; + } + + num = mod; + while ( *mod >= '0' && + *mod <= '9' ) // search format char + mod++; + + // get the numeric value + if (num < mod) { + StrNCopy(tmp, num, mod - num); + tmp[mod - num] = 0; + count = StrAToI(tmp); + } else { + count = 0; + } + + if (*mod == 'l') // already set to %...l(x) ? + mod++; + + // prepare new format +#if !defined(PALMOS_ARM) + if (*mod == 'c') { + StrCopy(tmp, "`c`%c%c"); + + } else +#endif + if (*mod == 'p') { + StrCopy(tmp, "%08lX"); // %x = %08X in palmos + + } else { + len = 0; + + switch (*mod) { + case 'x': + case 'X': + case 'o': + tmp[0] = '`'; + tmp[1] = (zero) ? '0' : ' '; + tmp[2] = *mod; + StrIToA(tmp + 3, count); + len += StrLen(tmp); + tmp[len++] = '`'; + tmp[len] = 0; + + if (*mod == 'o') { // set as base 10 num and convert later + *mod = 'd'; + count = 8; // force 8char + } + + break; + } + + StrNCopy(tmp + len, found, (num - found)); + len += (num - found); + + if (count) { + StrIToA(tmp + len, count); + len += StrLen(tmp + len); + } + + if (*mod == 'd' || + *mod == 'i' || + *mod == 'x' || + *mod == 'X' || + *mod == 'u' + ) { + tmp[len++] = 'l'; + } + + tmp[len + 0] = *mod; + tmp[len + 1] = 0; + } + + mod++; + MemMove(found + StrLen(tmp), mod, StrLen(mod) + 1); + StrNCopy(found, tmp, StrLen(tmp)); + mod = found + StrLen(tmp); + } + + next = (mod - format); + } + + // Copy result in a temp buffer to process last formats + StrVPrintF(result, format, argParam); +#if !defined(PALMOS_ARM) + StrProcC_(result, 256); +#endif + StrProcXO(result, 256, tmp); + StrCopy(s, result); + + return StrLen(s); +} |