예제 #1
0
/** Parse member function.
 *
 * @param parse		Parser object.
 * @param outer_csi	CSI containing this declaration or @c NULL if global.
 * @return		New syntax tree node.
 */
static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
{
	stree_fun_t *fun;
	stree_symbol_t *symbol;
	bool_t body_expected;

	fun = stree_fun_new();
	symbol = stree_symbol_new(sc_fun);

	symbol->u.fun = fun;
	symbol->outer_csi = outer_csi;
	fun->symbol = symbol;

	lmatch(parse, lc_fun);
	fun->name = parse_ident(parse);

#ifdef DEBUG_PARSE_TRACE
	printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
#endif
	fun->sig = parse_fun_sig(parse);

	/* Parse attributes. */
	parse_symbol_attrs(parse, symbol);

	body_expected = !stree_symbol_has_attr(symbol, sac_builtin) &&
	    (outer_csi->cc != csi_interface);

	fun->proc = stree_proc_new();
	fun->proc->outer_symbol = symbol;

	if (lcur_lc(parse) == lc_scolon) {
		lskip(parse);

		/* Body not present */
		if (body_expected) {
			cspan_print(fun->name->cspan);
			printf(" Error: Function '");
			symbol_print_fqn(symbol);
			printf("' should have a body.\n");
			parse_note_error(parse);
		}

		fun->proc->body = NULL;
	} else {
		lmatch(parse, lc_is);
		fun->proc->body = parse_block(parse);
		lmatch(parse, lc_end);

		/* Body present */
		if (!body_expected) {
			cspan_print(fun->name->cspan);
			printf(" Error: Function declaration '");
			symbol_print_fqn(symbol);
			printf("' should not have a body.\n");
			parse_note_error(parse);
		}
	}

	return fun;
}
예제 #2
0
/** Parse variable declaration statement.
 *
 * @param parse		Parser object.
 * @return		New syntax tree node.
 */
static stree_vdecl_t *parse_vdecl(parse_t *parse)
{
	stree_vdecl_t *vdecl;

	vdecl = stree_vdecl_new();

	lmatch(parse, lc_var);
	vdecl->name = parse_ident(parse);
	lmatch(parse, lc_colon);
	vdecl->type = parse_texpr(parse);

	if (lcur_lc(parse) == lc_assign) {
		lskip(parse);
		(void) parse_expr(parse);
	}

	lmatch(parse, lc_scolon);

#ifdef DEBUG_PARSE_TRACE
	printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
	printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
	    vdecl, vdecl->name, vdecl->name->sid);
#endif
	return vdecl;
}
예제 #3
0
/** Parse @c if statement.
 *
 * @param parse		Parser object.
 * @return		New syntax tree node.
 */
static stree_if_t *parse_if(parse_t *parse)
{
	stree_if_t *if_s;
	stree_if_clause_t *if_c;

#ifdef DEBUG_PARSE_TRACE
	printf("Parse 'if' statement.\n");
#endif
	if_s = stree_if_new();
	list_init(&if_s->if_clauses);

	/* Parse @c if clause. */
	lmatch(parse, lc_if);

	if_c = stree_if_clause_new();
	if_c->cond = parse_expr(parse);
	lmatch(parse, lc_then);
	if_c->block = parse_block(parse);

	list_append(&if_s->if_clauses, if_c);

	/* Parse @c elif clauses. */
	while (lcur_lc(parse) == lc_elif) {
		lskip(parse);
		if_c = stree_if_clause_new();
		if_c->cond = parse_expr(parse);
		lmatch(parse, lc_then);
		if_c->block = parse_block(parse);

		list_append(&if_s->if_clauses, if_c);
	}

	/* Parse @c else clause. */
	if (lcur_lc(parse) == lc_else) {
		lskip(parse);
		if_s->else_block = parse_block(parse);
	} else {
		if_s->else_block = NULL;
	}

	lmatch(parse, lc_end);
	return if_s;
}
예제 #4
0
int extinputs_parse_2D(const char *filename, struct pulse_2D **cfginputs,
                       int N1, int N2)
{
    FILE *fin;
    char buf[MAX_LINE];

    char *start;
    char *end;
    char *values;

    int error = 0;

    fin = fopen(filename, "r");
    if (!fin)
        return -1;

    int lineno = 0;

    double t, q1, q2, i, d, m;  /* the values to be read */

    /* Scan through file line by line */
    while (fgets(buf, sizeof(buf), fin) != NULL) {
        lineno++;
        start = lskip(rstrip(buf));     /* chop whites */

        if (*start && *start != '#') {
            /* Remove possible comments at the end */
            end = find_char_or_comment(start, '#');
            if (*end == '#')
                *end = '\0';
            values = rstrip(start);
            /* Not a comment, must be a line containing 6 numbers */
            /* Scan and check if the inputs is correctly formatted */
            if (sscanf(values, "%lf %lf %lf %lf %lf %lf",
                       &t, &d, &q1, &q2, &i, &m) == 6) {
                if (t >= 0 && d > 0 && m >= 0) {
                    *cfginputs =
                        append_pulse_2D(*cfginputs,
                                        new_pulse_2D(N1, N2, t, d,
                                                     -q1, -q2, i, m));
                } else {
                    printf("Durations and time onsets should be positive.\n");
                    printf("Check configuration file for external inputs.\n");
                    error = lineno;
                }
            } else if (!error) {
                /* No '=' found on name=value line  */
                error = lineno;
            }
        }
    }
    fclose(fin);
    return error;
}
예제 #5
0
/** Parse symbol attributes.
 *
 * Parse list of attributes and add them to @a symbol.
 *
 * @param parse		Parser object
 * @param symbol	Symbol to add these attributes to
 */
static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol)
{
	stree_symbol_attr_t *attr;

	/* Parse attributes. */
	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
		lskip(parse);
		attr = parse_symbol_attr(parse);
		list_append(&symbol->attr, attr);
	}
}
예제 #6
0
static char *stripquote(char *s)
{
    s = lskip(s);
    char *p=NULL;
    rstrip(s, &p);
    p--;
    if( ISQUOTE(*s) && ISQUOTE(*p) ) {
        s++;
        *p = '\0';
    }
    return s;
}
예제 #7
0
/** Parse identifier.
 *
 * @param parse		Parser object.
 * @return		New syntax tree node.
 */
stree_ident_t *parse_ident(parse_t *parse)
{
	stree_ident_t *ident;

#ifdef DEBUG_PARSE_TRACE
	printf("Parse identifier.\n");
#endif
	lcheck(parse, lc_ident);
	ident = stree_ident_new();
	ident->sid = lcur(parse)->u.ident.sid;
	ident->cspan = lcur_span(parse);
	lskip(parse);

	return ident;
}
예제 #8
0
/** Parse function signature.
 *
 * @param parse		Parser object.
 * @return		New syntax tree node.
 */
static stree_fun_sig_t *parse_fun_sig(parse_t *parse)
{
	stree_fun_sig_t *sig;
	stree_proc_arg_t *arg;

	sig = stree_fun_sig_new();

	lmatch(parse, lc_lparen);

#ifdef DEBUG_PARSE_TRACE
	printf("Parsing function signature.\n");
#endif

	list_init(&sig->args);

	if (lcur_lc(parse) != lc_rparen) {

		/* Parse formal parameters. */
		while (!parse_is_error(parse)) {
			arg = parse_proc_arg(parse);

			if (stree_arg_has_attr(arg, aac_packed)) {
				sig->varg = arg;
				break;
			} else {
				list_append(&sig->args, arg);
			}

			if (lcur_lc(parse) == lc_rparen)
				break;

			lmatch(parse, lc_scolon);
		}
	}

	lmatch(parse, lc_rparen);

	if (lcur_lc(parse) == lc_colon) {
	    	lskip(parse);
		sig->rtype = parse_texpr(parse);
	} else {
		sig->rtype = NULL;
	}

	return sig;
}
예제 #9
0
/** Parse argument attribute.
 *
 * @param parse		Parser object.
 * @return		New syntax tree node.
 */
