groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Groff] Several file arguments to groff


From: Bernd Warken
Subject: Re: [Groff] Several file arguments to groff
Date: Thu, 7 Nov 2002 14:47:06 +0100
User-agent: Mutt/1.2.5i

On Wed, Oct 30, 2002 at 08:35:46PM +0100, Bernd Warken wrote:
> On Tue, Oct 29, 2002 at 09:06:56PM +0000, Ralph Corderoy wrote:
> > 
> > Unix just doesn't sort command line options, so why does GNU have to
> > choose otherwise?  And since the library doesn't seem to allow this to
> > be turned off, although I'm still looking, we have to re-invent our own
> > getopt, wasting their effort.
> > 
> I will write groffer partly in C++.  I need a better getopt for it 
> anyway.  Does anybody know if there is some GNU project for this?
> If I need to write it myself it will take some time, but my plan is
> to do it for groffer.
> 
It's not necessary to write a now getopt() because the actual GNU
getopt()/getopt_long() already provide all necessary features by adding
a starting '+' or '-' to the string representing all short options.
The `man 3 getopt' displays:

       By default, getopt() permutes the contents of argv as it scans,
       so that eventually all the non-options are at the end.  Two
       other modes are also implemented.  If the first character of
       optstring is `+' or the environment variable POSIXLY_CORRECT is
       set, then option processing stops as soon as a non-option
       argument is encountered.  If the first character of optstring
       is `-', then each non-option argv-element is handled as if it
       were the argument of an option with character code 1.  (This is
       used by programs that were written to expect options and other
       argv-elements in any order and that care about the ordering of
       the two.)  The special argument `--' forces an end of
       option-scanning regardless of the scanning mode.

This means that adding a leading '-' to the string containing all short
options will keep each file name arguments at their position by creating
them as option argument for pseudo short option 1 (character code is 1,
not character '1').  The following example written in C shows how to use
this; to simplify the example the function getopt() is used, but the
smae results occur with getopt_long().

##################################

/* opt.c */

#include <getopt.h>
#include <stdio.h>

char *short_opts="-ab";

void
main(int argc, char **argv){
  int c;
  while (1) {
    c = getopt(argc, argv, short_opts);
    if (c == EOF)
      break;
    switch (c) {
    case 1:
      printf("file argument: %s\n", optarg);
      break;
    default:
      printf("option: -%c\n", c);
      break;
    }
  }
  if (optind < argc) {
    printf ("non-option ARGV-elements: ");
    while (optind < argc)
      printf ("%s ", argv[optind++]);
    printf ("\n");
  }
}

#######################

Calling this with

  `./opt  -a file1 -b file2 file3'

results in

  option: -a
  file argument: file1
  option: -b
  file argument: file2
  file argument: file3


If the C code line

  char *short_opts="-ab";

is replaced by

  char *short_opts="ab";

the same call results in

  option: -a
  option: -b
  non-option ARGV-elements: file1 file2 file3 

Here all file names are sorted to the end.


If is replaced by

  char *short_opts="+ab";

the same call results in

  option: -a
  non-option ARGV-elements: file1 -b file2 file3 

Here the first file name ends the option processing, all following
arguments are interpreted as file names.  This is the insane behavior
that is also created by setting the environment variable
$POSIXLY_CORRECT.


###################################

The correct behavior to get control over the placement of arguments in
groff is to add a leading '-' before the short option string in the
getopt_long() call in <groff-src-top>/src/roff/groff/groff.cc and then
add a `case 1:' in `switch(opt)'.  Replace

 while ((opt = getopt_long(argc, argv,
                 "abcCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
                 long_options, NULL))
        != EOF) {

by 

 while ((opt = getopt_long(argc, argv,
                 "-abcCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
                 long_options, NULL))
        != EOF) {


Bernd Warken


reply via email to

[Prev in Thread] Current Thread [Next in Thread]