~ubuntu-branches/ubuntu/intrepid/plplot/intrepid

« back to all changes in this revision

Viewing changes to sys/win32/msdev/jim/jim-aio.c

  • Committer: Bazaar Package Importer
  • Author(s): Rafael Laboissiere
  • Date: 2006-11-04 10:19:34 UTC
  • mfrom: (2.1.8 edgy)
  • Revision ID: james.westby@ubuntu.com-20061104101934-mlirvdg4gpwi6i5q
Tags: 5.6.1-10
* Orphaning the package
* debian/control: Changed the maintainer to the Debian QA Group

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Jim - ANSI I/O extension
 
2
 * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
 
3
 *
 
4
 * $Id: jim-aio.c,v 1.1 2006/04/13 19:06:27 arjenmarkus Exp $
 
5
 *
 
6
 * Licensed under the Apache License, Version 2.0 (the "License");
 
7
 * you may not use this file except in compliance with the License.
 
8
 * You may obtain a copy of the License at
 
9
 *
 
10
 *     http://www.apache.org/licenses/LICENSE-2.0
 
11
 *
 
12
 * A copy of the license is also included in the source distribution
 
13
 * of Jim, as a TXT file name called LICENSE.
 
14
 *
 
15
 * Unless required by applicable law or agreed to in writing, software
 
16
 * distributed under the License is distributed on an "AS IS" BASIS,
 
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
18
 * See the License for the specific language governing permissions and
 
19
 * limitations under the License.
 
20
 */
 
21
 
 
22
#include <stdio.h>
 
23
#include <string.h>
 
24
#include <errno.h>
 
25
 
 
26
#define JIM_EXTENSION
 
27
#include "jim.h"
 
28
 
 
29
#define AIO_CMD_LEN 128
 
30
#define AIO_BUF_LEN 1024
 
31
 
 
32
typedef struct AioFile {
 
33
    FILE *fp;
 
34
    int keepOpen; /* If set, the file is not fclosed on cleanup (stdin, ...) */
 
35
} AioFile;
 
36
 
 
37
static void JimAioSetError(Jim_Interp *interp)
 
38
{
 
39
    Jim_SetResultString(interp, strerror(errno), -1);
 
40
}
 
41
 
 
42
static void JimAioDelProc(Jim_Interp *interp, void *privData)
 
43
{
 
44
    AioFile *af = privData;
 
45
    JIM_NOTUSED(interp);
 
46
 
 
47
    if (!af->keepOpen)
 
48
        fclose(af->fp);
 
49
    Jim_Free(af);
 
50
}
 
51
 
 
52
/* Calls to [aio.file] create commands that are implemented by this
 
53
 * C command. */
 
54
static int JimAioHandlerCommand(Jim_Interp *interp, int argc,
 
55
        Jim_Obj *const *argv)
 
