Don't redeclare forceUpdate() with the wrong prototype.
[oweals/cde.git] / cde / programs / dtdspmsg / dtdspmsg.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /* $XConsortium: dtdspmsg.c /main/4 1996/04/21 19:28:47 drk $ */
24 /*
25  * COMPONENT_NAME: (CMDMSG) Message Catalogue Facilities
26  *
27  * FUNCTIONS: main, pars_args
28  *
29  * ORIGINS: 27
30  *
31  * IBM CONFIDENTIAL -- (IBM Confidential Restricted when
32  * combined with the aggregated modules for this product)
33  * OBJECT CODE ONLY SOURCE MATERIALS
34  * (C) COPYRIGHT International Business Machines Corp. 1988, 1989, 1991
35  * All Rights Reserved
36  *
37  * US Government Users Restricted Rights - Use, duplication or
38  * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
39  */
40 /*
41  * @OSF_COPYRIGHT@
42  */
43 /*static char rcsid[] = "RCSfile: dspmsg.c,v Revision: 1.4  (OSF) Date: 90/10/07 16:45:19 ";*/
44
45 /*
46  * (c) Copyright 1993, 1994 Hewlett-Packard Company
47  * (c) Copyright 1993, 1994 International Business Machines Corp. 
48  * (c) Copyright 1993, 1994 Sun Microsystems, Inc. 
49  * (c) Copyright 1993, 1994 Novell, Inc.   
50  */
51
52 /*                                                                   
53  * EXTERNAL PROCEDURES CALLED: standard library functions
54  */
55
56
57 #include <stdlib.h>
58 #include <stdio.h>
59 #include <locale.h>
60 #include "msgfac_msg.h"
61
62 #define die(s)                  puts(s), exit(1)
63 #define isanumber(c) (c >= '0' && c <= '9') ? 1 : 0
64 #define isaoctal(c) (c >= '0' && c <= '7') ? 1 : 0
65 #define toanumber(c) (c - '0')
66 #define NOT_SET -1
67 #define TRUE    1
68 #define FALSE   0
69
70 struct arguments {
71         int     set,
72                 msg,
73                 argmax;
74         char    *catname,
75                 *def,
76                 **args;
77 };
78
79         /*-- subroutine used to parse the input arguments ---*/
80 void parse_args(int argc, char *argv[], struct arguments *args);
81
82 nl_catd catderr;        /* error message catalog descriptor */
83
84
85
86 /*
87  * NAME: main
88  *                                                                    
89  * FUNCTION:    Extract a message string from a catalog. Perform printf
90  *              style substitutions and print it out.
91  * 
92  * EXECUTION ENVIRONMENT:
93  *      User mode.
94  *                                                                          
95  * RETURNS:     Exit with 0, except when: the format string 
96  *              is invalid.
97  */  
98
99 int main(int argc,char *argv[]) 
100
101         /* argc: Number of arguments */
102         /* argv: argument vector */
103
104 {
105         struct arguments   args;   /* place to store the parsed arguments*/
106         nl_catd catdmsg;           /* catalog descriptor for message catalog */
107         char    *message;          /* place to store message */
108         char    *p;                /* pointer to current pos within message */
109         int     idx,               /* current argument to be printed */
110                 reorder = NOT_SET; /* Reordering  (TRUE, FALSE, NOT_SET) */
111         int     n;                 /* # bytes in a character */
112
113         setlocale (LC_ALL,"");
114         catderr = catopen(MF_MSGFAC, 0);
115         if (argc < 3) {
116                 die(catgets(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
117         }
118
119 /*______________________________________________________________________
120         Parse the input arguments int the args structure.
121   ______________________________________________________________________*/
122
123         parse_args(argc,argv,&args);
124
125 /*______________________________________________________________________
126         get the message out of the catalog.
127   ______________________________________________________________________*/
128
129         catdmsg = catopen(args.catname, 0);
130         message = catgets(catdmsg,args.set,args.msg,args.def);
131
132 /*______________________________________________________________________
133
134         print out the message making the appropriate sub's for
135         the parameters.  Reorder the parameters if necessary.
136         Do not use mixed reordering!!!
137   ______________________________________________________________________*/
138
139         for (p = message , idx = 0 ; *p ; p++ )  {
140
141                 /* quoted escape characters */
142                 if (*p == '\\' && message == args.def) {
143                         switch (*++p) {
144                                 case 'n':
145                                         putc('\n',stdout);
146                                         break;
147
148                                 case 't':
149                                         putc('\t',stdout);
150                                         break;
151
152                                 case 'b':
153                                         putc('\b',stdout);
154                                         break;
155
156                                 case 'r':
157                                         putc('\r',stdout);
158                                         break;
159
160                                 case 'v':
161                                         putc('\v',stdout);
162                                         break;
163
164                                 case 'f':
165                                         putc('\f',stdout);
166                                         break;
167
168                                 case 'x':
169                                         {
170                                         char *pesc = p;
171                                         int hex, hexlen = 0;
172
173                                         while (isxdigit(*++pesc))
174                                                 hexlen++;
175                                         if (hexlen == 2)
176                                                 sscanf (p+1, "%2x", &hex);
177                                         else if (hexlen == 4)
178                                                 sscanf (p+1, "%4x", &hex);
179                                         else {
180                                                 putc('x',stdout);
181                                                 break;
182                                         }
183                                         putc(hex,stdout);
184                                         p += hexlen;
185                                         break;
186                                         }
187
188                                 case '0':
189                                 case '1':
190                                 case '2':
191                                 case '3':
192                                 case '4':
193                                 case '5':
194                                 case '6':
195                                 case '7':
196                                         {
197                                         int c = 0;
198                                         char *pesc = p;
199
200                                         do
201                                                 c = c * 8 + *pesc++ - '0';
202                                         while (isaoctal(*pesc) && pesc < p+3);
203                                         if (c <= 0377) {
204                                                 putc(c,stdout);
205                                                 p = pesc - 1;
206                                         } else
207                                                 putc(*p,stdout);
208                                         break;
209                                         }
210
211                                 default: 
212                                         putc(*p,stdout);
213                                         break;
214                         }
215                 }
216
217                 /* printf % style substitution */
218                 else if (*p == '%') {
219
220                         /* %% prints one % */
221                         if (*++p == '%')  {
222                                 putc(*p,stdout);
223                                 continue;
224                         }
225
226                         /* %n$ reorders the argument list and uses variable n next */
227                         /* once this is used, all arguments must use it */
228                         if (isanumber(*p)) {
229
230                                 /* do not allow mixing of reorder types */
231                                 if (reorder == FALSE) {
232                                         die(catgets(catderr,MS_DSPMSG,M_REORDER,"\nNone or all arguments must use %n$ format"));
233                                 }
234                                 for (idx = 0 ; isanumber(*p) ; p++)
235                                         idx += idx * 10 + toanumber(*p);
236                                 idx--;
237                                 if (*p++ != '$') {
238                                         die(catgets(catderr,MS_DSPMSG,M_INVRE,"\n% missing from %n$ format"));
239                                 }
240                                 reorder = TRUE;
241                         }
242                         else {
243                                 /* do not allow mixing of reorder types */
244                                 if (reorder == TRUE) {
245                                         die(catgets(catderr,MS_DSPMSG,M_REORDER,"\nNone or all arguments must use %n$ format"));
246                                 }
247                                 reorder = FALSE;        
248                         }
249                         /* report invalid printf argument number */
250                         if (idx < 0 || idx >= args.argmax) {
251                                 die(catgets(catderr,MS_DSPMSG,M_REINDEX,"\nInvalid argument index"));
252                         }
253                         /* report unsupported % type */
254                         if (*p == 's')
255                                 ;
256                         else if (*p == 'l' && p[1] == 'd')
257                                 p++;
258                         else {
259                                 exit(1);
260                         }
261                         fwrite(args.args[idx],strlen(args.args[idx]),1,stdout);
262                         idx++;                          
263                 }
264
265                 /* just print the next character */
266                 else {
267                         n = mblen(p, MB_CUR_MAX);
268                         if (n < 0)
269                                 n = 1;
270                         do
271                                 putc(*p++,stdout);
272                         while (--n > 0);
273                         p--;
274                 }
275         }
276         exit(0);
277 }
278
279
280
281 /*
282  * NAME: parse_args
283  *
284  * FUNCTION: Sets up the args-> data structure for main().
285  *
286  * EXECUTION ENVIRONMENT:
287  *      User mode.
288  * 
289  * RETURNS: void
290  */
291
292 void parse_args(int argc, char *argv[], struct arguments *args) 
293
294         /* argc: The number or arguments */
295         /* argv: The input argument vector */
296         /* args: The output argument structure */
297
298 {
299
300         args->args = NULL;
301         args->def = "";
302         args->argmax = 0;
303         args->set = 1;
304         argv++ ; 
305         argc--;                         /* Skip the program name */
306         if (!strcmp(*argv,"-s")) {      /* check for a set number */
307                 if (argc < 4)           /* check for sufficient arguements */
308                 die(catgets(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
309                 argv++; 
310                 argc--;                         /* skip past the '-s' */
311                 sscanf(*argv,"%d",&args->set);  /* get the real set number */
312                 argv++; 
313                 argc--;                         /* skip past the set number */
314         }
315         args->catname = *argv++;                /* get the cat name */
316         argc--;
317         if (!strcmp(*argv,"-s")) {              /* check for a set number */
318                 if (argc < 3)           /* check for sufficient arguements */
319                 die(catgets(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
320
321                 argv++; 
322                 argc--;                         /* skip past the '-s' */
323                 sscanf(*argv,"%d",&args->set);  /* get the real set number */
324                 argv++; 
325                 argc--;                         /* skip past the set number */
326         }
327         sscanf(*argv++,"%d",&args->msg);        /* scan the message number */
328         argc--;
329         if (argc) {                             /* check for the arg count 
330                                                    for a default string */
331                 args->def= *argv++;
332                 argc--;
333         }
334         if (argc)  {
335                 args->args = argv;
336                 args->argmax = argc;
337         }
338 }