#!/bin/sh -xeu
# This script will detect the OS, and try to grab the libraries. And then
# creates a tarball for distribution.
# Check if another config is being sourced.
set +u
if [ -z "$TUP_CONFIG" ];
then
. ./tup.config
else
. ./"$TUP_CONFIGpre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *///: For convenience, some instructions will take literal arrays of characters
//: (text or strings).
//:
//: Instead of quotes, we'll use [] to delimit strings. That'll reduce the
//: need for escaping since we can support nested brackets. And we can also
//: imagine that 'recipe' might one day itself be defined in Mu, doing its own
//: parsing.
:(scenarios load)
:(scenario string_literal)
def main [
1:address:array:character <- copy [abc def]
]
+parse: ingredient: {"abc def": "literal-string"}
:(scenario string_literal_with_colons)
def main [
1:address:array:character <- copy [abc:def/ghi]
]
+parse: ingredient: {"abc:def/ghi": "literal-string"}
:(before "End Mu Types Initialization")
put(Type_ordinal, "literal-string", 0);
:(before "End next_word Special-cases")
if (in.peek() == '[') {
string result = slurp_quoted(in);
skip_whitespace_and_comments_but_not_newline(in);
return result;
}
:(code)
string slurp_quoted(istream& in) {
ostringstream out;
assert(has_data(in)); assert(in.peek() == '['); out << static_cast<char>(in.get()); // slurp the '['
if (is_code_string(in, out))
slurp_quoted_comment_aware(in, out);
else
slurp_quoted_comment_oblivious(in, out);
return out.str();
}
// A string is a code string (ignores comments when scanning for matching
// brackets) if it contains a newline at the start before any non-whitespace.
bool is_code_string(istream& in, ostream& out) {
while (has_data(in)) {
char c = in.get();
if (!isspace(c)) {
in.putback(c);
return false;
}
out << c;
if (c == '\n') {
return true;
}
}
return false;
}
// Read a regular string. Regular strings can only contain other regular
// strings.
void slurp_quoted_comment_oblivious(istream& in, ostream& out) {
int brace_depth = 1;
while (has_data(in)) {
char c = in.get();
if (c == '\\') {
slurp_one_past_backslashes(in, out);
continue;
}
out << c;
if (c == '[') ++brace_depth;
if (c == ']') --brace_depth;
if (brace_depth == 0) break;
}
if (!has_data(in) && brace_depth > 0) {
raise << "unbalanced '['\n" << end();
out.clear();
}
}
// Read a code string. Code strings can contain either code or regular strings.
void slurp_quoted_comment_aware(istream& in, ostream& out) {
char c;
while (in >> c) {
if (c == '\\') {
slurp_one_past_backslashes(in, out);
continue;
}
if (c == '#') {
out << c;
while (has_data(in) && in.peek() != '\n') out << static_cast<char>(in.get());
continue;
}
if (c == '[') {
in.putback(c);
// recurse
out << slurp_quoted(in);
continue;
}
out << c;
if (c == ']') return;
}
raise << "unbalanced '['\n" << end();
out.clear();
}
:(after "Parsing reagent(string s)")
if (starts_with(s, "[")) {
if (*s.rbegin() != ']') return; // unbalanced bracket; handled elsewhere
name = s;
// delete [] delimiters
name.erase(0, 1);
strip_last(name);
type = new type_tree("literal-string", 0);
return;
}
//: Unlike other reagents, escape newlines in literal strings to make them
//: more friendly to trace().
:(after "string to_string(const reagent& r)")
if (is_literal_text(r))
return emit_literal_string(r.name);
:(code)
bool is_literal_text(const reagent& x) {
return x.type && x.type->name == "literal-string";
}
string emit_literal_string(string name) {
size_t pos = 0;
while (pos != string::npos)
pos = replace(name, "\n", "\\n", pos);
return "{\""+name+"\": \"literal-string\"}";
}
size_t replace(string& str, const string& from, const string& to, size_t n) {
size_t result = str.find(from, n);
if (result != string::npos)
str.replace(result, from.length(), to);
return result;
}
void strip_last(string& s) {
if (!s.empty()) s.erase(SIZE(s)-1);
}
void slurp_one_past_backslashes(istream& in, ostream& out) {
// When you encounter a backslash, strip it out and pass through any
// following run of backslashes. If we 'escaped' a single following
// character, then the character '\' would be:
// '\\' escaped once
// '\\\\' escaped twice
// '\\\\\\\\' escaped thrice (8 backslashes)
// ..and so on. With our approach it'll be:
// '\\' escaped once
// '\\\' escaped twice
// '\\\\' escaped thrice
// This only works as long as backslashes aren't also overloaded to create
// special characters. So Mu doesn't follow C's approach of overloading
// backslashes both to escape quote characters and also as a notation for
// unprintable characters like '\n'.
while (has_data(in)) {
char c = in.get();
out << c;
if (c != '\\') break;
}
}
:(scenario string_literal_nested)
def main [
1:address:array:character <- copy [abc [def]]
]
+parse: ingredient: {"abc [def]": "literal-string"}
:(scenario string_literal_escaped)
def main [
1:address:array:character <- copy [abc \[def]
]
+parse: ingredient: {"abc [def": "literal-string"}
:(scenario string_literal_escaped_twice)
def main [
1:address:array:character <- copy [
abc \\[def]
]
+parse: ingredient: {"\nabc \[def": "literal-string"}
:(scenario string_literal_and_comment)
def main [
1:address:array:character <- copy [abc] # comment
]
+parse: --- defining main
+parse: instruction: copy
+parse: number of ingredients: 1
+parse: ingredient: {"abc": "literal-string"}
+parse: product: {1: ("address" "array" "character")}
:(scenario string_literal_escapes_newlines_in_trace)
def main [
copy [abc
def]
]
+parse: ingredient: {"abc\ndef": "literal-string"}
:(scenario string_literal_can_skip_past_comments)
def main [
copy [
# ']' inside comment
bar
]
]
+parse: ingredient: {"\n # ']' inside comment\n bar\n ": "literal-string"}
:(scenario string_literal_empty)
def main [
copy []
]
+parse: ingredient: {"": "literal-string"}
:(scenario multiple_unfinished_recipes)
% Hide_errors = true;
def f1 [
def f2 [
+error: unbalanced '['