56
{
 
57
    AioFile *af = Jim_CmdPrivData(interp);
 
58
    int option;
 
59
    const char *options[] = {
 
60
        "close", "seek", "tell", "gets", "read", "puts", "flush", "eof", NULL
 
61
    };
 
62
    enum {OPT_CLOSE, OPT_SEEK, OPT_TELL, OPT_GETS, OPT_READ, OPT_PUTS,
 
63
          OPT_FLUSH, OPT_EOF};
 
64
 
 
65
    if (argc < 2) {
 
66
        Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?");
 
67
        return JIM_ERR;
 
68
    }
 
69
    if (Jim_GetEnum(interp, argv[1], options, &option, "AIO method",
 
70
                JIM_ERRMSG) != JIM_OK)
 
71
        return JIM_ERR;
 
72
    /* CLOSE */
 
73
    if (option == OPT_CLOSE) {
 
74
        if (argc != 2) {
 
75
            Jim_WrongNumArgs(interp, 2, argv, "");
 
76
            return JIM_ERR;
 
77
        }
 
78
        Jim_DeleteCommand(interp, Jim_GetString(argv[0], NULL));
 
79
        return JIM_OK;
 
80
    } else if (option == OPT_SEEK) {
 
81
    /* SEEK */
 
82
        int orig = SEEK_SET;
 
83
        long offset;
 
84
 
 
85
        if (argc != 3 && argc != 4) {
 
86
            Jim_WrongNumArgs(interp, 2, argv, "offset ?origin?");
 
87
            return JIM_ERR;
 
88
        }
 
89
        if (argc == 4) {
 
90
            if (Jim_CompareStringImmediate(interp, argv[3], "start"))
 
91
                orig = SEEK_SET;
 
92
            else if (Jim_CompareStringImmediate(interp, argv[3], "current"))
 
93
                orig = SEEK_CUR;
 
94
            else if (Jim_CompareStringImmediate(interp, argv[3], "end"))
 
95
                orig = SEEK_END;
 
96
            else {
 
97
                Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
 
98
                Jim_AppendStrings(interp, Jim_GetResult(interp),
 
99
                        "bad origin \"", Jim_GetString(argv[3], NULL),
 
100
                        "\" must be: start, current, or end", NULL);
 
101
                return JIM_ERR;
 
102
            }
 
103
        }
 
104
        if (Jim_GetLong(interp, argv[2], &offset) != JIM_OK)
 
105
            return JIM_ERR;
 
106
        if (fseek(af->fp, offset, orig) == -1) {
 
107
            JimAioSetError(interp);
 
108
            return JIM_ERR;
 
109
        }
 
110
        return JIM_OK;
 
111
    } else if (option == OPT_TELL) {
 
112
    /* TELL */
 
113
        long position;
 
114
 
 
115
        if (argc != 2) {
 
116
            Jim_WrongNumArgs(interp, 2, argv, "");
 
117
            return JIM_ERR;
 
118
        }
 
119
        position = ftell(af->fp);
 
120
        Jim_SetResult(interp, Jim_NewIntObj(interp, position));
 
121
        return JIM_OK;
 
122
    } else if (option == OPT_GETS) {
 
123
    /* GETS */
 
124
        char buf[AIO_BUF_LEN];
 
125
        Jim_Obj *objPtr;
 
126
 
 
127
        if (argc != 2 && argc != 3) {
 
128
            Jim_WrongNumArgs(interp, 2, argv, "?varName?");
 
129
            return JIM_ERR;
 
130
        }
 
131
        objPtr = Jim_NewStringObj(interp, NULL, 0);
 
132
        while (1) {
 
133
            int more = 0;
 
134
            buf[AIO_BUF_LEN-1] = '_';
 
135
            if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
 
136
                break;
 
137
            if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN] == '\n')
 
138
                more = 1;
 
139
            if (more) {
 
140
                Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1);
 
141
            } else {
 
142
                /* strip "\n" */
 
143
                Jim_AppendString(interp, objPtr, buf, strlen(buf)-1);
 
144
            }
 
145
            if (!more)
 
146
                break;
 
147
        }
 
148
        if (ferror(af->fp)) {
 
149
            /* I/O error */
 
150
            Jim_IncrRefCount(objPtr);
 
151
            Jim_DecrRefCount(interp, objPtr);
 
152
            JimAioSetError(interp);
 
153
            return JIM_ERR;
 
154
        }
 
155
        /* On EOF returns -1 if varName was specified, or the empty string. */
 
156
        if (feof(af->fp) && Jim_Length(objPtr) == 0) {
 
157
            Jim_IncrRefCount(objPtr);
 
158
            Jim_DecrRefCount(interp, objPtr);
 
159
            if (argc == 3)
 
160
                Jim_SetResult(interp, Jim_NewIntObj(interp, -1));
 
161
            return JIM_OK;
 
162
        }
 
