Fix linux/mac support.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of SourcePawn.
7 * SourcePawn is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * SourcePawn. If not, see http://www.gnu.org/licenses/.
20 #define WIN32_LEAN_AND_MEAN
29 ToProtBits(OS::Protection prot)
32 case OS::Prot_ReadWrite:
33 return PAGE_READWRITE;
34 case OS::Prot_ReadWriteExecute:
35 return PAGE_EXECUTE_READWRITE;
37 assert(prot == OS::Prot_ReadExecute);
38 return PAGE_EXECUTE_READ;
43 OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
45 DWORD prot = ToProtBits(prot_);
46 DWORD type = MEM_RESERVE;
47 if (mode == Map_Commit)
50 return (Address)VirtualAlloc(NULL, amount, type, prot);
54 OS::CommitMemory(Address address, size_t amount, Protection prot_)
56 DWORD prot = ToProtBits(prot_);
57 return !!VirtualAlloc(address, amount, MEM_COMMIT, prot);
61 OS::UnmapMemory(Address address, size_t size)
63 VirtualFree(address, 0, MEM_RELEASE);
67 MapMemoryAt(Address address, size_t amount, OS::MapMode mode, OS::Protection prot_)
69 DWORD bits = ToProtBits(prot_);
70 DWORD flags = MEM_RESERVE;
71 if (mode == OS::Map_Commit)
74 return (Address)VirtualAlloc((LPVOID)address, amount, flags, bits);
78 OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
80 Address addr = MapMemory(amount, mode, OS::Prot_ReadWrite);
82 return AlignableMapping(NULL, alignment, 0);
84 if (!IsAligned(addr, alignment)) {
85 UnmapMemory(addr, amount);
87 // Try to grab the next available aligned address.
88 addr = AlignedBase(addr, alignment);
89 addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
91 // Try to over-allocate to get the right region. This can race
92 // with other threads; we expect this to be rare. If this turns
93 // out to be a problem, the API is set up such that we can just
94 // return two pointers: the base, and the aligned address into
95 // the over-allocated region.
96 addr = MapMemory(amount + alignment, mode, OS::Prot_ReadWrite);
98 return AlignableMapping(NULL, alignment, 0);
99 UnmapMemory(addr, amount + alignment);
100 addr = AlignedBase(addr, alignment);
101 addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
105 return AlignableMapping(addr, alignment, amount);
109 OS::UnmapAlignedMemory(Address address, size_t size)
111 OS::UnmapMemory(address, size);
115 OS::GetAbsolutePath(const char *path, AutoFree<char> &chars)
118 DWORD result = GetFullPathName(path, sizeof(try1), try1, NULL);
122 // +1 because if result < MAX_PATH, it doesn't include the null terminator.
123 chars = (char *)calloc(result + 1, sizeof(char));
127 if (result <= MAX_PATH) {
128 strcpy(*chars, try1);
132 // We should get the same output on the next try.
133 return GetFullPathName(path, result, *chars, NULL) == result - 1;
137 OS::SplitPath(const char *path, AutoFree<char> &base, AutoFree<char> &name)
139 size_t len = strlen(path);
141 // Skip trailing slashes.
142 while (len > 1 && (path[len - 1] == '/' || path[len - 1] == '\\'))
145 for (size_t i = len - 1; i < len; i--) {
146 if (path[i] == '\\' || path[i] == '/') {
147 name = (char *)calloc(len - i, sizeof(char));
151 strcpy(*name, &path[i + 1]);
153 base = (char *)calloc(i + 1, sizeof(char));
157 memcpy(*base, path, i);
163 // The path should have been absolute, which contains at least one separator.
174 OS::InspectPath(const char *path)
177 int result = _stat(path, &s);
179 return OS::Path_Invalid;
181 if (s.st_mode & _S_IFDIR)
182 return OS::Path_Folder;
183 if (s.st_mode & _S_IFREG)
184 return OS::Path_File;
186 return OS::Path_Invalid;