static const char * get_token_in(struct line_stat *ls) { int cc, esc; int in_quote = 0; if (ls->stat == PS_EOF) { return NULL; } if (ls->stat == PS_RET) { return NL; } /* トークンが始まるまで空白を読み飛ばす */ do { esc = mygetc(&cc); } while (cc > 0 && myisblank(cc) && esc == 0); if (cc == -1) { return NULL; } if (cc == '\n'){ return NL; } /**/ if (cc == '\"' && !esc) { in_quote = 1; } /**/ do { pushchar(ls, cc); esc = mygetc(&cc); if (cc < 0){ /* EOF */ pushchar(ls, 0); ls->stat = PS_EOF; return ls->buf; } if (cc == '\n' && !esc) { /* 改行 */ pushchar(ls, 0); ls->stat = PS_RET; return ls->buf; } if (!in_quote && myisblank(cc)) { break; } if (in_quote && cc == '\"' && !esc) { pushchar(ls, '\"'); break; } } while (1); pushchar(ls, 0); return ls->buf; }
static char *add_end_dot(char arg[]) { int sz = strlen(arg), i; i = sz; while (i && myisblank(arg[--i])) ; if (i && arg[i] != ',') { char *p = (char *)malloc(sz + 2); if (!p) return NULL; strncpy(p, arg, sz); p[sz] = '.'; p[sz + 1] = '\0'; return p; } return arg; }
/* Small FSM. States indicate what the machine is looking for *next*, * so eg _cfgKEYSTART means "looking for the token that indicates the start * of a key" */ struct configFile *_cfgParseConfigFile (struct configFile *cfg) { char *currentSectionString="DEFAULT"; char *currentStringStart=NULL; char *currentKey=NULL; unsigned int filePos=0, state=_cfgKEYSTART; hash_table *tempHash; /* Create the default section. */ tempHash=hashConstructTable (31); hashInsert (currentSectionString, tempHash, cfg->sections); while (filePos < cfg->bbdgSize) { switch (state) { case _cfgKEYSTART: if (cfg->bbdg[filePos]=='[') { filePos++; currentStringStart=(char *) &(cfg->bbdg[filePos]); state=_cfgSECTIONEND; break; } if (isCommentStart(cfg->bbdg[filePos])) { filePos++; state=_cfgCOMMENTEND; break; } if ( !isspace (cfg->bbdg[filePos]) ) { currentStringStart=(char *) &(cfg->bbdg[filePos]); state=_cfgKEYEND; } else { filePos ++; } break; case _cfgCOMMENTEND: if (cfg->bbdg[filePos]=='\n') { state=_cfgKEYSTART; } filePos++; break; case _cfgSECTIONEND: if (cfg->bbdg[filePos]==']') { cfg->bbdg[filePos]='\0'; currentSectionString=currentStringStart; state=_cfgKEYSTART; } filePos++; break; case _cfgKEYEND: if (isspace (cfg->bbdg[filePos]) || isKeyValSep(cfg->bbdg[filePos])) { if (isKeyValSep(cfg->bbdg[filePos])) { cfg->bbdg[filePos]='\0'; } else { cfg->bbdg[filePos]='\0'; filePos++; } currentKey=currentStringStart; state=_cfgCOLON; } else { //Do this in search routine instead (with strcasecmp) //cfg->bbdg[filePos] = tolower(cfg->bbdg[filePos]); filePos++; } break; case _cfgCOLON: if (isKeyValSep(cfg->bbdg[filePos]) || cfg->bbdg[filePos]=='\0') { state=_cfgVALSTART; } filePos++; break; case _cfgVALSTART: if (!myisblank(cfg->bbdg[filePos])) { currentStringStart=(char *) &(cfg->bbdg[filePos]); state=_cfgVALEND; } else { filePos ++; } break; case _cfgVALEND: if (cfg->bbdg[filePos]=='\n' || isCommentStart(cfg->bbdg[filePos])) { /* First see if the current section exists. */ tempHash=hashLookup (currentSectionString, cfg->sections); if (tempHash==NULL) { tempHash=hashConstructTable (31); hashInsert (currentSectionString, tempHash, cfg->sections); } /* Now stick it in the table. */ if (isCommentStart(cfg->bbdg[filePos])) { cfg->bbdg[filePos]='\0'; hashInsert (currentKey, currentStringStart, tempHash); state=_cfgCOMMENTEND; } else { cfg->bbdg[filePos]='\0'; hashInsert (currentKey, currentStringStart, tempHash); state=_cfgKEYSTART; } } filePos++; break; } } return cfg; }