msvcport cmake project, patch attached for review

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I've attached a patch that adds a CMakeLists.txt and msvcport to enable native compilation on windows via cmake. The patch is against a recent git version of fontconfig. I am not sure what procedures to follow for contributing a patch. Please comment so I can improve it or drop it if there is no interest.

Thank you,
    Pavel.

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..23bc25b
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,503 @@
+cmake_minimum_required(VERSION 2.8.0)
+
+project(fontconfig)
+
+include_directories(AFTER
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  src
+  )
+
+
+set(CASEFOLDING_TXT "${PROJECT_SOURCE_DIR}/fc-case/CaseFolding.txt")
+set(FCCASE_TMPL_H "${PROJECT_SOURCE_DIR}/fc-case/fccase.tmpl.h")
+set(FCCASE_H "${PROJECT_SOURCE_DIR}/fc-case/fccase.h")
+set_source_files_properties("${FCCASE_H}" PROPERTIES GENERATED true)
+
+if (MINGW OR MSYS)
+  string(REPLACE "/" "\\\\" NATIVE_CASEFOLDING_TXT "${CASEFOLDING_TXT}")
+  string(REPLACE "/" "\\\\" NATIVE_FCCASE_TMPL_H "${FCCASE_TMPL_H}")
+  string(REPLACE "/" "\\\\" NATIVE_FCCASE_H "${FCCASE_H}")
+else (MINGW OR MSYS)
+  file(TO_NATIVE_PATH "${CASEFOLDING_TXT}" NATIVE_CASEFOLDING_TXT)
+  file(TO_NATIVE_PATH "${FCCASE_TMPL_H}" NATIVE_FCCASE_TMPL_H)
+  file(TO_NATIVE_PATH "${FCCASE_H}" NATIVE_FCCASE_H)
+endif (MINGW OR MSYS)
+
+add_custom_command(OUTPUT "${FCCASE_H}"
+  COMMAND fc-case
+  ARGS
+  "${NATIVE_CASEFOLDING_TXT}" < "${NATIVE_FCCASE_TMPL_H}" > "${NATIVE_FCCASE_H}"
+  DEPENDS
+  fc-case
+  )
+
+set(ZAPFDINGBATS_TXT "${PROJECT_SOURCE_DIR}/fc-glyphname/zapfdingbats.txt")
+set(FCGLYPHNAME_TMPL_H "${PROJECT_SOURCE_DIR}/fc-glyphname/fcglyphname.tmpl.h")
+set(FCGLYPHNAME_H "${PROJECT_SOURCE_DIR}/fc-glyphname/fcglyphname.h")
+set_source_files_properties("${FCGLYPHNAME_H}" PROPERTIES GENERATED true)
+
+if (MINGW OR MSYS)
+  string(REPLACE "/" "\\\\" NATIVE_ZAPFDINGBATS_TXT "${ZAPFDINGBATS_TXT}")
+  string(REPLACE "/" "\\\\" NATIVE_FCGLYPHNAME_TMPL_H "${FCGLYPHNAME_TMPL_H}")
+  string(REPLACE "/" "\\\\" NATIVE_FCGLYPHNAME_H "${FCGLYPHNAME_H}")
+else (MINGW OR MSYS)
+  file(TO_NATIVE_PATH "${ZAPFDINGBATS_TXT}" NATIVE_ZAPFDINGBATS_TXT)
+  file(TO_NATIVE_PATH "${FCGLYPHNAME_TMPL_H}" NATIVE_FCGLYPHNAME_TMPL_H)
+  file(TO_NATIVE_PATH "${FCGLYPHNAME_H}" NATIVE_FCGLYPHNAME_H)
+endif (MINGW OR MSYS)
+
+add_custom_command(OUTPUT "${FCGLYPHNAME_H}"
+  COMMAND fc-glyphname
+  ARGS
+  "${NATIVE_ZAPFDINGBATS_TXT}" < "${NATIVE_FCGLYPHNAME_TMPL_H}" > "${NATIVE_FCGLYPHNAME_H}"
+  DEPENDS
+  fc-glyphname
+  )
+
+
+set(FCLANG_ORTH
+  aa.orth
+  ab.orth
+  af.orth
+  ak.orth
+  am.orth
+  an.orth
+  ar.orth
+  as.orth
+  ast.orth
+  av.orth
+  ay.orth
+  az_az.orth
+  az_ir.orth
+  ba.orth
+  be.orth
+  ber_dz.orth
+  ber_ma.orth
+  bg.orth
+  bh.orth
+  bho.orth
+  bi.orth
+  bin.orth
+  bm.orth
+  bn.orth
+  bo.orth
+  br.orth
+  brx.orth
+  bs.orth
+  bua.orth
+  byn.orth
+  ca.orth
+  ce.orth
+  ch.orth
+  chm.orth
+  chr.orth
+  co.orth
+  crh.orth
+  cs.orth
+  csb.orth
+  cu.orth
+  cv.orth
+  cy.orth
+  da.orth
+  de.orth
+  doi.orth
+  dv.orth
+  dz.orth
+  ee.orth
+  el.orth
+  en.orth
+  eo.orth
+  es.orth
+  et.orth
+  eu.orth
+  fa.orth
+  fat.orth
+  ff.orth
+  fi.orth
+  fil.orth
+  fj.orth
+  fo.orth
+  fr.orth
+  fur.orth
+  fy.orth
+  ga.orth
+  gd.orth
+  gez.orth
+  gl.orth
+  gn.orth
+  gu.orth
+  gv.orth
+  ha.orth
+  haw.orth
+  he.orth
+  hi.orth
+  hne.orth
+  ho.orth
+  hr.orth
+  hsb.orth
+  ht.orth
+  hu.orth
+  hy.orth
+  hz.orth
+  ia.orth
+  id.orth
+  ie.orth
+  ig.orth
+  ii.orth
+  ik.orth
+  io.orth
+  is.orth
+  it.orth
+  iu.orth
+  ja.orth
+  jv.orth
+  ka.orth
+  kaa.orth
+  kab.orth
+  ki.orth
+  kj.orth
+  kk.orth
+  kl.orth
+  km.orth
+  kn.orth
+  ko.orth
+  kok.orth
+  kr.orth
+  ks.orth
+  ku_am.orth
+  ku_iq.orth
+  ku_ir.orth
+  ku_tr.orth
+  kum.orth
+  kv.orth
+  kw.orth
+  kwm.orth
+  ky.orth
+  la.orth
+  lah.orth
+  lb.orth
+  lez.orth
+  lg.orth
+  li.orth
+  ln.orth
+  lo.orth
+  lt.orth
+  lv.orth
+  mai.orth
+  mg.orth
+  mh.orth
+  mi.orth
+  mk.orth
+  ml.orth
+  mn_cn.orth
+  mn_mn.orth
+  mni.orth
+  mo.orth
+  mr.orth
+  ms.orth
+  mt.orth
+  my.orth
+  na.orth
+  nb.orth
+  nds.orth
+  ne.orth
+  ng.orth
+  nl.orth
+  nn.orth
+  no.orth
+  nqo.orth
+  nr.orth
+  nso.orth
+  nv.orth
+  ny.orth
+  oc.orth
+  om.orth
+  or.orth
+  os.orth
+  ota.orth
+  pa.orth
+  pa_pk.orth
+  pap_an.orth
+  pap_aw.orth
+  pes.orth
+  pl.orth
+  prs.orth
+  ps_af.orth
+  ps_pk.orth
+  pt.orth
+  qu.orth
+  rm.orth
+  rn.orth
+  ro.orth
+  ru.orth
+  rw.orth
+  sa.orth
+  sah.orth
+  sat.orth
+  sc.orth
+  sco.orth
+  sd.orth
+  se.orth
+  sel.orth
+  sg.orth
+  sh.orth
+  shs.orth
+  si.orth
+  sid.orth
+  sk.orth
+  sl.orth
+  sm.orth
+  sma.orth
+  smj.orth
+  smn.orth
+  sms.orth
+  sn.orth
+  so.orth
+  sq.orth
+  sr.orth
+  ss.orth
+  st.orth
+  su.orth
+  sv.orth
+  sw.orth
+  syr.orth
+  ta.orth
+  te.orth
+  tg.orth
+  th.orth
+  ti_er.orth
+  ti_et.orth
+  tig.orth
+  tk.orth
+  tl.orth
+  tn.orth
+  to.orth
+  tr.orth
+  ts.orth
+  tt.orth
+  tw.orth
+  ty.orth
+  tyv.orth
+  ug.orth
+  uk.orth
+  ur.orth
+  uz.orth
+  ve.orth
+  vi.orth
+  vo.orth
+  vot.orth
+  wa.orth
+  wal.orth
+  wen.orth
+  wo.orth
+  xh.orth
+  yap.orth
+  yi.orth
+  yo.orth
+  za.orth
+  zh_cn.orth
+  zh_hk.orth
+  zh_mo.orth
+  zh_sg.orth
+  zh_tw.orth
+  zu.orth
+)
+
+
+set(FCLANG_DIR "${PROJECT_SOURCE_DIR}/fc-lang")
+set(FCLANG_TMPL_H "${PROJECT_SOURCE_DIR}/fc-lang/fclang.tmpl.h")
+set(FCLANG_H "${PROJECT_SOURCE_DIR}/fc-lang/fclang.h")
+set_source_files_properties("${FCLANG_H}" PROPERTIES GENERATED true)
+
+if (MINGW OR MSYS)
+  string(REPLACE "/" "\\\\" NATIVE_FCLANG_DIR "${FCLANG_DIR}")
+  string(REPLACE "/" "\\\\" NATIVE_FCLANG_TMPL_H "${FCLANG_TMPL_H}")
+  string(REPLACE "/" "\\\\" NATIVE_FCLANG_H "${FCLANG_H}")
+else (MINGW OR MSYS)
+  file(TO_NATIVE_PATH "${FCLANG_DIR}" NATIVE_FCLANG_DIR)
+  file(TO_NATIVE_PATH "${FCLANG_TMPL_H}" NATIVE_FCLANG_TMPL_H)
+  file(TO_NATIVE_PATH "${FCLANG_H}" NATIVE_FCLANG_H)
+endif (MINGW OR MSYS)
+
+add_custom_command(OUTPUT "${FCLANG_H}"
+  COMMAND fc-lang
+  ARGS
+  -d "${NATIVE_FCLANG_DIR}" ${FCLANG_ORTH} < "${NATIVE_FCLANG_TMPL_H}" > "${NATIVE_FCLANG_H}"
+  DEPENDS
+  fc-lang "${FCCASE_H}"
+  )
+
+
+add_custom_target("autogenerate" ALL
+  DEPENDS
+  "${FCCASE_H}"
+  "${FCGLYPHNAME_H}"
+  "${FCLANG_H}"
+  )
+
+add_executable(fc-case
+  fc-case/fc-case.c
+  fc-case/fccase.tmpl.h
+  fc-case/CaseFolding.txt
+  )
+
+
+add_executable(fc-lang
+  "${FCCASE_H}"
+  fc-lang/fc-lang.c
+  fc-lang/fclang.tmpl.h
+  fc-lang/iso-3166.txt
+  fc-lang/iso639-1
+  fc-lang/iso639-2
+)
+
+add_executable(fc-glyphname
+  fc-glyphname/fc-glyphname.c
+  fc-glyphname/fcglyphname.tmpl.h
+  )
+
+if (WIN32)
+  ADD_DEFINITIONS(-D_USE_MATH_DEFINES)
+  ADD_DEFINITIONS(-DNOMINMAX)
+  ADD_DEFINITIONS(-DFC_CACHEDIR="WINDOWSTEMPDIR_FONTCONFIG_CACHE")
+  ADD_DEFINITIONS(-DHAVE_CONFIG_H)
+
+  OPTION(LINKING_TO_STATIC_EXPAT_LIB "Check this if linking to static expat library" false)
+  if (LINKING_TO_STATIC_EXPAT_LIB)
+    ADD_DEFINITIONS(-DXML_STATIC=1)
+  endif(LINKING_TO_STATIC_EXPAT_LIB)
+
+  include_directories(AFTER
+    msvcport
+    )
+endif (WIN32)
+
+
+set(FREETYPE_DIR "$ENV{FREETYPE_DIR}"
+  CACHE PATH "root path for freetype lib/ and include/ folders"
+  )
+find_path(FREETYPE_INCLUDE_DIR
+  ft2build.h freetype2/freetype/freetype.h
+  PATHS ${FREETYPE_DIR}/include
+  )
+find_library(FREETYPE_LIBRARY
+  freetype libfreetype
+  PATHS ${FREETYPE_DIR}/lib
+  DOC "freetype library"
+  )
+if (FREETYPE_INCLUDE_DIR)
+  include_directories(AFTER ${FREETYPE_INCLUDE_DIR} ${FREETYPE_INCLUDE_DIR}/freetype2)
+endif (FREETYPE_INCLUDE_DIR)
+
+
+set(EXPAT_DIR "$ENV{EXPAT_DIR}"
+  CACHE PATH "root path for expat lib/ and include/ folders"
+  )
+find_path(EXPAT_INCLUDE_DIR
+  expat.h
+  PATHS ${EXPAT_DIR}/include
+  )
+find_library(EXPAT_LIBRARY
+  expat libexpat
+  PATHS ${EXPAT_DIR}/lib
+  DOC "expat library"
+  )
+if (EXPAT_INCLUDE_DIR)
+  include_directories(AFTER ${EXPAT_INCLUDE_DIR})
+endif (EXPAT_INCLUDE_DIR)
+
+
+set(ICONV_DIR "$ENV{ICONV_DIR}"
+  CACHE PATH "root path for iconv lib/ and include/ folders"
+  )
+find_path(ICONV_INCLUDE_DIR
+  iconv.h
+  PATHS ${ICONV_DIR}/include
+  )
+find_library(ICONV_LIBRARY
+  iconv libiconv
+  PATHS ${ICONV_DIR}/lib
+  DOC "iconv library"
+  )
+if (ICONV_INCLUDE_DIR)
+  include_directories(AFTER ${ICONV_INCLUDE_DIR})
+endif (ICONV_INCLUDE_DIR)
+
+
+set(project_sources
+  "${FCCASE_H}"
+  "${FCLANG_H}"
+  "${FCGLYPHNAME_H}"
+  src/fcarch.h
+  src/fcatomic.c
+  src/fcblanks.c
+  src/fccache.c
+  src/fccfg.c
+  src/fccharset.c
+  src/fcdbg.c
+  src/fcdefault.c
+  src/fcdir.c
+  src/fcformat.c
+  src/fcfreetype.c
+  src/fcfs.c
+  src/fcinit.c
+  src/fclang.c
+  src/fclist.c
+  src/fcmatch.c
+  src/fcmatrix.c
+  src/fcname.c
+  src/fcpat.c
+  src/fcserialize.c
+  src/fcstat.c
+  src/fcstr.c
+  src/fcxml.c
+  src/ftglue.h
+  src/ftglue.c
+  )
+
+if (WIN32)
+  set(project_sources
+    ${project_sources}
+    msvcport/config.h
+    msvcport/dirent.h
+    msvcport/fcalias.h
+    msvcport/fcaliastail.h
+    msvcport/fcftalias.h
+    msvcport/fcftaliastail.h
+    msvcport/inttypes.h
+    msvcport/stdint.h
+    msvcport/msvcport.h
+    msvcport/msvcport_private.h
+    msvcport/msvcport_private.c
+    )
+  find_library(LIBGCC_LIBRARY libgcc PATHS ${FFMPEG_LIBS_PATH} DOC "mingw libgcc library")
+endif (WIN32)
+
+add_library(fontconfig_static STATIC
+  ${project_sources}
+  )
+add_dependencies(fontconfig_static "autogenerate")
+
+add_library(fontconfig_shared SHARED
+  ${project_sources}
+  )
+add_dependencies(fontconfig_shared "autogenerate")
+
+
+set(THIRD_PARTY_LIBS ${FREETYPE_LIBRARY} ${EXPAT_LIBRARY} ${ICONV_LIBRARY})
+if (WIN32)
+  if (LIBGCC_LIBRARY)
+    set(THIRD_PARTY_LIBS ${THIRD_PARTY_LIBS} ${LIBGCC_LIBRARY})
+  endif (LIBGCC_LIBRARY)
+endif (WIN32)
+target_link_libraries(fontconfig_shared ${THIRD_PARTY_LIBS})
+
+
+install(TARGETS fontconfig_static fontconfig_shared DESTINATION lib)
+install(FILES
+  fontconfig/fontconfig.h
+  fontconfig/fcfreetype.h
+  fontconfig/fcprivate.h
+
+  DESTINATION
+  include/fontconfig)
diff --git a/config-fixups.h b/config-fixups.h
index 93ebf5b..e613711 100644
--- a/config-fixups.h
+++ b/config-fixups.h
@@ -38,3 +38,21 @@
 #  define ALIGNOF_DOUBLE 4
 # endif
 #endif
