/* kleinkram.cc			letzte Änderung: 23.1.2012 */
const char *VERSION="Version 0.1"; //Programm-Version

#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif

#include <stdio.h>
#if GCC_VERSION<3000
#include <stream.h>
#else
#include <iostream>
using namespace std;
#endif

//fast immer gebraucht:
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

//beim Umgang mit Dateien:
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>

static int test=0;

/*************************** kleinkram ***************************/

/*********************** Zufallszahlen ***************************/
inline double random11()	// Zufallszahl zwischen -1. und 1.
{
 return (1. - rand()/1073741824.);//Variante fuer VAX/ALPHA
}
inline double random01()        // Zufallszahl zwischen 0. und 1.
{
 return (1. - rand()/(double)RAND_MAX);//Variante fuer VAX/ALPHA
}

double zufall(double y=0.);
double zufall(double y)  /* liefert Zufallszahl zwischen 0.0 und 1.0      */
{			 /* ergibt aber Streifen im Flächentest in rndcheck */
 static double x=1.3757;
 if(y!=0.) x=y;
 x=(100.+x)/(100.*(x-(long)(x))+0.7);
 y=10.*x;
 return (y-(long)(y));
}

double zufall3()	/* Zufallszahl zwischen 0.0 und 1.0 */
{			/* ergibt aber Unregelmässigkeiten im Zombitest */
 static double x=1.7;
 double y;
 if(x==0.) x=1.7;
 if(x>100.) x=x/1163.;
 else x*=773.;
 y=10.*(x-(long)(x));
 return (y-(long)(y));
}

double zufall4()	/* Zufallszahl zwischen 0.0 und 1.0 */
{			/* bisher bester Zufallsgenerator   */
 static double x=581;
 double y;
 if(x==0.) x=581;
 x/=1.163;
 x-=(long)(x);
 y=10.*x;
 x*=1000.;
 return (y-(long)(y));
}

#include <time.h>
double zufall5(int start=0)
{
 static int flag=1;
 if(flag!=0 || start!=0)
  {time_t t;
   time(&t);
   srand(t);
   flag=0;
  }
 return (1.0 - rand()/(double)RAND_MAX);
}

/************************* Stringfunktionen *************************/
void getzeile(FILE *fp,char *s)
{		/* liest Zeile samt Zeilentrenner und schliesst mit 0 ab */
 while ((*s++ = getc(fp)) != '\n')
	;
 *s=0;
}

int getline(FILE *fp,char *s,int lim)
{		/* liest eine Textzeile oder maximal lim Zeichen */
		/* und ersetzt den Zeilentrenner durch 0         */
 int c;
 while(--lim && (c=getc(fp))!=EOF && c!='\n')
	*s++ = c;
 *s='\0';
 return (c!=EOF);	/* TRUE wenn erfolgreich, FALSE wenn Fileende */
}

void putline(FILE *fp,const char *s) /* wie fprintf(fp,"%s\n",s)  aber */
{				     /* ohne ein Nullbyte zu schreiben */
 char c;
 while(c= *s++)  putc(c,fp);
 putc('\n',fp);
}

int ascitodigit(int c)
{		/* wandelt ein ASCI-Zeichen in eine 1-stellige Hex-Zahl */
 if(!isxdigit(c)) return 0;
 if(islower(c)) c=toupper(c)-'0';
 else c-='0';
 if(c>9) c += '0'-'A'+10;
 return c;
}

char *ohnepunkt(char *name)  /* in name alles ab erstem '.' loeschen */
{
 char c,*s=name;
 while((c= *s)!='.' && c!=0) s++;
 if(c=='.') *s='\0';
 return name;
}

char *ohneletztenpunkt(char *name)  /* die Endung .xxx loeschen */
{
 char c=0,*s; int i;
 for(i=0,s=name;*s!=0;s++,i++) ;
 while(i>0 && (c= *s)!='.')
        {--i; --s;}
 if(c=='.') *s='\0';
 return name;
}

bool hatpunkt(const char *name,int c='.')
{
 int c2;
 while(c2= *name++) if(c2==c) return true;
 return false;
}

