root/NEWT0/trunk/src/newt_core/NewtIO.c

Revision 113, 9.8 kB (checked in by gnue, 17 months ago)

'#pragma mark' is invalidated by '#if 0'

Line 
1/*------------------------------------------------------------------------*/
2/**
3 * @file    NewtIO.c
4 * @brief   入出力処理
5 *
6 * @author M.Nukui
7 * @date 2004-06-05
8 *
9 * Copyright (C) 2003-2004 M.Nukui All rights reserved.
10 */
11
12
13/* ヘッダファイル */
14#include <string.h>
15#include <stdio.h>
16#include <errno.h>
17
18#include "NewtCore.h"
19#include "NewtIO.h"
20
21#if defined(HAVE_TERMIOS_H)
22    #include <termios.h>
23    #include <unistd.h>
24    #include <sys/select.h>
25#elif defined(__WIN32__)
26    #include <conio.h>
27#endif
28
29
30/* マクロ */
31#if defined(HAVE_TERMIOS_H)
32    #define newt_getch()    tcgetch(0)
33#elif defined(__WIN32__)
34    #define newt_getch()    getch()
35#else
36    #define newt_getch()    (0)
37#endif
38
39
40/* 関数プロトタイプ */
41static int  cbreak_and_noecho(int fd, int vmin, struct termios *tiosp);
42static int  tcgetch(int fd);
43
44
45/*------------------------------------------------------------------------*/
46/** 入出力ストリーム構造体にファイルの情報をセットする
47 *
48 * @param stream    [out]入出力ストリーム
49 * @param f         [in] ファイル
50 *
51 * @return          なし
52 */
53
54void NIOSetFile(newtStream_t * stream, FILE * f)
55{
56    stream->file = f;
57
58    if (f == stdout)
59        stream->obj = NcGetGlobalVar(NSSYM0(_STDOUT_));
60    else if (f == stderr)
61        stream->obj = NcGetGlobalVar(NSSYM0(_STDERR_));
62    else
63        stream->obj = kNewtRefUnbind;
64}
65
66
67/*------------------------------------------------------------------------*/
68/** printf フォーマットで出力する(不定長)
69 *
70 * @param stream    [in] 出力ストリーム
71 * @param format    [in] フォーマット
72 * @param ...       [in] printf 引数
73 *
74 * @return          printf の戻り値
75 *
76 * @note            newtStream_t を使用
77 */
78
79int NIOFprintf(newtStream_t * stream, const char * format, ...)
80{
81    va_list args;
82    int     result;
83
84    va_start(args, format);
85    result = NIOVfprintf(stream, format, args);
86    va_end(args);
87
88    return result;
89}
90
91
92/*------------------------------------------------------------------------*/
93/** vprintf フォーマットで出力する
94 *
95 * @param stream    [in] 出力ストリーム
96 * @param format    [in] フォーマット
97 * @param ap        [in] vprintf 引数
98 *
99 * @return          vprintf の戻り値
100 *
101 * @note            newtStream_t を使用
102 *                  文字列に追加する場合の制限 NEWT_SNPRINTF_BUFFSIZE (NewtConf.h)
103 */
104
105int NIOVfprintf(newtStream_t * stream, const char * format, va_list ap)
106{
107    int     result = 0;
108
109    if (NewtRefIsString(stream->obj))
110    {
111        char    wk[NEWT_SNPRINTF_BUFFSIZE];
112
113        result = vsnprintf(wk, sizeof(wk), format, ap);
114
115        if (0 < result)
116        {
117            if (sizeof(wk) < result)
118                wk[sizeof(wk) - 1] = '\0';
119
120            NewtStrCat(stream->obj, wk);
121        }
122    }
123    else
124    {
125        result = vfprintf(stream->file, format, ap);
126    }
127
128    return result;
129}
130
131
132/*------------------------------------------------------------------------*/
133/** 文字を出力する
134 *
135 * @param c         [in] 文字
136 * @param stream    [in] 出力ストリーム
137 *
138 * @return          fputc の戻り値
139 *
140 * @note            newtStream_t を使用
141 */
142
143int NIOFputc(int c, newtStream_t * stream)
144{
145    int     result = 0;
146
147    if (NewtRefIsString(stream->obj))
148    {
149        char    wk[4];
150
151        sprintf(wk, "%c", c);
152        NewtStrCat(stream->obj, wk);
153    }
154    else
155    {
156        result = fputc(c, stream->file);
157    }
158
159    return result;
160}
161
162
163/*------------------------------------------------------------------------*/
164/** 文字列を出力する
165 *
166 * @param str       [in] 文字列
167 * @param stream    [in] 出力ストリーム
168 *
169 * @return          fputs の戻り値
170 *
171 * @note            newtStream_t を使用
172 */
173
174int NIOFputs(const char *str, newtStream_t * stream)
175{
176    int     result = 0;
177
178    if (NewtRefIsString(stream->obj))
179    {
180        NewtStrCat(stream->obj, (char *)str);
181    }
182    else
183    {
184        result = fputs(str, stream->file);
185    }
186
187    return result;
188}
189
190
191#if 0
192#pragma mark -
193#endif
194/*------------------------------------------------------------------------*/
195/** printf フォーマットで出力する(不定長)
196 *
197 * @param f         [in] 出力ストリーム
198 * @param format    [in] フォーマット
199 * @param ...       [in] printf 引数
200 *
201 * @return          printf の戻り値
202 */
203
204int NewtFprintf(FILE * f, const char * format, ...)
205{
206    newtStream_t    stream;
207    va_list args;
208    int     result;
209
210    NIOSetFile(&stream, f);
211
212    va_start(args, format);
213    result = NIOVfprintf(&stream, format, args);
214    va_end(args);
215
216    return result;
217}
218
219
220/*------------------------------------------------------------------------*/
221/** 文字の出力
222 *
223 * @param c         [in] 文字
224 * @param f         [in] 出力ストリーム
225 *
226 * @return          fputc の戻り値
227 */
228
229int NewtFputc(int c, FILE * f)
230{
231    newtStream_t    stream;
232
233    NIOSetFile(&stream, f);
234    return NIOFputc(c, &stream);
235}
236
237
238/*------------------------------------------------------------------------*/
239/** 文字の出力
240 *
241 * @param str       [in] 文字列
242 * @param f         [in] 出力ストリーム
243 *
244 * @return          fputs の戻り値
245 */
246
247int NewtFputs(const char *str, FILE * f)
248{
249    newtStream_t    stream;
250
251    NIOSetFile(&stream, f);
252    return NIOFputs(str, &stream);
253}
254
255
256#if 0
257#pragma mark -
258#endif
259/*------------------------------------------------------------------------*/
260/** printf フォーマットで出力する(不定長)
261 *
262 * @param title     [in] タイトル
263 * @param format    [in] フォーマット
264 * @param ...       [in] printf 引数
265 *
266 * @return          printf の戻り値
267 */
268
269int NewtDebugMsg(const char * title, const char * format, ...)
270{
271    newtStream_t    stream;
272    va_list args;
273    int     result;
274
275    NIOSetFile(&stream, stderr);
276
277    if (title != NULL)
278    {
279        NIOFputs("[", &stream);
280        NIOFputs(title, &stream);
281        NIOFputs("] ", &stream);
282    }
283
284    va_start(args, format);
285    result = NIOVfprintf(&stream, format, args);
286    va_end(args);
287
288    return result;
289}
290
291
292#if 0
293#pragma mark -
294#endif
295/*------------------------------------------------------------------------*/
296/** 入力ストリームから文字列を取出す
297 *
298 * @param stream    [in] 入力ストリーム
299 *
300 * @retval          文字列オブジェクト   入力データが存在する場合
301 * @retval          NIL             入力データが存在しない場合
302 *
303 * @note            制限 NEWT_FGETS_BUFFSIZE (NewtConf.h)
304 */
305
306newtRef NewtFgets(FILE * stream)
307{
308    newtRefVar  result = kNewtRefNIL;
309    char    buff[NEWT_FGETS_BUFFSIZE];
310    char *  str;
311    char    c;
312    int     maxsize;
313    int     oldlen;
314    int     len;
315
316    maxsize = sizeof(buff) - 1;
317
318    while (str = fgets(buff, sizeof(buff), stream))
319    {
320        len = strlen(str);
321
322        if (result == kNewtRefNIL)
323        {   // 文字列オブジェクト作成
324            result = NewtMakeString2(str, len, false);
325
326            if (NewtRefIsNIL(result))
327            {   // メモリを確保できなかった
328                return NewtThrow0(kNErrOutOfObjectMemory);
329            }
330        }
331        else
332        {   // 追加
333            oldlen = NewtStringLength(result);
334            result = NewtStrCat2(result, str, len);
335
336            if (NewtStringLength(result) < oldlen + len)
337            {   // メモリを確保できなかった
338                return NewtThrow0(kNErrOutOfObjectMemory);
339            }
340        }
341
342        if (len < maxsize)
343            break;
344
345        // 最後の文字をチェック
346        c = buff[maxsize - 1];
347
348        if (c == '\n')
349            break;
350
351        if (c == '\r')
352        {
353            // 1文字先読み
354            c = fgetc(stream);
355
356            if (c != '\n')
357            {   // CRLF でない(CR のみ)場合
358                // 先読みした文字をストリームに戻す
359                ungetc(c, stream);
360                break;
361            }
362        }
363    }
364
365    return result;
366}
367
368
369/*------------------------------------------------------------------------*/
370/** 標準入力から文字列を取出す
371 *
372 * @param rcvr      [in] レシーバ
373 *
374 * @retval          文字列オブジェクト   入力データが存在する場合
375 * @retval          NIL             入力データが存在しない場合
376 */
377
378newtRef NsGets(newtRefArg rcvr)
379{
380    return NewtFgets(stdin);
381}
382
383
384/*------------------------------------------------------------------------*/
385/** 入力ストリームから文字を取出す
386 *
387 * @param stream    [in] 入力ストリーム
388 *
389 * @retval          文字オブジェクト    入力データが存在する場合
390 * @retval          NIL             EOF
391 */
392
393newtRef NewtFgetc(FILE * stream)
394{
395    int     c;
396
397    c = fgetc(stream);
398
399    if (c == EOF)
400        return kNewtRefNIL;
401    else
402        return NewtMakeCharacter(c);
403}
404
405
406/*------------------------------------------------------------------------*/
407/** 標準入力から文字を取出す
408 *
409 * @param rcvr      [in] レシーバ
410 *
411 * @retval          文字オブジェクト    入力データが存在する場合
412 * @retval          NIL             入力データが存在しない場合
413 */
414
415newtRef NsGetc(newtRefArg rcvr)
416{
417    return NewtFgetc(stdin);
418}
419
420
421#ifdef HAVE_TERMIOS_H
422
423/*------------------------------------------------------------------------*/
424/** ターミナルを非カノニカルモードおよびエコーなしに設定する
425 *
426 * @param fd        [in] ターミナル
427 * @param vmin      [in] 非カノニカル読み込み時の最小文字数
428 * @param tiosp     [out]変更前の termios構造体
429 *
430 * @retval          0           正常終了
431 * @retval          0以外     エラー
432 */
433
434int cbreak_and_noecho(int fd, int vmin, struct termios *tiosp)
435{
436    struct termios  tios;
437    int     err;
438
439    err = tcgetattr(fd, &tios);
440    if (err) return err;
441
442    if (tiosp) *tiosp = tios;
443
444    tios.c_lflag &= ~ (ICANON | ECHO);
445    tios.c_cc[VTIME] = 0;
446    tios.c_cc[VMIN] = vmin;
447    err = tcsetattr(fd, TCSANOW, &tios);
448
449    return err;
450}
451
452
453/*------------------------------------------------------------------------*/
454/** ターミナルから入力文字を1文字取得
455 *
456 * @param fd        [in] ターミナル
457 *
458 * @retval          文字データ   入力データが存在する場合
459 * @retval          0           入力データが存在しない場合
460 */
461
462int tcgetch(int fd)
463{
464    struct termios  tios;
465    char    buf[1];
466    int     c = 0;
467    int     err;
468
469    err = cbreak_and_noecho(fd, 1, &tios);
470    if (err) return -1;
471
472    if (0 < read(fd, buf, sizeof(buf)))
473        c = buf[0];
474
475    tcsetattr(fd, TCSANOW, &tios);
476
477    return c;
478}
479
480
481#endif /* HAVE_TERMIOS_H */
482
483
484/*------------------------------------------------------------------------*/
485/** キーボードから入力文字を1文字取得
486 *
487 * @param rcvr      [in] レシーバ
488 *
489 * @retval          文字オブジェクト    入力データが存在する場合
490 * @retval          NIL             入力データが存在しない場合
491 */
492
493newtRef NsGetch(newtRefArg rcvr)
494{
495    int     c;
496
497    c = newt_getch();
498
499    if (c)
500        return NewtMakeCharacter(c);
501    else
502        return kNewtRefNIL;
503}
Note: See TracBrowser for help on using the browser.