[Dhcp-agent-commits] dhcp-agent dhcp-parser.c,NONE,1.1 dhcp-parser.h,NONE,1.1 dhcp-varfile.c,NONE,1.
Status: Alpha
Brought to you by:
actmodern
From: <act...@us...> - 2002-06-17 02:25:12
|
Update of /cvsroot/dhcp-agent/dhcp-agent In directory usw-pr-cvs1:/tmp/cvs-serv4639 Added Files: dhcp-parser.c dhcp-parser.h dhcp-varfile.c dhcp-varfile.h Log Message: new parser --- NEW FILE: dhcp-parser.c --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/dhcp-parser.c,v 1.1 2002/06/17 02:25:09 actmodern Exp $ * * Copyright 2001 Thamer Alharbash * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Parser driver. Here we can build custom parsers by plugging in * the applicable functions for each single character token. A * default parser with a 0 for a character is used as a fallback * (and to mark the end of the parser driver) * * This parser will b0rk on something that's not printable and not even * call the parse function. * * We build from the parser utility routines or we can pass our * own. * */ #include <dhcp-agent.h> #include <dhcp-util.h> #include <dhcp-stringbuffer.h> #include <dhcp-files.h> #include <dhcp-parser.h> static int is_valid_string_char(int c) { if(ispunct(c) || isalnum(c)) return 1; else return 0; } static token_t check_eof(parser_t *input) { if(feof(input->fp)) return PARSER_TOKEN_EOF; else return PARSER_TOKEN_ERROR; } /* just gobble up till the end of the newline */ static token_t parse_gobble_line(parser_t *input) { int c; while(1) { c = fgetc(input->fp); switch(c) { case EOF: return check_eof(input); case '\n': input->line_no++; return PARSER_TOKEN_NEWLINE; default: break; } } } static token_t parse_get_quoted_string(parser_t *input) { int c; while(1) { c = fgetc(input->fp); switch(c) { case EOF: return check_eof(input); case '\"': return PARSER_TOKEN_QUOTED_STRING; case '\n': return PARSER_TOKEN_ERROR; /* error to have newline in string constant. */ case ' ': case '\t': default: if(is_valid_string_char(c) || c == ' ' || c == '\t') stringbuffer_append_c(input->data_buff, (char)c); else { ungetc(c, input->fp); return PARSER_TOKEN_ERROR; } } } } static token_t parse_get_string(parser_t *input) { int c; while(1) { c = fgetc(input->fp); switch(c) { case EOF: return check_eof(input); case '\n': ungetc(c, input->fp); return PARSER_TOKEN_STRING; /* newline terminates string. */ case '\t': case ' ': ungetc(c, input->fp); return PARSER_TOKEN_STRING; /* newline terminates string. */ case '=': ungetc(c, input->fp); return PARSER_TOKEN_STRING; /* newline terminates string. */ default: if(is_valid_string_char(c)) stringbuffer_append_c(input->data_buff, (char)c); else { ungetc(c, input->fp); return PARSER_TOKEN_ERROR; /* anything else and we've been terminated. */ } } } } atom_t get_next_atom(parser_t *input) { int c; token_t token; stringbuffer_clear(input->data_buff); while(1) { c = fgetc(input->fp); switch(c) { case EOF: return PARSER_ATOM_EOF; case '#': token = parse_gobble_line(input); if(token == PARSER_TOKEN_NEWLINE || token == PARSER_TOKEN_EOF) return PARSER_ATOM_END_OF_STATEMENT; /* anything else is an error. */ return PARSER_ATOM_ERROR; case '\n': input->line_no++; return PARSER_ATOM_END_OF_STATEMENT; case '=': return PARSER_ATOM_ASSIGNMENT; case '\t': case ' ': break; case '\"': token = parse_get_quoted_string(input); if(token == PARSER_TOKEN_ERROR) return PARSER_ATOM_ERROR; return PARSER_ATOM_STRING; default: /* if we have an alphanumeric it's a string. read it in. */ if(is_valid_string_char(c)) { ungetc(c, input->fp); token = parse_get_string(input); if(token == PARSER_TOKEN_ERROR) return PARSER_ATOM_ERROR; return PARSER_ATOM_STRING; } return PARSER_ATOM_ERROR; } } } parser_t *create_parser(const char *filename) { FILE *fp; parser_t *parser; fp = file_open_or_create_safe(filename, "r"); if(fp == NULL) return NULL; parser = xmalloc(sizeof(parser_t)); parser->fp = fp; parser->line_no = 1; parser->data_buff = create_stringbuffer(); return parser; } void destroy_parser(parser_t *parser) { fclose(parser->fp); destroy_stringbuffer(parser->data_buff); xfree(parser); return; } int parser_get_line_no(parser_t *parser) { return parser->line_no; } const char *parser_get_data(parser_t *parser) { return stringbuffer_getstring(parser->data_buff); } --- NEW FILE: dhcp-parser.h --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/dhcp-parser.h,v 1.1 2002/06/17 02:25:09 actmodern Exp $ * * Copyright 2001 Thamer Alharbash <tm...@wh...> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Parser for varfiles. * */ #ifndef DHCP_PARSER_H #define DHCP_PARSER_H #define PARSER_TOKEN_ERROR 0 #define PARSER_TOKEN_NEWLINE 1 #define PARSER_TOKEN_EOF 2 #define PARSER_TOKEN_QUOTED_STRING 3 #define PARSER_TOKEN_STRING 4 #define PARSER_TOKEN_ASSIGNMENT 5 #define PARSER_ATOM_ERROR 0 #define PARSER_ATOM_STRING 1 #define PARSER_ATOM_ASSIGNMENT 2 #define PARSER_ATOM_END_OF_STATEMENT 3 #define PARSER_ATOM_EOF 4 typedef uint8_t token_t; typedef uint8_t atom_t; typedef struct { FILE *fp; int line_no; stringbuffer *data_buff; } parser_t; extern void destroy_parser(parser_t *parser); extern parser_t *create_parser(const char *filename); extern atom_t get_next_atom(parser_t *input); extern const char *parser_get_data(parser_t *input); extern int parser_get_line_no(parser_t *parser); #endif /* DHCP_PARSER_H */ --- NEW FILE: dhcp-varfile.c --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/dhcp-varfile.c,v 1.1 2002/06/17 02:25:09 actmodern Exp $ * Copyright 2001 Thamer Alharbash <tm...@wh...> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * varfiles -- variable files. All the files which we read are varfiles. * */ #include <dhcp-agent.h> #include <dhcp-util.h> #include <dhcp-stringbuffer.h> #include <dhcp-files.h> #include <dhcp-parser.h> #include <dhcp-varfile.h> const char *varfile_get_name(varfile_t *varfile) { return stringbuffer_getstring(varfile->var_name); } const char *varfile_get_val(varfile_t *varfile) { return stringbuffer_getstring(varfile->var_val); } int varfile_get_lineno(varfile_t *varfile) { return parser_get_line_no(varfile->parser); } varfile_t *create_varfile(const char *filename, uint8_t mode) { varfile_t *varfile; varfile = xmalloc(sizeof(varfile_t)); varfile->filename = strdup(filename); varfile->var_name = create_stringbuffer(); varfile->var_val = create_stringbuffer(); varfile->parser = create_parser(filename); varfile->mode = mode; return varfile; } void destroy_varfile(varfile_t *varfile) { destroy_parser(varfile->parser); destroy_stringbuffer(varfile->var_name); destroy_stringbuffer(varfile->var_val); xfree(varfile->filename); xfree(varfile); return; } const char *varfile_get_filename(varfile_t *varfile) { return varfile->filename; } int varfile_get_next_varnames(varfile_t *varfile) { atom_t atom; while(1) { atom = get_next_atom(varfile->parser); if(atom == PARSER_ATOM_END_OF_STATEMENT) /* skip empty lines/comments. */ continue; if(atom == PARSER_ATOM_EOF) return VARFILE_EOF; if(atom != PARSER_ATOM_STRING) return VARFILE_PARSE_ERROR; /* copy string out into varname */ stringbuffer_set(varfile->var_name, parser_get_data(varfile->parser)); atom = get_next_atom(varfile->parser); /* if we don't get an end of statement or eof here it's a parse error. */ if(atom != PARSER_ATOM_END_OF_STATEMENT && atom != PARSER_ATOM_EOF) return VARFILE_PARSE_ERROR; return VARFILE_SUCCESS; } } int varfile_get_next_varval(varfile_t *varfile) { atom_t atom; /* get the name first. */ while(1) { atom = get_next_atom(varfile->parser); if(atom == PARSER_ATOM_END_OF_STATEMENT) /* skip empty lines/comments. */ continue; if(atom == PARSER_ATOM_EOF) return VARFILE_EOF; if(atom != PARSER_ATOM_STRING) return VARFILE_PARSE_ERROR; /* copy string out into varname */ stringbuffer_set(varfile->var_name, parser_get_data(varfile->parser)); break; } /* the rest should be ASSIGNMENT STRING END_OF_STATEMENT; */ atom = get_next_atom(varfile->parser); if(atom != PARSER_ATOM_ASSIGNMENT) return VARFILE_PARSE_ERROR; atom = get_next_atom(varfile->parser); if(atom != PARSER_ATOM_STRING) return VARFILE_PARSE_ERROR; /* copy string out into var val */ stringbuffer_set(varfile->var_val, parser_get_data(varfile->parser)); /* now we need a clean end of statement. */ atom = get_next_atom(varfile->parser); if(atom != PARSER_ATOM_END_OF_STATEMENT && atom != PARSER_ATOM_EOF) return VARFILE_PARSE_ERROR; return VARFILE_SUCCESS; } /* Get the next var statement from file. */ int varfile_get_next_var(varfile_t *varfile) { switch(varfile->mode) { case VARFILE_VARNAMES_MODE: return(varfile_get_next_varnames(varfile)); case VARFILE_VARVAL_MODE: return(varfile_get_next_varval(varfile)); default: fatal_error("varfile: file_get_next_var: encountered a fatal bug -- please report this."); } /* should never get here. */ return 0; } --- NEW FILE: dhcp-varfile.h --- /* $Header: /cvsroot/dhcp-agent/dhcp-agent/dhcp-varfile.h,v 1.1 2002/06/17 02:25:09 actmodern Exp $ * Copyright 2001 Thamer Alharbash <tm...@wh...> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Parser for varfiles. * */ #ifndef DHCP_VARFILE_H #define DHCP_VARFILE_H typedef struct { char *filename; parser_t *parser; stringbuffer *var_name; stringbuffer *var_val; uint8_t mode; } varfile_t; /* open/close a varfile. */ extern varfile_t *create_varfile(const char *filename, uint8_t mode); extern void destroy_varfile(varfile_t *varfile); /* get variables and variable names. */ extern const char *varfile_get_name(varfile_t *varfile); extern const char *varfile_get_val(varfile_t *varfile); extern int varfile_get_lineno(varfile_t *varfile); extern const char *varfile_get_filename(varfile_t *varfile); /* get the next var */ int varfile_get_next_var(varfile_t *varfile); /* modes for varfiles. */ #define VARFILE_VARNAMES_MODE 0 /* just names. */ #define VARFILE_VARVAL_MODE 1 /* names and values. */ /* return values for get_next_var */ #define VARFILE_PARSE_ERROR -1 /* parse error. */ #define VARFILE_EOF 0 /* end of file. */ #define VARFILE_SUCCESS 1 /* success */ #endif /* DHCP_VARFILE_H */ |