diff interps/cfunge/cfunge-src/src/support.c @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interps/cfunge/cfunge-src/src/support.c	Sun Dec 09 19:30:08 2012 +0000
@@ -0,0 +1,118 @@
+/* -*- mode: C; coding: utf-8; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
+ *
+ * cfunge - A standard-conforming Befunge93/98/109 interpreter in C.
+ * Copyright (C) 2008-2009 Arvid Norlander <anmaster AT tele2 DOT se>
+ *
+ * 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 the proxy's option) any later version. Arvid Norlander is a
+ * proxy who can decide which future versions of the GNU General Public
+ * License can be used.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "global.h"
+#include "support.h"
+
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+#ifndef SSIZE_MAX
+# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
+#endif
+
+// This function is from Gnulib
+FUNGE_ATTR_FAST FUNGE_ATTR_WARN_UNUSED
+static inline ssize_t
+cf_getdelim(char **lineptr, size_t *n, int delimiter, FILE *fp)
+{
+	ssize_t result;
+	size_t cur_len = 0;
+
+	if (lineptr == NULL || n == NULL || fp == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	cf_flockfile(fp);
+
+	if (*lineptr == NULL || *n == 0) {
+		*n = 120;
+		*lineptr = (char *) cf_realloc(*lineptr, *n);
+		if (*lineptr == NULL) {
+			result = -1;
+			goto unlock_return;
+		}
+	}
+
+	for (;;) {
+		int i;
+
+		i = cf_getc_unlocked(fp);
+		if (i == EOF) {
+			result = -1;
+			break;
+		}
+
+		/* Make enough space for len+1 (for final NUL) bytes.  */
+		if (cur_len + 1 >= *n) {
+			size_t needed_max =
+			    SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+			size_t needed = 2 * *n + 1;   /* Be generous. */
+			char *new_lineptr;
+
+			if (needed_max < needed)
+				needed = needed_max;
+			if (cur_len + 1 >= needed) {
+				result = -1;
+// This ifdef is for Windows only really. Most OS defines EOVERFLOW.
+#ifdef EOVERFLOW
+				errno = EOVERFLOW;
+#endif
+				goto unlock_return;
+			}
+
+			new_lineptr = (char *) cf_realloc(*lineptr, needed);
+			if (new_lineptr == NULL) {
+				result = -1;
+				goto unlock_return;
+			}
+
+			*lineptr = new_lineptr;
+			*n = needed;
+		}
+
+		(*lineptr)[cur_len] = (char)i;
+		cur_len++;
+
+		if (i == delimiter)
+			break;
+	}
+	(*lineptr)[cur_len] = '\0';
+	result = cur_len ? (ssize_t)cur_len : result;
+
+unlock_return:
+	cf_funlockfile(fp);  // doesn't set errno
+
+	return result;
+}
+
+// This function is from Gnulib
+FUNGE_ATTR_FAST ssize_t
+cf_getline(char **lineptr, size_t *n, FILE *stream)
+{
+	return cf_getdelim(lineptr, n, '\n', stream);
+}