static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
{
	stree_arg_attr_t *attr;

	if (lcur_lc(parse) != lc_packed) {
		cspan_print(lcur_span(parse));
		printf(" Error: Unexpected attribute '");
		lem_print(lcur(parse));
		printf("'.\n");
		parse_note_error(parse);
	}

	lskip(parse);

	attr = stree_arg_attr_new(aac_packed);
	return attr;
}
예제 #10
0
/** Verify that lclass of current lem is @a lc and go to next lem.
 *
 * If a lem of different lclass is found, a parse error is raised and
 * a message is printed.
 *
 * @param parse		Parser object.
 * @param lc		Expected lclass.
 */
void lmatch(parse_t *parse, lclass_t lc)
{
#ifdef DEBUG_LPARSE_TRACE
	printf("lmatch(");
	lclass_print(lc);
	printf(")\n");
#endif
	/*
	 * This allows us to skip error checking in many places. If there is an
	 * active error, lmatch() does nothing (similar to parse_block(), etc.
	 *
	 * Without this measure we would have to check for error all the time
	 * or risk requiring extra input from the user (in interactive mode)
	 * before actually bailing out from the parser.
	 */
	if (parse_is_error(parse))
		return;

	lcheck(parse, lc);
	lskip(parse);
}
예제 #11
0
/** Parse formal function argument.
 *
 * @param parse		Parser object.
 * @return		New syntax tree node.
 */
static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
{
	stree_proc_arg_t *arg;
	stree_arg_attr_t *attr;

	arg = stree_proc_arg_new();
	arg->name = parse_ident(parse);
	lmatch(parse, lc_colon);
	arg->type = parse_texpr(parse);

#ifdef DEBUG_PARSE_TRACE
	printf("Parse procedure argument.\n");
#endif
	list_init(&arg->attr);

	/* Parse attributes. */
	while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
		lskip(parse);
		attr = parse_arg_attr(parse);
		list_append(&arg->attr, attr);
	}

	return arg;
}
예제 #12
0
/* Parse given INI-style file. May have [section]s, name=value pairs
   (whitespace stripped), and comments starting with ';' (semicolon). Section
   is "" if name=value pair parsed before any section heading. name:value
   pairs are also supported as a concession to Python's ConfigParser.

   For each name=value pair parsed, call handler function with given user
   pointer as well as section, name, and value (data only valid for duration
   of handler call). Handler should return nonzero on success, zero on error.

   Returns 0 on success, line number of first error on parse error (doesn't
   stop on first error).
*/
static int ini_parse(char *filestart, size_t filelen,
	int (*handler)(void *, char *, char *, char *),	void *user)
{
	/* Uses a fair bit of stack (use heap instead if you need to) */
	char line[MAX_LINE];
	char section[MAX_SECTION] = "";
	char prev_name[MAX_NAME] = "";

	char *curmem = filestart;
	char *start;
	char *end;
	char *name;
	char *value;
	size_t memleft = filelen;
	int lineno = 0;
	int error = 0;

	/* Scan through file line by line */
	while (memgets(line, sizeof(line), &curmem, &memleft) != NULL) {
		lineno++;
		start = lskip(rstrip(line));

		if (*start == ';' || *start == '#') {
			/*
			 * Per Python ConfigParser, allow '#' comments at start
			 * of line
			 */
		}
#if CONFIG_INI_ALLOW_MULTILINE
		else if (*prev_name && *start && start > line) {
			/*
			 * Non-blank line with leading whitespace, treat as
			 * continuation of previous name's value (as per Python
			 * ConfigParser).
			 */
			if (!handler(user, section, prev_name, start) && !error)
				error = lineno;
		}
#endif
		else if (*start == '[') {
			/* A "[section]" line */
			end = find_char_or_comment(start + 1, ']');
			if (*end == ']') {
				*end = '\0';
				strncpy0(section, start + 1, sizeof(section));
				*prev_name = '\0';
			} else if (!error) {
				/* No ']' found on section line */
				error = lineno;
			}
		} else if (*start && *start != ';') {
			/* Not a comment, must be a name[=:]value pair */
			end = find_char_or_comment(start, '=');
			if (*end != '=')
				end = find_char_or_comment(start, ':');
			if (*end == '=' || *end == ':') {
				*end = '\0';
				name = rstrip(start);
				value = lskip(end + 1);
				end = find_char_or_comment(value, '\0');
				if (*end == ';')
					*end = '\0';
				rstrip(value);
				/* Strip double-quotes */
				if (value[0] == '"' &&
				    value[strlen(value)-1] == '"') {
					value[strlen(value)-1] = '\0';
					value += 1;
				}

				/*
				 * Valid name[=:]value pair found, call handler
				 */
				strncpy0(prev_name, name, sizeof(prev_name));
				if (!handler(user, section, name, value) &&
				     !error)
					error = lineno;
			} else if (!error)
				/* No '=' or ':' found on name[=:]value line */
				error = lineno;
		}
	}

	return error;
}
예제 #13
0
/** Parse member property.
 *
 * @param parse		Parser object.
 * @param outer_csi	CSI containing this declaration or @c NULL if global.
 * @return		New syntax tree node.
 */
static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
{
	stree_prop_t *prop;
	stree_symbol_t *symbol;

	stree_ident_t *ident;
	stree_proc_arg_t *arg;

	prop = stree_prop_new();
	list_init(&prop->args);

	symbol = stree_symbol_new(sc_prop);
	symbol->u.prop = prop;
	symbol->outer_csi = outer_csi;
	prop->symbol = symbol;

	lmatch(parse, lc_prop);

	if (lcur_lc(parse) == lc_self) {
		/* Indexed property set */

		/* Use some name that is impossible as identifier. */
		ident = stree_ident_new();
		ident->sid = strtab_get_sid(INDEXER_IDENT);
		prop->name = ident;

		lskip(parse);
		lmatch(parse, lc_lsbr);

		/* Parse formal parameters. */
		while (!parse_is_error(parse)) {
			arg = parse_proc_arg(parse);
			if (stree_arg_has_attr(arg, aac_packed)) {
				prop->varg = arg;
				break;
			} else {
				list_append(&prop->args, arg);
			}

			if (lcur_lc(parse) == lc_rsbr)
				break;

			lmatch(parse, lc_scolon);
		}

		lmatch(parse, lc_rsbr);
	} else {
		/* Named property */
		prop->name = parse_ident(parse);
	}

	lmatch(parse, lc_colon);
	prop->type = parse_texpr(parse);

	/* Parse attributes. */
	parse_symbol_attrs(parse, symbol);

	lmatch(parse, lc_is);

	while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
		switch (lcur_lc(parse)) {
		case lc_get:
			parse_prop_get(parse, prop);
			break;
		case lc_set:
			parse_prop_set(parse, prop);
			break;
		default:
			lunexpected_error(parse);
		}
	}

	lmatch(parse, lc_end);

	return prop;
}
예제 #14
0
/* See documentation in header file. */
int CIniParser::ini_parse_file(FILE* file, void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */

    char line[256];
    char section[64] = "";
    char prev_name[64] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

    /* Scan through file line by line */
    while (fgets(line, 256, file) != NULL) {
        lineno++;

        start = line;

#if INI_ALLOW_BOM
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }
#endif
        start = lskip(rstrip(start));

        if (*start == ';' || *start == '#') {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }

#if INI_ALLOW_MULTILINE
        else if (*prev_name && *start && start > line) {
            /* Non-black line with leading whitespace, treat as continuation
               of previous name's value (as per Python ConfigParser). */
            if (!handler(user, section, prev_name, start) && !error)
                error = lineno;
        }
#endif
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!ValueHandler(user, section, name, value) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }

