more reconcile fixes, optimized ++
[swftools.git] / lib / args.h
1 /* args.h
2    Routines to simplify argument handling
3
4    Part of the swftools package.
5
6    Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> 
7  
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
21
22 #ifndef __args_h__
23 #define __args_h__
24
25 #ifndef NO_ARGPARSER
26
27 extern int args_callback_option(char*,char*);
28 extern int args_callback_longoption(char*,char*);
29 extern int args_callback_command(char*,char*);
30 extern void args_callback_usage(char*name);
31
32 //int argn;
33 //char**argv;
34
35 static void processargs(int argn2,char**argv2)
36 {
37     int t;
38     if(argn2==1)
39     {
40         args_callback_usage(argv2[0]);
41         exit(1);
42     }
43     for(t=1;t<argn2;t++)
44     {
45         char*next;
46         if(t<argn2-1) next=argv2[t+1];
47         else        next=0;
48
49         if(argv2[t][0]=='-' && argv2[t][1])
50         {
51             if(argv2[t][1]=='-')
52             {
53                 if(!strcmp(&argv2[t][2],"help")) 
54                 {
55                     args_callback_usage(argv2[0]);
56                     exit(1);
57                 }
58                 t+=args_callback_longoption(&argv2[t][2],next);
59             }
60             else
61             {
62                 if(strchr("?h",argv2[t][1]))
63                 {
64                     args_callback_usage(argv2[0]);
65                     exit(1);
66                 }
67                 if(argv2[t][1]) // this might be something like e.g. -xvf
68                 {
69                     char buf[2];
70                     int s=1;
71                     int ret;
72                     buf[1]=0;
73                     do{
74                         if(argv2[t][s+1]) {
75                           buf[0] = argv2[t][s];
76                           ret = args_callback_option(buf,&argv2[t][s+1]);
77                         }
78                         else {
79                           t+= args_callback_option(&argv2[t][s], next);
80                           break;
81                         }
82                         s++;
83                     } while(!ret);
84                 }
85             }
86         }
87         else
88         {
89             int num = args_callback_command(argv2[t],next);
90             if(num>2) {
91                 fprintf(stderr, "internal error in command line parsing\n");
92                 exit(1);
93             }
94             t+=num;
95         }
96     }
97 }
98
99 struct options_t
100 {
101     const char*shortoption;
102     const char*longoption;
103 };
104
105 static int args_long2shortoption(struct options_t*options, char*name, char*val)
106 {
107     char*equal = strchr(name,'=');
108     if (equal) {
109         *equal = 0;
110         equal++;
111     }
112     while(options->shortoption) {
113         if(!strcmp(options->longoption, name)) {
114                 char*tmp = (char*)malloc(strlen(options->shortoption)
115                         +(equal?strlen(equal)+2:2));
116                 strcpy(tmp, options->shortoption);
117                 if(equal) {
118                     //strcpy(&tmp[strlen(tmp)], equal);
119                     int ret = args_callback_option(tmp, equal);
120                     if(!ret) {
121                         fprintf(stderr, "Warning: Option --%s takes no parameter.\n", name);
122                     }
123                     return 0;
124                 }
125                 return args_callback_option(tmp,val);
126         }
127         options++;
128     }
129     fprintf(stderr, "Unknown option: --%s\n", name);
130     exit(1);
131 }
132
133 #endif
134
135 /* check whether the value t is in a given range.
136   examples: 3 is in range 1-10: true
137             7 is in range 2-4,6,8-10: false
138             9 is in range 1,2,3-12: true
139 */
140 static char is_in_range(int t, char*irange)
141 {
142     char*pos = irange;
143     char*digits;
144     int num;
145     char range = 0;
146     int last=0;
147     char tmp;
148
149     if(!irange)  // no range resembles (-OO,OO)
150         return 1;
151
152     while(*pos)
153     {
154         while(*pos == ' ' || *pos == '\r' || *pos == '\n' || *pos == '\t')
155             pos++;
156
157         digits = pos;
158         while(*digits>='0' && *digits<='9')
159             digits++;
160         if(digits == pos) {
161             fprintf(stderr, "Error: \"%s\" is not a valid format (digit expected)\n",irange);
162             exit(1);
163         }
164         
165         tmp=*digits;*digits=0;
166         num = atoi(pos);
167         *digits=tmp;
168         pos = digits;
169
170         while(*pos == ' ' || *pos == '\r' || *pos == '\n' || *pos == '\t')
171             pos++;
172
173         if(range && last<=t && num>=t)
174             return 1;
175         if(range) {
176             range = 0;
177             if(*pos)
178              pos ++;
179             continue;
180         }
181
182         if(*pos=='-')
183         {
184             if(range) {
185                 fprintf(stderr, "Error: \"%s\" is not a valid format (too many '-'s)\n",irange);
186                 exit(1);
187             }
188             last = num;
189             range = 1;
190             if(*pos)
191              pos ++;
192             continue;
193         } 
194         else 
195         {
196             /* if it isn't a '-', we assume it is a seperator like
197                ',', ';', ':', whatever. */
198             if(t == num)
199                 return 1;
200             if(*pos)
201              pos ++;
202             continue;
203         }
204     }
205     if(range && last<=t)
206         return 1;
207     return 0;
208 }
209
210 static char* filename2template(char*filename, int*startindex)
211 {
212     int l = strlen(filename);
213     char*newname = (char*)malloc(l+5);
214     /* first look whether the file is already numbered */
215     while(1) {
216         l--;
217         if(l<0 || strchr("0123456789", filename[l]))
218             break;
219     };
220     if(l>=0) {
221         int lastdigit=l;
222         int firstdigit=l;
223         while(firstdigit && strchr("0123456789", filename[firstdigit-1]))
224             firstdigit--;
225         *startindex = atoi(filename+firstdigit);
226         memcpy(newname, filename, firstdigit);
227         sprintf(newname+firstdigit, "%%%dd", lastdigit+1-firstdigit);
228         strcat(newname+firstdigit, filename+lastdigit+1);
229         return newname;
230     }
231     /* if it isn't, try to paste a %d between filename and extension */
232     char*dot = strrchr(filename, '.');
233     if(dot) {
234         int pos = dot-filename;
235         memcpy(newname, filename, pos);
236         newname[pos++] = '.';
237         newname[pos++] = '%';
238         newname[pos++] = 'd';
239         strcpy(newname+pos, dot);
240         *startindex = 1;
241         return newname;
242     }
243     /* if that didn't work either, just append the number at the end */
244     strcpy(newname, filename);
245     strcat(newname, ".%d");
246     *startindex = 1;
247     return newname;
248 }
249
250 #endif //__args_h__