1 /*********************************************************************
2 Example source code for using the argtable2 library to implement:
3 
4   ls [-aAbBcCdDfFgGhHiklLmnNopqQrRsStuUvxX1] [--author]
5   [--block-size=SIZE] [--color=[WHEN]] [--format=WORD] [--full-time]
6   [--si] [--dereference-command-line-symlink-to-dir] [--indicator-style=WORD]
7   [-I PATTERN] [--show-control-chars] [--quoting-style=WORD] [--sort=WORD]
8   [--time=WORD] [--time-style=STYLE] [-T COLS] [-w COLS] [--help]
9   [--version] [FILE]...
10 
11 This file is part of the argtable2 library.
12 Copyright (C) 1998-2001,2003-2011 Stewart Heitmann
13 sheitmann@users.sourceforge.net
14 
15 The argtable2 library is free software; you can redistribute it and/or
16 modify it under the terms of the GNU Library General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19 
20 This software is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 Library General Public License for more details.
24 
25 You should have received a copy of the GNU Library General Public
26 License along with this library; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 USA.
29 **********************************************************************/
30 
31 #include "argtable2.h"
32 
33 /* These variables hold the values parsed from the comand line by arg_parse() */
34 struct arg_lit *a, *A, *author, *b, *B, *c, *C, *d, *D, *f, *F, *fulltime;
35 struct arg_lit *g, *G, *h, *H, *si, *deref, *i, *k, *l, *L, *m, *n, *N, *o, *p;
36 struct arg_lit *q, *shcont, *Q, *r, *R, *s, *S, *t, *u, *U, *v, *x, *X, *one;
37 struct arg_lit *help, *version;
38 struct arg_int *blocksize, *T, *w;
39 struct arg_str *color, *format, *indic, *I, *Qstyle, *sort, *Time, *timesty;
40 struct arg_file *files;
41 struct arg_end *end;
42 
43 /* Here we simply echo the command line option values as a demonstration. */
44 /* In a real program, this is where we would perform the main processing. */
mymain(void)45 int mymain(void)
46     {
47     int j;
48 
49     if (a->count > 0)
50         printf("a=YES\n");
51     if (A->count > 0)
52         printf("A=YES\n");
53     if (author->count > 0)
54         printf("author=YES\n");
55     if (b->count > 0)
56         printf("b=YES\n");
57     if (blocksize->count > 0)
58         printf("blocksize=%d\n",blocksize->count);
59     if (B->count > 0)
60         printf("B=YES\n");
61     if (c->count > 0)
62         printf("c=YES\n");
63     if (C->count > 0)
64         printf("C=YES\n");
65     if (color->count > 0)
66         printf("color=%s\n",color->sval[0]);
67     if (d->count > 0)
68         printf("d=YES\n");
69     if (D->count > 0)
70         printf("D=YES\n");
71     if (f->count > 0)
72         printf("f=YES\n");
73     if (F->count > 0)
74         printf("F=YES\n");
75     if (format->count > 0)
76         printf("format=%s\n",format->sval[0]);
77     if (fulltime->count > 0)
78         printf("fulltime=YES\n");
79     if (g->count > 0)
80         printf("g=YES\n");
81     if (G->count > 0)
82         printf("G=YES\n");
83     if (h->count > 0)
84         printf("h=YES\n");
85     if (si->count > 0)
86         printf("si=YES\n");
87     if (H->count > 0)
88         printf("H=YES\n");
89     if (deref->count > 0)
90         printf("deref=YES\n");
91     if (indic->count > 0)
92         printf("indic=%s\n",indic->sval[0]);
93     if (i->count > 0)
94         printf("i=YES\n");
95     if (I->count > 0)
96         printf("I=%s\n",I->sval[0]);
97     if (k->count > 0)
98         printf("k=YES\n");
99     if (l->count > 0)
100         printf("l=YES\n");
101     if (L->count > 0)
102         printf("L=YES\n");
103     if (m->count > 0)
104         printf("m=YES\n");
105     if (n->count > 0)
106         printf("n=YES\n");
107     if (N->count > 0)
108         printf("N=YES\n");
109     if (o->count > 0)
110         printf("o=YES\n");
111     if (p->count > 0)
112         printf("p=YES\n");
113     if (q->count > 0)
114         printf("q=YES\n");
115     if (shcont->count > 0)
116         printf("shcont=YES\n");
117     if (Q->count > 0)
118         printf("Q=YES\n");
119     if (Qstyle->count > 0)
120         printf("Qstyle=%s\n",Qstyle->sval[0]);
121     if (r->count > 0)
122         printf("r=YES\n");
123     if (R->count > 0)
124         printf("R=YES\n");
125     if (s->count > 0)
126         printf("s=YES\n");
127     if (S->count > 0)
128         printf("S=YES\n");
129     if (sort->count > 0)
130         printf("sort=%s\n",sort->sval[0]);
131     if (Time->count > 0)
132         printf("time=%s\n",Time->sval[0]);
133     if (timesty->count > 0)
134         printf("timesty=%s\n",timesty->sval[0]);
135     if (t->count > 0)
136         printf("t=YES\n");
137     if (T->count > 0)
138         printf("T=%d\n",T->ival[0]);
139     if (u->count > 0)
140         printf("u=YES\n");
141     if (U->count > 0)
142         printf("U=YES\n");
143     if (v->count > 0)
144         printf("v=YES\n");
145     if (w->count > 0)
146         printf("w=%d\n",w->ival[0]);
147     if (x->count > 0)
148         printf("x=YES\n");
149     if (X->count > 0)
150         printf("X=YES\n");
151     if (one->count > 0)
152         printf("1=YES\n");
153 
154     /* print the filenames */
155     for (j=0; j<files->count; j++)
156         printf("filename[%d] = \"%s\"\n", j, files->filename[j]);
157 
158     return 0;
159     }
160 
161 
main(int argc,char ** argv)162 int main(int argc, char **argv)
163     {
164     /* The argtable[] entries define the command line options */
165     void *argtable[] = {
166                 a = arg_lit0("a", "all",                 "do not hide entries starting with ."),
167                 A = arg_lit0("A", "almost-all",          "do not list implied . and .."),
168            author = arg_lit0(NULL,"author",              "print the author of each file"),
169                 b = arg_lit0("b", "escape",              "print octal escapes for nongraphic characters"),
170         blocksize = arg_int0(NULL,"block-size","SIZE",   "use SIZE-byte blocks"),
171                 B = arg_lit0("B", "ignore-backups",      "do not list implied entries ending with ~"),
172                 c = arg_lit0("c", NULL,                  "with -lt: sort by, and show, ctime (time of last"),
173                     arg_rem(NULL,                        "  modification of file status information)"),
174                     arg_rem(NULL,                        "  with -l: show ctime and sort by name"),
175                     arg_rem(NULL,                        "  otherwise: sort by ctime"),
176                 C = arg_lit0("C", NULL,                  "list entries by columns"),
177             color = arg_str0(NULL,"color","WHEN",        "control whether color is used to distinguish file"),
178                     arg_rem(NULL,                        "  types.  WHEN may be `never', `always', or `auto'"),
179                 d = arg_lit0("d", "directory",           "list directory entries instead of contents,"),
180                     arg_rem(NULL,                        "  and do not dereference symbolic links"),
181                 D = arg_lit0("D", "dired",               "generate output designed for Emacs' dired mode"),
182                 f = arg_lit0("f", NULL,                  "do not sort, enable -aU, disable -lst"),
183                 F = arg_lit0("F", "classify",            "append indicator (one of */=@|) to entries"),
184            format = arg_str0(NULL,"format","WORD",       "across -x, commas -m, horizontal -x, long -l,"),
185                     arg_rem (NULL,                       "  single-column -1, verbose -l, vertical -C"),
186          fulltime = arg_lit0(NULL,"full-time",           "like -l --time-style=full-iso"),
187                 g = arg_lit0("g", NULL,                  "like -l, but do not list owner"),
188                 G = arg_lit0("G", "no-group",            "inhibit display of group information"),
189                 h = arg_lit0("h", "human-readable",      "print sizes in human readable format (e.g., 1K 234M 2G)"),
190                si = arg_lit0(NULL,"si",                  "likewise, but use powers of 1000 not 1024"),
191                 H = arg_lit0("H", "dereference-command-line","follow symbolic links listed on the command line"),
192             deref = arg_lit0(NULL,"dereference-command-line-symlink-to-dir","follow each command line symbolic link"),
193                     arg_rem(NULL,                       "  that points to a directory"),
194             indic = arg_str0(NULL,"indicator-style","WORD","append indicator with style WORD to entry names:"),
195                     arg_rem (NULL,                       "  none (default), classify (-F), file-type (-p)"),
196                 i = arg_lit0("i", "inode",               "print index number of each file"),
197                 I = arg_str0("I", "ignore","PATTERN",    "do not list implied entries matching shell PATTERN"),
198                 k = arg_lit0("k", NULL,                  "like --block-size=1K"),
199                 l = arg_lit0("l", NULL,                  "use a long listing format"),
200                 L = arg_lit0("L", "dereference",         "when showing file information for a symbolic"),
201                     arg_rem (NULL,                       "  link, show information for the file the link"),
202                     arg_rem (NULL,                       "  references rather than for the link itself"),
203                 m = arg_lit0("m", NULL,                  "fill width with a comma separated list of entries"),
204                 n = arg_lit0("n", "numeric-uid-gid",     "like -l, but list numeric UIDs and GIDs"),
205                 N = arg_lit0("N", "literal",             "print raw entry names (don't treat e.g. control"),
206                     arg_rem (NULL,                       "  characters specially)"),
207                 o = arg_lit0("o", NULL,                  "like -l, but do not list group information"),
208                 p = arg_lit0("p", "file-type",           "append indicator (one of /=@|) to entries"),
209                 q = arg_lit0("q", "hide-control-chars",  "print ? instead of non graphic characters"),
210            shcont = arg_lit0(NULL,"show-control-chars",  "show non graphic characters as-is (default"),
211                     arg_rem (NULL,                       "unless program is `ls' and output is a terminal)"),
212                 Q = arg_lit0("Q", "quote-name",          "enclose entry names in double quotes"),
213            Qstyle = arg_str0(NULL,"quoting-style","WORD","use quoting style WORD for entry names:"),
214                     arg_rem (NULL,                       "  literal, locale, shell, shell-always, c, escape"),
215                 r = arg_lit0("r", "reverse",             "reverse order while sorting"),
216                 R = arg_lit0("R", "recursive",           "list subdirectories recursively"),
217                 s = arg_lit0("s", "size",                "print size of each file, in blocks"),
218                 S = arg_lit0("S", NULL,                  "sort by file size"),
219              sort = arg_str0(NULL,"sort","WORD",         "extension -X, none -U, size -S, time -t, version -v,"),
220                     arg_rem (NULL,                       "status -c, time -t, atime -u, access -u, use -u"),
221              Time = arg_str0(NULL,"time","WORD",         "show time as WORD instead of modification time:"),
222                     arg_rem (NULL,                       "  atime, access, use, ctime or status; use"),
223                     arg_rem (NULL,                       "  specified time as sort key if --sort=time"),
224           timesty = arg_str0(NULL, "time-style","STYLE", "show times using style STYLE:"),
225                     arg_rem (NULL,                       "  full-iso, long-iso, iso, locale, +FORMAT"),
226                     arg_rem (NULL,                       "FORMAT is interpreted like `date'; if FORMAT is"),
227                     arg_rem (NULL,                       "FORMAT1<newline>FORMAT2, FORMAT1 applies to"),
228                     arg_rem (NULL,                       "non-recent files and FORMAT2 to recent files;"),
229                     arg_rem (NULL,                       "if STYLE is prefixed with `posix-', STYLE"),
230                     arg_rem (NULL,                       "takes effect only outside the POSIX locale"),
231                 t = arg_lit0("t", NULL,                  "sort by modification time"),
232                 T = arg_int0("T", "tabsize", "COLS",     "assume tab stops at each COLS instead of 8"),
233                 u = arg_lit0("u", NULL,                  "with -lt: sort by, and show, access time"),
234                     arg_rem (NULL,                       "  with -l: show access time and sort by name"),
235                     arg_rem (NULL,                       "  otherwise: sort by access time"),
236                 U = arg_lit0("U", NULL,                  "do not sort; list entries in directory order"),
237                 v = arg_lit0("v", NULL,                  "sort by version"),
238                 w = arg_int0("w", "width", "COLS",       "assume screen width instead of current value"),
239                 x = arg_lit0("x", NULL,                  "list entries by lines instead of by columns"),
240                 X = arg_lit0("X", NULL,                  "sort alphabetically by entry extension"),
241               one = arg_lit0("1", NULL,                  "list one file per line"),
242              help = arg_lit0(NULL,"help",                "display this help and exit"),
243           version = arg_lit0(NULL,"version",             "display version information and exit"),
244             files = arg_filen(NULL, NULL, "FILE", 0, argc+2, NULL),
245               end = arg_end(20),
246         };
247     const char *progname = "ls";
248     int exitcode=0;
249     int nerrors;
250 
251     /* verify the argtable[] entries were allocated sucessfully */
252     if (arg_nullcheck(argtable) != 0)
253         {
254         /* NULL entries were detected, some allocations must have failed */
255         printf("%s: insufficient memory\n",progname);
256         exitcode=1;
257         goto exit;
258         }
259 
260     /* allow optional argument values for --color */
261     /* and set the default value to "always" */
262     color->hdr.flag |= ARG_HASOPTVALUE;
263     color->sval[0] = "always";
264 
265     /* Parse the command line as defined by argtable[] */
266     nerrors = arg_parse(argc,argv,argtable);
267 
268     /* special case: '--help' takes precedence over error reporting */
269     if (help->count > 0)
270         {
271         printf("Usage: %s", progname);
272         arg_print_syntax(stdout,argtable,"\n");
273         printf("List information about the FILE(s) (the current directory by default).\n");
274         printf("Sort entries alphabetically if none of -cftuSUX nor --sort.\n\n");
275         arg_print_glossary(stdout,argtable,"  %-25s %s\n");
276         printf("\nSIZE may be (or may be an integer optionally followed by) one of following:\n"
277                "kB 1000, K 1024, MB 1,000,000, M 1,048,576, and so on for G, T, P, E, Z, Y.\n\n"
278                "By default, color is not used to distinguish types of files.  That is\n"
279                "equivalent to using --color=none.  Using the --color option without the\n"
280                "optional WHEN argument is equivalent to using --color=always.  With\n"
281                "--color=auto, color codes are output only if standard output is connected\n"
282                "to a terminal (tty).\n\n"
283                "Report bugs to <foo@bar>.\n");
284         exitcode=0;
285         goto exit;
286         }
287 
288     /* special case: '--version' takes precedence error reporting */
289     if (version->count > 0)
290         {
291         printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname);
292         printf("September 2003, Stewart Heitmann\n");
293         exitcode=0;
294         goto exit;
295         }
296 
297     /* If the parser returned any errors then display them and exit */
298     if (nerrors > 0)
299         {
300         /* Display the error details contained in the arg_end struct.*/
301         arg_print_errors(stdout,end,progname);
302         printf("Try '%s --help' for more information.\n",progname);
303         exitcode=1;
304         goto exit;
305         }
306 
307     /* Command line parsing is complete, do the main processing */
308     exitcode = mymain();
309 
310 exit:
311     /* deallocate each non-null entry in argtable[] */
312     arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0]));
313 
314     return exitcode;
315     }
316 
317 
318