Exemple #1
0
static ERL_NIF_TERM make_scalar(ErlNifEnv* env, yaml_event_t *event, int flags)
{
    int as_atom = PLAIN_AS_ATOM & flags;
    long int i;
    double d;
    int type;
    yaml_scalar_style_t style = event->data.scalar.style;
    ERL_NIF_TERM rterm;

    if (as_atom && style == YAML_SINGLE_QUOTED_SCALAR_STYLE) {
	rterm =  enif_make_atom_len(env,
				    (char *) event->data.scalar.value,
				    event->data.scalar.length);
    } else if (style == YAML_DOUBLE_QUOTED_SCALAR_STYLE) {
	rterm = make_binary_size(env, event->data.scalar.value,
				 event->data.scalar.length);
    } else if ((type = make_num(env, event->data.scalar.value, 
				event->data.scalar.length, &i, &d))) {
	if (type == INTEGER)
	    rterm = enif_make_long(env, i);
	else
	    rterm = enif_make_double(env, d);
    } else if (as_atom && style == YAML_PLAIN_SCALAR_STYLE && event->data.scalar.length) {
	rterm = enif_make_atom_len(env,
				   (char *) event->data.scalar.value,
				   event->data.scalar.length);
    } else {
	rterm = make_binary_size(env, event->data.scalar.value,
				 event->data.scalar.length);
    }

    return rterm;
}
Exemple #2
0
static struct tm *
parse_date_elements(const char *day, const char *month, const char *year,
	const char *time, const char *zone)
{
    static struct tm tm;
    char *t;
    memset(&tm, 0, sizeof(tm));

    if (!day || !month || !year || !time)
	return NULL;
    tm.tm_mday = atoi(day);
    tm.tm_mon = make_month(month);
    if (tm.tm_mon < 0)
	return NULL;
    tm.tm_year = atoi(year);
    if (strlen(year) == 4)
	tm.tm_year -= 1900;
    else if (tm.tm_year < 70)
	tm.tm_year += 100;
    else if (tm.tm_year > 19000)
	tm.tm_year -= 19000;
    tm.tm_hour = make_num(time);
    t = strchr(time, ':');
    if (!t)
	return NULL;
    t++;
    tm.tm_min = atoi(t);
    t = strchr(t, ':');
    if (t)
	tm.tm_sec = atoi(t + 1);
    return tmSaneValues(&tm) ? &tm : NULL;
}
Exemple #3
0
extern char *show_buf_num(char *start, char *end, num_t n)
{
    if (n == inf)
        return show_buf_str(start, end, "inf");
    if (n == -inf)
        return show_buf_str(start, end, "-inf");

    char tmp[NUM_MAX_LEN];
    ssize_t l;
    size_t p = NUM_MIN_PRECISION;
    num_t n1;
    do
    {
        l = snprintf(tmp, sizeof(tmp), "%.*g", (int)p, n);
        if (l < 0)
            panic("snprintf failed: %s", strerror(errno));
        p++;
        if (p >= NUM_MAX_PRECISION)
            break;
        sscanf(tmp, "%lf", &n1);
        n1 = num(make_num(n1));
    }
    while (n != n1);

    if (start >= end)
        return start + (size_t)l;

    return show_buf_str(start, end, tmp);
}
Exemple #4
0
static obj_t string_length_fn(obj_t args, Reporter rep)
{
	obj_t obj;
	if (!args_match(rep, args, 1, is_string))
		return unspecific;
	obj = list_ref(args, 0);
	return make_num(fetch_string(obj)->len);
}
Exemple #5
0
/*
 * Initialise the parser.
 */