+
+/* a very thin portability layer */
+#if defined(_WIN32) && !defined(__MINGW32__)
+#include "msvcport.h"
+#else
+#define fc_opendir(x) opendir(x)
+#define fc_readdir(x) readdir(x)
+#define fc_closedir(x) closedir(x)
+
+#define fc_mkdir(x, y) mkdir(x, y)
+#define fc_rmdir(x) rmdir(x)
+
+#define fc_access(x, y) access(x, y)
+#define fc_chmod(x, y) chmod(x, y)
+#define fc_unlink(x) unlink(x)
+#define fc_open(x, y, ...) open(x, y, __VA_ARGS__)
+
+#endif
diff --git a/msvcport/dirent.h b/msvcport/dirent.h
new file mode 100644
index 0000000..b045938
--- /dev/null
+++ b/msvcport/dirent.h
@@ -0,0 +1,8 @@
+/* -*- Mode: c++; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+#ifndef FONTCONFIG_DIRENT_H_
+#define FONTCONFIG_DIRENT_H_
+
+#include "msvcport.h"
+
+#endif /* FONTCONFIG_DIRENT_H_ */
diff --git a/msvcport/fcftalias.h b/msvcport/fcftalias.h
new file mode 100644
index 0000000..e69de29
diff --git a/msvcport/fcftaliastail.h b/msvcport/fcftaliastail.h
new file mode 100644
index 0000000..e69de29
diff --git a/msvcport/inttypes.h b/msvcport/inttypes.h
new file mode 100644
index 0000000..4b3828a
--- /dev/null
+++ b/msvcport/inttypes.h
@@ -0,0 +1,305 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+#endif // __STDC_FORMAT_MACROS ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot = numer / denom;
+   result.rem = numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -= denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/msvcport/msvcport.h b/msvcport/msvcport.h
new file mode 100644
index 0000000..c548e02
--- /dev/null
+++ b/msvcport/msvcport.h
@@ -0,0 +1,21 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+#ifndef FONTCONFIG_MSVCPORT_H_
+#define FONTCONFIG_MSVCPORT_H_
+
+#include "msvcport_private.h"
+
+#define fc_opendir(x) fc_msvcport_opendir(x)
+#define fc_readdir(x) fc_msvcport_readdir(x)
+#define fc_closedir(x) fc_msvcport_closedir(x)
+
+#define fc_mkdir(x, y) fc_msvcport_mkdir(x, y)
+#define fc_rmdir(x) fc_msvcport_rmdir(x)
+
+#define fc_access(x, y) fc_msvcport_access(x, y)
+#define fc_chmod(x, y) chmod(x, y)
+#define fc_unlink(x) fc_msvcport_unlink(x)
+#define fc_open(x, y, ...) fc_msvcport_open(x, y, __VA_ARGS__)
+
+
+#endif /* FONTCONFIG_MSVCPORT_H_ */
diff --git a/msvcport/msvcport_private.c b/msvcport/msvcport_private.c
new file mode 100644
index 0000000..af339d8
--- /dev/null
+++ b/msvcport/msvcport_private.c
@@ -0,0 +1,343 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#if defined(_WIN32)
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <windows.h>
+#include <io.h>
+#include <winnls.h>
+#include <wchar.h>
+#include <share.h>
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "msvcport_private.h"
+
+wchar_t *
+fc_utf8_to_utf16(const char * cstr)
+{
+    int sz = MultiByteToWideChar(CP_UTF8, 0, cstr, -1, NULL, 0);
+    wchar_t * wstr = (wchar_t *)malloc(sz * sizeof(wchar_t));
+    MultiByteToWideChar(CP_UTF8, 0, cstr, -1, wstr, sz);
+    return wstr;
+}
+
+char *
+fc_utf16_to_utf8(const wchar_t * wstr)
+{
+    int sz = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
+    char * cstr = (char *)malloc(sz);
+    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, cstr, sz, NULL, NULL);
+    return cstr;
+}
+
+
+struct TDir
+{
+    struct dirent         dirent_;
+    intptr_t              handle_;
+    struct _wfinddata64_t dfound_;
+    int                   nfound_;
+    wchar_t *             wquery_;
+};
+
+static void
+TDirInit(struct TDir * d)
+{
+    memset(d, 0, sizeof(struct TDir));
+}
+
+static int
+TDirClose(struct TDir * d)
+{
+    if (d->handle_)
+    {
+        int err = _findclose(d->handle_);
+        memset(&d->dirent_, 0, sizeof(d->dirent_));
+        d->nfound_ = 0;
+        free(d->wquery_);
+        d->wquery_ = NULL;
+        return err;
+    }
+
+    return 0;
+}
+
+static int
+TDirOpen(struct TDir * d, const char * path)
+{
+    size_t pathLen = strlen(path);
+    size_t queryLen = pathLen;
+
+    char * query = (char *)malloc(pathLen + 3);
+    memcpy(query, path, queryLen);
+
+    if (!pathLen || !strchr("\\/", path[pathLen - 1]))
+    {
+        query[queryLen++] = '/';
+    }
+
+    query[queryLen++] = '*';
+    query[queryLen] = 0;
+
+    TDirClose(d);
+    d->wquery_ = fc_utf8_to_utf16(query);
+    free(query);
+    query = NULL;
+
+    if (!d->wquery_)
+    {
+        return 0;
+    }
+
+    d->handle_ = _wfindfirst64(d->wquery_, &d->dfound_);
+    if (d->handle_)
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void
+TDirLoad(struct TDir * d)
+{
+    static const size_t nameMax = sizeof(d->dirent_.d_name);
+    char * name = fc_utf16_to_utf8(d->dfound_.name);
+    size_t nameLen = strlen(name);
+    size_t copyLen = nameLen < nameMax ? nameLen : nameMax;
+    strncpy_s(d->dirent_.d_name, nameMax, name, copyLen);
+    free(name);
+}
+
+static int
+TDirNext(struct TDir * d)
+{
+    if (!d->handle_ || d->nfound_ < 0)
+    {
+        return 0;
+    }
+
+    TDirLoad(d);
+
+    if (_wfindnext64(d->handle_, &d->dfound_) == -1)
+    {
+        d->nfound_ = -1;
+    }
+    else
+    {
+        d->nfound_ ++;
+    }
+
+    return 1;
+}
+
+
+void *
+fc_msvcport_opendir(const char * path)
+{
+    struct TDir * dir = (struct TDir *)malloc(sizeof(struct TDir));
+    TDirInit(dir);
+
+    if (TDirOpen(dir, path))
+    {
+        return dir;
+    }
+
+    TDirClose(dir);
+    free(dir);
+    return NULL;
+}
+
+int
+fc_msvcport_closedir(void * priv)
+{
+    struct TDir * dir = (struct TDir *)priv;
+    if (!dir)
+    {
+        return -1;
+    }
+
+    TDirClose(dir);
+    free(dir);
+    return 0;
+}
+
+struct dirent *
+fc_msvcport_readdir(void * priv)
+{
+    struct TDir * dir = (struct TDir *)priv;
+    if (dir && TDirNext(dir))
+    {
+        return &(dir->dirent_);
+    }
+
+    return NULL;
+}
+
+int
+fc_msvcport_mkdir(const char * path, int mode)
+{
+    wchar_t * tmp = fc_utf8_to_utf16(path);
+    int r = _wmkdir(tmp);
+    free(tmp);
+    return r;
+}
+
+int
+fc_msvcport_rmdir(const char * path)
+{
+    wchar_t * tmp = fc_utf8_to_utf16(path);
+    int r = _wrmdir(tmp);
+    free(tmp);
+    return r;
+}
+
+int
+fc_msvcport_access(const char * path, int perms)
+{
+    /* X_OK (01) permission causes fatal error in win32 _access(..),
+       therefore it must be excluded from the permission bitmask: */
+    int wperms = perms & ~1;
+
+    wchar_t * tmp = fc_utf8_to_utf16(path);
+    int r = _waccess(tmp, wperms);
+    free(tmp);
+    return r;
+}
+
+int
+fc_msvcport_chmod(const char * path, int unixPerms)
+{
+    wchar_t * tmp = fc_utf8_to_utf16(path);
+    int permissions = 0;
+    int ret = 0;
+
+    if (unixPerms & 0444)
+    {
+        permissions |= _S_IREAD;
+    }
+
+    if (unixPerms & 0222)
+    {
+        permissions |= _S_IWRITE;
+    }
+    
+    ret = _wchmod(tmp, permissions);
+    free(tmp);
+    return ret;
+}
+
+int
+fc_msvcport_rename(const char * fnOld, const char * fnNew)
+{
+    wchar_t * wold = fc_utf8_to_utf16(fnOld);
+    wchar_t * wnew = fc_utf8_to_utf16(fnNew);
+
+    int ret = _wrename(wold, wnew);
+
+    free(wold);
+    free(wnew);
+    return ret;
+}
+
+int
+fc_msvcport_unlink(const char * path)
+{
+    wchar_t * tmp = fc_utf8_to_utf16(path);
+    int r = _wunlink(tmp);
+    free(tmp);
+    return r;
+}
+
+int
+fc_msvcport_open(const char * filenameUtf8, int accessMode, ...)
+{
+    int waccessMode = accessMode | O_BINARY;
+
+    wchar_t * wname = fc_utf8_to_utf16(filenameUtf8);
+    int fd = -1;
+    int sh = accessMode & (_O_RDWR | _O_WRONLY) ? _SH_DENYWR : _SH_DENYNO;
+    int permissions = _S_IREAD;
+    errno_t err = 0;
+
+    if ((accessMode & _O_CREAT) != 0)
+    {
+        int unixPerms = 0644;
+        va_list ap;
+        va_start(ap, accessMode);
+        unixPerms = va_arg(ap, int);
+
+        permissions = 0;
+        if (unixPerms & 0444)
+        {
+            permissions |= _S_IREAD;
+        }
+
+        if (unixPerms & 0222)
+        {
+            permissions |= _S_IWRITE;
+        }
+
+        if (unixPerms & 0111)
+        {
+            permissions |= _S_IEXEC;
+        }
+
+        va_end(ap);
+    }
+
+    err = _wsopen_s(&fd, wname, waccessMode, sh, permissions);
+    free(wname);
+
+    return fd;
+}
+
+int64_t
+fc_msvcport_file_seek64(int fd, int64_t offset, int whence)
+{
+    __int64 pos = _lseeki64(fd, offset, whence);
+    return pos;
+}
+
+int64_t
+fc_msvcport_file_size64(int fd)
+{
+    struct _stati64 st;
+    __int64 ret = _fstati64(fd, &st);
+
+    if (ret < 0)
+    {
+        return ret;
+    }
+
+    return st.st_size;
+}
+
+void *
+fc_msvcport_fopen(const char * filenameUtf8, const char * mode)
+{
+    FILE * file = NULL;
+
+    wchar_t * wname = fc_utf8_to_utf16(filenameUtf8);
+    wchar_t * wmode = fc_utf8_to_utf16(mode);
+
+    _wfopen_s(&file, wname, wmode);
+
+    free(wname);
+    free(wmode);
+
+    return file;
+}
+
+
+#endif /* _WIN32 */
diff --git a/msvcport/msvcport_private.h b/msvcport/msvcport_private.h
new file mode 100644
index 0000000..18cfe3a
--- /dev/null
+++ b/msvcport/msvcport_private.h
@@ -0,0 +1,65 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+#ifndef FONTCONFIG_MSVCPORT_PRIVATE_H_
+#define FONTCONFIG_MSVCPORT_PRIVATE_H_
+
+#include <stdint.h>
+#include <wchar.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+    wchar_t * fc_utf8_to_utf16(const char * cstr);
+    char * fc_utf16_to_utf8(const wchar_t * wstr);
+
+    /* NOTE:
+       all char * strings passed to or returned from these
+       fc_msvcport_... functions are UTF-8 encoded
+    */
+
+    typedef void * DIR;
+
+    /*
+      this structure is layed out same as in mingw/include/dirent.h
+      for binary compatibility with code built with mingw compiler
+    */
+    struct dirent
+    {
+        long int           d_ino;       /* always zero */
+        unsigned short int d_reclen;    /* always zero */
+        unsigned short int d_namlen;    /* name length */
+        char               d_name[260]; /* name[FILENAME_MAX] */
+    };
+
+    extern void * fc_msvcport_opendir(const char * path);
+    extern struct dirent * fc_msvcport_readdir(void * priv);
+    extern int fc_msvcport_closedir(void * priv);
+
+    extern int fc_msvcport_mkdir(const char * path, int mode);
+    extern int fc_msvcport_rmdir(const char * path);
+
+    enum
+    {
+        F_OK = 0, /* Existence only */
+        W_OK = 2, /* Write permission */
+        R_OK = 4  /* Read permission */
+    };
+
+    extern int fc_msvcport_access(const char * path, int perms);
+    extern int fc_msvcport_chmod(const char * path, int mode);
+    extern int fc_msvcport_rename(const char * fnOld, const char * fnNew);
+    extern int fc_msvcport_unlink(const char * path);
+    extern int fc_msvcport_open(const char * fn, int oflag, ...);
+
+    extern int64_t fc_msvcport_file_seek64(int fd, int64_t offset, int whence);
+    extern int64_t fc_msvcport_file_size64(int fd);
+
+    extern void * fc_msvcport_fopen(const char * path, const char * mode);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+
+#endif /* FONTCONFIG_MSVCPORT_PRIVATE_H_ */
diff --git a/msvcport/stdint.h b/msvcport/stdint.h
new file mode 100644
index 0000000..d02608a
--- /dev/null
+++ b/msvcport/stdint.h
@@ -0,0 +1,247 @@
+// ISO C9x  compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
+// 
+//  Copyright (c) 2006-2008 Alexander Chemeris
+// 
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// 
+//   1. Redistributions of source code must retain the above copyright notice,
+//      this list of conditions and the following disclaimer.
+// 
+//   2. Redistributions in binary form must reproduce the above copyright
+//      notice, this list of conditions and the following disclaimer in the
+//      documentation and/or other materials provided with the distribution.
+// 
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#ifdef __cplusplus
+extern "C" {
+#endif
+#  include <wchar.h>
+#ifdef __cplusplus
+}
+#endif
+
+// Define _W64 macros to mark types changing their size, like intptr_t.
+#ifndef _W64
+#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
+#     define _W64 __w64
+#  else
+#     define _W64
+#  endif
+#endif
+
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+
+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
+// realize that, e.g. char has the same size as __int8
+// so we give up on __intX for them.
+#if (_MSC_VER < 1300)
+   typedef signed char       int8_t;
+   typedef signed short      int16_t;
+   typedef signed int        int32_t;
+   typedef unsigned char     uint8_t;
+   typedef unsigned short    uint16_t;
+   typedef unsigned int      uint32_t;
+#else
+   typedef signed __int8     int8_t;
+   typedef signed __int16    int16_t;
+   typedef signed __int32    int32_t;
+   typedef unsigned __int8   uint8_t;
+   typedef unsigned __int16  uint16_t;
+   typedef unsigned __int32  uint32_t;
+#endif
+typedef signed __int64       int64_t;
+typedef unsigned __int64     uint64_t;
+
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+   typedef signed __int64    intptr_t;
+   typedef unsigned __int64  uintptr_t;
+#else // _WIN64 ][
+   typedef _W64 signed int   intptr_t;
+   typedef _W64 unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     ((int8_t)_I8_MIN)
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    ((int16_t)_I16_MIN)
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    ((int32_t)_I32_MIN)
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    ((int64_t)_I64_MIN)
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/src/fcatomic.c b/src/fcatomic.c
index 350744a..d7a5eb2 100644
--- a/src/fcatomic.c
+++ b/src/fcatomic.c
@@ -51,14 +51,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <stdlib.h>
 #include <time.h>
 
-#ifdef _WIN32
-#define mkdir(path,mode) _mkdir(path)
-#endif
-
 #define NEW_NAME	".NEW"
 #define LCK_NAME	".LCK"
 #define TMP_NAME	".TMP-XXXXXX"
@@ -116,19 +114,19 @@ FcAtomicLock (FcAtomic *atomic)
     if (!f)
     {
     	close (fd);
-	unlink ((char *) atomic->tmp);
+	fc_unlink ((char *) atomic->tmp);
 	return FcFalse;
     }
     ret = fprintf (f, "%ld\n", (long)getpid());
     if (ret <= 0)
     {
 	fclose (f);
-	unlink ((char *) atomic->tmp);
+	fc_unlink ((char *) atomic->tmp);
 	return FcFalse;
     }
     if (fclose (f) == EOF)
     {
-	unlink ((char *) atomic->tmp);
+	fc_unlink ((char *) atomic->tmp);
 	return FcFalse;
     }
     ret = link ((char *) atomic->tmp, (char *) atomic->lck);
@@ -137,12 +135,12 @@ FcAtomicLock (FcAtomic *atomic)
 	/* the filesystem where atomic->lck points to may not supports
 	 * the hard link. so better try to fallback
 	 */
-	ret = mkdir ((char *) atomic->lck, 0600);
+	ret = fc_mkdir ((char *) atomic->lck, 0600);
 	no_link = FcTrue;
     }
