~ubuntu-branches/ubuntu/hardy/uim/hardy

« back to all changes in this revision

Viewing changes to sigscheme/src/scmport-file.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2007-04-21 03:46:09 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20070421034609-gpcurkutp8vaysqj
Tags: 1:1.4.1-3
* Switch to dh_gtkmodules for the gtk 2.10 transition (Closes:
  #419318)
  - debian/control: Add ${misc:Depends} and remove libgtk2.0-bin on
    uim-gtk2.0.
  - debian/uim-gtk2.0.post{inst,rm}: Removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*===========================================================================
 
2
 *  Filename : scmport-file.c
 
3
 *  About    : A ScmBytePort implementation for file stream of the standard C
 
4
 *             library
 
5
 *
 
6
 *  Copyright (C) 2005-2006 YAMAMOTO Kengo <yamaken AT bp.iij4u.or.jp>
 
7
 *  Copyright (c) 2007 SigScheme Project <uim AT freedesktop.org>
 
8
 *
 
9
 *  All rights reserved.
 
10
 *
 
11
 *  Redistribution and use in source and binary forms, with or without
 
12
 *  modification, are permitted provided that the following conditions
 
13
 *  are met:
 
14
 *
 
15
 *  1. Redistributions of source code must retain the above copyright
 
16
 *     notice, this list of conditions and the following disclaimer.
 
17
 *  2. Redistributions in binary form must reproduce the above copyright
 
18
 *     notice, this list of conditions and the following disclaimer in the
 
19
 *     documentation and/or other materials provided with the distribution.
 
20
 *  3. Neither the name of authors nor the names of its contributors
 
21
 *     may be used to endorse or promote products derived from this software
 
22
 *     without specific prior written permission.
 
23
 *
 
24
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 
25
 *  IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
26
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
27
 *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
 
28
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
29
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
30
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
31
 *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
32
 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
33
 *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
34
 *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
35
===========================================================================*/
 
36
 
 
37
/*
 
38
 * - This file is intended to be portable. Don't depend on SigScheme.
 
39
 * - To isolate and hide implementation-dependent things, don't merge this file
 
40
 *   into another
 
41
 */
 
42
 
 
43
#include <config.h>
 
44
 
 
45
#include <stdlib.h>
 
46
#include <stdio.h>
 
47
#include <string.h>
 
48
 
 
49
#include "scmint.h"
 
50
#include "scmport-config.h"
 
51
#include "scmport.h"
 
52
#include "scmport-file.h"
 
53
 
 
54
/*=======================================
 
55
  File Local Macro Definitions
 
56
=======================================*/
 
57
#define OK 0
 
58
 
 
59
/*=======================================
 
60
  File Local Type Definitions
 
61
=======================================*/
 
62
typedef struct ScmFilePort_ ScmFilePort;
 
63
 
 
64
struct ScmFilePort_ {  /* inherits ScmBytePort */
 
65
    const ScmBytePortVTbl *vptr;
 
66
 
 
67
    FILE *file;
 
68
    char *aux_info;  /* human readable auxilialy information about the file */
 
69
    scm_bool ownership;  /* whether close the file at fileport_close() */
 
70
};
 
71
 
 
72
/*=======================================
 
73
  File Local Function Declarations
 
74
=======================================*/
 
75
static ScmBytePort *fileport_new_internal(FILE *file, const char *aux_info,
 
76
                                          scm_bool ownership);
 
77
static ScmBytePort *fileport_open_internal(const char *path, const char *mode);
 
78
static scm_ichar_t fixup_read_char(FILE *f, int c);
 
79
 
 
80
static ScmBytePort *fileport_dyn_cast(ScmBytePort *bport,
 
81
                                      const ScmBytePortVTbl *dest_vptr);
 
82
static void fileport_close(ScmFilePort *bport);
 
83
static char *fileport_inspect(ScmFilePort *port);
 
84
static scm_ichar_t fileport_get_byte(ScmFilePort *bport);
 
85
static scm_ichar_t fileport_peek_byte(ScmFilePort *bport);
 
86
static scm_bool fileport_byte_readyp(ScmFilePort *bport);
 
87
static void fileport_puts(ScmFilePort *bport, const char *str);
 
88
static void fileport_write(ScmFilePort *bport, size_t nbytes, const char *buf);
 
89
static void fileport_flush(ScmFilePort *bport);
 
90
 
 
91
/*=======================================
 
92
  Variable Definitions
 
93
=======================================*/
 
94
static const ScmBytePortVTbl ScmFilePort_vtbl = {
 
95
    (ScmBytePortMethod_dyn_cast)   &fileport_dyn_cast,
 
96
    (ScmBytePortMethod_close)      &fileport_close,
 
97
    (ScmBytePortMethod_inspect)    &fileport_inspect,
 
98
    (ScmBytePortMethod_get_byte)   &fileport_get_byte,
 
99
    (ScmBytePortMethod_peek_byte)  &fileport_peek_byte,
 
100
    (ScmBytePortMethod_byte_readyp)&fileport_byte_readyp,
 
101
    (ScmBytePortMethod_puts)       &fileport_puts,
 
102
    (ScmBytePortMethod_write)      &fileport_write,
 
103
    (ScmBytePortMethod_flush)      &fileport_flush
 
104
};
 
105
SCM_EXPORT const ScmBytePortVTbl *const ScmFilePort_vptr = &ScmFilePort_vtbl;
 
106
 
 
107
/*=======================================
 
108
  Function Definitions
 
109
=======================================*/
 
110
 
 
111
/*
 
112
 * Client code must call this first even if current implementation does not
 
113
 * contain actual code.
 
114
 */
 
115
SCM_EXPORT void
 
116
scm_fileport_init(void)
 
117
{
 
118
}
 
119
 
 
120
static ScmBytePort *
 
121
fileport_new_internal(FILE *file, const char *aux_info, scm_bool ownership)
 
122
{
 
123
    ScmFilePort *port;
 
124
 
 
125
    SCM_PORT_ASSERT(file);
 
126
    SCM_PORT_ASSERT(aux_info);
 
127
 
 
128
    port = SCM_PORT_MALLOC(sizeof(ScmFilePort));
 
129
 
 
130
    port->vptr = ScmFilePort_vptr;
 
131
    port->file = file;
 
132
    port->aux_info = SCM_PORT_STRDUP(aux_info);
 
133
    port->ownership = ownership;
 
134
 
 
135
    return (ScmBytePort *)port;
 
136
}
 
137
 
 
138
SCM_EXPORT ScmBytePort *
 
139
ScmFilePort_new(FILE *file, const char *aux_info)
 
140
{
 
141
    return fileport_new_internal(file, aux_info, scm_true);
 
142
}
 
143
 
 
144
SCM_EXPORT ScmBytePort *
 
145
ScmFilePort_new_shared(FILE *file, const char *aux_info)
 
146
{
 
147
    return fileport_new_internal(file, aux_info, scm_false);
 
148
}
 
149
 
 
150
static ScmBytePort *
 
151
fileport_open_internal(const char *path, const char *mode)
 
152
{
 
153
    FILE *file;
 
154
 
 
155
    file = fopen(path, mode);
 
156
    /* FIXME: Raise error by SCM_BYTEPORT_ERROR(). Returning NULL as error
 
157
     * indicator is a temporary solution to display filename to user. */
 
158
#if 1
 
159
    return (file) ? ScmFilePort_new(file, path) : NULL;
 
160
#else
 
161
    if (!file)
 
162
        SCM_BYTEPORT_ERROR(NULL, SCM_ERRMSG_OPEN_PORT);
 
163
    return ScmFilePort_new(file, path);
 
164
#endif
 
165
}
 
166
 
 
167
SCM_EXPORT ScmBytePort *
 
168
ScmFilePort_open_input_file(const char *path)
 
169
{
 
170
    return fileport_open_internal(path, "rb");
 
171
}
 
172
 
 
173
SCM_EXPORT ScmBytePort *
 
174
ScmFilePort_open_output_file(const char *path)
 
175
{
 
176
    return fileport_open_internal(path, "wb");
 
177
}
 
178
 
 
179
static ScmBytePort *
 
180
fileport_dyn_cast(ScmBytePort *bport, const ScmBytePortVTbl *dst_vptr)
 
181
{
 
182
    return (dst_vptr == ScmFilePort_vptr) ? bport : NULL;
 
183
}
 
184
 
 
185
static void
 
186
fileport_close(ScmFilePort *port)
 
187
{
 
188
    int ret;
 
189
 
 
190
    ret = (port->ownership) ? fclose(port->file) : OK;
 
191
    free(port->aux_info);
 
192
    free(port);
 
193
    if (ret == EOF)
 
194
        SCM_BYTEPORT_ERROR(NULL, SCM_ERRMSG_CLOSE_PORT);
 
195
}
 
196
 
 
197
static char *
 
198
fileport_inspect(ScmFilePort *port)
 
199
{
 
200
    char *combined;
 
201
    size_t size;
 
202
 
 
203
    if (port->aux_info) {
 
204
        size = sizeof("file ") + strlen(port->aux_info);
 
205
        combined = SCM_PORT_MALLOC(size);
 
206
        sprintf(combined, "file %s", port->aux_info);
 
207
        return combined;
 
208
    } else {
 
209
        return SCM_PORT_STRDUP("file");
 
210
    }
 
211
}
 
212
 
 
213
static scm_ichar_t
 
214
fixup_read_char(FILE *f, int c)
 
215
{
 
216
    if (c == EOF) {
 
217
        if (ferror(f)) {
 
218
            clearerr(f);
 
219
            SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_READ_FROM_PORT);
 
220
        }
 
221
        return SCM_ICHAR_EOF;
 
222
    }
 
223
 
 
224
    return (scm_ichar_t)c;
 
225
}
 