extern void parse_init(void)
{
    name_t entry;
    entry = name_lookup("false");
    entry->val = term_boolean(make_boolean(false));
    entry = name_lookup("inf");
    entry->val = term_num(make_num(1.0/0.0));
    entry = name_lookup("nil");
    entry->val = term_nil(make_nil());
    entry = name_lookup("true");
    entry->val = term_boolean(make_boolean(true));
}
Exemple #6
0
static struct tm *
parse_date2(const char *str)
{
    /* Thu, 10 Jan 1993 01:29:59 GMT */
    const char *s;
    static struct tm tm;
    assert(NULL != str);
    memset(&tm, '\0', sizeof(struct tm));
    s = strchr(str, ',');
    if (NULL == s)
	return NULL;
    s++;
    while (*s == ' ')
	s++;
    /* backup if month is only one digit */
    if (xisdigit(*s) && !xisdigit(*(s + 1)))
	s--;
    if (strchr(s, '-'))
	return NULL;
    if ((int) strlen(s) < 20)
	return NULL;
    memset(&tm, '\0', sizeof(tm));
    tm.tm_mday = make_num(s);
    tm.tm_mon = make_month(s + 3);
    tm.tm_year = (100 * make_num(s + 7) - 1900) + make_num(s + 9);
    tm.tm_hour = make_num(s + 12);
    tm.tm_min = make_num(s + 15);
    tm.tm_sec = make_num(s + 18);
    return tmSaneValues(&tm) ? &tm : NULL;
}
Exemple #7
0
static struct tm *
parse_date1(const char *str)
{
    /* Thursday, 10-Jun-93 01:29:59 GMT */
    const char *s;
    static struct tm tm;
    assert(NULL != str);
    memset(&tm, '\0', sizeof(struct tm));
    s = strchr(str, ',');
    if (NULL == s)
	return NULL;
    s++;
    while (*s == ' ')
	s++;
    /* backup if month is only one digit */
    if (xisdigit(*s) && !xisdigit(*(s + 1)))
	s--;
    if (!strchr(s, '-'))
	return NULL;
    if ((int) strlen(s) < 18)
	return NULL;
    memset(&tm, '\0', sizeof(tm));
    tm.tm_mday = make_num(s);
    tm.tm_mon = make_month(s + 3);
    tm.tm_year = make_num(s + 7);
    /*
     * Y2K: Arjan de Vet <*****@*****.**>
     * if tm.tm_year < 70, assume it's after the year 2000.
     */
    if (tm.tm_year < 70)
	tm.tm_year += 100;
    tm.tm_hour = make_num(s + 10);
    tm.tm_min = make_num(s + 13);
    tm.tm_sec = make_num(s + 16);
    return tmSaneValues(&tm) ? &tm : NULL;
}
Exemple #8
0
//NUMのパース
object_t *parse_num(FILE *fp){
  int i=0;
  char buf;
  char tmp[BUFFER_SIZE];
  buf=skip_space_getchar(fp); 
  
  while(isdigit(buf)){
    tmp[i]=buf;    
    buf = getc(fp);
    i++;
  }
  tmp[i]='\0';
  ungetc(buf,fp);

  return make_num(atoi(tmp));
}
Exemple #9
0
void
make_time(stralloc* out, time_t t, size_t width) {
  if(opt_numeric) {
    make_num(out, (size_t)t, width);
  } else {
    struct tm ltime;
    char buf[1024];
    size_t sz;
    ssize_t n;
#ifdef HAVE_LOCALTIME_R_FUNC
    localtime_r(&t, &ltime);
#else
    ltime = *localtime(&t);
#endif
    sz = strftime(buf, sizeof(buf), opt_timestyle, &ltime);
    n = width - sz;
    while(n-- > 0) {
      stralloc_catb(out, " ", 1);
    }
    stralloc_catb(out, buf, sz);
  }
}
Exemple #10
0
int
list_dir_internal(stralloc* dir, char type) {
  size_t l;
  struct dir_s d;
  stralloc pre;
  int dtype;
  int is_dir, is_symlink;
  size_t len;
#if !WINDOWS_NATIVE
  struct stat st;
  static dev_t root_dev;
#endif
  char *name, *s;
  (void)type;
  while(dir->len > 1 && IS_DIRSEP(dir->s[dir->len - 1])) dir->len--;
  stralloc_nul(dir);
#if !WINDOWS_NATIVE
  if(root_dev == 0) {
    if(stat(dir->s, &st) != -1) {
      root_dev = st.st_dev;
    }
  }
#endif
  if(dir_open(&d, dir->s) != 0) {
    buffer_puts(buffer_2, "ERROR: Opening directory ");
    buffer_putsa(buffer_2, dir);
    buffer_puts(buffer_2, " failed!\n");
    buffer_flush(buffer_2);
    goto end;
  }
  if(dir->s[dir->len - 1] != DIRSEP_C)
    stralloc_cats(dir, DIRSEP_S);
  l = dir->len;
  while((name = dir_read(&d))) {
    unsigned int mode = 0, nlink = 0, uid = 0, gid = 0;
    uint64 size = 0, mtime = 0;
    dtype = dir_type(&d);
    dir->len = l;
    if(str_equal(name, "") || str_equal(name, ".") || str_equal(name, "..")) {
      continue;
    }
    stralloc_readyplus(dir, str_len(name) + 1);
    str_copy(dir->s + dir->len, name);
    dir->len += str_len(name);
    is_symlink = !!(dtype & D_SYMLINK);
#if !WINDOWS_NATIVE
    if(!opt_deref && lstat(dir->s, &st) != -1) {
      if(root_dev && st.st_dev) {
        if(st.st_dev != root_dev) {
          continue;
        }
      }
    }
#endif
#if !WINDOWS_NATIVE
    if(S_ISLNK(st.st_mode)) {
      stat(dir->s, &st);
    }
    mode = st.st_mode;
#endif
    if(dtype) {
      is_dir = !!(dtype & D_DIRECTORY);
    } else {
#if WINDOWS_NATIVE
      is_dir = 0;
#else
      is_dir = !!S_ISDIR(mode);
#endif
    }
    if(dtype & D_SYMLINK)
      is_symlink = 1;
#if !WINDOWS_NATIVE
    nlink = st.st_nlink;
    uid = st.st_uid;
    gid = st.st_gid;
    size = st.st_size;
    mtime = st.st_mtime;
#else
    mode = (is_dir ? 0040000 : 0100000) | (is_symlink ? 0120000 : 0);
#if USE_READDIR
    if(!is_dir) {
      size = dir_size(&d); /* dir_INTERNAL(&d)->dir_entry->d_name); */
      mtime = dir_time(&d);
    } else {
      mtime = 0;
      size = 0;
    }
#else
    size = dir_size(&d);
    mtime = dir_time(&d, D_TIME_MODIFICATION);
#endif
#endif
    if(opt_list && size >= opt_minsize) {
      stralloc_init(&pre);
      /* Mode string */
      mode_str(&pre, mode);
      stralloc_catb(&pre, " ", 1);
      /* num links */
      make_num(&pre, nlink, 3);
      stralloc_catb(&pre, " ", 1);
      /* uid */
      make_num(&pre, uid, 0);
      stralloc_catb(&pre, " ", 1);
      /* gid */
      make_num(&pre, gid, 0);
      stralloc_catb(&pre, " ", 1);
      /* size */
      make_num(&pre, size, 6);
      stralloc_catb(&pre, " ", 1);
      /* time */
      make_num(&pre, mtime, 0);
      /*     make_time(&pre, mtime, 10); */
      stralloc_catb(&pre, " ", 1);
    }
    /* fprintf(stderr, "%d %08x\n", is_dir, dir_ATTRS(&d)); */
    if(is_dir)
      stralloc_catc(dir, opt_separator);
    if(dir->len > MAX_PATH) {
      buffer_puts(buffer_2, "ERROR: Directory ");
      buffer_putsa(buffer_2, dir);
      buffer_puts(buffer_2, " longer than MAX_PATH (" STRINGIFY(MAX_PATH) ")!\n");
      /*buffer_putulong(buffer_2, MAX_PATH);
      buffer_puts(buffer_2, ")!\n");*/
      buffer_flush(buffer_2);
      goto end;
    }
    s = dir->s;
    len = dir->len;
    if(len >= 2 && s[0] == '.' && IS_DIRSEP(s[1])) {
      len -= 2;
      s += 2;
    }
    if(opt_list && size >= opt_minsize)
      buffer_putsa(buffer_1, &pre);

    if(opt_relative_to) {
      size_t sz = str_len(opt_relative_to);
      if(str_diffn(s, opt_relative_to, sz) == 0) {
        s += sz;
        len -= sz;
        while(*s == '\\' || *s == '/') {
          s++;
          len--;
        }
      }
    }

    if(size >= opt_minsize) {
      buffer_put(buffer_1, s, len);
      buffer_put(buffer_1, "\n", 1);
      buffer_flush(buffer_1);
    }

    if(is_dir && (opt_deref || !is_symlink)) {
      dir->len--;
      list_dir_internal(dir, 0);
    }
  }
end:
  dir_close(&d);
  return 0;
}
Exemple #11
0
static uint8_t *compile_def(uint8_t *pc, uint16_t *def, struct dict *d, uint16_t dn) {
	struct caddr *c=atom2caddr(dn,def[2]);
#ifdef DEBUG
	printf("(atom2caddr(%hu,%hu)=%lu)\n",dn,def[2],c-caddrs);
#endif
	c->c=pc;
	backrefs(c);
	int32_t *lbacks[16], **lback=lbacks;

	uint16_t *p=def+4;
	int l=def[0]/sizeof(uint16_t);
	for(;l--;p++) {
#ifdef DEBUG
		uint8_t *bc=pc;
		print_atom(*p);
#endif

		if(l&&p[1]==makeatom(0,0x3c)) {
			pc=compile_number(pc,*p);
			l--; p++;
			continue;
		}

		if(number(*p)) {
			uint64_t n=make_num(*p);
#ifdef DEBUG
			printf("NUMBER(%lx)",n);
#endif
			if(l&&p[1]==makeatom(0,0x37)) { // #
				pc=compile_kick(pc,n); p++; l--;
			} else {
				pc=compile_number(pc,n);
			}
		} else {
			uint16_t ww,wdn,*sdef;
			if(l>1&&p[1]==makeatom(0,0x36)) { // @
				int idx;
				ww=*p;
				wdn=p[2];
				idx=atom2idx(p[2],dict);
				if(0x10000&idx) {
					printf("\nunknown dict ");
					print_atom(p[2]);
					printf(" for ");
					print_atom(*p);
					printf("\n");
					abort();
				}
				struct dict *d1=(struct dict *)(dict->def[idx]+4);
				idx=atom2idx(*p,d1);
				if(idx&0x10000) {
					printf("unknown word ");
					print_atom(*p);
					printf(" @ ");
					print_atom(p[2]);
					printf("\n");
					abort();
				}
				sdef=d1->def[idx];
				p+=2; l-=2;
			} else if(*p==makeatom(0,0x33)) { // {
				*lback++=(int32_t*)pc;
				pc+=4;
				continue;
			} else if(*p==makeatom(0,0x34)) { // }
				lback--;
				**lback=pc-(((uint8_t*)(*lback))+4);
				continue;
			} else {
				int idx=atom2idx(*p,d);
				ww=*p; wdn=dn;
				if(0x10000&idx) {
					idx=atom2idx(*p,dict);
					wdn=makeatom(0,0x030f1205);
					if(0x10000&idx) {
						printf("unknown word");
						print_atom(*p);
						printf("\n");
						abort();

					}
					sdef=dict->def[idx];
				} else {
					sdef=d->def[idx];
				}
			}
			if(sdef[1]==makeatom(0,0x060f121408LL)) { // forth
				pc=compile_forth(pc,ww,wdn,(!l)||(p[1]==makeatom(0,0x2b)));
			} else if(sdef[1]==makeatom(0,0x090e0c090e05LL)) { // inline
				pc=compile_inline(pc,sdef);
			} else if(sdef[1]==makeatom(0,0x04011401)) { // data
				pc=compile_data(pc,sdef);
			} else if(sdef[1]==makeatom(0,0x04090314)) { // dict
				pc=compile_data(pc,sdef);
			} else {
				printf("unknown type ");
				print_atom(sdef[1]);
				printf("\n");
				abort();
			} 
		}
#ifdef DEBUG
		putchar('['); hexdump(bc,pc-bc); putchar(']');
#endif
	}
	*pc++=0xc3;
	c->len=pc-c->c;
#ifdef DEBUG
	printf("%p -> %p",c->c,pc);
	hexdump(c->c,c->len);
#endif
	return pc;
}
Exemple #12
0
time_t parse_time(const char *str, const int str_len)
{
	int hour;
	int min;
	int sec;
	int mday;
	int mon;
	int year;

	if (str[3] == ',') {
		/* Thu, 09 Jan 1993 01:29:59 GMT */

		if (str_len < 29) 
			return -1;

		mday = make_num(str+5);
		mon = make_month(str + 8);
		year = 100 * make_num(str + 12) + make_num(str + 14);
		hour = make_num(str + 17);
		min = make_num(str + 20);
		sec = make_num(str + 23);
	}
	else {
		const char *s;
		s = strchr(str, ',');
		if (!s || (str_len - (s - str) < 24)) {
			/* Wed Jun  9 01:29:59 1993 */

			if (str_len < 24)
                        	return -1;

			mon = make_month(str+4);
			mday = make_num(str+8);
			hour = make_num(str+11);
			min = make_num(str+14);
			sec = make_num(str+17);
			year = make_num(str+20)*100 + make_num(str+22);
		}
		else {
			/* Thursday, 10-Jun-93 01:29:59 GMT */

			mday = make_num(s + 2);
			mon = make_month(s + 5);
			year = make_num(s + 9) + 1900;
			if (year < 1970)
				year += 100;
			hour = make_num(s + 12);
			min = make_num(s + 15);
			sec = make_num(s + 18);
		}
	}

	if (sec < 0 || sec > 59)
		return -1;
	if (min < 0 || min > 59)
		return -1;
	if (hour < 0 || hour > 23)
		return -1;
	if (mday < 1 || mday > 31)
		return -1;
	if (mon < 1 || mon > 12)
		return -1;
	if (year < 1970 || year > 2020)
		return -1;

	return mktime(year, mon, mday, hour, min, sec);
}
Exemple #13
0
PUBLIC time_t parse_http_time ARGS1(char *, str)
{
    char * s;
    struct tm tm;
    time_t t;
#ifdef ISC3   /* Lauren */
    struct tm * gorl;		/* GMT or localtime */
    long z = 0L;
#endif

    if (!str) return 0;

    if ((s = strchr(str, ','))) {	/* Thursday, 10-Jun-93 01:29:59 GMT */
	s++;				/* or: Thu, 10 Jan 1993 01:29:59 GMT */
	while (*s && *s==' ') s++;
	if (strchr(s,'-')) {		/* First format */
	    CTRACE(stderr, "Format...... Weekday, 00-Mon-00 00:00:00 GMT\n");
	    if ((int)strlen(s) < 18) {
		CTRACE(stderr,
		       "ERROR....... Not a valid time format \"%s\"\n", s);
		return 0;
	    }
	    tm.tm_mday = make_num(s);
	    tm.tm_mon = make_month(s+3);
	    tm.tm_year = make_num(s+7);
	    tm.tm_hour = make_num(s+10);
	    tm.tm_min = make_num(s+13);
	    tm.tm_sec = make_num(s+16);
	}
	else {				/* Second format */
	    CTRACE(stderr, "Format...... Wkd, 00 Mon 0000 00:00:00 GMT\n");
	    if ((int)strlen(s) < 20) {
		CTRACE(stderr,
		       "ERROR....... Not a valid time format \"%s\"\n", s);
		return 0;
	    }
	    tm.tm_mday = make_num(s);
	    tm.tm_mon = make_month(s+3);
	    tm.tm_year = (100*make_num(s+7) - 1900) + make_num(s+9);
	    tm.tm_hour = make_num(s+12);
	    tm.tm_min = make_num(s+15);
	    tm.tm_sec = make_num(s+18);

	}
    }
    else {	/* Try the other format:  Wed Jun  9 01:29:59 1993 GMT */
	CTRACE(stderr, "Format...... Wkd Mon 00 00:00:00 0000 GMT\n");
	s = str;
	while (*s && *s==' ') s++;
	CTRACE(stderr, "Trying...... The Wrong time format: %s\n", s);
	if ((int)strlen(s) < 24) {
	    CTRACE(stderr, "ERROR....... Not a valid time format \"%s\"\n", s);
	    return 0;
	}
	tm.tm_mday = make_num(s+8);
	tm.tm_mon = make_month(s+4);
	tm.tm_year = make_num(s+22);
	tm.tm_hour = make_num(s+11);
	tm.tm_min = make_num(s+14);
	tm.tm_sec = make_num(s+17);
    }
    if (tm.tm_sec  < 0  ||  tm.tm_sec  > 59  ||
	tm.tm_min  < 0  ||  tm.tm_min  > 59  ||
	tm.tm_hour < 0  ||  tm.tm_hour > 23  ||
	tm.tm_mday < 1  ||  tm.tm_mday > 31  ||
	tm.tm_mon  < 0  ||  tm.tm_mon  > 11  ||
	tm.tm_year <70  ||  tm.tm_year >120) {
	CTRACE(stderr,
	"ERROR....... Parsed illegal time: %02d.%02d.%02d %02d:%02d:%02d\n",
	       tm.tm_mday, tm.tm_mon+1, tm.tm_year,
	       tm.tm_hour, tm.tm_min, tm.tm_sec);
	return 0;
    }

    tm.tm_isdst = -1;

    /*
     *	What a pain it is to get the timezone correctly.
     */

#if defined(sun) && !defined(__svr4__)
    t = timegm(&tm);
#else /* not sun, except svr4 */

    t = mktime(&tm);

/* BSD, have tm_gmtoff */
#if defined(SIGTSTP) && !defined(AIX) && !defined(__sgi) && !defined(_AUX) && !defined(__svr4__)
    {
	time_t cur_t = time(NULL);
	struct tm * local = localtime(&cur_t);
	t += local->tm_gmtoff;
	CTRACE(stderr,"TimeZone.... %02d hours from GMT\n",
	       (int)local->tm_gmtoff / 3600);
    }
#else /* SysV or VMS */
    {
#ifdef VMS
	CTRACE(stderr,"TimeZone.... undefined\n");
#else /* SysV */
#ifdef ISC3   /* Lauren */
	time_t cur_t = time(NULL);
	gorl = localtime(&cur_t);
	if (daylight && gorl->tm_isdst)	/* daylight time? */
	    z = altzone;	/* yes */
	else
	    z = timezone;	/* no */

	z /= 60;		/* convert to minutes */
	z = -z;			/* ISC 3.0 has it vice versa */
	t += z * 60;	
	CTRACE(stderr,"TimeZone.... %02d hours from GMT\n", z / 60);
#else
	int dst = 0;
	/*
	 * The following assumes a fixed DST offset of 1 hour,
	 * which is probably wrong.
	 */
	if (tm.tm_isdst > 0)
	    dst = -3600;
	t -= (timezone + dst);
	CTRACE(stderr,"TimeZone.... %02d hours from GMT\n", 
	       (timezone + dst) / 3600);
#endif
#endif /* SysV */
    }
#endif /* SysV or VMS */

#endif /* not sun, except svr4 */

    CTRACE(stderr, "Time string. %s", str);
    CTRACE(stderr, "Parsed...... to %ld seconds, %s", (long)t, ctime(&t));
    return t;
}
Exemple #14
0
static obj_t parse_atom(struct Parser *st)
{
	struct token *t = next(st);
	size_t i;

	switch (t->type) {
	case DOT:
		reportlocf(st->rep, t->loc, "datum expected");
		return unspecific;
	case CPAREN:
		reportlocf(st->rep, t->loc, "unmatched parenthesis");
		return unspecific;
	case END:
		return unspecific;
	case CHAR:
		if (t->len == 2) {
			reportlocf(st->rep, t->loc,
				   "end-of-input in character literal");
			return unspecific;
		} else if (t->len == 3) {
			return make_char(t->text[2]);
		} else {
			/* Convert to lowercase */
			for (i = 0; i < t->len; i++)
				t->text[i] = tolower(t->text[i]);

			if (atom_eq("#\\space", t->text, t->len)) {
				/* Space character literal */
				return make_char(' ');
			} else if (atom_eq("#\\newline", t->text, t->len)) {
				/* Newline character literal */
				return make_char('\n');
			} else {
				reportlocf(st->rep, t->loc,
					   "illegal character literal");
				return unspecific;
			}
		}
	case ATOM:
		/* Convert to lowercase */
		for (i = 0; i < t->len; i++)
			t->text[i] = tolower(t->text[i]);

		if (atom_eq("#f", t->text, t->len)) {
			/* False constant */
			return false_obj;
		} else if (atom_eq("#t", t->text, t->len)) {
			/* True constant */
			return true_obj;
		} else if (is_number(t->text, t->len)) {
			/* Copy to buffer to make null-terminated */
			char *buf = GC_MALLOC_ATOMIC((t->len+1) * sizeof(char));
			strncpy(buf, t->text, t->len);
			buf[t->len] = 0;

			/* Convert to number */
			return make_num(atol(buf));
		} else if (is_ident(t->text, t->len)) {
			/* Symbol */
			return make_symbol(intern_string(string_from(t->text, t->len)));
		} else {
			/* Invalid atom */
			reportlocf(st->rep, t->loc, "unrecognized atom");
			return unspecific;
		}
	case STRING:
		return parse_string(st, t);
	case OARRAY:
		reportlocf(st->rep, t->loc, "array literals are not supported");
		/* fallthrough: continue processing as lists */
	case OPAREN:
		return parse_list(st);
	case QUOTE:
		return parse_quotation(S_QUOTE, st);
	case QUASIQUOTE:
		return parse_quotation(S_QUASIQUOTE, st);
	case UNQUOTE:
		return parse_quotation(S_UNQUOTE, st);
	case UNQUOTE_SPLICING:
		return parse_quotation(S_UNQUOTE_SPLICING, st);
	}

	/* We should never get to here */
	return unspecific;
}