2012-03-29 13:48:05 -07:00
|
|
|
import ast::{crate, expr_, mac_invoc,
|
2012-02-04 15:42:12 -07:00
|
|
|
mac_aq, mac_var};
|
2012-03-29 13:48:05 -07:00
|
|
|
import fold::*;
|
|
|
|
import visit::*;
|
|
|
|
import ext::base::*;
|
|
|
|
import ext::build::*;
|
|
|
|
import parse::parser;
|
2012-04-17 23:34:48 -07:00
|
|
|
import parse::parser::parse_from_source_str;
|
2012-01-26 17:03:20 -07:00
|
|
|
|
2012-03-29 13:48:05 -07:00
|
|
|
import print::*;
|
2012-03-12 20:04:27 -07:00
|
|
|
import io::*;
|
2012-01-27 01:50:57 -07:00
|
|
|
|
2012-01-26 17:03:20 -07:00
|
|
|
import codemap::span;
|
|
|
|
|
2012-01-27 01:50:57 -07:00
|
|
|
type aq_ctxt = @{lo: uint,
|
2012-03-26 18:35:18 -07:00
|
|
|
mut gather: [{lo: uint, hi: uint,
|
2012-02-01 17:20:56 -07:00
|
|
|
e: @ast::expr,
|
|
|
|
constr: str}]};
|
2012-02-01 16:19:45 -07:00
|
|
|
enum fragment {
|
|
|
|
from_expr(@ast::expr),
|
|
|
|
from_ty(@ast::ty)
|
|
|
|
}
|
2012-01-27 01:50:57 -07:00
|
|
|
|
2012-02-01 08:01:21 -07:00
|
|
|
iface qq_helper {
|
|
|
|
fn span() -> span;
|
|
|
|
fn visit(aq_ctxt, vt<aq_ctxt>);
|
2012-02-01 16:19:45 -07:00
|
|
|
fn extract_mac() -> option<ast::mac_>;
|
2012-02-01 08:01:21 -07:00
|
|
|
fn mk_parse_fn(ext_ctxt,span) -> @ast::expr;
|
2012-02-01 17:20:56 -07:00
|
|
|
fn get_fold_fn() -> str;
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
2012-02-21 15:34:26 -08:00
|
|
|
|
|
|
|
impl of qq_helper for @ast::crate {
|
|
|
|
fn span() -> span {self.span}
|
|
|
|
fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_crate(*self, cx, v);}
|
|
|
|
fn extract_mac() -> option<ast::mac_> {fail}
|
|
|
|
fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
|
|
|
|
mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_crate"])
|
|
|
|
}
|
|
|
|
fn get_fold_fn() -> str {"fold_crate"}
|
|
|
|
}
|
2012-02-01 08:01:21 -07:00
|
|
|
impl of qq_helper for @ast::expr {
|
|
|
|
fn span() -> span {self.span}
|
|
|
|
fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_expr(self, cx, v);}
|
2012-02-01 16:19:45 -07:00
|
|
|
fn extract_mac() -> option<ast::mac_> {
|
|
|
|
alt (self.node) {
|
|
|
|
ast::expr_mac({node: mac, _}) {some(mac)}
|
|
|
|
_ {none}
|
|
|
|
}
|
|
|
|
}
|
2012-02-01 08:01:21 -07:00
|
|
|
fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
|
|
|
|
mk_path(cx, sp, ["syntax", "parse", "parser", "parse_expr"])
|
|
|
|
}
|
2012-02-01 17:20:56 -07:00
|
|
|
fn get_fold_fn() -> str {"fold_expr"}
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
|
|
|
impl of qq_helper for @ast::ty {
|
|
|
|
fn span() -> span {self.span}
|
|
|
|
fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_ty(self, cx, v);}
|
2012-02-01 16:19:45 -07:00
|
|
|
fn extract_mac() -> option<ast::mac_> {
|
|
|
|
alt (self.node) {
|
|
|
|
ast::ty_mac({node: mac, _}) {some(mac)}
|
|
|
|
_ {none}
|
|
|
|
}
|
|
|
|
}
|
2012-02-01 08:01:21 -07:00
|
|
|
fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
|
|
|
|
mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_ty"])
|
|
|
|
}
|
2012-02-01 17:20:56 -07:00
|
|
|
fn get_fold_fn() -> str {"fold_ty"}
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
|
|
|
impl of qq_helper for @ast::item {
|
|
|
|
fn span() -> span {self.span}
|
|
|
|
fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_item(self, cx, v);}
|
2012-02-01 16:19:45 -07:00
|
|
|
fn extract_mac() -> option<ast::mac_> {fail}
|
2012-02-01 08:01:21 -07:00
|
|
|
fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
|
|
|
|
mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_item"])
|
|
|
|
}
|
2012-02-01 17:20:56 -07:00
|
|
|
fn get_fold_fn() -> str {"fold_item"}
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
|
|
|
impl of qq_helper for @ast::stmt {
|
|
|
|
fn span() -> span {self.span}
|
|
|
|
fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_stmt(self, cx, v);}
|
2012-02-01 16:19:45 -07:00
|
|
|
fn extract_mac() -> option<ast::mac_> {fail}
|
2012-02-01 08:01:21 -07:00
|
|
|
fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
|
|
|
|
mk_path(cx, sp, ["syntax", "ext", "qquote", "parse_stmt"])
|
|
|
|
}
|
2012-02-01 17:20:56 -07:00
|
|
|
fn get_fold_fn() -> str {"fold_stmt"}
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
|
|
|
impl of qq_helper for @ast::pat {
|
|
|
|
fn span() -> span {self.span}
|
|
|
|
fn visit(cx: aq_ctxt, v: vt<aq_ctxt>) {visit_pat(self, cx, v);}
|
2012-02-01 16:19:45 -07:00
|
|
|
fn extract_mac() -> option<ast::mac_> {fail}
|
2012-02-01 08:01:21 -07:00
|
|
|
fn mk_parse_fn(cx: ext_ctxt, sp: span) -> @ast::expr {
|
|
|
|
mk_path(cx, sp, ["syntax", "parse", "parser", "parse_pat"])
|
|
|
|
}
|
2012-02-01 17:20:56 -07:00
|
|
|
fn get_fold_fn() -> str {"fold_pat"}
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn gather_anti_quotes<N: qq_helper>(lo: uint, node: N) -> aq_ctxt
|
2012-01-27 01:50:57 -07:00
|
|
|
{
|
2012-04-19 14:26:45 -07:00
|
|
|
let v = @{visit_expr: {|node, &&cx, v|
|
|
|
|
visit_aq(node, "from_expr", cx, v)},
|
|
|
|
visit_ty: {|node, &&cx, v|
|
|
|
|
visit_aq(node, "from_ty", cx, v)}
|
2012-01-27 01:50:57 -07:00
|
|
|
with *default_visitor()};
|
2012-03-26 18:35:18 -07:00
|
|
|
let cx = @{lo:lo, mut gather: []};
|
2012-02-01 08:01:21 -07:00
|
|
|
node.visit(cx, mk_vt(v));
|
2012-03-06 18:07:10 -07:00
|
|
|
// FIXME: Maybe this is an overkill (merge_sort), it might be better
|
2012-04-19 14:26:45 -07:00
|
|
|
// to just keep the gather array in sorted order ... (Issue #2250)
|
2012-03-06 18:07:10 -07:00
|
|
|
cx.gather = std::sort::merge_sort({|a,b| a.lo < b.lo}, copy cx.gather);
|
2012-01-27 01:50:57 -07:00
|
|
|
ret cx;
|
|
|
|
}
|
|
|
|
|
2012-02-01 16:19:45 -07:00
|
|
|
fn visit_aq<T:qq_helper>(node: T, constr: str, &&cx: aq_ctxt, v: vt<aq_ctxt>)
|
2012-01-27 01:50:57 -07:00
|
|
|
{
|
2012-02-01 16:19:45 -07:00
|
|
|
alt (node.extract_mac()) {
|
|
|
|
some(mac_aq(sp, e)) {
|
2012-01-27 01:50:57 -07:00
|
|
|
cx.gather += [{lo: sp.lo - cx.lo, hi: sp.hi - cx.lo,
|
2012-02-01 16:19:45 -07:00
|
|
|
e: e, constr: constr}];
|
2012-01-27 01:50:57 -07:00
|
|
|
}
|
2012-02-01 16:19:45 -07:00
|
|
|
_ {node.visit(cx, v);}
|
2012-01-27 01:50:57 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 18:20:43 -07:00
|
|
|
fn is_space(c: char) -> bool {
|
2012-03-29 13:48:05 -07:00
|
|
|
parse::lexer::is_whitespace(c)
|
2012-01-28 18:20:43 -07:00
|
|
|
}
|
|
|
|
|
2012-02-01 08:01:21 -07:00
|
|
|
fn expand_ast(ecx: ext_ctxt, _sp: span,
|
|
|
|
arg: ast::mac_arg, body: ast::mac_body)
|
2012-02-01 03:40:49 -07:00
|
|
|
-> @ast::expr
|
2012-02-01 02:58:28 -07:00
|
|
|
{
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut what = "expr";
|
2012-04-06 12:14:09 -07:00
|
|
|
option::iter(arg) {|arg|
|
2012-02-01 08:01:21 -07:00
|
|
|
let args: [@ast::expr] =
|
|
|
|
alt arg.node {
|
|
|
|
ast::expr_vec(elts, _) { elts }
|
|
|
|
_ {
|
|
|
|
ecx.span_fatal
|
|
|
|
(_sp, "#ast requires arguments of the form `[...]`.")
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if vec::len::<@ast::expr>(args) != 1u {
|
|
|
|
ecx.span_fatal(_sp, "#ast requires exactly one arg");
|
|
|
|
}
|
|
|
|
alt (args[0].node) {
|
|
|
|
ast::expr_path(@{node: {idents: id, _},_}) if vec::len(id) == 1u
|
|
|
|
{what = id[0]}
|
|
|
|
_ {ecx.span_fatal(args[0].span, "expected an identifier");}
|
|
|
|
}
|
|
|
|
}
|
2012-02-01 02:58:28 -07:00
|
|
|
let body = get_mac_body(ecx,_sp,body);
|
2012-02-01 08:01:21 -07:00
|
|
|
|
|
|
|
ret alt what {
|
2012-02-21 15:34:26 -08:00
|
|
|
"crate" {finish(ecx, body, parse_crate)}
|
2012-02-01 08:01:21 -07:00
|
|
|
"expr" {finish(ecx, body, parser::parse_expr)}
|
|
|
|
"ty" {finish(ecx, body, parse_ty)}
|
|
|
|
"item" {finish(ecx, body, parse_item)}
|
|
|
|
"stmt" {finish(ecx, body, parse_stmt)}
|
|
|
|
"pat" {finish(ecx, body, parser::parse_pat)}
|
|
|
|
_ {ecx.span_fatal(_sp, "unsupported ast type")}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2012-02-21 15:34:26 -08:00
|
|
|
fn parse_crate(p: parser) -> @ast::crate {
|
|
|
|
parser::parse_crate_mod(p, [])
|
|
|
|
}
|
|
|
|
|
2012-02-01 08:01:21 -07:00
|
|
|
fn parse_ty(p: parser) -> @ast::ty {
|
|
|
|
parser::parse_ty(p, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_stmt(p: parser) -> @ast::stmt {
|
|
|
|
parser::parse_stmt(p, [])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_item(p: parser) -> @ast::item {
|
|
|
|
alt (parser::parse_item(p, [])) {
|
2012-04-19 14:26:45 -07:00
|
|
|
some(item) { item }
|
|
|
|
none { fail "parse_item: parsing an item failed"; }
|
2012-02-01 08:01:21 -07:00
|
|
|
}
|
2012-02-01 02:58:28 -07:00
|
|
|
}
|
|
|
|
|
2012-02-10 12:23:40 -07:00
|
|
|
fn finish<T: qq_helper>
|
|
|
|
(ecx: ext_ctxt, body: ast::mac_body_, f: fn (p: parser) -> T)
|
2012-02-01 03:40:49 -07:00
|
|
|
-> @ast::expr
|
2012-02-01 02:58:28 -07:00
|
|
|
{
|
2012-03-22 18:53:30 -07:00
|
|
|
let cm = ecx.codemap();
|
2012-02-10 12:23:40 -07:00
|
|
|
let str = @codemap::span_to_snippet(body.span, cm);
|
2012-03-12 10:19:35 -07:00
|
|
|
#debug["qquote--str==%?", str];
|
2012-02-10 12:23:40 -07:00
|
|
|
let fname = codemap::mk_substr_filename(cm, body.span);
|
|
|
|
let node = parse_from_source_str
|
|
|
|
(f, fname, codemap::fss_internal(body.span), str,
|
2012-03-22 18:53:30 -07:00
|
|
|
ecx.cfg(), ecx.parse_sess());
|
2012-02-10 12:23:40 -07:00
|
|
|
let loc = codemap::lookup_char_pos(cm, body.span.lo);
|
|
|
|
|
|
|
|
let sp = node.span();
|
2012-02-01 08:01:21 -07:00
|
|
|
let qcx = gather_anti_quotes(sp.lo, node);
|
2012-01-27 01:50:57 -07:00
|
|
|
let cx = qcx;
|
2012-02-10 17:27:35 -07:00
|
|
|
|
|
|
|
uint::range(1u, vec::len(cx.gather)) {|i|
|
|
|
|
assert cx.gather[i-1u].lo < cx.gather[i].lo;
|
2012-03-06 18:07:10 -07:00
|
|
|
// ^^ check that the vector is sorted
|
|
|
|
assert cx.gather[i-1u].hi <= cx.gather[i].lo;
|
|
|
|
// ^^ check that the spans are non-overlapping
|
2012-01-27 01:50:57 -07:00
|
|
|
}
|
2012-02-10 17:27:35 -07:00
|
|
|
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut str2 = "";
|
2012-01-28 18:20:43 -07:00
|
|
|
enum state {active, skip(uint), blank};
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut state = active;
|
|
|
|
let mut i = 0u, j = 0u;
|
2012-01-27 01:50:57 -07:00
|
|
|
let g_len = vec::len(cx.gather);
|
2012-02-10 12:23:40 -07:00
|
|
|
str::chars_iter(*str) {|ch|
|
2012-01-28 18:20:43 -07:00
|
|
|
if (j < g_len && i == cx.gather[j].lo) {
|
2012-01-27 01:50:57 -07:00
|
|
|
assert ch == '$';
|
2012-01-28 18:20:43 -07:00
|
|
|
let repl = #fmt("$%u ", j);
|
2012-02-23 16:59:30 +01:00
|
|
|
state = skip(str::char_len(repl));
|
2012-01-28 18:20:43 -07:00
|
|
|
str2 += repl;
|
|
|
|
}
|
|
|
|
alt state {
|
|
|
|
active {str::push_char(str2, ch);}
|
|
|
|
skip(1u) {state = blank;}
|
|
|
|
skip(sk) {state = skip (sk-1u);}
|
|
|
|
blank if is_space(ch) {str::push_char(str2, ch);}
|
|
|
|
blank {str::push_char(str2, ' ');}
|
2012-01-27 01:50:57 -07:00
|
|
|
}
|
|
|
|
i += 1u;
|
2012-01-28 18:20:43 -07:00
|
|
|
if (j < g_len && i == cx.gather[j].hi) {
|
2012-01-27 01:50:57 -07:00
|
|
|
assert ch == ')';
|
2012-01-28 18:20:43 -07:00
|
|
|
state = active;
|
2012-01-27 01:50:57 -07:00
|
|
|
j += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let cx = ecx;
|
2012-03-22 18:53:30 -07:00
|
|
|
|
|
|
|
let cfg_call = {||
|
|
|
|
mk_call_(cx, sp, mk_access(cx, sp, ["ext_cx"], "cfg"), [])
|
|
|
|
};
|
|
|
|
|
|
|
|
let parse_sess_call = {||
|
|
|
|
mk_call_(cx, sp, mk_access(cx, sp, ["ext_cx"], "parse_sess"), [])
|
2012-03-20 17:18:34 -07:00
|
|
|
};
|
|
|
|
|
2012-01-27 01:50:57 -07:00
|
|
|
let pcall = mk_call(cx,sp,
|
2012-01-26 17:03:20 -07:00
|
|
|
["syntax", "parse", "parser",
|
2012-02-01 08:01:21 -07:00
|
|
|
"parse_from_source_str"],
|
|
|
|
[node.mk_parse_fn(cx,sp),
|
2012-02-10 12:23:40 -07:00
|
|
|
mk_str(cx,sp, fname),
|
|
|
|
mk_call(cx,sp,
|
|
|
|
["syntax","ext","qquote", "mk_file_substr"],
|
|
|
|
[mk_str(cx,sp, loc.file.name),
|
|
|
|
mk_uint(cx,sp, loc.line),
|
|
|
|
mk_uint(cx,sp, loc.col)]),
|
2012-02-15 11:25:39 -08:00
|
|
|
mk_unary(cx,sp, ast::box(ast::m_imm),
|
2012-01-27 01:50:57 -07:00
|
|
|
mk_str(cx,sp, str2)),
|
2012-03-22 18:53:30 -07:00
|
|
|
cfg_call(),
|
|
|
|
parse_sess_call()]
|
2012-01-26 17:03:20 -07:00
|
|
|
);
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut rcall = pcall;
|
2012-01-27 01:50:57 -07:00
|
|
|
if (g_len > 0u) {
|
|
|
|
rcall = mk_call(cx,sp,
|
|
|
|
["syntax", "ext", "qquote", "replace"],
|
|
|
|
[pcall,
|
2012-02-03 17:39:39 -08:00
|
|
|
mk_vec_e(cx,sp, vec::map(copy qcx.gather) {|g|
|
2012-02-01 16:19:45 -07:00
|
|
|
mk_call(cx,sp,
|
|
|
|
["syntax", "ext", "qquote", g.constr],
|
2012-02-01 17:20:56 -07:00
|
|
|
[g.e])}),
|
|
|
|
mk_path(cx,sp,
|
|
|
|
["syntax", "ext", "qquote",
|
|
|
|
node.get_fold_fn()])]);
|
2012-01-27 01:50:57 -07:00
|
|
|
}
|
2012-01-28 18:09:37 -07:00
|
|
|
ret rcall;
|
2012-01-26 17:03:20 -07:00
|
|
|
}
|
|
|
|
|
2012-02-01 17:20:56 -07:00
|
|
|
fn replace<T>(node: T, repls: [fragment], ff: fn (ast_fold, T) -> T)
|
|
|
|
-> T
|
|
|
|
{
|
2012-01-26 18:10:33 -07:00
|
|
|
let aft = default_ast_fold();
|
|
|
|
let f_pre = {fold_expr: bind replace_expr(repls, _, _, _,
|
2012-02-01 16:19:45 -07:00
|
|
|
aft.fold_expr),
|
|
|
|
fold_ty: bind replace_ty(repls, _, _, _,
|
|
|
|
aft.fold_ty)
|
2012-01-26 18:10:33 -07:00
|
|
|
with *aft};
|
2012-02-01 17:20:56 -07:00
|
|
|
ret ff(make_fold(f_pre), node);
|
2012-01-26 18:10:33 -07:00
|
|
|
}
|
2012-02-21 15:34:26 -08:00
|
|
|
fn fold_crate(f: ast_fold, &&n: @ast::crate) -> @ast::crate {
|
|
|
|
@f.fold_crate(*n)
|
|
|
|
}
|
2012-02-01 17:20:56 -07:00
|
|
|
fn fold_expr(f: ast_fold, &&n: @ast::expr) -> @ast::expr {f.fold_expr(n)}
|
|
|
|
fn fold_ty(f: ast_fold, &&n: @ast::ty) -> @ast::ty {f.fold_ty(n)}
|
|
|
|
fn fold_item(f: ast_fold, &&n: @ast::item) -> @ast::item {f.fold_item(n)}
|
|
|
|
fn fold_stmt(f: ast_fold, &&n: @ast::stmt) -> @ast::stmt {f.fold_stmt(n)}
|
|
|
|
fn fold_pat(f: ast_fold, &&n: @ast::pat) -> @ast::pat {f.fold_pat(n)}
|
2012-01-26 18:10:33 -07:00
|
|
|
|
2012-02-01 16:19:45 -07:00
|
|
|
fn replace_expr(repls: [fragment],
|
2012-01-26 18:10:33 -07:00
|
|
|
e: ast::expr_, s: span, fld: ast_fold,
|
|
|
|
orig: fn@(ast::expr_, span, ast_fold)->(ast::expr_, span))
|
|
|
|
-> (ast::expr_, span)
|
|
|
|
{
|
|
|
|
alt e {
|
2012-02-01 16:19:45 -07:00
|
|
|
ast::expr_mac({node: mac_var(i), _}) {
|
|
|
|
alt (repls[i]) {
|
|
|
|
from_expr(r) {(r.node, r.span)}
|
|
|
|
_ {fail /* fixme error message */}}}
|
|
|
|
_ {orig(e,s,fld)}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn replace_ty(repls: [fragment],
|
|
|
|
e: ast::ty_, s: span, fld: ast_fold,
|
|
|
|
orig: fn@(ast::ty_, span, ast_fold)->(ast::ty_, span))
|
|
|
|
-> (ast::ty_, span)
|
|
|
|
{
|
|
|
|
alt e {
|
|
|
|
ast::ty_mac({node: mac_var(i), _}) {
|
|
|
|
alt (repls[i]) {
|
|
|
|
from_ty(r) {(r.node, r.span)}
|
|
|
|
_ {fail /* fixme error message */}}}
|
2012-01-26 18:10:33 -07:00
|
|
|
_ {orig(e,s,fld)}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-27 01:50:57 -07:00
|
|
|
fn print_expr(expr: @ast::expr) {
|
2012-03-12 20:04:27 -07:00
|
|
|
let stdout = io::stdout();
|
2012-01-27 01:50:57 -07:00
|
|
|
let pp = pprust::rust_printer(stdout);
|
|
|
|
pprust::print_expr(pp, expr);
|
|
|
|
pp::eof(pp.s);
|
|
|
|
stdout.write_str("\n");
|
|
|
|
}
|
|
|
|
|
2012-02-10 12:23:40 -07:00
|
|
|
fn mk_file_substr(fname: str, line: uint, col: uint) -> codemap::file_substr {
|
|
|
|
codemap::fss_external({filename: fname, line: line, col: col})
|
|
|
|
}
|
|
|
|
|
2012-01-26 17:03:20 -07:00
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|