11/* This file is part of the argparse library.
22 *
3- * Copyright (C) 2021 by Sergey Lafin
3+ * Copyright (C) 2021-2022 by Sergey Lafin
44 *
55 * Licensed under the LGPL v2.1, see the file LICENSE in base directory. */
66
3131
3232/* A simple implementation of some important "string.h" functions */
3333#ifdef ARG_STANDALONE
34- # define ARG_ASSERT ( x )
34+ # define ARG_ASSRT ( str ) /* Pretty much impossible to implement in standalone */
3535# define ARG_STRLEN (str ) arg_strlen(str)
3636# define ARG_STRCPY (dest , src ) arg_strcpy(dest, src)
3737# define ARG_MEMCPY (dest , src , n ) arg_memcpy(dest, src, n)
3838# define ARG_STRCMP (a , b ) arg_strcmp(a, b)
3939
40- static ARG_INLINE size_t arg_strlen (char * str ) {
40+ static ARG_INLINE size_t arg_strlen (const char * str ) {
4141 size_t len = 0 ;
4242 while (* str ) {
4343 ++ str ; ++ len ;
4444 }
4545 return len ;
4646}
4747
48- static ARG_INLINE char * arg_strcpy (char * dest , char * src ) {
48+ static ARG_INLINE char * arg_strcpy (char * dest , const char * src ) {
4949 while (* src ) {
5050 * dest ++ = * src ++ ;
5151 }
5252 dest = 0x0 ;
5353 return dest ;
5454}
5555
56- static ARG_INLINE void * arg_memcpy (void * dest , void * src , size_t n ) {
56+ static ARG_INLINE void * arg_memcpy (void * dest , const void * src , size_t n ) {
5757 while (* (char * )dest ) {
5858 * (char * )dest ++ = * (char * )src ++ ;
5959 }
6060 return dest ;
6161}
6262
63- static ARG_INLINE int arg_strcmp (char * f , char * s ) {
63+ static ARG_INLINE int arg_strcmp (const char * f , const char * s ) {
6464 while (* f && * s ) {
6565 if (!(* f ++ == * s ++ )) {
6666 break ;
@@ -71,18 +71,28 @@ static ARG_INLINE int arg_strcmp (char * f, char * s) {
7171
7272#else
7373# include <string.h>
74- # include <assert.h>
75- # define ARG_ASSERT (x ) assert(x)
7674# define ARG_STRLEN (str ) strlen(str)
7775# define ARG_STRCPY (dest , src ) strcpy(dest, src)
7876# define ARG_MEMCPY (dest , src , n ) memcpy(dest, src, n)
7977# define ARG_STRCMP (a , b ) strcmp(a, b)
78+
79+ /* Uses my own simplified assert */
80+
81+ # include <stdio.h>
82+ # include <stdlib.h>
83+ # define ARG_ASSERT (x ) { if (!(x)) arg_assert (#x); }
84+ static ARG_INLINE void arg_assert (const char * expr ) {
85+ fprintf (stderr , "argparse: assertion failed: %s\n" , expr );
86+ abort ();
87+ }
88+
8089#endif
8190
8291#define ARG_STREQ (a , b ) (ARG_STRCMP(a, b) == 0)
92+ #define RETPTR (p ) ((void **)p)
8393
8494arg_return arg_string_handler (char * data_ptr , size_t blksize , void * retval ) {
85- void * * _retval = ( void * * ) retval ;
95+ void * * _retval = RETPTR ( retval ) ;
8696 * _retval = data_ptr ;
8797 return 0 ;
8898}
@@ -227,15 +237,23 @@ static ARG_INLINE arg_return arg_parse_long (struct arg_state * state) {
227237 return ARG_NMATCH ;
228238}
229239
230- char * arg_parse (int * argc , char * * * argv , arg_list list , char * * nk , size_t * nk_size , arg_flags flags , arg_return * code ) {
240+ char * arg_parse (int * argc , char * * * argv , arg_list list , char * * nk_buf , size_t * nk_size , arg_flags flags , arg_return * code ) {
231241 ARG_ASSERT (argv != NULL );
232242 ARG_ASSERT (list != NULL );
233243
234244 size_t len = arg_list_len (list );
235245 ARG_ASSERT (len > 0 );
236246
237- if (nk_size )
238- * nk_size = 0 ;
247+ /* if nk_buf is specified, so should be the nk_size */
248+ if (nk_buf )
249+ ARG_ASSERT (nk_buf != NULL && nk_size != NULL );
250+
251+ size_t nk_lim = nk_buf ? * nk_size : 0 ;
252+ if (nk_buf )
253+ * nk_size = 0 ;
254+
255+ ++ (* argv );
256+
239257
240258 struct arg_state state ;
241259 state .argc = argc ;
@@ -247,50 +265,53 @@ char * arg_parse (int * argc, char *** argv, arg_list list, char ** nk, size_t *
247265
248266 char accept_args = 1 ;
249267
250- arg_return _code ;
251- while (-- (* state .argc )) {
252- ++ state .argv ;
253- char * arg = * state .argv ;
254- /* Not a key */
255- if ((* arg ) != '-' || !accept_args ) {
256- if (!nk ) {
257- * code = ARG_UNEXP ;
258- * argv = state .argv ;
259- return arg ;
260- }
261- if (nk_size ) ++ (* nk_size );
262- * nk = * state .argv ;
263- ++ nk ;
264- continue ;
265- }
266-
267- /* long */
268- if (* (arg + 1 ) == '-' ) {
269- * state .argv += 2 ;
270- if (!(* * state .argv )) {
271- accept_args = 0 ;
272- continue ;
273- }
274- state .type = ARG_LONG ;
275- if ((_code = arg_parse_long (& state )) != ARG_SUCCESS ) {
276- * code = _code ;
277- * argv = state .argv ;
278- return arg ;
279- }
280- continue ;
281- }
282-
283- /* short */
284- ++ (* state .argv );
285- state .type = ARG_SHORT ;
286- if ((_code = arg_parse_short (& state )) != ARG_SUCCESS ) {
287- * code = _code ;
288- * argv = state .argv ;
289- return arg ;
290- }
291- }
292-
293- return NULL ;
268+ arg_return retcode ;
269+ #define arg (*state.argv)
270+ for ((* state .argc )-- ; * state .argc ; ++ state .argv , -- (* state .argc )) {
271+ if (* arg != '-' || !accept_args ) {
272+ /* if nkbuf is null, we considered the argument malformed */
273+ if (!nk_buf ) {
274+ * code = ARG_UNEXP ;
275+ * argv = state .argv ;
276+
277+ return arg ;
278+ }
279+
280+ if ((* nk_size )++ < nk_lim ) {
281+ * nk_buf ++ = arg ;
282+ }
283+ continue ;
284+ }
285+
286+ if (* arg == '-' ) {
287+ ++ arg ;
288+ if (* arg == '-' ) {
289+ ++ arg ;
290+ /* just "--" */
291+ if (!(* arg )) {
292+ accept_args = 0 ;
293+ } else {
294+ state .type = ARG_LONG ;
295+ if ((* code = arg_parse_long (& state )) != ARG_SUCCESS ) {
296+ * argv = state .argv ;
297+ return arg - 2 ;
298+ }
299+ }
300+
301+ continue ;
302+ }
303+ else {
304+ state .type = ARG_SHORT ;
305+ if ((* code = arg_parse_short (& state )) != ARG_SUCCESS ) {
306+ * argv = state .argv ;
307+
308+ return arg - 1 ;
309+ }
310+ }
311+ }
312+ }
313+
314+ return NULL ;
294315}
295316
296317const char * arg_geterror (arg_return code ) {
0 commit comments