From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8135 invoked from network); 5 Oct 2001 14:57:48 -0000 Received: from sunsite.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 5 Oct 2001 14:57:48 -0000 Received: (qmail 19136 invoked by alias); 5 Oct 2001 14:57:25 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 15948 Received: (qmail 19060 invoked from network); 5 Oct 2001 14:57:22 -0000 X-VirusChecked: Checked Sender: kiddleo@cav.logica.co.uk Message-ID: <3BBDC9C3.96DD07BD@yahoo.co.uk> Date: Fri, 05 Oct 2001 15:54:59 +0100 From: Oliver Kiddle X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.15 i686) X-Accept-Language: en MIME-Version: 1.0 To: zsh-workers@sunsite.dk Subject: Re: PATCH: printf builtin References: <87.1001328606@csr.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Peter Stephenson wrote: > It does seem to be that, since everything looks OK up to the call to > printf. As a test, I got it to work with a nasty hack using a void * and > separate variables for different types. The void * hack was also not portable (doubles on Linux didn't work). Instead, I've used a macro so the duplication is avoided in the source if not in the compiled code. Should this macro be moved elsewhere in the source at all? I'll commit this now but I should be around next week so can fix any problems in a more timely manner than with getting this last little bit done. Oliver Index: Src/builtin.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v retrieving revision 1.54 diff -u -r1.54 builtin.c --- Src/builtin.c 2001/09/24 10:12:51 1.54 +++ Src/builtin.c 2001/10/05 14:42:33 @@ -92,6 +92,7 @@ BUILTIN("popd", 0, bin_cd, 0, 2, BIN_POPD, NULL, NULL), BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "RDPbnrslzNu0123456789pioOcm-", NULL), + BUILTIN("printf", 0, bin_printf, 1, -1, 0, NULL, NULL), BUILTIN("pushd", 0, bin_cd, 0, 2, BIN_PUSHD, NULL, NULL), BUILTIN("pushln", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"), BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL), @@ -3051,6 +3052,179 @@ if (fout != stdout) fclose(fout); return 0; +} + +/* printf */ + +#define print_val(VAL) \ + if (width >= 0) { \ + if (prec >= 0) \ + printf(start, width, prec, VAL); \ + else \ + printf(start, width, VAL); \ + } else { \ + if (prec >= 0) \ + printf(start, prec, VAL); \ + else \ + printf(start, VAL); \ + } + +/**/ +int +bin_printf(char *name, char **args, char *ops, int func) +{ + int len, nnl, width, prec, type, ret = 0; + char *start, *endptr, *c, *fmt = getkeystring(*args, &len, 0, &nnl); + char **first = ++args, nullstr = '\0', save = '\0'; + + double doubleval; + int intval; + unsigned int uintval; + char *stringval; + + do { + + for (c = fmt;c-fmt < len;c++) { + type = prec = width = -1; + + if (*c != '%') { + putchar(*c); + continue; + } + + start = c++; + if (*c == '%') { + putchar('%'); + continue; + } + + if (strchr("+- #", *c)) c++; + + if (*c == '*') { + width = (*args) ? strtoul(*args++, NULL, 0) : 0; + c++; + } else { + while (idigit(*c)) c++; + } + + if (*c == '.') { + c++; + if (*c == '*') { + prec = (*args) ? strtoul(*args++, NULL, 0) : 0; + c++; + } else { + while (idigit(*c)) c++; + } + } + + if (*c == 'l' || *c == 'L' || *c == 'h') c++; + + if (*c) { + save = c[1]; + c[1] = '\0'; + } + switch (*c) { + case 'c': + if (*args) { + if (**args == Meta) + intval = (*args)[1] ^ 32; + else + intval = **args; + args++; + } else + intval = 0; + print_val(intval); + break; + case 's': + if (*args) + stringval = unmetafy(*args++, NULL); + else + stringval = &nullstr; + print_val(stringval); + break; + case 'b': + if (*args) { + int l; + char *b = getkeystring(*args++, &l, 0, &nnl); + fwrite(b, l, 1, stdout); + } + continue; + case 'q': + if (*args) + stringval = bslashquote(unmetafy(*args++, NULL), NULL, 0); + else + stringval = &nullstr; + *c = 's'; + print_val(stringval); + break; + case 'd': + case 'i': + type=1; + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + type=2; + break; + case 'o': + case 'u': + case 'x': + case 'X': + type=3; + break; + default: + zerrnam(name, "%s: invalid directive", start, 0); + ret = 1; + } + + if (type > 0) { + if (*args && (**args == '\'' || **args == '"' )) { + if (type == 2) { + doubleval = (*args)[1]; + print_val(doubleval); + } else { + intval = (*args)[1]; + print_val(intval); + } + args++; + } else { + switch (type) { + case 1: + intval = (*args) ? strtol(*args, &endptr, 0) : 0; + print_val(intval); + break; + case 2: + doubleval = (*args) ? strtod(*args, &endptr) : 0; + print_val(doubleval); + break; + case 3: + uintval = (*args) ? strtoul(*args, &endptr, 0) : 0; + print_val(uintval); + } + if (*args) { + if (errno == ERANGE) { + zerrnam(name, "`%s' arithmetic overflow", *args, 0); + ret = 1; + } else if (**args && endptr == *args) { + zerrnam(name, "`%s' expected numeric value", endptr, 0); + ret = 1; + } else if (*endptr) { + zerrnam(name, "`%s' not completely converted", *args, 0); + ret = 1; + } + args++; + } + } + } + if (*c) c[1] = save; + } + + /* if there are remaining args, reuse format string */ + } while (*args && args != first); + + return ret; } /* shift builtin */ _____________________________________________________________________ This message has been checked for all known viruses by the MessageLabs Virus Scanning Service. For further information visit http://www.messagelabs.com/stats.asp