The documentation is wrong, although perhaps the code should be fixed to match the documentation rather than the other way around. In fact, I think I'll do that. There is not a good way to add extensions to the builtins. Coincidentally, though, I rewrote itoa() last weekend to make it easier to control the format in which an integer appears. With the code below you can say, besides the old itoa(27), itoa(27, "%x"), itoa(27, "value is %#.8x"), etc. The format string is a general print format that a) must accept ints and b) has the sense of %#x inverted. I fully acknowledge the utter hackedness of this. A better idea should be employed. -rob In main.c, int xconv(va_list *arg, Fconv *f) { f->f3 ^= 1<<2; /* was |= */ return numbconv(arg, f); } In builtin.c, void cvtitoa(Node *r, Node *args) { Node res; Node *av[Maxarg]; int ival; char buf[128], *fmt; if(args == 0) err: error("itoa(number [, printformat]): arg count"); na = 0; flatten(av, args); if(na == 0 || na > 2) goto err; expr(av[0], &res); if(res.type != TINT) error("itoa(integer): arg type"); ival = (int)res.ival; fmt = "%d"; if(na == 2){ expr(av[1], &res); if(res.type != TSTRING) error("itoa(integer, string): arg type"); fmt = res.string->string; } sprint(buf, fmt, ival); r->op = OCONST; r->type = TSTRING; r->string = strnode(buf); r->fmt = 's'; }