*.swp
*.a
*.lib
+retrorend
*.exe
src = $(wildcard src/*.c) $(wildcard src/modern/*.c) $(gawsrc_$(build_gfx))
obj = $(src:.c=.o)
dep = $(src:.c=.d)
-bin = game
+bin = retrorend
warn = -pedantic -Wall
dbg = -g
ldsys = -lopengl32 -lglu32 -lgdi32 -lwinmm
ldsys_pre = -static-libgcc -lmingw32 -mconsole
else
- ldsys = -lGL -lGLU -lX11
+ ldsys = -lGL -lGLU -lX11 -lm
endif
$(bin): $(obj) libs
#include "app.h"
#include "options.h"
#include "font.h"
+#include "util.h"
static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls);
struct app_screen *cur_scr;
-struct font *font;
+struct font *uifont;
/* available screens */
#define MAX_SCREENS 8
dtx_target_user(txdraw, 0);
- font = malloc_nf(sizeof *font);
+ uifont = malloc_nf(sizeof *uifont);
if(load_font(uifont, "data/uifont.gmp") == -1) {
free(uifont);
return -1;
}
}
if(!cur_scr) {
- app_chscr(&scr_logo);
+ app_chscr(&scr_model);
}
return 0;
putchar('\n');
- save_options(GAME_CFG_FILE);
+ save_options("retroray.cfg");
for(i=0; i<num_screens; i++) {
if(screens[i]->destroy) {
void app_display(void)
{
- static long nframes, interv, prev_msec;
-
time_msec = app_getmsec();
cur_scr->display();
case '\n':
case '\r':
- if(modkeys & GKEY_MOD_ALT) {
- case GKEY_F11:
+ if(modkeys & KEY_MOD_ALT) {
+ case KEY_F11:
app_fullscreen(-1);
return;
}
static void txdraw(struct dtx_vertex *v, int vcount, struct dtx_pixmap *pixmap, void *cls)
{
+ /*
int i, aref, npix;
unsigned char *src, *dest;
struct texture *tex = pixmap->udata;
gaw_restore();
gaw_set_tex2d(0);
+ */
}
#include <string.h>
#include "util.h"
#include "gaw.h"
-#include "opengl.h"
+
+#if defined(WIN32) || defined(__WIN32)
+#include <windows.h>
+#endif
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
static const float *vertex_ptr, *normal_ptr, *texcoord_ptr, *color_ptr;
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
#include <stdio.h>
#include <stdlib.h>
+#include <assert.h>
#include "miniglut.h"
#include "app.h"
+
+static void reshape(int x, int y);
+static void keydown(unsigned char key, int x, int y);
+static void keyup(unsigned char key, int x, int y);
+static void skeydown(int key, int x, int y);
+static void skeyup(int key, int x, int y);
+static void mouse(int bn, int st, int x, int y);
+static void motion(int x, int y);
+static int translate_skey(int key);
+
+#if defined(__unix__) || defined(unix)
+#include <GL/glx.h>
+static Display *xdpy;
+static Window xwin;
+
+static void (*glx_swap_interval_ext)();
+static void (*glx_swap_interval_sgi)();
+#endif
+#ifdef _WIN32
+#include <windows.h>
+static PROC wgl_swap_interval_ext;
+#endif
+
+
+
+int main(int argc, char **argv)
+{
+ glutInit(&argc, argv);
+ glutInitWindowSize(1024, 768);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
+ glutCreateWindow("RetroRay");
+
+ glutDisplayFunc(app_display);
+ glutReshapeFunc(reshape);
+ glutKeyboardFunc(keydown);
+ glutKeyboardUpFunc(keyup);
+ glutSpecialFunc(skeydown);
+ glutSpecialUpFunc(skeyup);
+ glutMouseFunc(mouse);
+ glutMotionFunc(motion);
+ glutPassiveMotionFunc(motion);
+ glutSpaceballMotionFunc(app_sball_motion);
+ glutSpaceballRotateFunc(app_sball_rotate);
+ glutSpaceballButtonFunc(app_sball_button);
+
+#if defined(__unix__) || defined(unix)
+ xdpy = glXGetCurrentDisplay();
+ xwin = glXGetCurrentDrawable();
+
+ if(!(glx_swap_interval_ext = glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"))) {
+ glx_swap_interval_sgi = glXGetProcAddress((unsigned char*)"glXSwapIntervalSGI");
+ }
+#endif
+#ifdef _WIN32
+ wgl_swap_interval_ext = wglGetProcAddress("wglSwapIntervalEXT");
+#endif
+
+ app_reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
+
+ if(app_init() == -1) {
+ return 1;
+ }
+ atexit(app_shutdown);
+ glutMainLoop();
+ return 0;
+}
+
+long app_getmsec(void)
+{
+ return glutGet(GLUT_ELAPSED_TIME);
+}
+
+void app_redisplay(void)
+{
+ glutPostRedisplay();
+}
+
+void app_swap_buffers(void)
+{
+ glutSwapBuffers();
+ assert(glGetError() == GL_NO_ERROR);
+}
+
+void app_quit(void)
+{
+ exit(0);
+}
+
+void app_resize(int x, int y)
+{
+ if(x == win_width && y == win_height) return;
+
+ glutReshapeWindow(x, y);
+}
+
+void app_fullscreen(int fs)
+{
+ static int prev_w, prev_h;
+
+ if(fs == -1) {
+ fs = !fullscr;
+ }
+
+ if(fs == fullscr) return;
+
+ if(fs) {
+ prev_w = glutGet(GLUT_WINDOW_WIDTH);
+ prev_h = glutGet(GLUT_WINDOW_HEIGHT);
+ glutFullScreen();
+ } else {
+ glutReshapeWindow(prev_w, prev_h);
+ }
+ fullscr = fs;
+}
+
+#if defined(__unix__) || defined(unix)
+void app_vsync(int vsync)
+{
+ vsync = vsync ? 1 : 0;
+ if(glx_swap_interval_ext) {
+ glx_swap_interval_ext(xdpy, xwin, vsync);
+ } else if(glx_swap_interval_sgi) {
+ glx_swap_interval_sgi(vsync);
+ }
+}
+#endif
+#ifdef WIN32
+void app_vsync(int vsync)
+{
+ if(wgl_swap_interval_ext) {
+ wgl_swap_interval_ext(vsync ? 1 : 0);
+ }
+}
+#endif
+
+
+
+static void reshape(int x, int y)
+{
+ app_reshape(x, y);
+}
+
+static void keydown(unsigned char key, int x, int y)
+{
+ modkeys = glutGetModifiers();
+ app_keyboard(key, 1);
+}
+
+static void keyup(unsigned char key, int x, int y)
+{
+ app_keyboard(key, 0);
+}
+
+static void skeydown(int key, int x, int y)
+{
+ int k;
+ modkeys = glutGetModifiers();
+ if((k = translate_skey(key)) >= 0) {
+ app_keyboard(k, 1);
+ }
+}
+
+static void skeyup(int key, int x, int y)
+{
+ int k = translate_skey(key);
+ if(k >= 0) {
+ app_keyboard(k, 0);
+ }
+}
+
+static void mouse(int bn, int st, int x, int y)
+{
+ modkeys = glutGetModifiers();
+ app_mouse(bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y);
+}
+
+static void motion(int x, int y)
+{
+ app_motion(x, y);
+}
+
+static int translate_skey(int key)
+{
+ switch(key) {
+ case GLUT_KEY_LEFT:
+ return KEY_LEFT;
+ case GLUT_KEY_UP:
+ return KEY_UP;
+ case GLUT_KEY_RIGHT:
+ return KEY_RIGHT;
+ case GLUT_KEY_DOWN:
+ return KEY_DOWN;
+ case GLUT_KEY_PAGE_UP:
+ return KEY_PGUP;
+ case GLUT_KEY_PAGE_DOWN:
+ return KEY_PGDOWN;
+ case GLUT_KEY_HOME:
+ return KEY_HOME;
+ case GLUT_KEY_END:
+ return KEY_END;
+ case GLUT_KEY_INSERT:
+ return KEY_INS;
+ default:
+ if(key >= GLUT_KEY_F1 && key <= GLUT_KEY_F12) {
+ return key - GLUT_KEY_F1 + KEY_F1;
+ }
+ }
+
+ return -1;
+}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "options.h"
+#include "treestor.h"
+
+#define DEF_XRES 640
+#define DEF_YRES 480
+#define DEF_VSYNC 1
+#define DEF_FULLSCR 1
+#define DEF_MOUSE_SPEED 50
+#define DEF_SBALL_SPEED 50
+
+
+struct options opt = {
+ DEF_XRES, DEF_YRES,
+ DEF_VSYNC,
+ DEF_FULLSCR,
+ DEF_MOUSE_SPEED, DEF_SBALL_SPEED,
+};
+
+int load_options(const char *fname)
+{
+ struct ts_node *cfg;
+
+ if(!(cfg = ts_load(fname))) {
+ return -1;
+ }
+ printf("loaded config: %s\n", fname);
+
+ opt.xres = ts_lookup_int(cfg, "options.video.xres", DEF_XRES);
+ opt.yres = ts_lookup_int(cfg, "options.video.yres", DEF_YRES);
+ opt.vsync = ts_lookup_int(cfg, "options.video.vsync", DEF_VSYNC);
+ opt.fullscreen = ts_lookup_int(cfg, "options.video.fullscreen", DEF_FULLSCR);
+
+ opt.mouse_speed = ts_lookup_int(cfg, "options.input.mousespeed", DEF_MOUSE_SPEED);
+ opt.sball_speed = ts_lookup_int(cfg, "options.input.sballspeed", DEF_SBALL_SPEED);
+
+ ts_free_tree(cfg);
+ return 0;
+}
+
+#define WROPT(lvl, fmt, val, defval) \
+ do { \
+ int i; \
+ for(i=0; i<lvl; i++) fputc('\t', fp); \
+ if((val) == (defval)) fputc('#', fp); \
+ fprintf(fp, fmt "\n", val); \
+ } while(0)
+
+int save_options(const char *fname)
+{
+ FILE *fp;
+
+ printf("writing config: %s\n", fname);
+
+ if(!(fp = fopen(fname, "wb"))) {
+ fprintf(stderr, "failed to save options (%s): %s\n", fname, strerror(errno));
+ }
+ fprintf(fp, "options {\n");
+ fprintf(fp, "\tvideo {\n");
+ WROPT(2, "xres = %d", opt.xres, DEF_XRES);
+ WROPT(2, "yres = %d", opt.yres, DEF_YRES);
+ WROPT(2, "vsync = %d", opt.vsync, DEF_VSYNC);
+ WROPT(2, "fullscreen = %d", opt.fullscreen, DEF_FULLSCR);
+ fprintf(fp, "\t}\n");
+
+ fprintf(fp, "\tinput {\n");
+ WROPT(2, "mousespeed = %d", opt.mouse_speed, DEF_MOUSE_SPEED);
+ WROPT(2, "sballspeed = %d", opt.sball_speed, DEF_SBALL_SPEED);
+ fprintf(fp, "\t}\n");
+
+ fprintf(fp, "}\n");
+ fprintf(fp, "# v" "i:ts=4 sts=4 sw=4 noexpandtab:\n");
+
+ fclose(fp);
+ return 0;
+}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef OPTIONS_H_
+#define OPTIONS_H_
+
+struct options {
+ int xres, yres;
+ int vsync;
+ int fullscreen;
+
+ int mouse_speed, sball_speed;
+};
+
+extern struct options opt;
+
+int load_options(const char *fname);
+int save_options(const char *fname);
+
+#endif /* OPTIONS_H_ */
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+#include "gaw/gaw.h"
+#include "app.h"
+
+static int mdl_init(void);
+static void mdl_destroy(void);
+static int mdl_start(void);
+static void mdl_stop(void);
+static void mdl_display(void);
+static void mdl_reshape(int x, int y);
+static void mdl_keyb(int key, int press);
+static void mdl_mouse(int bn, int press, int x, int y);
+static void mdl_motion(int x, int y);
+
+
+struct app_screen scr_model = {
+ "modeller",
+ mdl_init, mdl_destroy,
+ mdl_start, mdl_stop,
+ mdl_display, mdl_reshape,
+ mdl_keyb, mdl_mouse, mdl_motion
+};
+
+
+static int mdl_init(void)
+{
+ return 0;
+}
+
+static void mdl_destroy(void)
+{
+}
+
+static int mdl_start(void)
+{
+ return 0;
+}
+
+static void mdl_stop(void)
+{
+}
+
+static void mdl_display(void)
+{
+}
+
+static void mdl_reshape(int x, int y)
+{
+ gaw_matrix_mode(GAW_PROJECTION);
+ gaw_load_identity();
+ gaw_perspective(50, win_aspect, 0.5, 100.0);
+}
+
+static void mdl_keyb(int key, int press)
+{
+}
+
+static void mdl_mouse(int bn, int press, int x, int y)
+{
+}
+
+static void mdl_motion(int x, int y)
+{
+}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+#include "gaw/gaw.h"
+#include "app.h"
+
+static int rend_init(void);
+static void rend_destroy(void);
+static int rend_start(void);
+static void rend_stop(void);
+static void rend_display(void);
+static void rend_reshape(int x, int y);
+static void rend_keyb(int key, int press);
+static void rend_mouse(int bn, int press, int x, int y);
+static void rend_motion(int x, int y);
+
+
+struct app_screen scr_rend = {
+ "renderer",
+ rend_init, rend_destroy,
+ rend_start, rend_stop,
+ rend_display, rend_reshape,
+ rend_keyb, rend_mouse, rend_motion
+};
+
+
+static int rend_init(void)
+{
+ return 0;
+}
+
+static void rend_destroy(void)
+{
+}
+
+static int rend_start(void)
+{
+ return 0;
+}
+
+static void rend_stop(void)
+{
+}
+
+static void rend_display(void)
+{
+}
+
+static void rend_reshape(int x, int y)
+{
+ gaw_matrix_mode(GAW_PROJECTION);
+ gaw_load_identity();
+ gaw_perspective(50, win_aspect, 0.5, 100.0);
+}
+
+static void rend_keyb(int key, int press)
+{
+}
+
+static void rend_mouse(int bn, int press, int x, int y)
+{
+}
+
+static void rend_motion(int x, int y)
+{
+}
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "util.h"
+
+void *malloc_nf_impl(size_t sz, const char *file, int line)
+{
+ void *p;
+ if(!(p = malloc(sz))) {
+ fprintf(stderr, "%s:%d failed to allocate %lu bytes\n", file, line, (unsigned long)sz);
+ abort();
+ }
+ return p;
+}
+
+void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line)
+{
+ void *p;
+ if(!(p = calloc(num, sz))) {
+ fprintf(stderr, "%s:%d failed to allocate %lu bytes\n", file, line, (unsigned long)(num * sz));
+ abort();
+ }
+ return p;
+}
+
+void *realloc_nf_impl(void *p, size_t sz, const char *file, int line)
+{
+ if(!(p = realloc(p, sz))) {
+ fprintf(stderr, "%s:%d failed to realloc %lu bytes\n", file, line, (unsigned long)sz);
+ abort();
+ }
+ return p;
+}
+
+char *strdup_nf_impl(const char *s, const char *file, int line)
+{
+ int len;
+ char *res;
+
+ len = strlen(s);
+ if(!(res = malloc(len + 1))) {
+ fprintf(stderr, "%s:%d failed to duplicate string\n", file, line);
+ abort();
+ }
+ memcpy(res, s, len + 1);
+ return res;
+}
+
+
+int match_prefix(const char *str, const char *prefix)
+{
+ while(*str && *prefix) {
+ if(*str++ != *prefix++) {
+ return 0;
+ }
+ }
+ return *prefix ? 0 : 1;
+}
+
+#if defined(__APPLE__) && !defined(TARGET_IPHONE)
+#include <xmmintrin.h>
+
+void enable_fpexcept(void)
+{
+ unsigned int bits;
+ bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW;
+ _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() & ~bits);
+}
+
+void disable_fpexcept(void)
+{
+ unsigned int bits;
+ bits = _MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW | _MM_MASK_UNDERFLOW;
+ _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | bits);
+}
+
+#elif defined(__GLIBC__) && !defined(__MINGW32__)
+#ifndef __USE_GNU
+#define __USE_GNU
+#endif
+#include <fenv.h>
+
+void enable_fpexcept(void)
+{
+ feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
+}
+
+void disable_fpexcept(void)
+{
+ fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
+}
+
+#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__)
+#include <float.h>
+
+#if defined(__MINGW32__) && !defined(_EM_OVERFLOW)
+/* if gcc's float.h gets precedence, the mingw MSVC includes won't be declared */
+#define _MCW_EM 0x8001f
+#define _EM_INVALID 0x10
+#define _EM_ZERODIVIDE 0x08
+#define _EM_OVERFLOW 0x04
+unsigned int __cdecl _clearfp(void);
+unsigned int __cdecl _controlfp(unsigned int, unsigned int);
+#elif defined(__WATCOMC__)
+#define _clearfp _clear87
+#define _controlfp _control87
+#endif
+
+void enable_fpexcept(void)
+{
+ _clearfp();
+ _controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM);
+}
+
+void disable_fpexcept(void)
+{
+ _clearfp();
+ _controlfp(_controlfp(0, 0) | (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM);
+}
+#else
+void enable_fpexcept(void) {}
+void disable_fpexcept(void) {}
+#endif
--- /dev/null
+/*
+RetroRay - integrated standalone vintage modeller/renderer
+Copyright (C) 2023 John Tsiombikas <nuclear@mutantstargoat.com>
+
+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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <stdlib.h>
+#include "byteord.h" /* from imago, to sort out the sized int types mess */
+
+#if defined(__WATCOMC__) || defined(_WIN32) || defined(__DJGPP__)
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+
+/* Non-failing versions of malloc/calloc/realloc. They never return 0, they call
+ * demo_abort on failure. Use the macros, don't call the *_impl functions.
+ */
+#define malloc_nf(sz) malloc_nf_impl(sz, __FILE__, __LINE__)
+void *malloc_nf_impl(size_t sz, const char *file, int line);
+#define calloc_nf(n, sz) calloc_nf_impl(n, sz, __FILE__, __LINE__)
+void *calloc_nf_impl(size_t num, size_t sz, const char *file, int line);
+#define realloc_nf(p, sz) realloc_nf_impl(p, sz, __FILE__, __LINE__)
+void *realloc_nf_impl(void *p, size_t sz, const char *file, int line);
+#define strdup_nf(s) strdup_nf_impl(s, __FILE__, __LINE__)
+char *strdup_nf_impl(const char *s, const char *file, int line);
+
+int match_prefix(const char *str, const char *prefix);
+
+void enable_fpexcept(void);
+void disable_fpexcept(void);
+
+#endif /* UTIL_H_ */