re2c: Work around tmpfile() issue on win32.

tmpfile() defaults to C:\, and on Windows 7 can run into permissions issues.
Add workaround implementation from cairo
(http://cgit.freedesktop.org/cairo/commit/?id=4fa46e3caaffb54f4419887418d8d0ea39816092)

See also: http://msdn.microsoft.com/en-us/library/x8x7sakw(v=VS.80).aspx
(community content section)
This commit is contained in:
Peter Johnson 2011-10-30 23:50:31 -07:00
parent b334347286
commit ab19547382

View file

@ -1,3 +1,7 @@
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@ -6,6 +10,57 @@
#include "tools/re2c/dfa.h"
#include "tools/re2c/parse.h"
#ifdef _WIN32
/* tmpfile() replacment for Windows.
*
* On Windows tmpfile() creates the file in the root directory. This
* may fail due to unsufficient privileges.
*/
static FILE *
win32_tmpfile (void)
{
DWORD path_len;
WCHAR path_name[MAX_PATH + 1];
WCHAR file_name[MAX_PATH + 1];
HANDLE handle;
int fd;
FILE *fp;
path_len = GetTempPathW (MAX_PATH, path_name);
if (path_len <= 0 || path_len >= MAX_PATH)
return NULL;
if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
return NULL;
handle = CreateFileW (file_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
DeleteFileW (file_name);
return NULL;
}
fd = _open_osfhandle((intptr_t) handle, 0);
if (fd < 0) {
CloseHandle (handle);
return NULL;
}
fp = fdopen(fd, "w+b");
if (fp == NULL) {
_close(fd);
return NULL;
}
return fp;
}
#endif
static void useLabel(size_t value) {
while (value >= vUsedLabelAlloc) {
vUsedLabels = realloc(vUsedLabels, vUsedLabelAlloc * 2);
@ -844,7 +899,11 @@ void DFA_emit(DFA *d, FILE *o){
nOrgOline = oline;
maxFillIndexes = vFillIndexes;
orgVFillIndexes = vFillIndexes;
#ifdef _WIN32
tmpo = win32_tmpfile();
#else
tmpo = tmpfile();
#endif
for(s = d->head; s; s = s->next){
int readCh = 0;
State_emit(s, tmpo, &readCh);