[cairo] [PATCH] script: More compatible with C89 and VC++.

Zoxc zoxc32 at gmail.com
Thu Jun 24 08:34:19 PDT 2010


---
 util/basename.c                          |  165 ++++++++++++++++++++++++++++++
 util/basename.h                          |    7 ++
 util/cairo-script/cairo-script-private.h |    5 +
 util/cairo-script/csi-exec.c             |    8 ++-
 util/cairo-script/csi-replay.c           |   27 ++++--
 util/cairo-script/csi-trace.c            |   17 +++-
 6 files changed, 218 insertions(+), 11 deletions(-)
 create mode 100644 util/basename.c
 create mode 100644 util/basename.h

diff --git a/util/basename.c b/util/basename.c
new file mode 100644
index 0000000..8d034cf
--- /dev/null
+++ b/util/basename.c
@@ -0,0 +1,165 @@
+/* basename.c
+ *
+ * $Id: basename.c,v 1.2 2007/03/08 23:15:58 keithmarshall Exp $
+ *
+ * Provides an implementation of the "basename" function, conforming
+ * to SUSv3, with extensions to accommodate Win32 drive designators,
+ * and suitable for use on native Microsoft(R) Win32 platforms.
+ *
+ * Written by Keith Marshall <keithmarshall at users.sourceforge.net>
+ *
+ * This is free software.  You may redistribute and/or modify it as you
+ * see fit, without restriction of copyright.
+ *
+ * This software is provided "as is", in the hope that it may be useful,
+ * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
+ * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE.  At no
+ * time will the author accept any form of liability for any damages,
+ * however caused, resulting from the use of this software.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+
+char *basename( char *path )
+{
+  size_t len;
+  static char *retfail = NULL;
+
+  /* to handle path names for files in multibyte character locales,
+   * we need to set up LC_CTYPE to match the host file system locale
+   */
+
+  char *locale = setlocale( LC_CTYPE, NULL );
+  if( locale != NULL ) locale = strdup( locale );
+  setlocale( LC_CTYPE, "" );
+
+  if( path && *path )
+  {
+    /* allocate sufficient local storage space,
+     * in which to create a wide character reference copy of path
+     */
+	  
+    wchar_t * refcopy, * refpath;
+    len = mbstowcs( NULL, path, 0 );
+    refcopy = malloc((1 + len) * sizeof(wchar_t));
+
+    /* create the wide character reference copy of path,
+     * and step over the drive designator, if present ...
+     */
+
+    refpath = refcopy;
+    if( ((len = mbstowcs( refpath, path, len )) > 1) && (refpath[1] == L':') )
+    {
+      /* FIXME: maybe should confirm *refpath is a valid drive designator */
+
+      refpath += 2;
+    }
+
+    /* ensure that our wide character reference path is NUL terminated */
+
+    refcopy[ len ] = L'\0';
+
+    /* check again, just to ensure we still have a non-empty path name ... */
+
+    if( *refpath )
+    {
+      /* and, when we do, process it in the wide character domain ...
+       * scanning from left to right, to the char after the final dir separator
+       */
+
+      wchar_t *refname;
+      for( refname = refpath ; *refpath ; ++refpath )
+      {
+	if( (*refpath == L'/') || (*refpath == L'\\') )
+	{
+	  /* we found a dir separator ...
+	   * step over it, and any others which immediately follow it
+	   */
+
+	  while( (*refpath == L'/') || (*refpath == L'\\') )
+	    ++refpath;
+
+	  /* if we didn't reach the end of the path string ... */
+
+	  if( *refpath )
+
+	    /* then we have a new candidate for the base name */
+
+	    refname = refpath;
+
+	  /* otherwise ...
+	   * strip off any trailing dir separators which we found
+	   */
+
+	  else while(  (refpath > refname)
+	  &&          ((*--refpath == L'/') || (*refpath == L'\\'))   )
+	    *refpath = L'\0';
+	}
+      }
+
+      /* in the wide character domain ...
+       * refname now points at the resolved base name ...
+       */
+
+      if( *refname )
+      {
+	/* if it's not empty,
+	 * then we transform the full normalised path back into
+	 * the multibyte character domain, and skip over the dirname,
+	 * to return the resolved basename.
+	 */
+	
+	if( (len = wcstombs( path, refcopy, len )) != (size_t)(-1) )
+	  path[ len ] = '\0';
+	*refname = L'\0';
+	if( (len = wcstombs( NULL, refcopy, 0 )) != (size_t)(-1) )
+	  path += len;
+      }
+
+      else
+      {
+	/* the basename is empty, so return the default value of "/",
+	 * transforming from wide char to multibyte char domain, and
+	 * returning it in our own buffer.
+	 */
+
+	retfail = realloc( retfail, len = 1 + wcstombs( NULL, L"/", 0 ));
+	wcstombs( path = retfail, L"/", len );
+      }
+
+      /* restore the caller's locale, clean up, and return the result */
+
+      setlocale( LC_CTYPE, locale );
+      free( locale );
+      return( path );
+    }
+
+    free(refcopy);
+    /* or we had an empty residual path name, after the drive designator,
+     * in which case we simply fall through ...
+     */
+  }
+
+  /* and, if we get to here ...
+   * the path name is either NULL, or it decomposes to an empty string;
+   * in either case, we return the default value of "." in our own buffer,
+   * reloading it with the correct value, transformed from the wide char
+   * to the multibyte char domain, just in case the caller trashed it
+   * after a previous call.
+   */
+
+  retfail = realloc( retfail, len = 1 + wcstombs( NULL, L".", 0 ));
+  wcstombs( retfail, L".", len );
+
+  /* restore the caller's locale, clean up, and return the result */
+
+  setlocale( LC_CTYPE, locale );
+  free( locale );
+  return( retfail );
+}
+
+/* $RCSfile: basename.c,v $$Revision: 1.2 $: end of file */
diff --git a/util/basename.h b/util/basename.h
new file mode 100644
index 0000000..0392a29
--- /dev/null
+++ b/util/basename.h
@@ -0,0 +1,7 @@
+
+#ifndef BASENAME_H
+#define BASENAME_H
+
+char *basename (char *path);
+
+#endif /* BASENAME_H */
diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h
index 64dd155..6732d94 100644
--- a/util/cairo-script/cairo-script-private.h
+++ b/util/cairo-script/cairo-script-private.h
@@ -55,6 +55,11 @@
 #define NULL (void *) 0
 #endif
 