-    (void) unlink ((char *) atomic->tmp);
+    (void) fc_unlink ((char *) atomic->tmp);
 #else
-    ret = mkdir ((char *) atomic->lck, 0600);
+    ret = fc_mkdir ((char *) atomic->lck, 0600);
 #endif
     if (ret < 0)
     {
@@ -160,23 +158,23 @@ FcAtomicLock (FcAtomic *atomic)
 #ifdef HAVE_LINK
 		if (no_link)
 		{
-		    if (rmdir ((char *) atomic->lck) == 0)
+		    if (fc_rmdir ((char *) atomic->lck) == 0)
 			return FcAtomicLock (atomic);
 		}
 		else
 		{
-		    if (unlink ((char *) atomic->lck) == 0)
+		    if (fc_unlink ((char *) atomic->lck) == 0)
 			return FcAtomicLock (atomic);
 		}
 #else
-		if (rmdir ((char *) atomic->lck) == 0)
+		if (fc_rmdir ((char *) atomic->lck) == 0)
 		    return FcAtomicLock (atomic);
 #endif
 	    }
 	}
 	return FcFalse;
     }
-    (void) unlink ((char *) atomic->new);
+    (void) fc_unlink ((char *) atomic->new);
     return FcTrue;
 }
 
@@ -196,7 +194,7 @@ FcBool
 FcAtomicReplaceOrig (FcAtomic *atomic)
 {
 #ifdef _WIN32
-    unlink ((const char *) atomic->file);
+    fc_unlink ((const char *) atomic->file);
 #endif
     if (rename ((char *) atomic->new, (char *) atomic->file) < 0)
 	return FcFalse;
@@ -206,17 +204,17 @@ FcAtomicReplaceOrig (FcAtomic *atomic)
 void
 FcAtomicDeleteNew (FcAtomic *atomic)
 {
-    unlink ((char *) atomic->new);
+    fc_unlink ((char *) atomic->new);
 }
 
 void
 FcAtomicUnlock (FcAtomic *atomic)
 {
 #ifdef HAVE_LINK
-    if (unlink ((char *) atomic->lck) == -1)
-	rmdir ((char *) atomic->lck);
+    if (fc_unlink ((char *) atomic->lck) == -1)
+	fc_rmdir ((char *) atomic->lck);
 #else
-    rmdir ((char *) atomic->lck);
+    fc_rmdir ((char *) atomic->lck);
 #endif
 }
 
diff --git a/src/fccache.c b/src/fccache.c
index 81985df..b307cb3 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -131,7 +131,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
         cache_hashed = FcStrPlus (cache_dir, cache_base);
         if (!cache_hashed)
 	    break;
-	(void) unlink ((char *) cache_hashed);
+	(void) fc_unlink ((char *) cache_hashed);
 	FcStrFree (cache_hashed);
     }
     FcStrListDone (list);
