shithub: p9-stm32-example-os

ref: f801657f77f3923ec2388c25bdcb036c8019ba89
dir: /libkern/fmt.c/

View raw version
/*
 * The authors of this software are Rob Pike and Ken Thompson.
 *              Copyright (c) 2002 by Lucent Technologies.
 * Permission to use, copy, modify, and distribute this software for any
 * purpose without fee is hereby granted, provided that this entire notice
 * is included in all copies of any software which is or includes a copy
 * or modification of this software and in all copies of the supporting
 * documentation for such software.
 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
 */
#include	<u.h>
#include	"kern.h"
#include "fmtdef.h"

int	(*doquote)(int);

static Fmts
fmtfmt(int c)
{
	switch(c) {
	case ' ':	return _flagfmt;
	case '#':	return _flagfmt;
	case '%':	return _percentfmt;
	case '+':	return _flagfmt;
	case ':':	return _flagfmt;
	case '-':	return _flagfmt;
	case 'C':	return _runefmt;
	case 'S':	return _runesfmt;
	case 'X':	return _ifmt;
	case 'b':	return _ifmt;
	case 'c':	return _charfmt;
	case 'd':	return _ifmt;
	case 'h':	return _flagfmt;
	case 'l':	return _flagfmt;
	case 'n':	return _countfmt;
	case 'o':	return _ifmt;
	case 'p':	return _ifmt;
	case 's':	return _strfmt;
	case 'u':	return _flagfmt;
	case 'x':	return _ifmt;
	}
	return _badfmt;
}

void*
_fmtdispatch(Fmt *f, void *fmt, int isrunes)
{
	Rune rune, r;
	int i, n;

	f->flags = 0;
	f->width = f->prec = 0;

	for(;;){
		if(isrunes){
			r = *(Rune*)fmt;
			fmt = (Rune*)fmt + 1;
		}else{
			fmt = (char*)fmt + chartorune(&rune, fmt);
			r = rune;
		}
		f->r = r;
		switch(r){
		case '\0':
			return nil;
		case '.':
			f->flags |= FmtWidth|FmtPrec;
			continue;
		case '0':
			if(!(f->flags & FmtWidth)){
				f->flags |= FmtZero;
				continue;
			}
			/* fall through */
		case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			i = 0;
			while(r >= '0' && r <= '9'){
				i = i * 10 + r - '0';
				if(isrunes){
					r = *(Rune*)fmt;
					fmt = (Rune*)fmt + 1;
				}else{
					r = *(char*)fmt;
					fmt = (char*)fmt + 1;
				}
			}
			if(isrunes)
				fmt = (Rune*)fmt - 1;
			else
				fmt = (char*)fmt - 1;
		numflag:
			if(f->flags & FmtWidth){
				f->flags |= FmtPrec;
				f->prec = i;
			}else{
				f->flags |= FmtWidth;
				f->width = i;
			}
			continue;
		case '*':
			i = va_arg(f->args, int);
			if(i < 0){
				i = -i;
				f->flags |= FmtLeft;
			}
			goto numflag;
		}
		n = (*fmtfmt(r))(f);
		if(n < 0)
			return nil;
		if(n == 0)
			return fmt;
	}
}