Eliminate the `rlimits.h' header using scary macros.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 29 Jun 2013 13:56:57 +0000 (14:56 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 29 Jun 2013 13:56:57 +0000 (14:56 +0100)
The `rlimits.h' header is a bit of a hack, which was thought necessary
because if must assemble a list of things conditionally.  This patch
eliminates this unpleasantness by replacing it with a different hack
which is at least as nasty.

Associate with each potential limit name a macro whose value is either
`t' or `nil', indicating whether the limit is known.  This can be done
using lots of `#ifdef ... #else ... #endif' blocks.  Finally, assemble
a list macro of all of the names, whether they're known or not (because
we can't tell at this point).  The trick is that, instead of just calling
`_(...)' for each item, we call `MAYBE_CALL(_, HAVE_???_P, (...))', and
the latter uses token-pasting to dispatch on the `HAVE_???_P' flag and
conditionally invoke `_(...)'.  Thus callers can work with this as a
conventional list macro.

Of course, building all of this is monumentally tedious, so we get Emacs
to do it for us.

Makefile.am
exec.c
fwd.h
rlimits.h [deleted file]

index 44fba7a..dfc03ad 100644 (file)
@@ -90,7 +90,6 @@ fwd_SOURCES           += file.c
 
 ## Executables.
 fwd_SOURCES            += exec.c
-fwd_SOURCES            += rlimits.h
 
 ## Documentation.
 fwd_SOURCES            += mantext.c
diff --git a/exec.c b/exec.c
index 9b7e87b..92c0b26 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -33,8 +33,9 @@
 #ifdef HAVE_SETRLIMIT
 
 typedef struct xlimit {
-#define R(r, n) struct rlimit n;
-#include "rlimits.h"
+#define XLIMIT_ENTRY(name, constant) struct rlimit name;
+  RLIMITS(XLIMIT_ENTRY)
+#undef XLIMIT_ENTRY
 } xlimit;
 
 #endif
