diff --git a/example/brainfuck/bottles.bf b/example/brainfuck/bottles.bf new file mode 100644 index 00000000..b8db9cda --- /dev/null +++ b/example/brainfuck/bottles.bf @@ -0,0 +1,45 @@ +// 99 Bottles of Beer +">+++++++++[<+++++++++++>-]<[>[-]>[-]<<[>+>+<<-]>>[<<+>>-]>>>" +"[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<" +"-]<<-<-]+++++++++>[<->-]>>+>[<[-]<<+>>>-]>[-]+<<[>+>-<<-]<<<" +"[>>+>+<<<-]>>>[<<<+>>>-]>[<+>-]<<-[>[-]<[-]]>>+<[>[-]<-]<+++" +"+++++[<++++++<++++++>>-]>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-" +"]<<<<<<.>>[-]>[-]++++[<++++++++>-]<.>++++[<++++++++>-]<++.>+" +"++++[<+++++++++>-]<.><+++++..--------.-------.>>[>>+>+<<<-]>" +">>[<<<+>>>-]<[<<<<++++++++++++++.>>>>-]<<<<[-]>++++[<+++++++" +"+>-]<.>+++++++++[<+++++++++>-]<--.---------.>+++++++[<------" +"---->-]<.>++++++[<+++++++++++>-]<.+++..+++++++++++++.>++++++" +"++[<---------->-]<--.>+++++++++[<+++++++++>-]<--.-.>++++++++" +"[<---------->-]<++.>++++++++[<++++++++++>-]<++++.-----------" +"-.---.>+++++++[<---------->-]<+.>++++++++[<+++++++++++>-]<-." +">++[<----------->-]<.+++++++++++..>+++++++++[<---------->-]<" +"-----.---.>>>[>+>+<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>>+++" +"+[<++++++>-]<--.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<." +"><+++++..--------.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++" +"++++++++++++.>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<++" +"+++++++>-]<--.---------.>+++++++[<---------->-]<.>++++++[<++" +"+++++++++>-]<.+++..+++++++++++++.>++++++++++[<---------->-]<" +"-.---.>+++++++[<++++++++++>-]<++++.+++++++++++++.++++++++++." +"------.>+++++++[<---------->-]<+.>++++++++[<++++++++++>-]<-." +"-.---------.>+++++++[<---------->-]<+.>+++++++[<++++++++++>-" +"]<--.+++++++++++.++++++++.---------.>++++++++[<---------->-]" +"<++.>+++++[<+++++++++++++>-]<.+++++++++++++.----------.>++++" +"+++[<---------->-]<++.>++++++++[<++++++++++>-]<.>+++[<----->" +"-]<.>+++[<++++++>-]<..>+++++++++[<--------->-]<--.>+++++++[<" +"++++++++++>-]<+++.+++++++++++.>++++++++[<----------->-]<++++" +".>+++++[<+++++++++++++>-]<.>+++[<++++++>-]<-.---.++++++.----" +"---.----------.>++++++++[<----------->-]<+.---.[-]<<<->[-]>[" +"-]<<[>+>+<<-]>>[<<+>>-]>>>[-]<<<+++++++++<[>>>+<<[>+>[-]<<-]" +">[<+>-]>[<<++++++++++>>>+<-]<<-<-]+++++++++>[<->-]>>+>[<[-]<" +"<+>>>-]>[-]+<<[>+>-<<-]<<<[>>+>+<<<-]>>>[<<<+>>>-]<>>[<+>-]<" +"<-[>[-]<[-]]>>+<[>[-]<-]<++++++++[<++++++<++++++>>-]>>>[>+>+" +"<<-]>>[<<+>>-]<[<<<<<.>>>>>-]<<<<<<.>>[-]>[-]++++[<++++++++>" +"-]<.>++++[<++++++++>-]<++.>+++++[<+++++++++>-]<.><+++++..---" +"-----.-------.>>[>>+>+<<<-]>>>[<<<+>>>-]<[<<<<++++++++++++++" +".>>>>-]<<<<[-]>++++[<++++++++>-]<.>+++++++++[<+++++++++>-]<-" +"-.---------.>+++++++[<---------->-]<.>++++++[<+++++++++++>-]" +"<.+++..+++++++++++++.>++++++++[<---------->-]<--.>+++++++++[" +"<+++++++++>-]<--.-.>++++++++[<---------->-]<++.>++++++++[<++" +"++++++++>-]<++++.------------.---.>+++++++[<---------->-]<+." +">++++++++[<+++++++++++>-]<-.>++[<----------->-]<.+++++++++++" +"..>+++++++++[<---------->-]<-----.---.+++.---.[-]<<<]" diff --git a/example/brainfuck/echo.bf b/example/brainfuck/echo.bf new file mode 100644 index 00000000..c799d4cd --- /dev/null +++ b/example/brainfuck/echo.bf @@ -0,0 +1,2 @@ +// echo +"+[>,.<]" diff --git a/example/brainfuck/fizzBuzz.bf b/example/brainfuck/fizzBuzz.bf new file mode 100644 index 00000000..b57e5627 --- /dev/null +++ b/example/brainfuck/fizzBuzz.bf @@ -0,0 +1,6 @@ +// FizzBuzz +"++++++++++++[->++++++>+++++++++>+++++>++++++++++>++++++++++>+++>>>>>>++++++++<<<<<<<<<<<<]>-->--->++" +"++++>--->++>---->>>>+++>+++++>++++[>>>+[-<<[->>+>+<<<]>>>[-<<<+>>>]+<[[-]>-<<[->+>+<<]>>[-<<+>>]+<[[" +"-]>-<<<+>->]>[-<<<--------->+++++++++>>>>>+<<<]<]>[-<+++++++[<<+++++++>>-]<++++++++>>]>>>]<<<<<<[<<<" +"<]>-[-<<+>+>]<[->+<]+<[[-]>-<]>[->+++<<<<<<<<<.>.>>>..>>+>>]>>-[-<<<+>+>>]<<[->>+<<]+<[[-]>-<]>[->>+" +"++++<<<<<<<<.>.>..>>+>>]<+<[[-]>-<]>[->>>>>[>>>>]<<<<[.<<<<]<]<<.>>>>>>-]" diff --git a/example/brainfuck/hello.bf b/example/brainfuck/hello.bf new file mode 100644 index 00000000..c678869a --- /dev/null +++ b/example/brainfuck/hello.bf @@ -0,0 +1,3 @@ +// Hello, world! +"+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-." +"------------.<++++++++.--------.+++.------.--------.>+." diff --git a/example/brainfuck/quine.bf b/example/brainfuck/quine.bf new file mode 100644 index 00000000..2088368f --- /dev/null +++ b/example/brainfuck/quine.bf @@ -0,0 +1,11 @@ +// Quine +"-" +">++>+++>+>+>+++>>>>>>>>>>>>>>>>>>>>>>+>+>++>+++>++>>+++" +">+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>+>>+++>>>>+++>>>+++" +">+>>>>>>>++>+++>+++>+>>+++>+++>+>+++>+>+++>+>++>+++>>>+" +">+>+>+>++>+++>+>+>>+++>>>>>>>+>+>>>+>+>++>+++>+++>+>>+++" +">+++>+>+++>+>++>+++>++>>+>+>++>+++>+>+>>+++>>>+++>+>>>++" +">+++>+++>+>>+++>>>+++>+>+++>+>>+++>>+++>>" +"+[[>>+[>]+>+[<]<-]>>[>]<+<+++[<]<<+]" +">>>[>]+++>+" +"[+[<++++++++++++++++>-]<++++++++++.<]" diff --git a/example/brainfuck/self.bf b/example/brainfuck/self.bf new file mode 100644 index 00000000..adf9af9d --- /dev/null +++ b/example/brainfuck/self.bf @@ -0,0 +1,2 @@ +// Self-describing +"+++++[>+++++++++<-],[[>--.++>+<<-]>+.->[<.>-]<<,]" diff --git a/example/brainfuck/x86_compile.cpp b/example/brainfuck/x86_compile.cpp new file mode 100644 index 00000000..2ad57b5c --- /dev/null +++ b/example/brainfuck/x86_compile.cpp @@ -0,0 +1,578 @@ +/*============================================================================= + Copyright (c) 2011-2014 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// +// PE関連の構造体 +// からコピペ +// +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned short WORD; + + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + + +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + + // + // NT additional fields. + // + + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; + + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; +// union { +// DWORD PhysicalAddress; +// DWORD VirtualSize; +// } Misc; + struct { + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + + +// +// 出力バイナリサイズ +// +#ifndef BRAINFUCK_BINARY_SIZE +# define BRAINFUCK_BINARY_SIZE (16 * 1024) +#endif + +// +// ループ制限 +// +#ifndef BRAINFUCK_LOOP_LIMIT +# define BRAINFUCK_LOOP_LIMIT 256 +#endif + +// +// 入力ファイル名 +// +#ifndef BRAINFUCK_SOURCE_FILE +# define BRAINFUCK_SOURCE_FILE a.bf +#endif + + +// +// 定数 +// +SPROUT_STATIC_CONSTEXPR std::size_t bin_size = BRAINFUCK_BINARY_SIZE; + +SPROUT_STATIC_CONSTEXPR std::size_t loop_limit = BRAINFUCK_LOOP_LIMIT; + +SPROUT_STATIC_CONSTEXPR auto source = sprout::to_string( +# include SPROUT_PP_STRINGIZE(BRAINFUCK_SOURCE_FILE) + ); + +SPROUT_STATIC_CONSTEXPR std::int32_t addr_putchar = 0x00405044; +SPROUT_STATIC_CONSTEXPR std::int32_t addr_getchar = addr_putchar + 4; +SPROUT_STATIC_CONSTEXPR std::int32_t addr_buf = 0x00406000; + + +// +// 出力用関数 +// +template +SPROUT_CXX14_CONSTEXPR std::size_t +write_bytes(OutputIterator& out, T const& val) { + typedef sprout::little_endian_traits traits; + for (std::size_t i = 0; i != traits::size(); ++i) { + *out++ = sprout::little_endian_traits::get_byte(val, i); + } + return traits::size(); +} +template +SPROUT_CXX14_CONSTEXPR std::size_t +write_bytes(OutputIterator& out, T const(& vals)[N]) { + typedef sprout::little_endian_traits traits; + for (std::size_t i = 0; i != N; ++i) { + ::write_bytes(out, vals[i]); + } + return traits::size() * N; +} +template +SPROUT_CXX14_CONSTEXPR std::size_t +write_bytes(OutputIterator& out, Head const& head, Tail const&... tail) { + return ::write_bytes(out, head) + ::write_bytes(out, tail...); +} + +template +SPROUT_CXX14_CONSTEXPR std::size_t +write_pe_header(OutputIterator& out, std::size_t n = 0) { + SPROUT_CONSTEXPR unsigned char stub[] = { + // 00-3b: DOS Header + 'M', 'Z', 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 3c-3f: Pointer to PE Header (=80) + 0x80, 0x00, 0x00, 0x00, + // 40-7f: DOS Stub + 0xba, 0x10, 0x00, 0x0e, 0x1f, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x90, 0x90, + 'T', 'h', 'i', 's', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', + 'n', 'o', 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', + 'S', ' ', 'm', 'o', 'd', 'e', '.', '\r', '\n', '$', 0, 0, 0, 0, 0, 0, + // 80-83: PE Signature + 'P', 'E', 0, 0 + }; + n += ::write_bytes( + out, + stub + ); + + SPROUT_CONSTEXPR ::IMAGE_FILE_HEADER coff = { + 0x014c, // Machine + 3, // NumberOfSections + 0, // TimeDateStamp + 0, // PointerToSymbolTable + 0, // NumberOfSymbols + sizeof(::IMAGE_OPTIONAL_HEADER32), // SizeOfOptionalHeader + 0x030f // Characteristics + }; + n += ::write_bytes( + out, + coff.Machine, + coff.NumberOfSections, + coff.TimeDateStamp, + coff.PointerToSymbolTable, + coff.NumberOfSymbols, + coff.SizeOfOptionalHeader, + coff.Characteristics + ); + + SPROUT_CONSTEXPR ::IMAGE_OPTIONAL_HEADER32 opt = { + 0x010b, // Magic + 6, 0, // MajorLinkerVersion, MinorLinkerVersion + ::bin_size, // SizeOfCode + 0, // SizeOfInitializedData + 65536, // SizeOfUninitializedData + 0x1000, // AddressOfEntryPoint + 0x1000, // BaseOfCode + 0x6000, // BaseOfData + 0x00400000, // ImageBase + 0x1000, // SectionAlignment + 0x0200, // FileAlignment + 4, 0, // MajorOperatingSystemVersion, MinorOperatingSystemVersion + 0, 0, // MajorImageVersion, MinorImageVersion + 4, 0, // MajorSubsystemVersion, MinorSubsystemVersion + 0, // Win32VersionValue + 0x16000, // SizeOfImage + 0x200, // SizeOfHeaders + 0, // CheckSum + 3, // Subsystem + 0, // DllCharacteristics + 1024 * 1024, // SizeOfStackReserve + 8 * 1024, // SizeOfStackCommit + 1024 * 1024, // SizeOfHeapReserve + 4 * 1024, // SizeOfHeapCommit + 0, // LoaderFlags + 16, // NumberOfRvaAndSizes + { + {}, + { + 0x5000, // VirtualAddress (import table) + 100 // Size + }, + {} + } + }; + n += ::write_bytes( + out, + opt.Magic, + opt.MajorLinkerVersion, opt.MinorLinkerVersion, + opt.SizeOfCode, + opt.SizeOfInitializedData, + opt.SizeOfUninitializedData, + opt.AddressOfEntryPoint, + opt.BaseOfCode, + opt.BaseOfData, + opt.ImageBase, + opt.SectionAlignment, + opt.FileAlignment, + opt.MajorOperatingSystemVersion, opt.MinorOperatingSystemVersion, + opt.MajorImageVersion, opt.MinorImageVersion, + opt.MajorSubsystemVersion, opt.MinorSubsystemVersion, + opt.Win32VersionValue, + opt.SizeOfImage, + opt.SizeOfHeaders, + opt.CheckSum, + opt.Subsystem, + opt.DllCharacteristics, + opt.SizeOfStackReserve, + opt.SizeOfStackCommit, + opt.SizeOfHeapReserve, + opt.SizeOfHeapCommit, + opt.LoaderFlags, + opt.NumberOfRvaAndSizes, + opt.DataDirectory[0].VirtualAddress, opt.DataDirectory[0].Size, + opt.DataDirectory[1].VirtualAddress, opt.DataDirectory[1].Size + ); + for (std::size_t i = 2; i != IMAGE_NUMBEROF_DIRECTORY_ENTRIES; ++i) { + n += ::write_bytes( + out, + opt.DataDirectory[i].VirtualAddress, opt.DataDirectory[i].Size + ); + } + + SPROUT_CONSTEXPR ::IMAGE_SECTION_HEADER sects[3] = { + { + ".text", // Name + {::bin_size}, // Misc.VirtualSize + 0x1000, // VirtualAddress + ::bin_size, // SizeOfRawData + 0x400, // PointerToRawData + 0, // PointerToRelocations + 0, // PointerToLinenumbers + 0, // NumberOfRelocations + 0, // NumberOfLinenumbers + 0x60500060 // Characteristics + }, + { + ".idata", // Name + {100}, // Misc.VirtualSize + 0x5000, // VirtualAddress + 512, // SizeOfRawData + 0x200, // PointerToRawData + 0, // PointerToRelocations + 0, // PointerToLinenumbers + 0, // NumberOfRelocations + 0, // NumberOfLinenumbers + 0xc0300040 // Characteristics + }, + { + ".bss", // Name + {65536}, // Misc.VirtualSize + 0x6000, // VirtualAddress + 0, // SizeOfRawData + 0, // PointerToRawData + 0, // PointerToRelocations + 0, // PointerToLinenumbers + 0, // NumberOfRelocations + 0, // NumberOfLinenumbers + 0xc0400080 // Characteristics + } + }; + for (std::size_t i = 0; i != 3; ++i) { + n += ::write_bytes( + out, + sects[i].Name, + sects[i].Misc.VirtualSize, + sects[i].VirtualAddress, + sects[i].SizeOfRawData, + sects[i].PointerToRawData, + sects[i].PointerToRelocations, + sects[i].PointerToLinenumbers, + sects[i].NumberOfRelocations, + sects[i].NumberOfLinenumbers, + sects[i].Characteristics + ); + } + + for (; n != 0x200; ) { + n += ::write_bytes( + out, + (unsigned char)0 + ); + } + return n; +} + +template +SPROUT_CXX14_CONSTEXPR std::size_t +write_idata(OutputIterator& out, std::size_t n = 0) { + SPROUT_CONSTEXPR int idt[] = { + // IDT 1 + 0x5028, 0, 0, 0x5034, 0x5044, + // IDT (終端) + 0, 0, 0, 0, 0 + }; + n += ::write_bytes( + out, + idt + ); + + SPROUT_CONSTEXPR int ilt_iat[] = { + 0x5050, 0x505a, 0 + }; + + // ILT + n += ::write_bytes( + out, + ilt_iat + ); + n += ::write_bytes( + out, + "msvcrt.dll\0\0\0\0\0" + ); + + // IAT + n += ::write_bytes( + out, + ilt_iat + ); + n += ::write_bytes( + out, + (std::int16_t)0, + "putchar", + (std::int16_t)0, + "getchar" + ); + + for (; n != 0x400; ) { + n += ::write_bytes( + out, + (unsigned char)0 + ); + } + return n; +} + +// +// コンパイル +// +template +SPROUT_CXX14_CONSTEXPR std::size_t +compile(InputIterator first, InputIterator last, RandomAccessIterator& out_first) { + sprout::array loops {{}}; // ループを保存するスタック + auto loop_first = sprout::begin(loops); + auto loop_last = sprout::end(loops); + auto loop = loop_first; + + int idx = 0; + auto out = out_first; + + idx += ::write_bytes( + out, + (unsigned char)0x31, (unsigned char)0xc9, // xor ecx, ecx + (unsigned char)0x57, // push edi + (unsigned char)0xbf, ::addr_buf // mov edi, addr_buf + ); + + for (; first != last; ++first) { + switch (*first) { + case '>': + idx += ::write_bytes( + out, + (unsigned char)0x66, (unsigned char)0x41 // inc cx + ); + break; + case '<': + idx += ::write_bytes( + out, + (unsigned char)0x66, (unsigned char)0x49 // dec cx + ); + break; + case '+': + idx += ::write_bytes( + out, + (unsigned char)0xfe, (unsigned char)0x04, (unsigned char)0x0f // inc byte [edi+ecx] + ); + break; + case '-': + idx += ::write_bytes( + out, + (unsigned char)0xfe, (unsigned char)0x0c, (unsigned char)0x0f // dec byte [edi+ecx] + ); + break; + case '.': + idx += ::write_bytes( + out, + (unsigned char)0x51, // push ecx + (unsigned char)0x0f, (unsigned char)0xb6, (unsigned char)0x04, (unsigned char)0x0f, // movzx eax,byte [edi+ecx] + (unsigned char)0x50, // push eax + (unsigned char)0xa1, ::addr_putchar, // mov eax, [addr_putchar] + (unsigned char)0xff, (unsigned char)0xd0, // call eax + (unsigned char)0x58, // pop eax + (unsigned char)0x59 // pop ecx + ); + break; + case ',': + idx += ::write_bytes( + out, + (unsigned char)0x51, // push ecx + (unsigned char)0xa1, ::addr_getchar, // mov eax, [addr_getchar] + (unsigned char)0xff, (unsigned char)0xd0, // call eax + (unsigned char)0x59, // pop ecx + (unsigned char)0x88, (unsigned char)0x04, (unsigned char)0x0f // mov [edi+ecx],al + ); + break; + case '[': + SPROUT_ASSERT_MSG(loop != loop_last, "loop overflow"); + *loop++ = idx; // インデックスをスタックに積む + idx += ::write_bytes( + out, + (unsigned char)0x80, (unsigned char)0x3c, (unsigned char)0x0f, (unsigned char)0x00, // cmp byte [edi+ecx],0 + (unsigned char)0x0f, (unsigned char)0x84, // jz 対応する]の直後 + (unsigned char)0xde, (unsigned char)0xad, (unsigned char)0xbe, (unsigned char)0xef // (アドレスは後で決定) + ); + break; + case ']': + { + SPROUT_ASSERT_MSG(loop != loop_first, "missing '['"); + int idx_loop = *--loop; + idx += ::write_bytes( + out, + (unsigned char)0xe9, (std::int32_t)(idx_loop - (idx + 5)) // jmp idx_loop + ); + auto out_loop = out_first + (idx_loop + 6); + ::write_bytes( + out_loop, + (std::int32_t)(idx - (idx_loop + 10)) // (アドレス) + ); + break; + } + } + SPROUT_ASSERT_MSG(idx <= (int)::bin_size - 32, "buffer overflow"); + } + + SPROUT_ASSERT_MSG(loop == loop_first, "missing ']'"); + + // 終了処理 + idx += ::write_bytes( + out, + (unsigned char)0x5f, // pop edi + (unsigned char)0x31, (unsigned char)0xc0, // xor eax, eax + (unsigned char)0xc3 // ret + ); + + return idx; +} + +// +// ビルド +// +template +SPROUT_CXX14_CONSTEXPR std::size_t +build(InputIterator first, InputIterator last, RandomAccessIterator& out) { + std::size_t n = 0; + n += ::write_pe_header(out, n); // ヘッダ出力 + n += ::write_idata(out, n); // .idataセクション出力 + n += ::compile(first, last, out); // コンパイル + return n; +} + + +SPROUT_CXX14_CONSTEXPR sprout::sub_array > +build_brainfuck() { + sprout::array bin{{}}; + auto out = sprout::begin(bin); + auto n = ::build<::loop_limit>(sprout::begin(::source), sprout::end(::source), out); + return sprout::sub_copy(bin, 0, n); +} + +int main(int argc, char* argv[]) { + SPROUT_CXX14_CONSTEXPR auto bin = ::build_brainfuck(); + + char const* filename = argc >= 2 ? argv[1] + : "a.exe" + ; + std::ofstream ofs(filename); + if (!ofs) { + std::cout + << "could not open file" << std::endl + ; + return -1; + } + sprout::range::copy(bin, std::ostreambuf_iterator(ofs)); +} diff --git a/example/perceptron/g3.cpp b/example/perceptron/g3.cpp new file mode 100644 index 00000000..3a09013e --- /dev/null +++ b/example/perceptron/g3.cpp @@ -0,0 +1,204 @@ +/*============================================================================= + Copyright (c) 2011-2014 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// perceptron +// +template +class perceptron { +public: + typedef FloatType value_type; +private: + struct worker { + public: + // 入力 + sprout::array xi1; + sprout::array xi2; + sprout::array xi3; + // 出力 + sprout::array o1; + sprout::array o2; + sprout::array o3; + }; +private: + // 誤差 + sprout::array d2; + sprout::array d3; + // 重み + sprout::array w1; + sprout::array w2; +private: + // 順伝播 + template + SPROUT_CXX14_CONSTEXPR void + forward_propagation(ForwardIterator in_first, ForwardIterator in_last, worker& work) const { + // 入力層の順伝播 + sprout::copy(in_first, in_last, sprout::begin(work.xi1)); + work.xi1[In] = 1; + sprout::copy(sprout::begin(work.xi1), sprout::end(work.xi1), sprout::begin(work.o1)); + + // 隠れ層の順伝播 + for (std::size_t i = 0; i != Hid; ++i) { + work.xi2[i] = 0; + for (std::size_t j = 0; j != In + 1; ++j) { + work.xi2[i] += w1[j * Hid + i] * work.o1[j]; + } + work.o2[i] = sprout::math::sigmoid(work.xi2[i]); + } + work.o2[Hid] = 1; + + // 出力層の順伝播 + for (std::size_t i = 0; i != Hid; ++i) { + work.xi3[i] = 0; + for (std::size_t j = 0; j != In + 1; ++j) { + work.xi3[i] += w2[j * Out + i] * work.o2[j]; + } + work.o3[i] = work.xi3[i]; + } + } +public: + template + explicit SPROUT_CXX14_CONSTEXPR perceptron(RandomNumberGenerator& rng) + : d2{{}}, d3{{}} + , w1(sprout::random::generate_array<(In + 1) * Hid>(rng, sprout::random::uniform_01())) + , w2(sprout::random::generate_array<(Hid + 1) * Out>(rng, sprout::random::uniform_01())) + {} + + // ニューラルネットの訓練 + // [in_first, in_last) : 訓練データ (N*In 個) + // [t_first, t_last) : 教師データ (N 個) + template + SPROUT_CXX14_CONSTEXPR void + train( + ForwardIterator1 in_first, ForwardIterator1 in_last, + ForwardIterator2 t_first, ForwardIterator2 t_last, + std::size_t repeat = 1000, value_type eta = value_type(0.1) + ) + { + SPROUT_ASSERT(sprout::distance(in_first, in_last) % In == 0); + SPROUT_ASSERT(sprout::distance(in_first, in_last) / In == sprout::distance(t_first, t_last)); + + worker work{}; + for (std::size_t times = 0; times != repeat; ++times) { + ForwardIterator1 in_it = in_first; + ForwardIterator2 t_it = t_first; + for (; in_it != in_last; sprout::advance(in_it, In), ++t_it) { + // 順伝播 + forward_propagation(in_it, sprout::next(in_it, In), work); + + // 出力層の誤差計算 + for (std::size_t i = 0; i != Out; ++i) { + d3[i] = *t_it == i ? work.o3[i] - 1 + : work.o3[i] + ; + } + + // 出力層の重み更新 + for (std::size_t i = 0; i != Hid + 1; ++i) { + for (std::size_t j = 0; j != Out; ++j) { + w2[i * Out + j] -= eta * d3[j] * work.o2[i]; + } + } + + // 隠れ層の誤差計算 + for (std::size_t i = 0; i != Hid + 1; ++i) { + d2[i] = 0; + for (std::size_t j = 0; j != Out; ++j) { + d2[i] += w2[i * Out + j] * d3[j]; + } + d2[i] *= sprout::math::d_sigmoid(work.xi2[i]); + } + + // 隠れ層の重み更新 + for (std::size_t i = 0; i != In + 1; ++i) { + for (std::size_t j = 0; j != Hid; ++j) { + w1[i * Hid + j] -= eta * d2[j] * work.o1[i]; + } + } + } + } + } + + // 与えられたデータに対して最も可能性の高いクラスを返す + template + SPROUT_CXX14_CONSTEXPR std::size_t + predict(ForwardIterator in_first, ForwardIterator in_last) const { + SPROUT_ASSERT(sprout::distance(in_first, in_last) == In); + + worker work{}; + + // 順伝播による予測 + forward_propagation(in_first, in_last, work); + + // 出力が最大になるクラスを判定 + return sprout::distance( + sprout::begin(work.o3), + sprout::max_element(sprout::begin(work.o3), sprout::end(work.o3)) + ); + } +}; + +#include +#include +#include +#include +#include +#include + +// 訓練データ +SPROUT_CONSTEXPR auto train_data = sprout::make_array( +# include "g3_train.csv" + ); +// 教師データ +SPROUT_CONSTEXPR auto teach_data = sprout::make_array( +# include "g3_teach.csv" + ); + +SPROUT_STATIC_ASSERT(train_data.size() % 2 == 0); +SPROUT_STATIC_ASSERT(train_data.size() / 2 == teach_data.size()); + +// 訓練済みパーセプトロンを生成 +template +SPROUT_CXX14_CONSTEXPR ::perceptron +make_trained_perceptron() { + // 乱数生成器 + sprout::random::default_random_engine rng(SPROUT_UNIQUE_SEED); + + // パーセプトロン + ::perceptron per(rng); + + // 訓練 + per.train( + train_data.begin(), train_data.end(), + teach_data.begin(), teach_data.end(), + 500, 0.1 + ); + + return per; +} + +int main() { + // パーセプトロンを生成(入力2 隠れ3 出力3) + SPROUT_CXX14_CONSTEXPR auto per = ::make_trained_perceptron(); + + // 結果の表示 + for (auto it = train_data.begin(), last = train_data.end(); it != last; it += 2) { + std::cout << per.predict(it, it + 2) << std::endl; + } +} diff --git a/example/perceptron/g3_teach.csv b/example/perceptron/g3_teach.csv new file mode 100644 index 00000000..97d7eb6b --- /dev/null +++ b/example/perceptron/g3_teach.csv @@ -0,0 +1,150 @@ +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2 \ No newline at end of file diff --git a/example/perceptron/g3_train.csv b/example/perceptron/g3_train.csv new file mode 100644 index 00000000..66b9464c --- /dev/null +++ b/example/perceptron/g3_train.csv @@ -0,0 +1,150 @@ +2.838248351,-0.057127115, +2.84962986,0.30984388, +3.069875981,0.069165603, +3.033612564,0.237406102, +3.162983688,0.334387888, +3.163831849,0.487806933, +2.997986085,0.061074061, +2.799347441,0.521430032, +3.137156052,0.266393153, +2.870857355,0.267030982, +3.43934308,0.170662698, +3.035552198,0.251317543, +2.886143741,0.125075012, +3.221207099,0.030493356, +3.050238248,0.007279557, +2.733967037,0.235668448, +3.153513285,-0.010778431, +3.311231402,0.343325475, +3.298245949,0.065857414, +2.848633328,-0.004875479, +3.070831457,0.211490982, +3.082296334,0.31440897, +2.926651655,-0.240105616, +2.978054772,0.031004937, +2.35804167,0.239646483, +2.645048857,0.159202643, +2.932230736,0.104463435, +3.097376157,0.150507296, +2.803701193,0.042427284, +2.953016638,0.28536828, +3.238065532,0.346081055, +3.055363223,0.445131721, +2.995237434,0.507696093, +2.804479208,0.245421171, +3.012620496,0.384000638, +2.693411745,0.312330244, +3.102647408,0.343171956, +2.896095389,0.036131501, +2.718440992,-0.01150165, +3.170644375,-0.048096883, +3.011452172,0.034237664, +2.872141309,0.07956016, +2.865096742,0.008559658, +3.279540305,0.302372444, +2.860098477,0.218127155, +3.269317565,-0.005452377, +2.761144719,0.673127168, +2.902469266,0.361832898, +3.11297363,0.50154383, +3.025469568,0.399359182, +1.840419314,1.905105063, +1.813240148,1.813839986, +2.123039813,2.132571185, +1.946192802,1.773046885, +1.969172236,1.805946832, +2.258526017,2.000929535, +1.864577066,2.144995459, +1.911976195,1.980181472, +1.990154583,1.919792502, +1.769958598,2.105082362, +2.137578551,1.944983188, +2.00439482,2.072477229, +1.927718762,1.694463892, +2.207399026,1.851368634, +2.495855335,1.78918729, +2.381107166,2.040305134, +2.05695779,2.458901875, +1.782594688,2.133780789, +1.731552089,2.188212826, +2.157206504,2.249346956, +1.771550549,2.388096625, +1.596862739,2.285617904, +2.116253295,2.043142148, +2.051844958,2.033143301, +1.931137989,2.426396361, +1.987232105,2.141510946, +2.265269874,2.150853439, +2.02603174,2.015376408, +1.95851869,2.243280964, +1.982323697,1.705817048, +1.860646929,2.221006838, +1.850979072,2.557549512, +2.245893751,1.851633418, +2.225460386,1.968984437, +1.817314806,2.306871098, +2.28503916,2.17214804, +1.974994597,1.313041694, +2.031987688,2.022965729, +1.953448998,2.261221941, +2.167787963,1.950768156, +2.325040244,1.533073263, +2.058211845,2.0741863, +2.047485215,2.098219462, +2.228436076,1.920446541, +2.328240588,2.151820146, +2.183441475,2.292478916, +2.190968871,1.760135247, +1.716478165,2.078620922, +1.878852022,2.15075819, +2.085908678,1.96855502, +3.798041143,2.925502959, +3.835899929,3.004531872, +4.226026357,3.327911034, +3.63906142,2.764149093, +3.976732793,2.765971538, +3.735533807,3.211145512, +3.922743188,2.908463331, +3.959548749,2.92371863, +4.220358369,3.028638464, +4.101855229,2.860451817, +3.818023487,2.821524824, +3.944688596,3.251039443, +4.139128323,3.071444196, +4.235165326,3.005161748, +4.248626372,3.156115907, +4.286060111,2.952368701, +3.974827507,2.924985851, +4.140698521,3.042471222, +4.31503215,2.912715016, +4.41718743,3.064667839, +3.894120786,2.925224863, +3.953199682,3.348500249, +4.003736459,3.208318835, +3.872457887,2.698607706, +3.889675701,2.977512411, +3.974258739,3.099134752, +3.794940485,3.033699013, +4.020409067,2.784229901, +3.851699136,2.972769818, +4.036060943,3.066876325, +3.590866735,3.062219821, +4.000802489,3.041278742, +4.254308353,2.947953876, +4.126845488,2.932815351, +3.807568611,3.145490402, +3.986677755,3.378673859, +3.684653059,2.911221769, +4.259008498,3.374089548, +3.964802614,3.072807287, +4.182124157,2.950380575, +3.948426268,3.099264552, +4.053742816,3.195652528, +4.340603893,3.098341999, +3.67327559,2.94969907, +4.043519751,3.311304107, +3.97872525,3.166533465, +4.19023214,2.962725503, +3.717902917,2.75762358, +3.947763326,3.160248033, +4.191797555,3.162533112 \ No newline at end of file diff --git a/sprout/math/detail/float_compute.hpp b/sprout/math/detail/float_compute.hpp index 7d884ea6..913a089d 100644 --- a/sprout/math/detail/float_compute.hpp +++ b/sprout/math/detail/float_compute.hpp @@ -18,6 +18,12 @@ namespace sprout { struct float_compute : public sprout::float_promote {}; + + template + inline SPROUT_CONSTEXPR typename sprout::math::detail::float_compute::type + as_float_compute(FloatType const& x) { + return static_cast::type>(x); + } } // namespace detail } // namespace math } // namespace sprout diff --git a/sprout/math/functions.hpp b/sprout/math/functions.hpp index 10d80a8e..254f4070 100644 --- a/sprout/math/functions.hpp +++ b/sprout/math/functions.hpp @@ -15,5 +15,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_MATH_FUNCTIONS_HPP diff --git a/sprout/math/sigmoid.hpp b/sprout/math/sigmoid.hpp new file mode 100644 index 00000000..a46c17ea --- /dev/null +++ b/sprout/math/sigmoid.hpp @@ -0,0 +1,203 @@ +/*============================================================================= + Copyright (c) 2011-2014 Bolero MURAKAMI + https://github.com/bolero-MURAKAMI/Sprout + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#ifndef SPROUT_MATH_SIGMOID_HPP +#define SPROUT_MATH_SIGMOID_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace math { + // + // sigmoid + // + namespace detail { + template + inline SPROUT_CONSTEXPR T + sigmoid_impl(T x){ + return 1 / (1 + sprout::math::exp(-x)); + } + template + inline SPROUT_CONSTEXPR T + sigmoid_impl(T x, T a){ + return sprout::math::detail::sigmoid_impl(a * x); + } + } // namespace detail + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + sigmoid(FloatType x){ + return sprout::math::detail::sigmoid_impl(sprout::math::detail::as_float_compute(x)); + } + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + sigmoid(FloatType x, FloatType a){ + return sprout::math::detail::sigmoid_impl(sprout::math::detail::as_float_compute(x), sprout::math::detail::as_float_compute(a)); + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + sigmoid(IntType x) { + return sprout::math::sigmoid(static_cast(x)); + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + sigmoid(ArithmeticType1 x, ArithmeticType2 a) { + typedef typename sprout::float_promote::type type; + return sprout::math::sigmoid(static_cast(x), static_cast(a)); + } + + // + // d_sigmoid + // + namespace detail { + template + inline SPROUT_CONSTEXPR T + d_sigmoid_impl_1(T s){ + return s * (1 - s); + } + template + inline SPROUT_CONSTEXPR T + d_sigmoid_impl_1(T s, T a){ + return a * s * (1 - s); + } + template + inline SPROUT_CONSTEXPR T + d_sigmoid_impl(T x){ + return sprout::math::detail::d_sigmoid_impl_1(sprout::math::sigmoid(x)); + } + template + inline SPROUT_CONSTEXPR T + d_sigmoid_impl(T x, T a){ + return sprout::math::detail::d_sigmoid_impl_1(sprout::math::sigmoid(x, a), a); + } + } // namespace detail + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + d_sigmoid(FloatType x){ + return sprout::math::detail::d_sigmoid_impl(sprout::math::detail::as_float_compute(x)); + } + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + d_sigmoid(FloatType x, FloatType a){ + return sprout::math::detail::d_sigmoid_impl(sprout::math::detail::as_float_compute(x), sprout::math::detail::as_float_compute(a)); + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + d_sigmoid(IntType x) { + return sprout::math::d_sigmoid(static_cast(x)); + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + d_sigmoid(ArithmeticType1 x, ArithmeticType2 a) { + typedef typename sprout::float_promote::type type; + return sprout::math::d_sigmoid(static_cast(x), static_cast(a)); + } + + // + // d2_sigmoid + // + namespace detail { + template + inline SPROUT_CONSTEXPR T + d2_sigmoid_impl_1(T s){ + return s * (1 - s) * (1 - 2 * s); + } + template + inline SPROUT_CONSTEXPR T + d2_sigmoid_impl_1(T s, T a){ + return a * a * s * (1 - s) * (1 - 2 * s); + } + template + inline SPROUT_CONSTEXPR T + d2_sigmoid_impl(T x){ + return sprout::math::detail::d2_sigmoid_impl_1(sprout::math::sigmoid(x)); + } + template + inline SPROUT_CONSTEXPR T + d2_sigmoid_impl(T x, T a){ + return sprout::math::detail::d2_sigmoid_impl_1(sprout::math::sigmoid(x, a), a); + } + } // namespace detail + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + d2_sigmoid(FloatType x){ + return sprout::math::detail::d2_sigmoid_impl(sprout::math::detail::as_float_compute(x)); + } + template< + typename FloatType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR FloatType + d2_sigmoid(FloatType x, FloatType a){ + return sprout::math::detail::d2_sigmoid_impl(sprout::math::detail::as_float_compute(x), sprout::math::detail::as_float_compute(a)); + } + template< + typename IntType, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR double + d2_sigmoid(IntType x) { + return sprout::math::d2_sigmoid(static_cast(x)); + } + template< + typename ArithmeticType1, + typename ArithmeticType2, + typename sprout::enabler_if< + std::is_arithmetic::value && std::is_arithmetic::value + >::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout::float_promote::type + d2_sigmoid(ArithmeticType1 x, ArithmeticType2 a) { + typedef typename sprout::float_promote::type type; + return sprout::math::d2_sigmoid(static_cast(x), static_cast(a)); + } + } // namespace math + + using sprout::math::sigmoid; + using sprout::math::d_sigmoid; + using sprout::math::d2_sigmoid; +} // namespace sprout + +#endif // #ifndef SPROUT_MATH_SIGMOID_HPP diff --git a/sprout/random/generate_array.hpp b/sprout/random/generate_array.hpp index 8118d9b1..0c87a627 100644 --- a/sprout/random/generate_array.hpp +++ b/sprout/random/generate_array.hpp @@ -8,9 +8,11 @@ #ifndef SPROUT_RANDOM_GENERATE_ARRAY_HPP #define SPROUT_RANDOM_GENERATE_ARRAY_HPP +#include #include #include #include +#include #include #include #include @@ -29,6 +31,15 @@ namespace sprout { } return result; } + template + inline SPROUT_CXX14_CONSTEXPR sprout::array::type::result_type, N> + generate_array(RandomNumberGenerator& rng, Distribution&& dist) { + sprout::array::type::result_type, N> result{{}}; + for (std::size_t i = 0; i != N; ++i) { + result[i] = SPROUT_FORWARD(Distribution, dist)(rng); + } + return result; + } namespace detail { template diff --git a/tools/testspr/test.sh b/tools/testspr/test.sh index 9884c997..2dedacb5 100755 --- a/tools/testspr/test.sh +++ b/tools/testspr/test.sh @@ -32,30 +32,56 @@ test_cpp=$(cd $(dirname $0); pwd)/test.cpp test_py=$(cd $(dirname $0); pwd)/test.py get_std_option() { - if [ "${3}" = "c++1y" ]; then + vn=0 + if [ "${2}" = "." ]; then if [ "${1}" = "gcc" ]; then - if [ "${2}" = "." ]; then - echo -n "-std=c++1y" - elif [ "${2//.}" -lt "480" ]; then + read -ra current_version_array <<< `g++ --version` + vn=${current_version_array[2]//.} + elif [ "${1}" = "clang" ]; then + read -ra current_version_array <<< `clang++ --version` + vn=${current_version_array[2]//.} + fi + else + vn=${2//.} + fi + if [ "${3}" = "c++17" -o "${3}" = "c++1z" ]; then + if [ "${1}" = "gcc" ]; then + if [ "${vn}" -lt "480" ]; then echo -n "-std=c++11" else echo -n "-std=c++1y" fi elif [ "${1}" = "clang" ]; then - if [ "${2}" = "." ]; then + if [ "${vn}" -lt "32" ]; then + echo -n "-std=c++11" + elif [ "${vn}" -lt "350" ]; then echo -n "-std=c++1y" - elif [ "${2//.}" -lt "32" ]; then + else + echo -n "-std=c++1z" + fi + fi + elif [ "${3}" = "c++14" -o "${3}" = "c++1y" ]; then + if [ "${1}" = "gcc" ]; then + if [ "${vn}" -lt "480" ]; then echo -n "-std=c++11" else echo -n "-std=c++1y" fi + elif [ "${1}" = "clang" ]; then + if [ "${vn}" -lt "32" ]; then + echo -n "-std=c++11" + elif [ "${vn}" -lt "350" ]; then + echo -n "-std=c++1y" + else + echo -n "-std=c++14" + fi fi else echo -n "-std=c++11" fi } -args=`getopt -o S:g:c:O:C:V:D:I:P:f -l stagedir:,gcc-version:,clang-version:,gcc-root:,clang-root:,std:,option:,compiler-option:,version-option:,define:,include:,max-procs:,force,help -- "$@"` +args=`getopt -o S:s:g:c:O:C:V:D:I:P:f -l stagedir:,source:,gcc-version:,clang-version:,gcc-root:,clang-root:,std:,option:,compiler-option:,version-option:,define:,include:,max-procs:,force,help -- "$@"` if [ "$?" -ne 0 ]; then echo >&2 "error: options parse error. See 'test.sh --help'" exit 1 @@ -64,6 +90,7 @@ eval set -- ${args} while [ -n "$1" ]; do case $1 in -S|--stagedir) stagedir=$2; shift 2;; + -s|--source) test_cpp=$2; shift 2;; -g|--gcc-version) gcc_version="$2"; shift 2;; -c|--clang-version) clang_version="$2"; shift 2;; --gcc-root) gcc_root="$2"; shift 2;; @@ -88,6 +115,9 @@ if [ ${use_help} -ne 0 ]; then echo " -S, --stagedir= Output files here." echo " Default; 'testspr'" echo "" + echo " -s, --source= C++ source file." + echo " Default; './test.cpp'" + echo "" echo " -g, --gcc-version= Indicates gcc version list (space separated)." echo " If '.', version that is installed on the system." echo " Default; '.'" @@ -115,7 +145,7 @@ if [ ${use_help} -ne 0 ]; then echo "" echo " -D, --define= Define macro for preprocessor." echo "" - echo " -I, --include= Add system include path." + echo " -I, --include= Add system include path." echo "" echo " -P, --max-procs= The maximum number of process use." echo " If other than null, processing in parallel mode." @@ -129,6 +159,7 @@ fi echo "settings:" echo " stagedir = '${stagedir}'" +echo " source = '${test_cpp}'" echo " gcc-version = (${gcc_version})" echo " clang-version = (${clang_version})" echo " gcc-root = '${gcc_root}'"