summaryrefslogtreecommitdiff
path: root/obsolete/support/undump/scanargs.1
blob: 827788f4e358881d10f2a59f4c9166bfb563299f (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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
.TH SCANARGS 3 "AMPEX CORP."
.SH NAME
scanargs, qscanargs - formatted conversion from command argument list
.SH SYNOPSIS
.B "#include <stdio.h>"
.PP
.B "scanargs(argc, argv, format" 
[, pointer]...
.B )
.br
.B "int argc;"
.br
.B "char *argv[];"
.br
.B "char *format;"
.SH DESCRIPTION
.I Scanargs
reads
.I argc
arguments from an argument list pointed to by
.I argv.
It converts the argument list according to the format string,
and stores the results of the conversions in its parameters.
.I Qscanargs
is a smaller and less powerful version which does not understand floating 
point.
.PP
Scanargs expects as its parameters an argument count
.I argc,
a pointer to an argument list 
.I argv
(see 
.IR exec (2)),
a control string
.I format,
described below, and a set of
.I pointer
arguments indicating where the converted output should be stored.
.PP
The control string contains specifications, which are used to direct
interpretation of argument sequences.  It contains
the necessary information to describe an acceptable 
syntax for the argument list, and the expected meaning of each argument.
.PP
If the scanning fails it will print a cryptic 
message telling why it failed, and generate a 
.I usage
message from the control string.
.PP
The control string is composed of two parts:
.PP
.B Name:\ \ 
The first characters in the string are assumed to be the calling 
name of the program being executed. This is used for generation of
usage messages, but is otherwise ignored.
If this field is a % sign, it is replaced with the contents of
.IR argv [0]
in the message.
.PP
.B Conversions:\ \ 
Following the name, an optional list of conversion specifications is given,
with separating spaces.  The structure of a conversion specification:
.RS
.PP
.B "label_key_conversion"
.RE
.PP
consists of a
.I label
which is a string of non-space characters describing the acceptable
argument, a
.I key
which may be either of
.TP 4
.B %
The argument is optional. Its absence is ignored.
.TP 4 
.B !
A required argument. If absent, an error return ensues.
.PP
and a 
.I conversion
character which indicates the interpretation of the argument; the corresponding
pointer parameter must be of a restricted type.
.PP
The following conversion characters are supported:
.TP 4
.B d D
a decimal integer is expected; the corresponding parameter should be an 
.I int
or a
.I long
(if
.B D
is specified) pointer.
.TP 4
.B o O
an octal integer is expected; the corresponding parameter should be an 
.I int
or a
.I long
pointer.
.TP 4
.B x X
a hexadecimal integer is expected; the corresponding parameter should be an 
.I int
or a
.I long
pointer.
.TP 4
.B n N
an integer numeric conversion using 
.I C
language syntax.  Numbers beginning 
.B 0x
are hexadecimal, numbers beginning
.B 0
are octal, and other numbers are decimal.  Negative hex numbers must have
the minus sign
.I following
the
.BR 0x ,
i.e. negative 0xa would be given as 0x\-a.  The corresponding pointer
should point to an
.I int
or a
.I long.
.TP 4
.B f F
a floating point number is expected; the corresponding parameter should
be a pointer to a
.I float
or a
.I double.
Not available in
.I qscanargs.
.TP 4
.B "x X d D o O f F"
all numeric types supported by 
.I scanf(3S)
are legal in
.I scanargs;
.I qscanargs
supports all but
.B f
and
.B F
formats, and avoids including the large size of the
.I scanf
routine.
.TP 4
.B s
a character string is expected; the corresponding parameter should be the
address of a pointer to
.I char.
.TP 4
.B \-
a single character flag is expected; the corresponding parameter should
be an 
.I int
pointer.  The occurrence of a
.B \-
followed by the character specified in the label
will cause the setting of the least significant bit of the integer pointed to 
by the corresponding parameter.  The label may consist of up to sixteen 
(32 on a VAX) option
characters, in which case one of the bits of the integer is independantly
set to reflect which one of the flags was present. (The right most character
corresponds to the LSB of the integer)  Only one option may be chosen from
each conversion specification.  The bits which are not set will remain in
their previous state.  For example, a specification of 
.B abc%\-
would match one of
.B \-a \-b
or
.B \-c
in the argument list. 
.B \-c
would cause the corresponding variable to be set to 1, 
.B \-b
to 2, and
.B \-a
to 4.  (Actually, these bits would be ored in, but assuming an intial value
of 0, this is true).
.PP
.RS 4
The
.B \-
may be followed immediately by more label_key_conversion specifications.
These should not be separated by blanks and should not contain any
.B \-
specifications.  They will be processed only if the flag argument is scanned.
This allows optional specification of parameters corresponding to a flag
(e.g.
.I \-f file
).  Corresponding arguments on the command line must appear between the flag
which introduces them and the next flag in the command line.
.RE
.TP 4
.B $
This may appear only as the last specifier in the format string, and is used
to "eat up" the rest of the command arguments.  The corresponding function
argument is an
.I int
pointer.  An index into
.I argv
to the dividing point between the arguments which have been used, and those
which have not is returned.  This index points to the first unused command
argument.  If there is no such dividing point, an error
will be generated.
.PP
A string or numeric conversion character may be preceded by a
.B *
or a
.B ,
to indicate that a list of such arguments is expected.  If
.B ,
is used, then the AT&T proposed argument standard is followed, and a single 
string is expected, with the individual list elements separated by commas or
spaces.  Two commas in a row will produce a null entry (0 if numeric,
zero-length string if string conversion), but multiple spaces, and spaces
following a comma, are taken as a single separator.  If
.B *
is specified, then multiple arguments are parsed to produce the list.  A
format specifier with a
.B *
or a
.B ,
takes two arguments.  The first is an
.B int
pointer, the number of items in the list is returned here.  The second is a
pointer to pointer to the correct data type for the format specifier.  A
pointer to the list of arguments is returned here.
.PP
The scanner will process the control string from left to right,
and where there are multiple conversions of the same type, they will
be assigned one to one with their order of occurrence in the argument list.
Where the order of the arguments is not ambiguous in the control string,
they may occur in any order in the argument list. (ie. A decimal number
will not be confused with a flag, but may
be confused with an octal number or another decimal number. So if an
octal and a decimal number are to be arguments, their order will determine
their conversion, while a decimal number and a flag as arguments may occur
in any order and still be converted correctly.)
.PP
An argument list that does not match the requirements of the control
string will cause the printing of a short message telling why, and
a message telling what the correct usage is.
This usage is gleaned from the control string, and the labels are used
directly.  The labels should be both terse and descriptive!  Spaces, tabs,
and newlines in the format string will be reproduced in the usage message,
and can be used for effective prettyprinting.  A single tab (following a
newline) will indent the line directly under the command name in the usage
message.
.PP
The
.I scanargs
function returns 1 when the argument list matched the requirements
of the control string, and returns 0 if there was a failure.
Parameters for any conversions not matched are left untouched.
.br
For example, the call
.RS
.PP
int i; double x; char *name;
.br
scanargs(argc, argv, "program decimal%d floating%F file%s"
.in 15
, &i, &x, &name );
.RE
.PP
in a C program executed by the shell command
.RS
.PP
.I %
program 10 3.5397 inputfile
.RE
.PP
will assign to 
.I i
the value 10, 
.I x
the value 3.5397, and
.I name
will point to the string "inputfile".
.PP
If the program was executed by the shell command
.RS
.PP
.I %
program  3.4 .7 inputfile
.RE
.PP
the following would be printed on the standard error:
.RS
.PP
extra arguments not processed
.br
usage : program [decimal] [floating] [file]
.RE
.PP
because 3.4 matches the type of 'floating' and inputfile matches
the type of 'file', leaving .7 unmatched (it is considered a string by
scanargs, to be considered a number, it must begin with a digit).
.PP
Finally, executing the command
.RS
.br
.I %
program 10
.RE
.br
would assign 10 to 
.IR i ,
leaving
.I x
and
.I name
unaffected.
.PP
This call could be used for the 
.IR diff (1)
command
.RS
.PP
int blanks; int flags; char *file1; char *file2;
.br
scanargs(argc, argv, "diff b%\- efh%\- file1!s file2!s"
.in 15
, &blanks, &flags, &file1, &file2 );
.RE
.PP
and would only allow one of either 
.B "\-e \-f"
or
.B \-h
to be chosen optionally, with 
.B \-b 
as an independent option.
.B File1
and
.B file2
are both required.
The usage message for this version of
.I diff
would be
.RS
.PP
usage : diff [\-b] \-{efh} file1 file2
.RE

