dtdspmsg.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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 libraries 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. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  46. * (c) Copyright 1993, 1994 International Business Machines Corp.
  47. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  48. * (c) Copyright 1993, 1994 Novell, Inc.
  49. */
  50. /*
  51. * EXTERNAL PROCEDURES CALLED: standard library functions
  52. */
  53. #include <stdlib.h>
  54. #include <stdio.h>
  55. #include <string.h>
  56. #include <locale.h>
  57. #include <ctype.h>
  58. #include <Dt/MsgCatP.h>
  59. #include "msgfac_msg.h"
  60. #define die(s) puts(s), exit(1)
  61. #define isanumber(c) (c >= '0' && c <= '9') ? 1 : 0
  62. #define isaoctal(c) (c >= '0' && c <= '7') ? 1 : 0
  63. #define toanumber(c) (c - '0')
  64. #define NOT_SET -1
  65. #define TRUE 1
  66. #define FALSE 0
  67. struct arguments {
  68. int set,
  69. msg,
  70. argmax;
  71. char *catname,
  72. *def,
  73. **args;
  74. };
  75. /*-- subroutine used to parse the input arguments ---*/
  76. void parse_args(int argc, char *argv[], struct arguments *args);
  77. nl_catd catderr; /* error message catalog descriptor */
  78. /*
  79. * NAME: main
  80. *
  81. * FUNCTION: Extract a message string from a catalog. Perform printf
  82. * style substitutions and print it out.
  83. *
  84. * EXECUTION ENVIRONMENT:
  85. * User mode.
  86. *
  87. * RETURNS: Exit with 0, except when: the format string
  88. * is invalid.
  89. */
  90. int main(int argc,char *argv[])
  91. /* argc: Number of arguments */
  92. /* argv: argument vector */
  93. {
  94. struct arguments args; /* place to store the parsed arguments*/
  95. nl_catd catdmsg; /* catalog descriptor for message catalog */
  96. char *message; /* place to store message */
  97. char *p; /* pointer to current pos within message */
  98. int idx, /* current argument to be printed */
  99. reorder = NOT_SET; /* Reordering (TRUE, FALSE, NOT_SET) */
  100. int n; /* # bytes in a character */
  101. setlocale (LC_ALL,"");
  102. catderr = CATOPEN(MF_MSGFAC, 0);
  103. if (argc < 3) {
  104. die(CATGETS(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
  105. }
  106. /*______________________________________________________________________
  107. Parse the input arguments int the args structure.
  108. ______________________________________________________________________*/
  109. parse_args(argc,argv,&args);
  110. /*______________________________________________________________________
  111. get the message out of the catalog.
  112. ______________________________________________________________________*/
  113. catdmsg = CATOPEN(args.catname, 0);
  114. message = CATGETS(catdmsg,args.set,args.msg,args.def);
  115. /*______________________________________________________________________
  116. print out the message making the appropriate sub's for
  117. the parameters. Reorder the parameters if necessary.
  118. Do not use mixed reordering!!!
  119. ______________________________________________________________________*/
  120. for (p = message , idx = 0 ; *p ; p++ ) {
  121. /* quoted escape characters */
  122. if (*p == '\\' && message == args.def) {
  123. switch (*++p) {
  124. case 'n':
  125. putc('\n',stdout);
  126. break;
  127. case 't':
  128. putc('\t',stdout);
  129. break;
  130. case 'b':
  131. putc('\b',stdout);
  132. break;
  133. case 'r':
  134. putc('\r',stdout);
  135. break;
  136. case 'v':
  137. putc('\v',stdout);
  138. break;
  139. case 'f':
  140. putc('\f',stdout);
  141. break;
  142. case 'x':
  143. {
  144. char *pesc = p;
  145. unsigned int hex, hexlen = 0;
  146. while (isxdigit(*++pesc))
  147. hexlen++;
  148. if (hexlen == 2)
  149. sscanf (p+1, "%2x", &hex);
  150. else if (hexlen == 4)
  151. sscanf (p+1, "%4x", &hex);
  152. else {
  153. putc('x',stdout);
  154. break;
  155. }
  156. putc(hex,stdout);
  157. p += hexlen;
  158. break;
  159. }
  160. case '0':
  161. case '1':
  162. case '2':
  163. case '3':
  164. case '4':
  165. case '5':
  166. case '6':
  167. case '7':
  168. {
  169. int c = 0;
  170. char *pesc = p;
  171. do
  172. c = c * 8 + *pesc++ - '0';
  173. while (isaoctal(*pesc) && pesc < p+3);
  174. if (c <= 0377) {
  175. putc(c,stdout);
  176. p = pesc - 1;
  177. } else
  178. putc(*p,stdout);
  179. break;
  180. }
  181. default:
  182. putc(*p,stdout);
  183. break;
  184. }
  185. }
  186. /* printf % style substitution */
  187. else if (*p == '%') {
  188. /* %% prints one % */
  189. if (*++p == '%') {
  190. putc(*p,stdout);
  191. continue;
  192. }
  193. /* %n$ reorders the argument list and uses variable n next */
  194. /* once this is used, all arguments must use it */
  195. if (isanumber(*p)) {
  196. /* do not allow mixing of reorder types */
  197. if (reorder == FALSE) {
  198. die(CATGETS(catderr,MS_DSPMSG,M_REORDER,"\nNone or all arguments must use %n$ format"));
  199. }
  200. for (idx = 0 ; isanumber(*p) ; p++)
  201. idx += idx * 10 + toanumber(*p);
  202. idx--;
  203. if (*p++ != '$') {
  204. die(CATGETS(catderr,MS_DSPMSG,M_INVRE,"\n% missing from %n$ format"));
  205. }
  206. reorder = TRUE;
  207. }
  208. else {
  209. /* do not allow mixing of reorder types */
  210. if (reorder == TRUE) {
  211. die(CATGETS(catderr,MS_DSPMSG,M_REORDER,"\nNone or all arguments must use %n$ format"));
  212. }
  213. reorder = FALSE;
  214. }
  215. /* report invalid printf argument number */
  216. if (idx < 0 || idx >= args.argmax) {
  217. die(CATGETS(catderr,MS_DSPMSG,M_REINDEX,"\nInvalid argument index"));
  218. }
  219. /* report unsupported % type */
  220. if (*p == 's')
  221. ;
  222. else if (*p == 'l' && p[1] == 'd')
  223. p++;
  224. else {
  225. exit(1);
  226. }
  227. fwrite(args.args[idx],strlen(args.args[idx]),1,stdout);
  228. idx++;
  229. }
  230. /* just print the next character */
  231. else {
  232. n = mblen(p, MB_CUR_MAX);
  233. if (n < 0)
  234. n = 1;
  235. do
  236. putc(*p++,stdout);
  237. while (--n > 0);
  238. p--;
  239. }
  240. }
  241. exit(0);
  242. }
  243. /*
  244. * NAME: parse_args
  245. *
  246. * FUNCTION: Sets up the args-> data structure for main().
  247. *
  248. * EXECUTION ENVIRONMENT:
  249. * User mode.
  250. *
  251. * RETURNS: void
  252. */
  253. void parse_args(int argc, char *argv[], struct arguments *args)
  254. /* argc: The number or arguments */
  255. /* argv: The input argument vector */
  256. /* args: The output argument structure */
  257. {
  258. args->args = NULL;
  259. args->def = "";
  260. args->argmax = 0;
  261. args->set = 1;
  262. argv++ ;
  263. argc--; /* Skip the program name */
  264. if (!strcmp(*argv,"-s")) { /* check for a set number */
  265. if (argc < 4) /* check for sufficient arguments */
  266. die(CATGETS(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
  267. argv++;
  268. argc--; /* skip past the '-s' */
  269. sscanf(*argv,"%d",&args->set); /* get the real set number */
  270. argv++;
  271. argc--; /* skip past the set number */
  272. }
  273. args->catname = *argv++; /* get the cat name */
  274. argc--;
  275. if (!strcmp(*argv,"-s")) { /* check for a set number */
  276. if (argc < 3) /* check for sufficient arguments */
  277. die(CATGETS(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
  278. argv++;
  279. argc--; /* skip past the '-s' */
  280. sscanf(*argv,"%d",&args->set); /* get the real set number */
  281. argv++;
  282. argc--; /* skip past the set number */
  283. }
  284. sscanf(*argv++,"%d",&args->msg); /* scan the message number */
  285. argc--;
  286. if (argc) { /* check for the arg count
  287. for a default string */
  288. args->def= *argv++;
  289. argc--;
  290. }
  291. if (argc) {
  292. args->args = argv;
  293. args->argmax = argc;
  294. }
  295. }