void ohnepfad(char *ziel,const char *name,int max)
{
 char c,*z;
 const char *s;
 int i;
 for(i=0,s=name;*s!=0;s++,i++) ;
 while(i>0 && (c= *s)!='/' && c!=':' && c!='\\')
	{--i; --s;}
 for(i=1,z=ziel;i<max && (c= *s++)!=0;i++)
	*z++ = c;
 *z=0;
}

void stradd(const char *s,const char *t,char *z)	/*  s + t --> z */
{
 char c;
 while (c = *s++) *z++ = c;
 while (*z++ = *t++)	;
}

char *anhaengen(char *s,const char *t)  /* s + t --> s */
{
 char *p;
 for(p=s;*p!=0;p++) ;
 for(;*p++ = *t++;) ;
 return s;
}

char *endungersetzen(char *neu,const char *name,const char *endung)
{
 strcpy(neu,name); ohneletztenpunkt(neu);
 return anhaengen(neu,endung);
}

void spri(char *s,char *cstr,long x=0L,long y=0L,long z=0L)
{			/* wie sprintf(s,cstr,x,y,z) aber ohne Nullbyte */
 char c,*p;
 char *hstr=new char[80];
 sprintf(hstr,cstr,x,y,z);
 for(p=hstr; c= *p++;)  *s++ = c;
 delete hstr;
}

int linput(FILE *fp,char *str,int lim,int c,char *zeigerfeld[])
{		/* Liest eine Zeile ein und erzeugt     */
		/* einen Zeiger auf jedes Element, das  */
		/* jeweils mit '\0' abgeschlossen wird. */
		/* lim=Laenge von str  c=Trennzeichen (z.B.',') */
		/* das Zeigerfeld muss genug lang sein */
 char *p;
 int anf=0,i;
 if(!getline(fp,str,lim)) return EOF;
 for(p=str,i=0; *p!=0; i++)
   {zeigerfeld[i]=p;
    while(*p==' ' || *p=='\t')	p++;
    if(*p=='"' || *p=='\'')
	{anf= *p++; zeigerfeld[i]=p;}
    while(*p!=0 && *p!=c)
	{if(*p==anf) *p=0;
	 p++;
	}
    if(*p==c) *p++=0;
   }
 zeigerfeld[i]=NULL;
 return i;
}

int strcmpg(char *s,char *t)
{       /* Stringvergleich ohne Gross-Klein Unterscheidung */
 int c1,c2;
 do     {c1= *s++; c2= *t++;
         if(c1==0 && c2==0) return 0;/* Strings gleich */
         if(c1!=c2)
           {if(isupper(c1)) c1=tolower(c1);
            if(isupper(c2)) c2=tolower(c2);
        }  }
 while(c1==c2);
 return c1-c2;/* ungleich */
}

char *machgross(char *s)
{
 char *t;
 int c;
 t=s;
 while(c= *t)  *t++ = toupper(c);
 return s;
}

int index(const char *s1,const char *s2)
{	             /* Sucht den String s2 innerhalb von s1           */
 int i,c;	     /* und gibt Position zurueck (nicht gefunden: -1) */
 const char *p1,*p2;
 if(*s2==0) return 0;   /* leerer String ist immer enthalten */
 for(i=0;;i++)
	{if((c= *s1++)==0) return -1; /* nicht gefunden */
	 if(c== *s2)
		{for(p1=s1,p2=s2; c= *++p2;)
			if(*p1++!=c) break; /* noch nicht gefunden */
		 if(c==0) break; /* gefunden */
		}
	}
 return i;
}

char *strkopie(const char *s1)
{
 char *s=new char[strlen(s1)+1], *t;
 for(t=s;*t++ = *s1++;)  ;
 return s;
}

/************************* Grafikfunktionen *************************/
#include <xtekplot1.h>
//const int PENUP=3;
//const int PENDOWN=2;
//extern void plot(double,double,int); //schon in xtekplot1.h definiert

static double	cosalfa=0.994521895368273,
		sinalfa=0.104528463267653;
