/* Copyright (C) 2020 Gentoo-libre Install
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 3 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, see .
*/
#include
#include
#include //store if number is negative
//powq(): square roots
unsigned long powq(int number, int power)
{
unsigned long result = 1;//result int, 1 by default
if (!power){return 1;}//if to the power of 0, return 1
while(power)//loop until all powers have been calculated
{
result *= number;//in the end result=number*number*number*etc until power is reached
--power;//--power since a power has been calculated
}
return result;
}
//itoh(): Convert a string of decimal numbers to a string of hex. (No negative input num handling, no invalid char handling and ignores overflows)
void itoh(char s[], char *result)
{
int i; //counter variable
for(i=0;i<16;++i){result[i]='0';}//zero out the result string (16 chars due to that being the size of unsigned long long int max)
int power = 0; //int to store the power.
while(s[power] != '\0'){++power;}//increment power for however many non-null chars in the string.
--power;//The correct power is actually one less than above returns
unsigned long long integer = 0; //the variable in which the integer result from the input string is stored.
i=0;//reset the counter int
while (s[i] != '\0')//convert the string of decimal numbers into a long long int
{
if (s[i] >= '0' && s[i] <= '9'){integer += ((s[i] - '0') * powq(10,power));}//integer = integer + ([char converted to number] * (10^[position of number in string]))
++i;
--power;//Deincrement the power. E.g. ([charvalue]*(10^3))+([nextcharvalue]*(10^2)) etc
}
//convert the long long into a string of ASCII hex
i=15;//Write string right to left
int temp;
while(integer)
{
temp = (integer % 16);//temp = value to encode into ASCII char
if ((temp>=0)&&(temp<=9)){result[i] = temp + '0'; goto skip;}//if temp is 0-9, convert that to a digit and skip checking for A-F
if ((temp>=10)&&(temp<=15)){result[i] = temp + 55;}//if temp is 10-15, convert that to A-F
skip: integer/=16;//divide integer by 16 to allow generating the next ASCII char
--i;//write to the next digit to the left
}
}
int main(int argc, char *argv[])
{
bool negative = false; //handle negative numbers
if (!argv[1]){goto stdinMode;}
if (argv[1][1] == '-')
{
printf("Usage (stdin mode): %s\n", argv[0]);
printf("Ctrl+D to exit\n");
printf("Usage (cli args mode): %s [decnum]\n", argv[0]);
printf("Licence: AGPLv3\n");
return 0;
}
//result hex string, passed to itoh();
char *cli = malloc(17*sizeof(char));
if (!cli){printf("Malloc failed!\n"); return 1;}
cli[16]='\0';//add null terminating char
//strip out invalid chars from the input string
if (argv[1][0] == '-'){negative = true;}//handle negative numbers
int a,q;//counter variables
for (a=0; argv[1][a] != '\0'; ++a)
{
if ((argv[1][a] < '0')||(argv[1][a] > '9'))//if argv[1][i] is a character to remove....
{
q=a;
while(argv[1][q] != '\0'){argv[1][q++] = argv[1][q+1];}//shift all characters above left, overwriting the character
--a;//deincrement a, since the string was just shrunk by one and the one just above could indeed be a matching char
}
}
itoh(argv[1], cli);
if (negative){printf("-%s\n",cli); free(cli); return 0;}//handle negative numbers
printf("%s\n",cli);//print string with all leading 0's
free(cli);
return 0;
stdinMode: ;
//input decimal string, by default 10 chars long
int size = 10;
char *input = malloc(size*sizeof(char));
if (!input){printf("Malloc failed!\n"); return 1;}
//result hex string
char *result = malloc(17*sizeof(char));
if (!result){printf("Malloc failed!\n"); return 1;}
result[16]='\0';//add null terminating char
int i;
nextnum: i=0;
char c;
while ((c=getchar())!='\n')
{
if (c==EOF){free(result); free(input); exit(0);}//exit if EOF
if (i>size-2){size+=4; input=realloc(input,size*sizeof(char)); if (!input){printf("Realloc failed!\n"); return 1;}}//relloc if the input string is longer than size
input[i]=c;//write c to the string
++i;
}
input[i] = '\0'; //add NULL char for itoh
//strip out invalid chars from the input string
if (input[0] == '-'){negative = true;}//handle negative numbers
int j;//another counter variable
for (i=0; input[i] != '\0'; ++i)
{
if ((input[i] < '0')||(input[i] > '9'))//if input[i] is an invalid character
{
j=i;
while(input[j] != '\0'){input[j++] = input[j+1];}//shift all characters above left, overwriting the character
--i;//deincrement i, since the string was just shrunk by one and the one just above could indeed be a matching char
}
}
itoh(input, result);//itoh(): Given input string and a pointer to the result string
i=0;
while(result[i] == '0'){++i;}//increment i until a non-0 char is found
if (i == 16){--i;}//if all characters are 0, leave a 0 so the string isn't null
int x;//another counter variable
if (i){for(x=0;result[i-1]!='\0';++x){result[x]=result[i];++i;}}//copy non-0 characters to the left so there aren't any 0's in front of the output number. (Also don't do this if i=0 (there are no 0's))
if (negative){printf("Hexadecimal: -0x%s\n",result); negative = false; goto nextnum;}//handle negative numbers
printf("Hexadecimal: 0x%s\n",result);
goto nextnum; //process another number
//these won't be reached, but included anyway in case the above goto is removed
free(input);
free(result);
return 0;
}