main.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1995 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <libintl.h>
#include <locale.h>
#include <unistd.h>
#include <sys/param.h>
#include "genmsg.h"
#define MSG_SUFFIX ".msg"
#define NEW_SUFFIX ".new"
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "genmsg"
#endif
/*
* External functions.
*/
extern void write_msgfile(char *); /* from util.c */
extern int read_projfile(char *); /* from util.c */
extern void write_projfile(char *); /* from util.c */
extern void read_msgfile(char *); /* from util.c */
extern int is_writable(char *); /* from util.c */
extern int file_copy(char *, char *); /* from util.c */
extern void init_lex(void); /* from genmsg.l */
extern void init_linemsgid(void); /* from genmsg.l */
/* Program name. */
char *program;
/* File pointer for auto-message-numbering. */
FILE *newfp = NULL;
/* Input source file. */
char *srcfile;
/* Tag for message comments. */
char *mctag = NULL;
/* Tag for set number comments. */
char *sctag = NULL;
/* Mode mask to define the genmsg tasks. */
Mode active_mode = NoMode;
/*
* This flag will be TRUE if a catgets() call is found
* in the input file.
*/
int is_cat_found = FALSE;
/* Suppress an error message if this flag is TRUE. */
int suppress_error = FALSE;
/* Prefix and suffix of messages for testing. */
char *premsg = NULL;
char *sufmsg = NULL;
static void usage(void);
static void validate_options(void);
int
main(int argc, char **argv)
{
int c;
extern char *optarg; /* from getopt */
extern int optind; /* from getopt */
extern FILE *yyin; /* from lex */
extern int yyparse(void);
char *msgfile = NULL;
char *projfile = NULL;
char *newprojfile = NULL;
char *cpppath = NULL;
int do_msgfile = FALSE;
int tmpfd = -1;
program = basename(argv[0]);
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
while ((c = getopt(argc, argv, "arndfg:o:l:p:c:s:m:M:txvb")) != EOF) {
switch (c) {
case 'o':
SetActiveMode(MessageMode);
msgfile = optarg;
break;
case 'a':
SetActiveMode(AppendMode);
break;
case 'l':
projfile = optarg;
SetActiveMode(AutoNumMode);
break;
case 'r':
SetActiveMode(ReverseMode);
break;
case 'p':
cpppath = optarg;
SetActiveMode(PreProcessMode);
break;
case 'g':
newprojfile = optarg;
suppress_error = TRUE;
SetActiveMode(ProjectMode);
break;
case 'c':
mctag = optarg;
SetActiveMode(MsgCommentMode);
break;
case 's':
sctag = optarg;
SetActiveMode(SetCommentMode);
break;
case 'b':
SetActiveMode(BackCommentMode);
break;
case 'n':
SetActiveMode(LineInfoMode);
break;
case 'm':
premsg = optarg;
SetActiveMode(PrefixMode);
break;
case 'M':
sufmsg = optarg;
SetActiveMode(SuffixMode);
break;
case 't':
SetActiveMode(TripleMode);
break;
case 'd':
SetActiveMode(DoubleLineMode);
break;
case 'f':
SetActiveMode(OverwriteMode);
break;
case 'x':
suppress_error = TRUE;
SetActiveMode(NoErrorMode);
break;
case 'v':
(void) printf("genmsg version %s\n", "%I%");
exit(EXIT_SUCCESS);
break;
default:
usage();
break;
}
}
if (optind >= argc) {
usage();
}
validate_options();
if (IsActiveMode(AutoNumMode)) {
int len;
char *tmp;
if (read_projfile(projfile)) {
tmp = basename(projfile);
len = strlen(tmp);
if ((newprojfile = malloc(len + sizeof (NEW_SUFFIX)))
== NULL) {
prg_err(gettext("fatal: out of memory"));
exit(EXIT_FAILURE);
}
(void) sprintf(newprojfile, "%s%s", tmp, NEW_SUFFIX);
} else {
newprojfile = basename(projfile);
}
}
if ((IsActiveMode(AutoNumMode) || IsActiveMode(ProjectMode)) &&
(is_writable(IsActiveMode(OverwriteMode) ?
projfile : newprojfile) == FALSE)) {
prg_err(gettext("cannot write \"%s\": permission denied"),
IsActiveMode(OverwriteMode) ? projfile : newprojfile);
exit(EXIT_FAILURE);
}
if (IsActiveMode(AppendMode) && msgfile) {
read_msgfile(msgfile);
}
if (!msgfile) {
char *tmp = basename(argv[optind]);
int len = strlen(tmp);
if ((msgfile = malloc(len + sizeof (MSG_SUFFIX)))
== NULL) {
prg_err(gettext("fatal: out of memory"));
exit(EXIT_FAILURE);
}
(void) sprintf(msgfile, "%s%s", tmp, MSG_SUFFIX);
}
while (optind < argc) {
is_cat_found = FALSE;
srcfile = argv[optind];
if (IsActiveMode(AutoNumMode) || IsActiveMode(ReverseMode)) {
init_linemsgid();
}
if (IsActiveMode(PreProcessMode)) {
char cmd[MAXPATHLEN];
(void) sprintf(cmd, "%s %s", cpppath, srcfile);
if ((yyin = (FILE *) popen(cmd, "r")) == NULL) {
prg_err(
gettext("fatal: cannot execute \"%s\""),
cpppath);
exit(EXIT_FAILURE);
}
} else {
if ((yyin = fopen(srcfile, "r")) == NULL) {
prg_err(/* stupid cstyle */
gettext("cannot open \"%s\""), srcfile);
goto end;
}
}
init_lex();
yyparse();
if (IsActiveMode(PreProcessMode)) {
if (pclose(yyin) != 0) {
prg_err(gettext("\"%s\" failed for \"%s\""),
cpppath, srcfile);
goto end;
}
}
if (is_cat_found == FALSE) {
if (!IsActiveMode(PreProcessMode)) {
(void) fclose(yyin);
}
goto end;
}
if (!do_msgfile) {
do_msgfile = TRUE;
}
if (IsActiveMode(AutoNumMode) || IsActiveMode(ReverseMode)) {
char *tmp = basename(srcfile);
char newfile[MAXPATHLEN];
char tmpfile[32];
if (IsActiveMode(OverwriteMode)) {
(void) sprintf(newfile, "%s", srcfile);
} else {
(void) sprintf(newfile, "%s%s",
tmp, NEW_SUFFIX);
}
if (is_writable(newfile) == FALSE) {
prg_err(
gettext("cannot create \"%s\": permission denied"),
newfile);
goto end;
}
(void) sprintf(tmpfile, "%s", "/tmp/gensmg.XXXXXX");
if ((tmpfd = mkstemp(tmpfile)) == -1) {
prg_err(/* stupid cstyle */
gettext("cannot create \"%s\""), tmpfile);
if (!IsActiveMode(PreProcessMode)) {
(void) fclose(yyin);
}
goto end;
}
(void) close(tmpfd);
if ((newfp = fopen(tmpfile, "w")) == NULL) {
prg_err(/* stupid cstyle */
gettext("cannot create \"%s\""), tmpfile);
if (!IsActiveMode(PreProcessMode)) {
(void) fclose(yyin);
}
(void) unlink(tmpfile);
goto end;
}
if (IsActiveMode(PreProcessMode)) {
if ((yyin = fopen(srcfile, "r")) == NULL) {
prg_err(/* stupid cstyle */
gettext("cannot open \"%s\""), srcfile);
(void) unlink(tmpfile);
goto end;
}
} else {
rewind(yyin);
}
SetActiveMode(ReplaceMode);
init_lex();
yyparse();
ResetActiveMode(ReplaceMode);
(void) fclose(newfp);
newfp = NULL;
(void) fclose(yyin);
(void) file_copy(tmpfile, newfile);
(void) unlink(tmpfile);
goto end;
}
if (!IsActiveMode(PreProcessMode)) {
(void) fclose(yyin);
}
end:
optind++;
}
if (!do_msgfile) { /* no more business. */
return (EXIT_SUCCESS);
}
if (!IsActiveMode(ReverseMode) && !IsActiveMode(ProjectMode)) {
write_msgfile(msgfile);
}
if (IsActiveMode(AutoNumMode) || IsActiveMode(ProjectMode)) {
write_projfile(IsActiveMode(OverwriteMode) ?
projfile : newprojfile);
}
return (EXIT_SUCCESS);
}
static void
validate_options(void)
{
/* -r doesn't work with either -a or -l. */
if (IsActiveMode(ReverseMode) &&
(IsActiveMode(AutoNumMode) || IsActiveMode(AppendMode))) {
usage();
}
/* -b should be accompanied with -c, -s, -d, and -n. */
if (IsActiveMode(BackCommentMode) &&
(!IsActiveMode(MsgCommentMode) &&
!IsActiveMode(SetCommentMode) &&
!IsActiveMode(DoubleLineMode) &&
!IsActiveMode(LineInfoMode))) {
usage();
}
if (IsActiveMode(ProjectMode) &&
(IsActiveMode(AutoNumMode) || IsActiveMode(ReverseMode) ||
IsActiveMode(AppendMode) || IsActiveMode(MsgCommentMode) ||
IsActiveMode(LineInfoMode) || IsActiveMode(OverwriteMode) ||
IsActiveMode(PrefixMode) || IsActiveMode(SuffixMode) ||
IsActiveMode(TripleMode) || IsActiveMode(DoubleLineMode) ||
IsActiveMode(MessageMode) || IsActiveMode(NoErrorMode))) {
usage();
}
}
static void
usage(void)
{
(void) fprintf(stderr,
gettext("Usage: %s [-o message-file] [-a] [-d] [-p preprocessor]\n"
" [-s set-tag] [-c message-tag] [-b] [-n]\n"
" [-l project-file] [-r] [-f] [-g project-file]\n"
" [-m prefix] [-M suffix] [-t] [-x] files ...\n"),
program);
exit(EXIT_FAILURE);
}