1cad622003-08-24Martin Nilsson  #pike __REAL_VERSION__
d93b4b2002-12-05Henrik Grubbström (Grubba)  /* MirarDoc documentation extractor. */
8640032011-11-11Henrik Grubbström (Grubba) string IMAGE_DIR; // Alternative makepic implementations, current first. constant makepic = ({ // Pike 0.7.11 and later: #"// Illustration. #pike __REAL_VERSION__ string fn; int verbosity; void create(string _fn, int|void _verbosity, void|string type) { fn = _fn; verbosity = _verbosity; string ext; if(type==\"image/gif\") ext=\"gif\"; fn += \".\" + (ext||\"png\"); } object lena() { catch { return Image.load(IMAGE_DIR + \"image_ill.pnm\"); }; catch { return Image.load(IMAGE_DIR + \"lena.ppm\"); };
1ee3352011-11-16Henrik Grubbström (Grubba)  catch { return Image.load(IMAGE_DIR + \"lenna.rs\"); };
8640032011-11-11Henrik Grubbström (Grubba)  return Image.load(IMAGE_DIR + \"lena.gif\"); }
05262f2012-01-27Henrik Grubbström (Grubba)  array indices(mixed x) { if (x == Image.Color) { return sort(predef::indices(x)); } return predef::indices(x); } array values(mixed x) { if (x == Image.Color) { array res = predef::values(x); sort(predef::indices(x), res); return res; } return predef::values(x); }
8640032011-11-11Henrik Grubbström (Grubba)  object|string render(); string make() { #if constant(Image.PNG.encode) object|string o=render(); if(objectp(o)) o=Image.PNG.encode(o); Stdio.write_file(fn, o); if(verbosity > 1) werror(\"Wrote %s.\\n\", fn); #endif return \"<image>\"+fn+\"</image>\"; } object|string render() { ", // Prior to 7.3.11 there were implicit imports of Image // and Stdio. cf src/modules/Image/illustration.pike. // // There was also a compat layer for various functions // that later were removed. #"// Pike 7.3 illustration, implicit imports. #pike 7.3 import Image; import Stdio; string fn; int verbosity; void create(string _fn, int|void _verbosity, void|string type) { fn = _fn; verbosity = _verbosity; string ext; if(type==\"image/gif\") ext=\"gif\"; fn += \".\" + (ext||\"png\"); } object lena() { catch { return load(IMAGE_DIR + \"image_ill.pnm\"); }; catch { return load(IMAGE_DIR + \"lena.ppm\"); };
1ee3352011-11-16Henrik Grubbström (Grubba)  catch { return load(IMAGE_DIR + \"lenna.rs\"); }; return load(IMAGE_DIR + \"lena.gif\"); }
05262f2012-01-27Henrik Grubbström (Grubba)  array indices(mixed x) {
4de3de2012-02-11Henrik Grubbström (Grubba)  if (x == Color) {
05262f2012-01-27Henrik Grubbström (Grubba)  return sort(predef::indices(x)); } return predef::indices(x); } array values(mixed x) {
4de3de2012-02-11Henrik Grubbström (Grubba)  if (x == Color) {
05262f2012-01-27Henrik Grubbström (Grubba)  array res = predef::values(x); sort(predef::indices(x), res); return res; } return predef::values(x); }
1ee3352011-11-16Henrik Grubbström (Grubba)  object|string render(); string make() { #if constant(Image.PNG.encode) object|string o=render(); if(objectp(o)) o=PNG.encode(o); Stdio.write_file(fn, o); if(verbosity > 1) werror(\"Wrote %s.\\n\", fn); #endif return \"<image>\"+fn+\"</image>\"; } object|string render() { ", // Prior to 0.7.3 the Image module classes were all lower-case. #"// Pike 0.6 illustration, implicit imports, only Image.image. #pike 0.6 import 0.6::Image; import 0.6::Stdio; string fn; constant Image = 7.6::Image; int verbosity; void create(string _fn, int|void _verbosity, void|string type) { fn = _fn; verbosity = _verbosity; string ext; if(type==\"image/gif\") ext=\"gif\"; fn += \".\" + (ext||\"png\"); } object lena() { catch { return load(IMAGE_DIR + \"image_ill.pnm\"); }; catch { return load(IMAGE_DIR + \"lena.ppm\"); }; catch { return load(IMAGE_DIR + \"lenna.rs\"); };
8640032011-11-11Henrik Grubbström (Grubba)  return load(IMAGE_DIR + \"lena.gif\"); }
05262f2012-01-27Henrik Grubbström (Grubba)  array indices(mixed x) { if (x == Image.Color) { return sort(predef::indices(x)); } return predef::indices(x); } array values(mixed x) { if (x == Image.Color) { array res = predef::values(x); sort(predef::indices(x), res); return res; } return predef::values(x); }
8640032011-11-11Henrik Grubbström (Grubba)  object|string render(); string make() { #if constant(Image.PNG.encode) object|string o=render(); if(objectp(o)) o=PNG.encode(o); Stdio.write_file(fn, o); if(verbosity > 1) werror(\"Wrote %s.\\n\", fn); #endif return \"<image>\"+fn+\"</image>\"; } object|string render() { ", });
d93b4b2002-12-05Henrik Grubbström (Grubba) string execute;
c75acb2012-02-11Henrik Grubbström (Grubba) mapping parse=([ " appendix":([]) ]);
d93b4b2002-12-05Henrik Grubbström (Grubba) int illustration_counter;
f136d42002-12-19Henrik Grubbström (Grubba) int verbosity = 1;
d93b4b2002-12-05Henrik Grubbström (Grubba) /* module : mapping <- moduleM "desc" : text "see also" : array of references "note" : mapping of "desc": text "modules" : same as classes (below)
3524712015-05-26Martin Nilsson  "classes" : mapping
d93b4b2002-12-05Henrik Grubbström (Grubba)  class : mapping <- classM "see also" : array of references "desc" : text "note" : mapping of "desc": text "methods" : array of mappings <- methodM
7868692011-11-18Henrik Grubbström (Grubba)  "decl" : array of array of type, name[, params]
d93b4b2002-12-05Henrik Grubbström (Grubba)  "desc" : text "returns" : textline "see also" : array of references "note" : mapping of "desc": text "known bugs" : mapping of "desc": text "args" : array of mappings <- argM "args" : array of args names and types "desc" : description "names" : multiset of method name(s) Quoting: Only '<' must be quoted as '&lt;'. */
c75acb2012-02-11Henrik Grubbström (Grubba) mapping moduleM, classM, methodM, argM, nowM, descM, appendixM;
d93b4b2002-12-05Henrik Grubbström (Grubba)  mapping focM(mapping dest,string name,string line) { if (!dest->_order) dest->_order=({}); if (!has_value(dest->_order,name)) dest->_order+=({name}); return dest[name] || (dest[name]=(["_line":line])); } string stripws(string s) { if (s=="") return s; array lines = s / "\n"; lines = map(lines, lambda(string s) { s = reverse(s); sscanf(s, "%*[ \t\r]%s", s); s = reverse(s); return s; }); int m=10000; foreach (lines,string s) if (s!="") { sscanf(s,"%[ ]%s",string a,string b);
ead9722003-01-20Martin Nilsson  if (b!="") m=min(sizeof(a),m);
d93b4b2002-12-05Henrik Grubbström (Grubba)  } return map(lines,lambda(string s) { return s[m..]; })*"\n"; } mapping lower_nowM() { if (nowM &&
bc80572011-12-04Henrik Grubbström (Grubba)  (nowM==classM
d93b4b2002-12-05Henrik Grubbström (Grubba)  || nowM==methodM || nowM==moduleM)) return nowM;
bc80572011-12-04Henrik Grubbström (Grubba)  else return nowM=(methodM || classM || moduleM);
d93b4b2002-12-05Henrik Grubbström (Grubba) }
048ff92011-11-18Henrik Grubbström (Grubba) void report(int level, string currentfile, int line, sprintf_format msg, sprintf_args ... args)
d93b4b2002-12-05Henrik Grubbström (Grubba) {
048ff92011-11-18Henrik Grubbström (Grubba)  if (verbosity >= level) { if (sizeof(args)) msg = sprintf(msg, @args); werror("%s:%d: %s\n", currentfile, line, msg); }
d93b4b2002-12-05Henrik Grubbström (Grubba) } #define complain(X) (X) string file_version = "";
048ff92011-11-18Henrik Grubbström (Grubba) string format_line(string currentfile, int line) { return "file='"+currentfile+"' first-line='"+line+"'"; }
d93b4b2002-12-05Henrik Grubbström (Grubba) mapping keywords=
048ff92011-11-18Henrik Grubbström (Grubba) (["$""Id":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { file_version = " version='Id: "+arg[..search(arg, "$")-1]+"'"; },
c75acb2012-02-11Henrik Grubbström (Grubba)  "appendix":lambda(string arg, string currentfile, int line) { if (!(flags & .FLAG_COMPAT)) { report(.FLAG_NORMAL,currentfile,line, "Appendices are only supported in compat mode.\n"); return; } descM=nowM=appendixM=focM(parse[" appendix"],stripws(arg),format_line(currentfile,line)); report(.FLAG_VERBOSE,currentfile,line,"appendix "+arg); },
048ff92011-11-18Henrik Grubbström (Grubba)  "module":lambda(string arg, string currentfile, int line) { classM=descM=nowM=moduleM=focM(parse,stripws(arg),format_line(currentfile,line));
d93b4b2002-12-05Henrik Grubbström (Grubba)  methodM=0; if (!nowM->classes) nowM->classes=(["_order":({})]); if (!nowM->modules) nowM->modules=(["_order":({})]);
048ff92011-11-18Henrik Grubbström (Grubba)  report(.FLAG_VERBOSE,currentfile,line,"module "+arg); }, "class":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!moduleM) return complain("class w/o module");
048ff92011-11-18Henrik Grubbström (Grubba)  descM=nowM=classM=focM(moduleM->classes,stripws(arg),format_line(currentfile,line)); methodM=0; report(.FLAG_VERBOSE,currentfile,line,"class "+arg); }, "submodule":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!moduleM) return complain("submodule w/o module");
048ff92011-11-18Henrik Grubbström (Grubba)  classM=descM=nowM=moduleM=focM(moduleM->modules,stripws(arg),format_line(currentfile,line));
d93b4b2002-12-05Henrik Grubbström (Grubba)  methodM=0; if (!nowM->classes) nowM->classes=(["_order":({})]); if (!nowM->modules) nowM->modules=(["_order":({})]);
048ff92011-11-18Henrik Grubbström (Grubba)  report(.FLAG_VERBOSE,currentfile,line,"submodule "+arg); }, "method":lambda(string arg, string currentfile, int line)
1bc5652012-05-06Henrik Grubbström (Grubba)  { arg = stripws(arg); if (!sizeof(arg)) return ""; if (!classM) return complain("method w/o class");
d93b4b2002-12-05Henrik Grubbström (Grubba)  if (!nowM || methodM!=nowM || methodM->desc || methodM->args || descM==methodM) { if (!classM->methods) classM->methods=({});
048ff92011-11-18Henrik Grubbström (Grubba)  classM->methods+=({methodM=nowM=(["decl":({}),"_line":format_line(currentfile,line)])}); }
7868692011-11-18Henrik Grubbström (Grubba)  methodM->decl+=({parse_decl(arg)}); descM=0; },
1bc5652012-05-06Henrik Grubbström (Grubba)  "function":lambda(string arg, string currentfile, int line) { // Function in a (sub-)module (as opposed to in a class). arg = stripws(arg); if (!sizeof(arg)) return ""; if (!moduleM) return ""; // Pop the current class. classM = moduleM; if (!nowM || methodM!=nowM || methodM->desc || methodM->args || descM==methodM) { if (!moduleM->methods) moduleM->methods=({}); moduleM->methods+=({methodM=nowM=(["decl":({}),"_line":format_line(currentfile,line)])}); } methodM->decl+=({parse_decl(arg)}); descM=0; },
048ff92011-11-18Henrik Grubbström (Grubba)  "inherits":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!nowM) return complain("inherits w/o class or module"); if (nowM != classM) return complain("inherits outside class or module"); if (!classM->inherits) classM->inherits=({}); classM->inherits+=({stripws(arg)}); },
048ff92011-11-18Henrik Grubbström (Grubba)  "variable":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!classM) return complain("variable w/o class"); if (!classM->variables) classM->variables=({});
048ff92011-11-18Henrik Grubbström (Grubba)  classM->variables+=({descM=nowM=(["_line":format_line(currentfile,line)])});
7868692011-11-18Henrik Grubbström (Grubba)  nowM->decl=({parse_decl(arg)});
d93b4b2002-12-05Henrik Grubbström (Grubba)  },
048ff92011-11-18Henrik Grubbström (Grubba)  "constant":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!classM) return complain("constant w/o class"); if (!classM->constants) classM->constants=({});
048ff92011-11-18Henrik Grubbström (Grubba)  classM->constants+=({descM=nowM=(["_line":format_line(currentfile,line)])});
7868692011-11-18Henrik Grubbström (Grubba)  nowM->decl=({parse_decl(arg)});
d93b4b2002-12-05Henrik Grubbström (Grubba)  },
048ff92011-11-18Henrik Grubbström (Grubba)  "arg":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!methodM) return complain("arg w/o method"); if (!methodM->args) methodM->args=({});
048ff92011-11-18Henrik Grubbström (Grubba)  methodM->args+=({argM=nowM=(["args":({}),"_line":format_line(currentfile,line)])});
d93b4b2002-12-05Henrik Grubbström (Grubba)  argM->args+=({arg}); descM=argM; },
048ff92011-11-18Henrik Grubbström (Grubba)  "note":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!lower_nowM()) return complain("note w/o method, class or module");
048ff92011-11-18Henrik Grubbström (Grubba)  descM=nowM->note||(nowM->note=(["_line":format_line(currentfile,line)]));
d93b4b2002-12-05Henrik Grubbström (Grubba)  },
048ff92011-11-18Henrik Grubbström (Grubba)  "added":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!lower_nowM()) return complain("added in: w/o method, class or module");
048ff92011-11-18Henrik Grubbström (Grubba)  descM=nowM->added||(nowM->added=(["_line":format_line(currentfile,line)]));
d93b4b2002-12-05Henrik Grubbström (Grubba)  },
048ff92011-11-18Henrik Grubbström (Grubba)  "bugs":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (!lower_nowM()) return complain("bugs w/o method, class or module");
048ff92011-11-18Henrik Grubbström (Grubba)  descM=nowM->bugs||(nowM->bugs=(["_line":format_line(currentfile,line)]));
d93b4b2002-12-05Henrik Grubbström (Grubba)  },
048ff92011-11-18Henrik Grubbström (Grubba)  "see":lambda(string arg, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { if (arg[0..3]!="also") return complain("see w/o 'also:'\n"); if (!lower_nowM()) return complain("see also w/o method, class or module"); sscanf(arg,"also%*[:]%s",arg);
00f4b62011-11-18Henrik Grubbström (Grubba)  nowM["see also"]+=map(arg/",",stripws)-({""});
d93b4b2002-12-05Henrik Grubbström (Grubba)  if (!nowM["see also"]) return complain("empty see also\n"); }, "returns":lambda(string arg) { if (!methodM) return complain("returns w/o method"); methodM->returns=stripws(arg); descM=0; nowM=0; } ]); string getridoftabs(string s) { string res=""; while (sscanf(s,"%s\t%s",string a,s)==2) { res+=a;
ead9722003-01-20Martin Nilsson  res+=" "[(sizeof(res)%8)..7];
d93b4b2002-12-05Henrik Grubbström (Grubba)  } return res+s; } string htmlify(string s) { #define HTMLIFY(S) \ (replace((S),({"&lt;","&gt;",">","&","\240"}),({"&lt;","&gt;","&gt;","&amp;"," "}))) string t="",u,v; while (sscanf(s,"%s<%s>%s",u,v,s)==3) t+=HTMLIFY(u)+"<"+v+">"; return t+HTMLIFY(s); } #define linkify(S) \ ("\""+replace((S),({"->","()","&lt;","&gt;"}),({".","","<",">"}))+"\"") string make_nice_reference(string what,string prefix,string stuff) { string q;
8a531a2006-11-04Martin Nilsson  if (what==prefix[sizeof(prefix)-sizeof(what)-2..<2])
d93b4b2002-12-05Henrik Grubbström (Grubba)  {
8a531a2006-11-04Martin Nilsson  q=prefix[..<2];
d93b4b2002-12-05Henrik Grubbström (Grubba)  }
8a531a2006-11-04Martin Nilsson  else if (what==prefix[sizeof(prefix)-sizeof(what)-1..<1])
d93b4b2002-12-05Henrik Grubbström (Grubba)  {
8a531a2006-11-04Martin Nilsson  q=prefix[..<1];
d93b4b2002-12-05Henrik Grubbström (Grubba)  } else if (search(what,".")==-1 && search(what,"->")==-1 && !parse[what]) { q=prefix+what; }
3524712015-05-26Martin Nilsson  else
d93b4b2002-12-05Henrik Grubbström (Grubba)  q=what; return "<ref to="+linkify(q)+">"+htmlify(stuff)+"</ref>"; }
523e3e2011-11-11Henrik Grubbström (Grubba) // Mapping from tag to their required parent tag. constant dtd_nesting = ([ "dt":"dl", "dd":"dl", "tr":"table", "td":"tr", "th":"tr", ]);
c8866e2011-11-18Henrik Grubbström (Grubba) constant self_terminating = (< "br", "hr", "wbr" >);
523e3e2011-11-11Henrik Grubbström (Grubba)  ADT.Stack nesting; array(string) pop_to_tag(string tag) { array(string) res = ({}); string top; while ((top = nesting->top()) && (top != tag)) { res += ({ "</" + top + ">" }); nesting->pop(); }
c8866e2011-11-18Henrik Grubbström (Grubba)  if (!top && tag) {
523e3e2011-11-11Henrik Grubbström (Grubba)  error("Missing container tag %O\n", tag); } return res; } array(string) fix_tag_nesting(Parser.HTML p, string value) { // werror("fix_nesting(%O, %O)\n", p, value); if ((nesting->top() == "pre") && !has_prefix(value, "</pre>")) { return ({ _Roxen.html_encode_string(value) }); }
387c6d2012-01-19Henrik Grubbström (Grubba)  string orig_value = value; value = lower_case(value);
523e3e2011-11-11Henrik Grubbström (Grubba)  string tag = p->parse_tag_name(value[1..<1]); array(string) ret = ({}); if (has_prefix(tag, "/")) { // End tag. Pop to starttag.
e863f92011-11-16Henrik Grubbström (Grubba)  tag = tag[1..];
f533ba2018-03-13Henrik Grubbström (Grubba)  if (!has_value(nesting, tag)) {
e863f92011-11-16Henrik Grubbström (Grubba)  // Extraneous end-tag -- remove it. return ({""}); } ret = pop_to_tag(tag);
523e3e2011-11-11Henrik Grubbström (Grubba)  nesting->pop();
9e86032011-11-21Henrik Grubbström (Grubba)  } else if (!sizeof(tag) || has_value(tag, "(") || has_value(tag, ")")) { // Insufficient quoting of paired < and >.
387c6d2012-01-19Henrik Grubbström (Grubba)  return ({ _Roxen.html_encode_string(orig_value) });
523e3e2011-11-11Henrik Grubbström (Grubba)  } else { if (dtd_nesting[tag]) {
c8866e2011-11-18Henrik Grubbström (Grubba)  if (has_value(nesting, dtd_nesting[tag])) { ret = pop_to_tag(dtd_nesting[tag]); } else { // Surrounding tag is missing. Add it. nesting->push(dtd_nesting[tag]); ret += ({ "<" + dtd_nesting[tag] + ">" }); }
523e3e2011-11-11Henrik Grubbström (Grubba)  }
0494772012-01-19Henrik Grubbström (Grubba)  if (has_suffix(value, "/>")) {
523e3e2011-11-11Henrik Grubbström (Grubba)  // Self-terminating tag. } else if (self_terminating[tag]) { value = value[..<1] + " />";
e863f92011-11-16Henrik Grubbström (Grubba)  } else if (nesting->top() == tag) { // Probably a typo. Convert to a close tag. nesting->pop(); value = "</" + value[1..];
523e3e2011-11-11Henrik Grubbström (Grubba)  } else { nesting->push(tag); } } ret += ({ value }); return ret; }
6d36ff2011-11-16Henrik Grubbström (Grubba) .Flags flags;
523e3e2011-11-11Henrik Grubbström (Grubba) Parser.HTML nesting_parser;
d93b4b2002-12-05Henrik Grubbström (Grubba) Parser.HTML parser; string fixdesc(string s,string prefix,void|string where) { s = stripws(replace(s, "<p>", "\n"));
e863f92011-11-16Henrik Grubbström (Grubba)  // Take care of some special cases (shifts and arrows): s = replace(s, ({ "<<", ">>", "<->", "<=>", "<-", "->", "<=", "=>", "<0", "<1", "<2", "<3", "<4", "<5", "<6", "<7", "<8", "<9",
713eeb2011-11-22Henrik Grubbström (Grubba)  "'<'", "'>'", "\"<\"", "\">\"",
e863f92011-11-16Henrik Grubbström (Grubba)  }), ({ "&lt;&lt;", "&gt;&gt;", "&lt;-&gt;", "&lt;=&gt;", "&lt;-", "-&gt;", "&lt;=", "=&gt;", "&lt;0", "&lt;1", "&lt;2", "&lt;3", "&lt;4", "&lt;5", "&lt;6", "&lt;7", "&lt;8", "&lt;9",
713eeb2011-11-22Henrik Grubbström (Grubba)  "'&lt;'", "'&gt;'", "\"&lt;\"", "\"&gt;\"",
e863f92011-11-16Henrik Grubbström (Grubba)  }));
1197492012-01-19Henrik Grubbström (Grubba)  parser->set_extra(where); s = parser->finish(s)->read(); s = "<p>" + (s/"\n\n")*"</p>\n\n<p>" + "</p>";
523e3e2011-11-11Henrik Grubbström (Grubba)  nesting = ADT.Stack(); nesting->push(0); // End sentinel. nesting_parser->set_extra(where);
c8866e2011-11-18Henrik Grubbström (Grubba)  s = nesting_parser->finish(s)->read() + pop_to_tag(UNDEFINED) * "";
523e3e2011-11-11Henrik Grubbström (Grubba) 
d93b4b2002-12-05Henrik Grubbström (Grubba)  s = htmlify(s);
6d36ff2011-11-16Henrik Grubbström (Grubba)  if (where && !(flags & .FLAG_NO_DYNAMIC))
d93b4b2002-12-05Henrik Grubbström (Grubba)  return "<source-position " + where + "/>\n"+s; return s; }
7868692011-11-18Henrik Grubbström (Grubba) multiset(string) get_method_names(array(array(string)) decls)
d93b4b2002-12-05Henrik Grubbström (Grubba) { multiset(string) names=(<>);
7868692011-11-18Henrik Grubbström (Grubba)  foreach (decls, array(string) decl)
d93b4b2002-12-05Henrik Grubbström (Grubba)  {
7868692011-11-18Henrik Grubbström (Grubba)  names[decl[1]] = 1;
d93b4b2002-12-05Henrik Grubbström (Grubba)  } return names; } array(string) nice_order(array(string) arr) { sort(map(arr,replace,({"_","`"}),({"ÿ","þ"})), arr); return arr; } string addprefix(string suffix,string prefix) { return prefix+suffix; } #define S(X) ("'"+(X)+"'") /* XML arg quote */ string doctype(string type,void|string indent) { array(string) endparan(string in) { int i; int q=1;
ead9722003-01-20Martin Nilsson  for (i=0; i<sizeof(in); i++)
d93b4b2002-12-05Henrik Grubbström (Grubba)  switch (in[i]) { case '(': q++; break; case ')': q--; if (!q) return ({in[..i-1],in[i+1..]}); break; } return ({in,""}); }; string combine_or(string a,string b) {
8ff89d2016-07-04Martin Nilsson  b = String.trim(b);
8a531a2006-11-04Martin Nilsson  if (b[..3]=="<or>") b=b[4..<5];
d93b4b2002-12-05Henrik Grubbström (Grubba)  return "<or>"+a+b+"</or>"; }; array(string) paramlist(string in,string indent) { int i; int q=0; array res=({});
ead9722003-01-20Martin Nilsson  for (i=0; i<sizeof(in); i++)
d93b4b2002-12-05Henrik Grubbström (Grubba)  switch (in[i]) { case '(': q++; break; case ')': q--; break; case ':': case ',': if (!q) return ({doctype(in[..i-1],indent+" ")})+ paramlist(in[i+1..],indent); } return ({doctype(in,indent+" ")}); }; if (!indent) indent="\n "; string nindent=indent+" "; if (type[..2]=="...") return nindent+"<varargs>"+doctype(type[3..])+"</varargs>"; string a=type,b=0,c,o=0; sscanf(type,"%s(%s",a,b); if (b) [b,c]=endparan(b); if (sscanf(a,"%s|%s",string d,string e)==2) { if (b) e+="("+b+")"+c; return nindent+combine_or(doctype(d,nindent), doctype(e,nindent)); } if (b && c!="" && sscanf(c,"%s|%s",string d,string e)==2) return nindent+combine_or(doctype(a+"("+b+")"+d,nindent), doctype(e,nindent)); switch (a) { case "int": case "float": case "string": case "void": case "program": case "array": case "mapping": case "multiset": case "function": case "object": case "mixed": if (!b) return "<"+a+"/>"; break; } switch (a) { case "array": return nindent+"<array><valuetype>"+ doctype(b,nindent)+"</valuetype></array>"; case "multiset": return nindent+"<multiset><indextype>"+ doctype(b,nindent)+"</indextype></multiset>"; case "mapping": array z=paramlist(b,nindent); if (sizeof(z)!=2) werror("warning: confused mapping type: %O\n",type), z+=({"<mixed/>","<mixed/>"}); return nindent+"<mapping><indextype>"+z[0]+"</indextype>"+ nindent+" <valuetype>"+z[1]+"</valuetype></mapping>"; case "object": return nindent+"<object>"+b+"</object>"; case "function": z=paramlist(b,nindent); if (sizeof(z)<1) werror("warning: confused function type: %O\n",type), z+=({"<mixed/>"}); return nindent+ "<function>"+
8a531a2006-11-04Martin Nilsson  map(z[..<1],
d93b4b2002-12-05Henrik Grubbström (Grubba)  lambda(string s) { return nindent+" <argtype>"+s+"</argtype>"; })*""+ nindent+" <returntype>"+z[-1]+"</returntype>"+ nindent+"</function>"; } if (b && a=="int") { if (sscanf(b,"%d..%d",int min,int max)==2) return nindent+"<int><min>"+min+"</min><max>"+max+"</max></int>"; if (sscanf(b,"..%d",int max)==1) return nindent+"<int><max>"+max+"</max></int>";
505d5e2011-12-03Henrik Grubbström (Grubba)  if (sscanf(b,"%d..",int min)==1)
d93b4b2002-12-05Henrik Grubbström (Grubba)  return nindent+"<int><min>"+min+"</min></int>"; } if (b) werror("warning: confused type: %O\n",type); return nindent+"<object>"+type+"</object>"; } constant convname= ([ "`>":"`&gt;", "`<":"`&lt;", "`>=":"`&gt;=", "`<=":"`&lt;=", "`&":"`&amp;", ]);
7868692011-11-18Henrik Grubbström (Grubba) array(string) parse_decl(string raw_decl) { string rv,name,params=0; array tokens = Parser.Pike.split(replace(raw_decl, ({ "&lt;", "&gt;" }), ({ "<", ">"}))); tokens = Parser.Pike.tokenize(tokens); tokens = (tokens/({"="}))[0]; // Handle constants. tokens = Parser.Pike.group(tokens); tokens = Parser.Pike.hide_whitespaces(tokens); if (tokens[-1] == ";") { tokens = tokens[..<1]; } if (arrayp(tokens[-1])) { params = Parser.Pike.simple_reconstitute(tokens[-1]); tokens = tokens[..<1]; } name = objectp(tokens[-1])?tokens[-1]->text:tokens[-1]; rv = "mixed"; if (sizeof(tokens) > 1) { rv = Parser.Pike.simple_reconstitute(tokens[..<1]); } if (params) { return ({ rv, name, params }); } return ({ rv, name }); }
d93b4b2002-12-05Henrik Grubbström (Grubba) void docdecl(string enttype,
7868692011-11-18Henrik Grubbström (Grubba)  array(string) decl,
d93b4b2002-12-05Henrik Grubbström (Grubba)  object f) { string rv,name,params=0;
7868692011-11-18Henrik Grubbström (Grubba)  rv = decl[0]; name = decl[1]; if (sizeof(decl) == 3) params = decl[2][1..]; #if 0
d93b4b2002-12-05Henrik Grubbström (Grubba)  sscanf(decl,"%s %s(%s",rv,name,params) == 3 || sscanf(decl+"\n","%s %s\n",rv,name);
05f5e12003-11-06Henrik Grubbström (Grubba)  if (name == "`" && params && has_prefix(params, ")")) { name = "`()"; sscanf(params[1..], "%*s(%s", params); }
7868692011-11-18Henrik Grubbström (Grubba) #endif
05f5e12003-11-06Henrik Grubbström (Grubba) 
d93b4b2002-12-05Henrik Grubbström (Grubba)  if (convname[name]) name=convname[name]; f->write("<"+enttype+" name="+S(name)+">"); if (params) { string paramlist(string in) { int i; string res = ""; while(i<sizeof(in)) { // Find type string t = ""; int br; for (; i<sizeof(in); i++) { t += in[i..i]; if(in[i]=='(') br++; if(in[i]==')') br--; if(in[i]==' ' && !br) {
8a531a2006-11-04Martin Nilsson  t = doctype(t[..<1]);
d93b4b2002-12-05Henrik Grubbström (Grubba)  break; } if(br==-1 || (in[i]==',' && !br)) {
8ff89d2016-07-04Martin Nilsson  if(String.trim(t)==")")
d93b4b2002-12-05Henrik Grubbström (Grubba)  return res;
8ff89d2016-07-04Martin Nilsson  if(String.trim(t[..<1])=="void" && res=="")
d93b4b2002-12-05Henrik Grubbström (Grubba)  return "<argument/>\n"; if(t[-1]==')')
8a531a2006-11-04Martin Nilsson  return res += "<argument><value>" + t[..<1] + "</value></argument>";
d93b4b2002-12-05Henrik Grubbström (Grubba)  if(t[-1]==',') break; } } if(t[-1]==',') {
8a531a2006-11-04Martin Nilsson  res += "<argument><value>" + t[..<1] + "</value></argument>";
d93b4b2002-12-05Henrik Grubbström (Grubba)  i++; continue; } // Find name string n = ""; i++; for (; i<sizeof(in); i++) { if(in[i]==')') {
8ff89d2016-07-04Martin Nilsson  if(!sizeof(String.trim(n)))
d93b4b2002-12-05Henrik Grubbström (Grubba)  throw( ({ "Empty argument name. ("+in+")\n", backtrace() }) ); return res + "<argument name=" + S(n) + "><type>" + t + "</type></argument>\n"; } if(in[i]==',') {
8ff89d2016-07-04Martin Nilsson  if(!sizeof(String.trim(n)))
d93b4b2002-12-05Henrik Grubbström (Grubba)  throw( ({ "Empty argument name. ("+in+")\n", backtrace() }) ); res += "<argument name=" + S(n) + "><type>" + t + "</type></argument>\n"; break; } if(in[i]==' ') { if(n=="...") { n = ""; t = "<varargs>" + t + "</varargs>"; } } else n += in[i..i]; } i++; } throw( ({ "Malformed argument list \"(" + in + "\".\n", backtrace() }) ); }; f->write("\n <returntype>"+doctype(rv,"\n ")+"</returntype>\n" " <arguments>"+paramlist(params)+"\n </arguments>\n"); }
0a26712011-11-18Henrik Grubbström (Grubba)  else if (enttype == "variable") { f->write("<type>"+doctype(rv)+"</type>\n"); }
d93b4b2002-12-05Henrik Grubbström (Grubba)  else { f->write("<typevalue>"+doctype(rv)+"</typevalue>\n"); } f->write("</"+enttype+">"); } void document(string enttype, mapping huh,string name,string prefix,
048ff92011-11-18Henrik Grubbström (Grubba)  object f, string currentfile, int line)
d93b4b2002-12-05Henrik Grubbström (Grubba) { int(0..1) has_doc; array(string) names;
048ff92011-11-18Henrik Grubbström (Grubba)  if (huh->_line) { sscanf(huh->_line, "file='%s' first-line='%d'", currentfile, line); }
d93b4b2002-12-05Henrik Grubbström (Grubba)  if (huh->names) names=map(indices(huh->names),addprefix,name); else names=({name});
048ff92011-11-18Henrik Grubbström (Grubba)  report(.FLAG_VERBOSE,currentfile,line,name+" : "+names*",");
d93b4b2002-12-05Henrik Grubbström (Grubba)  array v=name/"."; string canname=v[-1]; sscanf(canname,"%s->",canname); sscanf(canname,"%s()",canname); string presname = replace(sort(names)[0], ([ ".":"_", ">":"_" ]) ); if (convname[canname]) canname=convname[canname]; switch (enttype) {
c75acb2012-02-11Henrik Grubbström (Grubba)  case "appendix": f->write("<"+enttype+" name="+S(name)+">\n"); break;
d93b4b2002-12-05Henrik Grubbström (Grubba)  case "class": case "module": f->write("<"+enttype+" name="+S(canname)+">\n");
d4db092012-05-04Henrik Grubbström (Grubba)  if (huh->inherits) { foreach(huh->inherits, string inh) { string name = (inh/"::")[-1]; name = (name/".")[-1]; f->write(sprintf("<docgroup homogen-name='%s'" " homogen-type='inherit'>\n" "<inherit name='%s'>" "<classname>%s</classname>" "</inherit>\n" "</docgroup>\n", name, name, inh)); } }
d93b4b2002-12-05Henrik Grubbström (Grubba)  break; default: f->write("<docgroup homogen-type="+S(enttype));
e01fa42003-03-31Martin Nilsson  if(huh->decl && sizeof(names)==1) {
d93b4b2002-12-05Henrik Grubbström (Grubba)  lambda() { string m,n;
7868692011-11-18Henrik Grubbström (Grubba)  foreach(huh->decl, array(string) decl) { n = decl[1];
d93b4b2002-12-05Henrik Grubbström (Grubba)  if(!m) { m=n; continue; } if(n!=m) return; } if(convname[m]) m=convname[m]; f->write(" homogen-name="+S(m)); }(); } f->write(">\n"); if (huh->decl) {
7868692011-11-18Henrik Grubbström (Grubba)  foreach (huh->decl, array(string) decl)
d93b4b2002-12-05Henrik Grubbström (Grubba)  docdecl(enttype,decl,f); } else foreach (names,string name) { if (convname[name]) name=convname[name]; f->write("<"+enttype+" name="+S(name)+">\n"); f->write("</"+enttype+">"); } break; }
6d36ff2011-11-16Henrik Grubbström (Grubba)  if (!(flags & .FLAG_NO_DYNAMIC)) f->write("<source-position " + huh->_line + "/>\n");
d93b4b2002-12-05Henrik Grubbström (Grubba)  // [DESCRIPTION] string res=""; if (huh->desc) { res+="<text>\n"; res+=fixdesc(huh->desc,prefix,huh->_line)+"\n"; res+="</text>\n"; } // [ARGUMENTS] if (huh->args) { mapping arg; array(string) v = ({}); foreach (huh->args, arg) { v += arg->args; if (arg->desc) { res+="<group>\n"; foreach (v,string arg) { sscanf(arg,"%*s %s",arg); sscanf(arg,"%s(%*s",arg); // type name(whatever) res+=" <param name="+S(arg)+"/>\n"; } res+= "<text>"+ fixdesc(arg->desc,prefix,arg->_line)+ "</text></group>\n"; v = ({}); } } if(sizeof(v)) werror("Parameters without description on line %O.\n%O\n", arg->_line, v); } // [RETURN VALUE] if (huh->returns) { res+="<group><returns/><text>\n"; res+=fixdesc(huh->returns,prefix,huh->_line)+"\n"; res+="</text></group>\n"; } // [NOTE] if (huh->note && huh->note->desc) { res+="<group><note/><text>\n"; res+=fixdesc(huh->note->desc,prefix,huh->_line)+"\n"; res+="</text></group>\n"; } // [BUGS] if (huh->bugs && huh->bugs->desc) { res+="<group><bugs/><text>\n"; res+=fixdesc(huh->bugs->desc,prefix,huh->_line)+"\n"; res+="</text></group>\n"; } // [ADDED] if (huh->added && huh->added->desc) { /* noop */ } // [SEE ALSO] if (huh["see also"]) { res+="<group><seealso/><text>\n"; res+=fixdesc( map(huh["see also"], lambda(string s) { return "<ref>"+htmlify(s)+"</ref>"; })*", ", prefix,0); res+="</text></group>\n"; } if (res!="") { has_doc = 1; f->write("<doc>\n"+res+"\n</doc>\n"); } // ---childs---- if (huh->constants) { foreach(huh->constants,mapping m) {
7868692011-11-18Henrik Grubbström (Grubba)  string type = m->decl[0][0]; string name = m->decl[0][1]; document("constant",m,prefix+name,prefix+name+".",f,currentfile,line);
d93b4b2002-12-05Henrik Grubbström (Grubba)  } } if (huh->variables) { foreach(huh->variables,mapping m) {
7868692011-11-18Henrik Grubbström (Grubba)  string type = m->decl[0][0]; string name = m->decl[0][1]; document("variable",m,prefix+name,prefix+name+".",f,currentfile,line);
d93b4b2002-12-05Henrik Grubbström (Grubba)  } } if (huh->methods) { // postprocess methods to get names multiset(string) method_names=(<>); array(string) method_names_arr; string method_name; mapping method;
3524712015-05-26Martin Nilsson  if (huh->methods)
d93b4b2002-12-05Henrik Grubbström (Grubba)  foreach (huh->methods,method) method_names|=(method->names=get_method_names(method->decl)); method_names_arr=nice_order(indices(method_names)); // alphabetically foreach (method_names_arr,method_name) if (method_names[method_name]) { // find it foreach (huh->methods,method) if ( method->names[method_name] ) {
048ff92011-11-18Henrik Grubbström (Grubba)  document("method",method,prefix,prefix,f,currentfile,line);
d93b4b2002-12-05Henrik Grubbström (Grubba)  method_names-=method->names; } if (method_names[method_name])
334e872003-03-12Marcus Agehall  werror("failed to find "+method_name+" again, weird...\n");
d93b4b2002-12-05Henrik Grubbström (Grubba)  } } if (huh->classes) { foreach(huh->classes->_order,string n) { // f->write("\n\n\n<section title=\""+prefix+n+"\">\n"); document("class",huh->classes[n],
048ff92011-11-18Henrik Grubbström (Grubba)  prefix+n,prefix+n+"->",f,currentfile,line);
d93b4b2002-12-05Henrik Grubbström (Grubba) // f->write("</section title=\""+prefix+n+"\">\n"); } } if (huh->modules) { foreach(huh->modules->_order,string n) { document("module",huh->modules[n],
048ff92011-11-18Henrik Grubbström (Grubba)  prefix+n,prefix+n+".",f,currentfile,line);
d93b4b2002-12-05Henrik Grubbström (Grubba)  } } // end ANCHOR switch (enttype) {
c75acb2012-02-11Henrik Grubbström (Grubba)  case "appendix":
d93b4b2002-12-05Henrik Grubbström (Grubba)  case "class": case "module": f->write("</"+enttype+">\n\n"); break; default: if(!has_doc) f->write("<doc/>"); f->write("</docgroup>\n\n"); break; } }
ac1e4f2002-12-12Henrik Grubbström (Grubba) string make_doc_files(string builddir, string imgdest, string|void namespace)
d93b4b2002-12-05Henrik Grubbström (Grubba) {
c40b9d2002-12-19Henrik Grubbström (Grubba)  if (verbosity > 0) werror("modules: " +
c75acb2012-02-11Henrik Grubbström (Grubba)  sort(indices(parse)-({" appendix"}))*", " +
c40b9d2002-12-19Henrik Grubbström (Grubba)  "\n");
ac1e4f2002-12-12Henrik Grubbström (Grubba)  namespace = namespace || "predef::"; if (has_suffix(namespace, "::")) {
8a531a2006-11-04Martin Nilsson  namespace = namespace[..<2];
ac1e4f2002-12-12Henrik Grubbström (Grubba)  }
d93b4b2002-12-05Henrik Grubbström (Grubba) 
96eb282002-12-12Henrik Grubbström (Grubba)  object f = class {
ac1e4f2002-12-12Henrik Grubbström (Grubba)  string doc = ""; int write(string in) {
d93b4b2002-12-05Henrik Grubbström (Grubba)  doc += in; return sizeof(in);
ac1e4f2002-12-12Henrik Grubbström (Grubba)  } string read() {
19d0a32012-01-29Henrik Grubbström (Grubba)  return string_to_utf8("<?xml version='1.0' encoding='utf-8'?>\n"
3650052015-09-17Henrik Grubbström (Grubba)  "<autodoc>\n" + string_to_utf8(doc) + "</autodoc>\n");
ac1e4f2002-12-12Henrik Grubbström (Grubba)  }
96eb282002-12-12Henrik Grubbström (Grubba)  }();
d93b4b2002-12-05Henrik Grubbström (Grubba) 
ae0bbf2011-11-11Henrik Grubbström (Grubba)  string here = getcwd(); cd(builddir); mixed err = catch { // Module documentation exists in a namespace... f->write("<namespace name='" + namespace + "'>\n");
c75acb2012-02-11Henrik Grubbström (Grubba)  foreach (sort(indices(parse)-({"_order", " appendix"})),string module)
048ff92011-11-18Henrik Grubbström (Grubba)  document("module",parse[module],module,module+".", f, "-", 1);
ae0bbf2011-11-11Henrik Grubbström (Grubba)  f->write("</namespace>\n"); };
d93b4b2002-12-05Henrik Grubbström (Grubba) 
c75acb2012-02-11Henrik Grubbström (Grubba)  // But appendices do not. if(appendixM) foreach(parse[" appendix"]->_order, string title) document("appendix",parse[" appendix"][title],title,"", f, "-", 1);
d93b4b2002-12-05Henrik Grubbström (Grubba)  cd(here);
ae0bbf2011-11-11Henrik Grubbström (Grubba)  if (err) throw(err); string autodoc = f->read(); err = catch {
6d36ff2011-11-16Henrik Grubbström (Grubba)  return Tools.AutoDoc.ProcessXML.moveImages(autodoc, builddir, imgdest, (flags & .FLAG_VERB_MASK) < .FLAG_VERBOSE);
ae0bbf2011-11-11Henrik Grubbström (Grubba)  }; throw(err);
d93b4b2002-12-05Henrik Grubbström (Grubba) } void process_line(string s,string currentfile,int line) { s=getridoftabs(s); int i;
db5b212002-12-05Henrik Grubbström (Grubba)  if ((i=search(s,"**""!"))!=-1 || (i=search(s,"//""!"))!=-1)
d93b4b2002-12-05Henrik Grubbström (Grubba)  { string kw,arg; sscanf(s[i+3..],"%*[ \t]%[^: \t\n\r]%*[: \t]%s",kw,arg); if (keywords[kw]) { string err;
048ff92011-11-18Henrik Grubbström (Grubba)  if ( (err=keywords[kw](arg,currentfile,line)) )
d93b4b2002-12-05Henrik Grubbström (Grubba)  {
f63d102011-11-18Henrik Grubbström (Grubba)  if (sizeof(err)) { report(.FLAG_QUIET, currentfile, line, "process_line failed: %O", err); if (!(flags & .FLAG_KEEP_GOING)) error("process_line failed: %O\n", err); } } else return;
d93b4b2002-12-05Henrik Grubbström (Grubba)  }
f63d102011-11-18Henrik Grubbström (Grubba)  if (s[i+3..]!="")
d93b4b2002-12-05Henrik Grubbström (Grubba)  { string d=s[i+3..]; // sscanf(d,"%*[ \t]!%s",d);
048ff92011-11-18Henrik Grubbström (Grubba)  // if (search(s,"$""Id")!=-1) // report(.FLAG_VERBOSE,currentfile,line,"Id: "+d);
d93b4b2002-12-05Henrik Grubbström (Grubba)  if (!descM) descM=methodM; if (!descM) {
048ff92011-11-18Henrik Grubbström (Grubba)  report(.FLAG_NORMAL, currentfile, line, "illegal description position.");
ae0bbf2011-11-11Henrik Grubbström (Grubba)  //error("process_line failed: Illegal description position.\n"); return;
d93b4b2002-12-05Henrik Grubbström (Grubba)  } if (!descM->desc) descM->desc=""; else descM->desc+="\n"; d=getridoftabs(d); descM->desc+=d; } else if (descM) { if (!descM->desc) descM->desc=""; else descM->desc+="\n"; } } } string safe_newlines(string in) { string old; do { old = in; in = replace(in, "\n\n", "\n \n"); } while(old!=in); return in; }
9ecfbe2011-11-28Henrik Grubbström (Grubba) string low_container(string tag, mapping(string:string) attrs, string|void c) { string res = "<" + tag; foreach(sort(indices(attrs)), string attr) { res += " " + attr + "='" + attrs[attr] + "'"; } if (c == "") return res + " />"; res += ">"; if (c) res += c + "</" + tag + ">"; return res; }
d93b4b2002-12-05Henrik Grubbström (Grubba) array(string) tag_quote_args(Parser.HTML p, mapping args) {
9ecfbe2011-11-28Henrik Grubbström (Grubba)  return ({ low_container(p->tag_name(), args) });
d93b4b2002-12-05Henrik Grubbström (Grubba) } array(string) tag_preserve_ws(Parser.HTML p, mapping args, string c) {
9ecfbe2011-11-28Henrik Grubbström (Grubba)  return ({ low_container(p->tag_name(), args, safe_newlines(p->clone()->finish(c)->read())) });
d93b4b2002-12-05Henrik Grubbström (Grubba) }
1ee3352011-11-16Henrik Grubbström (Grubba) class CompilationHandler
8640032011-11-11Henrik Grubbström (Grubba) {
1ee3352011-11-16Henrik Grubbström (Grubba)  array(string) lines = ({}); void compile_warning(string filename, int linenumber, string message) { lines += ({ sprintf("%s:%d:%s\n", filename, linenumber, message) }); } void compile_error(string filename, int linenumber, string message) { lines += ({ sprintf("%s:%d:%s\n", filename, linenumber, message) }); } }
68d87e2011-11-26Henrik Grubbström (Grubba) array(string) make_illustration(array(string) templates, string illustration_code, string where, string name, int verbosity, string type)
1ee3352011-11-16Henrik Grubbström (Grubba) { CompilationHandler handler; string code;
8640032011-11-11Henrik Grubbström (Grubba)  mixed err; string defines = sprintf("#define IMAGE_DIR %O\n", IMAGE_DIR);
68d87e2011-11-26Henrik Grubbström (Grubba)  program ip; foreach(reverse(templates); int t; string template) { if (!(flags & .FLAG_COMPAT) && ((t+1) != sizeof(templates))) {
8640032011-11-11Henrik Grubbström (Grubba)  continue; }
1ee3352011-11-16Henrik Grubbström (Grubba)  code = defines + template + illustration_code + "\n;\n}\n"; handler = CompilationHandler();
68d87e2011-11-26Henrik Grubbström (Grubba)  ip = UNDEFINED;
8640032011-11-11Henrik Grubbström (Grubba)  err = catch {
866ee92016-01-18Martin Nilsson  Random.Interface rnd = Random.Deterministic(0); add_constant("random", rnd->random); add_constant("random_string", rnd->random_string);
68d87e2011-11-26Henrik Grubbström (Grubba)  ip = compile_string(code, "-", handler);
866ee92016-01-18Martin Nilsson  object g = ip(name, verbosity, type);
68d87e2011-11-26Henrik Grubbström (Grubba)  return ({ g->make() });
8640032011-11-11Henrik Grubbström (Grubba)  }; }
68d87e2011-11-26Henrik Grubbström (Grubba)  werror("Illustration at %O failed:\n"
1ee3352011-11-16Henrik Grubbström (Grubba)  "%s\n" "******\n", where, handler->lines * ""); array(string) rows = code/"\n"; for(int i; i<sizeof(rows); i++) werror("%04d: %s\n", i+1, rows[i]); werror("******\n");
68d87e2011-11-26Henrik Grubbström (Grubba)  if (flags & .FLAG_KEEP_GOING) { if (ip) { werror("%s\n", describe_backtrace(err)); } return ({ "" }); // FIXME: Broken image? }
8640032011-11-11Henrik Grubbström (Grubba)  throw(err); }
6d36ff2011-11-16Henrik Grubbström (Grubba) void create(string image_dir, void|.Flags flags)
f136d42002-12-19Henrik Grubbström (Grubba) {
6d36ff2011-11-16Henrik Grubbström (Grubba)  verbosity = (flags & .FLAG_VERB_MASK);
8e06a32014-09-30Martin Nilsson  this::flags = flags;
8640032011-11-11Henrik Grubbström (Grubba)  IMAGE_DIR = image_dir;
d93b4b2002-12-05Henrik Grubbström (Grubba) 
523e3e2011-11-11Henrik Grubbström (Grubba)  nesting_parser = Parser.HTML(); nesting_parser->_set_tag_callback(fix_tag_nesting);
d93b4b2002-12-05Henrik Grubbström (Grubba)  parser = Parser.HTML(); Parser.HTML p = Parser.HTML(); parser->add_containers( ([ "pre":tag_preserve_ws, "table":tag_preserve_ws, "ul":tag_preserve_ws, "ol":tag_preserve_ws, ]) ); parser->add_container("li", lambda(Parser.HTML p, mapping m, string c) {
0494772012-01-19Henrik Grubbström (Grubba)  return "<group><item /><text>" + c + "</text></group>";
d93b4b2002-12-05Henrik Grubbström (Grubba)  }); parser->add_container("illustration", lambda(Parser.HTML p, mapping args, string c, string where) { c = replace(c, ([ "&gt;":">", "&lt;":"<" ])); string name; sscanf(where, "file='%s'", name); name = (name/"/")[-1];
68d87e2011-11-26Henrik Grubbström (Grubba)  return make_illustration(makepic, c, where, name + (illustration_counter++), verbosity, args->type);
d93b4b2002-12-05Henrik Grubbström (Grubba)  }); parser->add_container("execute", lambda(Parser.HTML p, mapping args, string c, string where) {
2778a82011-11-18Henrik Grubbström (Grubba)  c = replace(c, ([ "&gt;":">", "&lt;":"<", "&amp;":"&", // NB: src/modules/Image/layers.c had absolute paths... "/home/mirar/pike7/tutorial/":IMAGE_DIR, ])); // Repair some known typos in old versions. c = replace(c, ({ // src/modules/Image/layers.c:1.33 // Parenthesis/brace matching error. // The corresponding code is just longdesc at HEAD. "replace(longdesc,({\",\",\";\",\")\",({\",<wbr />\",\";<wbr />\",\")<wbr />\"}))))/", "\"<wbr />\"/1*({mktag(\"wbr\")})));", // src/modules/Image/layers.c:1.36 // longdesc still needs to be quoted. "mktag(\"td\",([\"align\":\"left\",\"valign\":\"center\"]),longdesc)", }), ({ "replace(longdesc, ({ \"<\",\">\",\"&\" }), ({\"&lt;\",\"&gt;\",\"&amp;\"}))", "));", "mktag(\"td\",([\"align\":\"left\",\"valign\":\"center\"]),replace(longdesc, ({ \"<\",\">\",\"&\" }), ({\"&lt;\",\"&gt;\",\"&amp;\"})))", }));
d93b4b2002-12-05Henrik Grubbström (Grubba)  string name; sscanf(where, "file='%s'", name); name = (name/"/")[-1]; array err; object g; err = catch {
866ee92016-01-18Martin Nilsson  Random.Interface rnd = Random.Deterministic(0); add_constant("random", rnd->random); add_constant("random_string", rnd->random_string);
d93b4b2002-12-05Henrik Grubbström (Grubba)  g = compile_string(execute + c) (illustration_counter, name);
866ee92016-01-18Martin Nilsson  g->main();
d93b4b2002-12-05Henrik Grubbström (Grubba)  }; if(err) { werror("%O\n", where); array rows = (execute+c)/"\n"; werror("******\n"); for(int i; i<sizeof(rows); i++)
1ee3352011-11-16Henrik Grubbström (Grubba)  werror("%04d: %s\n", i+1, rows[i]);
d93b4b2002-12-05Henrik Grubbström (Grubba)  werror("******\n"); throw(err); } illustration_counter = g->img_counter;
c8866e2011-11-18Henrik Grubbström (Grubba)  if (flags & .FLAG_COMPAT) { // NB: We may need to repair the output... nesting = ADT.Stack(); nesting->push(0); // End sentinel. nesting_parser->set_extra(where); return nesting_parser->finish(g->write->get())->read() + pop_to_tag(UNDEFINED) * ""; }
d93b4b2002-12-05Henrik Grubbström (Grubba)  return g->write->get(); }); parser->add_container("data_description", lambda(Parser.HTML p, mapping args, string c) {
2411cb2011-11-26Henrik Grubbström (Grubba)  string basetype = "mixed"; string subtype = "mixed"; sscanf(args->type, "%[a-z](%s)", basetype, subtype); switch(basetype) { case "mapping": {
d93b4b2002-12-05Henrik Grubbström (Grubba)  Parser.HTML i = Parser.HTML()-> add_container("elem", lambda(Parser.HTML p, mapping args, string c) {
2411cb2011-11-26Henrik Grubbström (Grubba)  if(!args->type && !args->name) { // Sub-heading: Note unbalanced tags! return "</mapping></p>\n<p><b>" + String.capitalize(c) + "</b><mapping>\n"; }
d93b4b2002-12-05Henrik Grubbström (Grubba)  if(!args->type) throw("mkxml: Type attribute missing on elem tag."); if(!args->name) throw("mkxml: Name attribute missing on elem tag.");
2411cb2011-11-26Henrik Grubbström (Grubba)  return "<group>\n<member><type>" + doctype(args->type) + "</type><index>\"" + args->name + "\"</index></member>\n"
d93b4b2002-12-05Henrik Grubbström (Grubba)  "<text><p>" + c + "</p></text>\n</group>\n"; }); return ({ "<mapping>\n " + safe_newlines(i->finish(c)->read()) + "</mapping>\n " }); }
2411cb2011-11-26Henrik Grubbström (Grubba)  case "array": { int index; Parser.HTML i = Parser.HTML()-> add_container("elem", lambda(Parser.HTML p, mapping args, string c) { if (args->value) { c = "<tt>" + args->value + "</tt>: " + c; } return ({ "<group>\n<elem><type>" + doctype(args->type || subtype) + "</type><index>" + index++ + "</index></elem>\n" "<text><p>" + c + "</p></text>\n" "</group>\n" }); }); return ({ "<array>\n " + safe_newlines(i->finish(c)->read()) + "</array>\n " }); } }
d93b4b2002-12-05Henrik Grubbström (Grubba)  throw("mkxml: Unknown data_description type "+args->type+".\n"); }); parser->add_tag("br",lambda(mixed...) { return ({"<br/>"}); }); parser->add_tag("wbr",lambda(mixed...) { return ({"<br/>"}); }); parser->add_tags( ([ "dl":tag_quote_args, "dt":tag_quote_args, "dd":tag_quote_args, "tr":tag_quote_args, "th":tag_quote_args, "td":tag_quote_args, "ref":tag_quote_args ]) ); parser->add_container( "text", lambda(Parser.HTML p,mapping args, string c) { c=p->clone()->finish(c)->read(); string res="<text><p>"+c+"</p></text>"; string t; do { t=res; res=replace(res,"<p></p>",""); res=replace(res,"<br/></p>","</p>"); } while (t!=res); return ({res}); }); parser->add_container("link", lambda(Parser.HTML p, mapping args, string c) {
9ecfbe2011-11-28Henrik Grubbström (Grubba)  return ({ low_container("ref", args, c) });
d93b4b2002-12-05Henrik Grubbström (Grubba)  }); parser->add_container("a", lambda(Parser.HTML p, mapping args, string c) {
9ecfbe2011-11-28Henrik Grubbström (Grubba)  return ({ low_container("url", args, c) });
d93b4b2002-12-05Henrik Grubbström (Grubba)  }); // Normalize IMAGE_DIR.
773c872002-12-05Henrik Grubbström (Grubba)  IMAGE_DIR = combine_path(getcwd(), IMAGE_DIR);
d93b4b2002-12-05Henrik Grubbström (Grubba)  if (!sizeof(IMAGE_DIR)) IMAGE_DIR="./"; else if (IMAGE_DIR[-1] != '/') IMAGE_DIR += "/"; execute = #" class Interceptor { string buffer = \"\"; void `()(string in) { buffer += in; } string get() { return buffer; } } Interceptor write = Interceptor(); int img_counter; string prefix; void create(int _img_counter, string _prefix) { img_counter = _img_counter; prefix = _prefix; }
68d87e2011-11-26Henrik Grubbström (Grubba)  string illustration(string|Image.Image img, mapping|object extra, void|string suffix) {
d93b4b2002-12-05Henrik Grubbström (Grubba)  string fn = prefix + \".\" + (img_counter++) + (suffix||\".png\");
68d87e2011-11-26Henrik Grubbström (Grubba)  if (objectp(extra)) extra = ([ \"alpha\":extra ]);
d93b4b2002-12-05Henrik Grubbström (Grubba) #if constant(Image.PNG.encode) if(!stringp(img))
68d87e2011-11-26Henrik Grubbström (Grubba)  img = Image.PNG.encode(img, extra);
f136d42002-12-19Henrik Grubbström (Grubba)  Stdio.write_file(fn, img);"+ ((verbosity > 1)?#" werror(\"Wrote %s from execute.\\n\", fn);":"") + #"
d93b4b2002-12-05Henrik Grubbström (Grubba) #endif return \"<image>\"+fn+\"</image>\"; }
2778a82011-11-18Henrik Grubbström (Grubba)  string illustration_jpeg(Image.Image img, mapping|void extra) {
d93b4b2002-12-05Henrik Grubbström (Grubba) #if constant(Image.JPEG.encode)
2778a82011-11-18Henrik Grubbström (Grubba)  return illustration(Image.JPEG.encode(img, extra||([])), extra, \".jpeg\");
d93b4b2002-12-05Henrik Grubbström (Grubba) #else return illustration(img, extra); #endif }
ff17962014-08-15Martin Nilsson  protected string low_mktag(string name, void|mapping args) {
d93b4b2002-12-05Henrik Grubbström (Grubba)  if(!args) args = ([]);
9ecfbe2011-11-28Henrik Grubbström (Grubba)  string res = \"<\" + name; foreach(sort(indices(args)), string attr) res += \" \" + attr + \"='\" + args[attr] + \"'\"; return res; } string mktag(string name, void|mapping args, void|string c) { string res = low_mktag(name, args);
d93b4b2002-12-05Henrik Grubbström (Grubba)  if(!c)
9ecfbe2011-11-28Henrik Grubbström (Grubba)  return res + \" />\"; return res + sprintf(\">%s</%s>\", c, name);
d93b4b2002-12-05Henrik Grubbström (Grubba)  } array(string) tag_stack = ({}); string begin_tag(string name, void|mapping args) { tag_stack += ({ name });
9ecfbe2011-11-28Henrik Grubbström (Grubba)  return low_mktag(name, args) + \">\";
d93b4b2002-12-05Henrik Grubbström (Grubba)  } string end_tag() { if(!sizeof(tag_stack)) throw( ({ \"Tag stack underflow.\\n\", backtrace() }) ); string name = tag_stack[-1];
8a531a2006-11-04Martin Nilsson  tag_stack = tag_stack[..<1];
d93b4b2002-12-05Henrik Grubbström (Grubba)  return \"</\" + name + \">\"; } string fix_image_path(string name) { return \"" + IMAGE_DIR + #"\" + name; }
2778a82011-11-18Henrik Grubbström (Grubba)  Image.Image load(string name) { if (!Stdio.exist(name)) name = fix_image_path(name); return Image.load(name); } Image.Layer load_layer(string name) { if (!Stdio.exist(name)) name = fix_image_path(name); return Image.load_layer(name); }
d93b4b2002-12-05Henrik Grubbström (Grubba) "; nowM = parse; }