/*	numconv.c -- Programm unter GPL, (c) RTC @ 2003				*/
/*	Programm konvertiert eine auf der Kommandozeile angegebene		*/
/*	Dezimalzahl in ein anderes Zahlensystem					*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/* ---- Funktions-Prototypen --------------------------------------------------	*/
int pruefe_doppelstrich(char *wort);
long int pruefe_zahl(char *wort);

/* ---- main() ----------------------------------------------------------------	*/
int main(int argc, char **argv){
		int i, fehler=0, binaer=0, oktal=0, hexa=0, zaehlzahl=0;
		long int zahl=0, hilfzahl=0;
		char *progname=argv[0], *zgr;

		/* solange noch Argumente vorhanden sind und diese mit einem Doppelstrich bzw. mit einer Zahl beginnen */
		while(--argc>0 && (pruefe_doppelstrich(*(++argv))==1 || (hilfzahl=pruefe_zahl(argv[0]))!=0)){
			/* wenn sie mit einem Doppelstrich beginnen */
			if(hilfzahl==0){
				/* werte alle Optionen hinter dem Doppelstrich aus */
				for(zgr=argv[0]+2; *zgr!='\0' && fehler==0; ++zgr){
					/* prüfe jeweilige Option auf Richtigkeit */
					switch(*zgr){
						case 'b':
							binaer=1;
							break;
						case 'o':
							oktal=1;
							break;
						case 'h':
							hexa=1;
							break;
						default:
							printf("... Unerlaubte Option: --%c\n", *zgr);
							fehler=1;
							break;
					}
				}
			}
			else{ //wenn eine Zahl erkannt wurde
				++zaehlzahl;
				zahl=hilfzahl;
				hilfzahl=0;
			}
		}

		/* wenn keine Option angegeben wurde, dann führe den Standard aus */
		if(binaer==0 && oktal==0 && hexa==0 && zaehlzahl==1)
			binaer=oktal=hexa=1;

		/* nur weitermachen, wenn nur eine Zahl eingegeben wurde und keine falsche Option */
		if(zaehlzahl==1 && fehler==0){
			printf("%20s: %ld\n", "Dezimal", zahl);
			if(binaer==1){
				printf("%20s: ", "Dual");
				for(i=sizeof(zahl)*8-1; i>=0; --i)
					printf("%ld%s", (zahl>>i) & 1, (i%8==0) ? " " : "");
				printf("\n");
			}
			if(oktal==1)
				printf("%20s: %#lo\n", "Oktal", zahl);
			if(hexa==1)
				printf("%20s: %#lx\n", "Hexadezimal", zahl);
		}
		/* ansonsten usage-Meldung ausgeben */
		else{	printf(	"usage: %s [--boh] Dezimalzahl\n"
				"  --b  Binaerzahl\n"
				"  --o  Oktalzahl\n"
				"  --h  Hexadezimalzahl\n", progname);
			if(zaehlzahl!=1)
				printf("... Es muss genau eine Zahl angegeben werden!\n");
		}

		return 0;
}


/* ---- pruefe_doppelstrich() -------------------------------------------------- */
int pruefe_doppelstrich(char *wort){
	int i;
	/* schauen, ob die beiden ersten Zeichen zwei Striche sind */
	for(i=1; i<3; ++i)
		if(*(wort++)!='-')
			return 0;
	return 1;
}

/* ---- pruefe_zahl() ---------------------------------------------------------	*/
long int pruefe_zahl(char *wort){
	char *zgr=wort;
	/* wenn das erste Zeichen ein Minuszeichen oder eine Ziffer ist */
	if(zgr[0]=='-' || isdigit(zgr[0]))
		/* solange auf Ziffern überprüfen, bis das Wort zu Ende ist */
		while(*(++zgr)!='\0'){
			if(!isdigit(zgr[0]))
				return 0;
		}
	else
		return 0;
	/* die Zahl umgewandelt zurückgeben */
	return strtol(wort, NULL, 10);
}