+#ifdef _MSC_VER
+#define inline __inline
+#define snprintf _snprintf
+#endif
+
 #if   HAVE_STDINT_H
 # include <stdint.h>
 #elif HAVE_INTTYPES_H
diff --git a/util/cairo-script/csi-exec.c b/util/cairo-script/csi-exec.c
index 23e9c36..58fb4ba 100644
--- a/util/cairo-script/csi-exec.c
+++ b/util/cairo-script/csi-exec.c
@@ -17,7 +17,13 @@ int
 main (int argc, char **argv)
 {
     const cairo_script_interpreter_hooks_t hooks = {
-	.surface_create = _surface_create
+        0, /* closure */
+        _surface_create, /* surface_create */
+        0, /* surface_destroy */
+        0, /* context_create */
+        0, /* context_destroy */
+        0, /* show_page */
+        0, /* copy_page */
     };
     cairo_script_interpreter_t *csi;
 	int status;
diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c
index 67fed3b..4d91ed3 100644
--- a/util/cairo-script/csi-replay.c
+++ b/util/cairo-script/csi-replay.c
@@ -276,23 +276,32 @@ main (int argc, char **argv)
 {
     cairo_script_interpreter_t *csi;
     cairo_script_interpreter_hooks_t hooks = {
+        0, /* closure */
 #if SINGLE_SURFACE
-	.surface_create = _similar_surface_create,
-	.context_create = _context_create,
-	.context_destroy = _context_destroy
+	_similar_surface_create, /* surface_create */
 #elif CAIRO_HAS_XLIB_XRENDER_SURFACE
-	.surface_create = _xrender_surface_create
+	_xrender_surface_create, /* surface_create */
 #elif CAIRO_HAS_XLIB_SURFACE
-	.surface_create = _xlib_surface_create
+	_xlib_surface_create, /* surface_create */
 #elif CAIRO_PDF_SURFACE
-	.surface_create = _pdf_surface_create
+	_pdf_surface_create, /* surface_create */
 #elif CAIRO_PS_SURFACE
-	.surface_create = _ps_surface_create
+	_ps_surface_create, /* surface_create */
 #elif CAIRO_SVG_SURFACE
-	.surface_create = _svg_surface_create
+	_svg_surface_create, /* surface_create */
 #else
-	.surface_create = _image_surface_create
+	_image_surface_create, /* surface_create */
 #endif
+        0, /* surface_destroy */
+#if SINGLE_SURFACE
+	_context_create, /* context_create */
+	_context_destroy, /* context_destroy */
+#else
+        0, /* context_create */
+        0, /* context_destroy */
+#endif
+        0, /* show_page */
+        0, /* copy_page */
     };
     int i;
     const struct backends {
diff --git a/util/cairo-script/csi-trace.c b/util/cairo-script/csi-trace.c
index c57a56b..9957612 100644
--- a/util/cairo-script/csi-trace.c
+++ b/util/cairo-script/csi-trace.c
@@ -3,7 +3,16 @@
 
 #include <stdio.h>
 #include <string.h>
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#ifdef _WIN32
+#include <basename.h>
+#else
 #include <libgen.h>
+#endif
 
 static cairo_surface_t *
 _script_surface_create (void *closure,
@@ -19,7 +28,13 @@ main (int argc, char **argv)
 {
     cairo_script_interpreter_t *csi;
     cairo_script_interpreter_hooks_t hooks = {
-	.surface_create = _script_surface_create,
+        0, /* closure */
+        _script_surface_create, /* surface_create */
+        0, /* surface_destroy */
+        0, /* context_create */
+        0, /* context_destroy */
+        0, /* show_page */
+        0, /* copy_page */
     };
     int i;
 
-- 
1.7.0.2.msysgit.0



More information about the cairo mailing list