Re: [Flex-help] flex 2.6.0 lexer cannot be restarted on Solaris 11.3
flex is a tool for generating scanners
Brought to you by:
wlestes
From: Mark B. <cha...@ya...> - 2016-06-10 11:45:32
|
Ok apparently my old and crusty code written in 2002 ought to be modernised. So instead of the old-fashioned close fd 0 and call fopen() immediately afterwards which I remember from time immemorial, if I use the fancy new shiny freopen() function with stdin instead it all turns out well and the problem goes away. Still, interesting I thought as to why this works on Linux, but that's more of an academic question now. Nothing to fix in flex then, just in the way that I redirect stdin. Best regards,Mark. Sent from Yahoo Mail on Android On Fri, 10 Jun, 2016 at 9:31, Mark Bannister<cha...@ya...> wrote: > I have all the equipment to test this and run through the whole > process but I know not many people do. I also know that Oracle is > pouring about a billion dollars into the new SPARC architecture and have > some new equipment about to release. Certainly the new SPARC M7 is a > monster and having 1024 cores at over 4GHz is pretty cool. Anyways, > Solaris is not going away any time soon and so it may be of value for me > to crack open a dev zone or some facilties for Will and some others to > use on these type of tasks. I've done some more debugging and I've found the problem. The issue is thatYY_INPUT is using fread() on stdin. However, as we never fopen() or fclose()stdin, the file buffer is left hanging around. I've tried various potential solutionsand the only one I can get to work is to use read() on STDIN_FILENO instead.That would require a change to the definition of the YY_INPUT macro. Here is a test case: #include <stdio.h> #include <unistd.h> #define MAX_BUFFER 100 int main(int argc, char **argv) { FILE *fp; int i, n; char buf[MAX_BUFFER]; if (argc<2) return -1; for (i=1; i<argc; i++) { close(STDIN_FILENO); if (!(fp=fopen(argv[i], "r"))) return -1; printf("%s open\n", argv[i]); /* n=(int)read(STDIN_FILENO, buf, MAX_BUFFER); */ n=(int)fread(buf, 1, MAX_BUFFER, stdin); printf("%d bytes read\n", n); fclose(fp); printf("%s closed\n\n", argv[i]); } return 0; } Compile with gcc, create two single line files (file1 and file2) and compare theoutput on Linux vs. Solaris: ---- Linux (Fedora 23) ----$ ./testread file1 file2 file1 open 5 bytes read file1 closed file2 open 5 bytes read file2 closed ---- Solaris 11.3 ----$ ./testread file1 file2 file1 open 5 bytes read file1 closed file2 open 0 bytes read file2 closed When run on Solaris, the stdin file buffer still records end of file when we really intendit to read from the second file. It doesn't know that we have subsequently closedand re-opened the underlying file descriptor. Also, if the first file were to be bigger than the read buffer (in this case more than 100bytes), when we think we're reading the second file we're actually reading the next100 bytes from the first file. I've tried setvbuf() on stdin to set it to unbuffered, which makes no difference. I've triedfflush(stdin) in various places, which also makes no difference. The only fix I can find to work is to replace the fread() from stdin to a read() fromSTDIN_FILENO. Then the behaviour on Solaris is identical to Linux, and the outputis as expected. Best regards,Mark. |