226
 
 
227
static scm_ichar_t
 
228
fileport_get_byte(ScmFilePort *port)
 
229
{
 
230
    int c;
 
231
 
 
232
    c = fgetc(port->file);
 
233
    return fixup_read_char(port->file, c);
 
234
}
 
235
 
 
236
static scm_ichar_t
 
237
fileport_peek_byte(ScmFilePort *port)
 
238
{
 
239
    int c;
 
240
    scm_ichar_t ic;
 
241
 
 
242
    ic = fileport_get_byte(port);
 
243
    if (ic != SCM_ICHAR_EOF) {
 
244
        c = ungetc(ic, port->file);
 
245
        ic = fixup_read_char(port->file, c);
 
246
    }
 
247
 
 
248
    return ic;
 
249
}
 
250
 
 
251
static scm_bool
 
252
fileport_byte_readyp(ScmFilePort *port)
 
253
{
 
254
    /* FIXME: does not support a FILE based on a pipe, or opened by
 
255
     * fdopen(3) */
 
256
#if HAVE_FILENO
 
257
    if (fileno(port->file) >= 0)
 
258
        SCM_BYTEPORT_ERROR(port, "known bug: ready? operation is not supported on this port");
 
259
#endif
 
260
    return scm_true;
 
261
}
 
262
 
 
263
static void
 
264
fileport_puts(ScmFilePort *port, const char *str)
 
265
{
 
266
    int ret;
 
267
 
 
268
    ret = fputs(str, port->file);
 
269
    if (ret == EOF)
 
270
        SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_WRITE_TO_PORT);
 
271
}
 
272
 
 
273
static void
 
274
fileport_write(ScmFilePort *port, size_t nbytes, const char *buf)
 
275
{
 
276
    size_t written_objs;
 
277
 
 
278
    written_objs = fwrite(buf, sizeof(char), nbytes, port->file);
 
279
    if (written_objs != nbytes)
 
280
        SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_WRITE_TO_PORT);
 
281
}
 
282
 
 
283
static void
 
284
fileport_flush(ScmFilePort *port)
 
285
{
 
286
    int ret;
 
287
 
 
288
    ret = fflush(port->file);
 
289
    if (ret == EOF)
 
290
        SCM_BYTEPORT_ERROR(port, SCM_ERRMSG_WRITE_TO_PORT);
 
291
}