163
        if (argc == 3) {
 
164
            int totLen;
 
165
 
 
166
            Jim_GetString(objPtr, &totLen);
 
167
            if (Jim_SetVariable(interp, argv[2], objPtr) != JIM_OK) {
 
168
                Jim_IncrRefCount(objPtr);
 
169
                Jim_DecrRefCount(interp, objPtr);
 
170
                return JIM_ERR;
 
171
            }
 
172
            Jim_SetResult(interp, Jim_NewIntObj(interp, totLen));
 
173
        } else {
 
174
            Jim_SetResult(interp, objPtr);
 
175
        }
 
176
        return JIM_OK;
 
177
    } else if (option == OPT_READ) {
 
178
    /* READ */
 
179
        char buf[AIO_BUF_LEN];
 
180
        Jim_Obj *objPtr;
 
181
        int nonewline = 0;
 
182
        int neededLen = -1; /* -1 is "read as much as possible" */
 
183
 
 
184
        if (argc != 2 && argc != 3) {
 
185
            Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? ?len?");
 
186
            return JIM_ERR;
 
187
        }
 
188
        if (argc == 3 &&
 
189
            Jim_CompareStringImmediate(interp, argv[2], "-nonewline"))
 
190
        {
 
191
            nonewline = 1;
 
192
            argv++;
 
193
            argc--;
 
194
        }
 
195
        if (argc == 3) {
 
196
            jim_wide wideValue;
 
197
            if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK)
 
198
                return JIM_ERR;
 
199
            if (wideValue < 0) {
 
200
                Jim_SetResultString(interp, "invalid parameter: negative len",
 
201
                        -1);
 
202
                return JIM_ERR;
 
203
            }
 
204
            neededLen = (int) wideValue;
 
205
        }
 
206
        objPtr = Jim_NewStringObj(interp, NULL, 0);
 
207
        while (neededLen != 0) {
 
208
            int retval;
 
209
            int readlen;
 
210
 
 
211
            if (neededLen == -1) {
 
212
                readlen = AIO_BUF_LEN;
 
213
            } else {
 
214
                readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
 
215
            }
 
216
            retval = fread(buf, 1, readlen, af->fp);
 
217
            if (retval > 0) {
 
218
                Jim_AppendString(interp, objPtr, buf, retval);
 
219
                if (neededLen != -1) {
 
220
                    neededLen -= retval;
 
221
                }
 
222
            }
 
223
            if (retval != readlen) break;
 
224
        }
 
225
        /* Check for error conditions */
 
226
        if (ferror(af->fp)) {
 
227
            /* I/O error */
 
228
            Jim_FreeNewObj(interp, objPtr);
 
229
            JimAioSetError(interp);
 
230
            return JIM_ERR;
 
231
        }
 
232
        if (nonewline) {
 
233
            int len;
 
234
            const char *s = Jim_GetString(objPtr, &len);
 
235
 
 
236
            if (len > 0 && s[len-1] == '\n') {
 
237
                objPtr->length--;
 
238
                objPtr->bytes[objPtr->length] = '\0';
 
239
            }
 
240
        }
 
241
        Jim_SetResult(interp, objPtr);
 
242
        return JIM_OK;
 