static int	n_ecken=60;
void initkreis(int n)	/* initialisiert schnellen Kreisalgorythmus */
{			/* mit Verwendung eines n-Ecks		    */
 double alfa;
 alfa=6.283185307/(n_ecken=n);
 cosalfa=cos(alfa); sinalfa=sin(alfa);
}
/*
void kreis(double x,double y,double r)	// zeichnet Kreis
{
 double dx,dx2,dy;
 int m;
 dx=0.; dy=r;
 plot(x+dx,y+dy,PENUP);
 for (m=n_ecken;m>0;--m)
	{dx2=dx*cosalfa+dy*sinalfa;
	 dy= dy*cosalfa-dx*sinalfa;
	 dx=dx2;
	 plot(x+dx,y+dy,PENDOWN);
	}
}

/************************* Astronomie *************************/
static int montab[]={31,28,31,30,31,30,31,31,30,31,30,31};

int jahrestag(int tag,int monat,int jahr)  /* bestimmt n-ten Tag im Jahr */
{
 int jtag,i;
 if(jahr%4==0 && jahr%100!=0 || jahr%400==0)	montab[1]=29;
 else						montab[1]=28;
 for(i=monat-2,jtag=tag; i>=0; i--)
	{jtag += montab[i];}
 return jtag;
}

void datum(int tag,int jahr,int *pmtag,int *pmonat)
{			/* bestimmt Datum des n-ten Tags im Jahr */
 int i=0;
 if(jahr%4==0 && jahr%100!=0 || jahr%400==0)	montab[1]=29;
 else						montab[1]=28;
 while(tag>montab[i]) tag -= montab[i++];
 *pmonat=i+1; *pmtag=tag;
}

/************************* Einzeiler *************************/
inline double sq(double x) {return x*x;}	/* Quadrieren */
inline long idfix(double x) {return long((x>=0.) ? x+0.5 : x-0.5);} //Runden
inline double abs(double x) {return (x<0.) ? -x : x;}	/* Betrag */

/************************* Konstanten *************************/
const double Pi =	3.14159265358979;
//const double ZWEIPI =	6.28318530717959;
const double PI = 4*atan(1.0), ZWEIPI=2*PI;
const double E	=	2.71828182845905;
#define WURZ10  3.16227766016838

/************************ Zahlen jonglieren ************************/

double rundezahl(double x,double y)  /* eine Runde Zahl zwischen x und y */
{
 static double rund[]={5.,8.,6.,4.,2.,9.,7.,3.,1.};
 double z1,z2,z3;
 int i;
 if(x<0.) return -rundezahl(-x,-y);
 if(y<0.) return 0.;
 if(x<y) {z1=x; x=y; y=z1;}
 if(x>=1.) /* 1 10 100 1000 ... */
  {for(z1=1.;z1<=x; z1*=10.)  if(z1>=y) return z1;
   z1/=10.;
  }
 else      /* 0.1 0.01 0.001 .... */
  {for(z1=0.1;z1>=y; z1*=0.1)  if(z1<=x) return z1;
  }
 for(i=0;i<8;i++) /* Test auf Gleichheit der ersten Ziffer */
        if((z2=z1*rund[i])<=x && z2>=y) return z2;
 for(z2=z1+z1;z2<x;z2+=z1)
        ;
 z2-=z1; /* z2 = erste Ziffer */
 while(z1>0.)
  {z1/=10.;
   for(i=0;i<9;i++)
        if((z3=rund[i]*z1+z2)<=x && z3>=y) return z3;
   for(z3=z1;z2+z3<x;z3+=z1)
                ;
   z2+=z3-z1;
  }
 return y; /* Fehler: x==y, keine runde Zahl */
}

double dmod(double x,double y)	/* Rest einer Fliesszahldivision */
{
 int n;
 x=x/y;
 n=(int)x;
 return (x-n)*y;
}

double xhochn(double x,int n)	/* Potenzieren mit Ganzzahligem Exponenten */
{
 double z=1.0;
 if(n>=0)
   while(n>0)
        {if(n&1) {z*=x; n--;}
         else    {x*=x; n=(n>>1);}
        }
 else
        z=1.0/xhochn(x,-n);
 return z;
}