This call could be used for a simplified version of the
.IR sed (1)
command
.RS
.PP
int efile; int noprint; char *script; char *file1; char *file2;
.br
scanargs(argc, argv, "sed n%\- script%s f%\-editfile!s file%s"
.in 15
, &noprint, &script, &efile, &file1, &file2 );
.RE
.PP
If the
.B \-f
option is specified, then a file name must be given as the next string
argument.
The usage message for this version of
.I sed
would be
.RS
.PP
usage : sed [\-n] [script] [\-f editfile] file
.RE

.PP
Further notes on putting together a format string:
.PP
It is still possible for conditional arguments to be confused with
arguments which stand alone.  For this reason, it is recommended that
all flags (and associated conditional arguments) be specified first in
the scanargs format string.  This ordering is not necessary for the
command line arguments, however.  The only case which could still cause
confusion if these rules are followed is illustrated below:
.br
.RS
format string:	"prog d%\-num%d othernum%d"
.br
command line:	prog \-d 9
.RE
.br
It is unclear whether the number 9 should be associated with the 
.I num
parameter or the
.I othernum
parameter.  
.I Scanargs 
assigns it to the
.I num
parameter.  To force it to be associated with
.I othernum
the
command could be invoked as either
.br
.RS
		prog 9 \-d
.br
or		prog \-d \-\- 9
.RE
.br
The 
.B \-\-
in the second example is interpreted as a flag, thereby
terminating the scan for arguments introduced by the 
.BR \-d .
According to the proposed standard, an argument of
.B \-\-
is to be interpreted as terminating the optional arguments on a flag.
.PP
Note that if the format string in the above example were
.br
.RS
		"prog othernum%d d%\-num%d"
.RE
.br
it would be impossible to assign a value to 
.I num
without also
assigning a value to 
.I othernum.

.SH SEE ALSO
exec(2), scanf(3S)
.SH DIAGNOSTICS
Returns 0 on error, 1 on success.
.SH AUTHOR
Gary Newman \(em Ampex Corporation
.br
Spencer W. Thomas \(em University of Utah
.SH BUGS
By its nature a call to scanargs defines a syntax
which may be ambiguous, and although the results may be surprising, 
they are quite predictable.
The heuristic used to tell string arguments from numeric arguments is just
that.  In fact, that you can't give a number as a string argument
is sort of bogus.