/*ARGSUSED1*/ void special(int key, int x, int y) { switch(key) { case GLUT_KEY_UP: levelup(); break; case GLUT_KEY_DOWN: leveldown(); break; } glutPostRedisplay(); }
int config_read_mem(config_t* cfg, char *mem, size_t n) { int c, line, next, status; enum {prekey, key, postkey, preval, val_raw, val_single, val_double, postval, comment} state = prekey; char *buf, *keybuf, *valbuf, *level; size_t i; line = 1; buf = keybuf = valbuf = level = NULL; for (i = 0; i <= n; ++i) { c = *mem++; if (i == n) c = EOF; switch (c) { case ';': switch (state) { case prekey: case val_raw: case postval: while (c != '\n' && c != '\r' && c != EOF && i < n) ++i, c = *mem++; --i, --mem; break; default: config_set_strerror(cfg, "unexpected start of comment"); goto error; } break; case '{': switch (state) { case key: case postkey: level = levelup(level, buf); free(buf); buf = NULL; state = prekey; break; default: config_set_strerror(cfg, "unexpected level declaration"); goto error; } break; case '}': switch (state) { case prekey: case val_raw: case postval: if (level == NULL) return line; level = leveldown(level); break; default: config_set_strerror(cfg, "unexpected '}'"); goto error; } break; case '=': switch (state) { case key: case postkey: keybuf = strdup(buf); free(buf); buf = NULL; state = preval; break; default: config_set_strerror(cfg, "unexpected '='"); goto error; } break; case '"': switch (state) { case preval: state = val_double; break; case val_double: state = postval; break; case val_single: buf = addchar(buf, c); break; default: config_set_strerror(cfg, "unexpected '\"'"); goto error; } break; case '\'': switch (state) { case preval: state = val_single; break; case val_single: state = postval; break; case val_double: buf = addchar(buf, c); break; default: config_set_strerror(cfg,"unexpected \"'\""); goto error; } break; case EOF: switch (state) { case prekey: case postval: case val_raw: break; default: line = -1; config_set_strerror(cfg,"parse error"); goto error; } case '\r': case '\n': switch (state) { case prekey: break; case val_raw: case postval: valbuf = strdup(buf); free(buf); buf = NULL; if (keybuf && valbuf) { status = config_set_with_level(cfg,level, keybuf, valbuf); free(keybuf); free(valbuf); keybuf = valbuf = NULL; if (status) { config_set_strerror(cfg,"out of memory"); line = -1; goto error; } } else { free (keybuf); free (valbuf); config_set_strerror(cfg,"out of memory"); line = -1; goto error; } break; default: config_set_strerror(cfg,"unexpected end of file"); goto error; } ++line; state = prekey; break; case ' ': case '\t': switch (state) { case key: state = postkey; break; case val_raw: state = postval; break; case val_single: case val_double: buf = addchar(buf, c); break; default: continue; } break; case '\\': //next = fgetc(fp); next = *(mem+1); switch (state) { case val_single: if (next == '\'') { buf = addchar(buf, '\''); ++mem, ++i; } else { buf = addchar(buf, '\\'); } break; case val_double: ++mem, ++i; if (next == 'n') buf = addchar(buf, '\n'); else if (next == 't') buf = addchar(buf, '\t'); else if (next == 'r') buf = addchar(buf, '\r'); else if (next == 'v') buf = addchar(buf, '\v'); else if (next == '\\') buf = addchar(buf, '\\'); else --mem, --i; break; default: break; } break; default: switch (state) { case prekey: state = key; case key: buf = addchar(buf, c); break; case preval: state = val_raw; case val_raw: case val_single: case val_double: buf = addchar(buf, c); break; default: config_set_strerror(cfg,"parse error"); goto error; } } } if (level != NULL) { config_set_strerror(cfg,"missing '}'"); goto error; } return 0; error: free(buf); free(keybuf); free(valbuf); free(level); return line; }