# line-number-db.pkg
# XXX BUGGO FIXME This seems severely redundant with
src/lib/compiler/front/basics/source/line-number-db.pkg# not to mention
src/lib/compiler/back/low/tools/line-number-db/line-number-database.pkg#
# XXX BUGGO FIXME "location" should be changed to "region".
# Compiled by:
#
src/lib/c-kit/src/parser/c-parser.sublib### "It is not knowledge, but the act of learning,
### not possession but the act of getting there,
### which grants the greatest enjoyment."
###
### -- Carl Friedrich Gauss
package line_number_db
: (weak) Line_Number_Db # Line_Number_Db is from
src/lib/c-kit/src/parser/stuff/line-number-db.api{
package f= sfprintf; # sfprintf is from
src/lib/src/sfprintf.pkg Charpos = Int;
Source_Code_Region = (Charpos, Charpos);
Location
= UNKNOWN
| LOC {
src_file: String,
begin_line: Int,
begin_col: Int,
end_line: Int,
end_col: Int
};
Sourcemap
=
SOURCEMAP {
line_pos: Ref( List( Charpos ) ),
line_num: Ref( Int ),
file_pos: Ref( List { line_pos: List( Charpos ),
line: Int,
src_file: String } )
};
# David B MacQueen: the filePos is a stack of records, but it doesn't get popped,
# so it looks like filePos could just be a REF of the record. XXX BUGGO FIXME
fun newmap { src_file }
=
SOURCEMAP {
line_pos => REF [1], # this compensates for lex bug: yypos off by 2
file_pos => REF [{ line_pos => [], line => 1, src_file } ],
line_num => REF 1
};
fun newline
(SOURCEMAP { line_pos, line_num, ... } )
pos
=
{ line_pos := pos ! *line_pos;
line_num := 1 + *line_num;
};
fun resynch (SOURCEMAP { line_pos, file_pos, line_num, ... } ) { pos, src_file, line }
=
{ line_pos := [pos];
line_num := line;
file_pos := { line_pos => *line_pos,
line => *line_num,
src_file
=>
case src_file
THE src_file => src_file;
NULL
=>
{ fpl = *file_pos;
case fpl
NIL => "";
x ! _ => x.src_file;
esac;
};
esac
}
!
*file_pos;
};
fun parse_directive line_number_db (pos, directive)
=
{ fun sep ' ' => TRUE;
sep '"' => TRUE;
sep '#' => TRUE;
sep '\n' => TRUE;
sep _ => FALSE;
end;
fun proc { line, src_opt }
=
case (int::from_string line)
THE line
=>
resynch line_number_db { line, pos, src_file => src_opt };
_ =>
newline line_number_db pos;
esac;
if config::parse_control::parse_directive
case (string::tokens sep directive)
("line" ! line ! src_file ! _)
=>
proc { line, src_opt => THE src_file };
line ! src_file ! _
=>
proc { line, src_opt => THE src_file };
line ! _
=>
proc { line, src_opt => NULL };
_ =>
newline line_number_db pos;
esac;
else
newline line_number_db pos;
fi;
};
fun curr_pos (SOURCEMAP { line_pos, ... } )
=
head *line_pos;
fun location (SOURCEMAP { line_pos, file_pos, line_num, ... } ) (x, y)
=
{ fun find_pos (p, curr_pos, curr_file, pos ! rest, file_pos, line)
=>
if (p > pos)
{ src_file=>curr_file, line, column=>p - pos };
else
find_pos (p, pos, curr_file, rest, file_pos, line - 1);
fi;
find_pos (p, curr_pos, curr_file,[],{ line_pos, line, src_file } ! file_pos, _)
=>
find_pos (p, curr_pos, .src_file (head file_pos), line_pos, file_pos, line);
# NOTE: very confusing...
# filePos stack contains previous line info and srcFile of current file
find_pos (p, curr_pos, curr_file,[],[], line)
=>
{ src_file=>curr_file, line, column=>0 };
end;
my { src_file=>curr_file, ... }
=
head *file_pos;
my { src_file, line=>l1, column=>c1 }
=
find_pos (x, x, curr_file,*line_pos,*file_pos,*line_num);
my { src_file, line=>l2, column=>c2 }
=
find_pos (y, y, curr_file,*line_pos,*file_pos,*line_num);
LOC {
src_file,
begin_line => l1,
begin_col => c1,
end_line => l2,
end_col => c2
};
};
# Return a string "foo.pkg:4596.16-23" representing a location:
fun loc_to_string UNKNOWN
=>
"\"???\"";
loc_to_string (LOC { src_file, begin_line, begin_col, end_line, end_col } )
=>
{ src_file = src_file;
p1line = begin_line;
p1pos = begin_col;
p2line = end_line;
p2pos = end_col;
if (begin_line == end_line)
if (p1pos < p2pos)
f::sprintf' "\"%s\":%d.%d-%d" [
f::STRING src_file, f::INT p1line, f::INT p1pos, f::INT p2pos
];
else
f::sprintf' "\"%s\":%d.%d" [
f::STRING src_file, f::INT p1line, f::INT p1pos
];
fi;
else
f::sprintf' "\"%s\":%d.%d-%d.%d" [
f::STRING src_file, f::INT p1line, f::INT p1pos,
f::INT p2line, f::INT p2pos
];
fi;
};
end; # loc_to_string
};