diff options
| author | Damien George <damien.p.george@gmail.com> | 2017-09-06 13:40:51 +1000 |
|---|---|---|
| committer | Damien George <damien.p.george@gmail.com> | 2017-09-06 13:40:51 +1000 |
| commit | 01dd7804b87d60b2deab16712eccb3b97351a9b7 (patch) | |
| tree | 1aa21f38a872b8e62a3d4e4f74f68033c6f827e4 /ports/windows | |
| parent | a9862b30068fc9df1022f08019fb35aaa5085f64 (diff) | |
ports: Make new ports/ sub-directory and move all ports there.
This is to keep the top-level directory clean, to make it clear what is
core and what is a port, and to allow the repository to grow with new ports
in a sustainable way.
Diffstat (limited to 'ports/windows')
28 files changed, 1762 insertions, 0 deletions
diff --git a/ports/windows/.appveyor.yml b/ports/windows/.appveyor.yml new file mode 100644 index 000000000..84060a116 --- /dev/null +++ b/ports/windows/.appveyor.yml @@ -0,0 +1,32 @@ +environment: + # Python version used + MICROPY_CPYTHON3: c:/python34/python.exe + +init: + # Set build version number to commit to be travis-like +- ps: Update-AppveyorBuild -Version $env:appveyor_repo_commit.substring(0,8) + +configuration: +- Debug +- Release + +platform: +- x86 +- x64 + +build: + project: windows/micropython.vcxproj + verbosity: normal + +test_script: +- cmd: >- + cd tests + + %MICROPY_CPYTHON3% run-tests + +skip_tags: true + +deploy: off + +nuget: + disable_publish_on_pr: true diff --git a/ports/windows/.gitignore b/ports/windows/.gitignore new file mode 100644 index 000000000..12235e7c9 --- /dev/null +++ b/ports/windows/.gitignore @@ -0,0 +1,11 @@ +*.user +*.*sdf +*.suo +*.sln +*.exe +*.pdb +*.ilk +*.filters +/build/* +.vs/* +*.VC.*db diff --git a/ports/windows/Makefile b/ports/windows/Makefile new file mode 100644 index 000000000..a39d34826 --- /dev/null +++ b/ports/windows/Makefile @@ -0,0 +1,65 @@ +include ../py/mkenv.mk +-include mpconfigport.mk + +# define main target +PROG = micropython.exe + +# qstr definitions (must come before including py.mk) +QSTR_DEFS = ../unix/qstrdefsport.h + +# include py core make definitions +include $(TOP)/py/py.mk + +INC += -I. +INC += -I$(TOP) +INC += -I$(BUILD) + +# compiler settings +CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) +LDFLAGS = $(LDFLAGS_MOD) -lm + +# Debugging/Optimization +ifdef DEBUG +CFLAGS += -g +COPT = -O0 +else +COPT = -Os #-DNDEBUG +endif + +# source files +SRC_C = \ + unix/main.c \ + unix/file.c \ + unix/input.c \ + unix/modos.c \ + unix/modmachine.c \ + unix/modtime.c \ + unix/gccollect.c \ + windows_mphal.c \ + realpath.c \ + init.c \ + sleep.c \ + +OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) + +ifeq ($(MICROPY_USE_READLINE),1) +CFLAGS_MOD += -DMICROPY_USE_READLINE=1 +SRC_C += lib/mp-readline/readline.c +else ifeq ($(MICROPY_USE_READLINE),2) +CFLAGS_MOD += -DMICROPY_USE_READLINE=2 +LDFLAGS_MOD += -lreadline +endif + +ifeq ($(CROSS_COMPILE),x86_64-w64-mingw32-) +CFLAGS_MOD += -DMICROPY_NLR_SETJMP=1 +endif + +LIB += -lws2_32 + +# List of sources for qstr extraction +SRC_QSTR += $(SRC_C) +# Append any auto-generated sources that are needed by sources listed in +# SRC_QSTR +SRC_QSTR_AUTO_DEPS += + +include $(TOP)/py/mkrules.mk diff --git a/ports/windows/README.md b/ports/windows/README.md new file mode 100644 index 000000000..6d3249903 --- /dev/null +++ b/ports/windows/README.md @@ -0,0 +1,74 @@ +This is the experimental, community-supported Windows port of MicroPython. +It is based on Unix port, and expected to remain so. +The port requires additional testing, debugging, and patches. Please +consider to contribute. + + +Building on Debian/Ubuntu Linux system +--------------------------------------- + + sudo apt-get install gcc-mingw-w64 + make CROSS_COMPILE=i686-w64-mingw32- + +If for some reason the mingw-w64 crosscompiler is not available, you can try +mingw32 instead, but it comes with a really old gcc which may produce some +spurious errors (you may need to disable -Werror): + + sudo apt-get install mingw32 mingw32-binutils mingw32-runtime + make CROSS_COMPILE=i586-mingw32msvc- + + +Building under Cygwin +--------------------- + +Install following packages using cygwin's setup.exe: + +* mingw64-i686-gcc-core +* mingw64-x86_64-gcc-core +* make + +Build using: + + make CROSS_COMPILE=i686-w64-mingw32- + +Or for 64bit: + + make CROSS_COMPILE=x86_64-w64-mingw32- + + +Building using MS Visual Studio 2013 (or higher) +------------------------------------------------ + +In the IDE, open `micropython.vcxproj` and build. + +To build from the command line: + + msbuild micropython.vcxproj + +__Stack usage__ + +The msvc compiler is quite stack-hungry which might result in a "maximum recursion depth exceeded" +RuntimeError for code with lots of nested function calls. +There are several ways to deal with this: +- increase the threshold used for detection by altering the argument to `mp_stack_set_limit` in `unix/main.c` +- disable detection all together by setting `MICROPY_STACK_CHECK` to "0" in `windows/mpconfigport.h` +- disable the /GL compiler flag by setting `WholeProgramOptimization` to "false" + +See [issue 2927](https://github.com/micropython/micropython/issues/2927) for more information. + + +Running on Linux using Wine +--------------------------- + +The default build (MICROPY_USE_READLINE=1) uses extended Windows console +functions and thus should be ran using the `wineconsole` tool. Depending +on the Wine build configuration, you may also want to select the curses +backend which has the look&feel of a standard Unix console: + + wineconsole --backend=curses ./micropython.exe + +For more info, see https://www.winehq.org/docs/wineusr-guide/cui-programs . + +If built without line editing and history capabilities +(MICROPY_USE_READLINE=0), the resulting binary can be run using the standard +`wine` tool. diff --git a/ports/windows/fmode.c b/ports/windows/fmode.c new file mode 100644 index 000000000..33ba24ed1 --- /dev/null +++ b/ports/windows/fmode.c @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "fmode.h" +#include "py/mpconfig.h" +#include <fcntl.h> +#include <stdlib.h> + +// Workaround for setting file translation mode: we must distinguish toolsets +// since mingw has no _set_fmode, and altering msvc's _fmode directly has no effect +STATIC int set_fmode_impl(int mode) { +#ifndef _MSC_VER + _fmode = mode; + return 0; +#else + return _set_fmode(mode); +#endif +} + +void set_fmode_binary(void) { + set_fmode_impl(O_BINARY); +} + +void set_fmode_text(void) { + set_fmode_impl(O_TEXT); +} diff --git a/ports/windows/fmode.h b/ports/windows/fmode.h new file mode 100644 index 000000000..c661c84d0 --- /dev/null +++ b/ports/windows/fmode.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_WINDOWS_FMODE_H +#define MICROPY_INCLUDED_WINDOWS_FMODE_H + +// Treat files opened by open() as binary. No line ending translation is done. +void set_fmode_binary(void); + +// Treat files opened by open() as text. +// When reading from the file \r\n will be converted to \n. +// When writing to the file \n will be converted into \r\n. +void set_fmode_text(void); + +#endif // MICROPY_INCLUDED_WINDOWS_FMODE_H diff --git a/ports/windows/init.c b/ports/windows/init.c new file mode 100644 index 000000000..09fa10417 --- /dev/null +++ b/ports/windows/init.c @@ -0,0 +1,69 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <windows.h> +#ifdef _MSC_VER +#include <crtdbg.h> +#endif +#include "sleep.h" + +extern BOOL WINAPI console_sighandler(DWORD evt); + +#ifdef _MSC_VER +void invalid_param_handler(const wchar_t *expr, const wchar_t *fun, const wchar_t *file, unsigned int line, uintptr_t p) { +} +#endif + +void init() { +#ifdef _MSC_VER + // Disable the 'Debug Error!' dialog for assertions failures and the likes, + // instead write messages to the debugger output and terminate. + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG); + + // Disable 'invalid parameter handling' which is for instance invoked when + // passing invalid file descriptors to functions like lseek() and make the + // functions called behave properly by setting errno to EBADF/EINVAL/.. + _set_invalid_parameter_handler(invalid_param_handler); +#endif + SetConsoleCtrlHandler(console_sighandler, TRUE); + init_sleep(); +#ifdef __MINGW32__ + putenv("PRINTF_EXPONENT_DIGITS=2"); +#elif _MSC_VER < 1900 + // This is only necessary for Visual Studio versions 2013 and below: + // https://msdn.microsoft.com/en-us/library/bb531344(v=vs.140).aspx + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif +} + +void deinit() { + SetConsoleCtrlHandler(console_sighandler, FALSE); + deinit_sleep(); +} diff --git a/ports/windows/init.h b/ports/windows/init.h new file mode 100644 index 000000000..c6fddb257 --- /dev/null +++ b/ports/windows/init.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_WINDOWS_INIT_H +#define MICROPY_INCLUDED_WINDOWS_INIT_H + +void init(void); +void deinit(void); + +#endif // MICROPY_INCLUDED_WINDOWS_INIT_H diff --git a/ports/windows/micropython.vcxproj b/ports/windows/micropython.vcxproj new file mode 100644 index 000000000..ee0b98abb --- /dev/null +++ b/ports/windows/micropython.vcxproj @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{740F3C30-EB6C-4B59-9C50-AE4D5A4A9D12}</ProjectGuid> + <RootNamespace>micropython</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="msvc/common.props" /> + <Import Project="msvc/debug.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="msvc/common.props" /> + <Import Project="msvc/release.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="msvc/common.props" /> + <Import Project="msvc/debug.props" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="msvc/common.props" /> + <Import Project="msvc/release.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros"> + <CustomPropsFile Condition="'$(CustomPropsFile)'==''">msvc/user.props</CustomPropsFile> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile /> + <Link /> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile /> + <Link /> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile /> + <Link /> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile /> + <Link /> + </ItemDefinitionGroup> + <ItemGroup> + </ItemGroup> + <Import Project="msvc/sources.props" /> + <Import Project="msvc/genhdr.targets" /> + <Import Project="$(CustomPropsFile)" Condition="exists('$(CustomPropsFile)')" /> + <Target Name="GenHeaders" BeforeTargets="BuildGenerateSources" DependsOnTargets="GenerateHeaders"> + </Target> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h new file mode 100644 index 000000000..abad35282 --- /dev/null +++ b/ports/windows/mpconfigport.h @@ -0,0 +1,251 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// options to control how MicroPython is built + +// Linking with GNU readline (MICROPY_USE_READLINE == 2) causes binary to be licensed under GPL +#ifndef MICROPY_USE_READLINE +#define MICROPY_USE_READLINE (1) +#endif + +#define MICROPY_ALLOC_PATH_MAX (260) //see minwindef.h for msvc or limits.h for mingw +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_COMP_MODULE_CONST (1) +#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) +#define MICROPY_COMP_RETURN_IF_EXPR (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_STACK_CHECK (1) +#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) +#define MICROPY_MEM_STATS (1) +#define MICROPY_DEBUG_PRINTERS (1) +#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print +#define MICROPY_READER_POSIX (1) +#define MICROPY_USE_READLINE_HISTORY (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_EMACS_KEYS (1) +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_HELPER_LEXER_UNIX (1) +#define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_STREAMS_NON_BLOCK (1) +#define MICROPY_OPT_COMPUTED_GOTO (0) +#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) +#define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_PY_FUNCTION_ATTRS (1) +#define MICROPY_PY_DESCRIPTORS (1) +#define MICROPY_PY_BUILTINS_STR_UNICODE (1) +#define MICROPY_PY_BUILTINS_STR_CENTER (1) +#define MICROPY_PY_BUILTINS_STR_PARTITION (1) +#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) +#define MICROPY_PY_BUILTINS_COMPILE (1) +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) +#define MICROPY_PY_BUILTINS_INPUT (1) +#define MICROPY_PY_BUILTINS_POW3 (1) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) +#define MICROPY_PY_ALL_SPECIAL_METHODS (1) +#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_SYS_EXIT (1) +#define MICROPY_PY_SYS_PLATFORM "win32" +#define MICROPY_PY_SYS_MAXSIZE (1) +#define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_SYS_EXC_INFO (1) +#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) +#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) +#define MICROPY_PY_CMATH (1) +#define MICROPY_PY_IO_FILEIO (1) +#define MICROPY_PY_GC_COLLECT_RETVAL (1) +#define MICROPY_MODULE_FROZEN_STR (0) + +#define MICROPY_STACKLESS (0) +#define MICROPY_STACKLESS_STRICT (0) + +#define MICROPY_PY_UTIME (1) +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_UERRNO (1) +#define MICROPY_PY_UCTYPES (1) +#define MICROPY_PY_UZLIB (1) +#define MICROPY_PY_UJSON (1) +#define MICROPY_PY_URE (1) +#define MICROPY_PY_UHEAPQ (1) +#define MICROPY_PY_UTIMEQ (1) +#define MICROPY_PY_UHASHLIB (1) +#define MICROPY_PY_UBINASCII (1) +#define MICROPY_PY_UBINASCII_CRC32 (1) +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_PULSE (1) +#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr +#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr + +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) +#define MICROPY_WARNINGS (1) +#define MICROPY_PY_STR_BYTES_CMP_WARN (1) + +#ifdef _MSC_VER +#define MICROPY_GCREGS_SETJMP (1) +#endif + +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) +#define MICROPY_KBD_EXCEPTION (1) + +#define MICROPY_PORT_INIT_FUNC init() +#define MICROPY_PORT_DEINIT_FUNC deinit() + +// type definitions for the specific machine + +#if defined( __MINGW32__ ) && defined( __LP64__ ) +typedef long mp_int_t; // must be pointer size +typedef unsigned long mp_uint_t; // must be pointer size +#elif defined ( __MINGW32__ ) && defined( _WIN64 ) +#include <stdint.h> +typedef __int64 mp_int_t; +typedef unsigned __int64 mp_uint_t; +#define MP_SSIZE_MAX __INT64_MAX__ +#elif defined ( _MSC_VER ) && defined( _WIN64 ) +typedef __int64 mp_int_t; +typedef unsigned __int64 mp_uint_t; +#else +// These are definitions for machines where sizeof(int) == sizeof(void*), +// regardless for actual size. +typedef int mp_int_t; // must be pointer size +typedef unsigned int mp_uint_t; // must be pointer size +#endif + +// Just assume Windows is little-endian - mingw32 gcc doesn't +// define standard endianness macros. +#define MP_ENDIANNESS_LITTLE (1) + +// Cannot include <sys/types.h>, as it may lead to symbol name clashes +#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) +typedef long long mp_off_t; +#else +typedef long mp_off_t; +#endif + +#if MICROPY_PY_OS_DUPTERM +#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) +void mp_hal_dupterm_tx_strn(const char *str, size_t len); +#else +#include <unistd.h> +#define MP_PLAT_PRINT_STRN(str, len) do { int ret = write(1, str, len); (void)ret; } while (0) +#define mp_hal_dupterm_tx_strn(s, l) +#endif + +#define MICROPY_PORT_BUILTINS \ + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) }, + +extern const struct _mp_obj_module_t mp_module_os; +extern const struct _mp_obj_module_t mp_module_time; +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) }, \ + { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \ + { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \ + +#if MICROPY_USE_READLINE == 1 +#define MICROPY_PORT_ROOT_POINTERS \ + char *readline_hist[50]; +#endif + +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_MPHALPORT_H "windows_mphal.h" + +// We need to provide a declaration/definition of alloca() +#include <malloc.h> + +#include "realpath.h" +#include "init.h" +#include "sleep.h" + +#ifdef __GNUC__ +#define MP_NOINLINE __attribute__((noinline)) +#endif + +// MSVC specifics +#ifdef _MSC_VER + +// Sanity check + +#if ( _MSC_VER < 1800 ) + #error Can only build with Visual Studio 2013 toolset +#endif + + +// CL specific overrides from mpconfig + +#define NORETURN __declspec(noreturn) +#define MP_NOINLINE __declspec(noinline) +#define MP_LIKELY(x) (x) +#define MP_UNLIKELY(x) (x) +#define MICROPY_PORT_CONSTANTS { "dummy", 0 } //can't have zero-sized array +#ifdef _WIN64 +#define MP_SSIZE_MAX _I64_MAX +#else +#define MP_SSIZE_MAX _I32_MAX +#endif + + +// CL specific definitions + +#define restrict +#define inline __inline +#define alignof(t) __alignof(t) +#define PATH_MAX MICROPY_ALLOC_PATH_MAX +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#ifdef _WIN64 +#define SSIZE_MAX _I64_MAX +typedef __int64 ssize_t; +#else +#define SSIZE_MAX _I32_MAX +typedef int ssize_t; +#endif + + +// Put static/global variables in sections with a known name +// This used to be required for GC, not the case anymore but keep it as it makes the map file easier to inspect +// For this to work this header must be included by all sources, which is the case normally +#define MICROPY_PORT_DATASECTION "upydata" +#define MICROPY_PORT_BSSSECTION "upybss" +#pragma data_seg(MICROPY_PORT_DATASECTION) +#pragma bss_seg(MICROPY_PORT_BSSSECTION) + + +// System headers (needed e.g. for nlr.h) + +#include <stddef.h> //for NULL +#include <assert.h> //for assert + +#endif diff --git a/ports/windows/mpconfigport.mk b/ports/windows/mpconfigport.mk new file mode 100644 index 000000000..87001d464 --- /dev/null +++ b/ports/windows/mpconfigport.mk @@ -0,0 +1,10 @@ +# Enable/disable modules and 3rd-party libs to be included in interpreter + +# Build 32-bit binaries on a 64-bit host +MICROPY_FORCE_32BIT = 0 + +# Linking with GNU readline causes binary to be licensed under GPL +MICROPY_USE_READLINE = 1 + +# ffi module requires libffi (libffi-dev Debian package) +MICROPY_PY_FFI = 0 diff --git a/ports/windows/msvc/common.props b/ports/windows/msvc/common.props new file mode 100644 index 000000000..26ea78e7e --- /dev/null +++ b/ports/windows/msvc/common.props @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ImportGroup Label="PropertySheets"> + <Import Project="paths.props" Condition="'$(PyPathsIncluded)' != 'True'"/> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <OutDir>$(PyOutDir)</OutDir> + <IntDir>$(PyIntDir)</IntDir> + <PyFileCopyCookie>$(PyBuildDir)copycookie$(Configuration)$(Platform)</PyFileCopyCookie> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <AdditionalIncludeDirectories>$(PyIncDirs);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>false</SDLCheck> + <WarningLevel>Level1</WarningLevel> + <ExceptionHandling>false</ExceptionHandling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <MinimalRebuild>false</MinimalRebuild> + </ClCompile> + <Link> + <GenerateDebugInformation>true</GenerateDebugInformation> + <GenerateMapFile>true</GenerateMapFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <PyOutputFiles Include="$(TargetPath)"> + <Destination>$(PyWinDir)%(FileName)%(Extension)</Destination> + </PyOutputFiles> + <PyCookieFiles Include="$(PyBuildDir)copycookie*" Exclude="$(PyFileCopyCookie)"/> + </ItemGroup> + + <!-- Copy PyOutputFiles to their target destination. + To force this when switching between platforms/configurations which are already up-to-date (and as such, + for which a build wouldn't even start because all outputs are effectively newer than the inputs) + an empty file $(PyFileCopyCookie) is created serving as a record to indicate what was last copied, + and any previous records are deleted. So when switching between builds which are otherwise up-to-date + the tracker will notice a missing file and a build is started anyway (and it will just copy our files). --> + <Target Name="CopyFilesToWinDir" AfterTargets="Build" + Inputs="$(TargetPath)" Outputs="$(PyFileCopyCookie);@(PyOutputFiles->'%(Destination)')"> + <Delete Files="@(PyCookieFiles)"/> + <Touch Files="$(PyFileCopyCookie)" AlwaysCreate="true"/> + <Copy SourceFiles="%(PyOutputFiles.Identity)" DestinationFiles="%(PyOutputFiles.Destination)"/> + <WriteLinesToFile File="$(TLogLocation)$(ProjectName).write.u.tlog" Lines="$(PyFileCopyCookie);@(PyOutputFiles->'%(Destination)')" Overwrite="True"/> + </Target> +</Project> diff --git a/ports/windows/msvc/debug.props b/ports/windows/msvc/debug.props new file mode 100644 index 000000000..fa1ca4fcb --- /dev/null +++ b/ports/windows/msvc/debug.props @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + </PropertyGroup> + <ItemDefinitionGroup /> + <ItemGroup /> +</Project>
\ No newline at end of file diff --git a/ports/windows/msvc/dirent.c b/ports/windows/msvc/dirent.c new file mode 100644 index 000000000..e050432a1 --- /dev/null +++ b/ports/windows/msvc/dirent.c @@ -0,0 +1,103 @@ +/* +* This file is part of the MicroPython project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2015 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include "dirent.h" +#include <errno.h> +#include <Windows.h> + +typedef struct DIR { + HANDLE findHandle; + WIN32_FIND_DATA findData; + struct dirent result; +} DIR; + +DIR *opendir(const char *name) { + if (!name || !*name) { + errno = ENOENT; + return NULL; + } + + DIR *dir = malloc(sizeof(DIR)); + if (!dir) { + errno = ENOMEM; + return NULL; + } + dir->result.d_ino = 0; + dir->result.d_name = NULL; + dir->findHandle = INVALID_HANDLE_VALUE; + + const size_t nameLen = strlen(name); + char *path = malloc(nameLen + 3); // allocate enough for adding "/*" + if (!path) { + free(dir); + errno = ENOMEM; + return NULL; + } + strcpy(path, name); + + // assure path ends with wildcard + const char lastChar = path[nameLen - 1]; + if (lastChar != '*') { + const char *appendWC = (lastChar != '/' && lastChar != '\\') ? "/*" : "*"; + strcat(path, appendWC); + } + + // init + dir->findHandle = FindFirstFile(path, &dir->findData); + free(path); + if (dir->findHandle == INVALID_HANDLE_VALUE) { + free(dir); + errno = ENOENT; + return NULL; + } + return dir; +} + +int closedir(DIR *dir) { + if (dir) { + FindClose(dir->findHandle); + free(dir); + return 0; + } else { + errno = EBADF; + return -1; + } +} + +struct dirent *readdir(DIR *dir) { + if (!dir) { + errno = EBADF; + return NULL; + } + + // first pass d_name is NULL so use result from FindFirstFile in opendir, else use FindNextFile + if (!dir->result.d_name || FindNextFile(dir->findHandle, &dir->findData)) { + dir->result.d_name = dir->findData.cFileName; + return &dir->result; + } + + return NULL; +} diff --git a/ports/windows/msvc/dirent.h b/ports/windows/msvc/dirent.h new file mode 100644 index 000000000..fca06785a --- /dev/null +++ b/ports/windows/msvc/dirent.h @@ -0,0 +1,48 @@ +/* +* This file is part of the MicroPython project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2015 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef MICROPY_INCLUDED_WINDOWS_MSVC_DIRENT_H +#define MICROPY_INCLUDED_WINDOWS_MSVC_DIRENT_H + +// dirent.h implementation for msvc + +// for ino_t +#include <sys/types.h> + +// opaque DIR structure +typedef struct DIR DIR; + +// the dirent structure +// d_ino is always 0 - if ever needed use GetFileInformationByHandle +typedef struct dirent { + ino_t d_ino; + char *d_name; +} dirent; + +DIR *opendir(const char *name); +int closedir(DIR *dir); +struct dirent *readdir(DIR *dir); + +#endif // MICROPY_INCLUDED_WINDOWS_MSVC_DIRENT_H diff --git a/ports/windows/msvc/genhdr.targets b/ports/windows/msvc/genhdr.targets new file mode 100644 index 000000000..cac3e3ddc --- /dev/null +++ b/ports/windows/msvc/genhdr.targets @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="GenerateHeaders"> + + <Import Project="paths.props" Condition="'$(PyPathsIncluded)' != 'True'"/> + + <!--Generate qstrdefs.generated.h and mpversion.h similar to what is done in py/mkrules.mk and py/py.mk--> + <Target Name="GenerateHeaders" DependsOnTargets="MakeVersionHdr;MakeQstrData"> + </Target> + + <PropertyGroup> + <DestDir>$(PyBuildDir)genhdr\</DestDir> + <PySrcDir>$(PyBaseDir)py\</PySrcDir> + <QstrDefs>$(PyBaseDir)unix\qstrdefsport.h</QstrDefs> + <PyQstrDefs>$(PySrcDir)qstrdefs.h</PyQstrDefs> + <QstrDefsCollected>$(DestDir)qstrdefscollected.h</QstrDefsCollected> + <QstrGen>$(DestDir)qstrdefs.generated.h</QstrGen> + <PyPython Condition="'$(PyPython)' == ''">python</PyPython> + </PropertyGroup> + + <Target Name="MakeDestDir"> + <MakeDir Directories="$(DestDir)"/> + </Target> + + <!-- Concatenate preprocessed files for use with makeqstrdefs.py. + Filters out any lines which aren't used by makeqstrdefs.py so the resulting file is + hundreds of times smaller and processing in python takes substantially less time--> + <UsingTask TaskName="ConcatPreProcFiles" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" > + <ParameterGroup> + <OutputFile Required="true" ParameterType="System.String"/> + <InputFiles Required="true" ParameterType="System.String[]"/> + </ParameterGroup> + <Task> + <Code Type="Fragment" Language="cs"> + <![CDATA[ +using(var outFile = System.IO.File.CreateText(OutputFile)) { + foreach(var inFile in InputFiles) + foreach(var line in System.IO.File.ReadAllLines(inFile)) + if((line.Contains(".c") && line.StartsWith("#line")) || line.Contains("MP_QSTR")) + outFile.WriteLine( line ); +} + ]]> + </Code> + </Task> + </UsingTask> + + <!-- If any of these changed we'll force all qstrs to be generated again--> + <ItemGroup> + <QstrDependencies Include="$(PyWinDir)mpconfigport.h;$(PySrcDir)mpconfig.h;$(PySrcDir)makeqstrdata.py"/> + </ItemGroup> + + <!-- Preprocess changed files, concatenate and feed into makeqstrdefs.py split/cat--> + <Target Name="MakeQstrDefs" DependsOnTargets="MakeDestDir" Inputs="@(ClCompile);@(QstrDependencies)" Outputs="$(QstrDefsCollected)"> + <ItemGroup> + <PyIncDirs Include="$(PyIncDirs)"/> + <PreProcDefs Include="%(ClCompile.PreProcessorDefinitions);NO_QSTR;N_X64;N_X86;N_THUMB;N_ARM"/> + <PyQstrSourceFiles Include="@(ClCompile)"> + <OutFile>$([System.String]::new('%(FullPath)').Replace('$(PyBaseDir)', '$(DestDir)qstr\'))</OutFile> + </PyQstrSourceFiles> + <PyQstrSourceFiles> + <OutFile>$([System.IO.Path]::ChangeExtension('%(OutFile)', '.pp'))</OutFile> + <OutDir>$([System.IO.Path]::GetDirectoryName('%(OutFile)'))</OutDir> + </PyQstrSourceFiles> + <PyQstrSourceFiles> + <Changed Condition="$([System.DateTime]::Compare($([System.IO.File]::GetLastWriteTime('%(FullPath)')), $([System.IO.File]::GetLastWriteTime('%(OutFile)')))) > 0">True</Changed> + </PyQstrSourceFiles> + <QstrDependencies> + <Changed Condition="$([System.DateTime]::Compare($([System.IO.File]::GetLastWriteTime('%(FullPath)')), $([System.IO.File]::GetLastWriteTime('$(DestDir)qstr.i.last')))) > 0">True</Changed> + </QstrDependencies> + </ItemGroup> + <PropertyGroup> + <ForceQstrRebuild>@(QstrDependencies->AnyHaveMetadataValue('Changed', 'True'))</ForceQstrRebuild> + <RunPreProcConcat>@(PyQstrSourceFiles->AnyHaveMetadataValue('Changed', 'True'))</RunPreProcConcat> + </PropertyGroup> + + <MakeDir Directories="@(PyQstrSourceFiles->'%(OutDir)')"/> + <Exec Command="cl /nologo /I@(PyIncDirs, ' /I') /D@(PreProcDefs, ' /D') /Fi%(PyQstrSourceFiles.OutFile) /P %(PyQstrSourceFiles.Identity)" + Condition="'%(PyQstrSourceFiles.Changed)' == 'True' Or '$(ForceQstrRebuild)' == 'True'"/> + <ConcatPreProcFiles InputFiles="@(PyQstrSourceFiles->'%(OutFile)')" OutputFile="$(DestDir)qstr.i.last" + Condition="'$(RunPreProcConcat)' == 'True' Or '$(ForceQstrRebuild)' == 'True'"/> + <Exec Command="$(PyPython) $(PySrcDir)makeqstrdefs.py split $(DestDir)qstr.i.last $(DestDir)qstr $(QstrDefsCollected)"/> + <Exec Command="$(PyPython) $(PySrcDir)makeqstrdefs.py cat $(DestDir)qstr.i.last $(DestDir)qstr $(QstrDefsCollected)"/> + </Target> + + <Target Name="MakeQstrData" DependsOnTargets="MakeQstrDefs" Inputs="$(QstrDefsCollected);$(PyQstrDefs);$(QstrDefs)" Outputs="$(QstrGen)"> + <PropertyGroup> + <TmpFile>$(QstrGen).tmp</TmpFile> + </PropertyGroup> + <Exec Command="cl /nologo /I@(PyIncDirs, ' /I') /D@(PreProcDefs, ' /D') /E $(PyQstrDefs) $(QstrDefs) > $(DestDir)qstrdefspreprocessed.h"/> + <Exec Command="$(PyPython) $(PySrcDir)makeqstrdata.py $(DestDir)qstrdefspreprocessed.h $(QstrDefsCollected) > $(TmpFile)"/> + <MSBuild Projects="$(MSBuildThisFileFullPath)" Targets="CopyFileIfDifferent" Properties="SourceFile=$(TmpFile);DestFile=$(QstrGen)"/> + </Target> + + <Target Name="MakeVersionHdr" DependsOnTargets="MakeDestDir"> + <PropertyGroup> + <DestFile>$(DestDir)mpversion.h</DestFile> + <TmpFile>$(DestFile).tmp</TmpFile> + </PropertyGroup> + <Exec Command="$(PyPython) $(PySrcDir)makeversionhdr.py $(TmpFile)"/> + <MSBuild Projects="$(MSBuildThisFileFullPath)" Targets="CopyFileIfDifferent" Properties="SourceFile=$(TmpFile);DestFile=$(DestFile)"/> + </Target> + + <Target Name="RemoveGeneratedFiles" AfterTargets="Clean"> + <RemoveDir Directories="$(DestDir)"/> + </Target> + + <!--Copies SourceFile to DestFile only if SourceFile's content differs from DestFile's. + We use this to 'touch' the generated files only when they are really newer + so a build is only triggered if the generated content actually changed, + and not just because the file date changed since the last build--> + <Target Name="CopyFileIfDifferent"> + <Exec Command="fc /B $(SourceFile) $(DestFile) > NUL 2>&1" IgnoreExitCode="true"> + <Output TaskParameter="ExitCode" PropertyName="FilesDiffer" /> + </Exec> + <Copy SourceFiles="$(SourceFile)" DestinationFiles="$(DestFile)" Condition="'$(FilesDiffer)'!='0'"/> + </Target> + +</Project> diff --git a/ports/windows/msvc/gettimeofday.c b/ports/windows/msvc/gettimeofday.c new file mode 100644 index 000000000..5f816df70 --- /dev/null +++ b/ports/windows/msvc/gettimeofday.c @@ -0,0 +1,58 @@ +/* +* This file is part of the MicroPython project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2013, 2014 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +#include <Winsock2.h> + +typedef union { + unsigned __int64 tm; // time in 100 nanoseconds interval + FILETIME ft; +} FT; + +int gettimeofday(struct timeval *tp, struct timezone *tz) { + if (tp == NULL) { + return 0; + } + + // UTC time + FT ft; + ZeroMemory(&ft, sizeof(ft)); + GetSystemTimeAsFileTime(&ft.ft); + + // to microseconds + ft.tm /= 10; + + // convert to unix format + // number of microseconds intervals between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days) + const unsigned __int64 deltaEpoch = 11644473600000000ull; + const unsigned __int64 microSecondsToSeconds = 1000000ull; + tp->tv_usec = ft.tm % microSecondsToSeconds; + tp->tv_sec = (ft.tm - deltaEpoch) / microSecondsToSeconds; + + // see man gettimeofday: timezone is deprecated and expected to be NULL + (void)tz; + + return 0; +} diff --git a/ports/windows/msvc/paths.props b/ports/windows/msvc/paths.props new file mode 100644 index 000000000..716698243 --- /dev/null +++ b/ports/windows/msvc/paths.props @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <PyPathsIncluded>True</PyPathsIncluded> + + <!-- The properties below specify the output directory structure. + This defaults to, for example for Configuration = Debug and Platform = x64: + + micropython [PyBaseDir] + |- ... + |- windows [PyWinDir] + |- ... + |- micropython.exe + |- build [PyBuildDir] + |- Debugx64 [PyOutDir] + | |- ... + | |- micropython.exe + | |- micropython.map + | |- obj [PyIntDir] + |- genhdr + + Note that the micropython executable will be copied from PyOutDir + to PyWinDir after each build. --> + + <!-- Start from project root --> + <PyBaseDir>$([System.IO.Path]::GetFullPath(`$(MSBuildThisFileDirectory)..\..`))\</PyBaseDir> + <PyWinDir>$(PyBaseDir)windows\</PyWinDir> + <PyBuildDir Condition="'$(PyBuildDir)' == ''">$(PyWinDir)build\</PyBuildDir> + + <!-- All include directories needed for uPy --> + <PyIncDirs>$(PyBaseDir);$(PyWinDir);$(PyBuildDir);$(PyWinDir)msvc</PyIncDirs> + + <!-- Within PyBuildDir different subdirectories are used based on configuration and platform. + By default these are chosen based on the Configuration and Platform properties, but + this file might be imported by other projects (to figure out where the artifacts go + or what the include files are) and those projects might already contain conflicting + Configuration/Platform properties, so allow to override these --> + <PyPlatform Condition="'$(PyPlatform)' == ''">$(Platform)</PyPlatform> + <PyConfiguration Condition="'$(PyConfiguration)' == ''">$(Configuration)</PyConfiguration> + + <!-- The final destination directories --> + <PyOutDir>$(PyBuildDir)$(PyConfiguration)$(PyPlatform)\</PyOutDir> + <PyIntDir>$(PyOutDir)obj\</PyIntDir> + </PropertyGroup> +</Project> diff --git a/ports/windows/msvc/release.props b/ports/windows/msvc/release.props new file mode 100644 index 000000000..ea0bf433d --- /dev/null +++ b/ports/windows/msvc/release.props @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <ItemDefinitionGroup> + <Link> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + </Link> + <ClCompile> + <IntrinsicFunctions>true</IntrinsicFunctions> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup /> +</Project> diff --git a/ports/windows/msvc/sources.props b/ports/windows/msvc/sources.props new file mode 100644 index 000000000..a97686cdc --- /dev/null +++ b/ports/windows/msvc/sources.props @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="paths.props" Condition="'$(PyPathsIncluded)' != 'True'"/> + <ItemGroup> + <ClCompile Include="$(PyBaseDir)py\*.c" /> + <ClCompile Include="$(PyBaseDir)windows\*.c" /> + <ClCompile Include="$(PyBaseDir)windows\msvc\*.c" /> + <ClCompile Include="$(PyBaseDir)lib\mp-readline\*.c" /> + <ClCompile Include="$(PyBaseDir)unix\file.c"/> + <ClCompile Include="$(PyBaseDir)unix\gccollect.c"/> + <ClCompile Include="$(PyBaseDir)unix\input.c"/> + <ClCompile Include="$(PyBaseDir)unix\main.c"/> + <ClCompile Include="$(PyBaseDir)unix\modos.c"/> + <ClCompile Include="$(PyBaseDir)unix\modtime.c"/> + <ClCompile Include="$(PyBaseDir)unix\modmachine.c" /> + <ClCompile Include="$(PyBaseDir)extmod\machine_mem.c" /> + <ClCompile Include="$(PyBaseDir)extmod\machine_pinbase.c" /> + <ClCompile Include="$(PyBaseDir)extmod\machine_pulse.c" /> + <ClCompile Include="$(PyBaseDir)extmod\machine_signal.c" /> + <ClCompile Include="$(PyBaseDir)extmod\modubinascii.c" /> + <ClCompile Include="$(PyBaseDir)extmod\moductypes.c" /> + <ClCompile Include="$(PyBaseDir)extmod\moduhashlib.c" /> + <ClCompile Include="$(PyBaseDir)extmod\moduheapq.c" /> + <ClCompile Include="$(PyBaseDir)extmod\modujson.c" /> + <ClCompile Include="$(PyBaseDir)extmod\modurandom.c" /> + <ClCompile Include="$(PyBaseDir)extmod\modure.c" /> + <ClCompile Include="$(PyBaseDir)extmod\modutimeq.c" /> + <ClCompile Include="$(PyBaseDir)extmod\moduzlib.c" /> + <ClCompile Include="$(PyBaseDir)extmod\utime_mphal.c" /> + <ClCompile Include="$(PyBaseDir)extmod\virtpin.c" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="$(PyBaseDir)py\*.h" /> + <ClInclude Include="$(PyBaseDir)windows\*.h" /> + <ClInclude Include="$(PyBaseDir)windows\msvc\*.h" /> + </ItemGroup> +</Project> diff --git a/ports/windows/msvc/sys/time.h b/ports/windows/msvc/sys/time.h new file mode 100644 index 000000000..7c95d409e --- /dev/null +++ b/ports/windows/msvc/sys/time.h @@ -0,0 +1,32 @@ +/* +* This file is part of the MicroPython project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2013, 2014 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef MICROPY_INCLUDED_WINDOWS_MSVC_SYS_TIME_H +#define MICROPY_INCLUDED_WINDOWS_MSVC_SYS_TIME_H + +// Get the definitions for timeval etc +#include <Winsock2.h> + +#endif // MICROPY_INCLUDED_WINDOWS_MSVC_SYS_TIME_H diff --git a/ports/windows/msvc/unistd.h b/ports/windows/msvc/unistd.h new file mode 100644 index 000000000..1a1629be4 --- /dev/null +++ b/ports/windows/msvc/unistd.h @@ -0,0 +1,44 @@ +/* +* This file is part of the MicroPython project, http://micropython.org/ +* +* The MIT License (MIT) +* +* Copyright (c) 2013, 2014 Damien P. George +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +#ifndef MICROPY_INCLUDED_WINDOWS_MSVC_UNISTD_H +#define MICROPY_INCLUDED_WINDOWS_MSVC_UNISTD_H + +// There's no unistd.h, but this is the equivalent +#include <io.h> + +#define F_OK 0 +#define W_OK 2 +#define R_OK 4 + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#define SEEK_CUR 1 +#define SEEK_END 2 +#define SEEK_SET 0 + +#endif // MICROPY_INCLUDED_WINDOWS_MSVC_UNISTD_H diff --git a/ports/windows/realpath.c b/ports/windows/realpath.c new file mode 100644 index 000000000..ac9adf812 --- /dev/null +++ b/ports/windows/realpath.c @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> + +// Make sure a path only has forward slashes. +char *to_unix_path(char *p) { + if (p != NULL) { + char *pp = p; + while (*pp != 0) { + if (*pp == '\\') + *pp = '/'; + ++pp; + } + } + return p; +} + +// Implement realpath() using _fullpath and make it use the same error codes as realpath() on unix. +// Also have it return a path with forward slashes only as some code relies on this, +// but _fullpath() returns backward slashes no matter what. +char *realpath(const char *path, char *resolved_path) { + char *ret = NULL; + if (path == NULL) { + errno = EINVAL; + } else if (access(path, R_OK) == 0) { + ret = resolved_path; + if (ret == NULL) + ret = malloc(_MAX_PATH); + if (ret == NULL) { + errno = ENOMEM; + } else { + ret = _fullpath(ret, path, _MAX_PATH); + if (ret == NULL) + errno = EIO; + } + } + return to_unix_path(ret); +} diff --git a/ports/windows/realpath.h b/ports/windows/realpath.h new file mode 100644 index 000000000..869fe80fa --- /dev/null +++ b/ports/windows/realpath.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_WINDOWS_REALPATH_H +#define MICROPY_INCLUDED_WINDOWS_REALPATH_H + +extern char *realpath(const char *path, char *resolved_path); + +#endif // MICROPY_INCLUDED_WINDOWS_REALPATH_H diff --git a/ports/windows/sleep.c b/ports/windows/sleep.c new file mode 100644 index 000000000..6043ec7b7 --- /dev/null +++ b/ports/windows/sleep.c @@ -0,0 +1,76 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <windows.h> +#include <errno.h> +#include <limits.h> + +HANDLE waitTimer = NULL; + +void init_sleep(void) { + waitTimer = CreateWaitableTimer(NULL, TRUE, NULL); +} + +void deinit_sleep(void) { + if (waitTimer != NULL) { + CloseHandle(waitTimer); + waitTimer = NULL; + } +} + +int usleep_impl(__int64 usec) { + if (waitTimer == NULL) { + errno = EAGAIN; + return -1; + } + if (usec < 0 || usec > LLONG_MAX / 10) { + errno = EINVAL; + return -1; + } + + LARGE_INTEGER ft; + ft.QuadPart = -10 * usec; // 100 nanosecond interval, negative value = relative time + if (SetWaitableTimer(waitTimer, &ft, 0, NULL, NULL, 0) == 0) { + errno = EINVAL; + return -1; + } + if (WaitForSingleObject(waitTimer, INFINITE) != WAIT_OBJECT_0) { + errno = EAGAIN; + return -1; + } + return 0; +} + +#ifdef _MSC_VER // mingw and the likes provide their own usleep() +int usleep(__int64 usec) { + return usleep_impl(usec); +} +#endif + +void msec_sleep(double msec) { + const double usec = msec * 1000.0; + usleep_impl(usec > (double)LLONG_MAX ? LLONG_MAX : (__int64)usec); +} diff --git a/ports/windows/sleep.h b/ports/windows/sleep.h new file mode 100644 index 000000000..430ec3a43 --- /dev/null +++ b/ports/windows/sleep.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_WINDOWS_SLEEP_H +#define MICROPY_INCLUDED_WINDOWS_SLEEP_H + +void init_sleep(void); +void deinit_sleep(void); +void msec_sleep(double msec); +#ifdef _MSC_VER +int usleep(__int64 usec); +#endif + +#endif // MICROPY_INCLUDED_WINDOWS_SLEEP_H diff --git a/ports/windows/windows_mphal.c b/ports/windows/windows_mphal.c new file mode 100644 index 000000000..153b04423 --- /dev/null +++ b/ports/windows/windows_mphal.c @@ -0,0 +1,229 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include "py/mpstate.h" +#include "py/mphal.h" + +#include <sys/time.h> +#include <windows.h> +#include <unistd.h> + +HANDLE std_in = NULL; +HANDLE con_out = NULL; +DWORD orig_mode = 0; + +STATIC void assure_stdin_handle() { + if (!std_in) { + std_in = GetStdHandle(STD_INPUT_HANDLE); + assert(std_in != INVALID_HANDLE_VALUE); + } +} + +STATIC void assure_conout_handle() { + if (!con_out) { + con_out = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, 0); + assert(con_out != INVALID_HANDLE_VALUE); + } +} + +void mp_hal_stdio_mode_raw(void) { + assure_stdin_handle(); + GetConsoleMode(std_in, &orig_mode); + DWORD mode = orig_mode; + mode &= ~ENABLE_ECHO_INPUT; + mode &= ~ENABLE_LINE_INPUT; + mode &= ~ENABLE_PROCESSED_INPUT; + SetConsoleMode(std_in, mode); +} + +void mp_hal_stdio_mode_orig(void) { + assure_stdin_handle(); + SetConsoleMode(std_in, orig_mode); +} + +// Handler to be installed by SetConsoleCtrlHandler, currently used only to handle Ctrl-C. +// This handler has to be installed just once (this has to be done elswhere in init code). +// Previous versions of the mp_hal code would install a handler whenever Ctrl-C input is +// allowed and remove the handler again when it is not. That is not necessary though (1), +// and it might introduce problems (2) because console notifications are delivered to the +// application in a separate thread. +// (1) mp_hal_set_interrupt_char effectively enables/disables processing of Ctrl-C via the +// ENABLE_PROCESSED_INPUT flag so in raw mode console_sighandler won't be called. +// (2) if mp_hal_set_interrupt_char would remove the handler while Ctrl-C was issued earlier, +// the thread created for handling it might not be running yet so we'd miss the notification. +BOOL WINAPI console_sighandler(DWORD evt) { + if (evt == CTRL_C_EVENT) { + if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) { + // this is the second time we are called, so die straight away + exit(1); + } + mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); + MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)); + return TRUE; + } + return FALSE; +} + +void mp_hal_set_interrupt_char(char c) { + assure_stdin_handle(); + if (c == CHAR_CTRL_C) { + DWORD mode; + GetConsoleMode(std_in, &mode); + mode |= ENABLE_PROCESSED_INPUT; + SetConsoleMode(std_in, mode); + } else { + DWORD mode; + GetConsoleMode(std_in, &mode); + mode &= ~ENABLE_PROCESSED_INPUT; + SetConsoleMode(std_in, mode); + } +} + +void mp_hal_move_cursor_back(uint pos) { + assure_conout_handle(); + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(con_out, &info); + info.dwCursorPosition.X -= (short)pos; + if (info.dwCursorPosition.X < 0) { + info.dwCursorPosition.X = 0; + } + SetConsoleCursorPosition(con_out, info.dwCursorPosition); +} + +void mp_hal_erase_line_from_cursor(uint n_chars_to_erase) { + assure_conout_handle(); + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(con_out, &info); + DWORD written; + FillConsoleOutputCharacter(con_out, ' ', n_chars_to_erase, info.dwCursorPosition, &written); + FillConsoleOutputAttribute(con_out, info.wAttributes, n_chars_to_erase, info.dwCursorPosition, &written); +} + +typedef struct item_t { + WORD vkey; + const char *seq; +} item_t; + +// map virtual key codes to VT100 escape sequences +STATIC item_t keyCodeMap[] = { + {VK_UP, "[A"}, + {VK_DOWN, "[B"}, + {VK_RIGHT, "[C"}, + {VK_LEFT, "[D"}, + {VK_HOME, "[H"}, + {VK_END, "[F"}, + {VK_DELETE, "[3~"}, + {0, ""} //sentinel +}; + +STATIC const char *cur_esc_seq = NULL; + +STATIC int esc_seq_process_vk(int vk) { + for (item_t *p = keyCodeMap; p->vkey != 0; ++p) { + if (p->vkey == vk) { + cur_esc_seq = p->seq; + return 27; // ESC, start of escape sequence + } + } + return 0; // nothing found +} + +STATIC int esc_seq_chr() { + if (cur_esc_seq) { + const char c = *cur_esc_seq++; + if (c) { + return c; + } + cur_esc_seq = NULL; + } + return 0; +} + +int mp_hal_stdin_rx_chr(void) { + // currently processing escape seq? + const int ret = esc_seq_chr(); + if (ret) { + return ret; + } + + // poll until key which we handle is pressed + assure_stdin_handle(); + DWORD num_read; + INPUT_RECORD rec; + for (;;) { + if (!ReadConsoleInput(std_in, &rec, 1, &num_read) || !num_read) { + return CHAR_CTRL_C; // EOF, ctrl-D + } + if (rec.EventType != KEY_EVENT || !rec.Event.KeyEvent.bKeyDown) { // only want key down events + continue; + } + const char c = rec.Event.KeyEvent.uChar.AsciiChar; + if (c) { // plain ascii char, return it + return c; + } + const int ret = esc_seq_process_vk(rec.Event.KeyEvent.wVirtualKeyCode); + if (ret) { + return ret; + } + } +} + +void mp_hal_stdout_tx_strn(const char *str, size_t len) { + write(1, str, len); +} + +void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { + mp_hal_stdout_tx_strn(str, len); +} + +void mp_hal_stdout_tx_str(const char *str) { + mp_hal_stdout_tx_strn(str, strlen(str)); +} + +mp_uint_t mp_hal_ticks_ms(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +mp_uint_t mp_hal_ticks_us(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +mp_uint_t mp_hal_ticks_cpu(void) { + LARGE_INTEGER value; + QueryPerformanceCounter(&value); +#ifdef _WIN64 + return value.QuadPart; +#else + return value.LowPart; +#endif +} diff --git a/ports/windows/windows_mphal.h b/ports/windows/windows_mphal.h new file mode 100644 index 000000000..5a93d4e18 --- /dev/null +++ b/ports/windows/windows_mphal.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "sleep.h" +#include "unix/mphalport.h" + +#define MICROPY_HAL_HAS_VT100 (0) + +void mp_hal_move_cursor_back(unsigned int pos); +void mp_hal_erase_line_from_cursor(unsigned int n_chars_to_erase); + +#undef mp_hal_ticks_cpu +mp_uint_t mp_hal_ticks_cpu(void); |
