// ------------------------------------------------------------------ // Route Diagram Drawing Tool. // Copyright (C) 1999 Odinn Sorensen // Copyright (C) 1999-2001 Alexander S. Aganichev // Copyright (C) 2005 Stas Degteff // ------------------------------------------------------------------ // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ------------------------------------------------------------------ // Designed to work with the Goldware library. May need some work.. // ------------------------------------------------------------------ // $Id$ // ------------------------------------------------------------------ #include <clocale> #include <cstdio> #include <iostream> #include <iomanip> #include <fstream> #include <list> using namespace std; #include <gstrall.h> #include <gftnall.h> #include <golded3.h> #include <gmemdbg.h> int debug = false; // ------------------------------------------------------------------ class node { public: node() { order = 0; depth = 0; used = false; posts = 0; } bool used; int order; int depth; int posts; ftn_addr address; string name; vector<ftn_addr> links; string display; void add(const char* s) { ftn_addr n = s; add(n); } void add(ftn_addr& addr); node& operator=(const node& a); }; // ------------------------------------------------------------------ typedef list<node> list_node; // ------------------------------------------------------------------ class nodetree { public: nodetree() { maxname = 0; maxdisp = 0; order = 0; indent = 2; posts = 0; } list_node nodes; int order; int maxname; int maxdisp; int indent; int posts; void prepare(ftn_addr& previous, ftn_addr& current, int depth); void sort(); void print(); void add(node& a); }; // ------------------------------------------------------------------ node& node::operator=(const node& a) { used = a.used; order = a.order; depth = a.depth; address = a.address; name = a.name; display = a.display; links = a.links; return *this; } // ------------------------------------------------------------------ bool equals2d(ftn_addr& a, ftn_addr& b) { if(a == b) return true; else if((a.net == b.net) and (a.node == b.node) and (a.point == b.point)) return true; return false; } // ------------------------------------------------------------------ void node::add(ftn_addr& addr) { if(equals2d(addr, address)) return; for(int l=0; l<links.size(); l++) { if(equals2d(addr, links[l])) return; } if(debug) { char buf1[50], buf2[50]; cout << address.make_string(buf1) << " += " << addr.make_string(buf2) << endl; } links.push_back(addr); } // ------------------------------------------------------------------ void nodetree::add(node& anode) { for(list_node::iterator n=nodes.begin(); n != nodes.end(); n++) { if(equals2d(anode.address, n->address)) { if(anode.address.zone) { n->address.zone = anode.address.zone; n->name = anode.name; } for(int l=0; l<anode.links.size(); l++) n->add(anode.links[l]); return; } } if(debug) { char buf[50]; cout << anode.address.make_string(buf) << endl; } nodes.push_back(anode); } // ------------------------------------------------------------------ void nodetree::prepare(ftn_addr& previous, ftn_addr& current, int depth) { if(debug) { char buf[50]; cout << "prepare(" << previous.make_string(buf); cout << ", " << current.make_string(buf); cout << ", " << depth << ")" << endl; } // Find top node for(list_node::iterator n=nodes.begin(); n != nodes.end(); n++) { if(not n->used) { if(equals2d(n->address, current)) { n->order = ++order; n->depth = depth; n->used = true; for(int l=0; l<n->links.size(); l++) { //if(not equals2d(n->links[l], previous)) if(n->links[l] != previous) prepare(current, n->links[l], depth+1); } break; } } } } // ------------------------------------------------------------------ bool _compare_nodes(const node& a, const node& b) { int cmp = compare_two(a.order ? 0 : 1, b.order ? 0 : 1); if(cmp) return (cmp < 0); cmp = compare_two(a.order, b.order); if(cmp) return (cmp < 0); return (a.address.compare(b.address) < 0); } #if defined(_MSC_VER) inline bool operator<(const node& A,const node& B){ return _compare_nodes(A,B); } #define compare_nodes #else #define compare_nodes _compare_nodes #endif // ------------------------------------------------------------------ void nodetree::sort() { nodes.sort(compare_nodes); } // ------------------------------------------------------------------ void nodetree::print() { list_node::iterator n; for(n=nodes.begin(); n != nodes.end(); n++) { char buf[100]; strsetsz(strcpy(buf, n->name.c_str()), maxname+indent); n->display = buf; list_node::iterator x; bool above, below; for(int d=1; d<n->depth; d++) { above = false; below = false; if(d > 0) { for(x=n; x-- != nodes.begin();) { if(x->depth < d) break; else if(x->depth == d) { above = true; break; } } for(x=n; ++x != nodes.end();) { if(x->depth < d) break; else if(x->depth == d) { below = true; break; } } } if(above and below) { #ifdef KOI8 strcpy(buf, "�"); #else strcpy(buf, "�"); #endif } else *buf = NUL; strsetsz(buf, indent); n->display += buf; } if(n->depth) { #ifdef KOI8 strcpy(buf, "�"); #else strcpy(buf, "�"); #endif strsetsz(buf, indent); #ifdef KOI8 strchg(buf, ' ', '�'); #else strchg(buf, ' ', '�'); #endif n->display += buf; } n->display += n->address.make_string(buf); maxdisp = maximum_of_two((size_t)maxdisp, n->display.length()); } for(n=nodes.begin(); n != nodes.end(); n++) { list_node::iterator x=n; if(++x != nodes.end()) { #ifdef KOI8 const char* p = strchr(n->display.c_str(), '�'); #else const char* p = strchr(n->display.c_str(), '�'); #endif if(p) { int len = p - n->display.c_str(); #ifdef KOI8 if((x->display[len] == '�') or (x->display[len] == '�')) n->display[len] = '�'; #else if((x->display[len] == '�') or (x->display[len] == '�')) n->display[len] = '�'; #endif } } n->display.resize(maxdisp, ' '); char buf[40]; sprintf(buf, "%*s[%i]", indent, "", n->depth); n->display += buf; } for(n=nodes.begin(); n != nodes.end(); n++) cout << n->display.c_str() << endl; } // ------------------------------------------------------------------ int main(int argc, char** argv) { throw_init(); // set locale setlocale(LC_CTYPE, ""); cout << "Route Diagram Drawing Tool v." << __gver_shortver__ << __gver_platform__ << __gver_postversion__; #ifdef KOI8 cout << " (koi8)"; #endif cout << endl << "Copyright (C) 1999 Odinn Sorensen" << endl << "Copyright (C) 1999-2001 Alexander S. Aganichev" << endl << "Copyright (C) 2005 Stas Degteff & Golded+ team" << endl << "----------------------------------------------------------------------" << endl << endl; if(argc < 2) { cout << "Syntax: RDDT <routefile> [options] [address or name]" << endl << "\twhere options may be:" << endl << "\t\t-d - Debug mode" << endl << "\t\t-p - Decode path" << endl << "\t\t-n ownaddress - Your own address" << endl << "\t\t-l ownuplink - Your own uplink" << endl << "\t\t-i num - indent <num> spaces" << endl << endl; return 1; } #if defined(GUTLOS_FUNCS) g_init_os(0); #endif node anode; nodetree atree; ifstream fp(argv[1]); ftn_addr address; bool decode_path = false; char* top = NULL; ftn_addr ownaddress; ftn_addr ownuplink; for(int argn=2; argn<argc; argn++) { char* argp = argv[argn]; if(*argp == '-') { switch(argp[1]) { case 'd': debug = true; break; case 'p': decode_path = true; break; case 'n': ownaddress = argp + 2; break; case 'l': ownuplink = argp + 2; break; case 'i': atree.indent = atoi(argp + 2); break; default: cerr << "Illegal option '" << argp << "', ignored" << endl; } } else top = argp; } if(fp) { if(anode.links.size()) { atree.add(anode); anode.links.resize(0); } char buf[2048]; while(not fp.eof()) { fp.getline(buf, sizeof(buf)); if((*buf != ';') and (*buf != '/')) { gstrarray links; tokenize(links, buf, " "); if(links.size() > 1) { anode.links.resize(0); strchg(&links[0][0], '_', ' '); anode.name = links[0]; atree.maxname = maximum_of_two(anode.name.length(), (size_t)atree.maxname); anode.address = links[1]; if(links.size() > 2) { if(decode_path) { anode.posts++; atree.posts++; int n; address = links[2]; if(not equals2d(address, anode.address)) anode.add(address); for(n=3; n<links.size(); n++) { char buf[50]; address.set(links[n]); links[n] = address.make_string(buf); } atree.add(anode); for(n=2; n<links.size(); n++) { anode.links.resize(0); anode.name = "?"; anode.address = links[n]; anode.add(links[n-1].c_str()); if((n+1) < links.size()) anode.add(links[n+1].c_str()); atree.add(anode); } } else { address = anode.address; for(int n=2; n<links.size(); n++) { address.set(links[n]); anode.add(address); } atree.add(anode); } } else if(anode.address == ownaddress) { anode.add(ownuplink); atree.add(anode); anode.name = "?"; anode.address = ownuplink; anode.links.resize(0); anode.add(ownaddress); atree.add(anode); } } } } fp.close(); address = 0; node& xnode = anode; if(top == NULL) { xnode = *atree.nodes.begin(); address = xnode.address; } else if(isdigit(*top)) { ftn_addr match = top; for(list_node::iterator n=atree.nodes.begin(); n != atree.nodes.end(); n++) { if(n->address.match(match)) { xnode = *n; address = n->address; break; } } } else { for(list_node::iterator n=atree.nodes.begin(); n != atree.nodes.end(); n++) { if(n->name.find(top) != n->name.npos) { xnode = *n; address = n->address; break; } } } if(address.valid()) { if(debug) { char buf[50]; for(list_node::iterator n=atree.nodes.begin(); n != atree.nodes.end(); n++) { xnode = *n; cout << xnode.address.make_string(buf) << endl; for(int l=0; l<xnode.links.size(); l++) cout << " " << xnode.links[l].make_string(buf) << endl; } } atree.prepare(address, address, 0); atree.sort(); atree.print(); } else { cout << "Address or name not found!" << endl; } } #if defined(GUTLOS_FUNCS) g_deinit_os(); #endif return 0; } // ------------------------------------------------------------------