Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/vbscript/global.c | 35 ++++++++++++++++++++++++++++++++--- dlls/vbscript/tests/api.vbs | 28 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index ab06db87624..da3da1f04d8 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2044,10 +2044,39 @@ static HRESULT Global_TimeValue(BuiltinDisp *This, VARIANT *arg, unsigned args_c return E_NOTIMPL; }
-static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + int year, month, day; + SYSTEMTIME lt; + HRESULT hres; + double date; + UDATE ud; + + TRACE("\n"); + + assert(args_cnt == 3); + + hres = to_int(args, &year); + if (SUCCEEDED(hres)) + hres = to_int(args + 1, &month); + if (SUCCEEDED(hres)) + hres = to_int(args + 2, &day); + + if (SUCCEEDED(hres)) + { + lt.wYear = year; + lt.wMonth = month; + lt.wDay = day; + + ud.st = lt; + ud.wDayOfYear = 0; + hres = VarDateFromUdateEx(&ud, 0, 0, &date); + } + + if (SUCCEEDED(hres)) + hres = return_date(res, date); + + return hres; }
static HRESULT Global_TimeSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index 20798a0aacd..f65789184e0 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -1958,4 +1958,32 @@ sub testErrRaise() end sub call testErrRaise()
+sub testDateSerial(yy, mm, dd, yyexp, mmexp, ddexp) + dim x + x = DateSerial(yy, mm, dd) + call ok(Year(x) = yyexp, "year = " & Year(x) & " expected " & yyexp) + call ok(Month(x) = mmexp, "month = " & Month(x) & " expected " & mmexp) + call ok(Day(x) = ddexp, "day = " & Day(x) & " expected " & ddexp) + call ok(getVT(x) = "VT_DATE*", "getVT = " & getVT(x)) +end sub + +sub testDateSerialError() + on error resume next + call Err.clear() + call DateSerial(10000, 1, 1) + call ok(Err.number = 5, "Err.number = " & Err.number) + call Err.clear() + call DateSerial(-10000, 1, 1) + call ok(Err.number = 5, "Err.number = " & Err.number) +end sub + +call testDateSerial(100, 2, 1, 100, 2, 1) +call testDateSerial(0, 2, 1, 2000, 2, 1) +call testDateSerial(49, 2, 1, 2049, 2, 1) +call testDateSerial(50, 2, 1, 1950, 2, 1) +call testDateSerial(99, 2, 1, 1999, 2, 1) +call testDateSerial(2000, 14, 2, 2001, 2, 2) +call testDateSerial(9999, 12, 1, 9999, 12, 1) +call testDateSerialError() + Call reportSuccess()
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52686 Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/vbscript/global.c | 57 +++++++++++++++++++++++++++++++++++-- dlls/vbscript/tests/api.vbs | 29 +++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index da3da1f04d8..f8770093f0e 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2209,10 +2209,61 @@ static HRESULT Global_GetObject(BuiltinDisp *This, VARIANT *args, unsigned args_ return hres; }
-static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_DateAdd(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - FIXME("\n"); - return E_NOTIMPL; + BSTR interval = NULL; + UDATE ud = { 0 }; + HRESULT hres; + double date; + int count; + + TRACE("\n"); + + assert(args_cnt == 3); + + hres = to_string(args, &interval); + if (SUCCEEDED(hres)) + hres = to_int(args + 1, &count); + if (SUCCEEDED(hres)) + hres = to_system_time(args + 2, &ud.st); + if (SUCCEEDED(hres)) + { + if (!wcscmp(interval, L"yyyy")) + ud.st.wYear += count; + else if (!wcscmp(interval, L"q")) + ud.st.wMonth += 3 * count; + else if (!wcscmp(interval, L"m")) + ud.st.wMonth += count; + else if (!wcscmp(interval, L"y") + || !wcscmp(interval, L"d") + || !wcscmp(interval, L"w")) + { + ud.st.wDay += count; + } + else if (!wcscmp(interval, L"ww")) + ud.st.wDay += 7 * count; + else if (!wcscmp(interval, L"h")) + ud.st.wHour += count; + else if (!wcscmp(interval, L"n")) + ud.st.wMinute += count; + else if (!wcscmp(interval, L"s")) + ud.st.wSecond += count; + else + { + WARN("Unrecognized interval %s.\n", debugstr_w(interval)); + hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); + } + } + + SysFreeString(interval); + + if (SUCCEEDED(hres)) + hres = VarDateFromUdateEx(&ud, 0, 0, &date); + + if (SUCCEEDED(hres)) + hres = return_date(res, date); + + return hres; }
static HRESULT Global_DateDiff(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index f65789184e0..d8b8578be2e 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -1986,4 +1986,33 @@ call testDateSerial(2000, 14, 2, 2001, 2, 2) call testDateSerial(9999, 12, 1, 9999, 12, 1) call testDateSerialError()
+sub testDateAdd(d, interval, number, expected_date) + dim x + x = DateAdd(interval, number, d) + call ok(Year(x) = Year(expected_date), "year = " & Year(x) & " expected " & Year(expected_date)) + call ok(Month(x) = Month(expected_date), "month = " & Month(x) & " expected " & Month(expected_date)) + call ok(Day(x) = Day(expected_date), "day = " & Day(x) & " expected " & Day(expected_date)) + call ok(getVT(x) = "VT_DATE*", "getVT = " & getVT(x)) +end sub + +sub testDateAddError() + on error resume next + call Err.clear() + call DateAdd("k", 1, DateSerial(2000, 2, 1)) + call ok(Err.number = 5, "Err.number = " & Err.number) +end sub + +call testDateAdd(DateSerial(2000, 1, 1), "yyyy", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "q", 1, DateSerial(2000, 4, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "m", -1, DateSerial(1999, 12, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "y", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "d", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 12, 31), "w", 1, DateSerial(2001, 1, 1)) +call testDateAdd(DateSerial(2000, 1, 1), "y", -1, DateSerial(1999, 12, 31)) +call testDateAdd(DateSerial(2000, 1, 1), "d", -1, DateSerial(1999, 12, 31)) +call testDateAdd(DateSerial(2000, 1, 1), "w", -1, DateSerial(1999, 12, 31)) +call testDateAdd(DateSerial(2000, 1, 1), "ww", 1, DateSerial(2000, 1, 8)) +call testDateAdd(DateSerial(2000, 1, 1), "ww", -1, DateSerial(1999, 12, 25)) +call testDateAddError() + Call reportSuccess()
On 5/16/22 14:43, Robert Wilhelm wrote:
Hi Nikolay, Thanks for working on vbs builtin. On minor nit: If we pass NULL as argument, we get error type mismatch instead of illegal null usage. In some builtins, we explicitely check for NULL like following: if(V_VT(arg) == VT_NULL) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE); Quite a few builtins lack these checks...
Yes, that's very true. I have a handful of extra patches, that use single helper for all conversion functions like CInt(), so I can do this null check in one place. Maybe it could be generalized at lop level, checking for null before Global_* functions are called, I haven't tested that far.
Best regards, Robert
Nikolay Sivov nsivov@codeweavers.com wrote:
-static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) {
- FIXME("\n");
- return E_NOTIMPL;
- int year, month, day;
- SYSTEMTIME lt;
- HRESULT hres;
- double date;
- UDATE ud;
- TRACE("\n");
- assert(args_cnt == 3);
- hres = to_int(args, &year);
- if (SUCCEEDED(hres))
hres = to_int(args + 1, &month);
- if (SUCCEEDED(hres))
hres = to_int(args + 2, &day);
- if (SUCCEEDED(hres))
- {
lt.wYear = year;
lt.wMonth = month;
lt.wDay = day;
ud.st = lt;
ud.wDayOfYear = 0;
hres = VarDateFromUdateEx(&ud, 0, 0, &date);
- }
Having 'lt' as an intermediate variable seems to be redundant. Also ud.st is not fully initialized unlike in 2/2.
On 5/15/22 15:58, Dmitry Timoshkov wrote:
Nikolay Sivov nsivov@codeweavers.com wrote:
-static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res) +static HRESULT Global_DateSerial(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) {
- FIXME("\n");
- return E_NOTIMPL;
- int year, month, day;
- SYSTEMTIME lt;
- HRESULT hres;
- double date;
- UDATE ud;
- TRACE("\n");
- assert(args_cnt == 3);
- hres = to_int(args, &year);
- if (SUCCEEDED(hres))
hres = to_int(args + 1, &month);
- if (SUCCEEDED(hres))
hres = to_int(args + 2, &day);
- if (SUCCEEDED(hres))
- {
lt.wYear = year;
lt.wMonth = month;
lt.wDay = day;
ud.st = lt;
ud.wDayOfYear = 0;
hres = VarDateFromUdateEx(&ud, 0, 0, &date);
- }
Having 'lt' as an intermediate variable seems to be redundant. Also ud.st is not fully initialized unlike in 2/2.
Thank you.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114721
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w7u_adm (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w7u_el (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w8 (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w8adm (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w864 (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w1064v1507 (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w1064v1809 (32 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w864 (64 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w1064v1507 (64 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"
=== w1064v1809 (64 bit report) ===
vbscript: run.c:1204: Test failed: api.vbs: L"year = 1949 expected 2049"