This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/rddt/rddt.cpp

523 lines
12 KiB
C++
Raw Blame History

// ------------------------------------------------------------------
// 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 <gstrarr.h>
#include <gftnall.h>
#include <golded3.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, "<EFBFBD>");
#else
strcpy(buf, "<EFBFBD>");
#endif
} else
*buf = NUL;
strsetsz(buf, indent);
n->display += buf;
}
if(n->depth) {
#ifdef KOI8
strcpy(buf, "<EFBFBD>");
#else
strcpy(buf, "<EFBFBD>");
#endif
strsetsz(buf, indent);
#ifdef KOI8
strchg(buf, ' ', '<EFBFBD>');
#else
strchg(buf, ' ', '<EFBFBD>');
#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(), '<EFBFBD>');
#else
const char* p = strchr(n->display.c_str(), '<EFBFBD>');
#endif
if(p) {
int len = p - n->display.c_str();
#ifdef KOI8
if((x->display[len] == '<EFBFBD>') or (x->display[len] == '<EFBFBD>'))
n->display[len] = '<EFBFBD>';
#else
if((x->display[len] == '<EFBFBD>') or (x->display[len] == '<EFBFBD>'))
n->display[len] = '<EFBFBD>';
#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]" <<
<< "\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;
}
// ------------------------------------------------------------------