aboutsummaryrefslogblamecommitdiff
path: root/7.3/mprintf.c
blob: 740f3950c0b97eeab56aec429280691b9611c4dd (plain) (tree)




































































































































































                                                                        
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include "mprintf.h"

#define DEFPRES 6
enum base { OCT = 8, DEC = 10, HEX = 16 };

struct flags {
	unsigned int fw;
	unsigned int pres;
	unsigned int fwc;
	unsigned int laligne : 1;
} flags;

void printnum(long long num, struct flags flags, int base);
void printflt(double num, struct flags flags);
void printstr(char *s, struct flags flags);
int reverse(long long *num, int base);

void mprintf(char *fmt, ...)
{
	va_list ap;
	char *p;
	int dlim;

	va_start(ap, fmt);
	for (p = fmt; *p; ++p) {
		if (*p != '%') {
			putchar(*p);
			continue;
		}

		flags.fwc = ' ';
		flags.fw = dlim = flags.pres = 0;
		while (!isalpha(*++p) && *p != '\0') {
			if (isalnum(*p) && !dlim)
				flags.fw = flags.fw * 10 + *p - '0';
			else if (isalnum(*p) && dlim)
				flags.pres = flags.pres * 10 + *p - '0';
			else if (*p == '.')
				dlim = 1;
			else if (*p == '-')
				flags.laligne = 1;
		}
		if (!dlim)
			flags.pres = DEFPRES;

		switch (*p) {
		case 'd':
		case 'i':
			printnum(va_arg(ap, int), flags, DEC);
			break;
		case 'o':
			printnum(va_arg(ap, int), flags, DEC);
			break;
		case 'u':
			printnum(va_arg(ap, unsigned), flags, DEC);
			break;
		case 'x':
			printnum(va_arg(ap, unsigned), flags, HEX);
			break;
		case 'c':
			putchar(va_arg(ap, unsigned));
			break;
		case 'p':
			mprintf("0x");
			printnum(va_arg(ap, long long), flags, HEX);
			break;
		case 'f':
			printflt(va_arg(ap, double), flags);
			break;
		case 's':
			printstr(va_arg(ap, char *), flags);
			break;
		default:
			putchar(*p);
			break;
		}
	}
	va_end(ap);

	return;
}

void printstr(char *s, struct flags flags)
{
	int blank; 

	blank = flags.fw - strlen(s);
	for (; blank > 0 && !flags.laligne; --blank)
		putchar(flags.fwc);

	for (; *s; ++s)
		putchar(*s);

	for (; blank > 0 && flags.laligne; --blank)
		putchar(flags.fwc);
}
void printnum(long long num, struct flags flags, int base)
{
	int temp, blank;

	if (num < 0) {
		putchar('-');
		num *= -1;
	}

	blank = flags.fw - reverse(&num, base);
	for (; blank > 0 && !flags.laligne; --blank)
		putchar(flags.fwc);

	for (; num; num /= base) {
		switch (temp = num % base) {
		case 10:
			putchar('a');
			break;
		case 11:
			putchar('b');
			break;
		case 12:
			putchar('c');
			break;
		case 13:
			putchar('d');
			break;
		case 14:
			putchar('e');
			break;
		case 15:
			putchar('f');
			break;
		default:
			putchar(temp + '0');
			break;
		}
	}

	for (; blank > 0 && flags.laligne; --blank)
		putchar(flags.fwc);
}

void printflt(double num, struct flags flags)
{
	printnum((int) num, flags, DEC);
	if (flags.pres) {
		flags.fwc = '0';
		putchar('.');
		printnum((long long) ((num - (int) num) *
	                 powl(10, flags.pres)), flags, DEC);
	}
}

int reverse(long long *num, int base)
{
	long long temp = *num;
	int len;

	for (*num = len = 0; temp; temp /= base, ++len)
		*num = *num * base + temp % base;

	return len;
}