/*
* args.c
*/
/*
* mpage: a program to reduce pages of print so that several pages
* of output appear on one printed page.
*
* Copyright (c) 1994-2004 Marcel J.E. Mol, The Netherlands
* Copyright (c) 1988 Mark P. Hahn, Herndon, Virginia
*
* Permission is granted to anyone to make or distribute verbatim
* copies of this document as received, in any medium, provided
* that this copyright notice is preserved, and that the
* distributor grants the recipient permission for further
* redistribution as permitted by this notice.
*
*/
#include "mpage.h"
#include <ctype.h>
#include <string.h>
/*
* Function declarations
*/
static char **slice(char *string, int *cntp);
int
do_args(int argc, char **argv, int envflag)
{
char *optstr;
int consumed;
int finished;
int currarg;
int opterrors;
int i;
opt_jarg = 0;
for (i = 0; i < MAXJARG; i++) {
opt_first[i] = 1;
opt_last[i] = MAXINT;
opt_alt[i] = 1;
}
#define OPTARG() \
{ char opt = *optstr; \
consumed = 1; if(*++optstr == '\0') optstr = argv[++currarg]; \
if (!optstr) { fprintf (stderr, "%s: -%c: option requires argument\n", \
MPAGE, opt); return -1; } \
}
opterrors = 0;
finished = 0;
for (currarg = 1; !finished && currarg < argc; currarg++) {
if (*argv[currarg] != '-') {
if (envflag)
opterrors++;
break;
}
optstr = argv[currarg];
consumed = 0;
while (!consumed && *++optstr) {
switch (*optstr) {
default:
fprintf(stderr, "%s: unknown option -%c\n",
MPAGE, *optstr);
opterrors++;
break;
case '-':
finished = 1;
break;
case '1':
sheetindex = 0;
break;
case '2':
sheetindex = 1;
break;
case '4':
sheetindex = 2;
break;
case '8':
sheetindex = 3;
break;
case 'a': /* toggle between accross and updown */
sheetorder = sheetorder == LEFTRIGHT ?
UPDOWN : LEFTRIGHT;
break;
case 'A': /* A4 sized, european paper */
opt_page = "A4"; /* deprecated */
break;
case 'b': /* base paper type */
OPTARG();
/* see if user wants help */
if (!strcmp(optstr, "?") || !strcmp(optstr, "l")) {
show_pagetypes();
exit(0);
}
/* set opt_page */
select_pagetype(optstr);
break;
case 'B': {
int pb = 0; /* set a default */
consumed = 1;
opt_textbox = 1 - opt_textbox;
if (*++optstr == '\0') {
break;
}
while (*optstr) {
int sign;
if (*optstr == '-') {
sign = -1;
optstr++;
}
else
sign = 1;
if (isdigit((int)*optstr)) {
pb = *optstr - '0';
while (*++optstr && isdigit((int)*optstr))
pb = pb*10 + *optstr - '0';
}
pb *= sign;
switch (*optstr) {
case 'l': textmargin_left = pb;
break;
case 'r': textmargin_right = pb;
break;
case 't': textmargin_top = pb;
break;
case 'b': textmargin_bottom = pb;
break;
case '\0':textbox.thick = pb;
break;
default: fprintf(stderr,
"%s: Unknown -B box specifier: %c\n",
MPAGE, *optstr);
break;
}
if (*optstr)
optstr++;
}
break;
}
case 'c': /* concat pages from different files on sheet */
opt_file = 1 - opt_file;
break;
case 'C': /* select character definitions */
consumed = 1;
if (*++optstr) { /* did we get a encoding name ? */
if ((charvec_file = (char *) malloc(strlen(libdir) +
strlen(optstr) +
2)) == NULL) {
perror(optstr);
fprintf(stderr,
"ignoring character encoding definition\n");
}
else {
(void) strcpy(charvec_file, libdir);
(void) strcat(charvec_file, "/");
(void) strcat(charvec_file, optstr);
opt_encoding = 1;
}
}
else /* no encoding name, toggle default one */
opt_encoding = 1 - opt_encoding;
break;
case 'd':
OPTARG();
switch (*optstr) {
case 'a': opt_input = IN_ASCII; break;
case 'p': opt_input = IN_PS; break;
default :
fprintf(stderr,
"ignoring input file type -d%c\n",
*optstr);
break;
}
break;
case 'D':
OPTARG();
dateformat = optstr;
break;
case 'e': /* GPN. for coli, 2,3,4,1(all) pages */
Coli = 3;
opt_duplex = 1 - opt_duplex;
break;
case 'E': /* GPN. for coli, 2,3(inside) pages */
Coli = 2;
break;
case 'f': /* fold long lines */
opt_fold = 1 - opt_fold;
break;
case 'F':
OPTARG();
fontname = optstr;
break;
case 'h':
OPTARG();
opt_header = optstr;
break;
case 'H':
opt_mp_header = 1;
break;
case 'I':
OPTARG();
opt_indent = atoi(optstr);
break;
case 'j': /* Just these sheets */
OPTARG();
if (opt_jarg >= MAXJARG) {
fprintf(stderr,
"%s: to many j args (%d), ignoring %s\n",
MPAGE, MAXJARG, optstr);
break;
}
opt_first[opt_jarg] = isdigit((int)*optstr) ?
strtol(optstr, &optstr, 10) : 1;
if (*optstr == '-') {
if (isdigit((int)*++optstr))
opt_last[opt_jarg] = strtol(optstr, &optstr, 10);
}
else
opt_last[opt_jarg] = MAXINT;
if (*optstr == '/' || *optstr == '%')
opt_alt[opt_jarg] = atoi(++optstr);
opt_jarg++;
break;
case 'J':
OPTARG();
ps_pagenum = atoi(optstr) - 1;
break;
case 'k': /* toggle kill on trailer */
opt_killtrail = 1 - opt_killtrail;
break;
case 'l': /* landscape */
sheetaspect = sheetaspect == LANDSCAPE ?
PORTRAIT : LANDSCAPE;
break;
case 'L':
OPTARG();
opt_lines = atoi(optstr);
break;
case 'm': {
int sm = 2*DEFAULTSMARGIN; /* set a default */
consumed = 1;
if (*++optstr == '\0') {
sheetmargin_left = sm;
#if defined(ALL_MARGINS)
sheetmargin_right = sm;
sheetmargin_top = sm;
sheetmargin_bottom = sm;
#endif
break;
}
while (*optstr) {
int sign;
if (*optstr == '-') {
sign = -1;
optstr++;
}
else
sign = 1;
if (isdigit((int)*optstr)) {
sm = *optstr - '0';
while (*++optstr && isdigit((int)*optstr))
sm = sm*10 + *optstr - '0';
}
sm *= sign;
switch (*optstr) {
case 'l': sheetmargin_left = sm;
break;
case 'r': sheetmargin_right = sm;
break;
case 't': sheetmargin_top = sm;
break;
case 'b': sheetmargin_bottom = sm;
break;
case '\0':sheetmargin_left = sm;
sheetmargin_right = sm;
sheetmargin_top = sm;
sheetmargin_bottom = sm;
break;
default: fprintf(stderr,
"%s: Unknown -m margin specifier: %c\n",
MPAGE, *optstr);
break;
}
if (*optstr)
optstr++;
}
break;
}
case 'M': {
int pm = 2*DEFAULTPMARGIN; /* set a default */
consumed = 1;
if (*++optstr == '\0') {
pagemargin_left = pm;
#if defined(ALL_MARGINS)
pagemargin_right = pm;
pagemargin_top = pm;
pagemargin_bottom = pm;
#endif
break;
}
while (*optstr) {
int sign;
if (*optstr == '-') {
sign = -1;
optstr++;
}
else
sign = 1;
if (isdigit((int)*optstr)) {
pm = *optstr - '0';
while (isdigit((int)*++optstr))
pm = pm*10 + *optstr - '0';
}
pm *= sign;
switch (*optstr) {
case 'l': pagemargin_left = pm;
break;
case 'r': pagemargin_right = pm;
break;
case 't': pagemargin_top = pm;
break;
case 'b': pagemargin_bottom = pm;
break;
case '\0':pagemargin_left = pm;
pagemargin_right = pm;
pagemargin_top = pm;
pagemargin_bottom = pm;
break;
default: fprintf(stderr,
"%s: Unknown -M margin specifier: %c\n",
MPAGE, *optstr);
break;
}
if (*optstr)
optstr++;
}
break;
}
case 'o': /* toggle print outlines */
opt_outline = 1 - opt_outline;
break;
case 'O': /* GPN. for coli, 4,1(outside) pages */
Coli = 1;
break;
case 'p': /* pr */
opt_pr = 1;
consumed = 1;
if (*++optstr)
prprog = optstr;
break;
case 'P': /* Printer */
consumed = 1;
doprint = 1;
if (*++optstr) {
if (*optstr == '-' && *(optstr+1) == '\0')
doprint = 0; /* kill MPAGE envvar que setting*/
else
printque = optstr;
}
break;
case 'r':
opt_reverse = 1;
break;
case 'R': /* reorient */
sheetaspect = LANDSCAPE_PORTRAIT;
break;
case 's': /* tab Stops */
OPTARG();
if ((opt_tabstop = atoi(optstr)) < 2)
opt_tabstop = DEFAULTTABSTOP;
break;
case 'S':
opt_square = 0;
break;
case 't':
opt_duplex = 1 - opt_duplex;
break;
case 'T':
opt_tumble = 1 - opt_tumble;
break;
case 'u':
check_utf8 = 1 - check_utf8;
break;
case 'U': /* Letter sized, US paper */
opt_page = "Letter"; /* deprecated */
break;
case 'v': /* verbose (print page count) */
opt_verbose = 1 - opt_verbose;
break;
case 'V': /* Version */
fprintf(stderr, "mpage version %s\n", VERSION);
exit(0);
break;
case 'W':
OPTARG();
opt_width = atoi(optstr);
break;
case 'x': /* force usage. Could be extended to usagelevel */
opterrors = 1;
break;
case 'X':
opt_sheetheader = 1;
consumed = 1;
if (*++optstr)
sheethead = optstr;
break;
case 'z':
OPTARG();
printprog = optstr;
break;
case 'Z':
OPTARG();
printarg = optstr;
break;
}
}
}
/*
* Just NOW set the page size parameters
*/
set_page();
if (opterrors)
return -1;
return currarg;
} /* do_args */
int
do_env()
{
int argc;
char **argv;
char *copy;
char *env;
#if SPOOLER == ATT_SPOOLER
if ((env = getenv("LPDEST")) != NULL)
#elif SPOOLER == BSD_SPOOLER
if ((env = getenv("PRINTER")) != NULL)
#endif
printque = env;
if ((env = getenv("MPAGE_LIB")) != NULL)
libdir = env;
if ((env = getenv("MPAGE")) != NULL) {
if ((copy = strdup(env)) == NULL) {
fprintf(stderr, "%s: Unable to alloc memory for environment args\n",
MPAGE);
return -1;
}
argv = slice(copy, &argc);
if (do_args(argc, argv, 1) < 0) {
fprintf(stderr, "%s: error in environment \"%s\"\n", MPAGE, env);
return -1;
}
}
return 0;
} /* do_env */
#define ARGCNT 20
char *slc_argv[ARGCNT+1];
static char **
slice(char *string, int *cntp)
{
int count;
/*
* mimic the shell for conformity
*/
slc_argv[0] = MPAGE;
count = 1;
/*
* while there are still characters to be processed
*/
while (*string && count < ARGCNT) {
/*
* skip any leading or leftover white space
*/
while (*string == ' ')
string++;
/*
* make sure we had more than just white space before
* we believe we actually have an argument
*/
if (*string) {
/*
* point the next slot in argv to this string
*/
slc_argv[count++] = string;
/*
* and go looking for the end of this string
* which is delienated by a space or NULL
*/
while (*string && *string != ' ')
string++;
/*
* if this not the end of the string, then convert
* the space into a NULL and move forward one byte.
* if this is the end of the string, we already have
* a suitable NULL byte for the string and it also
* drops us out of all the loops
*/
if (*string) {
*string = '\0';
string++;
}
}
}
/*
* return the count via the integer pointer we were given
* and put a null pointer into the argv array for conformity
*/
if (*string && count == ARGCNT)
fprintf(stderr,
"%s: to many options in MPAGE environment variable, skipping '%s'\n",
MPAGE, string);
slc_argv[count] = 0;
*cntp = count;
return slc_argv;
} /* slice */
|