0d03312003-08-24Martin Nilsson  #pike __REAL_VERSION__
6148162002-12-14Martin Nilsson  constant description = "Assembles AutoDoc output file.";
91a7b92002-12-05Henrik Grubbström (Grubba)  // AutoDoc mk II assembler
bbd98d2005-03-28Per Hedbor #define Node Parser.XML.Tree.Node
a972632011-11-18Henrik Grubbström (Grubba) #define CommentNode Parser.XML.Tree.CommentNode
91a7b92002-12-05Henrik Grubbström (Grubba) #define XML_ELEMENT Parser.XML.Tree.XML_ELEMENT #define XML_TEXT Parser.XML.Tree.XML_TEXT
19d0a32012-01-29Henrik Grubbström (Grubba) #define RootNode Parser.XML.Tree.RootNode #define HeaderNode Parser.XML.Tree.HeaderNode #define TextNode Parser.XML.Tree.TextNode
c0729f2012-02-11Henrik Grubbström (Grubba) #define ElementNode Parser.XML.Tree.ElementNode
91a7b92002-12-05Henrik Grubbström (Grubba)  int chapter;
c75acb2012-02-11Henrik Grubbström (Grubba) int appendix;
91a7b92002-12-05Henrik Grubbström (Grubba)  mapping queue = ([]);
c75acb2012-02-11Henrik Grubbström (Grubba) mapping appendix_queue = ([]);
f2c2ae2003-02-08Martin Nilsson mapping ns_queue = ([]);
91a7b92002-12-05Henrik Grubbström (Grubba) array(Node) chapters = ({});
4f01982011-11-18Henrik Grubbström (Grubba) Tools.AutoDoc.Flags flags = Tools.AutoDoc.FLAG_NORMAL; int verbose = Tools.AutoDoc.FLAG_NORMAL;
f5fa032011-11-18Henrik Grubbström (Grubba) string refdocdir;
91a7b92002-12-05Henrik Grubbström (Grubba) Node void_node = Node(XML_ELEMENT, "void", ([]), 0); // array( array(name,file,chapter_no,(subchapters)) ) array toc = ({}); class TocNode { inherit Node; string path; int(1..3) depth;
9eaf1d2008-06-28Martin Nilsson  protected void make_children() {
91a7b92002-12-05Henrik Grubbström (Grubba)  if(sizeof(mChildren)) return; foreach(toc, array ent) { string file = ent[1][sizeof(String.common_prefix( ({ path, ent[1] }) ))..]; if(file[0]=='/') file = file[1..]; Node dt = Node( XML_ELEMENT, "dt", ([]), 0 ); Node link = Node( XML_ELEMENT, "url", ([ "href" : file ]), 0 ); if(ent[2]) link->add_child( Node( XML_TEXT, 0, 0, ent[2]+". "+ent[0] ) ); else link->add_child( Node( XML_TEXT, 0, 0, ent[0] ) ); dt->add_child( link ); add_child( dt ); add_child( Node( XML_TEXT, 0, 0, "\n" ) ); int sub; if(sizeof(ent)>3 && depth>1) foreach(ent[3..], string subtit) { Node dd = Node( XML_ELEMENT, "dd", ([]), 0 ); sub++; Node link = Node( XML_ELEMENT, "url", ([ "href" : file+"#"+sub ]), 0 ); link->add_child( Node( XML_TEXT, 0, 0, ent[2]+"."+sub+". "+subtit ) ); dd->add_child( link ); add_child( dd ); add_child( Node( XML_TEXT, 0, 0, "\n" ) ); // TODO: Add depth 3 here } } } int walk_preorder_2(mixed ... args) { make_children(); ::walk_preorder_2( @args ); } array(Node) get_children() { make_children(); return ::get_children(); } int count_children() { make_children(); return ::count_children(); } void create(string _path, int(1..3) _depth) { path = _path; depth = _depth; ::create(XML_ELEMENT, "dl", ([]), ""); } } class Entry (Node target) { constant type = ""; mapping args; string _sprintf() {
91da4a2012-02-12Henrik Grubbström (Grubba)  return sprintf("%sEntry( %O )", type, target);
91a7b92002-12-05Henrik Grubbström (Grubba)  } } // --- Some debug functions string visualize(Node n, int depth) { if(n->get_node_type() == XML_TEXT) return Parser.XML.Tree.text_quote(n->get_text()); if(n->get_node_type() != XML_ELEMENT ||
ead9722003-01-20Martin Nilsson  !sizeof(n->get_tag_name()))
91a7b92002-12-05Henrik Grubbström (Grubba)  return ""; string name = n->get_tag_name();
2d2bbf2002-12-10Henrik Grubbström (Grubba)  if(!(<"autodoc","namespace","module","class">)[name])
91a7b92002-12-05Henrik Grubbström (Grubba)  return ""; string data = "<" + name; if (mapping attr = n->get_attributes()) { foreach(indices(attr), string a) data += " " + a + "='" + Parser.XML.Tree.attribute_quote(attr[a]) + "'"; } if (!n->count_children()) return data + "/>"; data += ">"; if(depth==0) data += "..."; else data += map(n->get_children(), visualize, depth-1)*""; return data + "</" + name + ">"; } string vis(Node n) { if(!n || n->get_node_type()!=XML_ELEMENT) return sprintf("%O", n); return sprintf("<%s%{ %s='%s'%}>", n->get_tag_name(), (array)n->get_attributes()); } // --- class mvEntry { inherit Entry; constant type = "mv";
91da4a2012-02-12Henrik Grubbström (Grubba)  Node parent;
aafb532004-05-14Henrik Grubbström (Grubba) 
9eaf1d2008-06-28Martin Nilsson  protected void create(Node target, Node parent)
aafb532004-05-14Henrik Grubbström (Grubba)  { ::create(target); mvEntry::parent = parent; }
91a7b92002-12-05Henrik Grubbström (Grubba)  void `()(Node data) { if(args) { mapping m = data->get_attributes(); foreach(indices(args), string index) m[index] = args[index]; }
aafb532004-05-14Henrik Grubbström (Grubba)  parent->replace_child(target, data);
91a7b92002-12-05Henrik Grubbström (Grubba)  } }
f2c2ae2003-02-08Martin Nilsson class mvPeelEntry { inherit Entry; constant type = "mvPeel";
9eaf1d2008-06-28Martin Nilsson  protected Node parent;
f2c2ae2003-02-08Martin Nilsson 
9eaf1d2008-06-28Martin Nilsson  protected void create(Node target, Node parent)
aafb532004-05-14Henrik Grubbström (Grubba)  { ::create(target); mvPeelEntry::parent = parent; } void `()(Node data) {
f2c2ae2003-02-08Martin Nilsson  // WARNING! Disrespecting information hiding!
aafb532004-05-14Henrik Grubbström (Grubba)  int pos = search(parent->mChildren, data); array pre = parent->mChildren[..pos-1]; array post = parent->mChildren[pos+1..]; parent->mChildren = pre + data->mChildren + post;
f2c2ae2003-02-08Martin Nilsson  } }
91a7b92002-12-05Henrik Grubbström (Grubba) class cpEntry { inherit Entry; constant type = "cp"; void `()(Node data) { // clone data subtree // target->replace_node(clone); } }
aafb532004-05-14Henrik Grubbström (Grubba) void enqueue_move(Node target, Node parent) {
f2c2ae2003-02-08Martin Nilsson  mapping(string:string) m = target->get_attributes(); if(m->namespace) { string ns = m->namespace; sscanf(ns, "%s::", ns); ns += "::"; if(ns_queue[ns]) error("Move source already allocated (%O).\n", ns); if(m->peel="yes")
aafb532004-05-14Henrik Grubbström (Grubba)  ns_queue[ns] = mvPeelEntry(target, parent);
f2c2ae2003-02-08Martin Nilsson  else
aafb532004-05-14Henrik Grubbström (Grubba)  ns_queue[ns] = mvEntry(target, parent);
f2c2ae2003-02-08Martin Nilsson  return; } else if(!m->entity) error("Error in insert-move element.\n");
91a7b92002-12-05Henrik Grubbström (Grubba)  mapping bucket = queue;
f2c2ae2003-02-08Martin Nilsson  if(m->entity != "") { array path = map(m->entity/".", replace, "-", ".");
bd2d9c2002-12-12Henrik Grubbström (Grubba)  if (!has_value(path[0], "::")) { // Default namespace. path = ({ "predef::" }) + path; } else { if (!has_suffix(path[0], "::")) { path = path[0]/"::" + path[1..]; } }
91a7b92002-12-05Henrik Grubbström (Grubba)  foreach(path, string node) { if(!bucket[node]) bucket[node] = ([]); bucket = bucket[node]; } } if(bucket[0])
f2c2ae2003-02-08Martin Nilsson  error("Move source already allocated (%s).\n", m->entity);
91a7b92002-12-05Henrik Grubbström (Grubba) 
aafb532004-05-14Henrik Grubbström (Grubba)  bucket[0] = mvEntry(target, parent);
91a7b92002-12-05Henrik Grubbström (Grubba) }
c0729f2012-02-11Henrik Grubbström (Grubba) Node parse_file(string fn) {
91a7b92002-12-05Henrik Grubbström (Grubba)  Node n; mixed err = catch {
bbd98d2005-03-28Per Hedbor  n = Parser.XML.Tree.parse_file(fn);
91a7b92002-12-05Henrik Grubbström (Grubba)  }; if(stringp(err)) error(err); if(err) throw(err); return n; } void section_ref_expansion(Node n) { int subsection; foreach(n->get_elements(), Node c) switch(c->get_tag_name()) { case "p": case "example": case "dl": case "ul": case "matrix": break; case "subsection": c->get_attributes()->number = (string)++subsection; break; case "insert-move":
aafb532004-05-14Henrik Grubbström (Grubba)  enqueue_move(c, n);
91a7b92002-12-05Henrik Grubbström (Grubba)  break; default: error("Unknown element %O in section element.\n", c->get_tag_name()); break; } } void chapter_ref_expansion(Node n, string dir) { int section; foreach(n->get_elements(), Node c) switch(c->get_tag_name()) {
e7e2112017-07-21Pontus Östlund  case "ul": case "li": case "dl": case "dt": case "dd":
91a7b92002-12-05Henrik Grubbström (Grubba)  case "p": break; case "contents":
cbe50d2004-07-08Henrik Grubbström (Grubba)  n->replace_child(c, TocNode(dir, 3) );
91a7b92002-12-05Henrik Grubbström (Grubba)  break; case "section": c->get_attributes()->number = (string)++section; section_ref_expansion(c); break; case "insert-move":
aafb532004-05-14Henrik Grubbström (Grubba)  enqueue_move(c, n);
91a7b92002-12-05Henrik Grubbström (Grubba)  break; default: error("Unknown element %O in chapter element.\n", c->get_tag_name()); break; } } int filec;
c0729f2012-02-11Henrik Grubbström (Grubba) void ref_expansion(Node n, string dir, void|string file) { string path;
91a7b92002-12-05Henrik Grubbström (Grubba)  foreach(n->get_elements(), Node c) { switch(c->get_tag_name()) { case "file": if(file) error("Nested file elements (%O).\n", file); file = c->get_attributes()->name; if(!file) { if(sizeof(c->get_elements())==1) { string name = c->get_elements()[0]->get_tag_name(); if(name == "chapter" || name == "chapter-ref") file = "chapter_" + (1+chapter);
c75acb2012-02-11Henrik Grubbström (Grubba)  else if(name == "appendix" || name == "appendix-ref") file = "appendix_" + (string)({ 65+appendix });
91a7b92002-12-05Henrik Grubbström (Grubba)  else file = "file_" + (++filec); } else file = "file_" + (++filec); file += ".html"; } c->get_attributes()->name = dir + "/" + file; ref_expansion(c, dir, c->get_attributes()->name); file = 0; break; case "dir": c->get_attributes()->name = dir + "/" + c->get_attributes()->name; ref_expansion(c, c->get_attributes()->name, file); break; case "chapter-ref": if(!file) error("chapter-ref element outside file element\n"); if(!c->get_attributes()->file) error("No file attribute on chapter-ref element.\n");
c0729f2012-02-11Henrik Grubbström (Grubba)  path = combine_path(refdocdir, c->get_attributes()->file); if (!Stdio.exist(path)) { if ((verbose >= Tools.AutoDoc.FLAG_VERBOSE) || (!(flags & Tools.AutoDoc.FLAG_COMPAT))) { werror("Warning: Chapter file %O not found.\n", path); } n->remove_child(c); break; }
6d046d2012-02-15Henrik Grubbström (Grubba)  mixed err = catch { n->replace_child(c, c = parse_file(path)-> get_first_element("chapter") ); }; if (err) { n->remove_child(c); if (flags & Tools.AutoDoc.FLAG_KEEP_GOING) { werror("Chapter ref for %O failed:\n" "%s\n", path, describe_backtrace(err)); break; } throw(err); }
91a7b92002-12-05Henrik Grubbström (Grubba)  // fallthrough case "chapter": mapping m = c->get_attributes(); if(m->unnumbered!="1") m->number = (string)++chapter; toc += ({ ({ m->title, file, m->number }) }); chapters += ({ c }); chapter_ref_expansion(c, dir); break;
c75acb2012-02-11Henrik Grubbström (Grubba)  case "appendix-ref":
c0729f2012-02-11Henrik Grubbström (Grubba)  if (!(flags & Tools.AutoDoc.FLAG_COMPAT)) { error("Appendices are only supported in compat mode.\n"); }
c75acb2012-02-11Henrik Grubbström (Grubba)  if(!file) error("appendix-ref element outside file element\n"); if(c->get_attributes()->name) { Entry e = mvEntry(c, n); e->args = ([ "number": (string)++appendix ]); appendix_queue[c->get_attributes()->name] = e; // No more than 26 appendicies... toc += ({ ({ c->get_attributes()->name, file, ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"/1)[appendix-1] }) }); break; } if(!c->get_attributes()->file) error("Neither file nor name attribute on appendix-ref element.\n");
c0729f2012-02-11Henrik Grubbström (Grubba)  path = combine_path(refdocdir, c->get_attributes()->file); if (!Stdio.exist(path)) { if ((verbose >= Tools.AutoDoc.FLAG_VERBOSE) || (!(flags & Tools.AutoDoc.FLAG_COMPAT))) { werror("Warning: Appendix file %O not found.\n", path); } n->remove_child(c); break; }
6d046d2012-02-15Henrik Grubbström (Grubba)  err = catch { c = c->replace_node( parse_file(path)-> get_first_element("appendix") ); }; if (err) { n->remove_child(c); if (flags & Tools.AutoDoc.FLAG_KEEP_GOING) { werror("Appendix ref for %O failed:\n" "%s\n", path, describe_backtrace(err)); break; } throw(err); }
c75acb2012-02-11Henrik Grubbström (Grubba)  // fallthrough case "appendix":
c0729f2012-02-11Henrik Grubbström (Grubba)  if (!(flags & Tools.AutoDoc.FLAG_COMPAT)) { error("Appendices are only supported in compat mode.\n"); }
c75acb2012-02-11Henrik Grubbström (Grubba)  c->get_attributes()->number = (string)++appendix; // No more than 26 appendicies... toc += ({ ({ c->get_attributes()->name, file, ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"/1)[appendix-1] }) }); break;
91a7b92002-12-05Henrik Grubbström (Grubba)  case "void":
aafb532004-05-14Henrik Grubbström (Grubba)  n->remove_child(c);
91a7b92002-12-05Henrik Grubbström (Grubba)  void_node->add_child(c); chapter_ref_expansion(c, dir);
7895d42004-07-08Henrik Grubbström (Grubba)  break; default: werror("Warning unhandled tag %O in ref_expansion\n", c->get_tag_name()); break;
91a7b92002-12-05Henrik Grubbström (Grubba)  } } }
c75acb2012-02-11Henrik Grubbström (Grubba) void move_appendices(Node n) { foreach(n->get_elements("appendix"), Node c) { string name = c->get_attributes()->name; Node a = appendix_queue[name]; if(a) { a(c); m_delete(appendix_queue, name); } else { c->remove_node();
5b6ffa2012-02-11Henrik Grubbström (Grubba)  if (verbose) { werror("Removed untargeted appendix %O.\n", name); }
c75acb2012-02-11Henrik Grubbström (Grubba)  } }
c0729f2012-02-11Henrik Grubbström (Grubba)  if(sizeof(appendix_queue)) {
5b6ffa2012-02-11Henrik Grubbström (Grubba)  if (verbose) { werror("Failed to find appendi%s %s.\n", (sizeof(appendix_queue)==1?"x":"ces"), String.implode_nicely(map(indices(appendix_queue), lambda(string in) { return "\""+in+"\""; })) ); }
c0729f2012-02-11Henrik Grubbström (Grubba)  foreach(values(appendix_queue), Node a) { // Remove the place-holder. a(ElementNode("appendix", ([]))); } }
c75acb2012-02-11Henrik Grubbström (Grubba) }
91a7b92002-12-05Henrik Grubbström (Grubba) Node wrap(Node n, Node wrapper) { if(wrapper->count_children()) wrap(n, wrapper[0]); else { wrapper->add_child(n); } return wrapper; }
7a10f02012-03-04Henrik Grubbström (Grubba) protected void move_items_low(Node parent, Node n, mapping jobs, void|Node wrapper) {
91a7b92002-12-05Henrik Grubbström (Grubba)  if(jobs[0]) {
7a10f02012-03-04Henrik Grubbström (Grubba)  // Detach the node from its original parent. parent->remove_child(n);
91a7b92002-12-05Henrik Grubbström (Grubba)  if(wrapper) jobs[0]( wrap(n, wrapper->clone()) ); else jobs[0](n); m_delete(jobs, 0); } if(!sizeof(jobs)) return;
627f3d2002-12-12Henrik Grubbström (Grubba)  foreach( ({ "module", "class", "docgroup" }), string type)
91a7b92002-12-05Henrik Grubbström (Grubba)  foreach(n->get_elements(type), Node c) {
91da4a2012-02-12Henrik Grubbström (Grubba)  mapping parent = jobs;
91a7b92002-12-05Henrik Grubbström (Grubba)  mapping m = c->get_attributes(); string name = m->name || m["homogen-name"];
91da4a2012-02-12Henrik Grubbström (Grubba)  string parent_name;
38b26b2012-03-04Henrik Grubbström (Grubba)  mapping e; if (name) { name = replace(name, "-", "."); e = jobs[ name ]; } else if (type == "docgroup") { // Check if any of the symbols in the group is relevant.
d814972012-03-24Henrik Grubbström (Grubba)  foreach(c->get_elements("method")+c->get_elements("directive"), Node m) {
38b26b2012-03-04Henrik Grubbström (Grubba)  mapping attrs = m->get_attributes(); name = attrs->name && replace(attrs->name, "-", "."); if (e = jobs[name]) break; } }
91da4a2012-02-12Henrik Grubbström (Grubba)  if (!e /*&& (flags & Tools.AutoDoc.FLAG_COMPAT)*/) { array(string) path; if (path = ([ "/precompiled/FILE": "Stdio.FILE"/".", "/precompiled/condition": "Thread.Condition"/".", "/precompiled/fifo": "Thread.Fifo"/".", "/precompiled/file": "Stdio.File"/".", "/precompiled/gdbm": "Gdbm.gdbm"/".", "/precompiled/mpz": "Gmp.mpz"/".", "/precompiled/mutex": "Thread.Mutex"/".", "/precompiled/mysql": "Mysql.mysql"/".", "/precompiled/mysql_result": "Mysql.mysql_result"/".", "/precompiled/port": "Stdio.Port"/".", "/precompiled/queue": "Thread.Queue"/".", "/precompiled/regexp": "Regexp"/".", "/precompiled/sql": "Sql.sql"/".", "/precompiled/sql/msql": "Msql.msql"/".", "/precompiled/sql/mysql": "Mysql.mysql"/".", "/precompiled/sql/mysql_result": "Mysql.mysql_result"/".", "/precompiled/sql/postgres": "Postgres.postgres"/".", "/precompiled/sql/sql_result": "Sql.sql_result"/".", "/precompiled/stack": "Stack"/".", "/precompiled/string_buffer": "String.Buffer"/".", ])[name]) { e = jobs; foreach(path; int i; name) { if (i) parent_name = path[i-1]; parent = e; e = e[name]; if (!e) { if ((parent != jobs) && parent[0] && parent[0]->parent) { // There's a move for our parent, but we can't use it directly, // since there may be more nodes that need moving. // // So we add a move for ourselves. // // NB: This is a bit round-about, since we could just add // ourselves directly... Node dummy = ElementNode("insert-move", ([ "entity":path[..i]*"." ])); parent[0]->parent->add_child_after(dummy, parent[0]->target); Entry new_mv = mvEntry(dummy, parent[0]->parent); e = parent[name] = ([ 0: new_mv ]); continue; } break; } } } }
91a7b92002-12-05Henrik Grubbström (Grubba)  if(!e) continue; Node wr = Node(XML_ELEMENT, n->get_tag_name(), n->get_attributes()+(["hidden":"1"]), 0); if(wrapper) wr = wrap( wr, wrapper->clone() );
7a10f02012-03-04Henrik Grubbström (Grubba)  move_items_low(n, c, e, wr);
91a7b92002-12-05Henrik Grubbström (Grubba) 
91da4a2012-02-12Henrik Grubbström (Grubba)  if ((parent != jobs) && !sizeof(e)) { m_delete(parent, name); name = parent_name; e = jobs[e]; if (!e) continue; }
91a7b92002-12-05Henrik Grubbström (Grubba)  if(!sizeof(e)) m_delete(jobs, name); } }
f2c2ae2003-02-08Martin Nilsson void move_items(Node n, mapping jobs)
627f3d2002-12-12Henrik Grubbström (Grubba) { if(jobs[0]) {
f2c2ae2003-02-08Martin Nilsson  jobs[0](n);
627f3d2002-12-12Henrik Grubbström (Grubba)  m_delete(jobs, 0); }
f2c2ae2003-02-08Martin Nilsson  if(!sizeof(jobs) && !sizeof(ns_queue)) return;
627f3d2002-12-12Henrik Grubbström (Grubba)  foreach(n->get_elements("namespace"), Node c) { mapping m = c->get_attributes(); string name = m->name + "::";
f2c2ae2003-02-08Martin Nilsson  if(ns_queue[name]) { ns_queue[name]( c ); m_delete(ns_queue, name); }
627f3d2002-12-12Henrik Grubbström (Grubba)  mapping e = jobs[name]; if(!e) continue;
9b33c62002-12-13Henrik Grubbström (Grubba)  Node wr = Node(XML_ELEMENT, "autodoc",
627f3d2002-12-12Henrik Grubbström (Grubba)  n->get_attributes()+(["hidden":"1"]), 0);
7a10f02012-03-04Henrik Grubbström (Grubba)  move_items_low(n, c, e, wr);
627f3d2002-12-12Henrik Grubbström (Grubba)  if(!sizeof(e)) m_delete(jobs, name); }
f2c2ae2003-02-08Martin Nilsson 
24c5462012-02-12Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE) {
4f01982011-11-18Henrik Grubbström (Grubba)  foreach(indices(ns_queue), string name) werror("Failed to move namespace %O.\n", name);
24c5462012-02-12Henrik Grubbström (Grubba)  } foreach(values(ns_queue), Node n) n(ElementNode("namespace", ([])));
627f3d2002-12-12Henrik Grubbström (Grubba) }
c0729f2012-02-11Henrik Grubbström (Grubba) void clean_empty_files(Node n) { foreach(n->get_elements("dir"), Node d) { foreach(d->get_elements("file"), Node f) { foreach(f->get_elements("appendix"), Node a) { if (!sizeof(a->get_elements())) { // Empty appendix. f->remove_child(a); } }
24c5462012-02-12Henrik Grubbström (Grubba)  foreach(f->get_elements("namespace"), Node a) { if (!sizeof(a->get_elements())) { // Empty appendix. f->remove_child(a); } }
c0729f2012-02-11Henrik Grubbström (Grubba)  if (!sizeof(f->get_elements())) { // No documentation in this file. d->remove_child(f); } } if (!sizeof(d->get_elements())) { // Remove the directory as well. n->remove_child(d); } } }
91a7b92002-12-05Henrik Grubbström (Grubba) string make_toc_entry(Node n) { if(n->get_tag_name()=="section") return n->get_attributes()->title; while(n->get_attributes()->hidden) n = n->get_first_element(); array a = reverse(n->get_ancestors(1)); array b = a->get_any_name(); int root; foreach( ({ "manual", "dir", "file", "chapter", "section", "subsection" }), string node) root = max(root, search(b, node)); a = a[root+1..]; if(sizeof(a) && a[0]->get_attributes()->name=="") a = a[1..]; return a->get_attributes()->name * "."; } void make_toc() { for(int i; i<sizeof(chapters); i++) { foreach(chapters[i]->get_elements(), Node c) if( (< "section", "module", "class" >)[c->get_tag_name()] ) toc[i] += ({ make_toc_entry(c) }); } } void report_failed_entries(mapping scope, string path) { if(scope[0]) {
246d202012-03-04Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_NORMAL) {
4f01982011-11-18Henrik Grubbström (Grubba)  werror("Failed to move %s\n", path[1..]); }
a972632011-11-18Henrik Grubbström (Grubba)  scope[0](CommentNode(sprintf("<insert-move entity=\"%s\" />", path[1..])));
91a7b92002-12-05Henrik Grubbström (Grubba)  m_delete(scope, 0); } foreach(scope; string id; mapping next) report_failed_entries(next, path + "." + id); }
786c322016-07-10Martin Nilsson class Options
e30db92011-11-20Henrik Grubbström (Grubba) {
786c322016-07-10Martin Nilsson  inherit Arg.Options; constant help_pre = "pike -x assemble_autodoc <structure file> <autodoc file>"; Opt pikever = HasOpt("--pike-version")|Default(version()); Opt timestamp = Int(HasOpt("--timestamp")|HasOpt("--time-stamp")|Default(time()));
0ea1362016-11-10Henrik Grubbström (Grubba)  Opt help = NoOpt("-h")|NoOpt("--help"); Opt output = HasOpt("-o")|HasOpt("--output")|HasOpt("--out");
786c322016-07-10Martin Nilsson  Opt verbose = NoOpt("-v")|NoOpt("--verbose"); Opt quiet = NoOpt("-q")|NoOpt("--quiet"); Opt compat = NoOpt("--compat"); Opt no_dynamic = NoOpt("--no-dynamic");
adb2072016-11-10Henrik Grubbström (Grubba)  Opt keep_going = NoOpt("--keep-going");
786c322016-07-10Martin Nilsson }
91a7b92002-12-05Henrik Grubbström (Grubba) 
786c322016-07-10Martin Nilsson int(0..1) main(int num, array(string) args) { Options options = Options(args); if(options->help) exit(1);
ede41c2008-06-28Martin Nilsson 
4f01982011-11-18Henrik Grubbström (Grubba)  int T = time();
786c322016-07-10Martin Nilsson  if( options->quiet ) { options->verbose = Tools.AutoDoc.FLAG_QUIET; flags &= ~Tools.AutoDoc.FLAG_VERB_MASK;
4f01982011-11-18Henrik Grubbström (Grubba)  }
786c322016-07-10Martin Nilsson  else if( options->verbose ) flags = (flags & ~Tools.AutoDoc.FLAG_VERB_MASK) | min(verbose, Tools.AutoDoc.FLAG_DEBUG-1); if( options->keep_going ) flags |= Tools.AutoDoc.FLAG_KEEP_GOING; if( options->compat ) flags |= Tools.AutoDoc.FLAG_COMPAT; args = options[Arg.REST]; if(sizeof(args)<2)
ede41c2008-06-28Martin Nilsson  exit(1," Too few arguments\n");
91a7b92002-12-05Henrik Grubbström (Grubba) 
4f01982011-11-18Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE)
786c322016-07-10Martin Nilsson  werror("Parsing structure file %O.\n", args[0]); Node n = parse_file(args[0]);
91a7b92002-12-05Henrik Grubbström (Grubba)  n = n->get_first_element("manual");
786c322016-07-10Martin Nilsson  n->get_attributes()->version = options->pikever; mapping t = localtime(options->timestamp);
91a7b92002-12-05Henrik Grubbström (Grubba)  n->get_attributes()["time-stamp"] = sprintf("%4d-%02d-%02d", t->year+1900, t->mon+1, t->mday);
786c322016-07-10Martin Nilsson  refdocdir = combine_path(args[0], "../..");
4f01982011-11-18Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE) {
f5fa032011-11-18Henrik Grubbström (Grubba)  werror("Refdoc directory: %s\n", refdocdir);
4f01982011-11-18Henrik Grubbström (Grubba)  werror("Executing reference expansion and queueing node insertions.\n"); }
91a7b92002-12-05Henrik Grubbström (Grubba)  mixed err = catch { ref_expansion(n, "."); }; if (err) {
c75acb2012-02-11Henrik Grubbström (Grubba)  if (flags & Tools.AutoDoc.FLAG_COMPAT) { werror("ref_expansion() failed:\n" " ch:%d app:%d toc:%O\n", chapter, appendix, toc); } else { werror("ref_expansion() failed:\n" " ch:%d toc:%O\n", chapter, toc); }
4f01982011-11-18Henrik Grubbström (Grubba)  if (!(flags & Tools.AutoDoc.FLAG_KEEP_GOING)) throw(err);
91a7b92002-12-05Henrik Grubbström (Grubba)  }
4f01982011-11-18Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE)
786c322016-07-10Martin Nilsson  werror("Parsing autodoc file %O.\n", args[1]); Node m = parse_file(args[1]);
2d2bbf2002-12-10Henrik Grubbström (Grubba)  m = m->get_first_element("autodoc");
91a7b92002-12-05Henrik Grubbström (Grubba) 
c75acb2012-02-11Henrik Grubbström (Grubba)  if (flags & Tools.AutoDoc.FLAG_COMPAT) { if (verbose >= Tools.AutoDoc.FLAG_VERBOSE) werror("Moving appendices.\n"); move_appendices(m); }
4f01982011-11-18Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE) werror("Executing node insertions.\n");
91a7b92002-12-05Henrik Grubbström (Grubba)  move_items(m, queue); if(sizeof(queue)) {
24c5462012-02-12Henrik Grubbström (Grubba)  report_failed_entries(queue, "");
4f01982011-11-18Henrik Grubbström (Grubba)  if (!(flags & Tools.AutoDoc.FLAG_KEEP_GOING)) return 1;
91a7b92002-12-05Henrik Grubbström (Grubba)  }
c0729f2012-02-11Henrik Grubbström (Grubba)  clean_empty_files(n);
91a7b92002-12-05Henrik Grubbström (Grubba)  make_toc();
19d0a32012-01-29Henrik Grubbström (Grubba)  Node root = RootNode(); root->replace_children(({ HeaderNode(([ "version":"1.0", "encoding":"utf-8" ])), TextNode("\n"), n, TextNode("\n"), }));
4f01982011-11-18Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE) werror("Writing final manual source file.\n");
786c322016-07-10Martin Nilsson  if (options->output) { Stdio.write_file(options->output, (string)root);
fe69e42011-11-18Henrik Grubbström (Grubba)  } else {
19d0a32012-01-29Henrik Grubbström (Grubba)  write( (string)root );
fe69e42011-11-18Henrik Grubbström (Grubba)  }
fce2b52008-06-01Henrik Grubbström (Grubba)  // Zap the XML trees so that the gc doesn't have to. m->zap_tree(); n->zap_tree();
4f01982011-11-18Henrik Grubbström (Grubba)  if (verbose >= Tools.AutoDoc.FLAG_VERBOSE) werror("Took %d seconds.\n\n", time()-T);
fce2b52008-06-01Henrik Grubbström (Grubba) 
91a7b92002-12-05Henrik Grubbström (Grubba)  return 0; }