/*
Reader for JMulTi data files.
Allin Cottrell, Aigust 2006
*/
#include <stdio.h>
#include <stdlib.h>
#include "libgretl.h"
static int try_fix_varname (char *name)
{
char test[VNAMELEN];
int err = 0;
*test = 0;
strncat(test, name, VNAMELEN - 2);
strcat(test, "1");
err = check_varname(test);
if (!err) {
fprintf(stderr, "Warning: illegal name '%s' changed to '%s'\n",
name, test);
strcpy(name, test);
} else {
/* get the right error message in place */
check_varname(name);
}
return err;
}
static int get_max_line_length (FILE *fp)
{
int c, cc = 0;
int maxlen = 0;
while ((c = fgetc(fp)) != EOF) {
if (c == '\n') {
if (cc > maxlen) {
maxlen = cc;
}
cc = 0;
}
cc++;
}
if (maxlen > 0) {
/* allow for newline and null terminator */
maxlen += 2;
}
return maxlen;
}
static int push_desc (char *line, char **desc)
{
char *p = strstr(line, "/*");
char *q = strstr(line, "*/");
char *s = NULL;
int len, err = 0;
if (p != NULL && q != NULL && q - p < 0) {
return E_DATA;
}
if (p == NULL) {
p = line;
} else {
p += 2;
}
if (q == NULL) {
q = p + strlen(p);
}
len = q - p;
if (*desc == NULL) {
s = malloc(len + 2);
if (s != NULL) {
*s = 0;
}
} else {
s = realloc(*desc, strlen(*desc) + len + 2);
}
if (s == NULL) {
free(*desc);
*desc = NULL;
err = E_ALLOC;
} else {
strncat(s, p, len);
strcat(s, "\n");
*desc = s;
}
return err;
}
static char *get_jmulti_comment (FILE *fp, char *line, int len,
int *err)
{
char *desc = NULL;
int outcomm = 0;
int incomm = 0;
while (fgets(line, len, fp) && !*err) {
if (!incomm && strstr(line, "/*") != NULL) {
incomm = 1;
}
if (incomm) {
tailstrip(line);
*err = push_desc(line, &desc);
if (strstr(line, "*/") != NULL) {
outcomm = 1;
break;
}
}
}
if (incomm && !outcomm) {
if (desc != NULL) {
free(desc);
desc = NULL;
}
*err = E_DATA;
} else if (!incomm) {
rewind(fp);
}
return desc;
}
static int parse_obs_bits (const char *s1, const char *s2,
int *pd, char *stobs)
{
int y0, p0;
int err = 0;
if ((*s2 == 'Q' || *s2 == 'M') && strlen(s2) < 2) {
return E_DATA;
}
if (strchr(s1, '/')) {
/* dated daily */
int y, m, d;
int nf;
if (strlen(s2) < 3) {
err = E_DATA;
} else {
nf = sscanf(s1, "%d/%d/%d", &m, &d, &y); /* ?? */
if (nf != 3) {
err = E_DATA;
} else {
nf = sscanf(s2, "(%d)", pd);
if (nf != 1) {
err = E_DATA;
}
}
}
if (!err) {
sprintf(stobs, "%d/%02d/%02d", y, m, d);
fprintf(stderr, "Daily data, starting '%s', pd = %d\n", stobs, *pd);
}
} else {
y0 = atoi(s1);
if (*s2 == 0) {
/* annual? */
sprintf(stobs, "%d", y0);
*pd = 1;
} else if (*s2 == 'Q') {
/* quarterly */
p0 = atoi(s2 + 1);
sprintf(stobs, "%d:%d", y0, p0);
*pd = 4;
} else if (*s2 == 'M') {
/* monthly */
p0 = atoi(s2 + 1);
sprintf(stobs, "%d:%02d", y0, p0);
*pd = 12;
} else {
err = E_DATA;
}
}
return err;
}
static int get_jmulti_obs_info (FILE *fp, char *line, int len,
int *pd, char *stobs)
{
char s1[16], s2[8];
int nf, err = 0;
while (fgets(line, len, fp) && !err) {
if (*line == '<' && strchr(line, '>') != NULL) {
tailstrip(line);
fprintf(stderr, "jmulti obs line: %s\n", line);
if (!strncmp(line, "<1>", 3)) {
/* undated data */
*pd = 1;
strcpy(stobs, "1");
} else {
*s1 = *s2 = 0;
nf = sscanf(line, "<%15s %7[^> ]", s1, s2);
if (nf < 1) {
err = E_DATA;
} else {
err = parse_obs_bits(s1, s2, pd, stobs);
}
}
break;
}
}
return err;
}
static int get_jmulti_var_info (FILE *fp, char *line, int len,
int *nv, int *nobs)
{
long offset = ftell(fp);
int err = 0;
if (fgets(line, len, fp) == NULL) {
return E_DATA;
}
tailstrip(line);
fprintf(stderr, "jmulti var line: %s\n", line);
*nv = count_fields(line);
while (fgets(line, len, fp)) {
if (!string_is_blank(line)) {
*nobs += 1;
}
}
fprintf(stderr, "jmulti: %d variables, %d observations\n",
*nv, *nobs);
fseek(fp, offset, SEEK_SET);
return err;
}
static int read_jmulti_data (FILE *fp, char *line, int len,
double **Z, DATAINFO *pdinfo,
PRN *prn)
{
char *s, numstr[32];
int i, t, err = 0;
if (fgets(line, len, fp) == NULL) {
return E_DATA;
}
s = line;
for (i=1; i<pdinfo->v; i++) {
s += strspn(s, " ");
sscanf(s, "%15s", pdinfo->varname[i]);
if (check_varname(pdinfo->varname[i]) &&
try_fix_varname(pdinfo->varname[i])) {
err = 1;
}
s += strcspn(s, " \t\n");
}
gretl_push_c_numeric_locale();
t = 0;
while (fgets(line, len, fp) && !err) {
if (string_is_blank(line)) {
continue;
}
s = line;
for (i=1; i<pdinfo->v && !err; i++) {
s += strspn(s, " \t");
if (sscanf(s, "%31s", numstr) != 1) {
err = 1;
} else {
if (!strcmp(numstr, "NaN")) {
Z[i][t] = NADBL;
} else {
Z[i][t] = atof(numstr);
}
s += strcspn(s, " \t");
}
}
t++;
}
gretl_pop_c_numeric_locale();
return err;
}
int jmulti_get_data (const char *fname, double ***pZ, DATAINFO *pdinfo,
PRN *prn)
{
int maxlen = 0;
int nvar = 0, nobs = 0;
FILE *fp;
char *descrip = NULL;
char *line = NULL;
double **newZ = NULL;
DATAINFO *newinfo = NULL;
char stobs[OBSLEN];
int pd = 0;
int err = 0;
fp = gretl_fopen(fname, "r");
if (fp == NULL) {
return E_FOPEN;
}
maxlen = get_max_line_length(fp);
if (maxlen == 0) {
fclose(fp);
return E_DATA;
}
line = malloc(maxlen);
if (line == NULL) {
fclose(fp);
return E_ALLOC;
}
rewind(fp);
descrip = get_jmulti_comment(fp, line, maxlen, &err);
if (err) {
free(line);
fclose(fp);
return err;
}
err = get_jmulti_obs_info(fp, line, maxlen, &pd, stobs);
if (err) {
goto bailout;
}
err = get_jmulti_var_info(fp, line, maxlen, &nvar, &nobs);
if (err) {
goto bailout;
}
newinfo = datainfo_new();
if (newinfo == NULL) {
pputs(prn, _("Out of memory\n"));
err = E_ALLOC;
goto bailout;
}
newinfo->v = nvar + 1;
newinfo->n = nobs;
newinfo->pd = pd;
strcpy(newinfo->stobs, stobs);
if (strcmp(newinfo->stobs, "1")) {
newinfo->structure = TIME_SERIES;
newinfo->sd0 = get_date_x(newinfo->pd, newinfo->stobs);
}
err = start_new_Z(&newZ, newinfo, 0);
if (err) {
pputs(prn, _("Out of memory\n"));
free_datainfo(newinfo);
goto bailout;
}
err = read_jmulti_data(fp, line, maxlen, newZ, newinfo, prn);
if (err) {
destroy_dataset(newZ, newinfo);
} else {
if (fix_varname_duplicates(newinfo)) {
pputs(prn, _("warning: some variable names were duplicated\n"));
}
newinfo->descrip = descrip;
descrip = NULL;
if (*pZ == NULL) {
*pZ = newZ;
*pdinfo = *newinfo;
} else {
err = merge_data(pZ, pdinfo, newZ, newinfo, prn);
}
}
bailout:
fclose(fp);
free(line);
free(descrip);
return err;
}
syntax highlighted by Code2HTML, v. 0.9.1