1.1 --- a/src/Packages.cpp Mon Jun 10 00:46:29 2013 +0100
1.2 +++ b/src/Packages.cpp Mon Jun 10 01:04:43 2013 +0100
1.3 @@ -1,226 +1,226 @@
1.4 -/*
1.5 - * Copyright (C) 2012 David Anderson
1.6 - *
1.7 - * This file is part of SourcePawn.
1.8 - *
1.9 - * SourcePawn is free software: you can redistribute it and/or modify it under
1.10 - * the terms of the GNU General Public License as published by the Free
1.11 - * Software Foundation, either version 3 of the License, or (at your option)
1.12 - * any later version.
1.13 - *
1.14 - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.15 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.16 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.17 - *
1.18 - * You should have received a copy of the GNU General Public License along with
1.19 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.20 - */
1.21 -#include <string.h>
1.22 -#include "Zone.h"
1.23 -#include "Heap.h"
1.24 -#include "Strings.h"
1.25 -#include "Modules.h"
1.26 -#include "Packages.h"
1.27 -#include "FileSystem.h"
1.28 -#include "List.h"
1.29 -#include "Heap-inl.h"
1.30 -#include "Handles-inl.h"
1.31 -
1.32 -using namespace ke;
1.33 -
1.34 -Package *
1.35 -Package::NewNormalized(Zone *zone, Handle<Package> parent, Handle<String> path, Handle<String> name, unsigned flags)
1.36 -{
1.37 - Local<Package> package(zone, Package::cast(zone->allocate(MapKind_Package, sizeof(Package), Heap::Tenure_Old)));
1.38 - if (!package)
1.39 - return NULL;
1.40 -
1.41 - // :TODO: assert path, name are atoms.
1.42 -
1.43 - package->flags_ = flags;
1.44 - package->name_ = name;
1.45 - package->parent_ = parent;
1.46 - package->path_ = path;
1.47 - package->nativeIdentity_ = parent ? parent->getNativeIdentity() : NULL;
1.48 -
1.49 - return package;
1.50 -}
1.51 -
1.52 -Package *
1.53 -Package::New(Zone *zone, Handle<Package> parent, const char *path, Handle<String> name, unsigned flags)
1.54 -{
1.55 - Local<String> strpath(zone, zone->makeSymbol(path));
1.56 - if (!strpath)
1.57 - return NULL;
1.58 -
1.59 - return Package::NewNormalized(zone, parent, strpath, name, flags);
1.60 -}
1.61 -
1.62 -bool
1.63 -Package::add(Zone *zone, Handle<Importable> obj)
1.64 -{
1.65 - Local<Package> pkg(zone, this);
1.66 -
1.67 - assert(obj->parent() == pkg);
1.68 -
1.69 - if (!pkg->contents_) {
1.70 - pkg->contents_ = List<Importable>::New(zone);
1.71 - if (!pkg->contents_)
1.72 - return false;
1.73 - }
1.74 -
1.75 -#ifndef NDEBUG
1.76 - // Assert no duplicate names.
1.77 - for (unsigned i = 0; i < pkg->contents_->length(); i++)
1.78 - assert(pkg->contents_->at(i)->name() != obj->name());
1.79 -#endif
1.80 -
1.81 - if (!pkg->contents_->append(zone, obj))
1.82 - return false;
1.83 -
1.84 - return true;
1.85 -}
1.86 -
1.87 -Importable *
1.88 -Package::import(Handle<String> name)
1.89 -{
1.90 - if (!contents_)
1.91 - return NULL;
1.92 -
1.93 - for (unsigned i = 0; i < contents_->length(); i++) {
1.94 - Importable *obj = contents_->at(i);
1.95 - if (obj->isPackage() && Package::cast(obj)->name() == name)
1.96 - return obj;
1.97 - if (obj->isModule() && Module::cast(obj)->name() == name)
1.98 - return obj;
1.99 - }
1.100 -
1.101 - return NULL;
1.102 -}
1.103 -
1.104 -PackageCache::PackageCache(Zone *zone)
1.105 - : zone_(zone)
1.106 -{
1.107 -}
1.108 -
1.109 -bool
1.110 -PackageCache::initialize()
1.111 -{
1.112 - return true;
1.113 -}
1.114 -
1.115 -void
1.116 -PackageCache::accept(VirtualObjectVisitor *visitor)
1.117 -{
1.118 - for (size_t i = 0; i < roots_.length(); i++)
1.119 - visitor->visit(roots_[i].address());
1.120 -}
1.121 -
1.122 -bool
1.123 -PackageCache::checkfs(Handle<Package> package, PathComponent *path, Importable **out)
1.124 -{
1.125 - AutoFree<char> left(strdup(package->path()->chars()));
1.126 - AutoFree<char> right(strdup(path->name->chars()));
1.127 - AutoFree<char> result;
1.128 -
1.129 - if (!JoinPaths(zone_, result, *left, *right))
1.130 - return false;
1.131 -
1.132 - OS::PathType type = OS::InspectPath(*result);
1.133 - if (type == OS::Path_Folder) {
1.134 - // If there is a folder matching this path, create a new subpackage,
1.135 - // and then either return it (if this is the last link), or keep
1.136 - // trying to import the rest of the path.
1.137 - Local<String> strpath(zone_, zone_->makeSymbol(*result));
1.138 - Local<Package> subpackage(zone_, Package::NewNormalized(zone_, package, strpath, path->name, Package::Normal));
1.139 - if (!subpackage)
1.140 - return false;
1.141 - if (!path->next) {
1.142 - *out = subpackage;
1.143 - return true;
1.144 - }
1.145 - return import(subpackage, path->next, out);
1.146 - }
1.147 -
1.148 - // Otherwise, look for a file ending in ".sp".
1.149 - AutoFree<char> filepath((char *)zone_->malloc(strlen(*result) + strlen(".sp") + 1));
1.150 - if (!*filepath)
1.151 - return false;
1.152 -
1.153 - strcpy(*filepath, *result);
1.154 - strcat(*filepath, ".sp");
1.155 -
1.156 - type = OS::InspectPath(*filepath);
1.157 - if (type != OS::Path_File)
1.158 - return true;
1.159 -
1.160 - // Create a new, empty module.
1.161 - Local<String> strpath(zone_, zone_->makeSymbol(*filepath));
1.162 - if (!strpath)
1.163 - return false;
1.164 -
1.165 - Local<Module> module(zone_, Module::New(zone_, package, strpath, path->name));
1.166 - if (!module || !package->add(zone_, module))
1.167 - return false;
1.168 -
1.169 - *out = module;
1.170 - return true;
1.171 -}
1.172 -
1.173 -bool
1.174 -PackageCache::import(Handle<Package> package, PathComponent *path, Importable **out)
1.175 -{
1.176 - // If the package is jailed, none of its imports are visible.
1.177 - if (package->jailed())
1.178 - return true;
1.179 -
1.180 - Local<Importable> obj(zone_, package->import(path->name));
1.181 - if (!obj) {
1.182 - // We couldn't find anything. Try the file system.
1.183 - if (!checkfs(package, path, out))
1.184 - return false;
1.185 -
1.186 - // checkfs will keep trying to import, so if it fails, we just
1.187 - // propagate up.
1.188 - return true;
1.189 - }
1.190 -
1.191 - // If we found an existing module, or the path has no next link, then
1.192 - // we can't go any further.
1.193 - if (obj->is(MapKind_Module) || !path->next) {
1.194 - *out = obj;
1.195 - return true;
1.196 - }
1.197 -
1.198 - Local<Package> subpackage(zone_, Package::cast(obj));
1.199 - return import(subpackage, path->next, out);
1.200 -}
1.201 -
1.202 -bool
1.203 -PackageCache::findOrAdd(Handle<Package> package, PathComponent *path, Importable **out)
1.204 -{
1.205 - // Local rooters should have initialized this, but whatever.
1.206 - assert(*out == NULL);
1.207 -
1.208 - // Try to import locally first.
1.209 - if (!import(package, path, out))
1.210 - return false;
1.211 - if (*out)
1.212 - return true;
1.213 -
1.214 - // Otherwise, search system roots.
1.215 - Local<Package> root(zone_);
1.216 - for (size_t i = 0; i < roots_.length(); i++) {
1.217 - root = roots_[i];
1.218 - if (!import(root, path, out))
1.219 - return false;
1.220 - if (*out)
1.221 - return true;
1.222 - }
1.223 -
1.224 - return true;
1.225 -}
1.226 -
1.227 -PackageCache::~PackageCache()
1.228 -{
1.229 -}
1.230 +/*
1.231 + * Copyright (C) 2012 David Anderson
1.232 + *
1.233 + * This file is part of SourcePawn.
1.234 + *
1.235 + * SourcePawn is free software: you can redistribute it and/or modify it under
1.236 + * the terms of the GNU General Public License as published by the Free
1.237 + * Software Foundation, either version 3 of the License, or (at your option)
1.238 + * any later version.
1.239 + *
1.240 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.241 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.242 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.243 + *
1.244 + * You should have received a copy of the GNU General Public License along with
1.245 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.246 + */
1.247 +#include <string.h>
1.248 +#include "Zone.h"
1.249 +#include "Heap.h"
1.250 +#include "Strings.h"
1.251 +#include "Modules.h"
1.252 +#include "Packages.h"
1.253 +#include "FileSystem.h"
1.254 +#include "List.h"
1.255 +#include "Heap-inl.h"
1.256 +#include "Handles-inl.h"
1.257 +
1.258 +using namespace ke;
1.259 +
1.260 +Package *
1.261 +Package::NewNormalized(Zone *zone, Handle<Package> parent, Handle<String> path, Handle<String> name, unsigned flags)
1.262 +{
1.263 + Local<Package> package(zone, Package::cast(zone->allocate(MapKind_Package, sizeof(Package), Heap::Tenure_Old)));
1.264 + if (!package)
1.265 + return NULL;
1.266 +
1.267 + // :TODO: assert path, name are atoms.
1.268 +
1.269 + package->flags_ = flags;
1.270 + package->name_ = name;
1.271 + package->parent_ = parent;
1.272 + package->path_ = path;
1.273 + package->nativeIdentity_ = parent ? parent->getNativeIdentity() : NULL;
1.274 +
1.275 + return package;
1.276 +}
1.277 +
1.278 +Package *
1.279 +Package::New(Zone *zone, Handle<Package> parent, const char *path, Handle<String> name, unsigned flags)
1.280 +{
1.281 + Local<String> strpath(zone, zone->makeSymbol(path));
1.282 + if (!strpath)
1.283 + return NULL;
1.284 +
1.285 + return Package::NewNormalized(zone, parent, strpath, name, flags);
1.286 +}
1.287 +
1.288 +bool
1.289 +Package::add(Zone *zone, Handle<Importable> obj)
1.290 +{
1.291 + Local<Package> pkg(zone, this);
1.292 +
1.293 + assert(obj->parent() == pkg);
1.294 +
1.295 + if (!pkg->contents_) {
1.296 + pkg->contents_ = List<Importable>::New(zone);
1.297 + if (!pkg->contents_)
1.298 + return false;
1.299 + }
1.300 +
1.301 +#ifndef NDEBUG
1.302 + // Assert no duplicate names.
1.303 + for (unsigned i = 0; i < pkg->contents_->length(); i++)
1.304 + assert(pkg->contents_->at(i)->name() != obj->name());
1.305 +#endif
1.306 +
1.307 + if (!pkg->contents_->append(zone, obj))
1.308 + return false;
1.309 +
1.310 + return true;
1.311 +}
1.312 +
1.313 +Importable *
1.314 +Package::import(Handle<String> name)
1.315 +{
1.316 + if (!contents_)
1.317 + return NULL;
1.318 +
1.319 + for (unsigned i = 0; i < contents_->length(); i++) {
1.320 + Importable *obj = contents_->at(i);
1.321 + if (obj->isPackage() && Package::cast(obj)->name() == name)
1.322 + return obj;
1.323 + if (obj->isModule() && Module::cast(obj)->name() == name)
1.324 + return obj;
1.325 + }
1.326 +
1.327 + return NULL;
1.328 +}
1.329 +
1.330 +PackageCache::PackageCache(Zone *zone)
1.331 + : zone_(zone)
1.332 +{
1.333 +}
1.334 +
1.335 +bool
1.336 +PackageCache::initialize()
1.337 +{
1.338 + return true;
1.339 +}
1.340 +
1.341 +void
1.342 +PackageCache::accept(VirtualObjectVisitor *visitor)
1.343 +{
1.344 + for (size_t i = 0; i < roots_.length(); i++)
1.345 + visitor->visit(roots_[i].address());
1.346 +}
1.347 +
1.348 +bool
1.349 +PackageCache::checkfs(Handle<Package> package, PathComponent *path, Importable **out)
1.350 +{
1.351 + AutoFree<char> left(strdup(package->path()->chars()));
1.352 + AutoFree<char> right(strdup(path->name->chars()));
1.353 + AutoFree<char> result;
1.354 +
1.355 + if (!JoinPaths(zone_, result, *left, *right))
1.356 + return false;
1.357 +
1.358 + OS::PathType type = OS::InspectPath(*result);
1.359 + if (type == OS::Path_Folder) {
1.360 + // If there is a folder matching this path, create a new subpackage,
1.361 + // and then either return it (if this is the last link), or keep
1.362 + // trying to import the rest of the path.
1.363 + Local<String> strpath(zone_, zone_->makeSymbol(*result));
1.364 + Local<Package> subpackage(zone_, Package::NewNormalized(zone_, package, strpath, path->name, Package::Normal));
1.365 + if (!subpackage)
1.366 + return false;
1.367 + if (!path->next) {
1.368 + *out = subpackage;
1.369 + return true;
1.370 + }
1.371 + return import(subpackage, path->next, out);
1.372 + }
1.373 +
1.374 + // Otherwise, look for a file ending in ".sp".
1.375 + AutoFree<char> filepath((char *)zone_->malloc(strlen(*result) + strlen(".sp") + 1));
1.376 + if (!*filepath)
1.377 + return false;
1.378 +
1.379 + strcpy(*filepath, *result);
1.380 + strcat(*filepath, ".sp");
1.381 +
1.382 + type = OS::InspectPath(*filepath);
1.383 + if (type != OS::Path_File)
1.384 + return true;
1.385 +
1.386 + // Create a new, empty module.
1.387 + Local<String> strpath(zone_, zone_->makeSymbol(*filepath));
1.388 + if (!strpath)
1.389 + return false;
1.390 +
1.391 + Local<Module> module(zone_, Module::New(zone_, package, strpath, path->name));
1.392 + if (!module || !package->add(zone_, module))
1.393 + return false;
1.394 +
1.395 + *out = module;
1.396 + return true;
1.397 +}
1.398 +
1.399 +bool
1.400 +PackageCache::import(Handle<Package> package, PathComponent *path, Importable **out)
1.401 +{
1.402 + // If the package is jailed, none of its imports are visible.
1.403 + if (package->jailed())
1.404 + return true;
1.405 +
1.406 + Local<Importable> obj(zone_, package->import(path->name));
1.407 + if (!obj) {
1.408 + // We couldn't find anything. Try the file system.
1.409 + if (!checkfs(package, path, out))
1.410 + return false;
1.411 +
1.412 + // checkfs will keep trying to import, so if it fails, we just
1.413 + // propagate up.
1.414 + return true;
1.415 + }
1.416 +
1.417 + // If we found an existing module, or the path has no next link, then
1.418 + // we can't go any further.
1.419 + if (obj->is(MapKind_Module) || !path->next) {
1.420 + *out = obj;
1.421 + return true;
1.422 + }
1.423 +
1.424 + Local<Package> subpackage(zone_, Package::cast(obj));
1.425 + return import(subpackage, path->next, out);
1.426 +}
1.427 +
1.428 +bool
1.429 +PackageCache::findOrAdd(Handle<Package> package, PathComponent *path, Importable **out)
1.430 +{
1.431 + // Local rooters should have initialized this, but whatever.
1.432 + assert(*out == NULL);
1.433 +
1.434 + // Try to import locally first.
1.435 + if (!import(package, path, out))
1.436 + return false;
1.437 + if (*out)
1.438 + return true;
1.439 +
1.440 + // Otherwise, search system roots.
1.441 + Local<Package> root(zone_);
1.442 + for (size_t i = 0; i < roots_.length(); i++) {
1.443 + root = roots_[i];
1.444 + if (!import(root, path, out))
1.445 + return false;
1.446 + if (*out)
1.447 + return true;
1.448 + }
1.449 +
1.450 + return true;
1.451 +}
1.452 +
1.453 +PackageCache::~PackageCache()
1.454 +{
1.455 +}