summaryrefslogtreecommitdiff
path: root/fonts/utilities/mff-29/argloop.c
blob: a523081eb614167ea46f817807e4ca09e7bb25b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* argloop.c 2.9.0 92/07/06 - interpret command-line arguments
 *
-----------------------------------------------------------------------
    This software module copyright (c) 1990, 1991 Damian Cugley.  
    It is provided for free on an "as-is" basis.
    See the file COPYING for more information.
    See argloop(3) for more information on this software module.
-----------------------------------------------------------------------
 * 2.0
 *  created - Damian Cugley <pdc@oxford.prg> Fri 12 Jan 1990
 * 2.1
 *  files as well
 * 2.2
 *  Standard initalisiation files
 * 2.3 - pdc Sun 25 Feb 1990
 *  Added the global variable |verbose| to argloop rather than importing
 *  it from the main program.
 * 2.4 - pdc Mon 2 Apr 1990
 *  Added argloop_verbatim
 * 2.5 - pdc Mon 14 May 1990
 *  -vf+qz is same as -v -f +q +z
 * 2.7 - pdc Sat. 2 Mar. 1991
 *  uses simpler file format (less shell-like)
 *  Made properly reentrant (!)
 * 2.7.1 - pdc Tue. 12 Mar. 1991
 *  Put xmalloc in strword.c & added strmisc header file
 * 2.7.2 - pdc Fri. 21 June 1991
 *  Added support for MS-DOS filenames
 */

#include "config.h"
#include "xstdio.h"		/* <stdio.h> plus prototypes */
#include "strmisc.h"		/* inludes <string(s).h> */
#include "argloop.h"

#ifndef NDEBUG
int argloop_debug = 0;
#  define log1(X,A)	if (argloop_debug) fprintf(stderr, X,A)
#else
#  define log1(X,A)
#endif

int	argloop_verbatim = 0;

typedef char *(*Argloop_next_fn)ARGS((void));
     
void
argloop(cxt, opts)
     Argloop_context	*cxt;
     Argloop_options	*opts;
{
  register const char *p;
  int		flag;		/* Boolean */
  const char   *arg;

  if (!cxt) return;
  arg = (cxt->first ? cxt->first : cxt->word(cxt->data));
  
  while (arg)
    {
      log1("%%%%%s\n", arg);
  
      if (argloop_verbatim || !(*arg == '-' || *arg == '+'))
	opts->arg(0, arg);	/* unflagged argument */
      else
	{
	  flag = (*arg == '-');
	  while (*++arg)
	    {
	      for (p = opts->optstring; *p && *p != *arg; p++)
		;		/* search for flag letter */
	      if (!*p)
		{
		  if (*arg == '-' || *arg == '+')
		    flag = (*arg == '-');
		  else
		    {
		      opts->error(*arg); return;
		    }
		}
	      else if (flag && *(p + 1) == ':')
		{		/* this flag wants an argument too */
		  if (*++arg)
		    {		/* use the remainder of this cmd-line arg */
		      opts->arg(*p, arg);
		    }
		  else
		    {		/* get new cmd-line arg */
		      const char *t = cxt->word(cxt->data);

		      log1("%%%%%%\"%s\"\n", (t ? t : "[NIL]") );
		      opts->arg(*p, t);
		      if (!t) 
			{
			  if (cxt->free) cxt->free(cxt->data);
			  return;
			}
		    }
		  break;	/* from inner while loop */
		}
	      else
		opts->flag(*p, flag);
	    }
	}
      arg = cxt->word(cxt->data);
    }
  if (cxt->free) cxt->free(cxt->data);
  xfree((addr)cxt);
}



/*
 *  How to use the above to parse command-line arguments
 */

struct argv { int argc; const char **argv; };

static const char *
argv_word(st)
     struct argv *st;
{
  return ((--st->argc > 0) ? *++st->argv : (char *)0);
}

static void
argv_free(st)
     struct argv *st;
{
  xfree(st);
}

Argloop_context *
al_argv(argc, argv)
     int		argc;
     const char        *argv[];
{
  struct argv *av = (struct argv *)xmalloc(sizeof (struct argv));
  Argloop_context *cxt = (Argloop_context *)xmalloc(sizeof (Argloop_context));
  
  av->argc = argc; av->argv = argv;
  cxt->data = (char *)av; cxt->first = (char *)0;
  cxt->word = argv_word; 
  cxt->free = argv_free;
  return cxt;
}


static const char *
string_word(st)
     char **st;
{
  return strword((char *)0, st);
}

static void
string_free(st)
     char **st;
{
  xfree(st);
}

Argloop_context *
al_string(string)
     char *string;	/* will be destroyed */
{
  Argloop_context *cxt;
  
  if (!string)
    return (Argloop_context *)0;

  cxt = (Argloop_context *)xmalloc(sizeof (Argloop_context));  
  cxt->word = string_word; 
  cxt->free = string_free;
  cxt->data = xmalloc(sizeof (char *));
  cxt->first = strword(string, (char **)cxt->data);
  return cxt;
}