#if INI_STOP_ON_FIRST_ERROR
        if (error)
            break;
#endif
    }

    return error;
}
예제 #15
0
int parse_ini_file(control *c, params *p, state *s)
{
    /*

    Loop through the file which is passed on the standard in, and break
    the file up into the relevant sections...

    */

    char line[STRING_LENGTH];
    char section[STRING_LENGTH] = "";
    char prev_name[STRING_LENGTH] = "";
    char *start;
    char *end;
    char *name;
    char *value;

    int error = 0;
    int line_number = 0;

    if ((c->ifp = fopen(c->cfg_fname, "r")) == NULL){
        prog_error("Error opening output file for write on line", __LINE__);
    }

    while (fgets(line, sizeof(line), c->ifp) != NULL) {
        line_number++;
        start = lskip(rstrip(line));
        if (*start == ';' || *start == '#') {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No ']' found on section line */
                error = line_number;

            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));

                if (!handler(section, name, value, c, p, s) && !error)
                    error = line_number;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = line_number;
                break;
            }
        }
    }

    if (c->print_options == END) {
        /* we need to re-read this file to dump the final state */
        rewind(c->ifp);
    }

    return error;


}
예제 #16
0
파일: ini.c 프로젝트: a2o/snoopy
/* See documentation in header file. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
                     void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
    char line[INI_MAX_LINE];
    int max_line = INI_MAX_LINE;
#else
    char* line;
    int max_line = INI_INITIAL_ALLOC;
#endif
#if INI_ALLOW_REALLOC
    char* new_line;
    int offset;
#endif
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

#if !INI_USE_STACK
    line = (char*)malloc(INI_INITIAL_ALLOC);
    if (!line) {
        return -2;
    }
#endif

#if INI_HANDLER_LINENO
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
#else
#define HANDLER(u, s, n, v) handler(u, s, n, v)
#endif

    /* Scan through stream line by line */
    while (reader(line, max_line, stream) != NULL) {
#if INI_ALLOW_REALLOC
        offset = strlen(line);
        while (offset == max_line - 1 && line[offset - 1] != '\n') {
            max_line *= 2;
            if (max_line > INI_MAX_LINE)
                max_line = INI_MAX_LINE;
            new_line = realloc(line, max_line);
            if (!new_line) {
                free(line);
                return -2;
            }
            line = new_line;
            if (reader(line + offset, max_line - offset, stream) == NULL)
                break;
            if (max_line >= INI_MAX_LINE)
                break;
            offset += strlen(line + offset);
        }
#endif

        lineno++;

        start = line;
#if INI_ALLOW_BOM
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }
#endif
        start = lskip(rstrip(start));

        if (strchr(INI_START_COMMENT_PREFIXES, *start)) {
            /* Start-of-line comment */
        }
#if INI_ALLOW_MULTILINE
        else if (*prev_name && *start && start > line) {
            /* Non-blank line with leading whitespace, treat as continuation
               of previous name's value (as per Python configparser). */
            if (!HANDLER(user, section, prev_name, start) && !error)
                error = lineno;
        }
#endif
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_chars_or_comment(start + 1, "]");
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        }
        else if (*start) {
            /* Not a comment, must be a name[=:]value pair */
            end = find_chars_or_comment(start, "=:");
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = end + 1;
#if INI_ALLOW_INLINE_COMMENTS
                end = find_chars_or_comment(value, NULL);
                if (*end)
                    *end = '\0';
#endif
                value = lskip(value);
                rstrip(value);

                /* Strip surrounding double and single quotes */
                if ((*value == '"') && (value[strlen(value) - 1] == '"')) {
                    value[strlen(value) - 1] = '\0';
                    value += 1;
                } else {
                    if ((*value == '"') && (value[strlen(value) - 1] == '"')) {
                        value[strlen(value) - 1] = '\0';
                        value += 1;
                    }
                }

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!HANDLER(user, section, name, value) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }

#if INI_STOP_ON_FIRST_ERROR
        if (error)
            break;
#endif
    }

#if !INI_USE_STACK
    free(line);
#endif

    return error;
}
예제 #17
0
int ini_parse_string_impl(const std::string & s,
                          int (*handler)(void*, const char*, const char*,
                                         const char*),
                          void* user)
{
    std::istringstream input(s);

    /* Uses a fair bit of stack (use heap instead if you need to) */
    char section[MAX_INI_STRING] = "";

    bool has_group = false;
    int lineno = 0;
    int error = 0;

    /* Scan through file line by line */
    while (!at_end(input)) {
        std::string newline;
        get_line(input, newline);
        char * line = (char*)newline.c_str();
        lineno++;

        char * start = line;
        char * end;

        // UTF-8 BOM
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }

        start = lskip(rstrip(start));

        char c = *start;

        if (c == ';' || c == '#' || (c == '/' && start[1] == '/')) {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        } else if (c == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                has_group = true;
            } else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        } else if (c && c != ';' && has_group) {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                char * name = rstrip(start);
                char * value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                if (!handler(user, section, name, value) && !error)
                    error = lineno;
            } else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }
    }

    return error;
}
예제 #18
0
    // read and parse
    int load(const char* filename) {
        FILE *file = fopen(filename, "r");
        if(!file) return false;

        char *line = new char[INI_MAX_LINE];
        std::string prev_value, prev_name;
        char *section = new char [MAX_SECTION];
        *section = '\0';

        int  bMultiline = 0;
        int lineno = 0, error=0;
        char *start, *end, *name, *value;
        while (fgets(line, INI_MAX_LINE, file) != NULL) {
            lineno++;
            start = line;
            start = lskip(start);
            // remove comment
            end = find_char_or_comment(start, '\0');
            if( *end != '\0' )  // it points to a comment char
                *end = '\0';
            rstrip(start, &end);

            if( start == end )
                continue;

            if ( bMultiline ) {
                if( *(end-1) == '\\' && (end-1 == start || *(end-2) == ' ') )  { // continue reading next line
                    // remove " \"
                    *(--end) = '\0';
                    if( end > start && *(end-1) == ' ')
                        *(--end) = '\0';

                    prev_value += start;
                }
                else{
                    prev_value += start;
                    if( !handle_record(section, prev_name.c_str(), prev_value.c_str()) )
                        error = lineno;
                    bMultiline = 0;
                    prev_value = "";
                    prev_name = "";
                }
            }
            else if( *start == '[' ) { // found section
                end = find_char_or_comment(start + 1, ']');
                if (*end == ']') {
                    *end = '\0';
                    strncpy0(section, start + 1, MAX_SECTION);
                }
                else{
                    /* No ']' found on section line */
                    error = lineno;
                }
                bMultiline = false;
            }
            else {
                /* Not a comment, must be a name[=:]value pair */
                bMultiline = false;
                char *nend = find_char_or_comment(start, '=');
                if (*nend != '=') {
                    nend = find_char_or_comment(start, ':');
                }
                if (*nend == '=' || *nend == ':') {
                    *nend = '\0';
                    value = lskip(nend + 1);
                    name = rstrip(start, &nend);

                    /* Valid name[=:]value pair found, call handler */
                    if( *(end-1) == '\\' && (end-1 == value || *(end-2) == ' ') )  { // continue reading next line
                        // remove " \"
                        *(--end) = '\0';
                        if( end > value && *(end-1) == ' ')
                            *(--end) = '\0';

                        prev_value = value;
                        prev_name = name;
                        bMultiline = true;
                    }
                    if( !bMultiline ) if (!handle_record(section, name, value))
                        error = lineno;
                }
                else if (!error) {
                    /* No '=' or ':' found on name[=:]value line */
                    error = lineno;
                }
            }
            if (error)
                break;
        } // while getline

        fclose(file);
        delete [] line;
        delete [] section;
        return error;
    } // read function
