123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- #include <errno.h>
- #include <stdlib.h>
- #define cc_t const unsigned char
- #define ch_t unsigned char
- static void
- copy_cooked( ch_t** ppDest, char const ** ppSrc );
- static void
- copy_raw( ch_t** ppDest, char const ** ppSrc );
- static void
- copy_cooked( ch_t** ppDest, char const ** ppSrc )
- {
- ch_t* pDest = (ch_t*)*ppDest;
- const ch_t* pSrc = (const ch_t*)(*ppSrc + 1);
- for (;;) {
- ch_t ch = *(pSrc++);
- switch (ch) {
- case NUL: *ppSrc = NULL; return;
- case '"': goto done;
- case '\\':
- pSrc += ao_string_cook_escape_char( (char*)pSrc, (char*)&ch, 0x7F );
- if (ch == 0x7F)
- break;
-
- default:
- *(pDest++) = ch;
- }
- }
- done:
- *ppDest = (ch_t*)pDest;
- *ppSrc = (char const *)pSrc;
- }
- static void
- copy_raw( ch_t** ppDest, char const ** ppSrc )
- {
- ch_t* pDest = *ppDest;
- cc_t* pSrc = (cc_t*) (*ppSrc + 1);
- for (;;) {
- ch_t ch = *(pSrc++);
- switch (ch) {
- case NUL: *ppSrc = NULL; return;
- case '\'': goto done;
- case '\\':
-
- switch (*pSrc) {
- case NUL: *ppSrc = NULL; return;
- case '\r':
- if (*(++pSrc) == '\n')
- ++pSrc;
- continue;
- case '\n':
- ++pSrc;
- continue;
- case '\'':
- ch = '\'';
-
- case '\\':
- ++pSrc;
- break;
- }
-
- default:
- *(pDest++) = ch;
- }
- }
- done:
- *ppDest = pDest;
- *ppSrc = (char const *) pSrc;
- }
- token_list_t*
- ao_string_tokenize( char const* str )
- {
- int max_token_ct = 1;
- token_list_t* res;
- if (str == NULL) goto bogus_str;
-
- while (IS_WHITESPACE_CHAR(*str)) str++;
- if (*str == NUL) {
- bogus_str:
- errno = ENOENT;
- return NULL;
- }
-
- {
- cc_t* pz = (cc_t*)str;
- do {
- max_token_ct++;
- while (! IS_WHITESPACE_CHAR(*++pz))
- if (*pz == NUL) goto found_nul;
- while (IS_WHITESPACE_CHAR(*pz)) pz++;
- } while (*pz != NUL);
- found_nul:
- ;
- }
- res = malloc( sizeof(*res) + strlen(str) + (max_token_ct * sizeof(ch_t*)) );
- if (res == NULL) {
- errno = ENOMEM;
- return res;
- }
-
- {
- ch_t* pzDest = (ch_t*)(res->tkn_list + (max_token_ct + 1));
- res->tkn_ct = 0;
- do {
- res->tkn_list[ res->tkn_ct++ ] = pzDest;
- for (;;) {
- int ch = (ch_t)*str;
- if (IS_WHITESPACE_CHAR(ch)) {
- found_white_space:
- while (IS_WHITESPACE_CHAR(*++str)) ;
- break;
- }
- switch (ch) {
- case '"':
- copy_cooked( &pzDest, &str );
- if (str == NULL) {
- free(res);
- errno = EINVAL;
- return NULL;
- }
- if (IS_WHITESPACE_CHAR(*str))
- goto found_white_space;
- break;
- case '\'':
- copy_raw( &pzDest, &str );
- if (str == NULL) {
- free(res);
- errno = EINVAL;
- return NULL;
- }
- if (IS_WHITESPACE_CHAR(*str))
- goto found_white_space;
- break;
- case NUL:
- goto copy_done;
- default:
- str++;
- *(pzDest++) = ch;
- }
- } copy_done:;
-
- *(pzDest++) = NUL;
- } while (*str != NUL);
- res->tkn_list[ res->tkn_ct ] = NULL;
- }
- return res;
- }
- #ifdef TEST
- #include <stdio.h>
- #include <string.h>
- int
- main( int argc, char** argv )
- {
- if (argc == 1) {
- printf("USAGE: %s arg [ ... ]\n", *argv);
- return 1;
- }
- while (--argc > 0) {
- char* arg = *(++argv);
- token_list_t* p = ao_string_tokenize( arg );
- if (p == NULL) {
- printf( "Parsing string ``%s'' failed:\n\terrno %d (%s)\n",
- arg, errno, strerror( errno ));
- } else {
- int ix = 0;
- printf( "Parsed string ``%s''\ninto %d tokens:\n", arg, p->tkn_ct );
- do {
- printf( " %3d: ``%s''\n", ix+1, p->tkn_list[ix] );
- } while (++ix < p->tkn_ct);
- free(p);
- }
- }
- return 0;
- }
- #endif
|