From b4e5e5a059a6736f346304b0a03e73946862e161 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sat, 3 Aug 2013 00:33:24 -0400 Subject: [PATCH] new path conversion code --- mpw/mpw.h | 1 + toolbox/CMakeLists.txt | 9 +- toolbox/pathnames.rl | 269 +++++++++++++++++++++++++++++++++++++++++ toolbox/toolbox.cpp | 2 + toolbox/toolbox.h | 4 +- 5 files changed, 282 insertions(+), 3 deletions(-) create mode 100644 toolbox/pathnames.rl diff --git a/mpw/mpw.h b/mpw/mpw.h index 55364cf..2c3d306 100644 --- a/mpw/mpw.h +++ b/mpw/mpw.h @@ -97,6 +97,7 @@ namespace MPW { std::string RootDirPathForFile(const std::string &file); std::string GetEnv(const std::string &); + std::string ExpandVariables(const std::string &s); // should add argc/argv/envp... diff --git a/toolbox/CMakeLists.txt b/toolbox/CMakeLists.txt index ad93762..fb1ca7b 100644 --- a/toolbox/CMakeLists.txt +++ b/toolbox/CMakeLists.txt @@ -17,6 +17,7 @@ set(TOOLBOX_SRC qd.cpp sane.cpp saneparser.cpp + pathnames.cpp utility.cpp ) @@ -27,8 +28,14 @@ add_custom_command( MAIN_DEPENDENCY saneparser.rl ) +add_custom_command( + OUTPUT pathnames.cpp + COMMAND ragel -p -G2 -o pathnames.cpp "${CMAKE_CURRENT_SOURCE_DIR}/pathnames.rl" + MAIN_DEPENDENCY pathnames.rl +) + set_source_files_properties( - saneparser.cpp + saneparser.cpp pathnames.cpp PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable" diff --git a/toolbox/pathnames.rl b/toolbox/pathnames.rl new file mode 100644 index 0000000..25630ae --- /dev/null +++ b/toolbox/pathnames.rl @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2013, Kelvin W Sherlock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include + +#include "toolbox.h" + +#ifndef TESTING +#include +#endif + + +namespace { + + + /* + * To Mac: + * file -> file + * :directory:file -> directory/file + * volume:directory -> /volume/directory + * :: -> ../ + * ::: -> ../../ + * + * + * To Unix: + * file -> file + * directory/file -> :directory:file + * /volume/file -> volume:file + * + */ + + + %%{ + machine mac; + + main := |* + + ':' {2,} { + + // :: = .. + // ::: = ../.. + // etc + unsigned count = te - ts; + + if (ts != begin) + { + rv.push_back('/'); + } + for (unsigned i = 1; i < count; ++i) + { + rv.append("../"); + } + }; + + ':' { + if (ts != begin) + rv.push_back('/'); + }; + + + any { + rv.push_back(*ts); + }; + + *|; + + write data; + }%% + + %%{ + machine unix; + + main := |* + + '/' + { + // collapse multiple /s to a single ':' + if (ts != begin) + { + rv.push_back(':'); + slash = true; + } + }; + + any { + rv.push_back(*ts); + }; + + *|; + + write data; + }%% + +} + +namespace ToolBox +{ + + std::string MacToUnix(std::string path) + { + + // todo -- Dev:Null -> lowercase it? + + #ifndef TESTING + if (path.find_first_of("${") != path.npos) + { + path = MPW::ExpandVariables(path); + } + #endif + + int sep = 0; + bool colon = false; + + for (char c : path) + { + switch (c) + { + case ':': + colon = true; + case '/': + if (!sep) sep = c; + break; + + } + if (colon) break; + } + + // no colon - no problem. + if (!colon) return path; + + + const char *p = path.c_str(); + const char *pe = p + path.length(); + const char *eof = pe; + const char *ts; + const char *te; + + const char *begin = p; + int cs; + int act; + + std::string rv; + + // volume:directory -> /volume + if (sep == ':' && path.front() != ':') + rv.push_back('/'); + + %%{ + machine mac; + + write init; + write exec; + }%% + + + return rv; + } + + + std::string UnixToMac(std::string path) + { + // /volume/directory -> volume:directory + // // -> / + + + bool slash = false; + bool sep = 0; + + for (char c : path) + { + switch(c) + { + case '/': + slash = true; + case ':': + if (!sep) sep = c; + break; + } + if (slash) break; + } + + if (!slash) return path; + + const char *p = path.c_str(); + const char *pe = p + path.length(); + const char *eof = pe; + const char *ts; + const char *te; + + const char *begin = p; + int act; + int cs; + + std::string rv; + + + slash = false; + // path/file -> :path:file + if (path.front() != '/') + { + rv.push_back(':'); + slash = true; + } + %%{ + machine unix; + + write init; + write exec; + }%% + + // special check /dir -> dir: + if (path.front() == '/' && !slash) rv.push_back(':'); + + return rv; + } + + +} + + +#ifdef TESTING + +#include + +int main(int argc, char **argv) +{ + + for (int i = 1; i < argc; ++i) + { + std::string s(argv[i]); + std::string a = ToolBox::MacToUnix(s); + std::string b = ToolBox::UnixToMac(s); + + if (s != a) + printf("ToUnix: %s -> %s\n", s.c_str(), a.c_str()); + + if (s != b) + printf("ToMac: %s -> %s\n", s.c_str(), b.c_str()); + + + } + + return 0; +} + +#endif diff --git a/toolbox/toolbox.cpp b/toolbox/toolbox.cpp index 0a26967..ba19032 100644 --- a/toolbox/toolbox.cpp +++ b/toolbox/toolbox.cpp @@ -558,6 +558,7 @@ namespace ToolBox { * :dir:file -> dir/file * volume:file -> /volume/file */ + #if 0 std::string UnixToMac(const std::string &path) { // ./..., //... etc. @@ -630,4 +631,5 @@ namespace ToolBox { return tmp; } + #endif } \ No newline at end of file diff --git a/toolbox/toolbox.h b/toolbox/toolbox.h index 88f4d7e..97169fe 100644 --- a/toolbox/toolbox.h +++ b/toolbox/toolbox.h @@ -33,8 +33,8 @@ namespace ToolBox bool WritePString(uint32_t address, const std::string &s); - std::string UnixToMac(const std::string &path); - std::string MacToUnix(const std::string &path); + std::string UnixToMac(std::string path); + std::string MacToUnix(std::string path); }