예제 #19
0
파일: inih.c 프로젝트: Namoshek/libelektra
/* See documentation in header file. */
int ini_parse_file (FILE * file, const struct IniConfig * config, void * user)
{
	/* Uses a fair bit of stack (use heap instead if you need to) */
	char * line;

	char section[MAX_SECTION] = "";
	char prev_name[MAX_NAME] = "";

	char * start;
	char * end;
	char * name;
	char * value;
	char delim = config->delim;
	int lineno = 0;
	int error = 0;

	line = (char *)malloc (INI_MAX_LINE);

	ELEKTRA_LOG_DEBUG ("Allocated memory for line");

	if (!line)
	{
		return -2;
	}

	/* Scan through file line by line */
	while (fgets (line, INI_MAX_LINE, file) != NULL)
	{
		lineno++;
		ELEKTRA_LOG_DEBUG ("Read line %d with content “%s”", lineno, line);

		start = line;
#if INI_ALLOW_BOM
		if (lineno == 1 && (unsigned char)start[0] == 0xEF && (unsigned char)start[1] == 0xBB && (unsigned char)start[2] == 0xBF)
		{
			start += 3;
			config->bomHandler (user, 1);
		}
		else
		{
			config->bomHandler (user, 0);
		}
#endif
		if (*start == '\n')
		{
			if (!config->commentHandler (user, "") && !error) error = lineno;
			continue;
		}
		start = lskip (line);
		if (*start == '\0')
		{
			if (!config->commentHandler (user, "") && !error) error = lineno;
			continue;
		}
		if (isContinuation (line, config) && config->supportMultiline && *prev_name)
		{
			start = line + strlen (config->continuationString);
			if (*start == '"') ++start;
			end = line + (strlen (line) - 1);
			while ((*end != '"') && (!isprint (*end)) && (end > start))
			{
				if (*end == '\n') *end = '\0';
				--end;
			}
			if (*end == '"') *end = '\0';

			if (!config->keyHandler (user, section, prev_name, start, 1) && !error) error = lineno;
		}
		else if (isSection (line))
		{
			ELEKTRA_LOG_DEBUG ("Line contains a section");
			end = line + (strlen (line) - 1);
			while (end > start)
			{
				if (*end == ']') break;
				--end;
			}
			++start;
			if (*end == ']')
			{
				*end = '\0';
				strncpy0 (section, start, sizeof (section));
				*prev_name = '\0';
				ELEKTRA_LOG_DEBUG ("Found section “%s”", section);

				size_t numberBackslashes = 0;
				for (char * endSection = section + strlen (section) - 1; endSection >= section && *endSection == '\\';
				     endSection--)
				{
					numberBackslashes++;
				}
				if (numberBackslashes % 2 != 0)
				{
					ELEKTRA_LOG_WARNING ("Found uneven number of backlashes at end of section");
					error = lineno;
					break;
				}

				if (!config->sectionHandler (user, section) && !error) error = lineno;
			}
			else
			{
				end = line + (strlen (line) - 1);
				if (*end == '\n')
				{
					strncpy0 (section, start, sizeof (section));
					while (fgets (line, INI_MAX_LINE, file))
					{
						end = line + (strlen (line) - 1);
						while ((end > line) && *end != ']')
							--end;
						if (*end == ']')
						{
							*end = '\0';
							strncpy0 (section + strlen (section), line, sizeof (section) - strlen (section));
							*prev_name = '\0';
							if (!config->sectionHandler (user, section) && !error) error = lineno;
							break;
						}
						else
						{
							strncpy0 (section + strlen (section), line, sizeof (section) - strlen (section));
						}
					}
				}
				else
				{
					error = lineno;
				}
			}
		}
		else if (isComment (line))
		{
			start = line;
			end = line + (strlen (line) - 1);
			if (*end == '\n') *end = '\0';
			if (!config->commentHandler (user, start) && !error) error = lineno;
		}
		else
		{
			ELEKTRA_LOG_DEBUG ("Line contains a key");

			char * ptr = start;
			unsigned int assign = 0;
			ELEKTRA_LOG_DEBUG ("Search for delimiter “%c”", delim);
			while (*ptr)
			{
				if (*ptr == delim)
				{
					++assign;
				}
				++ptr;
			}

			if (assign == 1)
			{
				ELEKTRA_LOG_DEBUG ("Found exactly one delimiter");
				name = start;
				end = strchr (start, delim);
				if (*name == '"')
				{
					ELEKTRA_LOG_DEBUG ("Name starts with double quote character");
					++name;
					if (*(end - 2) == '"')
					{
						*(end - 2) = '\0';
					}
					else if (*(end - 1) == '"')
					{
						*(end - 1) = '\0';
					}
					else
					{
						ELEKTRA_LOG_DEBUG ("Did not find closing double quote characters in current line");
						strncpy0 (prev_name, name, sizeof (prev_name));
						while (fgets (line, INI_MAX_LINE, file))
						{
							ELEKTRA_LOG_DEBUG ("Read continuation line with content “%s”", line);
							end = line + (strlen (line) - 1);
							while (end > line && *end != '"')
								--end;
							if (*end == '"')
							{
								ELEKTRA_LOG_DEBUG ("Found closing double quote character");
								*(end++) = '\0';
								strncpy0 (prev_name + strlen (prev_name), line,
									  sizeof (prev_name) - strlen (prev_name));
								break;
							}
							else
							{
								ELEKTRA_LOG_DEBUG ("Found name continuation");
								strncpy (prev_name + strlen (prev_name), line,
									 sizeof (prev_name) - strlen (prev_name));
							}
							ELEKTRA_LOG_DEBUG ("New extended name is “%s”", prev_name);
						}
						name = prev_name;
						ELEKTRA_LOG_DEBUG ("Name of key is “%s”", name);
					}
				}
				if (*end != delim)
				{
					ELEKTRA_LOG_DEBUG ("Search for delimiter in “%s”", end);
					ptr = lskip (end + 1);
					end = strchr (ptr, delim);
					if (end && *end == delim)
					{
						*end = '\0';
						ELEKTRA_LOG_DEBUG ("Found delimiter – New name is “%s”", end);
					}
					else
					{
						ELEKTRA_LOG_WARNING ("Unable to find delimiter");
						error = lineno;
						break;
					}
				}
				else
				{
					*end = '\0';
				}
				if (name != prev_name && end > line)
				{
					rstrip (end - 1);
				}
				value = lskip (end + 1);
				end = find_char_or_comment (value, '\0');
				if (*end == ';') *end = '\0';
				rstrip (value);
				if (*value == '"')
				{
					*(value++) = '\0';
					while ((*end != '"') && !isprint (*end) && end > value)
						--end;
					if (*end == '"') *end = '\0';
				}
				if (prev_name != name) strncpy0 (prev_name, name, sizeof (prev_name));
				if (!config->keyHandler (user, section, name, value, 0) && !error) error = lineno;
			}
			else if (assign == 0)
			{
				ELEKTRA_LOG_DEBUG ("Found no delimiter");
				if (*start == '"')
				{
					ELEKTRA_LOG_DEBUG ("Found initial double quote character");
					++start;
					end = line + (strlen (line) - 1);
					while (end > start && *end != '"')
						--end;
					if (*end == '"' && end != start)
					{
						*end = '\0';
						if (!config->keyHandler (user, section, start, NULL, 0) && !error) error = lineno;
					}
					else
					{
						ELEKTRA_LOG_DEBUG ("Did not find closing double quote character");
						strncpy0 (prev_name, start, sizeof (prev_name));
						while (fgets (line, INI_MAX_LINE, file))
						{
							end = line + (strlen (line) - 1);
							ELEKTRA_LOG_DEBUG ("Read continuation line with content “%s”", line);
							while (end > line && *end != '"')
								--end;
							if (*end == '"')
							{
								ELEKTRA_LOG_DEBUG ("Found closing double quote character");
								*end = '\0';
								strncpy0 (prev_name + strlen (prev_name), line,
									  sizeof (prev_name) - strlen (prev_name));
								break;
							}
							else
							{
								ELEKTRA_LOG_DEBUG ("Found name continuation");
								strncpy (prev_name + strlen (prev_name), line,
									 sizeof (prev_name) - strlen (prev_name));
							}
							ELEKTRA_LOG_DEBUG ("New extended name is “%s”", prev_name);
						}
						name = prev_name;
						ptr = end + 1;
						end = strchr (ptr, '=');
						if (!end) end = strchr (ptr, ':');
						if (!end)
						{
							if (!config->keyHandler (user, section, name, NULL, 0) && !error) error = lineno;
						}
						else
						{
							*end = '\0';
							value = lskip (end + 1);
							if (*value == '"') end = find_char_or_comment (value, '\0');
							if (*end == ';') *end = '\0';
							rstrip (value);
							if (*value == '"' || *(value + 1) == '"')
							{
								if (*value == '"')
									*(value++) = '\0';
								else if (*(value + 1) == '"')
								{
									*(value + 1) = '\0';
									value += 2;
								}
								while ((*end != '"') && !isprint (*end) && end > value)
									--end;
								if (*end == '"') *end = '\0';
							}
							if (prev_name != name) strncpy0 (prev_name, name, sizeof (prev_name));
							if (!config->keyHandler (user, section, name, value, 0) && !error) error = lineno;
						}
					}
				}
				else
				{
					name = rstrip (start);
					strncpy0 (prev_name, name, sizeof (prev_name));
					if (!config->keyHandler (user, section, name, NULL, 0) && !error) error = lineno;
				}
			}
			else
			{
				ELEKTRA_LOG_DEBUG ("Found multiple delimiters");
				ptr = start + 1;
				while (*ptr)
				{
					if (*ptr == delim)
					{
						if (*(ptr + 1) == '"' || *(ptr + 2) == '"' || *(ptr - 1) == '"' || *(ptr - 2) == '"') break;
					}
					++ptr;
				}
				if (*ptr)
				{
					ELEKTRA_LOG_DEBUG ("Found double quote character");
					char tmpDel[4] = { ' ', delim, ' ', '\0' };
					end = strstr (ptr, tmpDel);
					name = NULL;
					if (end)
					{
						// keyname == "=" or " = " where '=' is the delimiter
						if (*(ptr + 1) == '"')
						{
							*(ptr + 1) = '\0';
						}
						else if (*(ptr + 2) == '"')
						{
							*(ptr + 2) = '\0';
						}
						if (*(ptr - 1) == '"')
							*(ptr - 1) = '\0';
						else if (*(ptr - 2) == '"')
							*(ptr - 2) = '\0';
						name = ptr;
					}
					else if (*ptr == delim)
					{
						*ptr = '\0';
						rstrip (start);
						if (*start == '"') ++start;
						if (*(ptr - 1) == '"')
							*(ptr - 1) = '\0';
						else if (*(ptr - 2) == '"')
							*(ptr - 2) = '\0';
						name = start;
					}
					else
					{
						if (!end) end = strrstr (start + 1, tmpDel);
						*end = '\0';
						ptr = end + 2;
						rstrip (start);
						name = start;
					}
					value = ptr + 1;

					end = find_char_or_comment (value, '\0');
					if (*end == ';') *end = '\0';
					rstrip (value);
					if (*value == '"' || *(value + 1) == '"')
					{
						if (*value == '"')
							*(value++) = '\0';
						else if (*(value + 1) == '"')
						{
							*(value + 1) = '\0';
							value += 2;
						}
						while ((*end != '"') && !isprint (*end) && end > value)
							--end;
						if (*end == '"') *end = '\0';
					}
				}
				else
				{
					ELEKTRA_LOG_DEBUG ("Found no double quote character");
					rstrip (start);
					name = start;
					end = strchr (start, delim);
					if (!end)
					{
						ELEKTRA_LOG_DEBUG ("Found no delimiter");
						value = NULL;
					}
					else
					{
						ELEKTRA_LOG_DEBUG ("Found delimiter");
						if (*end == delim) *end = '\0';
						rstrip (end - 1);
						value = lskip (end + 1);
						rstrip (value);
						if (*value == '"')
						{
							*(value++) = '\0';
							while ((*end != '"') && !isprint (*end) && end > value)
								--end;
							if (*end == '"') *end = '\0';
						}
					}
				}
				strncpy0 (prev_name, name, sizeof (prev_name));

				if (!config->keyHandler (user, section, name, value, 0) && !error) error = lineno;
			}
		}

#if INI_STOP_ON_FIRST_ERROR
		if (error) break;
#endif
	}

	free (line);
	return error;
}
예제 #20
0
파일: ini.c 프로젝트: kevlar1818/umeter
/* See documentation in header file. */
int ini_parse_file(struct fat_file_struct* file,
                   int (*handler)(void*, const char*, const char*,
                                  const char*),
                   void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
    char line[INI_MAX_LINE];
#else
    char* line;
#endif
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

#if !INI_USE_STACK
    line = (unsigned char*)malloc(INI_MAX_LINE);
    if (!line) {
        return -2;
    }
#endif
#if INI_DEBUG
	printf("reading ini file...\r\n");
#endif
    /* Scan through file line by line */
    //while ( (error = fat_read_file(file, line, sizeof(line))) > 0) {
		//line[error] = '\0';
	while(fat_read_line(file, line, sizeof(line)) > 0) {
#if INI_DEBUG
		printf("read: '%s'\r\n", line);
#endif
        lineno++;

        start = line;
#if INI_ALLOW_BOM
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }
#endif
        start = lskip(rstrip(start));

        if (*start == ';' || *start == '#') {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }
#if INI_ALLOW_MULTILINE
        else if (*prev_name && *start && start > line) {
            /* Non-black line with leading whitespace, treat as continuation
               of previous name's value (as per Python ConfigParser). */
            if (!handler(user, section, prev_name, start) && !error) {
                error = lineno;
#if INI_DEBUG
				printf("multiline error\r\n");
#endif
			}
        }
#endif
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
#if INI_DEBUG				
				printf("No ']' found on section line\r\n");
#endif
            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!handler(user, section, name, value) && !error) {
#if INI_DEBUG					
					printf("error handling name/value pair\r\n");
#endif
					error = lineno;
				}
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
#if INI_DEBUG				
				printf("No '=' or ':' found on name[=:]value line\r\n");
