/* @@@HEAD@@@
// Miscellaneous operations.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "defs.h"
#include "y.tab.h"
#include "cdc_types.h"
#include "execute.h"
/* hardcoded wordsize, bad bad, but faster than mallocing it */
#define WORDSIZE 255
#define add_as_ident(__i) { \
*word = __i, word++, *word = NULL; \
d.type = SYMBOL; \
d.u.symbol = ident_get(w); \
list = list_add(list, &d); \
w[0] = NULL; \
word = w; \
ident_discard(d.u.symbol); \
}
#define add_as_str(__w) { \
if (wlen) { \
sw = string_from_chars(__w, wlen); \
d.type = STRING; \
d.u.str = sw; \
list = list_add(list, &d); \
string_discard(sw); \
__w[0] = NULL; \
word = __w; \
wlen = 0; \
} \
}
list_t * tokenize_cml(string_t * str) {
/* not that registering these will make much of a diff */
register int escaped;
int wlen;
char * s,
w[WORDSIZE],
* word;
list_t * list;
data_t d;
string_t * sw;
/* initialize everything */
escaped = 0;
s = string_chars(str);
w[0] = NULL;
word = w;
wlen = 0;
list = list_new(0);
for (; *s != NULL; s++) {
if (escaped) {
escaped--;
/* break the word, its all we can do with a restricted buffer */
if ((wlen + 1) == (WORDSIZE - 1))
add_as_str(w);
wlen++, *word = *s, word++, *word = NULL;
} else {
switch (*s) {
case '\\':
escaped = 1;
break;
case ' ':
add_as_str(w)
break;
case '{':
case '}':
case '[':
case ']':
case '=':
case '"':
case ':':
add_as_str(w);
add_as_ident(*s);
break;
default:
wlen++, *word = *s, word++, *word = NULL;
break;
}
}
}
if (wlen)
add_as_str(w);
return list;
}
void op_tokenize_cml(void) {
data_t * args,
* elem;
list_t * list;
string_t * str;
if (!func_init_1(&args, LIST))
return;
list = args[0].u.list;
str = string_new(0);
/* Join the list into a single string, denote line breaks */
for (elem = list_first(list); elem; elem = list_next(list, elem)) {
if (elem->type != STRING) {
string_discard(str);
cthrow(type_id, "Line %d (%D) is not a string.",
elem - list_first(list), elem);
return;
}
str = string_add_chars(str, elem->u.str->s, elem->u.str->len);
str = string_add_chars(str, "{_ln}", 5);
}
/* the old list was just a pointer to args, which gets popped */
list = tokenize_cml(str);
pop(1);
push_list(list);
list_discard(list);
}