diff --git a/qse/cmd/awk/Awk.cpp b/qse/cmd/awk/Awk.cpp index 3709e650..ca819a2f 100644 --- a/qse/cmd/awk/Awk.cpp +++ b/qse/cmd/awk/Awk.cpp @@ -244,6 +244,9 @@ protected: sa_int.sa_handler = stop_run; sigemptyset (&sa_int.sa_mask); sa_int.sa_flags = 0; + #ifdef SA_RESTART + sa_int.sa_flags |= SA_RESTART; + #endif sigaction (SIGINT, &sa_int, NULL); #endif diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index e7696bdc..bcaff467 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -58,6 +58,7 @@ static void dprint (const qse_char_t* fmt, ...) } } + #ifdef _WIN32 static BOOL WINAPI stop_run (DWORD ctrl_type) { @@ -71,12 +72,38 @@ static BOOL WINAPI stop_run (DWORD ctrl_type) return FALSE; } #else + +static int setsignal (int sig, void(*handler)(int), int restart) +{ + struct sigaction sa_int; + + sa_int.sa_handler = handler; + sigemptyset (&sa_int.sa_mask); + + sa_int.sa_flags = 0; + + if (restart) + { + #ifdef SA_RESTART + sa_int.sa_flags |= SA_RESTART; + #endif + } + else + { + #ifdef SA_INTERRUPT + sa_int.sa_flags |= SA_INTERRUPT; + #endif + } + return sigaction (sig, &sa_int, NULL); +} + static void stop_run (int sig) { int e = errno; qse_awk_stop (app_run); errno = e; } + #endif static void set_intr_run (void) @@ -84,14 +111,7 @@ static void set_intr_run (void) #ifdef _WIN32 SetConsoleCtrlHandler (stop_run, TRUE); #else - { - struct sigaction sa_int; - - sa_int.sa_handler = stop_run; - sigemptyset (&sa_int.sa_mask); - sa_int.sa_flags = 0; - sigaction (SIGINT, &sa_int, NULL); - } + setsignal (SIGINT, stop_run, 1); #endif } @@ -100,14 +120,7 @@ static void unset_intr_run (void) #ifdef _WIN32 SetConsoleCtrlHandler (stop_run, FALSE); #else - { - struct sigaction sa_int; - - sa_int.sa_handler = SIG_DFL; - sigemptyset (&sa_int.sa_mask); - sa_int.sa_flags = 0; - sigaction (SIGINT, &sa_int, NULL); - } + setsignal (SIGINT, SIG_DFL, 1); #endif } diff --git a/qse/cmd/awk/t10.awk b/qse/cmd/awk/t10.awk index f562146f..b2d59ffe 100644 --- a/qse/cmd/awk/t10.awk +++ b/qse/cmd/awk/t10.awk @@ -1,21 +1,24 @@ BEGIN { print "more"; - //print | "more"; - //print > "echo"; - //print >> "echo"; + #print | "more"; + #print > "echo"; + #print >> "echo"; getline x < "abc"; /* open("abc", O_RDONLY|O_LARGEFILE) = 3 */ - //print 10 >> "abc"; /* open("abc", O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE, 0666) = 4 */ + #print 10 >> "abc"; /* open("abc", O_WRONLY|O_APPEND|O_CREAT|O_LARGEFILE, 0666) = 4 */ getline x < "abc"; - //print x; + #print x; a = close ("abc"); /* close(4) */ print "a=" a; - //print "hey" + #print "hey" b = close ("abc"); /* close(3) */ print "b=" b; getline x < "Makefile.cl"; getline y < "awk.c"; + + print x; + print y; c = close ("Makefile.cl"); d = close ("awk.c"); diff --git a/qse/configure b/qse/configure index 5ffd4bce..381f3b61 100755 --- a/qse/configure +++ b/qse/configure @@ -21640,7 +21640,8 @@ fi -for ac_header in stddef.h wchar.h wctype.h sys/syscall.h + +for ac_header in stddef.h wchar.h wctype.h errno.h sys/syscall.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then diff --git a/qse/configure.ac b/qse/configure.ac index 3b162642..9b8ca2c3 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -83,7 +83,7 @@ AC_SUBST(LIBM, $LIBM) dnl check header files. AC_HEADER_STDC -AC_CHECK_HEADERS([stddef.h wchar.h wctype.h sys/syscall.h]) +AC_CHECK_HEADERS([stddef.h wchar.h wctype.h errno.h sys/syscall.h]) dnl check data types AC_CHECK_TYPE([wchar_t], diff --git a/qse/include/qse/cmn/fio.h b/qse/include/qse/cmn/fio.h index 4782023e..8b8bcbea 100644 --- a/qse/include/qse/cmn/fio.h +++ b/qse/include/qse/cmn/fio.h @@ -22,25 +22,30 @@ #include #include +#include + enum qse_fio_open_flag_t { + /* request qse_char_io based IO */ + QSE_FIO_TEXT = (1 << 0), + /* treat the file name pointer as a handle pointer */ - QSE_FIO_HANDLE = (1 << 0), + QSE_FIO_HANDLE = (1 << 1), - QSE_FIO_READ = (1 << 1), - QSE_FIO_WRITE = (1 << 2), - QSE_FIO_APPEND = (1 << 3), + QSE_FIO_READ = (1 << 8), + QSE_FIO_WRITE = (1 << 9), + QSE_FIO_APPEND = (1 << 10), - QSE_FIO_CREATE = (1 << 4), - QSE_FIO_TRUNCATE = (1 << 5), - QSE_FIO_EXCLUSIVE = (1 << 6), - QSE_FIO_SYNC = (1 << 7), + QSE_FIO_CREATE = (1 << 11), + QSE_FIO_TRUNCATE = (1 << 12), + QSE_FIO_EXCLUSIVE = (1 << 13), + QSE_FIO_SYNC = (1 << 14), /* for WIN32 only. harmless(no effect) when used on other platforms */ - QSE_FIO_NOSHRD = (1 << 16), - QSE_FIO_NOSHWR = (1 << 17), - QSE_FIO_RANDOM = (1 << 18), /* hint that access be random */ - QSE_FIO_SEQUENTIAL = (1 << 19) /* hint that access is sequential */ + QSE_FIO_NOSHRD = (1 << 24), + QSE_FIO_NOSHWR = (1 << 25), + QSE_FIO_RANDOM = (1 << 26), /* hint that access be random */ + QSE_FIO_SEQUENTIAL = (1 << 27) /* hint that access is sequential */ }; /* seek origin */ @@ -68,10 +73,10 @@ enum qse_fio_mode_t }; #ifdef _WIN32 -/* => typedef PVOID HANDLE; */ -typedef void* qse_fio_hnd_t; + /* => typedef PVOID HANDLE; */ + typedef void* qse_fio_hnd_t; #else -typedef int qse_fio_hnd_t; + typedef int qse_fio_hnd_t; #endif /* file offset */ @@ -83,8 +88,9 @@ typedef struct qse_fio_lck_t qse_fio_lck_t; struct qse_fio_t { - qse_mmgr_t* mmgr; + QSE_DEFINE_STD_FIELDS (fio) qse_fio_hnd_t handle; + qse_tio_t* tio; }; struct qse_fio_lck_t @@ -102,6 +108,8 @@ struct qse_fio_lck_t extern "C" { #endif +QSE_DEFINE_STD_FUNCTIONS (fio) + /****f* qse.fio/qse_fio_open * NAME * qse_fio_open - open a file @@ -144,9 +152,15 @@ void qse_fio_fini ( qse_fio_t* fio ); +/****f* qse.cmn.fio/qse_fio_gethandle + * NAME + * qse_fio_gethandle - get the native file handle + * SYNOPSIS + */ qse_fio_hnd_t qse_fio_gethandle ( qse_fio_t* fio ); +/******/ /****f* qse.cmn.fio/qse_fio_sethandle * NAME @@ -174,17 +188,45 @@ int qse_fio_truncate ( qse_fio_off_t size ); +/****f* qse.cmn.fio/qse_fio_read + * NAME + * qse_fio_read - read data + * SYNOPSIS + */ qse_ssize_t qse_fio_read ( - qse_fio_t* fio, - void* buf, - qse_size_t size + qse_fio_t* fio, + void* buf, + qse_size_t size ); +/******/ +/****f* qse.cmn.fio/qse_fio_write + * NAME + * qse_fio_write - write data + * SYNOPSIS + */ qse_ssize_t qse_fio_write ( - qse_fio_t* fio, - const void* buf, - qse_size_t size + qse_fio_t* fio, + const void* data, + qse_size_t size ); +/******/ + + +/****f* qse.cmn.fio/qse_fio_flush + * NAME + * qse_fio_flush - flush data + * + * DESCRIPTION + * The qse_fio_flush() function is useful if QSE_FIO_TEXT is used in + * qse_fio_open (). + * + * SYNOPSIS + */ +qse_ssize_t qse_fio_flush ( + qse_fio_t* fio +); +/******/ /****f* qse.cmn.fio/qse_fio_chmod * NAME diff --git a/qse/include/qse/cmn/io.h b/qse/include/qse/cmn/io.h deleted file mode 100644 index e8371a2a..00000000 --- a/qse/include/qse/cmn/io.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * $Id: sysapi.h,v 1.56 2006/03/21 16:15:16 bacon Ease $ - * - Copyright 2006-2008 Chung, Hyung-Hwan. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#ifndef _QSE_CMN_IO_H_ -#define _QSE_CMN_IO_H_ - -#include -#include - -/* flags for qse_open */ -enum -{ - QSE_OPEN_READ = (1 << 0), - QSE_OPEN_WRITE = (1 << 1), - QSE_OPEN_CREATE = (1 << 2), - QSE_OPEN_TRUNCATE = (1 << 3), - QSE_OPEN_EXCLUSIVE = (1 << 4), - QSE_OPEN_APPEND = (1 << 5), - QSE_OPEN_NONBLOCK = (1 << 6) -}; - -/* origin for qse_seek */ -enum -{ - QSE_SEEK_BEGIN = 0, - QSE_SEEK_CURRENT = 1, - QSE_SEEK_END = 2 -}; - -#ifdef __cplusplus -extern "C" { -#endif - -qse_hnd_t qse_open ( - const qse_char_t* path, - int flag, - ... -); - -int qse_close ( - qse_hnd_t handle -); - -qse_ssize_t qse_read ( - qse_hnd_t handle, - void* buf, - qse_size_t sz -); - -qse_ssize_t qse_write ( - qse_hnd_t handle, - const void* data, - qse_size_t sz -); - -qse_off_t qse_seek ( - qse_hnd_t handle, - qse_off_t offset, - int origin -); - -/* -int qse_hstat (qse_hnd_t handle, qse_stat_t* buf); -int qse_hchmod (qse_hnd_t handle, qse_mode_t mode); -*/ -int qse_htruncate (qse_hnd_t handle, qse_off_t size); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/qse/include/qse/cmn/pcp.h b/qse/include/qse/cmn/pcp.h index 495b7cab..a828d981 100644 --- a/qse/include/qse/cmn/pcp.h +++ b/qse/include/qse/cmn/pcp.h @@ -27,26 +27,27 @@ enum qse_pcp_open_flag_t { - QSE_PCP_WRITEIN = (1 << 0), - QSE_PCP_READOUT = (1 << 1), - QSE_PCP_READERR = (1 << 2), - - QSE_PCP_ERRTOOUT = (1 << 3), - QSE_PCP_OUTTOERR = (1 << 4), - - QSE_PCP_INTONUL = (1 << 5), - QSE_PCP_ERRTONUL = (1 << 6), - QSE_PCP_OUTTONUL = (1 << 7), - - QSE_PCP_DROPIN = (1 << 8), - QSE_PCP_DROPOUT = (1 << 9), - QSE_PCP_DROPERR = (1 << 10), - - /* invoke the command through a default system shell */ - QSE_PCP_SHELL = (1 << 11), - /* enable ase_char_t based IO */ - QSE_PCP_TEXT = (1 << 12) + QSE_PCP_TEXT = (1 << 0), + + /* invoke the command through a system shell + * (/bin/sh on *nix, command.com on windows) */ + QSE_PCP_SHELL = (1 << 1), + + QSE_PCP_WRITEIN = (1 << 8), + QSE_PCP_READOUT = (1 << 9), + QSE_PCP_READERR = (1 << 10), + + QSE_PCP_ERRTOOUT = (1 << 11), + QSE_PCP_OUTTOERR = (1 << 12), + + QSE_PCP_INTONUL = (1 << 13), + QSE_PCP_ERRTONUL = (1 << 14), + QSE_PCP_OUTTONUL = (1 << 15), + + QSE_PCP_DROPIN = (1 << 16), + QSE_PCP_DROPOUT = (1 << 17), + QSE_PCP_DROPERR = (1 << 18) }; enum qse_pcp_wait_flag_t diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 7101546e..ad53568b 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -30,6 +30,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + /* Define to 1 if you have the `exp' function. */ #undef HAVE_EXP diff --git a/qse/include/qse/macros.h b/qse/include/qse/macros.h index 47a65bfa..241f92eb 100644 --- a/qse/include/qse/macros.h +++ b/qse/include/qse/macros.h @@ -73,10 +73,13 @@ #define QSE_ABS(x) ((x) < 0? -(x): (x)) -#define QSE_LOOP_CONTINUE(id) goto __loop_ ## id ## _begin__; -#define QSE_LOOP_BREAK(id) goto __loop_ ## id ## _end__; +#define QSE_ERR_THROW(id) goto __err_ ## id +#define QSE_ERR_CATCH(id) while(0) __err_ ## id: + +#define QSE_LOOP_CONTINUE(id) goto __loop_ ## id ## _begin__ +#define QSE_LOOP_BREAK(id) goto __loop_ ## id ## _end__ #define QSE_LOOP_BEGIN(id) __loop_ ## id ## _begin__: { -#define QSE_LOOP_END(id) QSE_LOOP_CONTINUE(id) } __loop_ ## id ## _end__:; +#define QSE_LOOP_END(id) QSE_LOOP_CONTINUE(id) } __loop_ ## id ## _end__: #define QSE_REPEAT(n,blk) \ do { \ diff --git a/qse/lib/cmn/fio.c b/qse/lib/cmn/fio.c index 022edd74..14ba063a 100644 --- a/qse/lib/cmn/fio.c +++ b/qse/lib/cmn/fio.c @@ -21,16 +21,21 @@ #include "mem.h" #ifdef _WIN32 -#include -#include -#include +# include +# include +# include #else -#include "syscall.h" -#include -#include -#include +# include "syscall.h" +# include +# include +# include #endif +QSE_IMPLEMENT_STD_FUNCTIONS (fio) + +static qse_ssize_t fio_input (int cmd, void* arg, void* buf, qse_size_t size); +static qse_ssize_t fio_output (int cmd, void* arg, void* buf, qse_size_t size); + qse_fio_t* qse_fio_open ( qse_mmgr_t* mmgr, qse_size_t ext, const qse_char_t* path, int flags, int mode) @@ -198,12 +203,41 @@ qse_fio_t* qse_fio_init ( #endif + if (flags & QSE_FIO_TEXT) + { + qse_tio_t* tio; + + tio = qse_tio_open (fio->mmgr, 0); + if (tio == QSE_NULL) QSE_ERR_THROW (tio); + + if (qse_tio_attachin (tio, fio_input, fio) < 0 || + qse_tio_attachout (tio, fio_output, fio) < 0) + { + qse_tio_close (tio); + QSE_ERR_THROW (tio); + } + + QSE_ERR_CATCH (tio) + { + #ifdef _WIN32 + CloseHandle (handle); + #else + QSE_CLOSE (handle); + #endif + return QSE_NULL; + } + + fio->tio = tio; + } + fio->handle = handle; + return fio; } void qse_fio_fini (qse_fio_t* fio) { + if (fio->tio != QSE_NULL) qse_tio_close (fio->tio); #ifdef _WIN32 CloseHandle (fio->handle); #else @@ -301,7 +335,7 @@ int qse_fio_truncate (qse_fio_t* fio, qse_fio_off_t size) #endif } -qse_ssize_t qse_fio_read (qse_fio_t* fio, void* buf, qse_size_t size) +static qse_ssize_t fio_read (qse_fio_t* fio, void* buf, qse_size_t size) { #ifdef _WIN32 DWORD count; @@ -314,7 +348,15 @@ qse_ssize_t qse_fio_read (qse_fio_t* fio, void* buf, qse_size_t size) #endif } -qse_ssize_t qse_fio_write (qse_fio_t* fio, const void* data, qse_size_t size) +qse_ssize_t qse_fio_read (qse_fio_t* fio, void* buf, qse_size_t size) +{ + if (fio->tio == QSE_NULL) + return fio_read (fio, buf, size); + else + return qse_tio_read (fio->tio, buf, size); +} + +static qse_ssize_t fio_write (qse_fio_t* fio, const void* data, qse_size_t size) { #ifdef _WIN32 DWORD count; @@ -327,6 +369,21 @@ qse_ssize_t qse_fio_write (qse_fio_t* fio, const void* data, qse_size_t size) #endif } +qse_ssize_t qse_fio_write (qse_fio_t* fio, const void* data, qse_size_t size) +{ + if (fio->tio == QSE_NULL) + return fio_write (fio, data, size); + else + return qse_tio_write (fio->tio, data, size); +} + +qse_ssize_t qse_fio_flush (qse_fio_t* fio) +{ + if (fio->tio == QSE_NULL) return 0; + return qse_tio_flush (fio->tio); +} + + #ifdef _WIN32 static int get_devname_from_handle ( @@ -470,3 +527,31 @@ int qse_fio_unlock (qse_fio_t* fio, qse_fio_lck_t* lck, int flags) */ return -1; } + +static qse_ssize_t fio_input (int cmd, void* arg, void* buf, qse_size_t size) +{ + qse_fio_t* fio = (qse_fio_t*)arg; + QSE_ASSERT (fio != QSE_NULL); + if (cmd == QSE_TIO_IO_DATA) + { + return fio_read (fio, buf, size); + } + + /* take no actions for OPEN and CLOSE as they are handled + * by fio */ + return 0; +} + +static qse_ssize_t fio_output (int cmd, void* arg, void* buf, qse_size_t size) +{ + qse_fio_t* fio = (qse_fio_t*)arg; + QSE_ASSERT (fio != QSE_NULL); + if (cmd == QSE_TIO_IO_DATA) + { + return fio_write (fio, buf, size); + } + + /* take no actions for OPEN and CLOSE as they are handled + * by fio */ + return 0; +} diff --git a/qse/lib/cmn/pcp.c b/qse/lib/cmn/pcp.c index 534f45b1..bc6d22b3 100644 --- a/qse/lib/cmn/pcp.c +++ b/qse/lib/cmn/pcp.c @@ -26,7 +26,6 @@ #else # include "syscall.h" # include -# include # include #endif diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index 6c59d851..4acfbff2 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -15,6 +15,9 @@ #ifdef HAVE_SIGNAL_H #include #endif +#ifdef HAVE_ERRNO_H +#include +#endif #if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H) #include diff --git a/qse/test/cmn/fio.c b/qse/test/cmn/fio.c index 2a0c157e..95e62a1f 100644 --- a/qse/test/cmn/fio.c +++ b/qse/test/cmn/fio.c @@ -35,6 +35,7 @@ static int test1 (void) n = qse_fio_write (fio, x, strlen(x)); qse_printf (QSE_T("written %d bytes\n"), (int)n); + off = qse_fio_seek (fio, 0, QSE_FIO_CURRENT); if (off == (qse_fio_off_t)-1) { @@ -192,6 +193,56 @@ static int test2 (void) return 0; } +static int test3 (void) +{ + qse_fio_t* fio; + qse_ssize_t n; + const qse_char_t* x = QSE_T("\uB108 \uBB50\uAC00 \uC798\uB0AC\uC5B4?"); + qse_fio_off_t off; + qse_char_t buf[1000]; + + fio = qse_fio_open ( + QSE_NULL, + 0, + QSE_T("fio3.txt"), + + QSE_FIO_TEXT | QSE_FIO_READ | QSE_FIO_WRITE | + QSE_FIO_CREATE | QSE_FIO_TRUNCATE, + + QSE_FIO_RUSR|QSE_FIO_WUSR|QSE_FIO_RGRP|QSE_FIO_ROTH + ); + if (fio == QSE_NULL) + { + qse_printf (QSE_T("cannot open file\n")); + return -1; + } + + n = qse_fio_write (fio, x, qse_strlen(x)); + qse_printf (QSE_T("written %d chars\n"), (int)n); + + n = qse_fio_flush (fio); + qse_printf (QSE_T("flushed %d chars\n"), (int)n); + + off = qse_fio_seek (fio, 0, QSE_FIO_BEGIN); + if (off == (qse_fio_off_t)-1) + { + qse_printf (QSE_T("failed to get file offset\n")); + } + + + n = qse_fio_read (fio, buf, QSE_COUNTOF(buf)); + qse_printf (QSE_T("read %d chars\n"), (int)n); + if (n > 0) + { + qse_printf (QSE_T("[%.*s]\n"), (int)n, buf); + } + + + qse_fio_close (fio); + + return 0; +} + int main () { setlocale (LC_ALL, ""); @@ -202,6 +253,11 @@ int main () R (test1); R (test2); + R (test3); + + qse_printf (QSE_T("--------------------------------------------------------------------------------\n")); + qse_printf (QSE_T("Run \"rm -f fio?.txt\" to delete garbages\n")); + qse_printf (QSE_T("--------------------------------------------------------------------------------\n")); return 0; }