#endif
                error = lineno;
            }
        }
    }
#if !INI_USE_STACK
    free(line);
#endif

    return error;
}
예제 #21
0
파일: ini.cpp 프로젝트: dzzie/humidor.net
/* See documentation in header file. */
int ini_parse_stream(File file, ini_handler handler,  void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
    char line[INI_MAX_LINE];
#else
    char* line;
#endif
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

#if !INI_USE_STACK
    line = (char*)malloc(INI_MAX_LINE);
    if (!line) {
        return -2;
    }
#endif

    /* process file line by line */
	while( file.available() ){
		
freshLine:
		char b=0;
		int cnt=0;
		memset(line,0,INI_MAX_LINE);

		//load a line of text into internal buffer
		//this is my implementation of .readBytesUntil(\n) it has been customized so
		//that if first line character is a comment, then it will ignore the line
		//so comments can be longer than INI_MAX_LINE without error..
		while( file.available() ){
			
			if(cnt == INI_MAX_LINE){ //buffer full up, skip file pointer to end and process partial line? (visible error in output)
				readTillNewLine(file);
			    break;
			}

			size_t bytesRead = file.read(&b, 1);
			if (!bytesRead) return error;

			if(cnt==0 && (b=='#' || b==';') ){ //comment line, just skip it without impacting buffer length..
				readTillNewLine(file);
				goto freshLine;
			}else{
				line[cnt] = b;
				if (b == '\n') break;
				cnt++;
			}

		}

        lineno++;

        start = line;
        start = lskip(rstrip(start));

        if (*start == ';' || *start == '#') {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!handler(user, section, name, value) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }

	}

#if !INI_USE_STACK
    free(line);
#endif

    return error;
}
예제 #22
0
파일: ini.cpp 프로젝트: MarianoGnu/liblcf
/* See documentation in header file. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
					 void* user)
{
	/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
	char line[INI_MAX_LINE];
#else
	char* line;
#endif
	char section[MAX_SECTION] = "";
	char prev_name[MAX_NAME] = "";

	char* start;
	char* end;
	char* name;
	char* value;
	int lineno = 0;
	int error = 0;

#if !INI_USE_STACK
	line = (char*)malloc(INI_MAX_LINE);
	if (!line) {
		return -2;
	}
#endif

#if INI_HANDLER_LINENO
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
#else
#define HANDLER(u, s, n, v) handler(u, s, n, v)
#endif

	/* Scan through stream line by line */
	while (reader(line, INI_MAX_LINE, stream) != NULL) {
		lineno++;

		start = line;
#if INI_ALLOW_BOM
		if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
		    (unsigned char)start[1] == 0xBB &&
		    (unsigned char)start[2] == 0xBF) {
			start += 3;
		}
