340 lines
8.6 KiB
C
340 lines
8.6 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: dtdspmsg.c /main/4 1996/04/21 19:28:47 drk $ */
|
|
/*
|
|
* COMPONENT_NAME: (CMDMSG) Message Catalogue Facilities
|
|
*
|
|
* FUNCTIONS: main, pars_args
|
|
*
|
|
* ORIGINS: 27
|
|
*
|
|
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
|
|
* combined with the aggregated modules for this product)
|
|
* OBJECT CODE ONLY SOURCE MATERIALS
|
|
* (C) COPYRIGHT International Business Machines Corp. 1988, 1989, 1991
|
|
* All Rights Reserved
|
|
*
|
|
* US Government Users Restricted Rights - Use, duplication or
|
|
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
|
*/
|
|
/*
|
|
* @OSF_COPYRIGHT@
|
|
*/
|
|
/*static char rcsid[] = "RCSfile: dspmsg.c,v Revision: 1.4 (OSF) Date: 90/10/07 16:45:19 ";*/
|
|
|
|
/*
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
* (c) Copyright 1993, 1994 Novell, Inc.
|
|
*/
|
|
|
|
/*
|
|
* EXTERNAL PROCEDURES CALLED: standard library functions
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <locale.h>
|
|
#include <ctype.h>
|
|
#include <Dt/MsgCatP.h>
|
|
#include "msgfac_msg.h"
|
|
|
|
#define die(s) puts(s), exit(1)
|
|
#define isanumber(c) (c >= '0' && c <= '9') ? 1 : 0
|
|
#define isaoctal(c) (c >= '0' && c <= '7') ? 1 : 0
|
|
#define toanumber(c) (c - '0')
|
|
#define NOT_SET -1
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
struct arguments {
|
|
int set,
|
|
msg,
|
|
argmax;
|
|
char *catname,
|
|
*def,
|
|
**args;
|
|
};
|
|
|
|
/*-- subroutine used to parse the input arguments ---*/
|
|
void parse_args(int argc, char *argv[], struct arguments *args);
|
|
|
|
nl_catd catderr; /* error message catalog descriptor */
|
|
|
|
/*
|
|
* NAME: main
|
|
*
|
|
* FUNCTION: Extract a message string from a catalog. Perform printf
|
|
* style substitutions and print it out.
|
|
*
|
|
* EXECUTION ENVIRONMENT:
|
|
* User mode.
|
|
*
|
|
* RETURNS: Exit with 0, except when: the format string
|
|
* is invalid.
|
|
*/
|
|
|
|
int main(int argc,char *argv[])
|
|
|
|
/* argc: Number of arguments */
|
|
/* argv: argument vector */
|
|
|
|
{
|
|
struct arguments args; /* place to store the parsed arguments*/
|
|
nl_catd catdmsg; /* catalog descriptor for message catalog */
|
|
char *message; /* place to store message */
|
|
char *p; /* pointer to current pos within message */
|
|
int idx, /* current argument to be printed */
|
|
reorder = NOT_SET; /* Reordering (TRUE, FALSE, NOT_SET) */
|
|
int n; /* # bytes in a character */
|
|
|
|
setlocale (LC_ALL,"");
|
|
catderr = CATOPEN(MF_MSGFAC, 0);
|
|
if (argc < 3) {
|
|
die(CATGETS(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
|
|
}
|
|
|
|
/*______________________________________________________________________
|
|
Parse the input arguments int the args structure.
|
|
______________________________________________________________________*/
|
|
|
|
parse_args(argc,argv,&args);
|
|
|
|
/*______________________________________________________________________
|
|
get the message out of the catalog.
|
|
______________________________________________________________________*/
|
|
|
|
catdmsg = CATOPEN(args.catname, 0);
|
|
message = CATGETS(catdmsg,args.set,args.msg,args.def);
|
|
|
|
/*______________________________________________________________________
|
|
|
|
print out the message making the appropriate sub's for
|
|
the parameters. Reorder the parameters if necessary.
|
|
Do not use mixed reordering!!!
|
|
______________________________________________________________________*/
|
|
|
|
for (p = message , idx = 0 ; *p ; p++ ) {
|
|
|
|
/* quoted escape characters */
|
|
if (*p == '\\' && message == args.def) {
|
|
switch (*++p) {
|
|
case 'n':
|
|
putc('\n',stdout);
|
|
break;
|
|
|
|
case 't':
|
|
putc('\t',stdout);
|
|
break;
|
|
|
|
case 'b':
|
|
putc('\b',stdout);
|
|
break;
|
|
|
|
case 'r':
|
|
putc('\r',stdout);
|
|
break;
|
|
|
|
case 'v':
|
|
putc('\v',stdout);
|
|
break;
|
|
|
|
case 'f':
|
|
putc('\f',stdout);
|
|
break;
|
|
|
|
case 'x':
|
|
{
|
|
char *pesc = p;
|
|
unsigned int hex, hexlen = 0;
|
|
|
|
while (isxdigit(*++pesc))
|
|
hexlen++;
|
|
if (hexlen == 2)
|
|
sscanf (p+1, "%2x", &hex);
|
|
else if (hexlen == 4)
|
|
sscanf (p+1, "%4x", &hex);
|
|
else {
|
|
putc('x',stdout);
|
|
break;
|
|
}
|
|
putc(hex,stdout);
|
|
p += hexlen;
|
|
break;
|
|
}
|
|
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
{
|
|
int c = 0;
|
|
char *pesc = p;
|
|
|
|
do
|
|
c = c * 8 + *pesc++ - '0';
|
|
while (isaoctal(*pesc) && pesc < p+3);
|
|
if (c <= 0377) {
|
|
putc(c,stdout);
|
|
p = pesc - 1;
|
|
} else
|
|
putc(*p,stdout);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
putc(*p,stdout);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* printf % style substitution */
|
|
else if (*p == '%') {
|
|
|
|
/* %% prints one % */
|
|
if (*++p == '%') {
|
|
putc(*p,stdout);
|
|
continue;
|
|
}
|
|
|
|
/* %n$ reorders the argument list and uses variable n next */
|
|
/* once this is used, all arguments must use it */
|
|
if (isanumber(*p)) {
|
|
|
|
/* do not allow mixing of reorder types */
|
|
if (reorder == FALSE) {
|
|
die(CATGETS(catderr,MS_DSPMSG,M_REORDER,"\nNone or all arguments must use %n$ format"));
|
|
}
|
|
for (idx = 0 ; isanumber(*p) ; p++)
|
|
idx += idx * 10 + toanumber(*p);
|
|
idx--;
|
|
if (*p++ != '$') {
|
|
die(CATGETS(catderr,MS_DSPMSG,M_INVRE,"\n% missing from %n$ format"));
|
|
}
|
|
reorder = TRUE;
|
|
}
|
|
else {
|
|
/* do not allow mixing of reorder types */
|
|
if (reorder == TRUE) {
|
|
die(CATGETS(catderr,MS_DSPMSG,M_REORDER,"\nNone or all arguments must use %n$ format"));
|
|
}
|
|
reorder = FALSE;
|
|
}
|
|
/* report invalid printf argument number */
|
|
if (idx < 0 || idx >= args.argmax) {
|
|
die(CATGETS(catderr,MS_DSPMSG,M_REINDEX,"\nInvalid argument index"));
|
|
}
|
|
/* report unsupported % type */
|
|
if (*p == 's')
|
|
;
|
|
else if (*p == 'l' && p[1] == 'd')
|
|
p++;
|
|
else {
|
|
exit(1);
|
|
}
|
|
fwrite(args.args[idx],strlen(args.args[idx]),1,stdout);
|
|
idx++;
|
|
}
|
|
|
|
/* just print the next character */
|
|
else {
|
|
n = mblen(p, MB_CUR_MAX);
|
|
if (n < 0)
|
|
n = 1;
|
|
do
|
|
putc(*p++,stdout);
|
|
while (--n > 0);
|
|
p--;
|
|
}
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NAME: parse_args
|
|
*
|
|
* FUNCTION: Sets up the args-> data structure for main().
|
|
*
|
|
* EXECUTION ENVIRONMENT:
|
|
* User mode.
|
|
*
|
|
* RETURNS: void
|
|
*/
|
|
|
|
void parse_args(int argc, char *argv[], struct arguments *args)
|
|
|
|
/* argc: The number or arguments */
|
|
/* argv: The input argument vector */
|
|
/* args: The output argument structure */
|
|
|
|
{
|
|
|
|
args->args = NULL;
|
|
args->def = "";
|
|
args->argmax = 0;
|
|
args->set = 1;
|
|
argv++ ;
|
|
argc--; /* Skip the program name */
|
|
if (!strcmp(*argv,"-s")) { /* check for a set number */
|
|
if (argc < 4) /* check for sufficient arguments */
|
|
die(CATGETS(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
|
|
argv++;
|
|
argc--; /* skip past the '-s' */
|
|
sscanf(*argv,"%d",&args->set); /* get the real set number */
|
|
argv++;
|
|
argc--; /* skip past the set number */
|
|
}
|
|
args->catname = *argv++; /* get the cat name */
|
|
argc--;
|
|
if (!strcmp(*argv,"-s")) { /* check for a set number */
|
|
if (argc < 3) /* check for sufficient arguments */
|
|
die(CATGETS(catderr,MS_DSPMSG,M_DSPMSG, "Usage: dtdspmsg [-s setno] <catname> <msgno> ['default' arg ... ]"));
|
|
|
|
argv++;
|
|
argc--; /* skip past the '-s' */
|
|
sscanf(*argv,"%d",&args->set); /* get the real set number */
|
|
argv++;
|
|
argc--; /* skip past the set number */
|
|
}
|
|
sscanf(*argv++,"%d",&args->msg); /* scan the message number */
|
|
argc--;
|
|
if (argc) { /* check for the arg count
|
|
for a default string */
|
|
args->def= *argv++;
|
|
argc--;
|
|
}
|
|
if (argc) {
|
|
args->args = argv;
|
|
args->argmax = argc;
|
|
}
|
|
}
|