mirror of
https://github.com/irmen/prog8.git
synced 2025-04-06 10:38:48 +00:00
support symlinks in paths (triggered by symlinked tmp on mac os)
This commit is contained in:
parent
3e9b4ccc45
commit
f04b97d890
@ -1,8 +1,31 @@
|
||||
package prog8.code
|
||||
|
||||
import java.io.IOException
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.absolute
|
||||
|
||||
|
||||
// the automatically generated module where all string literals are interned to:
|
||||
const val INTERNED_STRINGS_MODULENAME = "prog8_interned_strings"
|
||||
|
||||
// all automatically generated labels everywhere need to have the same label name prefix:
|
||||
const val GENERATED_LABEL_PREFIX = "p8_label_gen_"
|
||||
|
||||
|
||||
/**
|
||||
* Returns the absolute path of the given path,
|
||||
* where links are replaced by the actual directories,
|
||||
* and containing no redundant path elements.
|
||||
* If the path doesn't refer to an existing directory or file on the file system,
|
||||
* it is returned unchanged.
|
||||
*/
|
||||
fun Path.sanitize(): Path {
|
||||
try {
|
||||
return this.toRealPath().normalize()
|
||||
} catch (_: java.nio.file.NoSuchFileException) {
|
||||
return this.absolute().normalize()
|
||||
//throw NoSuchFileException(this.toFile(), null, nx.reason).also { it.initCause(nx) }
|
||||
} catch (iox: IOException) {
|
||||
throw FileSystemException(this.toFile()).also { it.initCause(iox) }
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package prog8.code.core
|
||||
|
||||
import prog8.code.sanitize
|
||||
import prog8.code.source.SourceCode
|
||||
import java.nio.file.InvalidPathException
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.absolute
|
||||
|
||||
data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) {
|
||||
override fun toString(): String = "[$file: line $line col ${startCol+1}-${endCol+1}]"
|
||||
@ -13,7 +13,7 @@ data class Position(val file: String, val line: Int, val startCol: Int, val endC
|
||||
if(SourceCode.isLibraryResource(file))
|
||||
return "$file:$line:$startCol:"
|
||||
return try {
|
||||
val path = Path(file).absolute().normalize().toString()
|
||||
val path = Path(file).sanitize().toString()
|
||||
"file://$path:$line:$startCol:"
|
||||
} catch(_: InvalidPathException) {
|
||||
// this can occur on Windows when the source origin contains "invalid" characters such as ':'
|
||||
|
@ -1,10 +1,10 @@
|
||||
package prog8.code.source
|
||||
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.sanitize
|
||||
import java.nio.file.Path
|
||||
import java.util.TreeMap
|
||||
import java.util.*
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.absolute
|
||||
|
||||
|
||||
// Resource caching "filesystem".
|
||||
@ -22,7 +22,7 @@ object ImportFileSystem {
|
||||
fun expandTilde(path: Path): Path = Path(expandTilde(path.toString()))
|
||||
|
||||
fun getFile(path: Path, isLibrary: Boolean=false): SourceCode {
|
||||
val normalized = path.absolute().normalize()
|
||||
val normalized = path.sanitize()
|
||||
val cached = cache[normalized.toString()]
|
||||
if (cached != null)
|
||||
return cached
|
||||
@ -48,7 +48,7 @@ object ImportFileSystem {
|
||||
val cached = cache[position.file]
|
||||
if(cached != null)
|
||||
return getLine(cached, position.line)
|
||||
val path = Path(position.file).absolute().normalize()
|
||||
val path = Path(position.file).sanitize()
|
||||
val cached2 = cache[path.toString()]
|
||||
if(cached2 != null)
|
||||
return getLine(cached2, position.line)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package prog8.code.source
|
||||
|
||||
import prog8.code.sanitize
|
||||
import java.io.IOException
|
||||
import java.nio.file.Path
|
||||
import java.text.Normalizer
|
||||
@ -59,7 +60,7 @@ sealed class SourceCode {
|
||||
private const val LIBRARYFILEPREFIX = "library:"
|
||||
private const val STRINGSOURCEPREFIX = "string:"
|
||||
val curdir: Path = Path(".").absolute()
|
||||
fun relative(path: Path): Path = curdir.relativize(path.absolute())
|
||||
fun relative(path: Path): Path = curdir.relativize(path.sanitize())
|
||||
fun isRegularFilesystemPath(pathString: String) = !isLibraryResource(pathString) && !isStringResource(pathString)
|
||||
fun isLibraryResource(path: String) = path.startsWith(LIBRARYFILEPREFIX)
|
||||
fun isStringResource(path: String) = path.startsWith(STRINGSOURCEPREFIX)
|
||||
|
@ -75,7 +75,7 @@ class VMTarget: ICompilationTarget, IStringEncoding by Encoder, IMemSizer by Nor
|
||||
if(withExt.isReadable())
|
||||
vm.runProgram(withExt.readText())
|
||||
else
|
||||
throw NoSuchFileException(withExt.toFile(), reason="not a .p8ir file")
|
||||
throw java.nio.file.NoSuchFileException(withExt.name, null, "not a .p8ir file")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,7 @@
|
||||
package prog8.codegen.cpu6502
|
||||
|
||||
import com.github.michaelbull.result.fold
|
||||
import prog8.code.GENERATED_LABEL_PREFIX
|
||||
import prog8.code.IAssemblyProgram
|
||||
import prog8.code.ICodeGeneratorBackend
|
||||
import prog8.code.StNode
|
||||
import prog8.code.StNodeType
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.SymbolTableMaker
|
||||
import prog8.code.*
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.source.ImportFileSystem
|
||||
@ -15,7 +9,6 @@ import prog8.code.source.SourceCode
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.codegen.cpu6502.assignment.*
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.absolute
|
||||
import kotlin.io.path.writeLines
|
||||
|
||||
|
||||
@ -1144,8 +1137,8 @@ $repeatLabel""")
|
||||
val sourcePath = Path(incbin.definingBlock()!!.source.origin)
|
||||
val includedPath = sourcePath.resolveSibling(incbin.file)
|
||||
val pathForAssembler = options.outputDir // #54: 64tass needs the path *relative to the .asm file*
|
||||
.absolute()
|
||||
.relativize(includedPath.absolute())
|
||||
.sanitize()
|
||||
.relativize(includedPath.sanitize())
|
||||
.normalize() // avoid assembler warnings (-Wportable; only some, not all)
|
||||
.toString().replace('\\', '/')
|
||||
out(" .binary \"$pathForAssembler\" $offset $length")
|
||||
|
@ -8,6 +8,7 @@ import prog8.ast.statements.Directive
|
||||
import prog8.ast.statements.DirectiveArg
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.sanitize
|
||||
import prog8.code.source.ImportFileSystem
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.parser.Prog8Parser
|
||||
@ -24,8 +25,8 @@ class ModuleImporter(private val program: Program,
|
||||
sourceDirs: List<String>,
|
||||
libraryDirs: List<String>) {
|
||||
|
||||
private val sourcePaths: List<Path> = sourceDirs.map { Path(it).absolute().normalize() }.toSortedSet().toList()
|
||||
private val libraryPaths: List<Path> = libraryDirs.map { Path(it).absolute().normalize() }.toSortedSet().toList()
|
||||
private val sourcePaths: List<Path> = sourceDirs.map { Path(it).sanitize() }.toSortedSet().toList()
|
||||
private val libraryPaths: List<Path> = libraryDirs.map { Path(it).sanitize() }.toSortedSet().toList()
|
||||
|
||||
fun importMainModule(filePath: Path): Result<Module, NoSuchFileException> {
|
||||
val searchIn = (listOf(Path("").absolute()) + sourcePaths).toSortedSet()
|
||||
@ -141,7 +142,7 @@ class ModuleImporter(private val program: Program,
|
||||
if (importingModule == null) {
|
||||
sourcePaths
|
||||
} else {
|
||||
val pathFromImportingModule = (Path(importingModule.position.file).parent ?: Path("")).absolute().normalize()
|
||||
val pathFromImportingModule = (Path(importingModule.position.file).parent ?: Path("")).sanitize()
|
||||
listOf(pathFromImportingModule) + sourcePaths
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,12 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.sanitize
|
||||
import prog8.code.source.ImportFileSystem
|
||||
import prog8.code.source.SourceCode
|
||||
import prog8.compiler.builtinFunctionReturnType
|
||||
import java.io.File
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.absolute
|
||||
import kotlin.io.path.isRegularFile
|
||||
|
||||
|
||||
@ -268,10 +268,10 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
val offset: UInt? = if(directive.args.size>=2) directive.args[1].int!! else null
|
||||
val length: UInt? = if(directive.args.size>=3) directive.args[2].int!! else null
|
||||
val abspath = if(File(filename).isFile) {
|
||||
Path(filename).absolute()
|
||||
Path(filename).sanitize()
|
||||
} else {
|
||||
val sourcePath = Path(directive.definingModule.source.origin)
|
||||
sourcePath.resolveSibling(filename).absolute()
|
||||
sourcePath.resolveSibling(filename).sanitize()
|
||||
}
|
||||
if(abspath.toFile().isFile)
|
||||
PtIncludeBinary(abspath, offset, length, directive.position)
|
||||
|
@ -2,6 +2,7 @@ package prog8tests.compiler
|
||||
|
||||
import io.kotest.assertions.withClue
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.datatest.withData
|
||||
import io.kotest.engine.spec.tempdir
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
@ -10,24 +11,18 @@ import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.StringLiteral
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.ast.statements.Label
|
||||
import prog8.code.sanitize
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.*
|
||||
import kotlin.io.path.absolute
|
||||
import kotlin.io.path.name
|
||||
|
||||
|
||||
/**
|
||||
* ATTENTION: this is just kludge!
|
||||
* They are not really unit tests, but rather tests of the whole process,
|
||||
* from source file loading all the way through to running 64tass.
|
||||
*/
|
||||
class TestCompilerOnImportsAndIncludes: FunSpec({
|
||||
|
||||
val outputDir = tempdir().toPath()
|
||||
|
||||
context("Import") {
|
||||
|
||||
test("testImportFromSameFolder") {
|
||||
val outputDir = tempdir().toPath()
|
||||
val filepath = assumeReadableFile(fixturesDir, "importFromSameFolder.p8")
|
||||
assumeReadableFile(fixturesDir, "foo_bar.p8")
|
||||
|
||||
@ -49,7 +44,7 @@ class TestCompilerOnImportsAndIncludes: FunSpec({
|
||||
}
|
||||
|
||||
context("AsmInclude") {
|
||||
test("testAsmIncludeFromSameFolder") {
|
||||
test("AsmIncludeFromSameFolder") {
|
||||
val filepath = assumeReadableFile(fixturesDir, "asmIncludeFromSameFolder.p8")
|
||||
assumeReadableFile(fixturesDir, "foo_bar.asm")
|
||||
|
||||
@ -89,26 +84,22 @@ class TestCompilerOnImportsAndIncludes: FunSpec({
|
||||
}
|
||||
|
||||
val tests = listOf(
|
||||
Triple("same ", "asmBinaryFromSameFolder.p8", "do_nothing1.bin"),
|
||||
Triple("sub", "asmBinaryFromSubFolder.p8", "subFolder/do_nothing2.bin"),
|
||||
"same" to "asmBinaryFromSameFolder.p8",
|
||||
"sub" to "asmBinaryFromSubFolder.p8"
|
||||
)
|
||||
|
||||
tests.forEach {
|
||||
val (where, p8Str, _) = it
|
||||
test("%asmbinary from ${where}folder") {
|
||||
val p8Path = assumeReadableFile(fixturesDir, p8Str)
|
||||
// val binPath = assumeReadableFile(fixturesDir, binStr)
|
||||
withData<Pair<String, String>>({"%asmbinary from ${it.first} folder"}, tests) { (_, p8Str) ->
|
||||
val p8Path = assumeReadableFile(fixturesDir, p8Str)
|
||||
|
||||
// the bug we're testing for (#54) was hidden if outputDir == workingDir
|
||||
withClue("sanity check: workingDir and outputDir should not be the same folder") {
|
||||
outputDir.absolute().normalize() shouldNotBe workingDir.absolute().normalize()
|
||||
}
|
||||
// the bug we're testing for (#54) was hidden if outputDir == workingDir
|
||||
withClue("sanity check: workingDir and outputDir should not be the same folder") {
|
||||
outputDir.sanitize() shouldNotBe workingDir.sanitize()
|
||||
}
|
||||
|
||||
withClue("argument to assembler directive .binary " +
|
||||
"should be relative to the generated .asm file (in output dir), " +
|
||||
"NOT relative to .p8 neither current working dir") {
|
||||
compileFile(Cx16Target(), false, p8Path.parent, p8Path.name, outputDir) shouldNotBe null
|
||||
}
|
||||
withClue("argument to assembler directive .binary " +
|
||||
"should be relative to the generated .asm file (in output dir), " +
|
||||
"NOT relative to .p8 neither current working dir") {
|
||||
compileFile(Cx16Target(), false, p8Path.parent, p8Path.name, outputDir) shouldNotBe null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package prog8tests.compiler
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.engine.spec.tempdir
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.code.sanitize
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.compiler.CompilationResult
|
||||
import prog8.compiler.CompilerArguments
|
||||
@ -11,7 +12,6 @@ import prog8tests.helpers.assumeReadableFile
|
||||
import prog8tests.helpers.fixturesDir
|
||||
import prog8tests.helpers.workingDir
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.absolute
|
||||
|
||||
/**
|
||||
* ATTENTION: this is just kludge!
|
||||
@ -51,7 +51,7 @@ class TestCompilerOptionSourcedirs: FunSpec({
|
||||
|
||||
test("testAbsoluteFilePathOutsideWorkingDir") {
|
||||
val filepath = assumeReadableFile(fixturesDir, "ast_simple_main.p8")
|
||||
compileFile(filepath.absolute(), listOf()) shouldNotBe null
|
||||
compileFile(filepath.sanitize(), listOf()) shouldNotBe null
|
||||
}
|
||||
|
||||
test("testFilePathOutsideWorkingDirRelativeToWorkingDir") {
|
||||
|
@ -14,10 +14,10 @@
|
||||
<keywords keywords="&;&<;&>;->;@;alias;and;as;asmsub;break;clobbers;continue;do;downto;else;extsub;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%jmptable;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@bank;@dirty;@nosplit;@nozp;@requirezp;@shared;@split;@zp;atascii:;c64os:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords3 keywords="bool;byte;const;float;long;str;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;bmx;call;callfar;callfar2;cbm;clamp;cmp;conv;cx16;defer;divmod;floats;len;lsb;lsw;math;max;memory;min;mkword;msb;msw;peek;peekf;peekw;poke;pokef;pokew;psg;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt;strings;sys;txt;verafx" />
|
||||
<keywords4 keywords="abs;bmx;call;callfar;callfar2;cbm;clamp;cmp;conv;cx16;defer;diskio;divmod;floats;len;lsb;lsw;math;max;memory;min;mkword;msb;msw;peek;peekf;peekw;poke;pokef;pokew;psg;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt;strings;sys;txt;verafx" />
|
||||
</highlighting>
|
||||
<extensionMap>
|
||||
<mapping ext="p8" />
|
||||
<mapping ext="prog8" />
|
||||
<mapping ext="p8" />
|
||||
</extensionMap>
|
||||
</filetype>
|
||||
</filetype>
|
||||
|
@ -555,7 +555,7 @@ object SysCalls {
|
||||
Syscall.DIRECTORY -> {
|
||||
// no arguments
|
||||
val directory = Path("")
|
||||
println("Directory listing for ${directory.absolute().normalize()}")
|
||||
println("Directory listing for ${directory}")
|
||||
directory.listDirectoryEntries().sorted().forEach {
|
||||
println("${it.toFile().length()}\t${it.normalize()}")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user