#endif
		start = lskip(rstrip(start));

		if (*start == ';' || *start == '#') {
			/* Per Python configparser, allow both ; and # comments at the
			   start of a line */
		}
#if INI_ALLOW_MULTILINE
		else if (*prev_name && *start && start > line) {
			/* Non-blank line with leading whitespace, treat as continuation
			   of previous name's value (as per Python configparser). */
			if (!HANDLER(user, section, prev_name, start) && !error)
				error = lineno;
		}
#endif
		else if (*start == '[') {
			/* A "[section]" line */
			end = find_chars_or_comment(start + 1, "]");
			if (*end == ']') {
				*end = '\0';
				strncpy0(section, start + 1, sizeof(section));
				*prev_name = '\0';
			}
			else if (!error) {
				/* No ']' found on section line */
				error = lineno;
			}
		}
		else if (*start) {
			/* Not a comment, must be a name[=:]value pair */
			end = find_chars_or_comment(start, "=:");
			if (*end == '=' || *end == ':') {
				*end = '\0';
				name = rstrip(start);
				value = end + 1;
#if INI_ALLOW_INLINE_COMMENTS
				end = find_chars_or_comment(value, NULL);
				if (*end)
					*end = '\0';
#endif
				value = lskip(value);
				rstrip(value);

				/* Valid name[=:]value pair found, call handler */
				strncpy0(prev_name, name, sizeof(prev_name));
				if (!HANDLER(user, section, name, value) && !error)
					error = lineno;
			}
			else if (!error) {
				/* No '=' or ':' found on name[=:]value line */
				error = lineno;
			}
		}

#if INI_STOP_ON_FIRST_ERROR
		if (error)
			break;
#endif
	}

#if !INI_USE_STACK
	free(line);
#endif

	return error;
}
예제 #23
0
/** Parse member property setter.
 *
 * @param parse		Parser object.
 * @param prop		Property containing this declaration.
 */
