/* Parse bond data from line. Return MOLFILE_SUCCESS, if data was sucessfully parsed, MOLFILE_ERROR if an error occured. */ static int vtf_parse_bond(char *line, vtf_data *d) { char *s; int n; int from, to, aid, bid; s = line; while (1) { if (sscanf(s, "%u::%u%n", &from, &to, &n) == 2) { /* chain specifier */ if (from > to) { vtf_error("bad chain specifier (from > to):", s); return MOLFILE_ERROR; } bid = d->nbonds; d->nbonds += to-from; d->from = realloc(d->from, d->nbonds*sizeof(int)); d->to = realloc(d->to, d->nbonds*sizeof(int)); /* TODO: error handling */ for (aid = from; aid < to; aid++) { /*printf("creating bond from %d to %d\n", aid, aid+1);*/ d->from[bid] = aid+1; d->to[bid] = aid+2; bid++; } } else if (sscanf(s, "%u:%u%n", &from, &to, &n) == 2) { /* single bond specifier */ d->nbonds += 1; d->from = realloc(d->from, d->nbonds*sizeof(int)); d->to = realloc(d->to, d->nbonds*sizeof(int)); /* TODO: error handling */ d->from[d->nbonds-1] = from+1; d->to[d->nbonds-1] = to+1; } else { vtf_error("bad bond specifier", s); return MOLFILE_ERROR; } s += n; /* if there is no more to parse, break */ if (strlen(s) == 0) break; /* otherwise the next char should be a ',' */ if (s[0] != ',') { vtf_error("bad bond specifier in line", line); return MOLFILE_ERROR; } /* skip the ',' */ s++; } return MOLFILE_SUCCESS; }
static int vtf_read_bonds(void *data, int *nbonds, int **from, int **to, float **bondorder, int **bondtype, int *nbondtypes, char ***bondtypename) { vtf_data *d; if (!data) { vtf_error("Internal error: data==NULL in vtf_read_bonds", 0); return MOLFILE_ERROR; } d = (vtf_data*)data; *nbonds = d->nbonds; *from = d->from; *to = d->to; *bondorder = NULL; *bondtype = NULL; *nbondtypes = 0; *bondtypename = NULL; return MOLFILE_SUCCESS; }
/* Parse periodic boundary condition data from line. Called by vtf_parse_structure(). Return MOLFILE_SUCCESS, if data was sucessfully parsed, MOLFILE_ERROR if an error occured. */ static int vtf_parse_pbc(char *line, vtf_data *d) { char *s; int n = 0; if (sscanf(line, " %f %f %f%n", &d->A, &d->B, &d->C, &n) < 3) { s = line; vtf_error("Couldn't parse unit cell dimensions", s); return MOLFILE_ERROR; } s = line + n; n = sscanf(s, " %f %f %f", &d->alpha, &d->beta, &d->gamma); if (n > 0 && n < 3) { vtf_error("Couldn't parse unit cell angles", line); return MOLFILE_ERROR; } return MOLFILE_SUCCESS; }
/* Parse timestep command from line. Return MOLFILE_SUCCESS, if it was sucessfully parsed, MOLFILE_ERROR if an error occured. */ static int vtf_parse_timestep(char *line, vtf_data *d) { if (strlen(line) == 0) { d->timestep_mode = TIMESTEP_ORDERED; } else { switch (tolower(line[0])) { case 'o': { d->timestep_mode = TIMESTEP_ORDERED; break; } case 'i': { d->timestep_mode = TIMESTEP_INDEXED; break; } default: { vtf_error("bad timestep line", line); return MOLFILE_ERROR; } } } return MOLFILE_SUCCESS; }
static int vtf_read_next_timestep(void *data, int natoms, molfile_timestep_t *ts) { vtf_data *d; char *line; static char s[255]; float x,y,z; unsigned int aid; int n; if (data == NULL) { vtf_error("Internal error: data==NULL in vtf_read_next_timestep", 0); return MOLFILE_ERROR; } if (natoms <= 0) { vtf_error("Internal error: natoms <= 0 in vtf_read_next_timestep", 0); return MOLFILE_ERROR; } errno = 0; d = (vtf_data*)data; aid = 0; if (feof(d->file)) return MOLFILE_EOF; if (d->coords == NULL) { /* initialize coords */ d->coords = malloc(natoms*3*sizeof(float)); /* TODO: error handling */ for (n = 0; n < natoms*3; n++) d->coords[n] = 0.0; } /* read in the data, until the next timestep or EOF is reached */ do { line = vtf_getline(d->file); if (line == NULL) { if (errno != 0) { perror("vtfplugin"); return MOLFILE_ERROR; } break; } /* At the beginning of a vcf file, skip a timestep line */ if (d->timestep_mode == TIMESTEP_VCFSTART) { switch (tolower(line[0])) { case 'c': case 't': /* Remove the "timestep" or "coordinates" keyword */ sscanf(line, "%255s %n", s, &n); line += n; case 'i': case 'o': if (vtf_parse_timestep(line, d) != MOLFILE_SUCCESS) return MOLFILE_ERROR; line = vtf_getline(d->file); break; default: /* if this is already a coordinate line, expect an ordered block */ d->timestep_mode = TIMESTEP_ORDERED; } } /* parse timestep data */ if (d->timestep_mode == TIMESTEP_ORDERED && sscanf(line, " %f %f %f", &x, &y, &z) == 3) { if (aid < natoms) { d->coords[aid*3] = x; d->coords[aid*3+1] = y; d->coords[aid*3+2] = z; aid++; } else { vtf_error("too many atom coordinates in ordered timestep block", line); return MOLFILE_ERROR; } } else if (d->timestep_mode == TIMESTEP_INDEXED && sscanf(line, " %u %f %f %f", &aid, &x, &y, &z) == 4) { if (aid < natoms) { d->coords[aid*3] = x; d->coords[aid*3+1] = y; d->coords[aid*3+2] = z; } else { vtf_error("atom id too large in indexed timestep block", line); return MOLFILE_ERROR; } } else switch (tolower(line[0])) { /* PBC/UNITCELL RECORD */ case 'u': case 'p': { /* Remove the "pbc" or "unitcell" keyword */ sscanf(line, "%255s %n", s, &n); line += n; if (vtf_parse_pbc(line, d) != MOLFILE_SUCCESS) return MOLFILE_ERROR; break; } /* TIMESTEP RECORD*/ case 'c': case 't': { /* Remove the "timestep" or "coordinates" keyword */ sscanf(line, "%255s %n", s, &n); line += n; } case 'i': case 'o': { if (vtf_parse_timestep(line, d) != MOLFILE_SUCCESS) return MOLFILE_ERROR; line = NULL; /* indicate end of this timestep */ break; } default: { if (d->timestep_mode == TIMESTEP_INDEXED) vtf_error("unknown line in indexed timestep block", line); else vtf_error("unknown line in ordered timestep block", line); return MOLFILE_ERROR; } } if (line == NULL) break; } while (1); if (ts != NULL) { /* copy the ts data */ ts->A = d->A; ts->B = d->B; ts->C = d->C; ts->alpha = d->alpha; ts->beta = d->beta; ts->gamma = d->gamma; memcpy(ts->coords, d->coords, natoms*3*sizeof(float)); ts->velocities = NULL; ts->physical_time = 0.0; } return MOLFILE_SUCCESS; }
static void vtf_parse_structure(vtf_data *d) { char *line; /* next line in the file */ char s[255]; int n; /* initialize the default atom */ strcpy(default_atom.name, "X"); strcpy(default_atom.type, "X"); strcpy(default_atom.resname, "X"); default_atom.resid = 0; strcpy(default_atom.segid, ""); strcpy(default_atom.chain, ""); strcpy(default_atom.altloc, ""); strcpy(default_atom.insertion, ""); default_atom.occupancy = 1.0; default_atom.bfactor = 1.0; default_atom.mass = 1.0; default_atom.charge = 0.0; default_atom.radius = 1.0; do { line = vtf_getline(d->file); if (line == NULL) break; switch (tolower(line[0])) { /* ATOM RECORD */ case 'a': { /* Remove the "atom" keyword" */ sscanf(line, "%255s %n", s, &n); line += n; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'd': { /* parse atom */ d->return_code = vtf_parse_atom(line, d); break; } /* BOND RECORD */ case 'b': { /* Remove the "bond" keyword" */ sscanf(line, "%255s %n", s, &n); line += n; d->return_code = vtf_parse_bond(line, d); break; } /* PBC/UNITCELL RECORD */ case 'u': case 'p': { /* Remove the "pbc" or "unitcell" keyword */ sscanf(line, "%255s %n", s, &n); line += n; d->return_code = vtf_parse_pbc(line, d); break; } /* TIMESTEP RECORD*/ case 'c': case 't': { /* Remove the "timestep" or "coordinates" keyword */ sscanf(line, "%255s %n", s, &n); line += n; } case 'i': case 'o': { d->return_code = vtf_parse_timestep(line, d); line = NULL; /* indicate the end of the structure block */ break; } /* UNKNOWN RECORD */ default: { vtf_error("unknown line type", line); d->return_code = MOLFILE_ERROR; break; } } } while (line != NULL && d->return_code == MOLFILE_SUCCESS); /* test if structure data was parsed */ if (d->atoms == NULL && d->return_code == MOLFILE_SUCCESS) { d->return_code = MOLFILE_NOSTRUCTUREDATA; } /* test whether another error has occured */ if (errno != 0) { perror("vtfplugin"); d->return_code = MOLFILE_ERROR; } }
/* Parse atom data from line. Return MOLFILE_SUCCESS, if data was sucessfully parsed, MOLFILE_ERROR if an error occured. */ static int vtf_parse_atom(char *line, vtf_data *d) { static molfile_atom_t atom; static char aid_specifier[255]; static char keyword[255]; static char msg[255]; char *s; int n; int ignorerest; unsigned int from, to, aid; atom = default_atom; s = line; /* save the aid specifier */ if (sscanf(s, "%255s %n", aid_specifier, &n) < 1) { vtf_error("atom specifier is missing", line); return MOLFILE_ERROR; } s += n; ignorerest = 0; /* handle the keywords */ while (sscanf(s, "%255s %n", keyword, &n) == 1) { if (ignorerest) break; s += n; switch (tolower(keyword[0])) { case 'n': { /* name */ if (sscanf(s, "%16s %n", &atom.name, &n) < 1) { vtf_error("could not get name in atom record", line); return MOLFILE_ERROR; } s += n; break; } case 't': { /* type */ if (sscanf(s, "%16s %n", &atom.type, &n) < 1) { vtf_error("could not get type in atom record", line); return MOLFILE_ERROR; } s += n; break; } case 'r': { /* resname, resid, radius */ if (strlen(keyword) == 1 || strncmp(keyword, "rad", 3) == 0) { /* radius */ if (sscanf(s, "%f %n", &atom.radius, &n) < 1) { vtf_error("could not get radius in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_RADIUS; } else if (strcmp(keyword, "resid") == 0) { /* resid */ if (sscanf(s, "%d %n", &atom.resid, &n) < 1) { vtf_error("could not get resid in atom record", line); return MOLFILE_ERROR; } } else if (strcmp(keyword, "res") == 0 || strcmp(keyword, "resname") == 0) { /* resname */ if (sscanf(s, "%8s %n", &atom.resname, &n) < 1) { vtf_error("could not get resname in atom record", line); return MOLFILE_ERROR; } } else { strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); return MOLFILE_ERROR; } s += n; break; } case 's': { /* segid */ if (sscanf(s, "%8s %n", &atom.segid, &n) < 1) { vtf_error("could not get segid in atom record", line); return MOLFILE_ERROR; } s += n; break; } case 'i': { /* insertion */ if (sscanf(s, "%2s %n", &atom.insertion, &n) < 1) { vtf_error("could not get insertion in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_INSERTION; s += n; break; } case 'c': { /* chain, charge */ if (strlen(keyword) == 1 || strcmp(keyword, "chain") == 0) { if (sscanf(s, "%2s %n", &atom.chain, &n) < 1) { vtf_error("could not get chain in atom record", line); return MOLFILE_ERROR; } } } /* if "chain" is not recognized, continue with next case */ case 'q': { /* q and charge */ if (strlen(keyword) == 1 || strcmp(keyword, "charge") == 0) { if (sscanf(s, "%f %n", &atom.charge, &n) < 1) { vtf_error("could not get charge in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_CHARGE; } else { strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); return MOLFILE_ERROR; } s += n; break; } case 'a': { /* altloc, atomicnumber */ if (strlen(keyword)== 1 || strcmp(keyword, "atomicnumber") == 0) { if (sscanf(s, "%d %n", &atom.atomicnumber, &n) < 1) { vtf_error("could not get atomicnumber in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_ATOMICNUMBER; } else if (strcmp(keyword, "altloc")) { if (sscanf(s, "%2s %n", &atom.altloc, &n) < 1) { vtf_error("could not get altloc in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_ALTLOC; } else { strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); return MOLFILE_ERROR; } s += n; break; } case 'o': { /* occupancy */ if (sscanf(s, "%f %n", &atom.occupancy, &n) < 1) { vtf_error("could not get occupancy in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_OCCUPANCY; s += n; break; } case 'b': { /* bfactor */ if (sscanf(s, "%f %n", &atom.bfactor, &n) < 1) { vtf_error("could not get bfactor in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_BFACTOR; s += n; break; } case 'm': { /* mass */ if (sscanf(s, "%f %n", &atom.mass, &n) < 1) { vtf_error("could not get mass in atom record", line); return MOLFILE_ERROR; } d->optflags |= MOLFILE_MASS; s += n; break; } case 'u': { /* user data: ignore rest of the line */ ignorerest = 1; break; } default: { /* unrecognized */ strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); return MOLFILE_ERROR; } } } /* handle the aid specifier */ /* if the specifier is "default", set the default_atom */ if (aid_specifier[0] == 'd') { default_atom = atom; } else { /* otherwise parse the aid specifier */ s = aid_specifier; while (1) { from = d->natoms; if (sscanf(s, "%u:%u%n", &from, &to, &n) == 2) { /* range given */ if (from > to) { vtf_error("bad range specifier (from > to):", s); return MOLFILE_ERROR; } d->atoms = realloc(d->atoms, (to+1)*sizeof(molfile_atom_t)); /* TODO: error handling */ /* fill up with default atoms */ for (aid = d->natoms; aid < to; aid++) d->atoms[aid] = default_atom; /* create new atoms */ if (to+1 > d->natoms) d->natoms = to+1; /* TODO: error handling */ for (aid = from; aid <= to; aid++) d->atoms[aid] = atom; } else if (sscanf(s, "%u%n", &to, &n) == 1) { /* single aid given */ d->atoms = realloc(d->atoms, (to+1)*sizeof(molfile_atom_t)); /* TODO: error handling */ /* fill up with default atoms */ for (aid = d->natoms; aid < to; aid++) d->atoms[aid] = default_atom; /* create the new atom */ if (to+1 > d->natoms) d->natoms = to+1; d->atoms[to] = atom; } else { vtf_error("bad atom specifier", s); return MOLFILE_ERROR; } /* advance s */ s += n; /* if there is no more to parse, break */ if (strlen(s) == 0) break; /* otherwise the next char should be a ',' */ if (s[0] != ',') { vtf_error("bad atom specifier in line", line); return MOLFILE_ERROR; } /* skip the ',' */ s++; }; } return MOLFILE_SUCCESS; }
/* Parse atom data from line. Return MOLFILE_SUCCESS, if data was sucessfully parsed, MOLFILE_ERROR if an error occured. */ static int vtf_parse_atom(char *line, vtf_data *d) { static molfile_atom_t atom; static char keyword[255]; static char msg[255]; static char aid_specifier[255]; int n; char *s; int rest_is_userdata; int *aid_list = NULL; atom = default_atom; s = line; #ifdef DEBUG printf("\tatom record\n"); printf("line: %s\n", s); #endif /* HANDLE THE AID SPECIFIER */ /* save the aid specifier */ if (sscanf(s, " %255s%n", aid_specifier, &n) < 1) { vtf_error("atom specifier is missing", line); return MOLFILE_ERROR; } s += n; aid_list = vtf_parse_aid_specifier(aid_specifier, d); if (aid_list == NULL) return MOLFILE_ERROR; /* A -1 in the aid_list denotes the end of the list */ #define AIDLOOP(assignment) \ { \ int *aid_ptr; \ for (aid_ptr = aid_list; *aid_ptr != -1; aid_ptr++) { \ int aid = *aid_ptr; \ molfile_atom_t *cur_atom = &d->atoms[aid]; \ assignment; \ } \ } /* handle the keywords */ rest_is_userdata = 0; while (sscanf(s, " %255s%n", keyword, &n) == 1) { s += n; #ifdef DEBUG printf("keyword: \"%s\" rest: \"%s\"\n", keyword, s); #endif switch (tolower(keyword[0])) { case 'n': { /* name */ if (sscanf(s, " %16s%n", atom.name, &n) == 1) { AIDLOOP(strcpy(cur_atom->name, atom.name)); } else { vtf_error("could not get name in atom record", line); return MOLFILE_ERROR; } s += n; break; } case 't': { /* type */ if (sscanf(s, " %16s%n", atom.type, &n) == 1) { AIDLOOP(strcpy(cur_atom->type, atom.type)); } else { vtf_error("could not get type in atom record", line); return MOLFILE_ERROR; } s += n; break; } case 'r': { /* resname, resid, radius */ if (strlen(keyword) == 1 || strncmp(keyword, "rad", 3) == 0) { /* radius */ if (sscanf(s, " %f%n", &atom.radius, &n) == 1) { AIDLOOP(cur_atom->radius = atom.radius); } else { vtf_error("could not get radius in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_RADIUS; } else if (strcmp(keyword, "resid") == 0) { /* resid */ if (sscanf(s, " %d%n", &atom.resid, &n) == 1) { AIDLOOP(cur_atom->resid = atom.resid); } else { vtf_error("could not get resid in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } } else if (strcmp(keyword, "res") == 0 || strcmp(keyword, "resname") == 0) { /* resname */ if (sscanf(s, " %8s%n", atom.resname, &n) == 1) { AIDLOOP(strcpy(cur_atom->resname, atom.resname)); } else { vtf_error("could not get resname in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } } else { strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); sfree(aid_list); return MOLFILE_ERROR; } s += n; break; } case 's': { /* segid */ if (sscanf(s, " %8s%n", atom.segid, &n) == 1) { AIDLOOP(strcpy(cur_atom->segid, atom.segid)); } else { vtf_error("could not get segid in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } s += n; break; } case 'i': { /* insertion */ if (sscanf(s, " %2s%n", atom.insertion, &n) == 1) { AIDLOOP(strcpy(cur_atom->insertion, atom.insertion)); } else { vtf_error("could not get insertion in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_INSERTION; s += n; break; } case 'c': { /* chain, charge */ if (strlen(keyword) == 1 || strcmp(keyword, "chain") == 0) { if (sscanf(s, " %2s%n", atom.chain, &n) == 1) { AIDLOOP(strcpy(cur_atom->chain, atom.chain)); s += n; break; } else { vtf_error("could not get chain in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } } } /* if "chain" is not recognized, continue with next case */ case 'q': { /* q and charge */ if (strlen(keyword) == 1 || strcmp(keyword, "charge") == 0) { if (sscanf(s, " %f%n", &atom.charge, &n) == 1) { AIDLOOP(cur_atom->charge = atom.charge); } else { vtf_error("could not get charge in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_CHARGE; } else { strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); sfree(aid_list); return MOLFILE_ERROR; } s += n; break; } case 'a': { /* altloc, atomicnumber */ if (strlen(keyword)== 1 || strcmp(keyword, "atomicnumber") == 0) { if (sscanf(s, " %d%n", &atom.atomicnumber, &n) == 1) { AIDLOOP(cur_atom->atomicnumber = atom.atomicnumber); } else { vtf_error("could not get atomicnumber in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_ATOMICNUMBER; } else if (strcmp(keyword, "altloc")) { if (sscanf(s, " %2s%n", atom.altloc, &n) == 1) { AIDLOOP(strcpy(cur_atom->altloc, atom.altloc)); } else { vtf_error("could not get altloc in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_ALTLOC; } else { strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); sfree(aid_list); return MOLFILE_ERROR; } s += n; break; } case 'o': { /* occupancy */ if (sscanf(s, " %f%n", &atom.occupancy, &n) == 1) { AIDLOOP(cur_atom->occupancy = atom.occupancy); } else { vtf_error("could not get occupancy in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_OCCUPANCY; s += n; break; } case 'b': { /* bfactor */ if (sscanf(s, " %f%n", &atom.bfactor, &n) == 1) { AIDLOOP(cur_atom->bfactor = atom.bfactor); } else { vtf_error("could not get bfactor in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_BFACTOR; s += n; break; } case 'm': { /* mass */ if (sscanf(s, " %f%n", &atom.mass, &n) == 1) { AIDLOOP(cur_atom->mass = atom.mass); } else { vtf_error("could not get mass in atom record", line); sfree(aid_list); return MOLFILE_ERROR; } d->optflags |= MOLFILE_MASS; s += n; break; } case 'u': { /* userdata: the rest of the line is user data */ rest_is_userdata = 1; #ifdef _USE_TCL if (d->read_mode != VTF_MOLFILE) { AIDLOOP(vtf_set_atom_userdata(aid, s)); } #endif break; } default: { /* unrecognized */ strcpy(msg, "unrecognized keyword in atom record: "); strncat(msg, keyword, 200); vtf_error(msg, line); sfree(aid_list); return MOLFILE_ERROR; } } if (rest_is_userdata) break; } /* if the aid_list is empty, modify the default atom */ if (*aid_list == -1) { default_atom = atom; if (d->read_mode != VTF_MOLFILE) { sfree(default_userdata); default_userdata = strdup(s); } } sfree(aid_list); #ifdef DEBUG printf("\tparsed keywords\n"); #endif return MOLFILE_SUCCESS; }
/* Parse the aid specifier. Return an integer list of the aids that need to be modifed. The list is terminated by -1. If the list is NULL, an error occured. If the list is empty (i.e. it only contains -1), the default atom is to be modified. */ static int *vtf_parse_aid_specifier(char *s, vtf_data *d) { int n; unsigned int aid, from, to, offset; unsigned int size = 0; int *aid_list = NULL; if (s[0] == 'd') { /* DEFAULT */ /* if the specifier is "default", just leave the list empty! */ #ifdef DEBUG printf("%s", "\tdefine default atom\n"); #endif } else { /* otherwise parse the aid specifier */ while (1) { from = d->natoms; if (sscanf(s, " %u:%u%n", &from, &to, &n) == 2) { /* RANGE */ if (from > to) { vtf_error("bad range specifier (from > to):", s); sfree(aid_list); return NULL; } vtf_create_atoms_as_needed(to, d); /* add the range to the aid list */ offset = size; size += to-from+1; aid_list = realloc(aid_list, size*sizeof(int)); for (aid = from; aid <= to; aid++) { aid_list[offset] = aid; offset++; } } else if (sscanf(s, " %u%n", &to, &n) == 1) { /* SINGLE AID */ vtf_create_atoms_as_needed(to, d); /* add the aid to the aid_list */ size += 1; aid_list = realloc(aid_list, size*sizeof(int)); aid_list[size - 1] = to; } else { /* ERROR */ vtf_error("bad aid specifier", s); sfree(aid_list); return NULL; } /* advance s */ s += n; /* if there is no more to parse, break */ if (s[0] == '\0') break; /* otherwise the next char should be a ',' */ if (s[0] != ',') { vtf_error("bad aid specifier", s); sfree(aid_list); return NULL; } /* skip the ',' */ s++; }; } /* Terminate the list with -1 */ aid_list = realloc(aid_list, (size+1)*sizeof(int)); aid_list[size] = -1; return aid_list; }