Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* LogicalPathname.java
*
* Copyright (C) 2004-2005 Peter Graves
* $Id$
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
package org.armedbear.lisp;
import static org.armedbear.lisp.Lisp.*;
import java.util.HashMap;
import java.util.StringTokenizer;
public final class LogicalPathname extends Pathname
{
private static final String LOGICAL_PATHNAME_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-;*.";
private static final HashMap map = new HashMap();
protected LogicalPathname()
{
}
protected LogicalPathname(Pathname p) {
super(p);
}
public LogicalPathname(String host, String rest)
{
final int limit = rest.length();
for (int i = 0; i < limit; i++) {
char c = rest.charAt(i);
if (LOGICAL_PATHNAME_CHARS.indexOf(c) < 0) {
error(new ParseError("The character #\\" + c + " is not valid in a logical pathname."));
return;
}
}
this.host = new SimpleString(host);
// "The device component of a logical pathname is always :UNSPECIFIC;
// no other component of a logical pathname can be :UNSPECIFIC."
device = Keyword.UNSPECIFIC;
int semi = rest.lastIndexOf(';');
if (semi >= 0) {
// Directory.
String d = rest.substring(0, semi + 1);
directory = parseDirectory(d);
rest = rest.substring(semi + 1);
} else {
// "If a relative-directory-marker precedes the directories, the
// directory component parsed is as relative; otherwise, the
// directory component is parsed as absolute."
directory = new Cons(Keyword.ABSOLUTE);
}
int dot = rest.indexOf('.');
if (dot >= 0) {
String n = rest.substring(0, dot);
if (n.equals("*"))
name = Keyword.WILD;
else
name = new SimpleString(n.toUpperCase());
rest = rest.substring(dot + 1);
dot = rest.indexOf('.');
if (dot >= 0) {
String t = rest.substring(0, dot);
if (t.equals("*"))
type = Keyword.WILD;
else
type = new SimpleString(t.toUpperCase());
// What's left is the version.
String v = rest.substring(dot + 1);
if (v.equals("*"))
version = Keyword.WILD;
else if (v.equals("NEWEST") || v.equals("newest"))
version = Keyword.NEWEST;
else
version = PACKAGE_CL.intern("PARSE-INTEGER").execute(new SimpleString(v));
} else {
String t = rest;
if (t.equals("*"))
type = Keyword.WILD;
else
type = new SimpleString(t.toUpperCase());
}
} else {
String n = rest;
if (n.equals("*"))
name = Keyword.WILD;
else if (n.length() > 0)
name = new SimpleString(n.toUpperCase());
}
}
private static final String LOGICAL_PATHNAME_COMPONENT_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-";
public static final SimpleString canonicalizeStringComponent(AbstractString s)
{
final int limit = s.length();
for (int i = 0; i < limit; i++) {
char c = s.charAt(i);
if (LOGICAL_PATHNAME_COMPONENT_CHARS.indexOf(c) < 0) {
error(new ParseError("Invalid character #\\" + c +
" in logical pathname component \"" + s +
'"'));
// Not reached.
return null;
}
}
return new SimpleString(s.getStringValue().toUpperCase());
}
public static Pathname translateLogicalPathname(LogicalPathname pathname)
{
return (Pathname) Symbol.TRANSLATE_LOGICAL_PATHNAME.execute(pathname);
}
private static final LispObject parseDirectory(String s)
{
LispObject result;
if (s.charAt(0) == ';') {
result = new Cons(Keyword.RELATIVE);
s = s.substring(1);
} else
result = new Cons(Keyword.ABSOLUTE);
StringTokenizer st = new StringTokenizer(s, ";");
while (st.hasMoreTokens()) {
String token = st.nextToken();
LispObject obj;
if (token.equals("*"))
obj = Keyword.WILD;
else if (token.equals("**"))
obj = Keyword.WILD_INFERIORS;
else if (token.equals("..")) {
if (result.car() instanceof AbstractString) {
result = result.cdr();
continue;
}
obj= Keyword.UP;
} else
obj = new SimpleString(token.toUpperCase());
result = new Cons(obj, result);
}
return result.nreverse();
}
@Override
public LispObject typeOf()
{
return Symbol.LOGICAL_PATHNAME;
}
@Override
public LispObject classOf()
{
return BuiltInClass.LOGICAL_PATHNAME;
}
@Override
public LispObject typep(LispObject type)
{
if (type == Symbol.LOGICAL_PATHNAME)
return T;
if (type == BuiltInClass.LOGICAL_PATHNAME)
return T;
return super.typep(type);
}
@Override
protected String getDirectoryNamestring()
{
StringBuilder sb = new StringBuilder();
// "If a pathname is converted to a namestring, the symbols NIL and
// :UNSPECIFIC cause the field to be treated as if it were empty. That
// is, both NIL and :UNSPECIFIC cause the component not to appear in
// the namestring." 19.2.2.2.3.1
if (directory != NIL) {
LispObject temp = directory;
LispObject part = temp.car();
if (part == Keyword.ABSOLUTE) {
} else if (part == Keyword.RELATIVE)
sb.append(';');
else
error(new FileError("Unsupported directory component " + part.princToString() + ".",
this));
temp = temp.cdr();
while (temp != NIL) {
part = temp.car();
if (part instanceof AbstractString)
sb.append(part.getStringValue());
else if (part == Keyword.WILD)
sb.append('*');
else if (part == Keyword.WILD_INFERIORS)
sb.append("**");
else if (part == Keyword.UP)
sb.append("..");
else
error(new FileError("Unsupported directory component " + part.princToString() + ".",
this));
sb.append(';');
temp = temp.cdr();
}
}
return sb.toString();
}
@Override
public String printObject()
{
final LispThread thread = LispThread.currentThread();
boolean printReadably = (Symbol.PRINT_READABLY.symbolValue(thread) != NIL);
boolean printEscape = (Symbol.PRINT_ESCAPE.symbolValue(thread) != NIL);
StringBuilder sb = new StringBuilder();
if (printReadably || printEscape)
sb.append("#P\"");
sb.append(host.getStringValue());
sb.append(':');
if (directory != NIL)
sb.append(getDirectoryNamestring());
if (name != NIL) {
if (name == Keyword.WILD)
sb.append('*');
else
sb.append(name.getStringValue());
}
if (type != NIL) {
sb.append('.');
if (type == Keyword.WILD)
sb.append('*');
else
sb.append(type.getStringValue());
}
if (version.integerp()) {
sb.append('.');
int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread));
if (version instanceof Fixnum)
sb.append(Integer.toString(((Fixnum)version).value, base).toUpperCase());
else if (version instanceof Bignum)
sb.append(((Bignum)version).value.toString(base).toUpperCase());
} else if (version == Keyword.WILD) {
sb.append(".*");
} else if (version == Keyword.NEWEST) {
sb.append(".NEWEST");
}
if (printReadably || printEscape)
sb.append('"');
return sb.toString();
}
// ### canonicalize-logical-host host => canonical-host
private static final Primitive CANONICALIZE_LOGICAL_HOST = new canonicalize_logical_host();
private static class canonicalize_logical_host extends Primitive {
canonicalize_logical_host() {
super("canonicalize-logical-host", PACKAGE_SYS, true, "host");
}
@Override
public LispObject execute(LispObject arg)
{
AbstractString s = checkString(arg);
if (s.length() == 0) {
// "The null string, "", is not a valid value for any
// component of a logical pathname." 19.3.2.2
return error(new LispError("Invalid logical host name: \"" +
s.getStringValue() + '"'));
}
return canonicalizeStringComponent(s);
}
}
// ### %make-logical-pathname namestring => logical-pathname
private static final Primitive _MAKE_LOGICAL_PATHNAME = new _make_logical_pathname();
private static class _make_logical_pathname extends Primitive {
_make_logical_pathname() {
super("%make-logical-pathname", PACKAGE_SYS, true, "namestring");
}
@Override
public LispObject execute(LispObject arg)
{
// Check for a logical pathname host.
String s = arg.getStringValue();
String h = getHostString(s);
if (h != null) {
if (h.length() == 0) {
// "The null string, "", is not a valid value for any
// component of a logical pathname." 19.3.2.2
return error(new LispError("Invalid logical host name: \"" +
h + '"'));
}
if (Pathname.LOGICAL_PATHNAME_TRANSLATIONS.get(new SimpleString(h)) != null) {
// A defined logical pathname host.
return new LogicalPathname(h, s.substring(s.indexOf(':') + 1));
}
}
return error(new TypeError("Logical namestring does not specify a host: \"" + s + '"'));
}
}
public long getLastModified() {
Pathname p = translateLogicalPathname(this);
return p.getLastModified();
}
}