int fastgleich(double x,double y,double diff)
{		/* Teste ob x==y innerhalb der Genauigkeit diff */
 double d;
 if(diff<0.) diff= -diff;
 if(x>y) d=x-y; else d=y-x;
 return (d<diff);
}

/********************** Fouriertransformation ****************************/
void bitschuettler(double *rfeld,double *ifeld,int n)
{
 register int m,k,j; double hr,hi;
 for(j=1;j<n-1;j++)
    {k=0; m=j+n;
     do	{k += k + (m&1);	/* unterstes Bit von m links ins k schieben */
	 m >>= 1;		/* m 1 Bit nach rechts schieben */
	}
     while (m>1);	/* k= Bitreverse(j) */
      if (k<j)	{hr= rfeld[j]; hi= ifeld[j];
		 rfeld[j]= rfeld[k]; ifeld[j]= ifeld[k];
		 rfeld[k]= hr; ifeld[k]= hi;
    }		}
}
void fft(double *rfeld,double *ifeld,int *pn,int *pinv)
{
 int n= *pn, inv= *pinv, k,zweik,m;
 register int i,j;
 double a,treal,timag,wreal,wimag;
/* if(n>=4) j=n; else j=3;
/* while (j%2==0) j/= 2;	/* n auf die Form 2^k testen */
/* if(j!=1)  { printf("Error: ungueltiges n:%d",n); exit();} */
 bitschuettler(rfeld,ifeld,n);
 for(k=1; k<n; k=zweik)
  {zweik=k+k;
   for (m=0; m<k; m++)
       {wreal= cos(a=m*PI/k);
	wimag= (inv==1) ? sin(a) : -sin(a);
	for (i=m; i<n; i+= zweik)
	  {j=i+k;
	   treal= wreal*rfeld[j] - wimag*ifeld[j];
	   timag= wreal*ifeld[j] + wimag*rfeld[j];
	   rfeld[j]= rfeld[i]-treal; ifeld[j]= ifeld[i]-timag;
	   rfeld[i] += treal; ifeld[i] += timag;
  }    }  }
 if(inv==1)
	for(i=0;i<n;i++) {rfeld[i] /= n; ifeld[i] /= n;}
}

void dft(int nn,int inv,double *a,double *b,double *ya,double *yb)
{
 double m2pi,z,sinz,cosz,*pa,*pb;
 int m,n,Nhalbe=nn/2;
 for(m=0;m<nn;m++)
  {if(inv) m2pi= m*PI/Nhalbe;
   else m2pi= -m*PI/Nhalbe;
   *ya = *a;
   *yb = *b;
   for(pa=a,pb=b,n=0;++n<nn;)
	{z=n*m2pi;
	 *ya += *++pa*(cosz=cos(z)) - *++pb*(sinz=sin(z));
	 *yb += *pa*sinz + *pb*cosz;
	}
   if(inv) {*ya++ /= nn;  *yb++ /= nn;}
   else    {ya++; yb++;}
  }
}

/************************** Ein/Ausgaben *********************************/
void inputd(char *s,int *x) {printf("(%d) %s",*x,s); scanf("%d",x);}
void inputf(char *s,double *x) {printf("(%lf) %s",*x,s); scanf("%lf",x);}