static void parse_prop_set(parse_t *parse, stree_prop_t *prop)
{
	cspan_t *cspan;
	stree_block_t *block;
	stree_proc_t *setter;
	bool_t body_expected;

	body_expected = (prop->symbol->outer_csi->cc != csi_interface);

	lskip(parse);
	cspan = lprev_span(parse);

	if (prop->setter != NULL) {
		cspan_print(cspan);
		printf(" Error: Duplicate setter.\n");
		parse_note_error(parse);
		return;
	}

	prop->setter_arg = stree_proc_arg_new();
	prop->setter_arg->name = parse_ident(parse);
	prop->setter_arg->type = prop->type;

	if (lcur_lc(parse) == lc_scolon) {
		/* Body not present */
		lskip(parse);

		block = NULL;

		if (body_expected) {
			cspan_print(prop->name->cspan);
			printf(" Error: Property '");
			symbol_print_fqn(prop->symbol);
			printf("' setter should have "
			    "a body.\n");
			parse_note_error(parse);
		}
	} else {
		/* Body present */
		lmatch(parse, lc_is);
		block = parse_block(parse);
		lmatch(parse, lc_end);

		if (!body_expected) {
			cspan_print(prop->name->cspan);
			printf(" Error: Property '");
			symbol_print_fqn(prop->symbol);
			printf("' setter declaration should "
			    "not have a body.\n");
			parse_note_error(parse);
		}
	}


	/* Create setter procedure */
	setter = stree_proc_new();
	setter->body = block;
	setter->outer_symbol = prop->symbol;

	/* Store setter in property. */
	prop->setter = setter;
}
예제 #24
0
void CharacterImageObject::update_text()
{
    lines.clear();
    blocks.clear();
    total_height[0] = total_height[1] = total_height[2] = 0;

    if (text.empty())
        return;

    char * data = &text[0];
    char * end = data + text.size();

    char * start_text = NULL;
    char * tag_start = NULL;

    AttributeStack alias_stack(ALIAS_ATTRIB);
    AttributeStack tracking_stack(TRACKING_ATTRIB);
    AttributeStack transparent_stack(TRANSPARENT_ATTRIB);

    lines.resize(1);

    CharacterImageAttributes attribs;

    int line = 0;
    int line_height = 0;
    int line_width = 0;
    int leading = 0;

    while (true) {
        // read text
        char * text_start = data;
        char * wrap_point = data;
        int test_width = line_width;
        bool wrap_newline = false;
        bool has_newline = false;

        // scan for newline, tag start or wrap point
        while (true) {
            if (data >= end)
                break;
            unsigned char c = (unsigned char)*data;
            if (c == '\n') {
                data++;
                has_newline = true;
                break;
            } else if (c == '\r') {
                data++;
                continue;
            } else if (c == '[')
                break;
            if (c == ' ')
                wrap_point = data+1;

            int alias_index = attribs.values[ALIAS_ATTRIB];
            CharacterImageAlias & alias = aliases[alias_index];
            CharacterImage & img = alias.charmap[c];
            test_width += img.width + attribs.values[TRACKING_ATTRIB];
            if (c != ' ' && (test_width+1) >= width) {
                data = wrap_point;
                has_newline = true;
                wrap_newline = true;
                break;
            }
            data++;
        }

        char * text_end = data;

        bool at_end = data >= end;

        if (text_start != text_end) {
            int alias_index = attribs.values[ALIAS_ATTRIB];
            CharacterImageAlias & alias = aliases[alias_index];
            std::string new_text(text_start, text_end - text_start);

            for (int i = 0; i < int(new_text.size()); i++) {
                unsigned char c = (unsigned char)new_text[i];
                CharacterImage & img = alias.charmap[c];
                line_height = std::max(img.height, line_height);
                if (c == '\n' || c == '\r')
                    continue;
                line_width += img.width + attribs.values[TRACKING_ATTRIB];
            }

            if (line_height == 0)
                line_height = alias.charmap[' '].height;

            unformatted += new_text;
            blocks.push_back(CharacterImageBlock(line, attribs, new_text));
        }

        if (has_newline || at_end) {
            CharacterImageLine & l = lines[line];
            l.width = line_width;
            line_height += (line_height * leading) / 100;
            total_height[get_vertical_index(l)] += line_height;
            l.height = line_height;
            line_width = line_height = 0;
            if (!wrap_newline)
                leading = 0;
            line++;
        }

        if (at_end)
            return;

        if (has_newline) {
            lines.resize(line+1);
            if (wrap_newline) {
                // inherit line config
                lines[line].x_align = lines[line-1].x_align;
                lines[line].y_align = lines[line-1].y_align;
            }
        }

        if (has_newline)
            continue;

        // read tag
        data++; // skip '[''
        data = lskip(data, end);
        bool is_end_tag = *data == '/';
        if (is_end_tag) {
            data++;
            data = lskip(data, end);
        }
        char * tag_start = data;
        data = find_tag_end(data, end);
        char * tag_end = data;

        // read tag value
        data = lskip(data, end);
        bool has_value = *data == '=';
        char * value_start;
        char * value_end;

        if (*data == '=') {
            data++;
            data = lskip(data, end);
            value_start = data;
            data = find_tag_end(data, end);
            value_end = data;
        }
        data = find_char(data, end, ']');
        data++;

        // convert value to integer
        int value;
        if (has_value) {
            bool is_alignment = true;
            switch (value_start[0]) {
                case 'l': // left
                    value = ALIGN_LEFT;
                    break;
                case 'r': // right
                    value = ALIGN_RIGHT;
                    break;
                case 'c': // centre
                    value = ALIGN_HCENTER | ALIGN_VCENTER;
                    break;
                case 'j': // justify
                    value = ALIGN_JUSTIFY;
                    break;
                case 't': // top
                    value = ALIGN_TOP;
                    break;
                case 'b': // bottom
                    value = ALIGN_BOTTOM;
                    break;
                default:
                    is_alignment = false;
                    break;
            }

            if (!is_alignment) {
                std::string value_str(value_start, value_end-value_start);
                value = string_to_int(value_str);
            }
        }

        // test attributes
        AttributeStack * stack_ref;

        if (test_str(tag_start, tag_end, "alias")) {
            stack_ref = &alias_stack;
        } else if (test_str(tag_start, tag_end, "tracking")) {
            stack_ref = &tracking_stack;
        } else if (test_str(tag_start, tag_end, "transparent")) {
            stack_ref = &transparent_stack;
        } else if (test_str(tag_start, tag_end, "veralign")) {
            lines[line].y_align = value;
            continue;
        } else if (test_str(tag_start, tag_end, "horalign")) {
            lines[line].x_align = value;
            continue;
        } else if (test_str(tag_start, tag_end, "leading")) {
            leading = value;
            continue;
        } else {
            std::string tag(tag_start, tag_end - tag_start);
            std::cout << "Unknown tag: " << tag << std::endl;
            continue;
        }

        if (is_end_tag) {
            stack_ref->pop(attribs);
            continue;
        }

        stack_ref->push(value, attribs);
    }
}
예제 #25
0
/** Parse constructor.
 *
 * @param parse		Parser object.
 * @param outer_csi	CSI containing this declaration or @c NULL if global.
 * @return		New syntax tree node.
 */
static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi)
{
	stree_ctor_t *ctor;
	stree_symbol_t *symbol;
	cspan_t *cspan;

	ctor = stree_ctor_new();
	symbol = stree_symbol_new(sc_ctor);

	symbol->u.ctor = ctor;
	symbol->outer_csi = outer_csi;
	ctor->symbol = symbol;

	lmatch(parse, lc_new);
	cspan = lprev_span(parse);

	/* Fake identifier. */
	ctor->name = stree_ident_new();
	ctor->name->sid = strtab_get_sid(CTOR_IDENT);
	ctor->name->cspan = lprev_span(parse);

#ifdef DEBUG_PARSE_TRACE
	printf("Parsing constructor of CSI '");
	symbol_print_fqn(csi_to_symbol(outer_csi));
	printf("'.\n");
#endif
	ctor->sig = parse_fun_sig(parse);
	if (ctor->sig->rtype != NULL) {
		cspan_print(cspan);
		printf(" Error: Constructor of CSI '");
		symbol_print_fqn(csi_to_symbol(outer_csi));
		printf("' has a return type.\n");
		parse_note_error(parse);
	}

	/* Parse attributes. */
	parse_symbol_attrs(parse, symbol);

	ctor->proc = stree_proc_new();
	ctor->proc->outer_symbol = symbol;

	if (lcur_lc(parse) == lc_scolon) {
		lskip(parse);

		/* This constructor has no body. */
		cspan_print(cspan);
		printf(" Error: Constructor of CSI '");
		symbol_print_fqn(csi_to_symbol(outer_csi));
		printf("' has no body.\n");
		parse_note_error(parse);

		ctor->proc->body = NULL;
	} else {
		lmatch(parse, lc_is);
		ctor->proc->body = parse_block(parse);
		lmatch(parse, lc_end);
	}

	switch (outer_csi->cc) {
	case csi_class:
	case csi_struct:
		break;
	case csi_interface:
		cspan_print(ctor->name->cspan);
		printf(" Error: Constructor declared inside interface.\n");
		parse_note_error(parse);
		/* XXX Free ctor */
		return NULL;
	}

	return ctor;
}
예제 #26
0
파일: ini.c 프로젝트: noikiy/bscope
/* See documentation in header file. */
int ini_parse_file(FILE* file,
                   int (*handler)(void*, const char*, const char*,
                                  const char*),
                   void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
    char line[MAX_LINE];
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

    /* Scan through file line by line */
    while (fgets(line, sizeof(line), file) != NULL) {
        lineno++;
        start = lskip(rstrip(line));

        if (*start == ';' || *start == '#') {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }
#if INI_ALLOW_MULTILINE
        else if (*prev_name && *start && start > line) {
            /* Non-black line with leading whitespace, treat as continuation
               of previous name's value (as per Python ConfigParser). */
            if (!handler(user, section, prev_name, start) && !error)
                error = lineno;
        }
#endif
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!handler(user, section, name, value) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }
    }

    return error;
}
예제 #27
0
파일: inih.c 프로젝트: beku/libelektra
/* See documentation in header file. */
int ini_parse_file(FILE* file,const struct IniConfig* config, void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
    char line[INI_MAX_LINE];
#else
    char* line;
#endif
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

#if !INI_USE_STACK
    line = (char*)malloc(INI_MAX_LINE);
    if (!line) {
        return -2;
    }
#endif

    /* Scan through file line by line */
    while (fgets(line, INI_MAX_LINE, file) != NULL) {
        lineno++;

        start = line;
#if INI_ALLOW_BOM
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }
#endif
        start = lskip(rstrip(start));

        if (*start == ';' || *start == '#') {
        	start += 1;
        	if (!config->commentHandler(user, start) && !error)
        		error = lineno;
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }

        else if (config->supportMultiline && *prev_name && *start && start > line) {
            /* Non-black line with leading whitespace, treat as continuation
               of previous name's value (as per Python ConfigParser). */
            if (!config->keyHandler(user, section, prev_name, start, 1) && !error)
                error = lineno;
        }
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
                if(!config->sectionHandler(user, section) && !error)
                	error = lineno;
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!config->keyHandler(user, section, name, value, 0) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }

