2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: print.c /main/3 1995/11/01 16:29:05 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF *
29 * AT&T BELL LABORATORIES *
30 * AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN *
31 * ACCORDANCE WITH APPLICABLE AGREEMENTS *
33 * Copyright (c) 1995 AT&T Corp. *
34 * Unpublished & Not for Publication *
35 * All Rights Reserved *
37 * The copyright notice above does not evidence any *
38 * actual or intended publication of such source code *
40 * This software was created by the *
41 * Advanced Software Technology Department *
42 * AT&T Bell Laboratories *
44 * For further information contact *
45 * {research,attmail}!dgk *
47 ***************************************************************/
49 /* : : generated by proto : : */
51 #if !defined(__PROTO__)
52 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
53 #if defined(__cplusplus)
54 #define __MANGLE__ "C"
59 #define __PROTO__(x) x
61 #define __PARAM__(n,o) n
62 #if !defined(__STDC__) && !defined(__cplusplus)
63 #if !defined(c_plusplus)
74 #define __PROTO__(x) ()
75 #define __OTORP__(x) x
76 #define __PARAM__(n,o) o
84 #if defined(__cplusplus) || defined(c_plusplus)
85 #define __VARARG__ ...
89 #if defined(__STDARG__)
90 #define __VA_START__(p,a) va_start(p,a)
92 #define __VA_START__(p,a) va_start(p)
101 #include "builtins.h"
115 static int getarg __PROTO__((int, union types_t *));
116 static int extend __PROTO__((char*, int, int, char**));
117 static char *genformat __PROTO__((char*));
118 static int fmtvecho __PROTO__((const char*));
121 static char bsd_univ,cescape, raw, echon;
122 static char **nextarg;
123 static const char *options;
124 static const char preformat[] = "%&%@";
127 * Need to handle write failures to avoid locking output pool
129 static int outexceptf __PARAM__((Sfio_t* iop, int mode, Sfdisc_t* dp), (iop, mode, dp)) __OTORP__(Sfio_t* iop; int mode; Sfdisc_t* dp;){
130 if(mode==SF_DPOP || mode==SF_CLOSE)
132 else if(mode==SF_WRITE)
136 sfpool(iop,NIL(Sfio_t*),SF_WRITE);
138 error(ERROR_system(1),e_badwrite,sffileno(iop));
143 #ifndef SHOPT_ECHOPRINT
144 int b_echo __PARAM__((int argc, char *argv[],__V_ *extra), (argc, argv, extra)) __OTORP__(int argc; char *argv[];__V_ *extra;){
145 options = sh_optecho+5;
149 /* This mess is because /bin/echo on BSD is different */
152 register char *universe;
153 if(universe=astconf("_AST_UNIVERSE",0,0))
154 bsd_univ = (strcmp(universe,"ucb")==0);
158 return(b_print(0,argv,0));
159 options = sh_optecho;
161 if(argv[1] && strcmp(argv[1],"-n")==0)
163 return(b_print(0,argv+echon,0));
165 #endif /* SHOPT_ECHOPRINT */
167 int b_printf __PARAM__((int argc, char *argv[],__V_ *extra), (argc, argv, extra)) __OTORP__(int argc; char *argv[];__V_ *extra;){
170 options = sh_optprintf;
171 return(b_print(-1,argv,0));
175 * argc==0 when called from echo
176 * argc==-1 when called from printf
179 int b_print __PARAM__((int argc, char *argv[], __V_ *extra), (argc, argv, extra)) __OTORP__(int argc; char *argv[]; __V_ *extra;){
180 register Sfio_t *outfile;
181 register int n, fd = 1;
182 const char *msg = e_file+4;
184 int sflag = 0, nflag, rflag;
188 options = sh_optprint;
199 while((n = optget(argv,options))) switch(n)
212 /* print to history file */
214 error(ERROR_system(1),e_history);
215 fd = sffileno(sh.hist_ptr->histfp);
216 sh_onstate(SH_HISTORY);
226 fd = (int)strtol(opt_arg,&opt_arg,10);
229 else if(fd<0 || fd >= sh.lim.open_max)
231 else if(sh_inuse(fd) || (sh.hist_ptr && fd==sffileno(sh.hist_ptr->histfp)))
235 /* The followin is for backward compatibility */
236 if(strcmp(opt_option,"-R")==0)
239 if(error_info.errors==0)
242 /* special case test for -Rn */
243 if(strchr(argv[-1],'n'))
245 if(*argv && strcmp(*argv,"-n")==0)
258 error(ERROR_usage(2), opt_arg);
262 if(error_info.errors || (argc<0 && !(format = *argv++)))
263 error(ERROR_usage(2),optusage((char*)0));
266 format = genformat(format);
267 /* handle special case of '-' operand for print */
268 if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--"))
276 else if(!(n=sh.fdstatus[fd]))
277 n = sh_iocheckfd(fd);
281 /* don't print error message for stdout for compatibility */
284 error(ERROR_system(1),msg);
287 if(!(outfile=sh.sftable[fd]))
290 sh_onstate(SH_NOTRACK);
291 n = SF_WRITE|((n&IOREAD)?SF_READ:0);
292 sh.sftable[fd] = outfile = sfnew(NIL(Sfio_t*),sh.outbuff,IOBSIZE,fd,n);
293 sh_offstate(SH_NOTRACK);
294 sfpool(outfile,sh.outpool,SF_WRITE);
295 if(dp = new_of(Sfdisc_t,0))
297 dp->exceptf = outexceptf;
305 /* turn off share to guarantee atomic writes for printf */
306 n = sfset(outfile,SF_SHARE|SF_PUBLIC,0);
309 /* printf style print */
311 sh_offstate(SH_STOPOK);
312 pool=sfpool(sfstderr,NIL(Sfio_t*),SF_WRITE);
316 if(sh.trapnote&SH_SIGSET)
318 sfprintf(outfile,format,extend,getarg);
320 while(*nextarg && nextarg!=argv);
321 sfpool(sfstderr,pool,SF_WRITE);
325 /* echo style print */
326 if(sh_echolist(outfile,rflag,argv) && !nflag)
327 sfputc(outfile,'\n');
331 hist_flush(sh.hist_ptr);
332 sh_offstate(SH_HISTORY);
336 sfset(outfile,SF_SHARE|SF_PUBLIC,1);
343 * echo the argument list onto <outfile>
344 * if <raw> is non-zero then \ is not a special character.
345 * returns 0 for \c otherwise 1.
348 int sh_echolist __PARAM__((Sfio_t *outfile, int raw, char *argv[]), (outfile, raw, argv)) __OTORP__(Sfio_t *outfile; int raw; char *argv[];){
351 while(!cescape && (cp= *argv++))
353 if(!raw && (n=fmtvecho(cp))>=0)
356 sfwrite(outfile,stakptr(staktell()),n);
359 sfputr(outfile,cp,-1);
368 static char *genformat __PARAM__((char *format), (format)) __OTORP__(char *format;){
373 fp = (char*)stakfreeze(1);
374 stresc(fp+sizeof(preformat)-1);
378 static int getarg __PARAM__((int format,union types_t *value), (format, value)) __OTORP__(int format;union types_t *value;){
379 register char *argp = *nextarg;
381 register int neg = 0;
416 value->p = (char**)strtol(argp,&lastchar,10);
421 np = nv_open(argp,sh.var_tree,NV_VARNAME|NV_NOASSIGN|NV_ARRAY);
423 nv_onattr(np,NV_INTEGER);
424 np->nvalue.lp = new_of(long,0);
426 if(sizeof(int)==sizeof(long))
427 value->ip = (int*)np->nvalue.lp;
430 struct temp { int hi; int low; } *sp = (struct temp*)(np->nvalue.lp);
433 if(*np->nvalue.lp==1)
434 value->ip = &sp->low;
461 value->l = (long)sh_strnum(argp,&lastchar);
462 if(lastchar == *nextarg)
469 value->l = -value->l;
470 if(sizeof(int)!=sizeof(long) && format=='d')
471 value->i = (int)value->l;
475 value->d = sh_strnum(*nextarg,&lastchar);
476 if(sizeof(float)!=sizeof(double) && format=='f')
477 value->f = (float)value->d;
481 error(ERROR_exit(1),e_formspec,format);
484 error(ERROR_exit(1),e_argtype,format);
490 * This routine adds new % escape sequences to printf
492 static int extend __PARAM__((char *invalue,int format,int precis,char **outval), (invalue, format, precis, outval)) __OTORP__(char *invalue;int format;int precis;char **outval;){
498 if((n=fmtvecho(invalue))>=0)
500 *outval = stakptr(staktell());
504 return(strlen(*outval));
506 *outval = sh_fmtq(invalue);
507 return(strlen(*outval));
509 *outval = fmtmatch(invalue);
511 error(ERROR_exit(1),e_badregexp,invalue);
512 return(strlen(*outval));
514 *outval = fmtre(invalue);
516 error(ERROR_exit(1),e_badregexp,invalue);
517 return(strlen(*outval));
525 * construct System V echo string out of <cp>
526 * If there are not escape sequences, returns -1
527 * Otherwise, puts null terminated result on stack, but doesn't freeze it
528 * returns lenght of output.
531 static int fmtvecho __PARAM__((const char *string), (string)) __OTORP__(const char *string;){
532 static char *nullarg;
533 register const char *cp = string, *cpmax;
535 register int offset = staktell();
541 if ((chlen = mblen(cp, MB_CUR_MAX)) > 1)
543 /* Skip over multibyte characters */
549 if ((c == '\0') || (c == '\\'))
555 while((c= *cp++) && (c!='\\'));
560 stakwrite((__V_*)string,c);
561 /* for(; c= *cp; cp++) */
564 if ((MB_CUR_MAX > 1) && ((chlen = mblen(cp, MB_CUR_MAX)) > 1))
566 /* Skip over multibyte characters */
568 for (i = 0; i < chlen; i++)
576 if ((c = *cp) == '\0')
579 if( c=='\\') switch(*++cp)
615 while(++cp<cpmax && *cp>='0' && *cp<='7')
628 c = staktell()-offset;