summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/tools/mkdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/tools/mkdep.c')
-rw-r--r--ldap/servers/slapd/tools/mkdep.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/ldap/servers/slapd/tools/mkdep.c b/ldap/servers/slapd/tools/mkdep.c
new file mode 100644
index 00000000..469194fe
--- /dev/null
+++ b/ldap/servers/slapd/tools/mkdep.c
@@ -0,0 +1,335 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * Originally by Linus Torvalds.
+ * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
+ * Lobotomized by Robey Pointer.
+ *
+ * Usage: mkdep file ...
+ *
+ * Read source files and output makefile dependency lines for them.
+ * I make simple dependency lines for #include "*.h".
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WINNT
+#include <windows.h>
+#include <winbase.h>
+#include <io.h>
+#else
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif
+
+
+char __depname[512] = "\n\t@touch ";
+#define depname (__depname+9)
+int hasdep;
+
+char *outdir = ".";
+
+struct path_struct {
+ int len;
+ char buffer[256-sizeof(int)];
+} path = { 0, "" };
+
+
+#ifdef WINNT
+#define EXISTS(_fn) _access(_fn, 00)
+#else
+#define EXISTS(_fn) access(_fn, F_OK)
+#endif
+
+/*
+ * Handle an #include line.
+ */
+void handle_include(const char * name, int len)
+{
+ memcpy(path.buffer+path.len, name, len);
+ path.buffer[path.len+len] = '\0';
+ if (EXISTS(path.buffer))
+ return;
+
+ if (!hasdep) {
+ hasdep = 1;
+ /* don't use outdir if it's a .h file */
+ if ((strlen(depname) > 2) &&
+ (strcmp(depname + strlen(depname) - 2, ".h") == 0)) {
+ /* skip using the outdir */
+ } else {
+ if (outdir)
+ printf("%s/", outdir);
+ }
+ printf("%s:", depname);
+ }
+ printf(" \\\n %s", path.buffer);
+}
+
+
+/* --- removed weird functions to try to emulate asm ---
+ * (turns out it's faster just to scan thru a char*)
+ */
+
+#define GETNEXT { current = *next++; if (next >= end) break; }
+
+/*
+ * State machine macros.
+ */
+#define CASE(c,label) if (current == c) goto label
+#define NOTCASE(c,label) if (current != c) goto label
+
+/*
+ * Yet another state machine speedup.
+ */
+#define MAX2(a,b) ((a)>(b)?(a):(b))
+#define MIN2(a,b) ((a)<(b)?(a):(b))
+#define MAX4(a,b,c,d) (MAX2(a,MAX2(b,MAX2(c,d))))
+#define MIN4(a,b,c,d) (MIN2(a,MIN2(b,MIN2(c,d))))
+
+
+
+/*
+ * The state machine looks for (approximately) these Perl regular expressions:
+ *
+ * m|\/\*.*?\*\/|
+ * m|'.*?'|
+ * m|".*?"|
+ * m|#\s*include\s*"(.*?)"|
+ *
+ * About 98% of the CPU time is spent here, and most of that is in
+ * the 'start' paragraph. Because the current characters are
+ * in a register, the start loop usually eats 4 or 8 characters
+ * per memory read. The MAX6 and MIN6 tests dispose of most
+ * input characters with 1 or 2 comparisons.
+ */
+void state_machine(const char * map, const char * end)
+{
+ register const char * next = map;
+ register const char * map_dot;
+ register unsigned char current;
+
+ for (;;) {
+start:
+ GETNEXT
+__start:
+ if (current > MAX4('/','\'','"','#')) goto start;
+ if (current < MIN4('/','\'','"','#')) goto start;
+ CASE('/', slash);
+ CASE('\'', squote);
+ CASE('"', dquote);
+ CASE('#', pound);
+ goto start;
+
+/* / */
+slash:
+ GETNEXT
+ NOTCASE('*', __start);
+slash_star_dot_star:
+ GETNEXT
+__slash_star_dot_star:
+ NOTCASE('*', slash_star_dot_star);
+ GETNEXT
+ NOTCASE('/', __slash_star_dot_star);
+ goto start;
+
+/* '.*?' */
+squote:
+ GETNEXT
+ CASE('\'', start);
+ NOTCASE('\\', squote);
+ GETNEXT
+ goto squote;
+
+/* ".*?" */
+dquote:
+ GETNEXT
+ CASE('"', start);
+ NOTCASE('\\', dquote);
+ GETNEXT
+ goto dquote;
+
+/* #\s* */
+pound:
+ GETNEXT
+ CASE(' ', pound);
+ CASE('\t', pound);
+ CASE('i', pound_i);
+ goto __start;
+
+/* #\s*i */
+pound_i:
+ GETNEXT NOTCASE('n', __start);
+ GETNEXT NOTCASE('c', __start);
+ GETNEXT NOTCASE('l', __start);
+ GETNEXT NOTCASE('u', __start);
+ GETNEXT NOTCASE('d', __start);
+ GETNEXT NOTCASE('e', __start);
+ goto pound_include;
+
+/* #\s*include\s* */
+pound_include:
+ GETNEXT
+ CASE(' ', pound_include);
+ CASE('\t', pound_include);
+ map_dot = next;
+ CASE('"', pound_include_dquote);
+ goto __start;
+
+/* #\s*include\s*"(.*)" */
+pound_include_dquote:
+ GETNEXT
+ CASE('\n', start);
+ NOTCASE('"', pound_include_dquote);
+ handle_include(map_dot, next - map_dot - 1);
+ goto start;
+
+ }
+}
+
+
+#ifdef WINNT
+
+/*
+ * Alternate implementation of do_depend() for NT
+ * (NT has its own wacky versions of open/mmap/close)
+ */
+void do_depend(const char *filename, const char *command)
+{
+ HANDLE fd, mapfd;
+ BY_HANDLE_FILE_INFORMATION st;
+ char *map;
+
+ fd = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
+ if (fd == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "NT error opening '%s'\n", filename);
+ return;
+ }
+ if (! GetFileInformationByHandle(fd, &st)) {
+ fprintf(stderr, "NT error getting stat on '%s'\n", filename);
+ CloseHandle(fd);
+ return;
+ }
+ if (st.nFileSizeLow == 0) {
+ fprintf(stderr, "%s is empty\n", filename);
+ CloseHandle(fd);
+ return;
+ }
+
+ mapfd = CreateFileMapping(fd, NULL, PAGE_READONLY, st.nFileSizeHigh,
+ st.nFileSizeLow, NULL);
+ if (mapfd == NULL) {
+ fprintf(stderr, "NT error creating file mapping of '%s'\n",
+ filename);
+ CloseHandle(fd);
+ return;
+ }
+ map = MapViewOfFile(mapfd, FILE_MAP_READ, 0, 0, 0);
+ if (map == NULL) {
+ fprintf(stderr, "NT error creating mapped view of '%s'\n",
+ filename);
+ CloseHandle(mapfd);
+ CloseHandle(fd);
+ return;
+ }
+
+ hasdep = 0;
+ state_machine(map, map+st.nFileSizeLow);
+ if (hasdep)
+ puts(command);
+
+ UnmapViewOfFile(map);
+ CloseHandle(mapfd);
+ CloseHandle(fd);
+}
+
+#else
+
+/*
+ * Generate dependencies for one file.
+ */
+void do_depend(const char * filename, const char * command)
+{
+ int mapsize;
+ int pagesizem1 = getpagesize()-1;
+ int fd;
+ struct stat st;
+ char * map;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ return;
+ }
+
+ fstat(fd, &st);
+ if (st.st_size == 0) {
+ fprintf(stderr,"%s is empty\n",filename);
+ close(fd);
+ return;
+ }
+
+ mapsize = st.st_size;
+ mapsize = (mapsize+pagesizem1) & ~pagesizem1;
+ map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ((long) map == -1) {
+ perror("mkdep: mmap");
+ close(fd);
+ return;
+ }
+ if ((unsigned long) map % sizeof(unsigned long) != 0)
+ {
+ fprintf(stderr, "do_depend: map not aligned\n");
+ exit(1);
+ }
+
+ hasdep = 0;
+ state_machine(map, map+st.st_size);
+ if (hasdep)
+ puts(command);
+
+ munmap(map, mapsize);
+ close(fd);
+}
+
+#endif
+
+
+/*
+ * Generate dependencies for all files.
+ */
+int main(int argc, char **argv)
+{
+ int len;
+
+ while (--argc > 0) {
+ const char *filename = *++argv;
+ const char *command = __depname;
+
+ if (strcmp(filename, "-o") == 0) {
+ outdir = *++argv;
+ argc--;
+ continue;
+ }
+ len = strlen(filename);
+ memcpy(depname, filename, len+1);
+ if (len > 2 && filename[len-2] == '.') {
+ if (filename[len-1] == 'c' || filename[len-1] == 'S') {
+ depname[len-1] = 'o';
+ command = "";
+ }
+ }
+ do_depend(filename, command);
+ }
+ return 0;
+}