/********************** Umgang mit Dateien *******************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

bool vorhanden(const char *dateiname)
{
 struct stat buf;
 return (lstat(dateiname,&buf)>=0);
}

bool istordner(char *dateiname)
{
 struct stat buf;
 if(lstat(dateiname,&buf)<0) return false;
 //if(buf.st_mode & S_IFDIR) return true;
 if((buf.st_mode & S_IFMT)==S_IFDIR) return true;
 return false;
}
bool istregulaer(char *dateiname) //Regulaere Datei ohne Softlink ohne Ordner
{
 struct stat buf; //siehe man lstat
 //(Fehler in man lstat: S_IFMT ist nicht 0017000 sondern 0170000)
 if(lstat(dateiname,&buf)<0) return false;
 if((buf.st_mode & S_IFMT)==S_IFREG) return true;
 return false;
}
bool istsoftlink(char *dateiname)
{
 struct stat buf;
 if(lstat(dateiname,&buf)<0) return false;
 if((buf.st_mode & S_IFMT)==S_IFLNK) return true;
 return false;
}

bool istbilddatei(const char *name) //Bilddatei anhand der Endung
{
 int n=strlen(name);
 if(n<5) return false;
 if(name[n-4]=='.')
   return (strcmp(&name[n-3],"jpg")==0 || strcmp(&name[n-3],"JPG")==0 ||
	   strcmp(&name[n-3],"gif")==0 || strcmp(&name[n-3],"GIF")==0 ||
	 //strcmp(&name[n-3],"ppm")==0 || strcmp(&name[n-3],"PPM")==0 ||
	   strcmp(&name[n-3],"png")==0 || strcmp(&name[n-3],"PNG")==0);
 else if(n>5 && name[n-5]=='.')
   return (strcmp(&name[n-4],"jpeg")==0 || strcmp(&name[n-4],"JPEG")==0);
 return false;
}

int anzahlblanks(const char *s) //zaehle Anzahl Leerstellen im String
{                               //und Klammern auch
 int c,n=0;
 while((c= *s++)!=0)
    if(c==' ' || c=='(' || c==')') n++;
 return n;
}

char *escapeblanks(const char *s,int nb)
{
 char *name2=new char[strlen(s)+nb+1];
 char *p=name2;
 int c;
 while((c= *s++)!=0)
   {if(--nb>=0 && (c==' ' || c=='(' || c==')'))
       *p++ = '\\'; //vor jede Leerstelle oder Klammer ein \ setzen
    *p++ = c;
   }
 *p=0;
 return name2;
}

char *entferneblanks(const char *s)
{
 char *name2=new char[strlen(s)+1];
 char *p=name2;
 int c;
 while((c= *s++)!=0)
   {if(c==' ' || c=='(' || c==')')
       c = '_'; //Leerstelle oder Klammer durch _ ersetzen
    *p++ = c;
   }
 *p=0;
 return name2;
}

const int MAXL=1000;

class Aktuellerpfad
{
 char *pfad;
 char *liste[MAXL];//fuer Speicherrueckgabe
 int imax;
public:
 Aktuellerpfad() {pfad=NULL; imax=0;}
 ~Aktuellerpfad() {if(pfad!=NULL) delete[] pfad; loeschen();}
 void set(const char *arg0)
	{char *s; int n=strlen(arg0);
	 if(pfad!=NULL) delete[] pfad;
	 pfad=new char[n+1];
	 strcpy(pfad,arg0);
	 for(s= &pfad[n];*--s!='/';) ;
	 *s=0;
	 setenv("PWD",pfad,1);
	}
 void cd(const char* ordner);
 FILE *fopen2(const char *name,const char *rw);
 const char *vollpfad(const char *name);
 char *getpfad() {if(pfad) return pfad; else return getenv("PWD");}
 void loeschen() {while(imax>0) delete[] liste[--imax];}
};
void Aktuellerpfad::cd(const char* ordner)
{
 const char *s,*altpfad=pfad;
 if(ordner[0]=='/') s="";
 else if(altpfad==NULL) s=getenv("PWD");
 else s=altpfad;
 int n=strlen(s)+strlen(ordner)+2;
 pfad=new char[n];
 if(*s==0) strcpy(pfad,ordner);
 else sprintf(pfad,"%s/%s",s,ordner);
 while(!istordner(pfad) && (n=strlen(pfad))>1)
   {while(--n>1 && pfad[n]!='/') ;
    pfad[n]=0;
   }
 if(altpfad) delete[] altpfad;
}
FILE *Aktuellerpfad::fopen2(const char *name,const char *rw)
{
 FILE *fp;
 if(pfad!=NULL && *name!='/')
  {char str[strlen(pfad)+strlen(name)+2];
   sprintf(str,"%s/%s",pfad,name);
   fp=fopen(str,rw);
  }
 else fp=fopen(name,rw);
 return fp;
}
const char *Aktuellerpfad::vollpfad(const char *name)
{
 if(name==NULL || *name=='/' || pfad==NULL) return name;
 char *name2=NULL;
 int nb;
 if((nb=anzahlblanks(name))>0) //falls in name Leerstellen sind
   name=name2=escapeblanks(name,nb);
 char vollname[strlen(pfad)+strlen(name)+2];
 sprintf(vollname,"%s/%s",pfad,name);
 int i;
 for(i=0;i<imax;i++)
   if(strcmp(vollname,liste[i])==0) {return liste[i];}
 char *str=new char[strlen(vollname)+1];
 strcpy(str,vollname);
 if(imax<MAXL)
   {liste[imax++]=str;
    if(imax==MAXL && test>0)
      printf("Aktuellerpfad::vollpfad() liste fuer Speichrrueckgabe voll.\n");
   }
 if(name2!=NULL) delete[] name2;
 return str;
}

static Aktuellerpfad pwd;
inline FILE *fopen2(const char *na,const char *rw) {return pwd.fopen2(na,rw);}
inline const char *vollpfad(const char *s) {return pwd.vollpfad(s);}
inline bool vorhanden2(const char *name) {return vorhanden(vollpfad(name));}

#include <errno.h>
void fehlermeldung(int err)
{
 if(err== -1) err=errno;
#ifdef EEXIST
 if(err==EEXIST) printf("EEXIST - Datei schon vorhanden.\n");
 else if(err==EROFS) printf("EROFS - nur lesbar\n");
 else if(err==ENOMEM) printf("ENOMEM - nicht genug Kernelspeicher\n");
 else if(err==EACCES) printf("EACCES - kein Schreibrecht\n");
 else
#endif
    printf("Fehlercode %d: siehe 'more /usr/include/asm*/errno*.h'\n",err);
}

