#include #include #include #include #define LONGMIN 0x8000000000000000 #define RED "\x1b[91m" #define GRN "\x1b[92m" #define RST "\x1b[0m" /* segfaults if x = 0x8000000000000000 */ char* tobin(long int x) { size_t i = 0, j = 0; char buffer[64]; char *ret; char sgn = x < 0; x *= ((x > 0) << 1) - 1; /* Negate the number without if statement */ for (; x; x >>= 1) buffer[i++] = '0' + (x & 1); /* Write the bits to the buffer */ ret = calloc(i + 1 + sgn, sizeof *ret); /* Allocate an arary for the number */ ret[0] = '-'; /* Always write minus as the first sign*/ j += sgn; /* If sign is negative, increment j so that '-' is not overwritten */ while (i) ret[j++] = buffer[--i]; /* reverse copy buffer into ret */ return ret; } void handle_main_arg(int argc, char *argv[]) { long number; char *bin; int i; /* Iterate over every argument and print conversions to stdout */ for (i = 1; i < argc; ++i) { number = atol(argv[i]); /* Since I am negating a number using the branchless trick, * Multiplying this number by -1 still gives you a negative number because of the overflow * Unfortunately this has to be handled separately */ if (number == LONGMIN) { fprintf(stderr, RED "Error: " RST "The number %li does not fit in 64 bits\n", number); continue; } bin = tobin(number); printf("Binary for %-20li: %s\n", number, bin); free(bin); } } int handle_main_noarg(char *filename) { FILE *f; long num, pos, max; char *buf; f = fopen(filename, "r+"); if (!f) { fprintf(stderr, RED "Error: could not open file %s" RST " (errno %i: %s)\n", filename, errno, strerror(errno)); return EXIT_FAILURE; } fseek(f, 0, SEEK_END); max = ftell(f); fseek(f, 0, SEEK_SET); while (fscanf(f, "%li", &num) == 1) { if (num == LONGMIN) { fprintf(stderr, RED "Error: " RST "The number %li does not fit in 64 bits\n", num); continue; } pos = ftell(f); /* Remember position in file */ if (pos >= max) break; fseek(f, 0, SEEK_END); /* Go to end of file */ buf = tobin(num); /* Perform conversion */ fprintf(f, "%s\n", buf); /* Write the conversion there */ fseek(f, pos, SEEK_SET); /* Restore file position*/ free(buf); } fclose(f); return EXIT_SUCCESS; } int main(int argc, char* argv[]) { char * filename; if (argc < 2) { fprintf(stderr, RED "Error: Invalid arguments.\n" RST "Usage: " GRN "%s filename" RST " or " GRN "%s num1 num2 num3...\n" RST, *argv, *argv); return EXIT_FAILURE; } if (argc == 2) return handle_main_noarg(argv[1]); handle_main_arg(argc, argv); return EXIT_SUCCESS; }