@@ -138,8 +139,10 @@ typedef struct rlimit_ent {
 } rlimit_ent;
 
 static rlimit_ent rlimits[] = {
-#define R(r, n) { #n, #r, r, offsetof(xlimit, n) },
-#include "rlimits.h"
+#define TABLE_ENTRY(name, constant)                                    \
+  { #name, #constant, constant, offsetof(xlimit, name) },
+  RLIMITS(TABLE_ENTRY)
+#undef TABLE_ENTRY
   { 0, 0, 0, 0 }
 };
 
diff --git a/fwd.h b/fwd.h
index 2d139e4..5868fda 100644 (file)
--- a/fwd.h
+++ b/fwd.h
   extern char **environ;
 #endif
 
+/*----- Resource limit names ----------------------------------------------*/
+
+#if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
+#  define RLIMIT_NOFILE RLIMIT_OFILE
+#endif
+
+/*
+   ;;; The resource-limit name table is very boring to type and less fun to
+   ;;; maintain.  To make life less awful, put the names in this list and
+   ;;; evaluate the code to get Emacs to regenerate it.
+
+   (let ((limits '(as core cpu data fsize locks memlock msgqueue
+                  nice nofile nproc rss rtprio sigpending stack
+                  vmem)))
+     (save-excursion
+       (goto-char
+       (point-min))
+       (search-forward (concat "***" "BEGIN rlimitlist" "***"))
+       (beginning-of-line 2)
+       (delete-region (point)
+                     (progn
+                       (search-forward "***END***")
+                       (beginning-of-line)
+                       (point)))
+       (let ((avail (make-marker))
+            (list (make-marker)))
+        (set-marker avail (point))
+        (insert "#define RLIMITS(_)")
+        (set-marker list (point))
+        (dolist (limit (sort (copy-list limits) #'string<))
+          (let* ((name (symbol-name limit))
+                 (constant (concat "RLIMIT_" (upcase name)))
+                 (have (concat "HAVE_" constant "_P")))
+            (goto-char avail)
+            (insert-before-markers (format (concat "#ifdef %s\n"
+                                                   "#  define %s t\n"
+                                                   "#else\n"
+                                                   "#  define %s nil\n"
+                                                   "#endif\n")
+                                           constant have have))
+            (goto-char list)
+            (insert-before-markers
+             (format " \\\n  MAYBE_ITEM(_, %s, (%s, %s))"
+                     have name constant))))
+        (goto-char list)
+        (insert "\n"))))
+*/
+
+/***BEGIN rlimitlist***/
+#ifdef RLIMIT_AS
+#  define HAVE_RLIMIT_AS_P t
+#else
+#  define HAVE_RLIMIT_AS_P nil
+#endif
+#ifdef RLIMIT_CORE
+#  define HAVE_RLIMIT_CORE_P t
+#else
+#  define HAVE_RLIMIT_CORE_P nil
+#endif
+#ifdef RLIMIT_CPU
+#  define HAVE_RLIMIT_CPU_P t
+#else
+#  define HAVE_RLIMIT_CPU_P nil
+#endif
+#ifdef RLIMIT_DATA
+#  define HAVE_RLIMIT_DATA_P t
+#else
+#  define HAVE_RLIMIT_DATA_P nil
+#endif
+#ifdef RLIMIT_FSIZE
+#  define HAVE_RLIMIT_FSIZE_P t
+#else
+#  define HAVE_RLIMIT_FSIZE_P nil
+#endif
+#ifdef RLIMIT_LOCKS
+#  define HAVE_RLIMIT_LOCKS_P t
+#else
+#  define HAVE_RLIMIT_LOCKS_P nil
+#endif
+#ifdef RLIMIT_MEMLOCK
+#  define HAVE_RLIMIT_MEMLOCK_P t
+#else
+#  define HAVE_RLIMIT_MEMLOCK_P nil
+#endif
+#ifdef RLIMIT_MSGQUEUE
+#  define HAVE_RLIMIT_MSGQUEUE_P t
+#else
+#  define HAVE_RLIMIT_MSGQUEUE_P nil
+#endif
+#ifdef RLIMIT_NICE
+#  define HAVE_RLIMIT_NICE_P t
+#else
+#  define HAVE_RLIMIT_NICE_P nil
+#endif
+#ifdef RLIMIT_NOFILE
+#  define HAVE_RLIMIT_NOFILE_P t
+#else
+#  define HAVE_RLIMIT_NOFILE_P nil
+#endif
+#ifdef RLIMIT_NPROC
+#  define HAVE_RLIMIT_NPROC_P t
+#else
+#  define HAVE_RLIMIT_NPROC_P nil
+#endif
+#ifdef RLIMIT_RSS
+#  define HAVE_RLIMIT_RSS_P t
+#else
+#  define HAVE_RLIMIT_RSS_P nil
+#endif
+#ifdef RLIMIT_RTPRIO
+#  define HAVE_RLIMIT_RTPRIO_P t
+#else
+#  define HAVE_RLIMIT_RTPRIO_P nil
+#endif
+#ifdef RLIMIT_SIGPENDING
+#  define HAVE_RLIMIT_SIGPENDING_P t
+#else
+#  define HAVE_RLIMIT_SIGPENDING_P nil
+#endif
+#ifdef RLIMIT_STACK
+#  define HAVE_RLIMIT_STACK_P t
+#else
+#  define HAVE_RLIMIT_STACK_P nil
+#endif
+#ifdef RLIMIT_VMEM
+#  define HAVE_RLIMIT_VMEM_P t
+#else
+#  define HAVE_RLIMIT_VMEM_P nil
+#endif
+#define RLIMITS(_) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_AS_P, (as, RLIMIT_AS)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_CORE_P, (core, RLIMIT_CORE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_CPU_P, (cpu, RLIMIT_CPU)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_DATA_P, (data, RLIMIT_DATA)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_FSIZE_P, (fsize, RLIMIT_FSIZE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_LOCKS_P, (locks, RLIMIT_LOCKS)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_MEMLOCK_P, (memlock, RLIMIT_MEMLOCK)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_MSGQUEUE_P, (msgqueue, RLIMIT_MSGQUEUE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_NICE_P, (nice, RLIMIT_NICE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_NOFILE_P, (nofile, RLIMIT_NOFILE)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_NPROC_P, (nproc, RLIMIT_NPROC)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_RSS_P, (rss, RLIMIT_RSS)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_RTPRIO_P, (rtprio, RLIMIT_RTPRIO)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_SIGPENDING_P, (sigpending, RLIMIT_SIGPENDING)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_STACK_P, (stack, RLIMIT_STACK)) \
+  MAYBE_ITEM(_, HAVE_RLIMIT_VMEM_P, (vmem, RLIMIT_VMEM))
+/***END***/
+
+/* --- The unpleasant conditional-output machinery --- */
+
+#define MAYBE_ITEM(_, emitp, args) GLUE(MAYBE_ITEM_, emitp)(_, args)
+#define MAYBE_ITEM_t(_, args) _ args
+#define MAYBE_ITEM_nil(_, args)
+
 /*----- Main program ------------------------------------------------------*/
 
 /* --- The global select state --- */
diff --git a/rlimits.h b/rlimits.h
deleted file mode 100644 (file)
index f3f2769..0000000
--- a/rlimits.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*-c-*-
- *
- * List of resource limits known to mankind
- *
- * (c) 1999 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of the `fwd' port forwarder.
- *
- * `fwd' 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 2 of the License, or
- * (at your option) any later version.
- *
- * `fwd' 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 `fwd'; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*----- Magic -------------------------------------------------------------*/
-
-#ifndef R
-#  error "Don't try including rlimits.h unless you know what you're doing"
-#endif
-
-#if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
-#  define RLIMIT_NOFILE RLIMIT_OFILE
-#endif
-
-#ifdef RLIMIT_AS
-  R(RLIMIT_AS, as)
-#endif
-#ifdef RLIMIT_CORE
-  R(RLIMIT_CORE, core)
-#endif
-#ifdef RLIMIT_CPU
-  R(RLIMIT_CPU, cpu)
-#endif
-#ifdef RLIMIT_DATA
-  R(RLIMIT_DATA, data)
-#endif
-#ifdef RLIMIT_FSIZE
-  R(RLIMIT_FSIZE, fsize)
-#endif
-#ifdef RLIMIT_LOCKS
-  R(RLIMIT_LOCKS, locks)
-#endif
-#ifdef RLIMIT_MEMLOCK
-  R(RLIMIT_MEMLOCK, memlock)
-#endif
-#ifdef RLIMIT_MSGQUEUE
-  R(RLIMIT_MSGQUEUE, msgqueue)
-#endif
-#ifdef RLIMIT_NICE
-  R(RLIMIT_NICE, nice)
-#endif
-#ifdef RLIMIT_NOFILE
-  R(RLIMIT_NOFILE, nofile)
-#endif
-#ifdef RLIMIT_NPROC
-  R(RLIMIT_NPROC, nproc)
-#endif
-#ifdef RLIMIT_RSS
-  R(RLIMIT_RSS, rss)
-#endif
-#ifdef RLIMIT_RTPRIO
-  R(RLIMIT_RTPRIO, rtprio)
-#endif
-#ifdef RLIMIT_SIGPENDING
-  R(RLIMIT_SIGPENDING, sigpending)
-#endif
-#ifdef RLIMIT_STACK
-  R(RLIMIT_STACK, stack)
-#endif
-#ifdef RLIMIT_VMEM
-  R(RLIMIT_VMEM, vmem)
-#endif
-
-#undef R
-
-/*----- That's all, folks -------------------------------------------------*/