/* * 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 #include /* * 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 */