directory -- support for MacOS pathnames.

This commit is contained in:
Kelvin Sherlock 2016-02-09 23:50:33 -05:00
parent acf616845e
commit 3fea71d1e8
3 changed files with 280 additions and 3 deletions

View File

@ -6,7 +6,7 @@ project("mpw-shell")
set (PROJECT_TYPE "CXX")
set (PROJECT_NAME "MPW Shell")
set(CMAKE_CXX_FLAGS "-g -Wall -Wno-unused-variable -Wno-multichar")
set(CMAKE_CXX_FLAGS "-g -Wall -Wno-unused-variable -Wno-multichar -O1")
if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable ")
@ -66,6 +66,7 @@ endmacro()
RAGEL_TARGET(mpw-shell-read mpw-shell-read.rl mpw-shell-read.cpp COMPILE_FLAGS "-p -G2")
RAGEL_TARGET(phase1 phase1.rl phase1.cpp COMPILE_FLAGS "-p -G2")
RAGEL_TARGET(phase2 phase2.rl phase2.cpp COMPILE_FLAGS "-p -G2")
RAGEL_TARGET(pathnames pathnames.rl pathnames.cpp COMPILE_FLAGS "-p -G2")
# need to copy all OUTPUT file to the build dir
add_custom_command(
@ -113,7 +114,8 @@ add_custom_command(
# mpw-shell-execute.cpp mpw-shell-builtins.cpp mpw-shell-read.cpp
add_executable(mpw-shell mpw-shell.cpp mpw-shell-token.cpp mpw-shell-expand.cpp
mpw-shell-parser.cpp value.cpp mpw-shell-quote.cpp
phase1.cpp phase2.cpp phase2-parser.cpp command.cpp environment.cpp builtins.cpp mapped_file.cpp)
phase1.cpp phase2.cpp phase2-parser.cpp command.cpp environment.cpp builtins.cpp mapped_file.cpp
pathnames.cpp)
target_link_libraries(mpw-shell edit)

View File

@ -15,6 +15,12 @@
//MAXPATHLEN
#include <sys/param.h>
namespace ToolBox {
std::string MacToUnix(const std::string path);
std::string UnixToMac(const std::string path);
}
namespace {
/*
@ -46,6 +52,7 @@ namespace {
}
#undef stdin
#undef stdout
#undef stderr
@ -330,7 +337,8 @@ int builtin_directory(Environment &env, const std::vector<std::string> &tokens,
}
// todo -- pathname translation.
int ok = chdir(argv.front().c_str());
std::string path = ToolBox::MacToUnix(argv.front());
int ok = chdir(path.c_str());
if (ok < 0) {
fputs("### Directory - Unable to set current directory.\n", stderr);
perror("chdir: ");

267
pathnames.rl Normal file
View File

@ -0,0 +1,267 @@
/*
* 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 <string>
//#include "toolbox.h"
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.append("./");
else
rv.push_back('/');
*/
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(const std::string path)
{
// todo -- Dev:Null -> lowercase it?
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;
// special case ":" -> "."
if (colon && path.length() == 1) return ".";
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(const 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 <cstdio>
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