243
    } else if (option == OPT_PUTS) {
 
244
    /* PUTS */
 
245
        unsigned int wlen;
 
246
        const char *wdata;
 
247
 
 
248
        if (argc != 3 && (argc != 4 || !Jim_CompareStringImmediate(
 
249
                        interp, argv[2], "-nonewline"))) {
 
250
            Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? string");
 
251
            return JIM_ERR;
 
252
        }
 
253
        wdata = Jim_GetString(argv[2+(argc==4)], &wlen);
 
254
        if (fwrite(wdata, 1, wlen, af->fp) != wlen ||
 
255
            (argc == 3 && fwrite("\n", 1, 1, af->fp) != 1)) {
 
256
            JimAioSetError(interp);
 
257
            return JIM_ERR;
 
258
        }
 
259
        return JIM_OK;
 
260
    } else if (option  == OPT_FLUSH) {
 
261
    /* FLUSH */
 
262
        if (argc != 2) {
 
263
            Jim_WrongNumArgs(interp, 2, argv, "");
 
264
            return JIM_ERR;
 
265
        }
 
266
        if (fflush(af->fp) == EOF) {
 
267
            JimAioSetError(interp);
 
268
            return JIM_ERR;
 
269
        }
 
270
        return JIM_OK;
 
271
    } else if (option  == OPT_EOF) {
 
272
    /* EOF */
 
273
        if (argc != 2) {
 
274
            Jim_WrongNumArgs(interp, 2, argv, "");
 
275
            return JIM_ERR;
 
276
        }
 
277
        Jim_SetResult(interp, Jim_NewIntObj(interp, feof(af->fp)));
 
278
        return JIM_OK;
 
279
    }
 
280
    return JIM_OK;
 
281
}
 
282
 
 
283
static int JimAioOpenCommand(Jim_Interp *interp, int argc,
 
284
        Jim_Obj *const *argv)
 
285
{
 
286
    FILE *fp;
 
287
    AioFile *af;
 
288
    char buf[AIO_CMD_LEN];
 
289
    const char *mode = "r";
 
290
    Jim_Obj *objPtr;
 
291
    long fileId;
 
292
    const char *options[] = {"input", "output", "error"};
 
293
    enum {OPT_INPUT, OPT_OUTPUT, OPT_ERROR};
 
294
    int keepOpen = 0, modeLen;
 
295
 
 
296
    if (argc != 2 && argc != 3) {
 
297
        Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?");
 
298
        return JIM_ERR;
 
299
    }
 
300
    if (argc == 3)
 
301
        mode = Jim_GetString(argv[2], &modeLen);
 
302
    if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "standard") &&
 
303
            modeLen >= 3) {
 
304
            int option;
 
305
        if (Jim_GetEnum(interp, argv[2], options, &option, "standard channel",
 
306
                    JIM_ERRMSG) != JIM_OK)
 
307
            return JIM_ERR;
 
308
        keepOpen = 1;
 
309
        switch (option) {
 
310
        case OPT_INPUT: fp = stdin; break;
 
311
        case OPT_OUTPUT: fp = stdout; break;
 
312
        case OPT_ERROR: fp = stderr; break;
 
313
        default: fp = NULL; Jim_Panic("default reached in JimAioOpenCommand()");
 
314
                 break;
 
315
        }
 
316
    } else {
 
317
        fp = fopen(Jim_GetString(argv[1], NULL), mode);
 
318
        if (fp == NULL) {
 
319
            JimAioSetError(interp);
 
320
            return JIM_ERR;
 
321
        }
 
322
    }
 
323
    /* Get the next file id */
 
324
    if (Jim_EvalGlobal(interp,
 
325
                "if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK)
 
326
        return JIM_ERR;
 
327
    objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG);
 
328
    if (objPtr == NULL) return JIM_ERR;
 
329
    if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR;
 
330
 
 
331
    /* Create the file command */
 
332
    af = Jim_Alloc(sizeof(*af));
 
333
    af->fp = fp;
 
334
    af->keepOpen = keepOpen;
 
335
    sprintf(buf, "aio.handle%ld", fileId);
 
336
    Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
 
337
    Jim_SetResultString(interp, buf, -1);
 
338
    return JIM_OK;
 
339
}
 
340
 
 
341
#ifdef WIN32
 
342
__declspec(dllexport)
 
343
#endif
 
344
int Jim_OnLoad(Jim_Interp *interp)
 
345
{
 
346
    Jim_InitExtension(interp);
 
347
    if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG) != JIM_OK)
 
348
        return JIM_ERR;
 
349
    Jim_CreateCommand(interp, "aio.open", JimAioOpenCommand, NULL, NULL);
 
350
    return JIM_OK;
 
351
}