/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* This file was originally derived from the Polyglot extensible compiler framework.
*
* (C) Copyright 2000-2007 Polyglot project group, Cornell University
* (C) Copyright IBM Corporation 2007-2012.
*/
package polyglot.util;
import java.io.Serializable;
import polyglot.frontend.Globals;
import polyglot.main.Options;
/**
* This class represents a posiiton within a file.
**/
public class Position implements Serializable, Copy
{
static final long serialVersionUID = -4588386982624074261L;
private String path;
private String file;
private int line;
private int column;
private int endLine;
private int endColumn;
// Position in characters from the beginning of the containing character
// stream
private int offset;
private int endOffset;
private boolean compilerGenerated;
private Position outer = null;
public static final int UNKNOWN = -1;
public static final int END_UNUSED = -2;
public static final Position COMPILER_GENERATED = new Position(true, null, "Compiler Generated");
public static final int THIS_METHOD = 1;
public static final int CALLER = THIS_METHOD + 1;
// /**
// * Get a compiler generated position using the caller at the given stack
// * depth. Depth 1 is the caller. Depth 2 is the caller's caller, etc.
// */
// public static Position compilerGenerated(int depth) {
// if (! Globals.Options().precise_compiler_generated_positions)
// return COMPILER_GENERATED;
// StackTraceElement[] stack = new Exception().getStackTrace();
// if (depth < stack.length) {
// return new Position(true, null, stack[depth].getFileName() + " (compiler generated)", stack[depth].getLineNumber());
// }
// else {
// return COMPILER_GENERATED;
// }
// }
//
// /** Get a compiler generated position. */
// public static Position compilerGenerated() {
// return compilerGenerated(CALLER);
// }
public static Position compilerGenerated(Position pos) {
return pos==null ? COMPILER_GENERATED : pos.startOf().markCompilerGenerated();
}
public boolean isCompilerGenerated() {
return compilerGenerated;
}
public Position copy() {
try {
return (Position) super.clone();
} catch (CloneNotSupportedException e) {
assert false;
return Position.COMPILER_GENERATED;
}
}
public Position markCompilerGenerated() {
Position p = copy();
p.compilerGenerated = true;
return p;
}
/** For deserialization. */
protected Position() {
line = endLine = 0;
column = endColumn = 0;
offset = endOffset = 0;
}
private Position(boolean compilerGenerated, String path, String file) {
this(path, file, UNKNOWN, UNKNOWN);
this.compilerGenerated = compilerGenerated;
}
public Position(String path, String file) {
this(path, file, UNKNOWN, UNKNOWN);
}
private Position(boolean compilerGenerated, String path, String file, int line) {
this(path, file, line, UNKNOWN);
this.compilerGenerated = compilerGenerated;
}
public Position(String path, String file, int line) {
this(path, file, line, UNKNOWN);
}
public Position(String path, String file, int line, int column) {
this(path, file, line, column, END_UNUSED, END_UNUSED);
}
public Position(String path, String file, int line, int column, int endLine, int endColumn) {
this(path, file, line, column, endLine, endColumn, 0, 0);
}
public Position(String path, String file, int line, int column, int endLine, int endColumn, int offset, int endOffset) {
this.file = file;
assert (path == null || path.equals("")) : "Non-empty path in the position object";
this.path = path;
this.line = line;
this.column = column;
this.endLine = endLine;
this.endColumn = endColumn;
this.offset = offset;
this.endOffset = endOffset;
}
public Position(Position start, Position end) {
this(start.path(), start.file(), start.line, start.column, end.endLine, end.endColumn, start.offset, end.endOffset);
}
public Position truncateEnd(int len) {
if (this.isCompilerGenerated())
return this;
int eo = endOffset;
int el = endLine;
int ec = endColumn;
if (eo >= offset + len)
eo -= len;
else
eo = offset;
if (line == el) {
if (ec >= column + len)
ec -= len;
else
ec = column;
}
else {
if (ec >= len)
ec -= len;
else {
el = line;
ec = column;
}
}
return new Position(path, file, line, column, el, ec, offset, eo);
}
public Position startOf() {
if (this.isCompilerGenerated())
return this;
return new Position(path, file, line, column, line, column, offset, offset);
}
public Position endOf() {
if (this.isCompilerGenerated())
return this;
return new Position(path, file, endLine, endColumn, endLine, endColumn, endOffset, endOffset);
}
public int line() {
return line;
}
public int column() {
return column;
}
public int endLine() {
if (endLine == UNKNOWN || (line != UNKNOWN && endLine < line)) {
return line;
}
return endLine;
}
public int endColumn() {
if (endColumn == UNKNOWN || (column != UNKNOWN && endLine()==line() && endColumn < column)) {
return column;
}
return endColumn;
}
public int offset() {
return offset;
}
public int endOffset() {
if (endOffset == UNKNOWN || (offset != UNKNOWN && endOffset < offset)) {
return offset;
}
return endOffset;
}
public String file() {
return file;
}
public String path() {
return path;
}
public Position outer() {
return this.outer;
}
public Position outerMost() {
Position p = this;
while (p.outer != null)
p = p.outer;
return p;
}
public Position outer(Position o) {
Position p = copy();
p.outer = o;
return p;
}
public Position addOuter(Position o) {
if (o == this) {
return this;
}
if (this.outer == null) {
return outer(o);
}
Position t = this.outer.addOuter(o);
if (t == this.outer) {
return this;
}
Position p = copy();
p.outer = t;
return p;
}
public String nameAndLineString() {
// Maybe we should use path here, if it isn't too long...
String s = path;
if (s == null || s.length() == 0) {
s = file;
}
if (s == null || s.length() == 0) {
s = "unknown file";
}
if (line != UNKNOWN) {
s += ":" + line;
if (endLine != line &&
endLine != UNKNOWN && endLine != END_UNUSED) {
s += "-" + endLine;
}
}
return s;
}
public String toString() {
String s = path;
if (s == null || s.length() == 0) {
s = file;
}
if (s == null || s.length() == 0) {
s = "unknown file";
}
if (line != UNKNOWN) {
s += ":" + line;
if (column != UNKNOWN) {
s += "," + column;
if (line == endLine &&
endColumn != UNKNOWN && endColumn != END_UNUSED) {
s += "-" + endColumn;
}
if (line != endLine &&
endColumn != UNKNOWN && endColumn != END_UNUSED) {
s += "-" + endLine + "," + endColumn;
}
}
}
if (outer != null) {
s += " inlined from " + outer;
}
return s;
}
}