@@ -150,7 +150,7 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
     if (FcStat (cache_file, file_stat) < 0)
         return -1;
 #endif
-    fd = open((char *) cache_file, O_RDONLY | O_BINARY);
+    fd = fc_open((char *) cache_file, O_RDONLY | O_BINARY);
     if (fd < 0)
 	return fd;
 #ifndef _WIN32
@@ -802,10 +802,6 @@ bail1:
 }
 
 
-#ifdef _WIN32
-#define mkdir(path,mode) _mkdir(path)
-#endif
-
 static FcBool
 FcMakeDirectory (const FcChar8 *dir)
 {
@@ -818,10 +814,10 @@ FcMakeDirectory (const FcChar8 *dir)
     parent = FcStrDirname (dir);
     if (!parent)
 	return FcFalse;
-    if (access ((char *) parent, F_OK) == 0)
-	ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
-    else if (access ((char *) parent, F_OK) == -1)
-	ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
+    if (fc_access ((char *) parent, F_OK) == 0)
+	ret = fc_mkdir ((char *) dir, 0755) == 0 && fc_chmod ((char *) dir, 0755) == 0;
+    else if (fc_access ((char *) parent, F_OK) == -1)
+	ret = FcMakeDirectory (parent) && (fc_mkdir ((char *) dir, 0755) == 0) && fc_chmod ((char *) dir, 0755) == 0;
     else
 	ret = FcFalse;
     FcStrFree (parent);
@@ -853,7 +849,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     if (!list)
 	return FcFalse;
     while ((test_dir = FcStrListNext (list))) {
-	if (access ((char *) test_dir, W_OK) == 0)
+	if (fc_access ((char *) test_dir, W_OK) == 0)
 	{
 	    cache_dir = test_dir;
 	    break;
@@ -863,7 +859,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
 	    /*
 	     * If the directory doesn't exist, try to create it
 	     */
-	    if (access ((char *) test_dir, F_OK) == -1) {
+	    if (fc_access ((char *) test_dir, F_OK) == -1) {
 		if (FcMakeDirectory (test_dir))
 		{
 		    cache_dir = test_dir;
@@ -875,7 +871,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
 	    /*
 	     * Otherwise, try making it writable
 	     */
-	    else if (chmod ((char *) test_dir, 0755) == 0)
+	    else if (fc_chmod ((char *) test_dir, 0755) == 0)
 	    {
 		cache_dir = test_dir;
 		/* Try to create CACHEDIR.TAG too */
@@ -904,7 +900,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     if (!FcAtomicLock (atomic))
 	goto bail3;
 
-    fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
+    fd = fc_open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
     if (fd == -1)
 	goto bail4;
 
@@ -978,23 +974,23 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
 	fprintf (stderr, "Fontconfig error: %s: out of memory\n", cache_dir);
 	return FcFalse;
     }
-    if (access ((char *) cache_dir, W_OK) != 0)
+    if (fc_access ((char *) cache_dir, W_OK) != 0)
     {
 	if (verbose || FcDebug () & FC_DBG_CACHE)
 	    printf ("%s: not cleaning %s cache directory\n", cache_dir,
-		    access ((char *) cache_dir, F_OK) == 0 ? "unwritable" : "non-existent");
+		    fc_access ((char *) cache_dir, F_OK) == 0 ? "unwritable" : "non-existent");
 	goto bail0;
     }
     if (verbose || FcDebug () & FC_DBG_CACHE)
 	printf ("%s: cleaning cache directory\n", cache_dir);
-    d = opendir ((char *) cache_dir);
+    d = fc_opendir ((char *) cache_dir);
     if (!d)
     {
 	perror ((char *) cache_dir);
 	ret = FcFalse;
 	goto bail0;
     }
-    while ((ent = readdir (d)))
+    while ((ent = fc_readdir (d)))
     {
 	FcChar8	*file_name;
 	const FcChar8	*target_dir;
@@ -1025,7 +1021,7 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
 	else
 	{
 	    target_dir = FcCacheDir (cache);
-	    if (stat ((char *) target_dir, &target_stat) < 0)
+	    if (FcStat ((char *) target_dir, &target_stat) < 0)
 	    {
 		if (verbose || FcDebug () & FC_DBG_CACHE)
 		    printf ("%s: %s: missing directory: %s \n",
@@ -1035,7 +1031,7 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
 	}
 	if (remove)
 	{
-	    if (unlink ((char *) file_name) < 0)
+	    if (fc_unlink ((char *) file_name) < 0)
 	    {
 		perror ((char *) file_name);
 		ret = FcFalse;
@@ -1045,7 +1041,7 @@ FcDirCacheClean (const FcChar8 *cache_dir, FcBool verbose)
         FcStrFree (file_name);
     }
 
-    closedir (d);
+    fc_closedir (d);
   bail0:
     FcStrFree (dir_base);
 
@@ -1368,7 +1364,7 @@ FcDirCacheCreateTagFile (const FcChar8 *cache_dir)
     if (!cache_dir)
 	return FcFalse;
 
-    if (access ((char *) cache_dir, W_OK) == 0)
+    if (fc_access ((char *) cache_dir, W_OK) == 0)
     {
 	/* Create CACHEDIR.TAG */
 	cache_tag = FcStrPlus (cache_dir, (const FcChar8 *) FC_DIR_SEPARATOR_S "CACHEDIR.TAG");
@@ -1379,7 +1375,7 @@ FcDirCacheCreateTagFile (const FcChar8 *cache_dir)
 	    goto bail1;
 	if (!FcAtomicLock (atomic))
 	    goto bail2;
-	fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0644);
+	fd = fc_open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0644);
 	if (fd == -1)
 	    goto bail3;
 	fp = fdopen(fd, "wb");
diff --git a/src/fccfg.c b/src/fccfg.c
index d3752e5..c21d678 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -1747,7 +1747,7 @@ FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
     strcat ((char *) path, (char *) file);
 
     FcMemAlloc (FC_MEM_STRING, osize);
-    if (access ((char *) path, R_OK) == 0)
+    if (fc_access ((char *) path, R_OK) == 0)
 	return path;
 
     FcStrFree (path);
diff --git a/src/fcdir.c b/src/fcdir.c
index 2b476e8..fa00b25 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -168,7 +168,7 @@ FcDirScanConfig (FcFontSet	*set,
     if (FcDebug () & FC_DBG_SCAN)
 	printf ("\tScanning dir %s\n", dir);
 	
-    d = opendir ((char *) dir);
+    d = fc_opendir ((char *) dir);
     if (!d)
     {
 	/* Don't complain about missing directories */
@@ -183,7 +183,7 @@ FcDirScanConfig (FcFontSet	*set,
 	ret = FcFalse;
 	goto bail1;
     }
-    while ((e = readdir (d)))
+    while ((e = fc_readdir (d)))
     {
 	if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
 	{
@@ -209,7 +209,7 @@ FcDirScanConfig (FcFontSet	*set,
 bail2:
     FcStrSetDestroy (files);
 bail1:
-    closedir (d);
+    fc_closedir (d);
 bail:
     if (file)
 	free (file);
diff --git a/src/fcformat.c b/src/fcformat.c
index 8eef7bb..d4287db 100644
--- a/src/fcformat.c
+++ b/src/fcformat.c
@@ -566,7 +566,11 @@ interpret_count (FcFormatContext *c,
 	    count++;
     }
 
+#ifdef _WIN32
+    _snprintf_s ((char *) buf_static, sizeof (buf_static), sizeof (buf_static), "%d", count);
+#else
     snprintf ((char *) buf_static, sizeof (buf_static), "%d", count);
+#endif
     FcStrBufString (buf, buf_static);
 
     return FcTrue;
diff --git a/src/fcint.h b/src/fcint.h
index c078575..de72cb9 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -41,7 +41,9 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <stddef.h>
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/src/fcstat.c b/src/fcstat.c
index d8663d0..de92d6f 100644
--- a/src/fcstat.c
+++ b/src/fcstat.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t -*- */
 /*
  * Copyright © 2000 Keith Packard
  * Copyright © 2005 Patrick Lam
@@ -55,6 +56,15 @@ typedef long long INT64;
 typedef __int64 INT64;
 #endif
 
+static FcChar32
+FcStringHashW (const wchar_t * wstr)
+{
+    char * str = fc_utf16_to_utf8(wstr);
+    FcChar32 ret = FcStringHash(str);
+    free(str);
+    return ret;
+}
+
 /* Workaround for problems in the stat() in the Microsoft C library:
  *
  * 1) stat() uses FindFirstFile() to get the file
@@ -75,14 +85,14 @@ typedef __int64 INT64;
  */
 
 int
-FcStat (const FcChar8 *file, struct stat *statb)
+FcStatW (const wchar_t *wfile, struct stat *statb)
 {
     WIN32_FILE_ATTRIBUTE_DATA wfad;
-    char full_path_name[MAX_PATH];
-    char *basename;
+    wchar_t wfull_path_name[MAX_PATH];
+    wchar_t *wbasename;
     DWORD rc;
 
-    if (!GetFileAttributesEx ((LPCSTR) file, GetFileExInfoStandard, &wfad))
+    if (!GetFileAttributesExW (wfile, GetFileExInfoStandard, &wfad))
 	return -1;
 
     statb->st_dev = 0;
@@ -91,12 +101,12 @@ FcStat (const FcChar8 *file, struct stat *statb)
      * Call GetLongPathName() to get the spelling of the path name as it
      * is on disk.
      */
-    rc = GetFullPathName ((LPCSTR) file, sizeof (full_path_name), full_path_name, &basename);
-    if (rc == 0 || rc > sizeof (full_path_name))
+    rc = GetFullPathNameW (wfile, MAX_PATH, wfull_path_name, &wbasename);
+    if (rc == 0 || rc > MAX_PATH)
 	return -1;
 
-    rc = GetLongPathName (full_path_name, full_path_name, sizeof (full_path_name));
-    statb->st_ino = FcStringHash ((const FcChar8 *) full_path_name);
+    rc = GetLongPathNameW (wfull_path_name, wfull_path_name, MAX_PATH);
+    statb->st_ino = FcStringHashW (wfull_path_name);
 
     statb->st_mode = _S_IREAD | _S_IWRITE;
     statb->st_mode |= (statb->st_mode >> 3) | (statb->st_mode >> 6);
@@ -121,6 +131,21 @@ FcStat (const FcChar8 *file, struct stat *statb)
     return 0;
 }
 
+int
+FcStat (const FcChar8 *file_utf8, struct stat *statb)
+{
+    wchar_t * wfile = fc_utf8_to_utf16(file_utf8, CP_UTF8);
+    int ret = FcStatW(wfile, statb);
+    free(wfile);
+    return ret;
+}
+
+#if !defined(__MINGW32__)
+int S_ISDIR(int statb_st_mode)
+{
+    return statb_st_mode & _S_IFDIR;
+}
+#endif
 #else
 
 int
@@ -334,7 +359,7 @@ FcIsFsMmapSafe (int fd)
 FcBool
 FcIsFsMtimeBroken (const FcChar8 *dir)
 {
-    int fd = open ((const char *) dir, O_RDONLY);
+    int fd = fc_open ((const char *) dir, O_RDONLY);
 
     if (fd != -1)
     {
diff --git a/src/fcxml.c b/src/fcxml.c
index 5edc867..08a1115 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -25,8 +25,9 @@
 #include "fcint.h"
 #include <fcntl.h>
 #include <stdarg.h>
+#ifdef HAVE_DIRENT_H
 #include <dirent.h>
-
+#endif
 #ifdef ENABLE_LIBXML2
 
 #include <libxml/parser.h>
@@ -2764,6 +2765,7 @@ FcConfigParseAndLoadDir (FcConfig	*config,
 			 const FcChar8	*dir,
 			 FcBool		complain)
 {
+#ifdef HAVE_DIRENT_H
     DIR		    *d;
     struct dirent   *e;
     FcBool	    ret = FcTrue;
@@ -2771,7 +2773,7 @@ FcConfigParseAndLoadDir (FcConfig	*config,
     FcChar8	    *base;
     FcStrSet	    *files;
 
-    d = opendir ((char *) dir);
+    d = fc_opendir ((char *) dir);
     if (!d)
     {
 	if (complain)
@@ -2801,8 +2803,8 @@ FcConfigParseAndLoadDir (FcConfig	*config,
 
     if (FcDebug () & FC_DBG_CONFIG)
 	printf ("\tScanning config dir %s\n", dir);
-	
-    while (ret && (e = readdir (d)))
+
+    while (ret && (e = fc_readdir (d)))
     {
 	int d_len;
 #define TAIL	    ".conf"
@@ -2836,9 +2838,12 @@ bail3:
 bail2:
     free (file);
 bail1:
-    closedir (d);
+    fc_closedir (d);
 bail0:
     return ret || !complain;
+#else
+#error missing dirent.h
+#endif
 }
 
 #ifdef _WIN32
@@ -2908,7 +2913,7 @@ FcConfigParseAndLoad (FcConfig	    *config,
     if (FcDebug () & FC_DBG_CONFIG)
 	printf ("\tLoading config file %s\n", filename);
 
-    fd = open ((char *) filename, O_RDONLY);
+    fd = fc_open ((char *) filename, O_RDONLY);
     if (fd == -1) {
 	FcStrFree (filename);
 	goto bail0;
_______________________________________________
Fontconfig mailing list
Fontconfig@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/fontconfig

[Index of Archives]     [Fedora Fonts]     [Fedora Users]     [Fedora Cloud]     [Kernel]     [Fedora Packaging]     [Fedora Desktop]     [PAM]     [Gimp Graphics Editor]     [Yosemite News]

  Powered by Linux