Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVojtech Kral <vojtech@kral.hk>2019-02-27 13:53:09 +0300
committerVojtech Kral <vojtech@kral.hk>2019-03-01 15:15:20 +0300
commitbc1aaaa146feea45bfa925e9ef457b3d701858d7 (patch)
tree8a2f7ef5a497d1add6324fa879604166e7859543 /src/avrdude
parentc426c99af0d1ce3b35303f005aab7d2fafdc888e (diff)
avrdude: Fix string encoding handling on Windows
Diffstat (limited to 'src/avrdude')
-rw-r--r--src/avrdude/CMakeLists.txt5
-rw-r--r--src/avrdude/fileio.c5
-rw-r--r--src/avrdude/main-standalone.c7
-rw-r--r--src/avrdude/main-standalone.cpp54
-rw-r--r--src/avrdude/main.c1
-rw-r--r--src/avrdude/ser_win32.c214
-rw-r--r--src/avrdude/windows/utf8.c45
-rw-r--r--src/avrdude/windows/utf8.h10
8 files changed, 206 insertions, 135 deletions
diff --git a/src/avrdude/CMakeLists.txt b/src/avrdude/CMakeLists.txt
index 1022a5c0e..0e9b9e6d4 100644
--- a/src/avrdude/CMakeLists.txt
+++ b/src/avrdude/CMakeLists.txt
@@ -1,5 +1,7 @@
cmake_minimum_required(VERSION 3.0)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE) # To enable various useful macros and functions on Unices
remove_definitions(-D_UNICODE -DUNICODE)
@@ -68,6 +70,7 @@ set(AVRDUDE_SOURCES
)
if (MSVC)
set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
+ windows/utf8.c
windows/unistd.cpp
windows/getopt.c
)
@@ -90,7 +93,7 @@ add_custom_target(gen_conf_h
add_library(avrdude STATIC ${AVRDUDE_SOURCES})
add_dependencies(avrdude gen_conf_h)
-add_executable(avrdude-slic3r main-standalone.c)
+add_executable(avrdude-slic3r main-standalone.cpp)
target_link_libraries(avrdude-slic3r avrdude)
if (WIN32)
diff --git a/src/avrdude/fileio.c b/src/avrdude/fileio.c
index dcd0d6a66..7803497a0 100644
--- a/src/avrdude/fileio.c
+++ b/src/avrdude/fileio.c
@@ -40,6 +40,9 @@
#include "avrdude.h"
#include "libavrdude.h"
+#if defined(WIN32NATIVE)
+#include "windows/utf8.h"
+#endif
#define IHEX_MAXDATA 256
@@ -110,7 +113,7 @@ FILE *fopen_utf8(const char *filename, const char *mode)
static wchar_t mode_buffer[MAX_MODE_LEN];
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
- if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
+ if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
return _wfopen(fname_buffer, mode_buffer);
#else
diff --git a/src/avrdude/main-standalone.c b/src/avrdude/main-standalone.c
deleted file mode 100644
index 7cfc6f210..000000000
--- a/src/avrdude/main-standalone.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "avrdude.h"
-
-
-int main(int argc, char *argv[])
-{
- return avrdude_main(argc, argv);
-}
diff --git a/src/avrdude/main-standalone.cpp b/src/avrdude/main-standalone.cpp
new file mode 100644
index 000000000..df6d79e13
--- /dev/null
+++ b/src/avrdude/main-standalone.cpp
@@ -0,0 +1,54 @@
+extern "C" {
+#include "avrdude.h"
+}
+
+
+#ifdef WIN32
+#include <stdlib.h>
+#include <vector>
+
+extern "C" {
+#include "windows/utf8.h"
+}
+
+struct ArgvUtf8 : std::vector<char*>
+{
+ int argc;
+
+ ArgvUtf8(int argc_w, wchar_t *argv_w[]) : std::vector<char*>(argc_w + 1, nullptr), argc(0)
+ {
+ for (int i = 0; i < argc_w; i++) {
+ char *arg_utf8 = ::wstr_to_utf8(argv_w[i], -1);
+ if (arg_utf8 != nullptr) {
+ operator[](i) = arg_utf8;
+ argc = i + 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ ~ArgvUtf8()
+ {
+ for (char *arg : *this) {
+ if (arg != nullptr) {
+ ::free(arg);
+ }
+ }
+ }
+};
+
+int wmain(int argc_w, wchar_t *argv_w[])
+{
+ ArgvUtf8 argv_utf8(argc_w, argv_w);
+ return ::avrdude_main(argv_utf8.argc, &argv_utf8[0]);
+}
+
+#else
+
+int main(int argc, char *argv[])
+{
+ return ::avrdude_main(argc, argv);
+}
+
+#endif
diff --git a/src/avrdude/main.c b/src/avrdude/main.c
index 0f8807122..8f9040349 100644
--- a/src/avrdude/main.c
+++ b/src/avrdude/main.c
@@ -812,7 +812,6 @@ int avrdude_main(int argc, char * argv [])
// rc = read_config(sys_config);
rc = read_config_builtin();
- avrdude_message(MSG_NOTICE, "\n\nread_config_builtin: %d\n\n", rc);
if (rc) {
// avrdude_message(MSG_INFO, "%s: error reading system wide configuration file \"%s\"\n",
// progname, sys_config);
diff --git a/src/avrdude/ser_win32.c b/src/avrdude/ser_win32.c
index 4e1713128..c62e83608 100644
--- a/src/avrdude/ser_win32.c
+++ b/src/avrdude/ser_win32.c
@@ -34,16 +34,63 @@
#include <windows.h>
#include <stdio.h>
+#include <string.h>
#include <ctype.h> /* for isprint */
#include <errno.h> /* ENOTTY */
#include "avrdude.h"
#include "libavrdude.h"
+#include "windows/utf8.h"
long serial_recv_timeout = 5000; /* ms */
#define W32SERBUFSIZE 1024
+
+// Get last error message string in UTF-8
+// Always return a valid null-terminated string
+// The returned string should be freed by the caller
+char* last_error_string(int wsa)
+{
+ LPWSTR wbuffer = NULL;
+
+ (void)wsa;
+
+ DWORD wbuffer_len = FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+#ifdef HAVE_LIBWS2_32
+ wsa ? WSAGetLastError() : GetLastError(),
+#else
+ GetLastError(),
+#endif
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&wbuffer,
+ 0,
+ NULL);
+
+ if (wbuffer_len == 0) {
+ return NULL;
+ }
+
+ char *res = wstr_to_utf8(wbuffer, wbuffer_len);
+
+ LocalFree(wbuffer);
+
+ if (res == NULL) {
+ // If we get here, conversion to UTF-8 failed
+ res = strdup("(could not get error message)");
+ if (res == NULL) {
+ avrdude_oom("last_error_string(): out of memory\n");
+ }
+ }
+
+ return res;
+}
+
+
struct baud_mapping {
long baud;
DWORD speed;
@@ -129,7 +176,6 @@ static int
net_open(const char *port, union filedescriptor *fdp)
{
WSADATA wsaData;
- LPVOID lpMsgBuf;
char *hstr, *pstr, *end;
unsigned int pnum;
@@ -175,18 +221,10 @@ net_open(const char *port, union filedescriptor *fdp)
free(hstr);
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL);
- avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, (char *)lpMsgBuf);
- LocalFree(lpMsgBuf);
+ const char *error = last_error_string(1);
+ avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, error);
+ free(error);
+
return -1;
}
@@ -196,18 +234,9 @@ net_open(const char *port, union filedescriptor *fdp)
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL);
- avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname, (char *)lpMsgBuf);
- LocalFree(lpMsgBuf);
+ const char *error = last_error_string(1);
+ avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname);
+ free(error);
return -1;
}
@@ -221,7 +250,6 @@ net_open(const char *port, union filedescriptor *fdp)
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
{
- LPVOID lpMsgBuf;
HANDLE hComPort=INVALID_HANDLE_VALUE;
char *newname = 0;
@@ -261,19 +289,9 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hComPort == INVALID_HANDLE_VALUE) {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL);
- avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
- progname, port, (char*)lpMsgBuf);
- LocalFree( lpMsgBuf );
+ const char *error = last_error_string(0);
+ avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n", progname, port, error);
+ free(error);
return -1;
}
@@ -346,14 +364,13 @@ static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
#ifdef HAVE_LIBWS2_32
static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
{
- LPVOID lpMsgBuf;
int rc;
const unsigned char *p = buf;
size_t len = buflen;
if (fd->ifd < 0) {
avrdude_message(MSG_NOTICE, "%s: net_send(): connection not open\n", progname);
- exit(1);
+ return -1;
}
if (!len) {
@@ -382,19 +399,10 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
while (len) {
rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0);
if (rc < 0) {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL);
- avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, (char *)lpMsgBuf);
- LocalFree(lpMsgBuf);
- exit(1);
+ const char *error = last_error_string(1);
+ avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, error);
+ free(error);
+ return -1;
}
p += rc;
len -= rc;
@@ -423,8 +431,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
HANDLE hComPort=(HANDLE)fd->pfd;
if (hComPort == INVALID_HANDLE_VALUE) {
- avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n",
- progname);
+ avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n", progname);
return -1;
}
@@ -449,18 +456,18 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
}
avrdude_message(MSG_INFO, "\n");
}
-
+
serial_w32SetTimeOut(hComPort,500);
- if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
- avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
- progname, "sorry no info avail"); // TODO
+ if (!WriteFile(hComPort, buf, buflen, &written, NULL)) {
+ const char *error = last_error_string(0);
+ avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n", progname, error);
+ free(error);
return -1;
}
if (written != buflen) {
- avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n",
- progname);
+ avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n", progname);
return -1;
}
@@ -471,7 +478,6 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
#ifdef HAVE_LIBWS2_32
static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
{
- LPVOID lpMsgBuf;
struct timeval timeout, to2;
fd_set rfds;
int nfds;
@@ -481,7 +487,7 @@ static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
if (fd->ifd < 0) {
avrdude_message(MSG_INFO, "%s: net_recv(): connection not open\n", progname);
- exit(1);
+ return -1;
}
timeout.tv_sec = serial_recv_timeout / 1000L;
@@ -504,37 +510,19 @@ reselect:
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding, reselecting\n", progname);
goto reselect;
} else {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL);
- avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, (char *)lpMsgBuf);
- LocalFree(lpMsgBuf);
- exit(1);
+ const char *error = last_error_string(1);
+ avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, error);
+ free(error);
+ return -1;
}
}
rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0);
if (rc < 0) {
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL);
- avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, (char *)lpMsgBuf);
- LocalFree(lpMsgBuf);
- exit(1);
+ const char *error = last_error_string(1);
+ avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
+ free(error);
+ return -1;
}
p += rc;
len += rc;
@@ -579,37 +567,24 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
RETURN_IF_CANCEL();
HANDLE hComPort=(HANDLE)fd->pfd;
-
+
if (hComPort == INVALID_HANDLE_VALUE) {
- avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n",
- progname);
+ avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n", progname);
return -1;
}
-
+
serial_w32SetTimeOut(hComPort, serial_recv_timeout);
-
+
if (!ReadFile(hComPort, buf, buflen, &read, NULL)) {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL );
- avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
- progname, (char*)lpMsgBuf);
- LocalFree( lpMsgBuf );
+ const char *error = last_error_string(0);
+ avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, error);
+ free(error);
return -1;
}
/* time out detected */
if (read == 0) {
- avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
- progname);
+ avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n", progname);
return -1;
}
@@ -664,20 +639,9 @@ static int ser_drain(union filedescriptor *fd, int display)
readres=ReadFile(hComPort, buf, 1, &read, NULL);
if (!readres) {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL );
- avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
- progname, (char*)lpMsgBuf);
- LocalFree( lpMsgBuf );
+ const char *error = last_error_string(0);
+ avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, error);
+ free(error);
return -1;
}
diff --git a/src/avrdude/windows/utf8.c b/src/avrdude/windows/utf8.c
new file mode 100644
index 000000000..d3c51e67f
--- /dev/null
+++ b/src/avrdude/windows/utf8.c
@@ -0,0 +1,45 @@
+#include "utf8.h"
+
+
+char* wstr_to_utf8(LPWSTR wstr, int len)
+{
+ char *res = NULL;
+
+ int res_size = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
+ if (res_size > 0) {
+ // Note: WideCharToMultiByte doesn't null-terminate if real (ie. > 0) buffer length is passed
+ res = malloc(len != - 1 ? res_size + 1 : res_size);
+ if (res == NULL) { return NULL; }
+
+ if (WideCharToMultiByte(CP_UTF8, 0, wstr, len, res, res_size, NULL, NULL) == res_size) {
+ if (len != -1) { res[res_size] = '\0'; }
+ } else {
+ free(res);
+ return NULL;
+ }
+ }
+
+ return res;
+}
+
+LPWSTR utf8_to_wstr(const char *str, int len)
+{
+ LPWSTR res = NULL;
+
+ int res_size = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
+ if (res_size > 0) {
+ // Note: MultiByteToWideChar doesn't null-terminate if real (ie. > 0) buffer length is passed
+ res = malloc(len != - 1 ? res_size + 1 : res_size);
+
+ if (res == NULL) { return NULL; }
+
+ if (MultiByteToWideChar(CP_UTF8, 0, str, len, res, res_size) == res_size) {
+ if (len != -1) { res[res_size] = L'\0'; }
+ } else {
+ free(res);
+ return NULL;
+ }
+ }
+
+ return res;
+}
diff --git a/src/avrdude/windows/utf8.h b/src/avrdude/windows/utf8.h
new file mode 100644
index 000000000..a99fcbb7e
--- /dev/null
+++ b/src/avrdude/windows/utf8.h
@@ -0,0 +1,10 @@
+#ifndef SLIC3R_AVRDUDE_UTF8_H
+#define SLIC3R_AVRDUDE_UTF8_H
+
+#include <windows.h>
+
+extern char* wstr_to_utf8(LPWSTR wstr, int len);
+extern LPWSTR utf8_to_wstr(const char *str, int len);
+
+
+#endif // SLIC3R_AVRDUDE_UTF8_H