Author: andreas Date: 2011-06-09 01:25:48 -0700 (Thu, 09 Jun 2011) New Revision: 2411 Modified: trunk/platforms/Cross/plugins/FilePlugin/FilePlugin.h trunk/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c Log: Merging support files from cogvm branch. Modified: trunk/platforms/Cross/plugins/FilePlugin/FilePlugin.h =================================================================== --- trunk/platforms/Cross/plugins/FilePlugin/FilePlugin.h 2011-06-09 08:22:15 UTC (rev 2410) +++ trunk/platforms/Cross/plugins/FilePlugin/FilePlugin.h 2011-06-09 08:25:48 UTC (rev 2411) @@ -8,6 +8,7 @@ * EMAIL: * RCSID: $Id$ * +* 2009-05-15 EEM add stdio flag; reorder SQFile to make it more compact * 2005-03-26 IKP fix unaligned accesses to file member * 2004-06-10 IKP 64-bit cleanliness * 01/22/2002 JMM change off_t to squeakOffsetFileType @@ -18,11 +19,13 @@ /* squeak file record; see sqFilePrims.c for details */ typedef struct { - int sessionID; /* ikp: must be first */ - void *file; - int writable; - squeakFileOffsetType fileSize; - int lastOp; /* 0 = uncommitted, 1 = read, 2 = write */ + int sessionID; /* ikp: must be first */ + void *file; + squeakFileOffsetType fileSize; /* 64-bits we hope. */ + char writable; + char lastOp; /* 0 = uncommitted, 1 = read, 2 = write */ + char lastChar; + char isStdioStream; } SQFile; /* file i/o */ @@ -43,6 +46,7 @@ sqInt sqFileFlush(SQFile *f); sqInt sqFileTruncate(SQFile *f,squeakFileOffsetType offset); sqInt sqFileThisSession(void); +sqInt sqFileStdioHandlesInto(SQFile files[3]); /* directories */ Modified: trunk/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c =================================================================== --- trunk/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c 2011-06-09 08:22:15 UTC (rev 2410) +++ trunk/platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c 2011-06-09 08:25:48 UTC (rev 2411) @@ -9,8 +9,6 @@ * RCSID: $Id$ * * NOTES: See change log below. -* 2010-12-28 dtl add sqFileStdioHandlesInto() adapted from Cog branch -* 2008-08-29 bf add stdin/stdout/stderr support * 2005-03-26 IKP fix unaligned accesses to file[Size] members * 2004-06-10 IKP 64-bit cleanliness * 1/28/02 Tim remove non-ansi stuff @@ -28,7 +26,8 @@ * handling code. Note that the win32 platform #defines NO_STD_FILE_SUPPORT * and thus bypasses this file */ - + +#include <errno.h> #include "sq.h" #ifndef NO_STD_FILE_SUPPORT #include "FilePlugin.h" @@ -54,11 +53,13 @@ positioning operation to be done automatically if needed. typedef struct { + int sessionID; File *file; - int sessionID; - int writable; squeakFileOffsetType fileSize; //JMM Nov 8th 2001 64bits we hope - int lastOp; // 0 = uncommitted, 1 = read, 2 = write // + char writable; + char lastOp; // 0 = uncommitted, 1 = read, 2 = write // + char lastChar; // one character peek for stdin // + char isStdioStream; } SQFile; ***/ @@ -78,20 +79,32 @@ int thisSession = 0; extern struct VirtualMachine * interpreterProxy; +/* Since SQFile instaces are held on the heap in 32-bit-aligned byte arrays we + * may need to use memcpy to avoid alignment faults. + */ +#if DOUBLE_WORD_ALIGNMENT static void setFile(SQFile *f, FILE *file) { void *in= (void *)&file; void *out= (void *)&f->file; memcpy(out, in, sizeof(FILE *)); } +#else +# define setFile(f,fileptr) ((f)->file = (fileptr)) +#endif +#if DOUBLE_WORD_ALIGNMENT static void setSize(SQFile *f, squeakFileOffsetType size) { void *in= (void *)&size; void *out= (void *)&f->fileSize; memcpy(out, in, sizeof(squeakFileOffsetType)); } +#else +# define setSize(f,size) ((f)->fileSize = (size)) +#endif +#if DOUBLE_WORD_ALIGNMENT static FILE *getFile(SQFile *f) { FILE *file; @@ -100,7 +113,11 @@ memcpy(out, in, sizeof(FILE *)); return file; } +#else +# define getFile(f) ((FILE *)((f)->file)) +#endif +#if DOUBLE_WORD_ALIGNMENT static squeakFileOffsetType getSize(SQFile *f) { squeakFileOffsetType size; @@ -109,28 +126,43 @@ memcpy(out, in, sizeof(squeakFileOffsetType)); return size; } +#else +# define getSize(f) ((f)->fileSize) +#endif +#if 0 +# define pentry(func) do { int fn = fileno(getFile(f)); if (f->isStdioStream) printf("\n"#func "(%s) %lld %d\n", fn == 0 ? "in" : fn == 1 ? "out" : "err", (long long)ftell(getFile(f)), f->lastChar); } while (0) +# define pexit(expr) (f->isStdioStream && printf("\n\t^"#expr " %lld %d\n", (long long)(sqFileValid(f) ? ftell(getFile(f)) : -1), f->lastChar)), expr +# define pfail() printf("\tFAIL\n"); +#else +# define pentry(func) 0 +# define pexit(expr) expr +# define pfail() 0 +#endif sqInt sqFileAtEnd(SQFile *f) { /* Return true if the file's read/write head is at the end of the file. */ - if (!sqFileValid(f)) return interpreterProxy->success(false); - return ftell(getFile(f)) >= getSize(f); + if (!sqFileValid(f)) + return interpreterProxy->success(false); + pentry(sqFileAtEnd); + if (f->isStdioStream) + return pexit(feof(getFile(f))); + return ftell(getFile(f)) == getSize(f); } sqInt sqFileClose(SQFile *f) { /* Close the given file. */ - FILE *file; - if (!sqFileValid(f)) return interpreterProxy->success(false); - file = getFile(f); - if (file != stdin && file != stdout && file != stderr) - fclose(file); + if (!sqFileValid(f)) + return interpreterProxy->success(false); + fclose(getFile(f)); setFile(f, 0); f->sessionID = 0; f->writable = false; setSize(f, 0); f->lastOp = UNCOMMITTED; + return 1; } sqInt sqFileDeleteNameSize(char* sqFileName, sqInt sqFileNameSize) { @@ -148,6 +180,7 @@ if (err) { return interpreterProxy->success(false); } + return 1; } squeakFileOffsetType sqFileGetPosition(SQFile *f) { @@ -155,9 +188,15 @@ squeakFileOffsetType position; - if (!sqFileValid(f)) return interpreterProxy->success(false); + if (!sqFileValid(f)) + return interpreterProxy->success(false); + pentry(sqFileGetPosition); + if (f->isStdioStream + && !f->writable) + return pexit(f->lastChar == EOF ? 0 : 1); position = ftell(getFile(f)); - if (position == -1) return interpreterProxy->success(false); + if (position == -1) + return interpreterProxy->success(false); return position; } @@ -167,7 +206,7 @@ Should be called once at startup time. */ #if VM_PROXY_MINOR > 6 - thisSession = (int) interpreterProxy->getThisSessionID(); + thisSession = interpreterProxy->getThisSessionID(); #else thisSession = ioLowResMSecs() + time(NULL); if (thisSession == 0) thisSession = 1; /* don't use 0 */ @@ -179,15 +218,6 @@ return 1; } -static int setStdFilename(char* stdFilename, char *cFileName, char *sqFileName, sqInt sqFileNameSize) -{ - if (!strncmp(stdFilename, sqFileName,sqFileNameSize)) { - strcpy(cFileName, stdFilename); - return 1; - } else - return 0; -} - sqInt sqFileOpen(SQFile *f, char* sqFileName, sqInt sqFileNameSize, sqInt writeFlag) { /* Opens the given file using the supplied sqFile structure to record its state. Fails with no side effects if f is @@ -198,26 +228,18 @@ char cFileName[1001]; /* don't open an already open file */ - if (sqFileValid(f)) return interpreterProxy->success(false); + if (sqFileValid(f)) + return interpreterProxy->success(false); /* copy the file name into a null-terminated C string */ if (sqFileNameSize > 1000) { return interpreterProxy->success(false); } + interpreterProxy->ioFilenamefromStringofLengthresolveAliases(cFileName, sqFileName, sqFileNameSize, true); - if (setStdFilename("/dev/stdin", cFileName, sqFileName, sqFileNameSize)) - setFile(f, stdin); - else if (setStdFilename("/dev/stdout", cFileName, sqFileName, sqFileNameSize)) - setFile(f, stdout); - else if (setStdFilename("/dev/stderr", cFileName, sqFileName, sqFileNameSize)) - setFile(f, stderr); - else - interpreterProxy->ioFilenamefromStringofLengthresolveAliases(cFileName, sqFileName, sqFileNameSize, true); - if (writeFlag) { /* First try to open an existing file read/write: */ - if (getFile(f) == NULL) - setFile(f, fopen(cFileName, "r+b")); + setFile(f, fopen(cFileName, "r+b")); if (getFile(f) == NULL) { /* Previous call fails if file does not exist. In that case, try opening it in write mode to create a new, empty file. @@ -232,8 +254,7 @@ } f->writable = true; } else { - if (getFile(f) == NULL) - setFile(f, fopen(cFileName, "rb")); + setFile(f, fopen(cFileName, "rb")); f->writable = false; } @@ -250,6 +271,7 @@ fseek(file, 0, SEEK_SET); } f->lastOp = UNCOMMITTED; + return 1; } /* @@ -260,26 +282,36 @@ sqInt sqFileStdioHandlesInto(SQFile files[3]) { -#if defined(_IONBF) +#if defined(_IONBF) && 0 if (isatty(fileno(stdin))) - setvbuf(stdin,0,_IONBF,0); +# if 0 + setvbuf(stdin,0,_IONBF,1); +# else + setvbuf(stdin,0,_IOFBF,0); +# endif #endif files[0].sessionID = thisSession; files[0].file = stdin; files[0].fileSize = 0; files[0].writable = false; files[0].lastOp = READ_OP; + files[0].isStdioStream = true; + files[0].lastChar = EOF; files[1].sessionID = thisSession; files[1].file = stdout; files[1].fileSize = 0; files[1].writable = true; + files[1].isStdioStream = true; + files[1].lastChar = EOF; files[1].lastOp = WRITE_OP; files[2].sessionID = thisSession; files[2].file = stderr; files[2].fileSize = 0; files[2].writable = true; + files[2].isStdioStream = true; + files[2].lastChar = EOF; files[2].lastOp = WRITE_OP; return 7; @@ -296,14 +328,47 @@ char *dst; size_t bytesRead; FILE *file; +#if COGMTVM + sqInt myThreadIndex; +#endif - if (!sqFileValid(f)) return interpreterProxy->success(false); - file= getFile(f); - if (f->writable && (f->lastOp == WRITE_OP)) fseek(file, 0, SEEK_CUR); /* seek between writing and reading */ + if (!sqFileValid(f)) + return interpreterProxy->success(false); + pentry(sqFileReadIntoAt); + file = getFile(f); + if (f->writable) { + if (f->isStdioStream) + return interpreterProxy->success(false); + if (f->lastOp == WRITE_OP) + fseek(file, 0, SEEK_CUR); /* seek between writing and reading */ + } dst = byteArrayIndex + startIndex; - bytesRead = fread(dst, 1, count, file); +#if COGMTVM + if (f->isStdioStream) { + if (interpreterProxy->isInMemory((sqInt)f) + && interpreterProxy->isYoung((sqInt)f) + || interpreterProxy->isInMemory((sqInt)dst) + && interpreterProxy->isYoung((sqInt)dst)) { + interpreterProxy->primitiveFailFor(PrimErrObjectMayMove); + return 0; + } + myThreadIndex = interpreterProxy->disownVM(DisownVMLockOutFullGC); + } +#endif + do { + clearerr(file); + bytesRead = fread(dst, 1, count, file); + } while (bytesRead <= 0 && ferror(file) && errno == EINTR); +#if COGMTVM + if (f->isStdioStream) + interpreterProxy->ownVM(myThreadIndex); +#endif + /* support for skipping back 1 character for stdio streams */ + if (f->isStdioStream) + if (bytesRead > 0) + f->lastChar = dst[bytesRead-1]; f->lastOp = READ_OP; - return bytesRead; + return pexit(bytesRead); } sqInt sqFileRenameOldSizeNewSize(char* oldNameIndex, sqInt oldNameSize, char* newNameIndex, sqInt newNameSize) { @@ -323,38 +388,61 @@ if (err) { return interpreterProxy->success(false); } + return 1; } sqInt sqFileSetPosition(SQFile *f, squeakFileOffsetType position) { /* Set the file's read/write head to the given position. */ - if (!sqFileValid(f)) return interpreterProxy->success(false); + if (!sqFileValid(f)) + return interpreterProxy->success(false); + if (f->isStdioStream) { + pentry(sqFileSetPosition); + /* support one character of pushback for stdio streams. */ + if (!f->writable + && f->lastChar != EOF) { + squeakFileOffsetType currentPos = f->lastChar == EOF ? 0 : 1; + if (currentPos == position) + return pexit(1); + if (currentPos - 1 == position) { + ungetc(f->lastChar, getFile(f)); + f->lastChar = EOF; + return pexit(1); + } + } + pfail(); + return interpreterProxy->success(false); + } fseek(getFile(f), position, SEEK_SET); f->lastOp = UNCOMMITTED; + return 1; } squeakFileOffsetType sqFileSize(SQFile *f) { /* Return the length of the given file. */ - if (!sqFileValid(f)) return interpreterProxy->success(false); + if (!sqFileValid(f)) + return interpreterProxy->success(false); + if (f->isStdioStream) + return interpreterProxy->success(false); return getSize(f); } sqInt sqFileFlush(SQFile *f) { - /* Return the length of the given file. */ - if (!sqFileValid(f)) return interpreterProxy->success(false); + if (!sqFileValid(f)) + return interpreterProxy->success(false); + pentry(sqFileFlush); fflush(getFile(f)); return 1; } sqInt sqFileTruncate(SQFile *f,squeakFileOffsetType offset) { - /* Truncate the file*/ - if (!sqFileValid(f)) return interpreterProxy->success(false); - if (sqFTruncate(getFile(f), offset)) { - return interpreterProxy->success(false); - } + if (!sqFileValid(f)) + return interpreterProxy->success(false); + if (sqFTruncate(getFile(f), offset)) + return interpreterProxy->success(false); setSize(f, ftell(getFile(f))); return 1; } @@ -378,8 +466,10 @@ squeakFileOffsetType position; FILE *file; - if (!(sqFileValid(f) && f->writable)) return interpreterProxy->success(false); - file= getFile(f); + if (!(sqFileValid(f) && f->writable)) + return interpreterProxy->success(false); + pentry(sqFileWriteFromAt); + file = getFile(f); if (f->lastOp == READ_OP) fseek(file, 0, SEEK_CUR); /* seek between reading and writing */ src = byteArrayIndex + startIndex; bytesWritten = fwrite(src, 1, count, file); @@ -393,12 +483,10 @@ interpreterProxy->success(false); } f->lastOp = WRITE_OP; - return bytesWritten; + return pexit(bytesWritten); } sqInt sqFileThisSession() { return thisSession; } - #endif /* NO_STD_FILE_SUPPORT */ - |
Free forum by Nabble | Edit this page |