#!/bin/bash
################################################################################
# Script shell:	base.sh - affiche un nombre en différentes bases (Bourne Shell)
# Auteur      :	Heiner Steven (heiner.steven@odn.de)
# Date        :	07-03-95
# Catégorie   :	Desktop
# $Id: base.sh,v 1.10 2008-05-10 08:36:11 gleu Exp $
# ==> La ligne ci-dessus est l'information ID de RCS.
################################################################################
# Description
#
# Modifications
# 21-03-95 stv	correction d'une erreur arrivant avec 0xb comme entrée (0.2)
################################################################################

# ==> Utilisé dans le guide ABS avec la permission de l'auteur du script.
# ==> Commentaires ajoutés par l'auteur du guide ABS.

NOARGS=65
PN=`basename "$0"`			           # Nom du programme
VER=`echo '$Revision: 1.10 $' | cut -d' ' -f2`  # ==> VER=1.6

Usage () {
    echo "$PN - Affiche un nombre en différentes bases, $VER (stv '95)
usage: $PN [nombre ...]

Si aucun nombre n'est donné, les nombres sont lus depuis l'entrée standard.
Un nombre peut être
    binaire (base 2)		commençant avec 0b (i.e. 0b1100)
    octal (base 8)		commençant avec 0  (i.e. 014)
    hexadécimal (base 16)	commençant avec 0x (i.e. 0xc)
    décimal			autrement (c'est-à-dire 12)" >&2
    exit $NOARGS 
}   # ==> Fonction pour afficher le message d'usage.

Msg () {
    for i   # ==> [liste] manquante.
    do echo "$PN: $i" >&2
    done
}

Fatal () { Msg "$@"; exit 66; }

AfficheBases () {
    # Détermine la base du nombre
    for i      # ==> [liste] manquante...
    do         # ==> donc opère avec le(s) argument(s) en ligne de commande.
	case "$i" in
	    0b*)		ibase=2;;	# binaire
	    0x*|[a-f]*|[A-F]*)	ibase=16;;	# hexadécimal
	    0*)			ibase=8;;	# octal
	    [1-9]*)		ibase=10;;	# décimal
	    *)
		Msg "nombre illégal $i - ignoré"
		continue;;
	esac

	#  Suppression du préfixe, conversion des nombres hexadécimaux en
	#+ majuscule (bc a besoin de cela)
	number=`echo "$i" | sed -e 's:^0[bBxX]::' | tr '[a-f]' '[A-F]'`
	# ==> Utilise ":" comme séparateur sed, plutôt que "/".

	# Conversion des nombres en décimal
	dec=`echo "ibase=$ibase; $number" | bc`  # ==> 'bc' est un utilitaire de
	                                         #+ calcul.
	case "$dec" in
	    [0-9]*)	;;			 # nombre ok
	    *)		continue;;		 # erreur: ignore
	esac

	# Affiche toutes les conversions sur une ligne.
	# ==> le 'document en ligne' remplit la liste de commandes de 'bc'.
	echo `bc <<!
	    obase=16; "hex="; $dec
	    obase=10; "dec="; $dec
	    obase=8;  "oct="; $dec
	    obase=2;  "bin="; $dec
!
    ` | sed -e 's: :	:g'

    done
}

while [ $# -gt 0 ]
# ==>  est une "boucle while" réellement nécessaire
# ==>+ car tous les cas soit sortent de la boucle
# ==>+ soit terminent le script.
# ==> (commentaire de Paulo Marcel Coelho Aragao.)
do
    case "$1" in
	--)	shift; break;;
	-h)	Usage;;                 # ==> Message d'aide.
	-*)	Usage;;
	*)	break;;			# premier nombre
    esac   #  ==> Plus de vérification d'erreur pour des entrées illégales
           #+ serait utile.
    shift
done

if [ $# -gt 0 ]
then
    AfficheBases "$@"
else					#  lit à partir de l'entrée standard
                                        #+ stdin
    while read ligne
    do
	PrintBases $ligne
    done
fi

exit 0