#if INI_STOP_ON_FIRST_ERROR
        if (error)
            break;
#endif
    }

#if !INI_USE_STACK
    free(line);
#endif

    return error;
}
예제 #28
0
/** Parse class, struct or interface declaration.
 *
 * @param parse		Parser object.
 * @param dclass	What to parse: @c lc_class, @c lc_struct or @c lc_csi.
 * @param outer_csi	CSI containing this declaration or @c NULL if global.
 * @return		New syntax tree node.
 */
static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
    stree_csi_t *outer_csi)
{
	stree_csi_t *csi;
	csi_class_t cc;
	stree_csimbr_t *csimbr;
	stree_symbol_t *symbol;
	stree_ident_t *targ_name;
	stree_targ_t *targ;
	stree_texpr_t *pref;

	switch (dclass) {
	case lc_class: cc = csi_class; break;
	case lc_struct: cc = csi_struct; break;
	case lc_interface: cc = csi_interface; break;
	default: assert(b_false);
	}

	lskip(parse);

	csi = stree_csi_new(cc);
	csi->name = parse_ident(parse);

	list_init(&csi->targ);

	while (lcur_lc(parse) == lc_slash) {
		lskip(parse);
		targ_name = parse_ident(parse);

		targ = stree_targ_new();
		targ->name = targ_name;

		list_append(&csi->targ, targ);
	}

	symbol = stree_symbol_new(sc_csi);
	symbol->u.csi = csi;
	symbol->outer_csi = outer_csi;
	csi->symbol = symbol;

#ifdef DEBUG_PARSE_TRACE
	printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
	    strtab_get_str(csi->name->sid));
#endif
	if (lcur_lc(parse) == lc_colon) {
		/* Inheritance list */
		lskip(parse);

		while (b_true) {
			pref = parse_texpr(parse);
			if (parse_is_error(parse))
				break;

			list_append(&csi->inherit, pref);
			if (lcur_lc(parse) != lc_plus)
				break;

			lskip(parse);
		}
	}

	lmatch(parse, lc_is);
	list_init(&csi->members);

	/* Parse class, struct or interface members. */
	while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
		csimbr = parse_csimbr(parse, csi);
		if (csimbr == NULL)
			continue;

		list_append(&csi->members, csimbr);
	}

	lmatch(parse, lc_end);

	if (outer_csi != NULL) {
		switch (outer_csi->cc) {
		case csi_class:
		case csi_struct:
			break;
		case csi_interface:
			cspan_print(csi->name->cspan);
			printf(" Error: CSI declared inside interface.\n");
			parse_note_error(parse);
			/* XXX Free csi */
			return NULL;
		}
	}

	return csi;
}
예제 #29
0
int write_final_state(control *c, params *p, state *s)
{
    /*
    Write the final state to the input param file so we can easily restart
    the model. This function copies the input param file with the exception
    of anything in the git hash and the state which it replaces with the updated
    stuff.

    */

    char line[STRING_LENGTH];
    char saved_line[STRING_LENGTH];
    char section[STRING_LENGTH] = "";
    char prev_name[STRING_LENGTH] = "";
    char *start;
    char *end;
    char *name;
    char *value;

    int error = 0;
    int line_number = 0;
    int match = FALSE;

    while (fgets(line, sizeof(line), c->ifp) != NULL) {
        strcpy(saved_line, line);
        line_number++;
        start = lskip(rstrip(line));
        if (*start == ';' || *start == '#') {
            /* Per Python ConfigParser, allow '#' comments at start of line */
        }
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, ']');
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';

            }
            else if (!error) {
                /* No ']' found on section line */
                error = line_number;

            }
        }
        else if (*start && *start != ';') {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == ';')
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));

                if (!ohandler(section, name, value, c, p, s, &match) && !error)
                    error = line_number;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = line_number;
                break;
            }
        }
        if (match == FALSE)
            fprintf(c->ofp, "%s", saved_line);
        else
            match = FALSE; /* reset match flag */
    }
    return error;

}
예제 #30
0
/* See documentation in header file. */
int conf_parse_file(FILE* file,
                   int (*handler)(void*, const char*, const char*,
                                  const char*),
                   void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
#if CONF_USE_STACK
    char line[CONF_MAX_LINE];
#else
    char* line;
#endif
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

#if !CONF_USE_STACK
    line = (char*)malloc(CONF_MAX_LINE);
    if (!line) {
        return -2;
    }
#endif

    /* Scan through file line by line */
    while (fgets(line, CONF_MAX_LINE, file) != NULL) {
        lineno++;

        start = line;
#if CONF_ALLOW_BOM
        if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }
#endif
        start = lskip(rstrip(start));

        if (*start == COMMENT_CHAR) {
        }
#if CONF_ALLOW_MULTILINE
        else if (*prev_name && *start && start > line) {
            /* Non-black line with leading whitespace, treat as continuation
               of previous name's value (as per Python ConfigParser). */
            if (!handler(user, section, prev_name, start) && !error)
                error = lineno;
        }
#endif
        else if (*start == SECTION_START_CHAR) {
            /* A "[section]" line */
            end = find_char_or_comment(start + 1, SECTION_END_CHAR);
            if (*end == SECTION_END_CHAR) {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
            }
            else if (!error) {
                /* No SECTION_END_CHAR found on section line */
                error = lineno;
            }
        }
        else if (*start && *start != COMMENT_CHAR) {
            /* Not a comment, must be a name[=:]value pair */
            end = find_char_or_comment(start, '=');
            if (*end != '=') {
                end = find_char_or_comment(start, ':');
            }
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = lskip(end + 1);
                end = find_char_or_comment(value, '\0');
                if (*end == COMMENT_CHAR)
                    *end = '\0';
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!handler(user, section, name, value) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
                error = lineno;
            }
        }

#if CONF_STOP_ON_FIRST_ERROR
        if (error)
            break;
#endif
    }

#if !CONF_USE_STACK
    free(line);
#endif

    return error;
}