/* $Id: get_site.c,v 2.2 2006/02/10 08:41:24 cho Exp $ */ #include #include #include #include #include #include "local_proto.h" #define isnull(c) (c=='\0') static char *my_next_att (char *); int is_decimal(char *); Site *get_site (FILE *fd, int dims, char *fs, int *has_cat) { static char *ibuf = NULL, *buf = NULL, *save = NULL; char *b; char ebuf[256], nbuf[256]; static int first = 1; static unsigned int line = 0; static int tty; static int proj; int i, err,itmp; int n = 0; /* number of categories */ int d = 0; /* number of floating point attributes */ int c = 0; /* number of string attributes */ float ftmp; static Site *site; if (first) { site = G_site_new_struct (-1, dims, 0, 0); ibuf = G_malloc (1024 * sizeof (char)); buf = G_malloc (1024 * sizeof (char)); save = buf; if (ibuf == NULL || buf == NULL) G_fatal_error ("memory allocation errory"); tty = isatty (fileno (fd)); proj = G_projection (); if (tty) { fprintf (stdout,"Enter sites, one per line, in the format:\n"); fprintf (stdout,"east north "); for (i = 3; i <= dims; ++i) fprintf (stdout,"dim%d ", i); fprintf (stdout,"attributes\n"); fprintf (stdout,"When finished, type: end\n"); } first = 0; } err = 1; while (err) { if (tty) fprintf (stdout,"location attributes> "); else line++; if (!G_getl (ibuf, 1024, fd)) return (Site *) NULL; /* G_squeeze cleans DOS newlines, but that makes Mac OS9 impossible to check for, so we do this test first */ if(strchr(ibuf,'\r') != NULL) { if('\r' == ibuf[strlen(ibuf)-1]) { ibuf[strlen(ibuf)-1] = '\0'; /* cleanse */ if(strchr(ibuf,'\r') != NULL) /* any left, eg a short Mac OS9 file */ G_fatal_error("Input file not in UNIX format (invalid newline)"); else if(1 == line) /* ie DOS '\r\n' newline */ G_warning("Input file is DOS format. Attempting anyway .."); } else /* any others, eg Mac OS9 '\r' or a backwards DOS newline */ /* fgets() gets it wrong, so there is little we can do. */ G_fatal_error("Line %d: Input file not in UNIX format (invalid newline)", line); } buf = save; strcpy (buf, ibuf); buf = G_squeeze (buf); if (*buf == 0) return (Site *) NULL; if (strcmp (buf, "end") == 0) return (Site *) NULL; if (fs) { for (b = buf; *b; b++) if (*b == *fs) *b = ' '; } if (sscanf (buf, "%s %s", ebuf, nbuf) != 2 || !G_scan_easting (ebuf, &site->east, proj) || !G_scan_northing (nbuf, &site->north, proj)) { if (!tty) { fprintf (stderr, "%s - line %d ", G_program_name (), line); } fprintf (stderr, "** invalid format **\n"); if (!tty) fprintf (stderr, "<%s>\n", ibuf); /* return (Site *) NULL; */ } else err = 0; } buf += strlen (ebuf) + strlen (nbuf) + 1; dims -= 2; for (i = 0; i < dims; ++i) { sscanf (buf, "%s", ebuf); sscanf (ebuf, "%lf", &(site->dim[i])); buf += strlen (ebuf) + 1; } /* no more dimensions-now we parse attribute fields */ while(isspace(*buf)) buf++; while (buf != NULL) { switch (*buf) { /* check for prefixed atts first, then without prefix */ case '#': /* category field */ if (n == 0) { sscanf(buf,"#%s ",ebuf); if(G_strstr(ebuf,".")==NULL && sscanf(ebuf,"%d", &itmp) ==1) { site->cattype=CELL_TYPE; site->ccat=itmp; n++; } else if(G_strstr(ebuf,".")!=NULL && sscanf(ebuf,"%f", &ftmp) ==1) { site->cattype=FCELL_TYPE; site->fcat=ftmp; n++; } else site->cattype=-1; } else G_warning ("Only one category attribute allowed per record; ignoring"); /* move to beginning of next attribute */ buf = my_next_att (buf); break; case '%': /* decimal attribute */ if (d >= site->dbl_alloc) { site->dbl_alloc++; site->dbl_att = (double *) G_realloc (site->dbl_att, site->dbl_alloc * sizeof (double)); } if ((err = sscanf (buf, "%%%lf", &(site->dbl_att[d++]))) < 1) G_warning ("error scanning floating point attribute: [%s]", buf); buf = my_next_att (buf); break; case '@': /* string attribute */ if (isnull (*buf) || isnull (*(buf + 1))) { *buf = '\0'; break; } /* moved copy of commented out code back into @ case 2/00 rsb */ else { buf++; if (c >= site->str_alloc) { site->str_alloc++; site->str_att = (char **) G_realloc (site->str_att, site->str_alloc * sizeof (char *)); if (site->str_att == NULL) G_fatal_error ("memory allocation error"); site->str_att[site->str_alloc - 1] = (char *) G_malloc (MAX_SITE_STRING * sizeof (char)); if (site->str_att[site->str_alloc - 1] == NULL) G_fatal_error ("memory allocation error"); } if ((err = cleanse_string (buf)) > 0) { G_strncpy (site->str_att[c++], buf, err); buf += err; } else *buf = '\0'; buf = my_next_att (buf); break; /* end of modification 2/00 rsb */ } case '\0': /* EOL, null encountered */ buf = my_next_att (buf); break; default: /* changed to unprefixed decimals */ /* commented 12/99: default shall be decimal field! M.N.*/ /* defaults to string attribute */ /* allow both prefixed and unprefixed strings */ /* if (c >= site->str_alloc) { site->str_alloc++; site->str_att = (char **) G_realloc (site->str_att, site->str_alloc * sizeof (char *)); if (site->str_att == NULL) G_fatal_error ("memory allocation error"); site->str_att[site->str_alloc - 1] = (char *) G_malloc (MAX_SITE_STRING * sizeof (char)); if (site->str_att[site->str_alloc - 1] == NULL) G_fatal_error ("memory allocation error"); } if ((err = cleanse_string (buf)) > 0) { G_strncpy (site->str_att[c++], buf, err); buf += err; } else *buf = '\0'; buf = my_next_att (buf); break; ***/ /* end of comment (default=strings) */ /* default is unprefixed decimal attribute */ #ifdef USE_OTHER_CODE if (d >= site->dbl_alloc) { site->dbl_alloc++; site->dbl_att = (double *) G_realloc (site->dbl_att, site->dbl_alloc * sizeof (double)); } if ((err = sscanf (buf, "%lf", &(site->dbl_att[d++]))) < 1) G_warning ("error scanning floating point attribute: <%s>", buf); buf = my_next_att (buf); break; #else if(is_decimal(buf)) { /* Convert as double */ if (d >= site->dbl_alloc) { site->dbl_alloc++; site->dbl_att = (double *) G_realloc (site->dbl_att, site->dbl_alloc * sizeof (double)); } if ((err = sscanf (buf, "%lf", &(site->dbl_att[d++]))) < 1) G_warning ("error scanning floating point attribute: '%s'", buf); buf = my_next_att (buf); } else { /* Convert as string */ if (c >= site->str_alloc) { site->str_alloc++; site->str_att = (char **) G_realloc (site->str_att, site->str_alloc * sizeof (char *)); if (site->str_att == NULL) G_fatal_error ("memory allocation error"); site->str_att[site->str_alloc - 1] = (char *) G_malloc (MAX_SITE_STRING * sizeof (char)); if (site->str_att[site->str_alloc - 1] == NULL) G_fatal_error ("memory allocation error"); } if ((err = cleanse_string (buf)) > 0) { G_strncpy (site->str_att[c++], buf, err); buf += err; } else *buf = '\0'; buf = my_next_att (buf); } #endif /* USE_OTHER_CODE */ } /* switch */ } /* while */ *has_cat = n; return site; } static char *my_next_att (char *buf) { while (!isspace (*buf) && !isnull (*buf)) buf++; if (isnull (*buf) || isnull (*(buf + 1))) return (char *) NULL; else while (isspace (*(buf + 1)) && !isnull (*(buf + 1))) buf++; buf++; return buf; } int is_decimal(char *att) { char *p; p = att; while(*p != '\0' && !isspace(*p)) { if (!isdigit(*p) && *p != '.' && *p != '-' && *p != '+') { return 0; } p++; } return 1; } /* vim: set softtabstop=4 shiftwidth=4 expandtab: */