c2hs-0.28.3/tests/bugs/issue-123/issue123.h000664 001750 001750 00000000252 13206343576 020123 0ustar00deechdeech000000 000000 #pragma once typedef struct { int a[3]; /* An array of length 3. */ int *p; /* A pointer to an array. */ } array_t; array_t *get_struct(int n, int m, int o); c2hs-0.28.3/tests/bugs/issue-82/include/xlocale/_string.h000664 001750 001750 00000002562 13206343576 023216 0ustar00deechdeech000000 000000 /* * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef _XLOCALE__STRING_H_ #define _XLOCALE__STRING_H_ __BEGIN_DECLS int strcoll_l(const char *, const char *, locale_t); size_t strxfrm_l(char *, const char *, size_t, locale_t); int strcasecmp_l(const char *, const char *, locale_t); char *strcasestr_l(const char *, const char *, locale_t); int strncasecmp_l(const char *, const char *, size_t, locale_t); __END_DECLS #endif /* _XLOCALE__STRING_H_ */ c2hs-0.28.3/tests/bugs/issue-82/include/AvailabilityInternal.h000664 001750 001750 00000042554 13206343576 024236 0ustar00deechdeech000000 000000 /* * Copyright (c) 2007-2009 by Apple Inc.. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* File: AvailabilityInternal.h Contains: implementation details of __OSX_AVAILABLE_* macros from */ #ifndef __AVAILABILITY_INTERNAL__ #define __AVAILABILITY_INTERNAL__ /* if we want to support some compiler that does not support these attributes, we can test for the compiler version before defining these */ #define __AVAILABILITY_INTERNAL_DEPRECATED __attribute__((deprecated,visibility("default"))) #define __AVAILABILITY_INTERNAL_UNAVAILABLE __attribute__((unavailable,visibility("default"))) #define __AVAILABILITY_INTERNAL_WEAK_IMPORT __attribute__((weak_import,visibility("default"))) #define __AVAILABILITY_INTERNAL_REGULAR __attribute__((visibility("default"))) #ifndef __IPHONE_OS_VERSION_MIN_REQUIRED #ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ /* compiler sets __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ when -miphoneos-version-min is used */ #define __IPHONE_OS_VERSION_MIN_REQUIRED __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ #endif #endif #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED /* make sure a default max version is set */ #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_3_0 #endif /* make sure a valid min is set */ #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_0 #undef __IPHONE_OS_VERSION_MIN_REQUIRED #define __IPHONE_OS_VERSION_MIN_REQUIRED __IPHONE_2_0 #endif /* set up internal macros (up to 2.0) */ #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_2_0 #define __AVAILABILITY_INTERNAL__IPHONE_2_0 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_0 #define __AVAILABILITY_INTERNAL__IPHONE_2_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_2_0 __AVAILABILITY_INTERNAL_REGULAR #endif #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_NA __AVAILABILITY_INTERNAL__IPHONE_2_0 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_2_0 __AVAILABILITY_INTERNAL_DEPRECATED /* set up internal macros (up to 2.1) */ #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_2_1 #define __AVAILABILITY_INTERNAL__IPHONE_2_1 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_1 #define __AVAILABILITY_INTERNAL__IPHONE_2_1 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_2_1 __AVAILABILITY_INTERNAL_REGULAR #endif #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_NA __AVAILABILITY_INTERNAL__IPHONE_2_1 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_1 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_2_1 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_2_1 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_2_1 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_2_1 __AVAILABILITY_INTERNAL_DEPRECATED #endif /* set up internal macros (up to 2.2) */ #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_2_2 #define __AVAILABILITY_INTERNAL__IPHONE_2_2 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_2 #define __AVAILABILITY_INTERNAL__IPHONE_2_2 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_2_2 __AVAILABILITY_INTERNAL_REGULAR #endif #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_NA __AVAILABILITY_INTERNAL__IPHONE_2_2 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_1 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_WEAK_IMPORT #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_WEAK_IMPORT #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_2 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_2_2 __AVAILABILITY_INTERNAL_DEPRECATED #endif /* set up internal macros (up to 3.0) */ #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_3_0 #define __AVAILABILITY_INTERNAL__IPHONE_3_0 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_0 #define __AVAILABILITY_INTERNAL__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #endif #define __AVAILABILITY_INTERNAL__IPHONE_3_0_DEP__IPHONE_NA __AVAILABILITY_INTERNAL__IPHONE_3_0 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_1 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #define __AVAILABILITY_INTERNAL__IPHONE_3_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_2_2 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #define __AVAILABILITY_INTERNAL__IPHONE_3_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #elif __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_0 #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_REGULAR #define __AVAILABILITY_INTERNAL__IPHONE_3_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__IPHONE_2_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__IPHONE_2_1_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__IPHONE_2_2_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__IPHONE_3_0_DEP__IPHONE_3_0 __AVAILABILITY_INTERNAL_DEPRECATED #endif /* set up internal macros (n/a) */ #define __AVAILABILITY_INTERNAL__IPHONE_NA __AVAILABILITY_INTERNAL_UNAVAILABLE #define __AVAILABILITY_INTERNAL__IPHONE_NA_DEP__IPHONE_NA __AVAILABILITY_INTERNAL_UNAVAILABLE #elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) /* compiler for Mac OS X sets __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ */ #define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ /* make sure a default max version is set */ #ifndef __MAC_OS_X_VERSION_MAX_ALLOWED #define __MAC_OS_X_VERSION_MAX_ALLOWED __MAC_10_6 #endif /* set up internal macros */ #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_6 #define __AVAILABILITY_INTERNAL__MAC_10_6 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6 #define __AVAILABILITY_INTERNAL__MAC_10_6 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_6 __AVAILABILITY_INTERNAL_REGULAR #endif #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_5 #define __AVAILABILITY_INTERNAL__MAC_10_5 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_5 #define __AVAILABILITY_INTERNAL__MAC_10_5 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_5 __AVAILABILITY_INTERNAL_REGULAR #endif #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_4 #define __AVAILABILITY_INTERNAL__MAC_10_4 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_4 #define __AVAILABILITY_INTERNAL__MAC_10_4 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_4 __AVAILABILITY_INTERNAL_REGULAR #endif #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_3 #define __AVAILABILITY_INTERNAL__MAC_10_3 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_3 #define __AVAILABILITY_INTERNAL__MAC_10_3 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_3 __AVAILABILITY_INTERNAL_REGULAR #endif #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_2 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_2 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_2 __AVAILABILITY_INTERNAL_REGULAR #endif #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_1 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_1 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_1 __AVAILABILITY_INTERNAL_REGULAR #endif #if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_0 __AVAILABILITY_INTERNAL_UNAVAILABLE #elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_0 __AVAILABILITY_INTERNAL_WEAK_IMPORT #else #define __AVAILABILITY_INTERNAL__MAC_10_0 __AVAILABILITY_INTERNAL_REGULAR #endif #define __AVAILABILITY_INTERNAL__MAC_NA __AVAILABILITY_INTERNAL_UNAVAILABLE #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_1 __AVAILABILITY_INTERNAL_DEPRECATED #else #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_1 __AVAILABILITY_INTERNAL__MAC_10_0 #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_2 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_2 __AVAILABILITY_INTERNAL_DEPRECATED #else #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_2 __AVAILABILITY_INTERNAL__MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_2 __AVAILABILITY_INTERNAL__MAC_10_1 #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_3 #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_3 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_3 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_3 __AVAILABILITY_INTERNAL_DEPRECATED #else #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_3 __AVAILABILITY_INTERNAL__MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_3 __AVAILABILITY_INTERNAL__MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_3 __AVAILABILITY_INTERNAL__MAC_10_2 #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_4 #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_4 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_4 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_4 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_4 __AVAILABILITY_INTERNAL_DEPRECATED #else #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_4 __AVAILABILITY_INTERNAL__MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_4 __AVAILABILITY_INTERNAL__MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_4 __AVAILABILITY_INTERNAL__MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_4 __AVAILABILITY_INTERNAL__MAC_10_3 #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_5 #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_5 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_5 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_5 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_5 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_5 __AVAILABILITY_INTERNAL_DEPRECATED #else #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_5 __AVAILABILITY_INTERNAL__MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_5 __AVAILABILITY_INTERNAL__MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_5 __AVAILABILITY_INTERNAL__MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_5 __AVAILABILITY_INTERNAL__MAC_10_3 #define __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_5 __AVAILABILITY_INTERNAL__MAC_10_4 #endif #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_6 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_6 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_6 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_6 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_6 __AVAILABILITY_INTERNAL_DEPRECATED #define __AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_10_6 __AVAILABILITY_INTERNAL_DEPRECATED #else #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_10_6 __AVAILABILITY_INTERNAL__MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_10_6 __AVAILABILITY_INTERNAL__MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_10_6 __AVAILABILITY_INTERNAL__MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_10_6 __AVAILABILITY_INTERNAL__MAC_10_3 #define __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_10_6 __AVAILABILITY_INTERNAL__MAC_10_4 #define __AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_10_6 __AVAILABILITY_INTERNAL__MAC_10_5 #endif #define __AVAILABILITY_INTERNAL__MAC_10_0_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_0 #define __AVAILABILITY_INTERNAL__MAC_10_1_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_1 #define __AVAILABILITY_INTERNAL__MAC_10_2_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_2 #define __AVAILABILITY_INTERNAL__MAC_10_3_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_3 #define __AVAILABILITY_INTERNAL__MAC_10_4_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_4 #define __AVAILABILITY_INTERNAL__MAC_10_5_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_5 #define __AVAILABILITY_INTERNAL__MAC_10_6_DEP__MAC_NA __AVAILABILITY_INTERNAL__MAC_10_6 #define __AVAILABILITY_INTERNAL__MAC_NA_DEP__MAC_NA __AVAILABILITY_INTERNAL_UNAVAILABLE #endif #endif /* __AVAILABILITY_INTERNAL__ */ c2hs-0.28.3/tests/system/marsh/marsh.h000664 001750 001750 00000000112 13206343576 017715 0ustar00deechdeech000000 000000 #ifndef __MARSH_H__ #define __MARSH_H__ int x; #endif /* __MARSH_H__ */ c2hs-0.28.3/tests/bugs/issue-134/Issue134.chs000664 001750 001750 00000000166 13206343576 020421 0ustar00deechdeech000000 000000 module Main where #include "issue134.h" {# pointer *tst as ^ foreign newtype #} main :: IO () main = putStrLn "OK" c2hs-0.28.3/tests/bugs/issue-155/types.h000664 001750 001750 00000000127 13206343576 017717 0ustar00deechdeech000000 000000 typedef struct { int a; } example_struct; typedef struct { int b; } child_struct; c2hs-0.28.3/tests/system/structs/structs.h000664 001750 001750 00000002223 13206343576 020714 0ustar00deechdeech000000 000000 #ifndef __STRUCTS_H__ #define __STRUCTS_H__ typedef char bool, mychar; typedef struct _point *point; int _point(void); struct _point { int x, y; }; int _point(void); typedef struct { struct _point pnt; int col; } *cpoint; typedef struct { bool b; int x; struct { int y, z; point pnt; } nested; } *weird; typedef struct ambiguousName { int x; } ambiguousName; /* same name for struct tag and type */ typedef struct ambiguousName someOtherName; point make_point (int x, int y); weird make_weird (void); mychar *getSpacePtr (void); /* bitfield functionality */ struct bit_struct { char c1; unsigned int bit : 1; signed int very_small_int : 3; char c2; }; struct bit_struct *get_bit_struct(); #ifdef __GNUC__ /* this is to check c2hs's resistance to GNU extensions */ struct _MyStructAlign {long int x;}; struct _MyStruct { int bar; } __attribute__ ((aligned (__alignof (struct _MyStructAlign)))) ; #endif /* __GNUC__ */ /* to test nested struct/unions (regression test) */ typedef struct { int type; int typ1; } FT; typedef union { int type; FT typ1; } SDL_Event; #endif /* __STRUCTS_H__ */ c2hs-0.28.3/tests/bugs/issue-75/sndfile.h000664 001750 001750 00000052240 13206343576 020123 0ustar00deechdeech000000 000000 /* ** Copyright (C) 1999-2011Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 of the License, or ** (at your option) any later version. ** ** 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** sndfile.h -- system-wide definitions ** ** API documentation is in the doc/ directory of the source code tarball ** and at http://www.mega-nerd.com/libsndfile/api.html. */ #ifndef SNDFILE_H #define SNDFILE_H /* This is the version 1.0.X header file. */ #define SNDFILE_1 #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* The following file types can be read and written. ** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise ** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and ** SF_FORMAT_SUBMASK can be used to separate the major and minor file ** types. */ enum { /* Major formats. */ SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ SF_FORMAT_VOC = 0x080000, /* VOC files. */ SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ SF_FORMAT_WVE = 0x190000, /* Psion WVE format */ SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */ SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */ SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */ /* Subtypes from here on. */ SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */ /* Endian-ness options. */ SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ SF_FORMAT_SUBMASK = 0x0000FFFF, SF_FORMAT_TYPEMASK = 0x0FFF0000, SF_FORMAT_ENDMASK = 0x30000000 } ; /* ** The following are the valid command numbers for the sf_command() ** interface. The use of these commands is documented in the file ** command.html in the doc directory of the source code distribution. */ enum { SFC_GET_LIB_VERSION = 0x1000, SFC_GET_LOG_INFO = 0x1001, SFC_GET_CURRENT_SF_INFO = 0x1002, SFC_GET_NORM_DOUBLE = 0x1010, SFC_GET_NORM_FLOAT = 0x1011, SFC_SET_NORM_DOUBLE = 0x1012, SFC_SET_NORM_FLOAT = 0x1013, SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015, SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, SFC_GET_SIMPLE_FORMAT = 0x1021, SFC_GET_FORMAT_INFO = 0x1028, SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, SFC_GET_FORMAT_MAJOR = 0x1031, SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, SFC_GET_FORMAT_SUBTYPE = 0x1033, SFC_CALC_SIGNAL_MAX = 0x1040, SFC_CALC_NORM_SIGNAL_MAX = 0x1041, SFC_CALC_MAX_ALL_CHANNELS = 0x1042, SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, SFC_GET_SIGNAL_MAX = 0x1044, SFC_GET_MAX_ALL_CHANNELS = 0x1045, SFC_SET_ADD_PEAK_CHUNK = 0x1050, SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051, SFC_UPDATE_HEADER_NOW = 0x1060, SFC_SET_UPDATE_HEADER_AUTO = 0x1061, SFC_FILE_TRUNCATE = 0x1080, SFC_SET_RAW_START_OFFSET = 0x1090, SFC_SET_DITHER_ON_WRITE = 0x10A0, SFC_SET_DITHER_ON_READ = 0x10A1, SFC_GET_DITHER_INFO_COUNT = 0x10A2, SFC_GET_DITHER_INFO = 0x10A3, SFC_GET_EMBED_FILE_INFO = 0x10B0, SFC_SET_CLIPPING = 0x10C0, SFC_GET_CLIPPING = 0x10C1, SFC_GET_INSTRUMENT = 0x10D0, SFC_SET_INSTRUMENT = 0x10D1, SFC_GET_LOOP_INFO = 0x10E0, SFC_GET_BROADCAST_INFO = 0x10F0, SFC_SET_BROADCAST_INFO = 0x10F1, SFC_GET_CHANNEL_MAP_INFO = 0x1100, SFC_SET_CHANNEL_MAP_INFO = 0x1101, SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110, /* Support for Wavex Ambisonics Format */ SFC_WAVEX_SET_AMBISONIC = 0x1200, SFC_WAVEX_GET_AMBISONIC = 0x1201, SFC_SET_VBR_ENCODING_QUALITY = 0x1300, /* Following commands for testing only. */ SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, /* ** SFC_SET_ADD_* values are deprecated and will disappear at some ** time in the future. They are guaranteed to be here up to and ** including version 1.0.8 to avoid breakage of existng software. ** They currently do nothing and will continue to do nothing. */ SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, SFC_SET_ADD_DITHER_ON_READ = 0x1071 } ; /* ** String types that can be set and read from files. Not all file types ** support this and even the file types which support one, may not support ** all string types. */ enum { SF_STR_TITLE = 0x01, SF_STR_COPYRIGHT = 0x02, SF_STR_SOFTWARE = 0x03, SF_STR_ARTIST = 0x04, SF_STR_COMMENT = 0x05, SF_STR_DATE = 0x06, SF_STR_ALBUM = 0x07, SF_STR_LICENSE = 0x08, SF_STR_TRACKNUMBER = 0x09, SF_STR_GENRE = 0x10 } ; /* ** Use the following as the start and end index when doing metadata ** transcoding. */ #define SF_STR_FIRST SF_STR_TITLE #define SF_STR_LAST SF_STR_GENRE enum { /* True and false */ SF_FALSE = 0, SF_TRUE = 1, /* Modes for opening files. */ SFM_READ = 0x10, SFM_WRITE = 0x20, SFM_RDWR = 0x30, SF_AMBISONIC_NONE = 0x40, SF_AMBISONIC_B_FORMAT = 0x41 } ; /* Public error values. These are guaranteed to remain unchanged for the duration ** of the library major version number. ** There are also a large number of private error numbers which are internal to ** the library which can change at any time. */ enum { SF_ERR_NO_ERROR = 0, SF_ERR_UNRECOGNISED_FORMAT = 1, SF_ERR_SYSTEM = 2, SF_ERR_MALFORMED_FILE = 3, SF_ERR_UNSUPPORTED_ENCODING = 4 } ; /* Channel map values (used with SFC_SET/GET_CHANNEL_MAP). */ enum { SF_CHANNEL_MAP_INVALID = 0, SF_CHANNEL_MAP_MONO = 1, SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */ SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */ SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */ SF_CHANNEL_MAP_FRONT_LEFT, SF_CHANNEL_MAP_FRONT_RIGHT, SF_CHANNEL_MAP_FRONT_CENTER, SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */ SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */ SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */ SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */ SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */ SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */ SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */ SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */ SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */ SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */ SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */ SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */ SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */ SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */ SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */ SF_CHANNEL_MAP_AMBISONIC_B_W, SF_CHANNEL_MAP_AMBISONIC_B_X, SF_CHANNEL_MAP_AMBISONIC_B_Y, SF_CHANNEL_MAP_AMBISONIC_B_Z, SF_CHANNEL_MAP_MAX } ; /* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ typedef struct SNDFILE_tag SNDFILE ; /* The following typedef is system specific and is defined when libsndfile is ** compiled. sf_count_t will be a 64 bit value when the underlying OS allows ** 64 bit file offsets. ** On windows, we need to allow the same header file to be compiler by both GCC ** and the Microsoft compiler. */ #if (defined (_MSCVER) || defined (_MSC_VER)) typedef __int64 sf_count_t ; #define SF_COUNT_MAX 0x7fffffffffffffffi64 #else typedef int64_t sf_count_t ; #define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL #endif /* A pointer to a SF_INFO structure is passed to sf_open () and filled in. ** On write, the SF_INFO structure is filled in by the user and passed into ** sf_open (). */ struct SF_INFO { sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ int samplerate ; int channels ; int format ; int sections ; int seekable ; } ; typedef struct SF_INFO SF_INFO ; /* The SF_FORMAT_INFO struct is used to retrieve information about the sound ** file formats libsndfile supports using the sf_command () interface. ** ** Using this interface will allow applications to support new file formats ** and encoding types when libsndfile is upgraded, without requiring ** re-compilation of the application. ** ** Please consult the libsndfile documentation (particularly the information ** on the sf_command () interface) for examples of its use. */ typedef struct { int format ; const char *name ; const char *extension ; } SF_FORMAT_INFO ; /* ** Enums and typedefs for adding dither on read and write. ** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE ** and SFC_SET_DITHER_ON_READ. */ enum { SFD_DEFAULT_LEVEL = 0, SFD_CUSTOM_LEVEL = 0x40000000, SFD_NO_DITHER = 500, SFD_WHITE = 501, SFD_TRIANGULAR_PDF = 502 } ; typedef struct { int type ; double level ; const char *name ; } SF_DITHER_INFO ; /* Struct used to retrieve information about a file embedded within a ** larger file. See SFC_GET_EMBED_FILE_INFO. */ typedef struct { sf_count_t offset ; sf_count_t length ; } SF_EMBED_FILE_INFO ; /* ** Structs used to retrieve music sample information from a file. */ enum { /* ** The loop mode field in SF_INSTRUMENT will be one of the following. */ SF_LOOP_NONE = 800, SF_LOOP_FORWARD, SF_LOOP_BACKWARD, SF_LOOP_ALTERNATING } ; typedef struct { int gain ; char basenote, detune ; char velocity_lo, velocity_hi ; char key_lo, key_hi ; int loop_count ; struct { int mode ; unsigned int start ; unsigned int end ; unsigned int count ; } loops [16] ; /* make variable in a sensible way */ } SF_INSTRUMENT ; /* Struct used to retrieve loop information from a file.*/ typedef struct { short time_sig_num ; /* any positive integer > 0 */ short time_sig_den ; /* any positive power of 2 > 0 */ int loop_mode ; /* see SF_LOOP enum */ int num_beats ; /* this is NOT the amount of quarter notes !!!*/ /* a full bar of 4/4 is 4 beats */ /* a full bar of 7/8 is 7 beats */ float bpm ; /* suggestion, as it can be calculated using other fields:*/ /* file's lenght, file's sampleRate and our time_sig_den*/ /* -> bpms are always the amount of _quarter notes_ per minute */ int root_key ; /* MIDI note, or -1 for None */ int future [6] ; } SF_LOOP_INFO ; /* Struct used to retrieve broadcast (EBU) information from a file. ** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. */ #define SF_BROADCAST_INFO_VAR(coding_hist_size) \ struct \ { char description [256] ; \ char originator [32] ; \ char originator_reference [32] ; \ char origination_date [10] ; \ char origination_time [8] ; \ unsigned int time_reference_low ; \ unsigned int time_reference_high ; \ short version ; \ char umid [64] ; \ char reserved [190] ; \ unsigned int coding_history_size ; \ char coding_history [coding_hist_size] ; \ } /* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */ typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ; /* Virtual I/O functionality. */ typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; typedef sf_count_t (*sf_vio_tell) (void *user_data) ; struct SF_VIRTUAL_IO { sf_vio_get_filelen get_filelen ; sf_vio_seek seek ; sf_vio_read read ; sf_vio_write write ; sf_vio_tell tell ; } ; typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ; /* Open the specified file for read, write or both. On error, this will ** return a NULL pointer. To find the error number, pass a NULL SNDFILE ** to sf_strerror (). ** All calls to sf_open() should be matched with a call to sf_close(). */ SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; /* Use the existing file descriptor to create a SNDFILE object. If close_desc ** is TRUE, the file descriptor will be closed when sf_close() is called. If ** it is FALSE, the descritor will not be closed. ** When passed a descriptor like this, the library will assume that the start ** of file header is at the current file offset. This allows sound files within ** larger container files to be read and/or written. ** On error, this will return a NULL pointer. To find the error number, pass a ** NULL SNDFILE to sf_strerror (). ** All calls to sf_open_fd() should be matched with a call to sf_close(). */ SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; /* sf_error () returns a error number which can be translated to a text ** string using sf_error_number(). */ int sf_error (SNDFILE *sndfile) ; /* sf_strerror () returns to the caller a pointer to the current error message for ** the given SNDFILE. */ const char* sf_strerror (SNDFILE *sndfile) ; /* sf_error_number () allows the retrieval of the error string for each internal ** error number. ** */ const char* sf_error_number (int errnum) ; /* The following two error functions are deprecated but they will remain in the ** library for the forseeable future. The function sf_strerror() should be used ** in their place. */ int sf_perror (SNDFILE *sndfile) ; int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ int sf_format_check (const SF_INFO *info) ; /* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses ** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as ** stdio.h function fseek (). ** An offset of zero with whence set to SEEK_SET will position the ** read / write pointer to the first data sample. ** On success sf_seek returns the current position in (multi-channel) ** samples from the start of the file. ** Please see the libsndfile documentation for moving the read pointer ** separately from the write pointer on files open in mode SFM_RDWR. ** On error all of these functions return -1. */ sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; /* Functions for retrieving and setting string data within sound files. ** Not all file types support this features; AIFF and WAV do. For both ** functions, the str_type parameter must be one of the SF_STR_* values ** defined above. ** On error, sf_set_string() returns non-zero while sf_get_string() ** returns NULL. */ int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; const char* sf_get_string (SNDFILE *sndfile, int str_type) ; /* Return the library version string. */ const char * sf_version_string (void) ; /* Functions for reading/writing the waveform data of a sound file. */ sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ; /* Functions for reading and writing the data chunk in terms of frames. ** The number of items actually read/written = frames * number of channels. ** sf_xxxx_raw read/writes the raw data bytes from/to the file ** sf_xxxx_short passes data in the native short format ** sf_xxxx_int passes data in the native int format ** sf_xxxx_float passes data in the native float format ** sf_xxxx_double passes data in the native double format ** All of these read/write function return number of frames read/written. */ sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ; sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ; sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ; sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ; /* Functions for reading and writing the data chunk in terms of items. ** Otherwise similar to above. ** All of these read/write function return number of items read/written. */ sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ; sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ; sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ; /* Close the SNDFILE and clean up all memory allocations associated with this ** file. ** Returns 0 on success, or an error number. */ int sf_close (SNDFILE *sndfile) ; /* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file ** to force the writing of data to disk. If the file is opened SFM_READ ** no action is taken. */ void sf_write_sync (SNDFILE *sndfile) ; /* The function sf_wchar_open() is Windows Only! ** Open a file passing in a Windows Unicode filename. Otherwise, this is ** the same as sf_open(). ** ** In order for this to work, you need to do the following: ** ** #include ** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1 ** #including */ #if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES) SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ; #endif #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* SNDFILE_H */ c2hs-0.28.3/tests/bugs/issue-152/000775 001750 001750 00000000000 13206343576 016377 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-151/000775 001750 001750 00000000000 13206343576 016376 5ustar00deechdeech000000 000000 c2hs-0.28.3/examples/libghttpHS/ghttpHS.h000664 001750 001750 00000000740 13206343576 020261 0ustar00deechdeech000000 000000 /* Auxiliary C code for Ghttp. * * Copyright (c) 1999 Manuel M. T. Chakravarty * * This is required due to the inability of GHC's FFI to pass structures from C * to Haskell. */ #ifndef __GHTTPHS_H__ #define __GHTTPHS_H__ #include /* returns a reference to a newly allocated memory area holding the result of * the corresponding vanilla `libghttp' function */ ghttp_current_status *ghttpHS_get_status (ghttp_request *a_request); #endif /* __GHTTPHS_H__ */ c2hs-0.28.3/tests/bugs/issue-20/Issue20.chs000664 001750 001750 00000000276 13206343576 020247 0ustar00deechdeech000000 000000 module Main where import Foreign.C #include "issue20.h" {#typedef size_t CSize#} {#fun foo {`Int'} -> `CSize'#} main :: IO () main = do s1 <- foo 1 s4 <- foo 4 print $ s4 `div` s1 c2hs-0.28.3/tests/system/structs/structs.c000664 001750 001750 00000001271 13206343576 020711 0ustar00deechdeech000000 000000 #include #include "structs.h" point make_point (int x, int y) { point pnt; pnt = (point) malloc (sizeof (*pnt)); pnt->x = x; pnt->y = y; return pnt; } weird make_weird (void) { weird w; w = (weird) malloc (sizeof (*w)); w->b = ' '; w->x = -1; w->nested.y = 4; w->nested.z = 2; w->nested.pnt = make_point (100, 200); return w; } mychar *getSpacePtr (void) { static char c = ' '; return &c; } struct bit_struct my_bit_struct; struct bit_struct *get_bit_struct() { my_bit_struct.c1 = '\0'; my_bit_struct.bit = 1; my_bit_struct.very_small_int = -1; my_bit_struct.c2 = '\0'; return &my_bit_struct; } c2hs-0.28.3/tests/bugs/issue-83/Issue83.chs000664 001750 001750 00000002341 13206343576 020264 0ustar00deechdeech000000 000000 module Main where import Control.Monad import Foreign.Ptr import Foreign.C.String import Foreign.C.Types #include #include #include -- This is for testing marshalling of C... types, e.g. CInt, etc. {#fun strcmp as ^ {`CString', `CString'} -> `CInt'#} {#fun setenv as ^ {`String', `String', `Int'} -> `Int'#} {#fun getenv as ^ {`String'} -> `CString'#} {#fun sin as hsin {`Double'} -> `Double'#} {#fun sin as csin {`CDouble'} -> `CDouble'#} {#fun malloc as ^ {`CULong'} -> `Ptr ()'#} {#fun free as ^ {`Ptr ()'} -> `()'#} {#fun strcpy as ^ {`CString', `CString'} -> `()'#} main :: IO () main = do let s1 = "abc" ; s2 = "def" ; s3 = "def" res1 <- withCString s1 $ \cs1 -> withCString s2 $ \cs2 -> strcmp cs1 cs2 res2 <- withCString s2 $ \cs2 -> withCString s3 $ \cs3 -> strcmp cs2 cs3 print (res1 < 0, res2 == 0) void $ setenv "TEST_VAR" "TEST_VAL" 1 h <- getenv "TEST_VAR" peekCString h >>= putStrLn cx <- csin 1.0 print (round (10000 * cx) :: Integer) hx <- hsin 1.0 print (round (10000 * hx) :: Integer) let s = "TESTING" p <- malloc $ fromIntegral $ length s + 1 let ps = castPtr p :: CString cs <- newCString s strcpy ps cs res <- peekCString ps putStrLn res free p c2hs-0.28.3/tests/bugs/issue-23/issue23x.h000664 001750 001750 00000000033 13206343576 020146 0ustar00deechdeech000000 000000 enum hello { H1, H2, H3 }; c2hs-0.28.3/tests/bugs/issue-155/000775 001750 001750 00000000000 13206343576 016402 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-83/000775 001750 001750 00000000000 13206343576 016322 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-82/000775 001750 001750 00000000000 13206343576 016321 5ustar00deechdeech000000 000000 c2hs-0.28.3/examples/libghttpHS/ghttpHS.c000664 001750 001750 00000001033 13206343576 020250 0ustar00deechdeech000000 000000 /* Auxiliary C code for Ghttp. * * Copyright (c) 1999 Manuel M. T. Chakravarty * * This is required due to the inability of GHC's FFI to pass structures from C * to Haskell. */ #include "ghttpHS.h" ghttp_current_status *ghttpHS_get_status (ghttp_request *a_request) { ghttp_current_status *status; status = (ghttp_current_status *) malloc (sizeof (ghttp_current_status)); if (!status) { printf ("Ghttp: ghttpHS_get_status: Out of memory!"); exit (1); } *status = ghttp_get_status (a_request); return status; } c2hs-0.28.3/README000664 001750 001750 00000004141 13206343576 013520 0ustar00deechdeech000000 000000 `c2hs` is a interfacing tool that eases Haskell access to C libraries. The tool gets information about the C data type definitions and function signatures by analysing the C header files of the library. It uses this information to compute the missing details in the template of a Haskell module — called the binding file — that implements a Haskell binding to the C library. Hooks embedded in the binding file signal where, which, and how C objects are accessed from Haskell. The Haskell code in the binding file determines Haskell types signatures and marshaling details. Further information is on the [wiki](https://github.com/haskell/c2hs/wiki/Home). Also see the [user guide](https://github.com/haskell/c2hs/wiki/User-Guide) (also available in the `doc` directory of the repository). ## Installing See the file `INSTALL`. ## Copyleft This system 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. This system 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 system; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > **NOTE HOWEVER**, all code included into generated bindings is under > a BSD-style license that does not place any restrictions on the > license of the inteface produced with `c2hs` (ie, closed proprietary > licenses are possible, too). In other words, I do not care what you > use `c2hs` for or to whom you are giving `c2hs` or any interfaces > generated with `c2hs`, only if you modify or improve `c2hs` itself, > you have to contribute your changes back to the community. > Nevertheless, I will of course be particularly delighted if you > choose to make your work freely available. ## Credits See the file `AUTHORS`. c2hs-0.28.3/tests/bugs/issue-80/000775 001750 001750 00000000000 13206343576 016317 5ustar00deechdeech000000 000000 c2hs-0.28.3/regression-suite-vm/run-regression000775 001750 001750 00000000730 13206343576 021477 0ustar00deechdeech000000 000000 #!/bin/bash branch=${1:-master} vagrant up vagrant ssh < #include #include /*#include */ __BEGIN_DECLS /* Removed in Issue 7 */ #if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L int bcmp(const void *, const void *, size_t) __POSIX_C_DEPRECATED(200112L); void bcopy(const void *, void *, size_t) __POSIX_C_DEPRECATED(200112L); void bzero(void *, size_t) __POSIX_C_DEPRECATED(200112L); char *index(const char *, int) __POSIX_C_DEPRECATED(200112L); char *rindex(const char *, int) __POSIX_C_DEPRECATED(200112L); #endif int ffs(int); int strcasecmp(const char *, const char *); int strncasecmp(const char *, const char *, int); __END_DECLS /* Darwin extensions */ #if __DARWIN_C_LEVEL >= __DARWIN_C_FULL __BEGIN_DECLS int ffsl(long) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); int ffsll(long long) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); int fls(int) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); int flsl(long) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0); int flsll(long long) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); __END_DECLS #include #endif #endif /* _STRINGS_H_ */ c2hs-0.28.3/tests/bugs/issue-46/issue46.h000664 001750 001750 00000000222 13206343576 017770 0ustar00deechdeech000000 000000 typedef struct { int a; float b; char dummy; } oid; void func(oid *obj, int aval, float bval); int oid_a(oid *obj); float oid_b(oid *obj); c2hs-0.28.3/tests/bugs/issue-36/Issue36.chs000664 001750 001750 00000000475 13206343576 020266 0ustar00deechdeech000000 000000 module Main where #include "issue36.h" data Hit1 a = Hit1 a data Hit2 a b = Hit2 a b {#pointer *hit_int as HitEg1 -> Hit1 Int#} {#pointer *hit_double as HitEg2 -> Hit1 Double#} {#pointer *hit_int as HitEg3 -> `Hit2 Int ()'#} {#pointer *hit_double as HitEg4 -> `Hit2 Double [Int]'#} main :: IO () main = return () c2hs-0.28.3/src/C2HS/C/Builtin.hs000664 001750 001750 00000004251 13206343576 016254 0ustar00deechdeech000000 000000 -- C->Haskell Compiler: C builtin information -- -- Author : Manuel M. T. Chakravarty -- Created: 12 February 01 -- -- Copyright (c) 2001 Manuel M. T. Chakravarty -- -- This file 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. -- -- This file 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. -- --- DESCRIPTION --------------------------------------------------------------- -- -- This module provides information about builtin entities. -- --- DOCU ---------------------------------------------------------------------- -- -- language: Haskell 98 -- -- Currently, only builtin type names are supported. The only builtin type -- name is `__builtin_va_list', which is a builtin of GNU C. -- --- TODO ---------------------------------------------------------------------- -- module C2HS.C.Builtin ( builtinTypeNames ) where -- Language.C / compiler toolkit import Language.C.Data.Position import Language.C.Data.Ident import Language.C.Syntax import Language.C.Data import C2HS.C.Attrs (CObj(BuiltinCO)) -- | predefined type names -- builtinTypeNames :: [(Ident, CObj)] builtinTypeNames = [(va_list_ide, BuiltinCO $ Just ptrVoidDecl)] where va_list_ide :: Ident va_list_ide = builtinIdent "__builtin_va_list" ptrVoidDecl :: CDecl ptrVoidDecl = CDecl [ CStorageSpec (CTypedef builtin) , CTypeSpec (CVoidType builtin) ] [( Just $ CDeclr (Just va_list_ide) [CPtrDeclr [] builtin] Nothing [] builtin , Nothing , Nothing )] builtin builtin :: NodeInfo builtin = mkNodeInfoOnlyPos builtinPos c2hs-0.28.3/tests/bugs/issue-37/issue37.c000664 001750 001750 00000000150 13206343576 017763 0ustar00deechdeech000000 000000 #include "issue37.h" int f1(int *np) { return *np * 2; } float f2(float *np) { return *np * 3; } c2hs-0.28.3/src/000775 001750 001750 00000000000 13206343576 013427 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-46/issue46.c000664 001750 001750 00000000274 13206343576 017772 0ustar00deechdeech000000 000000 #include "issue46.h" void func(oid *obj, int aval, float bval) { obj->a = aval; obj->b = bval; } int oid_a(oid *obj) { return obj->a; } float oid_b(oid *obj) { return obj->b; } c2hs-0.28.3/tests/bugs/issue-115/issue115.h000664 001750 001750 00000000252 13206343576 020125 0ustar00deechdeech000000 000000 #pragma once typedef struct { int a[3]; /* An array of length 3. */ int *p; /* A pointer to an array. */ } array_t; array_t *get_struct(int n, int m, int o); c2hs-0.28.3/tests/bugs/issue-140/000775 001750 001750 00000000000 13206343576 016374 5ustar00deechdeech000000 000000 c2hs-0.28.3/src/C2HS/Gen/Wrapper.hs000664 001750 001750 00000014660 13206343576 016622 0ustar00deechdeech000000 000000 -- C->Haskell Compiler: custom wrapper generator -- -- Author : Manuel M T Chakravarty -- Created: 5 February 2003 -- -- Copyright (c) 2004 Manuel M T Chakravarty -- -- This file 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. -- -- This file 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. -- --- DESCRIPTION --------------------------------------------------------------- -- -- This module implements the generation of a custom C file to wrap -- functions requiring marshalling of bare C structs to pointers. -- module C2HS.Gen.Wrapper ( genWrappers ) where import Control.Monad -- Language.C / Compiler Toolkit import Language.C.Syntax import Language.C.Pretty import Text.PrettyPrint.HughesPJ (render) import Language.C.Data.Node (undefNode) import Language.C.Data.Position import Language.C.Data.Ident (Ident(..), internalIdent) import Data.DList (DList) import qualified Data.DList as DL -- C->Haskell import C2HS.State (CST, raiseError, throwExc, catchExc, errorsPresent, showErrors, fatal) import C2HS.C.Trav (isPtrDeclr) -- friends import C2HS.Gen.Monad (Wrapper(..)) -- | Generate a custom C wrapper from a CHS binding module for -- functions that require marshalling of bare C structs. -- genWrappers :: [Wrapper] -> CST s [String] genWrappers ws = do wraps <- mapM genWrapper (reverse ws) `ifWrapExc` return [] errs <- errorsPresent if errs then do errmsgs <- showErrors fatal ("Errors during generation of C wrappers:\n\n" ++ errmsgs) else do return $ DL.toList . DL.concat $ wraps -- | Process a single fragment. -- genWrapper :: Wrapper -> CST s (DList String) genWrapper (Wrapper wfn ofn (CDecl specs [(Just decl, _, _)] _) args (boolres, boolargs) pos) = do let renamed = rename (internalIdent wfn) decl wrapdecl <- fixArgs ofn pos args boolargs renamed let fspecs = if boolres then map replaceBoolSpec specs else specs expr <- callBody ofn pos args decl let body = CCompound [] [CBlockStmt (CReturn (Just expr) undefNode)] undefNode wrapfn = CFunDef fspecs wrapdecl [] body undefNode return $ DL.fromList [render (pretty wrapfn) ++ "\n"] genWrapper (Wrapper _ ofn _ _ _ pos) = internalWrapperErr pos ["genWrapper:" ++ ofn] rename :: Ident -> CDeclr -> CDeclr rename ide (CDeclr _ dds str attrs n) = CDeclr (Just ide) dds str attrs n fixArgs :: String -> Position -> [Bool] -> [Bool] -> CDeclr -> CST s CDeclr fixArgs ofn pos args bools (CDeclr ide fd str attrs n) = do fd' <- case fd of [] -> return [] f:fs -> do f' <- fixFunArgs ofn pos args bools f return $ f' : fs return $ CDeclr ide fd' str attrs n fixFunArgs :: String -> Position -> [Bool] -> [Bool] -> CDerivedDeclr -> CST s CDerivedDeclr fixFunArgs ofn pos args bools (CFunDeclr (Right (adecls, flg)) attrs n) = do adecls' <- zipWithM (fixDecl ofn pos) (zip3 args bools [1..]) adecls return $ CFunDeclr (Right (adecls', flg)) attrs n fixFunArgs ofn pos args bools cdecl = internalWrapperErr pos ["fixFunArgs:" ++ ofn, "args=" ++ show args, "bools=" ++ show bools, "cdecl=" ++ show cdecl] replaceBool :: CDecl -> CDecl replaceBool (CDecl spec ds n) = CDecl (map replaceBoolSpec spec) ds n replaceBoolSpec :: CDeclSpec -> CDeclSpec replaceBoolSpec (CTypeSpec (CBoolType tn)) = CTypeSpec (CIntType tn) replaceBoolSpec t = t fixDecl :: String -> Position -> (Bool, Bool, Int) -> CDecl -> CST s CDecl fixDecl _ _ (False, True, idx) d = return $ replaceBool $ fixEmpty d idx fixDecl _ _ (False, False, idx) d = return $ fixEmpty d idx fixDecl _ pos (True, _, idx) din = do let (CDecl specs [(Just decl, Nothing, Nothing)] n) = fixEmpty din idx decl' <- addPtr pos decl return $ CDecl specs [(Just decl', Nothing, Nothing)] n fixEmpty :: CDecl -> Int -> CDecl fixEmpty d@(CDecl _ [(Just _, Nothing, Nothing)] _) _ = d fixEmpty (CDecl ss [] n) idx = let d = CDeclr (Just $ internalIdent $ "c2hs__dummy_arg_" ++ show idx) [] Nothing [] n in CDecl ss [(Just d, Nothing, Nothing)] n addPtr :: Position -> CDeclr -> CST s CDeclr addPtr _ (CDeclr ide [] cs attrs n) = return $ CDeclr ide [CPtrDeclr [] n] cs attrs n addPtr pos cdecl = if isPtrDeclr cdecl then wrapperOnPointerErr pos else invalidWrapperErr pos callBody :: String -> Position -> [Bool] -> CDeclr -> CST s CExpr callBody fn pos args (CDeclr _ (fd:_) _ _ n) = do as <- zipWithM (makeArg pos) (zip args [1..]) (funArgs fd) return $ CCall (CVar (internalIdent fn) n) as n makeArg :: Position -> (Bool, Int) -> CDecl -> CST s CExpr makeArg _ (arg, _) (CDecl _ [(Just (CDeclr (Just i) _ _ _ _), _, _)] n) = return $ case arg of False -> CVar i n True -> CUnary CIndOp (CVar i n) n makeArg _ (arg, idx) (CDecl _ [] n) = let i = internalIdent $ "c2hs__dummy_arg_" ++ show idx in return $ case arg of False -> CVar i n True -> CUnary CIndOp (CVar i n) n makeArg pos (arg, idx) cdecl = internalWrapperErr pos ["makeArg:arg=" ++ show arg, "cdecl=" ++ show cdecl, "idx=" ++ show idx] funArgs :: CDerivedDeclr -> [CDecl] funArgs (CFunDeclr (Right (adecls, _)) _ _) = adecls throwWrapExc :: CST s a throwWrapExc = throwExc "wrapExc" "Error during wrapper generation" ifWrapExc :: CST s a -> CST s a -> CST s a ifWrapExc m handler = m `catchExc` ("wrapExc", const handler) raiseErrorWrapper :: Position -> [String] -> CST s a raiseErrorWrapper pos errs = raiseError pos errs >> throwWrapExc internalWrapperErr :: Position -> [String] -> CST s a internalWrapperErr pos msg = raiseErrorWrapper pos $ ["Internal wrapper error!", "Something went wrong generating a bare structure wrapper."] ++ msg wrapperOnPointerErr :: Position -> CST s a wrapperOnPointerErr pos = raiseErrorWrapper pos $ ["Bare structure wrapper error!", "Are you trying to put a wrapper on a pointer type?"] invalidWrapperErr :: Position -> CST s a invalidWrapperErr pos = raiseErrorWrapper pos $ ["Bare structure wrapper error!", "Invalid bare structure wrapper"] c2hs-0.28.3/tests/bugs/issue-128/issue128.h000664 001750 001750 00000000357 13206343576 020143 0ustar00deechdeech000000 000000 #include int f1(int n, bool incr); bool f2(int n); typedef struct { int a; bool b; } tststruct; tststruct *make_tststruct(int ain); void free_tststruct(tststruct *s); void mod_tststruct(tststruct *s, int da, bool incr); c2hs-0.28.3/tests/bugs/issue-75/Issue75.chs000664 001750 001750 00000000425 13206343576 020267 0ustar00deechdeech000000 000000 module Main where {#context prefix="chk"#} #include "issue75.h" data TstStruct = TstStruct { a :: Int } {#pointer *TST as TstPtr -> TstStruct#} {#fun make_tst as ^ {} -> `TstPtr'#} main :: IO () main = do s <- makeTst aval <- {#get CHK_TST.a#} s putStrLn $ show aval c2hs-0.28.3/tests/bugs/issue-115/issue115.c000664 001750 001750 00000000447 13206343576 020126 0ustar00deechdeech000000 000000 #include "issue115.h" array_t myStruct; int other_a[3]; array_t *get_struct(int n, int m, int o) { myStruct.a[0] = n; myStruct.a[1] = m; myStruct.a[2] = o; other_a[0] = n + 1; other_a[1] = m + 1; other_a[2] = o + 1; myStruct.p = other_a; return &myStruct; } c2hs-0.28.3/src/Text/Lexers.hs000664 001750 001750 00000045357 13206343576 016167 0ustar00deechdeech000000 000000 -- Compiler Toolkit: Self-optimizing lexers -- -- Author : Manuel M. T. Chakravarty -- Created: 2 March 99 -- -- Copyright (c) 1999 Manuel M. T. Chakravarty -- -- This library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Library General Public -- License as published by the Free Software Foundation; either -- version 2 of the License, or (at your option) any later version. -- -- This library 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 -- Library General Public License for more details. -- --- DESCRIPTION --------------------------------------------------------------- -- -- Self-optimizing lexer combinators. -- -- For detailed information, see ``Lazy Lexing is Fast'', Manuel -- M. T. Chakravarty, in A. Middeldorp and T. Sato, editors, Proceedings of -- Fourth Fuji International Symposium on Functional and Logic Programming, -- Springer-Verlag, LNCS 1722, 1999. (See my Web page for details.) -- -- Thanks to Simon L. Peyton Jones and Roman -- Lechtchinsky for their helpful suggestions that -- improved the design of this library. -- --- DOCU ---------------------------------------------------------------------- -- -- language: Haskell 98 -- -- The idea is to combine the benefits of off-line generators with -- combinators like in `Parsers.hs' (which builds on Swierstra/Duponcheel's -- technique for self-optimizing parser combinators). In essence, a state -- transition graph representing a lexer table is computed on the fly, to -- make lexing deterministic and based on cheap table lookups. -- -- Regular expression map to Haskell expressions as follows. If `x' and `y' -- are regular expressions, -- -- -> epsilon -- xy -> x +> y -- x*y -> x `star` y -- x+y -> x `plus` y -- x?y -> x `quest` y -- -- Given such a Haskelized regular expression `hre', we can use -- -- (1) hre `lexaction` \lexeme -> Nothing -- (2) hre `lexaction` \lexeme -> Just token -- (3) hre `lexmeta` \lexeme pos s -> (res, pos', s', Nothing) -- (4) hre `lexmeta` \lexeme pos s -> (res, pos', s', Just l) -- -- where `epsilon' is required at the end of `hre' if it otherwise ends on -- `star', `plus', or `quest', and then, we have -- -- (1) discards `lexeme' accepted by `hre', -- (2) turns the `lexeme' accepted by `hre' into a token, -- (3) while discarding the lexeme accepted by `hre', transforms the -- position and/or user state, and -- (4) while discarding the lexeme accepted by `hre', transforms the -- position and/or user state and returns a lexer to be used for the -- next lexeme. -- -- The component `res' in case of a meta action, can be `Nothing', `Just -- (Left err)', or `Just (Right token)' to return nothing, an error, or a -- token from a meta action, respectively. -- -- * By adding `ctrlLexer', `Positions' are properly handled in the presence -- of layout control characters. -- -- * This module makes essential use of graphical data structures (for -- representing the state transition graph) and laziness (for maintaining -- the last action in `execLexer'. -- -- NOTES: -- -- * In this implementation, the combinators `quest`, `star`, and `plus` are -- *right* associative - this was different in the ``Lazy Lexing is Fast'' -- paper. This change was made on a suggestion by Martin Norbäck -- . -- --- TODO ---------------------------------------------------------------------- -- -- * error correction is missing -- -- * in (>||<) in the last case, `(addBoundsNum bn bn')' is too simple, as -- the number of outgoing edges is not the sum of the numbers of the -- individual states when there are conflicting edges, ie, ones labeled -- with the same character; however, the number is only used to decide a -- heuristic, so it is questionable whether it is worth spending the -- additional effort of computing the accurate number -- -- * Unicode posses a problem as the character domain becomes too big for -- using arrays to represent transition tables and even sparse structures -- will posse a significant overhead when character ranges are naively -- represented. So, it might be time for finite maps again. -- -- Regarding the character ranges, there seem to be at least two -- possibilities. Doaitse explicitly uses ranges and avoids expanding -- them. The problem with this approach is that we may only have -- predicates such as `isAlphaNum' to determine whether a givne character -- belongs to some character class. From this representation it is -- difficult to efficiently compute a range. The second approach, as -- proposed by Tom Pledger (on the Haskell list) -- would be to actually use predicates directly and make the whole business -- efficient by caching predicate queries. In other words, for any given -- character after we have determined (in a given state) once what the -- following state on accepting that character is, we need not consult the -- predicates again if we memorise the successor state the first time -- around. -- -- * Ken Shan writes ``Section 4.3 of your paper -- computes the definition -- -- re1 `star` re2 = \l' -> let self = re1 self >||< re2 l' in self -- -- If we let re2 = epsilon, we get -- -- many :: Regexp s t -> Regexp s t -- many re = \l' -> let self = re1 self >||< l' in self -- -- since epsilon = id.'' This should actually be as good as the current -- definiton and it might be worthwhile to offer it as a variant. -- module Text.Lexers (Regexp, Lexer, Action, epsilon, char, (+>), lexaction, lexactionErr, lexmeta, (>|<), (>||<), ctrlChars, ctrlLexer, star, plus, quest, alt, string, LexerState, execLexer) where import Data.Maybe (fromMaybe) import Data.Array (Array, (!), assocs, accumArray) import Language.C.Data.Position import qualified Data.DList as DL import Data.Errors (interr, ErrorLevel(..), Error, makeError) infixr 4 `quest`, `star`, `plus` infixl 3 +>, `lexaction`, `lexmeta` infixl 2 >|<, >||< -- constants -- --------- -- | we use the dense representation if a table has at least the given number of -- (non-error) elements -- denseMin :: Int denseMin = 20 -- data structures -- --------------- -- | represents the number of (non-error) elements and the bounds of a table -- type BoundsNum = (Int, Char, Char) -- | combine two bounds -- addBoundsNum :: BoundsNum -> BoundsNum -> BoundsNum addBoundsNum (n, lc, hc) (n', lc', hc') = (n + n', min lc lc', max hc hc') -- | check whether a character is in the bounds -- inBounds :: Char -> BoundsNum -> Bool inBounds c (_, lc, hc) = c >= lc && c <= hc -- | Lexical actions take a lexeme with its position and may return a token; in -- a variant, an error can be returned -- -- * if there is no token returned, the current lexeme is discarded lexing -- continues looking for a token -- type Action t = String -> Position -> Maybe t type ActionErr t = String -> Position -> Either Error t -- | Meta actions transform the lexeme, position, and a user-defined state; they -- may return a lexer, which is then used for accepting the next token (this -- is important to implement non-regular behaviour like nested comments) -- type Meta s t = String -> Position -> s -> (Maybe (Either Error t), -- err/tok? Position, -- new pos s, -- state Maybe (Lexer s t)) -- lexer? -- | tree structure used to represent the lexer table -- -- * each node in the tree corresponds to a state of the lexer; the associated -- actions are those that apply when the corresponding state is reached -- data Lexer s t = Lexer (LexAction s t) (Cont s t) -- | represent the continuation of a lexer -- data Cont s t = -- on top of the tree, where entries are dense, we use arrays -- Dense BoundsNum (Array Char (Lexer s t)) -- -- further down, where the valid entries are sparse, we -- use association lists, to save memory (the first argument -- is the length of the list) -- | Sparse BoundsNum [(Char, Lexer s t)] -- -- end of a automaton -- | Done -- deriving Show -- | lexical action -- data LexAction s t = Action (Meta s t) | NoAction -- deriving Show -- | a regular expression -- type Regexp s t = Lexer s t -> Lexer s t -- basic combinators -- ----------------- -- | Empty lexeme -- epsilon :: Regexp s t epsilon = id -- | One character regexp -- char :: Char -> Regexp s t char c = \l -> Lexer NoAction (Sparse (1, c, c) [(c, l)]) -- | Concatenation of regexps -- (+>) :: Regexp s t -> Regexp s t -> Regexp s t (+>) = (.) -- | Close a regular expression with an action that converts the lexeme into a -- token -- -- * Note: After the application of the action, the position is advanced -- according to the length of the lexeme. This implies that normal -- actions should not be used in the case where a lexeme might contain -- control characters that imply non-standard changes of the position, -- such as newlines or tabs. -- lexaction :: Regexp s t -> Action t -> Lexer s t lexaction re a = re `lexmeta` a' where a' lexeme pos s = let pos' = incPos pos (length lexeme) in pos' `seq` case a lexeme pos of Nothing -> (Nothing, pos', s, Nothing) Just t -> (Just (Right t), pos', s, Nothing) -- | Variant for actions that may returns an error -- lexactionErr :: Regexp s t -> ActionErr t -> Lexer s t lexactionErr re a = re `lexmeta` a' where a' lexeme pos s = let pos' = incPos pos (length lexeme) in pos' `seq` (Just (a lexeme pos), pos', s, Nothing) -- | Close a regular expression with a meta action -- -- * Note: Meta actions have to advance the position in dependence of the -- lexeme by themselves. -- lexmeta :: Regexp s t -> Meta s t -> Lexer s t lexmeta re a = re (Lexer (Action a) Done) -- | disjunctive combination of two regexps -- (>|<) :: Regexp s t -> Regexp s t -> Regexp s t re >|< re' = \l -> re l >||< re' l -- | disjunctive combination of two lexers -- (>||<) :: Lexer s t -> Lexer s t -> Lexer s t (Lexer a c) >||< (Lexer a' c') = Lexer (joinActions a a') (joinConts c c') -- | combine two disjunctive continuations -- joinConts :: Cont s t -> Cont s t -> Cont s t joinConts Done c' = c' joinConts c Done = c joinConts c c' = let (bn , cls ) = listify c (bn', cls') = listify c' in -- note: `addsBoundsNum' can, at this point, only -- approx. the number of *non-overlapping* cases; -- however, the bounds are correct -- aggregate (addBoundsNum bn bn') (cls ++ cls') where listify (Dense n arr) = (n, assocs arr) listify (Sparse n cls) = (n, cls) listify _ = interr "Lexers.listify: Impossible argument!" -- | combine two actions -- joinActions :: LexAction s t -> LexAction s t -> LexAction s t joinActions NoAction a' = a' joinActions a NoAction = a joinActions _ _ = interr "Lexers.>||<: Overlapping actions!" -- | Note: `n' is only an upper bound of the number of non-overlapping cases -- aggregate :: BoundsNum -> ([(Char, Lexer s t)]) -> Cont s t aggregate bn@(n, lc, hc) cls | n >= denseMin = Dense bn (accumArray (>||<) noLexer (lc, hc) cls) | otherwise = Sparse bn (accum (>||<) cls) where noLexer = Lexer NoAction Done -- | combine the elements in the association list that have the same key -- accum :: Eq a => (b -> b -> b) -> [(a, b)] -> [(a, b)] accum _ [] = [] accum f ((k, e):kes) = let (ke, kes') = gather k e kes in ke : accum f kes' where gather k' e' [] = ((k', e'), []) gather k' e' (ke'@(k'2, e'2):kes') | k' == k'2 = gather k' (f e' e'2) kes' | otherwise = let (ke'2, kes'2) = gather k' e' kes' in (ke'2, ke':kes'2) -- handling of control characters -- ------------------------------ -- | control characters recognized by `ctrlLexer' -- ctrlChars :: [Char] ctrlChars = ['\n', '\r', '\f', '\t'] -- | control lexer -- -- * implements proper `Position' management in the presence of the standard -- layout control characters -- ctrlLexer :: Lexer s t ctrlLexer = char '\n' `lexmeta` newline >||< char '\r' `lexmeta` newline >||< char '\v' `lexmeta` newline >||< char '\f' `lexmeta` formfeed >||< char '\t' `lexmeta` tab where newline _ pos s = (Nothing, retPos pos , s, Nothing) formfeed _ pos s = (Nothing, incPos pos 1, s, Nothing) tab _ pos s = (Nothing, incPos pos 8, s, Nothing) -- non-basic combinators -- --------------------- -- | x `star` y corresponds to the regular expression x*y -- star :: Regexp s t -> Regexp s t -> Regexp s t -- -- The definition used below can be obtained by equational reasoning from this -- one (which is much easier to understand): -- -- star re1 re2 = let self = (re1 +> self >|< epsilon) in self +> re2 -- -- However, in the above, `self' is of type `Regexp s t' (ie, a functional), -- whereas below it is of type `Lexer s t'. Thus, below we have a graphical -- body (finite representation of an infinite structure), which doesn't grow -- with the size of the accepted lexeme - in contrast to the definition using -- the functional recursion. -- star re1 re2 = \l -> let self = re1 self >||< re2 l in self -- | x `plus` y corresponds to the regular expression x+y -- plus :: Regexp s t -> Regexp s t -> Regexp s t plus re1 re2 = re1 +> (re1 `star` re2) -- | x `quest` y corresponds to the regular expression x?y -- quest :: Regexp s t -> Regexp s t -> Regexp s t quest re1 re2 = (re1 +> re2) >|< re2 -- | accepts a non-empty set of alternative characters -- alt :: [Char] -> Regexp s t -- -- Equiv. to `(foldr1 (>|<) . map char) cs', but much faster -- alt [] = interr "Lexers.alt: Empty character set!" alt cs = \l -> let bnds = (length cs, minimum cs, maximum cs) in Lexer NoAction (aggregate bnds [(c, l) | c <- cs]) -- | accept a character sequence -- string :: String -> Regexp s t string [] = interr "Lexers.string: Empty character set!" string cs = (foldr1 (+>) . map char) cs -- execution of a lexer -- -------------------- -- | threaded top-down during lexing (current input, current position, meta -- state) -- type LexerState s = (String, Position, s) -- | apply a lexer, yielding a token sequence and a list of errors -- -- * Currently, all errors are fatal; thus, the result is undefined in case of -- an error (this changes when error correction is added). -- -- * The final lexer state is returned. -- -- * The order of the error messages is undefined. -- execLexer :: Lexer s t -> LexerState s -> ([t], LexerState s, [Error]) -- -- * the following is moderately tuned -- execLexer _ state@([], _, _) = ([], state, []) execLexer l state = case lexOne l state of (Nothing , _ , state') -> execLexer l state' (Just res, l', state') -> let (ts, final, allErrs) = execLexer l' state' in case res of (Left err) -> (ts , final, err:allErrs) (Right t ) -> (t:ts, final, allErrs) where -- accept a single lexeme -- -- lexOne :: Lexer s t -> LexerState s t -- -> (Either Error (Maybe t), Lexer s t, LexerState s t) lexOne l0 state' = oneLexeme l0 state' DL.empty lexErr where -- the result triple of `lexOne' that signals a lexical error; -- the result state is advanced by one character for error correction -- lexErr = let (cs, pos, s) = state' err = makeError LevelError pos ["Lexical error!", "The character " ++ show (head cs) ++ " does not fit here; skipping it."] in (Just (Left err), l, (tail cs, incPos pos 1, s)) -- we take an open list of characters down, where we accumulate the -- lexeme; this function returns maybe a token, the next lexer to use -- (can be altered by a meta action), the new lexer state, and a list -- of errors -- -- we implement the "principle of the longest match" by taking a -- potential result quadruple down (in the last argument); the -- potential result quadruple is updated whenever we pass by an action -- (different from `NoAction'); initially it is an error result -- -- oneLexeme :: Lexer s t -- -> LexerState -- -> DList Char -- -> (Maybe (Either Error t), Maybe (Lexer s t), -- LexerState s t) -- -> (Maybe (Either Error t), Maybe (Lexer s t), -- LexerState s t) oneLexeme (Lexer a cont') state''@(cs, pos, s) csDL last' = let last'' = action a csDL state'' last' in case cs of [] -> last'' (c:cs') -> oneChar cont' c (cs', pos, s) csDL last'' oneChar Done _ _ _ last' = last' oneChar (Dense bn arr) c state'' csDL last' | c `inBounds` bn = cont (arr!c) c state'' csDL last' | otherwise = last' oneChar (Sparse bn cls) c state'' csDL last' | c `inBounds` bn = case lookup c cls of Nothing -> last' Just l' -> cont l' c state'' csDL last' | otherwise = last' -- continue within the current lexeme -- cont l' c state'' csDL last' = oneLexeme l' state'' (csDL `DL.snoc` c) last' -- execute the action if present and finalise the current lexeme -- action (Action f) csDL (cs, pos, s) _last = case f (DL.toList csDL) pos s of (Nothing, pos', s', l') | not . null $ cs -> lexOne (fromMaybe l0 l') (cs, pos', s') (res , pos', s', l') -> (res, (fromMaybe l0 l'), (cs, pos', s')) action NoAction _csDL _state last' = last' -- no change c2hs-0.28.3/src/C2HS/State.hs000664 001750 001750 00000006133 13206343576 015545 0ustar00deechdeech000000 000000 -- C -> Haskell Compiler: C2HS's state -- -- Author : Manuel M. T. Chakravarty -- Created: 6 March 1999 -- -- Copyright (c) 1999 Manuel M. T. Chakravarty -- -- This file 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. -- -- This file 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. -- --- DESCRIPTION --------------------------------------------------------------- -- -- This module instantiates the Compiler Toolkit's extra state with C2HS's -- uncommon state information that should be stored in the Toolkit's base -- state. -- -- This modules re-exports everything provided by `State', and thus, should be -- used as the single reference to state related functionality within C2HS. -- --- DOCU ---------------------------------------------------------------------- -- -- language: Haskell 98 -- -- State components: -- -- - compiler switches -- --- TODO ---------------------------------------------------------------------- -- module C2HS.State (-- re-exports all of `State' -- module Control.State, -- -- instantiation of `PreCST' with C2HS's extra state -- CST, runC2HS, -- -- switches -- SwitchBoard(..), Traces(..), setTraces, traceSet, putTraceStr, setSwitch, getSwitch) where import Control.Monad (when) import System.IO (stderr) import Control.State import qualified System.CIO as CIO import C2HS.Switches (SwitchBoard(..), Traces(..), initialSwitchBoard) -- instantiation of the extra state -- -------------------------------- -- | the extra state consists of the `SwitchBoard' -- type CST s a = PreCST SwitchBoard s a -- | execution of c2hs starts with the initial `SwitchBoard' -- runC2HS :: CST () a -> IO a runC2HS = run initialSwitchBoard -- switch management -- ----------------- -- | set traces according to the given transformation function -- setTraces :: (Traces -> Traces) -> CST s () setTraces t = updExtra (\es -> es {tracesSB = t (tracesSB es)}) -- | inquire the status a trace using the given inquiry function -- traceSet :: (Traces -> Bool) -> CST s Bool traceSet t = readExtra (t . tracesSB) -- | output the given string to `stderr' when the trace determined by the inquiry -- function is activated -- putTraceStr :: (Traces -> Bool) -> String -> CST s () putTraceStr t msg = do set <- traceSet t when set $ CIO.hPutStr stderr msg -- | set a switch value -- setSwitch :: (SwitchBoard -> SwitchBoard) -> CST s () setSwitch = updExtra -- | get a switch values -- getSwitch :: (SwitchBoard -> a) -> CST s a getSwitch = readExtra c2hs-0.28.3/src/Data/NameSpaces.hs000664 001750 001750 00000013550 13206343576 016657 0ustar00deechdeech000000 000000 -- Compiler Toolkit: name space management -- -- Author : Manuel M. T. Chakravarty -- Created: 12 November 95 -- -- Copyright (c) [1995..1999] Manuel M. T. Chakravarty -- -- This file 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. -- -- This file 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. -- --- DESCRIPTION --------------------------------------------------------------- -- -- This module manages name spaces. -- --- DOCU ---------------------------------------------------------------------- -- -- language: Haskell 98 -- -- * A name space associates identifiers with their definition. -- -- * Each name space is organized in a hierarchical way using the notion of -- ranges. A name space, at any moment, always has a global range and may -- have several local ranges. Definitions in inner ranges hide definitions -- of the same identifiert in outer ranges. -- --- TODO ---------------------------------------------------------------------- -- -- * evaluate the performance gain that a hashtable would bring -- module Data.NameSpaces (NameSpace, nameSpace, defGlobal, enterNewRange, leaveRange, defLocal, find, nameSpaceToList) where import qualified Data.Map as Map (empty, insert, lookup, toList) import Data.Map (Map) import Language.C.Data.Ident import Data.Errors (interr) -- | name space -- -- * the definitions in the global ranges are stored in a finite map, because -- they tend to be a lot and are normally not updated after the global range -- is constructed -- -- * the definitions of the local ranges are stored in a single list, usually -- they are not very many and the definitions entered last are the most -- frequently accessed ones; the list structure naturally hides older -- definitions, i.e., definitions from outer ranges; adding new definitions -- is done in time proportinal to the current size of the range; removing a -- range is done in constant time (and the definitions of a range can be -- returned as a result of leaving the range); lookup is proportional to the -- number of definitions in the local ranges and the logarithm of the number -- of definitions in the global range---i.e., efficiency relies on a -- relatively low number of local definitions together with frequent lookup -- of the most recently defined local identifiers -- data NameSpace a = NameSpace (Map Ident a) -- defs in global range [[(Ident, a)]] -- stack of local ranges instance (Show a) => Show (NameSpace a) where show = show . nameSpaceToList -- | create a name space -- nameSpace :: NameSpace a nameSpace = NameSpace Map.empty [] -- | add global definition -- -- * returns the modfied name space -- -- * if the identfier is already declared, the resulting name space contains -- the new binding and the second component of the result contains the -- definition declared previously (which is henceforth not contained in the -- name space anymore) -- defGlobal :: NameSpace a -> Ident -> a -> (NameSpace a, Maybe a) defGlobal (NameSpace gs lss) ide def = (NameSpace (Map.insert ide def gs) lss, Map.lookup ide gs) -- | add new range -- enterNewRange :: NameSpace a -> NameSpace a enterNewRange (NameSpace gs lss) = NameSpace gs ([]:lss) -- | pop topmost range and return its definitions -- leaveRange :: NameSpace a -> (NameSpace a, [(Ident, a)]) leaveRange (NameSpace _gs []) = interr "NameSpaces.leaveRange: \ \No local range!" leaveRange (NameSpace gs (ls:lss)) = (NameSpace gs lss, ls) -- | add local definition -- -- * returns the modfied name space -- -- * if there is no local range, the definition is entered globally -- -- * if the identfier is already declared, the resulting name space contains -- the new binding and the second component of the result contains the -- definition declared previously (which is henceforth not contained in the -- name space anymore) -- defLocal :: NameSpace a -> Ident -> a -> (NameSpace a, Maybe a) defLocal ns@(NameSpace _ [] ) ide def = defGlobal ns ide def defLocal (NameSpace gs (ls:lss)) ide def = (NameSpace gs (((ide, def):ls):lss), lookup' ls) where lookup' [] = Nothing lookup' ((ide', def'):ls') | ide == ide' = Just def' | otherwise = lookup' ls' -- | search for a definition -- -- * the definition from the innermost range is returned, if any -- find :: NameSpace a -> Ident -> Maybe a find (NameSpace gs lss) ide = case (lookup' lss) of Nothing -> Map.lookup ide gs Just def -> Just def where lookup' [] = Nothing lookup' (ls:lss') = case (lookup'' ls) of Nothing -> lookup' lss' Just def -> Just def lookup'' [] = Nothing lookup'' ((ide', def):ls) | ide' == ide = Just def | otherwise = lookup'' ls -- | dump a name space into a list -- -- * local ranges are concatenated -- nameSpaceToList :: NameSpace a -> [(Ident, a)] nameSpaceToList (NameSpace gs lss) = Map.toList gs ++ concat lss c2hs-0.28.3/tests/bugs/issue-130/Issue130.chs000664 001750 001750 00000000550 13206343576 020406 0ustar00deechdeech000000 000000 module Main where import Foreign.C.Types import Foreign.Marshal.Alloc import Foreign.Storable #include "issue130.h" main :: IO () main = do print (myAdd 1 2) print =<< myAddIO 1 2 {#fun pure unsafe my_add as myAdd {`CInt', `CInt', alloca- `CInt' peek* } -> `()'#} {#fun unsafe my_add as myAddIO {`CInt', `CInt', alloca- `CInt' peek* } -> `()'#} c2hs-0.28.3/src/C2HS/Gen/Monad.hs000664 001750 001750 00000053401 13206343576 016234 0ustar00deechdeech000000 000000 {-# OPTIONS_GHC -fno-warn-orphans #-} -- C->Haskell Compiler: monad for the binding generator -- -- Author : Manuel M T Chakravarty -- Derived: 18 February 2 (extracted from GenBind.hs) -- -- Copyright (c) [2002..2005] Manuel M T Chakravarty -- -- This file 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. -- -- This file 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. -- --- DESCRIPTION --------------------------------------------------------------- -- -- This modules defines the monad and related utility routines for the code -- that implements the expansion of the binding hooks. -- --- DOCU ---------------------------------------------------------------------- -- -- language: Haskell 98 -- -- Translation table handling for enumerators: -- ------------------------------------------- -- -- First a translation table lookup on the original identifier of the -- enumerator is done. If that doesn't match and the prefix can be removed -- from the identifier, a second lookup on the identifier without the prefix -- is performed. If this also doesn't match, the identifier without prefix -- (possible after underscoreToCase or similar translation is returned). If -- there is a match, the translation (without any further stripping of -- prefix) is returned. -- -- Pointer map -- ----------- -- -- Pointer hooks allow the use to customise the Haskell types to which C -- pointer types are mapped. The globally maintained map essentially maps C -- pointer types to Haskell pointer types. The representation of the Haskell -- types is defined by the `type' or `newtype' declaration emitted by the -- corresponding pointer hook. However, the map stores a flag that tells -- whether the C type is itself the pointer type in question or whether it is -- pointers to this C type that should be mapped as specified. The pointer -- map is dumped into and read from `.chi' files. -- -- Haskell object map -- ------------------ -- -- Some features require information about Haskell objects defined by c2hs. -- Therefore, the Haskell object map maintains the necessary information -- about these Haskell objects. The Haskell object map is dumped into and -- read from `.chi' files. -- -- Enumeration map -- --------------- -- -- Map maintaining information about enum hooks for use in generation -- of default marshalling code. -- --- TODO ---------------------------------------------------------------------- -- -- * Look up in translation tables is naive - this probably doesn't affect -- costs much, but at some point a little profiling might be beneficial. -- module C2HS.Gen.Monad ( TransFun, transTabToTransFun, HsObject(..), Wrapper(..), GB, GBState(..), initialGBState, setContext, getLibrary, getPrefix, getReplacementPrefix, delayCode, getDelayedCode, ptrMapsTo, queryPtr, objIs, queryObj, sizeIs, querySize, queryClass, queryPointer, mergeMaps, dumpMaps, queryEnum, isEnum, queryTypedef, isC2HSTypedef, queryDefaultMarsh, isDefaultMarsh, addWrapper, getWrappers, addHsDependency, getHsDependencies ) where -- standard libraries import Data.Char (toUpper, toLower) import Data.List (find) import Data.Maybe (fromMaybe) import qualified Data.Map as Map (empty, insert, lookup, union, toList, fromList) import Data.Map (Map) import Data.Set (Set) import qualified Data.Set as Set (empty, insert, member, union, toList, fromList) -- Language.C import Language.C.Data.Position import Language.C.Data.Ident import Language.C.Syntax import Data.Errors -- C -> Haskell import C2HS.C (CT, readCT, transCT, raiseErrorCTExc) -- friends import C2HS.CHS (CHSFrag(..), CHSHook(..), CHSTrans(..), CHSChangeCase(..), CHSPtrType(..), CHSTypedefInfo, CHSDefaultMarsh, Direction(..)) -- translation tables -- ------------------ -- | takes an identifier to a lexeme including a potential mapping by a -- translation table -- type TransFun = Ident -> Maybe String -- | translation function for the 'underscoreToCase' flag -- underscoreToCase :: String -> String underscoreToCase lexeme = let ps = filter (not . null) . parts $ lexeme in concat . map adjustCase $ ps where parts s = let (l, s') = break (== '_') s in l : case s' of [] -> [] (_:s'') -> parts s'' adjustCase (c:cs) = toUpper c : map toLower cs -- | translation function for the 'upcaseFirstLetter' flag -- upcaseFirstLetter :: String -> String upcaseFirstLetter "" = "" upcaseFirstLetter (c:cs) = toUpper c : cs -- | translation function for the 'downcaseFirstLetter' flag -- downcaseFirstLetter :: String -> String downcaseFirstLetter "" = "" downcaseFirstLetter (c:cs) = toLower c : cs -- | takes an identifier association table to a translation function -- -- * if first argument is 'True', identifiers that are not found in the -- translation table are subjected to 'underscoreToCase' and friends -- -- * the details of handling the prefix are given in the DOCU section at the -- beginning of this file -- transTabToTransFun :: String -> String -> CHSTrans -> TransFun transTabToTransFun prefx rprefx (CHSTrans _2Case chgCase table omits) = \ide -> let caseTrafo = (if _2Case then underscoreToCase else id) . (case chgCase of CHSSameCase -> id CHSUpCase -> upcaseFirstLetter CHSDownCase -> downcaseFirstLetter) lexeme = identToString ide dft = caseTrafo lexeme -- default uses case trafo in if ide `elem` omits then Nothing else Just $ case lookup ide table of -- lookup original ident Just ide' -> identToString ide' -- original ident matches Nothing -> case eat prefx lexeme of Nothing -> dft -- no match & no prefix Just eatenLexeme -> let eatenIde = internalIdentAt (posOf ide) (rprefx ++ eatenLexeme) eatenDft = caseTrafo rprefx ++ caseTrafo eatenLexeme in case lookup eatenIde table of -- lookup without prefix Nothing -> eatenDft -- orig ide without prefix Just ide' -> identToString ide' -- without prefix matched where -- try to eat prefix and return `Just partialLexeme' if successful -- eat [] ('_':cs) = eat [] cs eat [] cs = Just cs eat (p:prefx') (c:cs) | toUpper p == toUpper c = eat prefx' cs | otherwise = Nothing eat _ _ = Nothing -- the local monad -- --------------- -- | map that for maps C pointer types to Haskell types for pointer that have -- been registered using a pointer hook -- -- * the 'Bool' indicates whether for a C type "ctype", we map "ctype" itself -- or "*ctype" -- -- * in the co-domain, the first string is the type for function arguments and -- the second string is for function results; this distinction is necessary -- as 'ForeignPtr's cannot be returned by a foreign function; the -- restriction on function result types is only for the actual result, not -- for type arguments to parametrised pointer types, ie, it holds for @res@ -- in `Int -> IO res', but not in `Int -> Ptr res' -- type PointerMap = Map (Bool, Ident) (String, String) -- | map that maintains key information about some of the Haskell objects -- generated by c2hs -- -- NB: using records here avoids to run into a bug with deriving 'Read' in GHC -- 5.04.1 -- data HsObject = Pointer { ptrTypeHO :: CHSPtrType, -- kind of pointer isNewtypeHO :: Bool -- newtype? } | Class { superclassHO :: (Maybe String),-- superclass ptrHO :: String -- pointer } deriving (Show, Read) type HsObjectMap = Map Ident HsObject type SizeMap = Map Ident Int -- | set of Haskell type names corresponding to C enums. type EnumSet = Set String -- Map from C type names to type default definitions. type TypedefMap = Map Ident CHSTypedefInfo -- Map from C type names to type default definitions. type DefaultMarshMap = Map (Direction, String, Bool) CHSDefaultMarsh -- Definitions for bare structure function wrappers. data Wrapper = Wrapper { wrapFn :: String , wrapOrigFn ::String , wrapDecl :: CDecl , wrapArgs :: [Bool] , wrapBools :: (Bool, [Bool]) , wrapPos :: Position } deriving Show instance Eq Wrapper where w1 == w2 = wrapFn w1 == wrapFn w2 instance Ord Wrapper where compare w1 w2 = compare (wrapFn w1) (wrapFn w2) type WrapperSet = Set Wrapper type Dependencies = Set String {- FIXME: What a mess... instance Show HsObject where show (Pointer ptrType isNewtype) = "Pointer " ++ show ptrType ++ show isNewtype show (Class osuper pointer ) = "Class " ++ show ptrType ++ show isNewtype -} -- Remove everything until the next element in the list (given by a -- ","), the end of the list (marked by "]"), or the end of a record -- "}". Everything inside parenthesis is ignored. chopIdent :: String -> String chopIdent str = goChop 0 str where goChop :: Int -> String -> String goChop 0 rest@('}':_) = rest goChop 0 rest@(',':_) = rest goChop 0 rest@(']':_) = rest goChop level ('(':rest) = goChop (level+1) rest goChop level (')':rest) = goChop (level-1) rest goChop level (_ :rest) = goChop level rest goChop _ [] = [] extractIdent :: String -> (Ident, String) extractIdent str = let isQuote c = c == '\'' || c == '"' (ideChars, rest) = span (not . isQuote) . tail . dropWhile (not . isQuote) $ str in if null ideChars then error $ "Could not interpret " ++ show str ++ "as an Ident." else (internalIdent ideChars, (chopIdent . tail) rest) -- super kludgy (depends on Show instance of Ident) instance Read Ident where readsPrec _ str = [extractIdent str] -- | the local state consists of -- -- (1) the dynamic library specified by the context hook, -- (2) the prefix specified by the context hook, -- (3) the set of delayed code fragaments, ie, pieces of Haskell code that, -- finally, have to be appended at the CHS module together with the hook -- that created them (the latter allows avoid duplication of foreign -- export declarations), and -- (4) a map associating C pointer types with their Haskell representation -- -- access to the attributes of the C structure tree is via the 'CT' monad of -- which we use an instance here -- data GBState = GBState { lib :: String, -- dynamic library prefix :: String, -- prefix repprefix :: String, -- replacement prefix frags :: [(CHSHook, CHSFrag)], -- delayed code (with hooks) ptrmap :: PointerMap, -- pointer representation objmap :: HsObjectMap, -- generated Haskell objects szmap :: SizeMap, -- object sizes enums :: EnumSet, -- enumeration hooks tdmap :: TypedefMap, -- typedefs dmmap :: DefaultMarshMap, -- user-defined default marshallers wrappers :: WrapperSet, -- C wrapper functions deps :: Dependencies -- Haskell dependencies (for imports) } type GB a = CT GBState a initialGBState :: GBState initialGBState = GBState { lib = "", prefix = "", repprefix = "", frags = [], ptrmap = Map.empty, objmap = Map.empty, szmap = Map.empty, enums = Set.empty, tdmap = Map.empty, dmmap = Map.empty, wrappers = Set.empty, deps = Set.empty } -- | set the dynamic library and library prefix -- setContext :: (Maybe String) -> (Maybe String) -> (Maybe String) -> GB () setContext lib' prefix' repprefix' = transCT $ \state -> (state {lib = fromMaybe "" lib', prefix = fromMaybe "" prefix', repprefix = fromMaybe "" repprefix'}, ()) -- | get the dynamic library -- getLibrary :: GB String getLibrary = readCT lib -- | get the prefix string -- getPrefix :: GB String getPrefix = readCT prefix -- | get the replacement prefix string -- getReplacementPrefix :: GB String getReplacementPrefix = readCT repprefix -- | add code to the delayed fragments (the code is made to start at a new line) -- -- * currently only code belonging to call hooks can be delayed -- -- * if code for the same call hook (ie, same C function) is delayed -- repeatedly only the first entry is stored; it is checked that the hooks -- specify the same flags (ie, produce the same delayed code) -- delayCode :: CHSHook -> String -> GB () delayCode hook str = do frags'' <- readCT frags frags' <- delay hook frags'' transCT (\state -> (state {frags = frags'}, ())) where newEntry = (hook, (CHSVerb ("\n" ++ str) (posOf hook))) -- delay hook'@(CHSCall isFun isUns ide _oalias _) frags' = case find (\(hook'', _) -> hook'' == hook') frags' of Just (CHSCall isFun' isUns' ide' _ _, _) | isFun == isFun' && isUns == isUns' && ide == ide' -> return frags' | otherwise -> err (posOf ide) (posOf ide') Nothing -> return $ frags' ++ [newEntry] delay hook'@(CHSPointer _ _ _ _ _ _ _ _) frags' = case find (\(hook'', _) -> hook'' == hook') frags' of Just (CHSPointer _ _ _ _ _ _ _ _, _) -> return frags' Nothing -> return $ frags' ++ [newEntry] delay _ _ = interr "GBMonad.delayCode: Illegal delay!" -- err = incompatibleCallHooksErr -- | get the complete list of delayed fragments -- getDelayedCode :: GB [CHSFrag] getDelayedCode = readCT (map snd . frags) -- | add an entry to the pointer map -- ptrMapsTo :: (Bool, Ident) -> (String, String) -> GB () (isStar, cName) `ptrMapsTo` hsRepr = transCT (\state -> (state { ptrmap = Map.insert (isStar, cName) hsRepr (ptrmap state) }, ())) -- | query the pointer map -- queryPtr :: (Bool, Ident) -> GB (Maybe (String, String)) queryPtr pcName = do fm <- readCT ptrmap return $ Map.lookup pcName fm -- | add an entry to the Haskell object map -- objIs :: Ident -> HsObject -> GB () hsName `objIs` obj = transCT (\state -> (state { objmap = Map.insert hsName obj (objmap state) }, ())) -- | query the Haskell object map -- queryObj :: Ident -> GB (Maybe HsObject) queryObj hsName = do fm <- readCT objmap return $ Map.lookup hsName fm -- | add an entry to the size map -- sizeIs :: Ident -> Int -> GB () hsName `sizeIs` sz = transCT (\state -> (state { szmap = Map.insert hsName sz (szmap state) }, ())) -- | query the size map -- querySize :: Ident -> GB (Maybe Int) querySize hsName = do sm <- readCT szmap return $ Map.lookup hsName sm -- | query the Haskell object map for a class -- -- * raise an error if the class cannot be found -- queryClass :: Ident -> GB HsObject queryClass hsName = do oobj <- queryObj hsName case oobj of Just obj@(Class _ _) -> return obj Just _ -> classExpectedErr hsName Nothing -> hsObjExpectedErr hsName -- | query the Haskell object map for a pointer -- -- * raise an error if the pointer cannot be found -- queryPointer :: Ident -> GB HsObject queryPointer hsName = do oobj <- queryObj hsName case oobj of Just obj@(Pointer _ _) -> return obj Just _ -> pointerExpectedErr hsName Nothing -> hsObjExpectedErr hsName -- | merge the pointer and Haskell object maps -- -- * currently, the read map overrides any entires for shared keys in the map -- that is already in the monad; this is so that, if multiple import hooks -- add entries for shared keys, the textually latest prevails; any local -- entries are entered after all import hooks anyway -- -- FIXME: This currently has several shortcomings: -- * It just dies in case of a corrupted .chi file -- * We should at least have the option to raise a warning if two -- entries collide in the 'objmap'. But it would be better to -- implement qualified names. -- * Do we want position information associated with the read idents? -- mergeMaps :: String -> GB () mergeMaps str = transCT (\state -> (state { ptrmap = Map.union readPtrMap (ptrmap state), objmap = Map.union readObjMap (objmap state), enums = Set.union readEnumSet (enums state) }, ())) where -- Deal with variant interface file formats (old .chi files don't -- contain the list of enumerations). (ptrAssoc, objAssoc, enumList) = case reads str of [] -> let (ptr, obj) = read str in (ptr, obj, []) [(r, "")] -> r readPtrMap = Map.fromList [((isStar, internalIdent ide), repr) | ((isStar, ide), repr) <- ptrAssoc] readObjMap = Map.fromList [(internalIdent ide, obj) | (ide, obj) <- objAssoc] readEnumSet = Set.fromList enumList -- | convert the whole pointer and Haskell object maps into printable form -- dumpMaps :: GB String dumpMaps = do ptrFM <- readCT ptrmap objFM <- readCT objmap enumS <- readCT enums let dumpable = ([((isStar, identToString ide), repr) | ((isStar, ide), repr) <- Map.toList ptrFM], [(identToString ide, obj) | (ide, obj) <- Map.toList objFM], Set.toList enumS) return $ show dumpable -- | query the enum map -- queryEnum :: String -> GB Bool queryEnum hsName = do es <- readCT enums return $ hsName `Set.member` es -- | add an entry to the enum map -- isEnum :: String -> GB () isEnum hsName = transCT (\state -> (state { enums = Set.insert hsName (enums state) }, ())) -- | query the type default map -- queryTypedef :: Ident -> GB (Maybe CHSTypedefInfo) queryTypedef cIde = do tds <- readCT tdmap return $ cIde `Map.lookup` tds -- | add an entry to the type default map -- isC2HSTypedef :: Ident -> CHSTypedefInfo -> GB () isC2HSTypedef cIde td = transCT (\state -> (state { tdmap = Map.insert cIde td (tdmap state) }, ())) -- | query the default marshaller map -- queryDefaultMarsh :: (Direction, String, Bool) -> GB (Maybe CHSDefaultMarsh) queryDefaultMarsh k = do dms <- readCT dmmap return $ k `Map.lookup` dms -- | add an entry to the type default map -- isDefaultMarsh :: (Direction, String, Bool) -> CHSDefaultMarsh -> GB () isDefaultMarsh k dm = transCT (\state -> (state { dmmap = Map.insert k dm (dmmap state) }, ())) -- | add a wrapper definition addWrapper :: String -> String -> CDecl -> [Bool] -> (Bool, [Bool]) -> Position -> GB () addWrapper wfn ofn cdecl args bools pos = let w = Wrapper wfn ofn cdecl args bools pos in transCT (\st -> (st { wrappers = Set.insert w (wrappers st) }, ())) getWrappers :: GB [Wrapper] getWrappers = Set.toList `fmap` readCT wrappers -- | add Haskell module dependency for import generation addHsDependency :: String -> GB () addHsDependency m = transCT (\st -> (st { deps = Set.insert m (deps st) }, ())) getHsDependencies :: GB [String] getHsDependencies = Set.toList `fmap` readCT deps -- error messages -- -------------- incompatibleCallHooksErr :: Position -> Position -> GB a incompatibleCallHooksErr here there = raiseErrorCTExc here ["Incompatible call hooks!", "There is a another call hook for the same C function at " ++ show there, "The flags and C function name of the two hooks should be identical,", "but they are not."] classExpectedErr :: Ident -> GB a classExpectedErr ide = raiseErrorCTExc (posOf ide) ["Expected a class name!", "Expected `" ++ identToString ide ++ "' to refer to a class introduced", "by a class hook."] pointerExpectedErr :: Ident -> GB a pointerExpectedErr ide = raiseErrorCTExc (posOf ide) ["Expected a pointer name!", "Expected `" ++ identToString ide ++ "' to be a type name introduced by", "a pointer hook."] hsObjExpectedErr :: Ident -> GB a hsObjExpectedErr ide = raiseErrorCTExc (posOf ide) ["Unknown name!", "`" ++ identToString ide ++ "' is unknown; it has *not* been defined by", "a previous hook."] c2hs-0.28.3/tests/bugs/issue-141/000775 001750 001750 00000000000 13206343576 016375 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-149/000775 001750 001750 00000000000 13206343576 016405 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-79/000775 001750 001750 00000000000 13206343576 016327 5ustar00deechdeech000000 000000 c2hs-0.28.3/doc/c2hs.xml000664 001750 001750 00000160305 13206343576 014773 0ustar00deechdeech000000 000000 c2hs'> ]>
The Binding Generator &C2hs; Manuel Chakravarty chak@cse.unsw.edu.au November 2007 &C2hs; is an interface generator that simplifies the development of Haskell bindings to C libraries. The tool processes existing C header files that determine data layout and function signatures on the C side in conjunction with Haskell modules that specify Haskell-side type signatures and marshaling details. Hooks embedded in the Haskell code signal access to C structures and functions -- they are expanded by the interfacing tool in dependence on information from the corresponding C header file. Another noteworthy property is the lightweight nature of the approach. More background information is available in a research paper discussing &C2hs;, which is at . However, this paper does not cover the more recent advanced features such as function hooks and conditional compilation. Installation It follows a brief discussion of the installation from source. There is, however, a file INSTALL in the source distribution, which is more frequently updated and should be consulted in any case. Where is the Source? The master site of &C2hs; is at . It has all the latest information and sources. Furthermore, it explains how to get access to the &C2hs; Darcs repository and has references to pre-compiled binaries. What Else Do I Need? You need a Haskell system supported by &C2hs;. Currently, this is only the Glasgow Haskell Compiler (GHC), which you can obtain from . Furthermore, you need the Haskell package system Cabal. See the INSTALL file for details on supported versions. To build the documentation, you will also need the SGML Tools, which you find at your nearest sunsite or Linux mirror or at . On an up-to-date Linux system, the tools are probably already installed. I Got Everything, and Now? The short answer is $ tar -xzf package.tar.gz # unpack the sources $ cd package # change to the toplevel directory $ runghc Setup.hs configure # configure the build system $ runghc Setup.hs build # build everything [ Become root if necessary ] $ runghc Setup.hs install # install c2hs In the INSTALL file, there are more details. Optionally, you can build the documentation by issuing make doc and install it with make install-doc. Usage of &C2hs; Let's have a brief look at how to call the tool and how to use the generated interfaces. Usage of &c2hs; &C2hs; is implemented by the executable &c2hs;. The simplest form of usage is c2hs Lib.chs where Lib.chs is the Haskell binding module defining the Haskell interface to a C library together with the required marshalling code. If &c2hs; is invoked in this manner, the binding module must contain a cpp #include directive to determine the C-side interface of the library. Alternatively, a C header file can be specified on the command line, as in c2hs lib.h Lib.chs However, the latter option is only preserved for backwards compatibility and not recommended. If no errors occur, &c2hs; generates three files: a pure Haskell module Lib.hs, which implements the Haskell API of the library a C header file Lib.h which some Haskell systems need to compile the generated Haskell code. a &c2hs; interface file Lib.chi that is used by other binding modules that import Lib.hs using an import hook (see the section on import hooks for details). The executable &c2hs; has a couple more options: Usage: c2hs [ option... ] [header-file] binding-file -C CPPOPTS --cppopts=CPPOPTS pass CPPOPTS to the C preprocessor -c CPP --cpp=CPP use executable CPP to invoke C preprocessor -d TYPE --dump=TYPE dump internal information (for debugging) -h, -? --help brief help (the present message) -i INCLUDE --include=INCLUDE include paths for .chi files -k --keep keep pre-processed C header -l --copy-library copy `C2HS' library module in -o FILE --output=FILE output result to FILE (should end in .hs) -p PLATFORM --platform=PLATFORM platform to use for cross compilation -t PATH --output-dir=PATH place generated files in PATH -v --version show version information --numeric-version show version number The header file must be a C header file matching the given binding file. The dump TYPE can be trace -- trace compiler phases genbind -- trace binding generation ctrav -- trace C declaration traversal chs -- dump the binding file (adds `.dump' to the name) PLATFORM can be x86_64-linux, i686-linux, m68k-palmos The most useful of these is probably --cppopts= (or -C). If the C header file needs any special options (like -D or -I) to go through the C pre-processor, here is the place to pass them. A call may look like this: c2hs --cppopts='-I/some/obscure/dir' --cppopts=-DEXTRA' Lib.chs If you have more than one option that you want to pass to the pre-processor it is best to use multiple --cppopts= flags. That way there is no need to worry about quoting. Often, lib.h will not be in the current directory, but in one of the header file directories. &c2hs; leaves locating the header file to the standard C preprocessor, which usually looks in two places for the header: first, in the standard include directory of the used system, this is usually /usr/include and /usr/local/include; and second, it will look in every directory that is mentioned in a -IDIR option passed to the pre-processor via --cppopts. If the compiled binding module contains import hooks, &C2hs; needs to find the .chi (&C2hs; interface files) produced while compiling the corresponding binding modules. By default, they will be searched for in the current working directory. If they are located elsewhere, the --include=INCLUDE option has to be used to indicate the location, where INCLUDE is a colon-separated list of directories. Multiple such options are admissible. Paths specified later are searched first. Compilation of a Generated Haskell API &C2hs; comes with a marshalling library, called C2HS, which needs to be explicitly imported into Haskell binding modules. The library contains functions that users might use explicitly, but also functions that &C2hs; will generate for some classes of bindings. The library takes the form of a single Haskell module, which &c2hs; places in the same directory as the generated binding whenever it is given the --copy-library (or -l) option. Implementation of Haskell Binding Modules A discussion of binding modules, the principles behind the tool, and a discussion of related work can be found in a research paper located at . All features described in the paper, except enum define hooks are implemented in the tool, but since the publication of the paper, the tool has been extended further. The library interface essentially consists of the new Haskell FFI Marshalling Library. More details about this library are provided in the next section. The remainder of this section describes the hooks that are available in binding modules. Import Hooks {#import [qualified] modid#} Is translated into the same syntactic form in Haskell, which implies that it may be followed by an explicit import list. Moreover, it implies that the module modid is also generated by &C2hs; and instructs the tool to read the file modid.chi. If an explicit output file name is given (--output option), this name determines the basename for the .chi file of the currently translated module. Currently, only pointer hooks generate information that is stored in a .chi file and needs to be incorporated into any client module that makes use of these pointer types. It is, however, regarded as good style to use import hooks for any module generated by &C2hs;. Restriction &C2hs; does not use qualified names. This can be a problem, for example, if two pointer hooks are defined to have the same unqualified Haskell name in two different modules, which are then imported by a third module. To partially work around this problem, it is guaranteed that the declaration of the textually later import hook dominates. Context Hooks {#context [lib = lib] [prefix = prefix]#} Context hooks define a set of global configuration options. Currently, there are two parameters which are both strings lib is a dynamic library that contains symbols needed by the present binding. prefix is an identifier prefix that may be omitted in the lexemes of identifiers referring to C definitions in any binding hook. The is useful as C libraries often use a prefix, such as gtk_, as a form of poor man's name spaces. Any occurrence of underline characters between a prefix and the main part of an identifier must also be dropped. Case is not relevant in a prefix. In case of a conflict of the abbreviation with an explicitly defined identifier, the explicit definition takes preference. Both parameters are optional. An example of a context hook is the following: {#context prefix = "gtk"#} If a binding module contains a binding hook, it must be the first hook in the module. Type Hooks {#type ident#} A type hooks maps a C type to a Haskell type. As an example, consider type GInt = {#type gint#} The type must be a defined type, primitive types, such as int, are not admissible. Sizeof Hooks {#sizeof ident#} A sizeof hooks maps a C type to its size in bytes. As an example, consider gIntSize :: Int gIntSize = {#sizeof gint#} The type must be a defined type, primitive types, such as int, are not admissible. The size of primitive types can always be obtained using Storable.sizeOf. Enumeration Hooks {#enum cid [as hsid] {alias1 , ... , aliasn} [with prefix = pref] [deriving (clid1 , ... , clidn)]#} Rewrite the C enumeration called cid into a Haskell data type declaration, which is made an instance of Enum such that the ordinals match those of the enumeration values in C. This takes explicit enumeration values in the C definitions into account. If hsid is given, this is the name of the Haskell data type. The identifiers clid1 to clidn are added to the deriving clause of the Haskell type. By default, the names of the C enumeration are used for the constructors in Haskell. If alias1 is underscoreToCase, the original C names are capitalised and the use of underscores is rewritten to caps. If it is upcaseFirstLetter or downcaseFirstLetter, the first letter of the original C name changes case correspondingly. It is also possible to combine underscoreToCase with one of upcaseFirstLetter or downcaseFirstLetter. Moreover, alias1 to aliasn may be aliases of the form cid as hsid, which map individual C names to Haskell names. Instead of the global prefix introduced by a context hook, a local prefix pref can optionally be specified. As an example, consider {#enum WindowType {underscoreToCase} deriving (Eq)#} <literal>enum define</literal> hooks Many C libraries do not use enum types, but macro definitions to implement constants. c2hs provides enum define hooks generate a haskell datatype from a collection of macro definitions. {#enum define hsid {alias1 , ... , aliasn} [deriving (clid1 , ... , clidn)]#} Create a haskell datatype hsid, with nullary constructors as given by the aliases alias1 through aliasn. Each alias has to be of the form macrodef as hsid, where hsid is the name of the nullary haskell constructor, and macrodef the C macro which the haskell constructor should map to. The deriving part is handled as in ordinary enum hooks. Here's an example #define X 0 #define Y 1 {#enum define Axis {X as Axis0, Y as Axis1} deriving (Eq,Ord) #} Call Hooks {#call [pure] [unsafe] cid [as (hsid | ^)]#} A call hook rewrites to a call to the C function cid and also ensures that the appropriate foreign import declaration is generated. The tags pure and unsafe specify that the external function is purely functional and cannot re-enter the Haskell runtime, respectively. If hsid is present, it is used as the identifier for the foreign declaration, which otherwise defaults to the cid. When instead of hsid, the symbol ^ is given, the cid after conversion from C's underscore notation to a capitalised identifier is used. As an example, consider sin :: Float -> Float sin = {#call pure sin as "_sin"#} Function Hooks {#fun [pure] [unsafe] cid [as (hsid | ^)] [ctxt =>] { parm1 , ... , parmn } -> parm Function hooks are call hooks including parameter marshalling. Thus, the components of a function hook up to and including the as alias are the same as for call hooks. However, an as alias has a different meaning; it specifies the name of the generated Haskell function. The remaining components use literals enclosed in backwards and foward single quotes (` and ') to denote Haskell code fragments (or more precisely, parts of the Haskell type signature for the bound function). The first one is the phrase ctxt preceding =>, which denotes the type context. This is followed by zero or more type and marshalling specifications parm1 to parmn for the function arguments and one parm for the function result. Each such specification parm has the form [inmarsh [* | -]] hsty[&] [outmarsh [*] [-]] where hsty is a Haskell code fragment denoting a Haskell type. The optional information to the left and right of this type determines the marshalling of the corresponding Haskell value to and from C; they are called the in and out marshaller, respectively. Each marshalling specification parm corresponds to one or two arguments of the C function, in the order in which they are given. A marshalling specification in which the symbol & follows the Haskell type corresponds to two C function arguments; otherwise, it corresponds only to one argument. The parm following the left arrow -> determines the marshalling of the result of the C function and may not contain the symbol &. The *- output marshal specification is for monadic actions that must be executed but whose results are discarded. This is very useful for e.g. checking an error value and throwing an exception if needed. Both inmarsh and outmarsh are identifiers of Haskell marshalling functions. By default they are assumed to be pure functions; if they have to be executed in the IO monad, the function name needs to be followed by a star symbol *. Alternatively, the identifier may be followed by a minux sign -, in which case the Haskell type does not appear as an argument (in marshaller) or result (out marshaller) of the generated Haskell function. In other words, the argument types of the Haskell function is determined by the set of all marshalling specifications where the in marshaller is not followed by a minus sign. Conversely, the result tuple of the Haskell function is determined by the set of all marshalling specifications where the out marshaller is not followed by a minus sign. The order of function arguments and components in the result tuple is the same as the order in which the marshalling specifications are given, with the exception that the value of the result marshaller is always the first component in the result tuple if it is included at all. For a set of commonly occuring Haskell and C type combinations, default marshallers are provided by &C2hs; if no explicit marshaller is given. The out marshaller for function arguments is by default void-. The defaults for the in marshallers for function arguments are as follows: Bool and integral C type (including chars): cFromBool Integral Haskell and integral C type: cIntConv Floating Haskell and floating C type: cFloatConv String and char*: withCString* String and char* with explicit length: withCStringLen* T and T*: with* T and T* where T is an integral type: withIntConv* T and T* where T is a floating type: withFloatConv* Bool and T* where T is an integral type: withFromBool* The defaults for the out marshaller of the result are the converse of the above; i.e., instead of the with functions, the corresponding peek functions are used. Moreover, when the Haskell type is (), the default marshaller is void-. As an example, consider {#fun notebook_query_tab_label_packing as ^ `(NotebookClass nb, WidgetClass cld)' => {notebook `nb' , widget `cld' , alloca- `Bool' peekBool*, alloca- `Bool' peekBool*, alloca- `PackType' peekEnum*} -> `()'#} which results in the Haskell type signature notebookQueryTabLabelPacking :: (NotebookClass nb, WidgetClass cld) => nb -> cld -> IO (Bool, Bool, PackType) which binds the following C function: void gtk_notebook_query_tab_label_packing (GtkNotebook *notebook, GtkWidget *child, gboolean *expand, gboolean *fill, GtkPackType *pack_type); Get Hooks {#get apath#} A get hook supports accessing a member value of a C structure. The hook itself yields a function that, when given the address of a structure of the right type, performs the structure access. The member that is to be extracted is specified by the access path apath. Access paths are formed as follows (following a subset of the C expression syntax): The root of any access path is a simple identifier, which denotes either a type name or struct tag. An access path of the form *apath denotes dereferencing of the pointer yielded by accessing the access path apath. An access path of the form apath.cid specifies that the value of the struct member called cid should be accessed. Finally, an access path of the form apath->cid, as in C, specifies a combination of dereferencing and member selection. For example, we may have visualGetType :: Visual -> IO VisualType visualGetType (Visual vis) = liftM cToEnum $ {#get Visual->type#} vis Set Hooks {#set apath#} Set hooks are formed in the same way as get hooks, but yield a function that assigns a value to a member of a C structure. These functions expect a pointer to the structure as the first and the value to be assigned as the second argument. For example, we may have {#set sockaddr_in.sin_family#} addr_in (cFromEnum AF_NET) Pointer Hooks {#pointer [*] cid [as hsid] [foreign | stable] [newtype | -> hsid2] [nocode]#} A pointer hook facilitates the mapping of C to Haskell pointer types. In particular, it enables the use of ForeignPtr and StablePtr types and defines type name translations for pointers to non-basic types. In general, such a hook establishes an association between the C type cid or *cid and the Haskell type hsid, where the latter defaults to cid if not explicitly given. The identifier cid will usually be a type name, but in the case of *cid may also be a struct, union, or enum tag. If both a type name and a tag of the same name are available, the type name takes precedence. Optionally, the Haskell representation of the pointer can be by a ForeignPtr or StablePtr instead of a plain Ptr. If the newtype tag is given, the Haskell type hsid is defined as a newtype rather than a transparent type synonym. In case of a newtype, the type argument to the Haskell pointer type will be hsid, which gives a cyclic definition, but the type argument is here really only used as a unique type tag. Without newtype, the default type argument is (), but another type can be specified after the symbol ->. For example, we may have {#pointer *GtkObject as Object newtype#} This will generate a new type Object as follows: newtype Object = Object (Ptr Object) which enables exporting Object as an abstract type and facilitates type checking at call sites of imported functions using the encapsulated pointer. The latter is achieved by &C2hs; as follows. The tool remembers the association of the C type *GtkObject with the Haskell type Object, and so, it generates for the C function void gtk_unref_object (GtkObject *obj); the import declaration foreign import gtk_unref_object :: Object -> IO () This function can obviously only be applied to pointers of the right type, and thus, protects against the common mistake of confusing the order of pointer arguments in function calls. However, as the Haskell FFI does not permit to directly pass ForeignPtrs to function calls or return them, the tool will use the type Ptr HsName in this case, where HsName is the Haskell name of the type. So, if we modify the above declaration to be {#pointer *GtkObject as Object foreign newtype#} the type Ptr Object will be used instead of a plain Object in import declarations; i.e., the previous import declaration will become foreign import gtk_unref_object :: Ptr Object -> IO () To simplify the required marshalling code for such pointers, the tool automatically generates a function withObject :: Object -> (Ptr Object -> IO a) -> IO a As an example that does not represent the pointer as an abstract type, consider the C type declaration: typedef struct {int x, y;} *point; We can represent it in Haskell as data Point = Point {x :: Int, y :: Int} {#pointer point as PointPtr -> Point#} which will translate to data Point = Point {x :: Int, y :: Int} type PointPtr = Ptr Point and establish a type association between point and PointPtr. If the keyword nocode is added to the end of a pointer hook, &C2hs; will not emit a type declaration. This is useful when a &C2hs; module wants to make use of an existing type declaration in a binding not generated by &C2hs; (i.e., where there are no .chi files). Restriction The name cid cannot be a basic C type (such as int), it must be a defined name. Class Hooks {#class [hsid1 =>] hsid2 hsid3#} Class hooks facilitate the definition of a single inheritance class hierachy for external pointers including up and down cast functionality. This is meant to be used in cases where the objects referred to by the external pointers are order in such a hierachy in the external API - such structures are encountered in C libraries that provide an object-oriented interface. Each class hook rewrites to a class declaration and one or more instance declarations. All classes in a hierarchy, except the root, will have a superclass identified by hsid1. The new class is given by hsid2 and the corresponding external pointer is identified by hsid3. Both the superclass and the pointer type must already have been defined by binding hooks that precede the class hook. The pointers in a hierachy must either all be foreign pointers or all be normal pointers. Stable pointers are not allowed. Both pointer defined as newtypes and those defined by type synonyms may be used in class declarations and they may be mixed. In the case of synonyms, Haskell's usual restrictions regarding overlapping instance declarations apply. The newly defined class has two members whose names are derived from the type name hsid3. The name of first member is derived from hsid3 by converting the first character to lower case. This function casts from any superclass to the current class. The name of the second member is derived by prefixing hsid3 with the from. It casts from the current class to any superclass. A class hook generates an instance for the pointer in the newly defined class as well as in all its superclasses. As an example, consider {#pointer *GtkObject newtype#} {#class GtkObjectClass GtkObject#} {#pointer *GtkWidget newtype#} {#class GtkObjectClass => GtkWidgetClass GtkWidget#} The second class hook generates an instance for GtkWidget for both the GtkWidgetClass as well as for the GtkObjectClass. CPP Directives and Inline C Code A Haskell binding module may include arbitrary C pre-processor directives using the standard C syntax. The directives are used in two ways: Firstly, they are included in the C header file generated by &C2hs; in exactly the same order in which they appear in the binding module. Secondly, all conditional directives are honoured by &C2hs; in that all Haskell binding code in alternatives that are discarded by the C pre-processor are also discarded by &C2hs;. This latter feature is, for example, useful to maintain different bindings for multiple versions of the same C API in a single Haskell binding module. In addition to C pre-processor directives, vanilla C code can be maintained in a Haskell binding module by bracketing this C code with the pseudo directives #c and #endc. Such inline C code is emitted into the C header generated by &C2hs; at exactly the same position relative to CPP directives as it occurs in the binding module. Pre-processor directives may encompass the #include directive, which can be used instead of specifying a C header file as an argument to c2hs. In particular, this enables the simultaneous use of multiple header files without the need to provide a custom header file that binds them together. If a header file lib.h is specified as an argument to c2hs, the tool will emit the directive #include"lib.h" into the generated C header before any other CPP directive or inline C code. As an artificial example of these features consider the following code: #define VERSION 2 #if (VERSION == 1) foo :: CInt -> CInt foo = {#call pure fooC#} #else foo :: CInt -> CInt -> CInt foo = {#call pure fooC#} #endif #c int fooC (int, int); #endc One of two versions of the Haskell function foo (having different arities) is selected in dependence on the value of the CPP macro VERSION, which in this example is defined in the same file. In realistic code, VERSION would be defined in the header file supplied with the C library that is made accessible from Haskell by a binding module. The above code fragment also includes one line of inline C code that declares a C prototype for fooC. Current limitation of the implementation Inline C code can currently not contain any code blocks; i.e., only declarations as typically found in header files may be included. Grammar Rules The following grammar rules define the syntax of binding hooks: hook -> `{#' inner `#}' inner -> `import' ['qualified'] ident | `context' ctxt | `type' ident | `sizeof' ident | `enum' idalias trans [`with' prefix] [deriving] | `call' [`pure'] [`unsafe'] idalias | `fun' [`pure'] [`unsafe'] idalias parms | `get' apath | `set' apath | `pointer' ['*'] idalias ptrkind | `class' [ident `=>'] ident ident ctxt -> [`lib' `=' string] [prefix] idalias -> ident [(`as' ident | `^')] prefix -> `prefix' `=' string deriving -> `deriving' `(' ident_1 `,' ... `,' ident_n `)' parms -> [verbhs `=>'] `{' parm_1 `,' ... `,' parm_n `}' `->' parm parm -> [ident_1 [`*' | `-']] verbhs [`&'] [ident_2 [`*'] [`-']] apath -> ident | `*' apath | apath `.' ident | apath `->' ident trans -> `{' alias_1 `,' ... `,' alias_n `}' alias -> `underscoreToCase' | `upcaseFirstLetter' | `downcaseFirstLetter' | ident `as' ident ptrkind -> [`foreign' | `stable'] ['newtype' | '->' ident] Identifier ident follow the lexis of Haskell. They may be enclosed in single quotes to disambiguate them from C->Haskell keywords. Bug Reports and Suggestions There is a tracker for bugs and feature requests: . Alternatively if you prefer email please send your bug reports and suggestions to the C->Haskell List c2hs@haskell.org. A good bug report contains information on the used operating system and Haskell compiler as well as the version of &C2hs; that you have been using. You can obtain the version information by running c2hs --version. If possible a concise example illustrating your problem would be appreciated. Copyright &C2hs; is Copyright (C) [1999..2005] Manuel M. T. Chakravarty &C2hs; License 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 2 of the License, or (at your option) any later version. 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Documentation License This manual is Copyright (c) [2000..2005] by Manuel M. T. Chakravarty. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with the no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". Possible Licenses of Generated Code All code included into generated bindings is under a BSD-style license that does not place any restrictions on the license of the inteface produced with &C2hs; (ie, closed proprietary licenses are possible, too). In other words, I do not care what you use &C2hs; for or to whom you are giving &C2hs; or any interfaces generated with &C2hs;, only if you modify or improve &C2hs; itself, you have to contribute your changes back to the community. Nevertheless, I will of course be particularly delighted if you choose to make your work freely available. GNU Free Documentation License The GNU Free Documentation License is available at . Release Notes Important changes (especially those affecting the semantics of the tool) are documented in the following. Version 0.15.1 "Rainy Days" New C parser that can parse all of C99 and GNU C Make c2hs integrate better with Cabal (1.2 and later) Adapted to GHC 6.8. Now requires Cabal 1.2. Lots and lots of old code removal Several bug fixes and improvements from Udo Stenzel: allowing variadic functions in structures allowing call and fun hooks for FunPtrs in C structs embedded arrays size calculated correctly Version 0.14.5 "Travelling Lightly" Added nocode directive to pointer hooks Can use structs properly in pointer hooks now (contributed by Jelmer Vernooij) upcaseFirstLetter and downcaseFirstLetter Cross-compiling with --platform flag Gcc's asm construct is supported (contributed by Duncan Coutts) Hierarchical modules syntax in import hooks supported No separately installed marshaling library anymore; as a result binary &C2hs; packages and installations are now independent of the targeted Haskell system New lexer and parser generated with Alex and Happy (contributed by Duncan Coutts) Cabal build system Version 0.13.6 "Pressing Forward" Works with GHC 6.4 and Cabal packages Strings may contain 8-bit characters (e.g., umlauts). Identifier may optionally be put in single quotes. (This is useful if they would otherwise collide with a &C2hs; keyword.) Some smaller bug fixes C chars are treated as integral types for marshalling purposes. If there is no explicit output file specified, the generated header file is put in the same directory as the binding file; otherwise, it goes in the directory where the output file is put. Moreover, the --output-dir option enables the specification of directory where all generated files are to be put. Foreign import declarations include the name of the header file generated by &C2hs; (ie, it needs neither be passed to the Haskell compiler at the command line nor in an OPTIONS pragma). We allow structs and unions with no declarations. Headers including function bodies are now parsed correctly. Duncan Coutts identified a space leak in the parser whose removal improved performance significantly. Version 0.12.1 "Springtime" Removed support for deprecated C2HS interface and for old versions of the FFI libraries Improved line pragma generation Works with GHC 6.3 Builds on Mac OS X thanks to a patch by Sean Seefried Version 0.11.5 "Powder Snow" Bug fixes Constant expression can now contain enumerators header label removed from context hooks This version of c2hs may overwrite C header files in the current directory. More precisely, if a binding module with the name Foo.chs is processed, a header file with the name Foo.h is generated and will overwrite any file of the same name in the current directory or the directory specified via the -o option. Added support for CPP directives, including special treatment of conditions, and for inline C code; specification of a header file as an argument to c2hs is now option. GHC line pragmas are emitted into generated Haskell code Swap the order of reading the binding module and the C header (i.e., we now read the binding module first) Version 0.10.17 "Altocumulus Stratiformis Perlucidus Undulatus" Worked around a bug in GHC 5.04.1 Solaris-related fix Marshalling support for bit masks represented as enumeration types Added fun hooks as aliases can use ^ convert the orignal identifier with underscore2case In call hooks, the attributes `fun' was replaced by `pure' (`fun' is will still be recognised for a while to ensure backwards compatibility, but it's use is deprecated) GHC's package system is now supported If two import hooks add a type mapping for a pointer hook with the same name, the textual later one dominates. Bug fixes Support for bitfields (they are correctly handled when computing struct offsets and they can be accessed using set and get hooks) Some more support for GNU C extensions ("alignof" and better support "__attribute__") Added class hooks Version 0.9.9 "Blue Ginger" Bug fixes Library names in foreign imports have been removed until the convention of the new FFI is implemented (they are currently silently omitted) Added sizeof hooks; sizeof of type names is now also supported in constant expressions Local prefix for enum hooks; courtesy of Armin Sander Added import hooks The documentation includes a description of binding hooks Added pointer hooks, which were derived from code for a similar feature by Axel Simon; this includes proper treatment of parametrised pointers Integrated deriving option for enum hooks, which was contributed by Axel Simon Adapted to GHC 5.0 Version 0.8.2 "Gentle Moon" Adaptation layer for legacy StablePtr interface Forgot to export FunPtr and associated functions from C2HS Forgot to export some names in C2HSDeprecated Added support for gcc's __builtin_va_list Version 0.8.1 "Gentle Moon" Library adapted to New FFI; the old interface can still be used by importing C2HSDeprecated FFI Library specification added to the documentation Version 0.7.10 "Afterthought" CygWin support; based on suggestions by Anibal Maffioletti Rodrigues de DEUS anibaldedeus@email.com IntConv instances for Int8, Word8, and Char Version 0.7.9 "Afterthought" Debugged the stripping of prefixes from enumerators; prefixes are now generally stripped, independent of whether they can be stripped from all enumerators of a given enumeration type Comma now correctly required after underscoreToCase. This breaks source compatibility with previous versions. Version 0.7.8 Provisional support for GHC 4.08 Corrected constant folding Version 0.7.7 Ignores any occurrence of #pragma. Version 0.7.6 Bug fixes and support for long long. Version 0.7.5 This is mainly a bug fix release. In particular, the space behaviour of &C2hs; has been significantly improved. IMPORTANT NOTE: From this release on, library names in lib tags in context hooks should not contain a suffix (i.e., omit .so etc).
c2hs-0.28.3/tests/bugs/issue-62/issue62.h000664 001750 001750 00000000226 13206343576 017770 0ustar00deechdeech000000 000000 /* @(#)issue62.h */ #ifndef _ISSUE62_H_ #define _ISSUE62_H_ int f1(int x, int y, int z); int f2(int x, int* y, int* z); #endif /* _ISSUE62_H_ */ c2hs-0.28.3/tests/bugs/issue-80/issue80.h000664 001750 001750 00000000061 13206343576 017765 0ustar00deechdeech000000 000000 enum foo { A = 1, B = 2, C = 2, D = 3 }; c2hs-0.28.3/tests/bugs/issue-75/000775 001750 001750 00000000000 13206343576 016323 5ustar00deechdeech000000 000000 c2hs-0.28.3/tests/bugs/issue-73/000775 001750 001750 00000000000 13206343576 016321 5ustar00deechdeech000000 000000 c2hs-0.28.3/regression-suite-vm/Vagrantfile-full000664 001750 001750 00000005242 13206343576 021717 0ustar00deechdeech000000 000000 $script = <