2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1996-1997 by Sun Microsystems, Inc. 2N/A * All rights reserved. 2N/A/* Copyright (c) 1988 AT&T */ 2N/A/* All Rights Reserved */ 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A/* Copyright (c) 1979 Regents of the University of California */ 2N/A * Routine to perform parameter substitution. 2N/A * instring is a string containing printf type escapes. 2N/A * The whole thing uses a stack, much like an HP 35. 2N/A * The following escapes are defined for substituting row/column: 2N/A * %[:[-+ #0]][0-9][.][0-9][dsoxX] 2N/A * print pop() as in printf(3), as defined in the local 2N/A * sprintf(3), except that a leading + or - must be preceded 2N/A * with a colon (:) to distinguish from the plus/minus operators. 2N/A * %c print pop() like %c in printf(3) 2N/A * %l pop() a string address and push its length. 2N/A * %P[a-z] set dynamic variable a-z 2N/A * %g[a-z] get dynamic variable a-z 2N/A * %P[A-Z] set static variable A-Z 2N/A * %g[A-Z] get static variable A-Z 2N/A * %p[1-0] push ith parm 2N/A * %'c' char constant c 2N/A * %{nn} integer constant nn 2N/A * %+ %- %* %/ %m arithmetic (%m is mod): push(pop() op pop()) 2N/A * %& %| %^ bit operations: push(pop() op pop()) 2N/A * %= %> %< logical operations: push(pop() op pop()) 2N/A * %A %O logical AND, OR push(pop() op pop()) 2N/A * %! %~ unary operations push(op pop()) 2N/A * %? expr %t thenpart %e elsepart %; 2N/A * if-then-else, %e elsepart is optional. 2N/A * else-if's are possible ala Algol 68: 2N/A * %? c1 %t %e c2 %t %e c3 %t %e c4 %t %e %; 2N/A * % followed by anything else 2N/A * is not defined, it may output the character, 2N/A * and it may not. This is done so that further 2N/A * enhancements to the format capabilities may 2N/A * be made without worrying about being upwardly 2N/A * compatible from buggy code. 2N/A * all other characters are ``self-inserting''. %% gets % output. 2N/A * The stack structure used here is based on an idea by Joseph Yao. 2N/A/* The following routine was added to make lint shut up about converting from 2N/A * a long to a char *. It is identical to the pop routine, except for the 2N/A * cast on the return statement. 2N/A long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
2N/A long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
2N/A long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
2N/A long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
2N/A long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
2N/A long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
2N/A while ((c = *
cp++) != 0) {
2N/A /* PRINTING CASES */ 2N/A /* leading ':' to allow +/- in format */ 2N/A /* take care of flags, width and precision */ 2N/A /* add in the conversion type */ 2N/A "conversion type\n");
2N/A * Pass off the dirty work to sprintf. 2N/A * It's debatable whether we should just pull in 2N/A * the appropriate code here. I decided not to for 2N/A * Advance outp past what sprintf just did. 2N/A * sprintf returns an indication of its length on some 2N/A * systems, others the first char, and there's 2N/A * no easy way to tell which. The Sys V on 2N/A * BSD emulations are particularly confusing. 2N/A * This code is worth scratching your head at for a 2N/A * while. The idea is that various weird things can 2N/A * happen to nulls, EOT's, tabs, and newlines by the 2N/A * tty driver, arpanet, and so on, so we don't send 2N/A * them if we can help it. So we instead alter the 2N/A * place being addessed and then move the cursor 2N/A * locally using UP or RIGHT. 2N/A * This is a kludge, clearly. It loses if the 2N/A * parameterized string isn't addressing the cursor 2N/A * (but hopefully that is all that %c terminals do 2N/A * with parms). Also, since tab and newline happen 2N/A * to be next to each other in ASCII, if tab were 2N/A * included a loop would be needed. Finally, note 2N/A * that lots of other processing is done here, so 2N/A * this hack won't always work (e.g. the Ann Arbor 2N/A * 4080, which uses %B and then %c.) 2N/A * Null. Problem is that our 2N/A * output is, by convention, null terminated. 2N/A op = 0
200;
/* Parity should */ 2N/A * Control D. Problem is that certain very 2N/A * ancient hardware hangs up on this, so the 2N/A * current(!) UNIX tty driver doesn't xmit 2N/A * Newline. Problem is that UNIX will expand 2N/A * Tab used to be in this group too, 2N/A * because UNIX might expand it to blanks. 2N/A * We now require that this tab mode be turned 2N/A * off by any program using this routine, 2N/A * or using termcap in general, since some 2N/A * terminals use tab for other stuff, like 2N/A * nondestructive space. (Filters like ul 2N/A * or vcrt will lose, since they can't stty.) 2N/A * Tab was taken out to get the Ann Arbor 2N/A * %i: shorthand for increment first two parms. 2N/A * Useful for terminals that start numbering from 2N/A * one instead of zero(like ANSI terminals). 2N/A /* %pi: push the ith parameter */ 2N/A /* %Pi: pop from stack into variable i (a-z) */ 2N/A " register name\n");
2N/A /* %gi: push variable i (a-z) */ 2N/A " register name\n");
2N/A /* %'c' : character constant */ 2N/A " closing quote\n");
2N/A /* %{nn} : integer constant. */ 2N/A while ((c = *
cp++) >=
'0' && c <=
'9') {
2N/A /* binary operators */ 2N/A break;
/* %m: mod */ 2N/A /* Unary operators. */ 2N/A /* Sorry, no unary minus, because minus is binary. */ 2N/A * If-then-else. Implemented by a low level hack of 2N/A * skipping forward until the match is found, counting 2N/A * nested if-then-elses. 2N/A case '?':
/* IF - just a marker */ 2N/A case 't':
/* THEN - branch if false */ 2N/A case 'e':
/* ELSE - branch to ENDIF */ 2N/A case ';':
/* ENDIF - just a marker */ 2N/A if ((c = *
cp++) ==
to || c ==
';') {