Source file: /~heha/basteln/Haus/Telefon/CLIP-Anzeige/vorwahl.zip/MSVC/maketree.cpp

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <vector>

struct Node{
 Node() {memset(this,0,sizeof*this);}
 byte magic;		// = 0, niemals 1. Byte bei Namen
 union{
  const char*name[10];	// 10 Zeiger auf Namen oder auf Node für die Wählziffern '0'..'9'
  Node*node[10];
 };
// operator const char*() const {return (const char*)this;}
 static void insert(Node*&,const char*number, const char*name);
 void emit(const char*varname);
};

Node*root;

void Node::insert(Node*&n,const char*number, const char*name) {
 if (!n) n=new Node;
 if (number[1]) {	// Weitere Ziffern folgen?
  insert(n->node[*number-'0'],number+1,name);
 }else{			// einzige oder letzte Ziffer
  if (n->name[*number-'0']) 
    printf("Doppelte Nummer für %s\n",name);
  n->name[*number-'0']=name;	// Name eintragen (Slot sollte noch 0 enthalten!)
 }
}

int nodecount;

void Node::emit(const char*varname) {
 char subname[8];
 if (strcmp(varname,"root")) strcpy(subname,varname);
 else strcpy(subname,"n");
 char*submod=subname+strlen(subname);
 submod[1]=0;
 int i;
 for (i=0; i<10; i++) {
  if (node[i] && !node[i]->magic) {
   *submod=i+'0';
   node[i]->emit(subname);
  }
 }
 nodecount++;
 printf("%s={\t",varname);
 for (i=0; i<10; i++) {
  if (node[i]) {
   if (node[i]->magic) {
    printf("\"%s\",\t",name[i]);
   }else{
    *submod=i+'0';
    printf("(char*)%s,\t",subname);
   }
  }else{
   printf("0,\t\t");
  }
 }
 printf("}%c\n",strcmp(varname,"root")?',':';');
}

EXTERN_C void mainCRTStartup() {
 char line[256];
 std::vector<const char*>names;
 int stringsize=0;
 while (fgets(line,256,stdin)) {
  char*t=strchr(line,'\t');
  if (t && t!=line) {
   *t=0;
   char*e=strchr(++t,'\n');
   if (e) *e=0;
   const char*nn=0;
   for (const char**in=names.begin(); in!=names.end(); in++) {
    if (!strcmp(*in,t)) {nn=*in; break;}
   }
   if (!nn) {
    nn=_strdup(t);
    names.push_back(nn);
    int l=strlen(nn);
//    if (l>20) l=16;	// max. 20 oder 16 Zeichen annehmen für ATmega-Implementierung
    stringsize+=l;
   }
   Node::insert(root,line,nn);
  }
 }
 printf("typedef const char* Node[10];\n");
 printf("static const Node\n");
 root->emit("root");
 printf("//nodecount: %d (%d bytes)\n",nodecount,nodecount*20);
 printf("//stringsize: %d (%d strings)\n",stringsize,names.size());
 printf("//needflash: %d ohne \\0, %d mit \\0\n",nodecount*20+stringsize,nodecount*20+stringsize+names.size());
 ExitProcess(0);
}
// Lösung für AVR-Mikrocontroller:
// Die 840 Einträge lange Nodeliste in ein Array packen
// und durch negative Indizes adressieren (max. -839).
// Die Strings: Umlaute durch 7-Bit-ASCII ersetzen ('Ä'='[' usw.)
// und Strings mit gesetztem Bit 7 terminieren.
// Dann genügen 16 Bit für alle Adressen,
// ohne (statt der möglichen Adressierung mit Stringnummer)
// 60 KB Flash parsen zu müssen.
// Auch gut für einen 128-KB-seriellen EEPROM 24FC1025 geeignet,
// da zur Nummernsuche nur wenige Zugriffe erforderlich sind
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded