/* * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /** * POSIX.2008 fake implementation for pre-POSIX.2008 systems. (OSX, BSD, MINGW, CYGWIN, older Linux &c.) */ #include #include #include #include #if !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L || defined(EMSCRIPTEN)) typedef struct memstream { off_t pos; off_t size; char * buffer; char ** bufp; size_t * sizep; bool realloc; } memstream_t; static int memstream_read (void * cookie, char * buf, int size) { memstream_t * mem = (memstream_t *) cookie; off_t available = mem->size - mem->pos; if (available < 0) available = 0; if (size > available) size = available; memcpy(buf, mem->buffer + mem->pos, size); mem->pos += size; return size; } static int memstream_write (void * cookie, const char * buf, int size) { memstream_t * mem = (memstream_t *) cookie; off_t available = mem->size - mem->pos; if (size > available) { if (mem->realloc) { mem->buffer = (char *) realloc(mem->buffer, mem->pos + size + 1); memset(mem->buffer + mem->size, 0, mem->pos + size + 1 - mem->size); mem->size = mem->pos + size; if (mem->bufp) *(mem->bufp) = mem->buffer; if (mem->sizep) *(mem->sizep) = mem->size; } else { size = available; } } memcpy(mem->buffer + mem->pos, buf, sizeof(char) * size); mem->pos += size; return size; } static fpos_t memstream_seek (void * cookie, fpos_t offset, int whence) { memstream_t * mem = (memstream_t *) cookie; switch (whence) { case SEEK_SET: if (offset < 0) goto error_inval; mem->pos = offset; return 0; case SEEK_CUR: if (mem->pos + offset < 0) goto error_inval; mem->pos += offset; return 0; case SEEK_END: if (mem->size + offset < 0) goto error_inval; mem->pos = mem->size + offset; break; default: goto error_inval; } return mem->pos; error_inval: errno = EINVAL; return -1; } static int memstream_close (void * cookie) { memstream_t * mem = (memstream_t *) cookie; if (mem->bufp) *(mem->bufp) = mem->buffer; if (mem->sizep) *(mem->sizep) = mem->size; free(cookie); return 0; } FILE * compat_fmemopen (void * buf, size_t size, const char * mode) { memstream_t * mem = (memstream_t *) malloc(sizeof(memstream_t)); memset(mem, 0, sizeof(memstream_t)); mem->size = size; mem->buffer = (char *) buf; (void) mode; return funopen(mem, memstream_read, memstream_write, memstream_seek, memstream_close); } FILE * compat_open_memstream (char ** bufp, size_t * sizep) { memstream_t * mem = (memstream_t *) malloc(sizeof(memstream_t)); memset(mem, 0, sizeof(memstream_t)); mem->bufp = bufp; mem->sizep = sizep; mem->realloc = true; return funopen(mem, memstream_read, memstream_write, memstream_seek, memstream_close); } #endif /* !(_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L) */