/******************* andere Programme aufrufen ***************************/
const int N80=80;//maximal vorkommende Laenge eines Dateinamens

void system1(const char *s,int k)
{
 if(test>=2) printf("system%d> %s\n",k,s);
 int n=system(s);
 if(n!=0)
   {if(n==127) printf("Fehler %d in system(): fehlendes /bin/sh\n",n);
    else if(n<0) {printf("Fehler %d in system(%s)\n",n,s); fehlermeldung(n);}
    else if(test>=2) printf("Rueckgabewert von system() = %d\n",n);
   }
}
void system2(const char *s,const char *p1,const char *p2=NULL)
{
 char str[3*N80];
 sprintf(str,s,vollpfad(p1),vollpfad(p2));
 system1(str,2);
}
void system3(const char *s,int p1,const char *p2,const char *p3)
{
 char str[3*N80];
 sprintf(str,s,p1,vollpfad(p2),vollpfad(p3));
 system1(str,3);
}

/**************** Routinen zur Parameterauswertung ********************/
//aus start.cc
#define MAXARG 2
static char argflag[128];
//static test=0;
void setargflags(char *s)
{
 int c;
 while(c= *s++)
  {if(c>='a' && c<='z')  c -= 'a'-'A';
   argflag[c&127]=1;
   if(c=='V') test++;
  }
}

/************************* Hauptprogramm ******************************/
main(int argc,char *argv[])
{
 char quellname[80],zielname[80];
 FILE *fp1,*fp2;
 int i,j,c;
 quellname[0]=zielname[0]=0;
 if(argc<=0)
   /* es wurde von WorkBench gestartet */
   ;
 else
   /* es wurde von der Shell gestartet */
   for(j=0,i=1;i<argc;i++)
	{if((c= *argv[i])=='-' || c=='?') setargflags(argv[i]);
	 else	{if(++j==1) strcpy(quellname,argv[i]);
		 else if(j==2) strcpy(zielname,argv[i]);
	}	}
 if(argflag['?'] || j>MAXARG)
	{printf("kleinkram  %s\n",VERSION);
	 printf("Anwendung: Unterprogramme mit copy/paste in\n");
	 printf("           eigenes Programm einfuegen\n");
	 exit(0);
	}
 printf("Dies ist kein sinnvolles Programm, sondern eine\n");
 printf("Sammlung von kleinen Unterprogrammen fuer C und C++\n");

 //diverse Tests:
 printf("Teste Zufallszahlen: ");
 for(i=0;i<10;i++) printf("%f ",zufall5());
 printf("\n");

 return 0;
}/* ende von main */
