diff --git a/qse/include/qse/cmn/pio.h b/qse/include/qse/cmn/pio.h index 0b9cc6e0..9a7cd36c 100644 --- a/qse/include/qse/cmn/pio.h +++ b/qse/include/qse/cmn/pio.h @@ -1,5 +1,5 @@ /* - * $Id: pio.h 168 2009-05-30 01:19:46Z hyunghwan.chung $ + * $Id: pio.h 241 2009-07-22 12:47:13Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -75,11 +75,12 @@ enum qse_pio_io_flag_t enum qse_pio_errnum_t { QSE_PIO_ENOERR = 0, - QSE_PIO_ENOMEM, /* out of memory */ - QSE_PIO_ENOHND, /* no handle available */ - QSE_PIO_ECHILD, /* the child is not valid */ - QSE_PIO_EINTR, /* interrupted */ - QSE_PIO_ESUBSYS /* subsystem(system call) error */ + QSE_PIO_ENOMEM, /**< out of memory */ + QSE_PIO_ENOHND, /**< no handle available */ + QSE_PIO_ECHILD, /**< the child is not valid */ + QSE_PIO_EINTR, /**< interrupted */ + QSE_PIO_EPIPE, /**< broken pipe */ + QSE_PIO_ESUBSYS /**< subsystem(system call) error */ }; typedef enum qse_pio_hid_t qse_pio_hid_t; @@ -191,15 +192,15 @@ qse_pio_errnum_t qse_pio_geterrnum ( /****f* Common/qse_pio_geterrmsg * NAME - * qse_pio_geterrstr - transllate an error code to a string + * qse_pio_geterrmsg - transllate an error code to a string * * DESCRIPTION - * The qse_pio_geterrstr() funcpion returns the pointer to a constant string + * The qse_pio_geterrmsg() function returns the pointer to a constant string * describing the last error occurred. * * SYNOPSIS */ -const qse_char_t* qse_pio_geterrstr ( +const qse_char_t* qse_pio_geterrmsg ( qse_pio_t* pio ); /******/ diff --git a/qse/lib/awk/StdAwk.cpp b/qse/lib/awk/StdAwk.cpp index dac99967..e6690b06 100644 --- a/qse/lib/awk/StdAwk.cpp +++ b/qse/lib/awk/StdAwk.cpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.cpp 235 2009-07-15 10:43:31Z hyunghwan.chung $ + * $Id: StdAwk.cpp 241 2009-07-22 12:47:13Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -677,7 +677,7 @@ int StdAwk::closeConsole (Console& io) return 0; } -ssize_t StdAwk::readConsole (Console& io, char_t* data, size_t size) +StdAwk::ssize_t StdAwk::readConsole (Console& io, char_t* data, size_t size) { qse_ssize_t nn; @@ -707,7 +707,7 @@ ssize_t StdAwk::readConsole (Console& io, char_t* data, size_t size) return nn; } -ssize_t StdAwk::writeConsole (Console& io, const char_t* data, size_t size) +StdAwk::ssize_t StdAwk::writeConsole (Console& io, const char_t* data, size_t size) { return qse_sio_putsn ( (qse_sio_t*)io.getHandle(), diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index bcacae17..3606a077 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c 240 2009-07-19 13:02:33Z hyunghwan.chung $ + * $Id: parse.c 241 2009-07-22 12:47:13Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -596,7 +596,6 @@ static int begin_include (qse_awk_t* awk) { if (qse_strlen(awk->token.name->ptr) != awk->token.name->len) { - qse_cstr_t errarg; SETERRARG ( awk, QSE_AWK_EIONMNL, @@ -5123,7 +5122,7 @@ static int skip_comment (qse_awk_t* awk) return 0; } -static int get_operators (qse_awk_t* awk, qse_cint_t c, qse_awk_token_t* token) +static int get_symbols (qse_awk_t* awk, qse_cint_t c, qse_awk_token_t* token) { struct ops_t { @@ -5307,7 +5306,7 @@ static int get_token_into (qse_awk_t* awk, qse_awk_token_t* token) } else { - n = get_operators (awk, c, token); + n = get_symbols (awk, c, token); if (n <= -1) return -1; if (n == 0) { @@ -5331,7 +5330,6 @@ static int get_token_into (qse_awk_t* awk, qse_awk_token_t* token) } } -/*get_token_ok:*/ return 0; } @@ -5361,7 +5359,6 @@ static int preget_token (qse_awk_t* awk) return get_token_into (awk, &awk->atoken); } - static int classify_ident ( qse_awk_t* awk, const qse_char_t* name, qse_size_t len) { diff --git a/qse/lib/cmn/pio.c b/qse/lib/cmn/pio.c index 22161d50..19b61a1b 100644 --- a/qse/lib/cmn/pio.c +++ b/qse/lib/cmn/pio.c @@ -1,5 +1,5 @@ /* - * $Id: pio.c 212 2009-06-25 07:39:27Z hyunghwan.chung $ + * $Id: pio.c 241 2009-07-22 12:47:13Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -72,6 +72,7 @@ qse_pio_t* qse_pio_init ( qse_pio_t* pio, qse_mmgr_t* mmgr, const qse_char_t* cmd, int flags) { qse_pio_pid_t pid; + qse_pio_hnd_t handle[6] = { QSE_PIO_HND_NIL, @@ -81,16 +82,22 @@ qse_pio_t* qse_pio_init ( QSE_PIO_HND_NIL, QSE_PIO_HND_NIL }; + qse_tio_t* tio[3] = { QSE_NULL, QSE_NULL, QSE_NULL }; + int i, minidx = -1, maxidx = -1; #ifdef _WIN32 SECURITY_ATTRIBUTES secattr; + PROCESS_INFORMATION procinfo; + STARTUPINFO startup; + qse_char_t* dup = QSE_NULL; + BOOL x; #endif QSE_MEMSET (pio, 0, QSE_SIZEOF(*pio)); @@ -105,24 +112,28 @@ qse_pio_t* qse_pio_init ( if (flags & QSE_PIO_WRITEIN) { + /* child reads, parent writes */ if (CreatePipe ( &handle[0], &handle[1], &secattr, 0) == FALSE) goto oops; + /* don't inherit write handle */ if (SetHandleInformation ( - handle[0], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops; + handle[1], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops; minidx = 0; maxidx = 1; } if (flags & QSE_PIO_READOUT) { + /* child writes, parent reads */ if (CreatePipe ( &handle[2], &handle[3], &secattr, 0) == FALSE) goto oops; + /* don't inherit read handle */ if (SetHandleInformation ( - handle[3], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops; + handle[2], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops; if (minidx == -1) minidx = 2; maxidx = 3; @@ -130,18 +141,79 @@ qse_pio_t* qse_pio_init ( if (flags & QSE_PIO_READERR) { + /* child writes, parent reads */ if (CreatePipe ( &handle[4], &handle[5], &secattr, 0) == FALSE) goto oops; + /* don't inherit read handle */ if (SetHandleInformation ( - handle[5], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops; + handle[4], HANDLE_FLAG_INHERIT, 0) == FALSE) goto oops; if (minidx == -1) minidx = 4; maxidx = 5; } - /* TODO: .... */ + /* TODO: handle QSE_PIO_DROPXXX , QSE_PIO_XXXTONUL + if (flags & QSE_PIO_INTONUL) ... + if (flags & QSE_PIO_OUTTONUL) ... + if (flags & QSE_PIO_ERRTONUL) ... + if (flags & QSE_PIO_DROPIN) ... + if (flags & QSE_PIO_DROPOUT) ... + if (flags & QSE_PIO_DROPERR) ... + */ + + QSE_MEMSET (&procinfo, 0, QSE_SIZEOF(procinfo)); + QSE_MEMSET (&startup, 0, QSE_SIZEOF(startup)); + + startup.cb = QSE_SIZEOF(startup); + startup.hStdInput = + (flags & QSE_PIO_WRITEIN)? handle[0]: INVALID_HANDLE_VALUE; + startup.hStdOutput = + (flags & QSE_PIO_READOUT)? handle[3]: INVALID_HANDLE_VALUE; + startup.hStdError = + (flags & QSE_PIO_READERR)? handle[5]: INVALID_HANDLE_VALUE; + startup.dwFlags |= STARTF_USESTDHANDLES; + + /* there is nothing to do for QSE_PIO_SHELL as CreateProcess + * takes the entire command line */ + + dup = qse_strdup (cmd, mmgr); + if (dup == QSE_NULL) goto oops; + + x = CreateProcess ( + NULL, /* LPCTSTR lpApplicationName */ + dup, /* LPTSTR lpCommandLine */ + NULL, /* LPSECURITY_ATTRIBUTES lpProcessAttributes */ + NULL, /* LPSECURITY_ATTRIBUTES lpThreadAttributes */ + TRUE, /* BOOL bInheritHandles */ + 0, /* DWORD dwCreationFlags */ + NULL, /* LPVOID lpEnvironment */ + NULL, /* LPCTSTR lpCurrentDirectory */ + &startup, /* LPSTARTUPINFO lpStartupInfo */ + &procinfo /* LPPROCESS_INFORMATION lpProcessInformation */ + ); + + if (x == FALSE) goto oops; + + if (flags & QSE_PIO_WRITEIN) + { + CloseHandle (handle[0]); + handle[0] = QSE_PIO_HND_NIL; + } + if (flags & QSE_PIO_READOUT) + { + CloseHandle (handle[3]); + handle[3] = QSE_PIO_HND_NIL; + } + if (flags & QSE_PIO_READERR) + { + CloseHandle (handle[5]); + handle[5] = QSE_PIO_HND_NIL; + } + + CloseHandle (procinfo.hThread); + pid = procinfo.hProcess; #else if (flags & QSE_PIO_WRITEIN) @@ -463,8 +535,15 @@ qse_pio_t* qse_pio_init ( return pio; oops: - for (i = 0; i < QSE_COUNTOF(tio); i++) qse_tio_close (tio[i]); -#if _WIN32 +#ifdef _WIN32 + if (dup != QSE_NULL) QSE_MMGR_FREE (mmgr, dup); +#endif + + for (i = 0; i < QSE_COUNTOF(tio); i++) + { + if (tio[i] != QSE_NULL) qse_tio_close (tio[i]); + } +#ifdef _WIN32 for (i = minidx; i < maxidx; i++) CloseHandle (handle[i]); #else for (i = minidx; i < maxidx; i++) QSE_CLOSE (handle[i]); @@ -507,7 +586,7 @@ qse_pio_errnum_t qse_pio_geterrnum (qse_pio_t* pio) /* TODO: qse_pio_geterrmsg (qse_pio_t* pio) */ -const qse_char_t* qse_pio_geterrstr (qse_pio_t* pio) +const qse_char_t* qse_pio_geterrmsg (qse_pio_t* pio) { static const qse_char_t* __errstr[] = { @@ -516,6 +595,7 @@ const qse_char_t* qse_pio_geterrstr (qse_pio_t* pio) QSE_T("no handle available"), QSE_T("child process not valid"), QSE_T("interruped"), + QSE_T("broken pipe"), QSE_T("systeam call error"), QSE_T("unknown error") }; @@ -553,7 +633,12 @@ static qse_ssize_t pio_read ( #ifdef _WIN32 if (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD); - if (ReadFile(hnd, buf, size, &count, QSE_NULL) == FALSE) return -1; + if (ReadFile(hnd, buf, size, &count, QSE_NULL) == FALSE) + { + pio->errnum = (GetLastError() == ERROR_BROKEN_PIPE)? + QSE_PIO_EPIPE: QSE_PIO_ESUBSYS; + return -1; + } return (qse_ssize_t)count; #else @@ -569,6 +654,10 @@ reread: pio->errnum = QSE_PIO_EINTR; else goto reread; } + else if (errno == EPIPE) + { + pio->errnum = QSE_PIO_EPIPE; + } else { pio->errnum = QSE_PIO_ESUBSYS; @@ -606,7 +695,12 @@ static qse_ssize_t pio_write ( #ifdef _WIN32 if (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD); - if (WriteFile (hnd, data, size, &count, QSE_NULL) == FALSE) return -1; + if (WriteFile (hnd, data, size, &count, QSE_NULL) == FALSE) + { + pio->errnum = (GetLastError() == ERROR_BROKEN_PIPE)? + QSE_PIO_EPIPE: QSE_PIO_ESUBSYS; + return -1; + } return (qse_ssize_t)count; #else if (size > QSE_TYPE_MAX(size_t)) size = QSE_TYPE_MAX(size_t); @@ -621,6 +715,10 @@ rewrite: pio->errnum = QSE_PIO_EINTR; else goto rewrite; } + else if (errno == EPIPE) + { + pio->errnum = QSE_PIO_EPIPE; + } else { pio->errnum = QSE_PIO_ESUBSYS; diff --git a/qse/lib/cmn/str_bas.c b/qse/lib/cmn/str_bas.c index 06683b2f..69c23d00 100644 --- a/qse/lib/cmn/str_bas.c +++ b/qse/lib/cmn/str_bas.c @@ -1,5 +1,5 @@ /* - * $Id: str_bas.c 127 2009-05-07 13:15:04Z hyunghwan.chung $ + * $Id: str_bas.c 241 2009-07-22 12:47:13Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -440,7 +440,7 @@ qse_char_t* qse_strdup (const qse_char_t* str, qse_mmgr_t* mmgr) { qse_char_t* tmp; - tmp = (qse_char_t*) QSE_MALLOC ( + tmp = (qse_char_t*) QSE_MMGR_ALLOC ( mmgr, (qse_strlen(str)+1)*QSE_SIZEOF(qse_char_t)); if (tmp == QSE_NULL) return QSE_NULL; @@ -453,7 +453,7 @@ qse_char_t* qse_strxdup ( { qse_char_t* tmp; - tmp = (qse_char_t*) QSE_MALLOC ( + tmp = (qse_char_t*) QSE_MMGR_ALLOC ( mmgr, (len+1)*QSE_SIZEOF(qse_char_t)); if (tmp == QSE_NULL) return QSE_NULL; @@ -467,7 +467,7 @@ qse_char_t* qse_strxdup2 ( { qse_char_t* tmp; - tmp = (qse_char_t*) QSE_MALLOC ( + tmp = (qse_char_t*) QSE_MMGR_ALLOC ( mmgr, (len1+len2+1) * QSE_SIZEOF(qse_char_t)); if (tmp == QSE_NULL) return QSE_NULL; diff --git a/qse/lib/cmn/time.c b/qse/lib/cmn/time.c index 8a9aede7..bb3c6d78 100644 --- a/qse/lib/cmn/time.c +++ b/qse/lib/cmn/time.c @@ -1,5 +1,5 @@ /* - * $Id: time.c 221 2009-07-02 01:26:57Z hyunghwan.chung $ + * $Id: time.c 241 2009-07-22 12:47:13Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. @@ -33,9 +33,9 @@ #define WIN_EPOCH_DAY (1) #define EPOCH_DIFF_YEARS (QSE_EPOCH_YEAR-WIN_EPOCH_YEAR) - #define EPOCH_DIFF_DAYS (EPOCH_DIFF_YEARS*365+EPOCH_DIFF_YEARS/4-3) - #define EPOCH_DIFF_SECS (EPOCH_DIFF_DAYS*24*60*60) - #define EPOCH_DIFF_MSECS (EPOCH_DIFF_SECS*QSE_MSECS_PER_SEC) + #define EPOCH_DIFF_DAYS ((qse_ntime_t)EPOCH_DIFF_YEARS*365+EPOCH_DIFF_YEARS/4-3) + #define EPOCH_DIFF_SECS ((qse_ntime_t)EPOCH_DIFF_DAYS*24*60*60) + #define EPOCH_DIFF_MSECS ((qse_ntime_t)EPOCH_DIFF_SECS*QSE_MSECS_PER_SEC) #endif static const int mdays[2][QSE_MONS_PER_YEAR] = diff --git a/qse/samples/cmn/pio.c b/qse/samples/cmn/pio.c index 78e2d701..bcf0ded6 100644 --- a/qse/samples/cmn/pio.c +++ b/qse/samples/cmn/pio.c @@ -4,6 +4,10 @@ #include #include +#ifdef _WIN32 +# include +#endif + #define R(f) \ do { \ qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \ @@ -36,7 +40,7 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) if (n == 0) break; if (n < 0) { - qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio)); break; } @@ -46,14 +50,13 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) #else qse_printf (QSE_T("buf => [%.*S]\n"), (int)n, buf); #endif - } x = qse_pio_wait (pio); qse_printf (QSE_T("qse_pio_wait returns %d\n"), x); if (x == -1) { - qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)qse_pio_geterrnum(pio), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)qse_pio_geterrnum(pio), qse_pio_geterrmsg(pio)); } qse_pio_close (pio); @@ -86,7 +89,7 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) if (n == 0) break; if (n < 0) { - qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio)); break; } @@ -98,7 +101,7 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) qse_printf (QSE_T("qse_pio_wait returns %d\n"), x); if (x == -1) { - qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)qse_pio_geterrnum(pio), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)qse_pio_geterrnum(pio), qse_pio_geterrmsg(pio)); } qse_pio_close (pio); @@ -109,12 +112,29 @@ static int pio2 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid) static int test1 (void) { - return pio1 (QSE_T("ls -laF"), QSE_PIO_READOUT|QSE_PIO_WRITEIN|QSE_PIO_SHELL, QSE_PIO_OUT); + + return pio1 ( +#ifdef _WIN32 + QSE_T("lda.exe"), +#else + QSE_T("ls -laF"), +#endif + QSE_PIO_READOUT|QSE_PIO_WRITEIN|QSE_PIO_SHELL, + QSE_PIO_OUT + ); } static int test2 (void) { - return pio1 (QSE_T("ls -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN|QSE_PIO_SHELL, QSE_PIO_ERR); + return pio1 ( +#ifdef _WIN32 + QSE_T("lda.exe"), +#else + QSE_T("ls -laF"), +#endif + QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN|QSE_PIO_SHELL, + QSE_PIO_ERR + ); } static int test3 (void) @@ -163,7 +183,7 @@ static int test7 (void) if (n == 0) break; if (n < 0) { - qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("qse_pio_read() returned error - %s\n"), qse_pio_geterrmsg(pio)); break; } } @@ -172,7 +192,7 @@ static int test7 (void) qse_printf (QSE_T("qse_pio_wait returns %d\n"), x); if (x == -1) { - qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)QSE_PIO_ERRNUM(pio), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)QSE_PIO_ERRNUM(pio), qse_pio_geterrmsg(pio)); } qse_pio_close (pio); @@ -196,6 +216,16 @@ static int test8 (void) return -1; } +#ifdef _WIN32 + { + int n = 5; + + qse_printf (QSE_T("sleeping for %d seconds\n"), n); + Sleep (n * 1000); + qse_printf (QSE_T("WaitForSingleObject....%d\n"), + WaitForSingleObject (pio->child, 0)); + } +#else { int status; int n = 5; @@ -204,12 +234,13 @@ static int test8 (void) sleep (n); qse_printf (QSE_T("waitpid...%d\n"), (int)waitpid (-1, &status, 0)); } +#endif x = qse_pio_wait (pio); qse_printf (QSE_T("qse_pio_wait returns %d\n"), x); if (x == -1) { - qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)QSE_PIO_ERRNUM(pio), qse_pio_geterrstr(pio)); + qse_printf (QSE_T("error code : %d, error string: %s\n"), (int)QSE_PIO_ERRNUM(pio), qse_pio_geterrmsg(pio)); } qse_pio_close (pio);