Example #1
0
module * module_parser::parse(const module_source & source, istream & text_stream)
{
    if (verbose<module_parser>::enabled())
        cout << "Parsing " << source.path << endl;

    ast::node_ptr ast;

    {
        stream::parsing::driver parser(text_stream, cout, source);

        int error = parser.parse();

        if (error)
            throw parser_error();

        ast = parser.ast();

        if (verbose<ast::output>::enabled())
        {
            cout << endl << "## AST for file " << source.path << " ##" << endl;
            ast::printer p;
            p.print(ast.get());
            cout << endl;
        }
    }

    auto & elems = ast->as_list()->elements;

    string mod_name;
    if (elems[0])
        mod_name = elems[0]->as_leaf<string>()->value;
    else
        mod_name = "m";

#if 0
    if (m_named_modules.find(mod_name) != m_named_modules.end())
    {
        ostringstream msg;
        msg << "Module " << mod_name << " is already imported.";
        throw io_error(msg.str());
    }
#endif

    if (verbose<module_parser>::enabled())
        cout << "Module name = " << mod_name << endl;

    auto mod = new module;
    mod->source = source;
    mod->name = mod_name;
    mod->ast = ast;
    m_named_modules.emplace(mod_name, mod);

    unordered_map<string, module*> imported_mods;

    auto imports_node = elems[1];
    if (imports_node)
    {
        for (auto & import_node : imports_node->as_list()->elements)
        {
            auto import_decl = parse_import(mod, import_node);
            imported_mods.insert(import_decl);
        }
    }

    mod->imports = imported_mods;

    m_ordered_modules.push_back(mod);

    if (verbose<module_parser>::enabled())
        cout << "Done parsing " << source.path << endl;

    return mod;
}
Example #2
0
static void
config_parse_line(calipso_config_t *config , char *line, int nline)
{
	char option[MAXOPTLEN]= {0}, value[MAXOPTLEN] = {0};
	char *s, *delim = NULL;

    if(strlen(line) > MAXOPTLEN ) 
		parser_error(nline, PERR_LINE);

	//printf("line '%s' %d\n", line, nline); 
	if(block_begin(line)) {

		if(!strlen(_block)) {
			s = strtok(line, BLOCK_BEGIN);
			if(s) { 
				strncpy(_block, s, MAXOPTLEN);
				trim(_block);
				//mark context begin 
				config_mark_ctx(config, CTX_BLOCK_BEGIN);
			} else 	parser_error(nline, PERR_BLOCK);
		}
		else parser_error(nline, PERR_BEGIN);
		//printf("begin '%s'\n", _block);
		return;
	}

	if(block_end(line)) {
	
		if(strlen(_block) > 0) {
			//mark context end 
			config_mark_ctx(config, CTX_BLOCK_END);
			memset(_block, 0 , MAXOPTLEN);
		}
		else parser_error(nline, PERR_END);
		//printf("end '%s'\n", _block);
		return;
	}

	if(strstr(line , DELIM_EQU)) 
		delim = DELIM_EQU;
	else if(strstr(line , DELIM_SPACE))
		delim = DELIM_SPACE;
	else if(strstr(line, DELIM_TAB))
		delim = DELIM_TAB;
	else 
		parser_error(nline, PERR_DELIM);

	s = strtok (line, delim); 

	if (s) {
		strncpy (option, s, MAXOPTLEN);
	}

	s = strtok (NULL, delim);

    if (s) {
		strncpy (value, s, MAXOPTLEN);
	}

    if ( strlen(option) && strlen(value)) {
		trim(option);
		trim(value);
		config_set_option(config, option, value, strlen(_block) ? _block : NULL );
	} else {
		parser_error(nline, PERR_PAIR);
	}
}
Example #3
0
static void check_identifier(parser & p, environment const & env, name const & ns, name const & id) {
    name full_id = ns + id;
    if (!env.find(full_id))
        throw parser_error(sstream() << "invalid 'using' command, unknown declaration '" << full_id << "'", p.pos());
}
Example #4
0
void Parser::parse() {
    std::string line;

    // Skip first line of input; SPICE syntax spec
    getline(file, line);
    this->line_no++;

    std::smatch matches;

    // Track highest node in file to determine matrix size
    int max_node = -1;

    while (!file.eof()) {
        // Get a line of input
        getline(file, line);

        // Flag for regex match
        bool match = false;

        try {
            // Check for line match
            match = this->match_line(line);

            // // Iterate through regex patterns; if match found, determine
            // // which component matched
            // for (auto r: this->regexes) {
            //     if (regex_search(line, matches, r.reg)) {
            //         switch (r.type) {
            //             case EMPTY_LINE: case COMMENT_LINE:
            //                 break;
            //             case R:
            //                 this->parse_line<Component>(matches, this->comps, r.type, &max_node);
            //                 break;
            //             case VDC: case IDC:
            //                 this->parse_line<Source>(matches, this->sources, r.type, &max_node);
            //                 break;
            //         }

            //         // Once found a match, no need to search more
            //         match = true;

            //         break;
            //     }
            //}

            if (!match) {
                throw parser_error("Syntax error", line, this->line_no);
            }
        }

        catch (parser_error& e) {
            this->error = e;
            this->state = parser_state::error;
            break;
        }

        this->line_no++;
    }

    // If really at EOF, then file has been parsed
    if (file.eof()) {
        this->state = parser_state::parsed;
    }
}
Example #5
0
double parser_read_builtin( parser_data *pd ){
	double v0, v1;
	char c, token[PARSER_MAX_TOKEN_SIZE];
	int pos=0;
	
	c = parser_peek( pd );
	if( isalpha(c) || c == '_' ){
		while( isalpha(c) || isdigit(c) || c == '-' ){
			token[pos++] = parser_eat( pd );
			c = parser_peek( pd );
		}
		token[pos] = '\0';
		
		// eat opening bracket
		if( parser_eat(pd) != '(' )
			parser_error( pd, "Expected '(' in builtin call!" );
		
		// start handling the specific builtin functions
		if( strcmp( token, "pow" ) == 0 ){
			v0 = parser_read_argument( pd );
			v1 = parser_read_argument( pd );
			v0 = pow( v0, v1 );
		} else if( strcmp( token, "sqrt" ) == 0 ){
			v0 = parser_read_argument( pd );
			if( v0 < 0.0 ) 
				parser_error( pd, "sqrt(x) undefined for x < 0!" );
			v0 = sqrt( v0 );
		} else if( strcmp( token, "log" ) == 0 ){
			v0 = parser_read_argument( pd );
			if( v0 <= 0 )
				parser_error( pd, "log(x) undefined for x <= 0!" );
			v0 = log( v0 );
		} else if( strcmp( token, "exp" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = exp( v0 );
		} else if( strcmp( token, "sin" ) == 0 ){
			v0 = parser_read_argument( pd );	
			v0 = sin( v0 );
		} else if( strcmp( token, "asin" ) == 0 ){
			v0 = parser_read_argument( pd );
			if( fabs(v0) > 1.0 )
				parser_error( pd, "asin(x) undefined for |x| > 1!" );
			v0 = asin( v0 );
		} else if( strcmp( token, "cos" ) == 0 ){
			v0 = parser_read_argument( pd );
			if( fabs(v0 ) > 1.0 )
				parser_error( pd, "acos(x) undefined for |x| > 1!" );
			v0 = cos( v0 );
		} else if( strcmp( token, "acos" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = acos( v0 );
		} else if( strcmp( token, "tan" ) == 0 ){
			v0 = parser_read_argument( pd );	
			v0 = tan( v0 );
		} else if( strcmp( token, "atan" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = atan( v0 );
		} else if( strcmp( token, "atan2" ) == 0 ){
			v0 = parser_read_argument( pd );
			v1 = parser_read_argument( pd );
			v0 = atan2( v0, v1 );
		} else if( strcmp( token, "abs" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = abs( v0 );
		} else if( strcmp( token, "fabs" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = fabs( v0 );
		} else if( strcmp( token, "floor" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = floor( v0 );
		} else if( strcmp( token, "ceil" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = floor( v0 );
		} else if( strcmp( token, "round" ) == 0 ){
			v0 = parser_read_argument( pd );
			v0 = round( v0 );
		} else {
			parser_error( pd, "Tried to call unknown builtin function!" );
		}
		
		// eat closing bracket of function call
		if( parser_eat( pd ) != ')' )
			parser_error( pd, "Expected ')' in builtin call!" );
		
	} else {
		// not a builtin function call, just read a literal double
		v0 = parser_read_double( pd );
	}
	
	// consume whitespace
	parser_eat_whitespace( pd );
	
	// return the value
	return v0;
}
Example #6
0
void decl_attributes::parse(parser & p) {
    buffer<char const *> attr_tokens;
    get_attribute_tokens(attr_tokens);
    while (true) {
        auto pos   = p.pos();
        if (auto it = parse_priority(p)) {
            m_prio = *it;
            bool has_prio_attr = false;
            for (auto const & entry : m_entries) {
                if (get_attribute_kind(entry.m_attr.c_str()) == attribute_kind::Prioritized) {
                    has_prio_attr = true;
                    break;
                }
            }
            if (!has_prio_attr) {
                throw parser_error("invalid '[priority]' attribute, declaration has not been marked with a prioritized attribute", pos);
            }
        } else if (p.curr_is_token(get_parsing_only_tk())) {
            if (!m_is_abbrev)
                throw parser_error("invalid '[parsing_only]' attribute, only abbreviations can be "
                                   "marked as '[parsing_only]'", pos);
            m_parsing_only = true;
            p.next();
        } else {
            bool found = false;
            for (char const * tk : attr_tokens) {
                if (p.curr_is_token(tk)) {
                    p.next();
                    char const * attr = get_attribute_from_token(tk);
                    for (auto const & entry : m_entries) {
                        if (are_incompatible(entry.m_attr.c_str(), attr)) {
                            throw parser_error(sstream() << "invalid attribute [" << attr
                                               << "], declaration was already marked with [" << entry.m_attr << "]", pos);
                        }
                    }
                    switch (get_attribute_kind(attr)) {
                    case attribute_kind::Default:
                    case attribute_kind::Prioritized:
                        m_entries = cons(entry(attr), m_entries);
                        break;
                    case attribute_kind::Parametric: {
                        unsigned v = p.parse_small_nat();
                        if (v == 0)
                            throw parser_error("invalid attribute parameter, value must be positive", pos);
                        p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected");
                        m_entries = cons(entry(attr, v-1), m_entries);
                        break;
                    }
                    case attribute_kind::OptParametric:
                        if (!p.curr_is_token(get_rbracket_tk())) {
                            unsigned v = p.parse_small_nat();
                            if (v == 0)
                                throw parser_error("invalid attribute parameter, value must be positive", pos);
                            p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected");
                            m_entries = cons(entry(attr, v-1), m_entries);
                        } else {
                            p.check_token_next(get_rbracket_tk(), "invalid attribute, ']' expected");
                            m_entries = cons(entry(attr), m_entries);
                        }
                        break;
                    case attribute_kind::MultiParametric: {
                        buffer<unsigned> vs;
                        while (true) {
                            unsigned v = p.parse_small_nat();
                            if (v == 0)
                                throw parser_error("invalid attribute parameter, value must be positive", pos);
                            vs.push_back(v-1);
                            if (p.curr_is_token(get_rbracket_tk()))
                                break;
                        }
                        p.next();
                        m_entries = cons(entry(attr, to_list(vs)), m_entries);
                        break;
                    }
                    }
                    found = true;
                    break;
                }
            }
            if (!found)
                break;
        }
    }
}
Example #7
0
ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt)
{
	ani_curico_t *ani = xmalloc(sizeof(ani_curico_t));
	riff_tag_t *rtp;
	int isswapped = 0;
	int doswap;
	const char *anistr = type == res_aniico ? "icon" : "cursor";

	assert(!memcmp(rd->data, riff, sizeof(riff)));
	assert(type == res_anicur || type == res_aniico);

	rtp = (riff_tag_t *)rd->data;

	if(BYTESWAP_DWORD(rtp->size) + 2*sizeof(DWORD) == rd->size)
		isswapped = 1;
	else if(rtp->size + 2*sizeof(DWORD) == rd->size)
		isswapped = 0;
	else
		parser_error("Animated %s has an invalid RIFF length", anistr);

	switch(byteorder)
	{
#ifdef WORDS_BIGENDIAN
	case WRC_BO_LITTLE:
#else
	case WRC_BO_BIG:
#endif
		doswap = !isswapped;
		break;
	default:
		doswap = isswapped;
	}

	/*
	 * When to swap what:
	 * isswapped | doswap |
	 * ----------+--------+---------------------------------
	 *     0     |    0   | read native; don't convert
	 *     1     |    0   | read swapped size; don't convert
	 *     0     |    1   | read native; convert
	 *     1     |    1   | read swapped size; convert
	 * Reading swapped size if necessary to calculate in native
	 * format. E.g. a little-endian source on a big-endian
	 * processor.
	 */
	if(doswap)
	{
		/* We only go through the RIFF file if we need to swap
		 * bytes in words/dwords. Else we couldn't care less
		 * what the file contains. This is consistent with
		 * MS' rc.exe, which doesn't complain at all, even though
		 * the file format might not be entirely correct.
		 */
		rtp++;	/* Skip the "RIFF" tag */

		while((char *)rtp < (char *)rd->data + rd->size)
		{
			if(!memcmp(rtp->tag, acon, sizeof(acon)))
			{
				rtp = SKIP_TAG(rtp,4);
			}
			else if(!memcmp(rtp->tag, list, sizeof(list)))
			{
				handle_ani_list(rtp, type, isswapped);
				rtp = NEXT_TAG(rtp);
			}
			else if(!memcmp(rtp->tag, anih, sizeof(anih)))
			{
				aniheader_t *ahp = (aniheader_t *)((char *)(rtp+1));
				ahp->structsize	= BYTESWAP_DWORD(ahp->structsize);
				ahp->frames	= BYTESWAP_DWORD(ahp->frames);
				ahp->steps	= BYTESWAP_DWORD(ahp->steps);
				ahp->cx		= BYTESWAP_DWORD(ahp->cx);
				ahp->cy		= BYTESWAP_DWORD(ahp->cy);
				ahp->bitcount	= BYTESWAP_DWORD(ahp->bitcount);
				ahp->planes	= BYTESWAP_DWORD(ahp->planes);
				ahp->rate	= BYTESWAP_DWORD(ahp->rate);
				ahp->flags	= BYTESWAP_DWORD(ahp->flags);
				rtp = NEXT_TAG(rtp);
			}
			else if(!memcmp(rtp->tag, rate, sizeof(rate)))
			{
				int cnt = rtp->size / sizeof(DWORD);
				DWORD *dwp = (DWORD *)(rtp+1);
				int i;
				for(i = 0; i < cnt; i++)
					dwp[i] = BYTESWAP_DWORD(dwp[i]);
				rtp = NEXT_TAG(rtp);
			}
			else if(!memcmp(rtp->tag, seq, sizeof(seq)))
			{
				int cnt = rtp->size / sizeof(DWORD);
				DWORD *dwp = (DWORD *)(rtp+1);
				int i;
				for(i = 0; i < cnt; i++)
					dwp[i] = BYTESWAP_DWORD(dwp[i]);
				rtp = NEXT_TAG(rtp);
			}
			else
				internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file",
				       isprint(rtp->tag[0]) ? rtp->tag[0] : '.',
				       isprint(rtp->tag[1]) ? rtp->tag[1] : '.',
				       isprint(rtp->tag[2]) ? rtp->tag[2] : '.',
				       isprint(rtp->tag[3]) ? rtp->tag[3] : '.');

			if((UINT_PTR)rtp & 1)
				rtp = SKIP_TAG(rtp,1);
		}

		/* We must end correctly here */
		if((char *)rtp != (char *)rd->data + rd->size)
			parser_error("Animated %s contains invalid field size(s)", anistr);
	}

	ani->data = rd;
	if(memopt)
	{
		ani->memopt = *memopt;
		free(memopt);
	}
	else
		ani->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE;
	return ani;
}
Example #8
0
void parser_imp::check_next(scanner::token t, char const * msg) {
    if (curr() == t)
        next();
    else
        throw parser_error(msg, pos());
}
Example #9
0
static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
{
	int cnt;
	int i;
	icon_t *ico;
	icon_t *list = NULL;
	icon_header_t *ih = (icon_header_t *)rd->data;
	int swap = 0;

	if(ih->type == 1)
		swap = 0;
	else if(BYTESWAP_WORD(ih->type) == 1)
		swap = 1;
	else
		parser_error("Icon resource data has invalid type id %d", ih->type);

	cnt = swap ? BYTESWAP_WORD(ih->count) : ih->count;
	for(i = 0; i < cnt; i++)
	{
		icon_dir_entry_t ide;
		BITMAPINFOHEADER info;
		memcpy(&ide, rd->data + sizeof(icon_header_t)
                                      + i*sizeof(icon_dir_entry_t), sizeof(ide));

		ico = new_icon();
		ico->id = alloc_icon_id(icog->lvc.language);
		ico->lvc = icog->lvc;
		if(swap)
		{
			ide.offset = BYTESWAP_DWORD(ide.offset);
			ide.ressize= BYTESWAP_DWORD(ide.ressize);
		}
		if(ide.offset > rd->size
		|| ide.offset + ide.ressize > rd->size)
			parser_error("Icon resource data corrupt");
		ico->width = ide.width;
		ico->height = ide.height;
		ico->nclr = ide.nclr;
		ico->planes = swap ? BYTESWAP_WORD(ide.planes) : ide.planes;
		ico->bits = swap ? BYTESWAP_WORD(ide.bits) : ide.bits;
		memcpy(&info, rd->data + ide.offset, sizeof(info));
         convert_bitmap((char *) &info, 0);
         memcpy(rd->data + ide.offset, &info, sizeof(info));

		if(!ico->planes)
		{
			/* Argh! They did not fill out the resdir structure */
			/* The bitmap is in destination byteorder. We want native for our structures */
			switch(byteorder)
			{
#ifdef WORDS_BIGENDIAN
			case WRC_BO_LITTLE:
#else
			case WRC_BO_BIG:
#endif
				ico->planes = BYTESWAP_WORD(info.biPlanes);
				break;
			default:
				ico->planes = info.biPlanes;
			}
		}
		if(!ico->bits)
		{
			/* Argh! They did not fill out the resdir structure */
			/* The bitmap is in destination byteorder. We want native for our structures */
			switch(byteorder)
			{
#ifdef WORDS_BIGENDIAN
			case WRC_BO_LITTLE:
#else
			case WRC_BO_BIG:
#endif
				ico->bits = BYTESWAP_WORD(info.biBitCount);
				break;
			default:
				ico->bits = info.biBitCount;
			}
		}
		ico->data = new_raw_data();
		copy_raw_data(ico->data, rd, ide.offset, ide.ressize);
		if(!list)
		{
			list = ico;
		}
		else
		{
			ico->next = list;
			list->prev = ico;
			list = ico;
		}
	}
	icog->iconlist = list;
	*nico = cnt;
}
Example #10
0
static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
{
	int cnt;
	int i;
	cursor_t *cur;
	cursor_t *list = NULL;
	cursor_header_t *ch = (cursor_header_t *)rd->data;
	int swap = 0;

	if(ch->type == 2)
		swap = 0;
	else if(BYTESWAP_WORD(ch->type) == 2)
		swap = 1;
	else
		parser_error("Cursor resource data has invalid type id %d", ch->type);
	cnt = swap ? BYTESWAP_WORD(ch->count) : ch->count;
	for(i = 0; i < cnt; i++)
	{
		cursor_dir_entry_t cde;
		BITMAPINFOHEADER info;
		memcpy(&cde, rd->data + sizeof(cursor_header_t)
                                      + i*sizeof(cursor_dir_entry_t), sizeof(cde));

		cur = new_cursor();
		cur->id = alloc_cursor_id(curg->lvc.language);
		cur->lvc = curg->lvc;
		if(swap)
		{
			cde.offset = BYTESWAP_DWORD(cde.offset);
			cde.ressize= BYTESWAP_DWORD(cde.ressize);
		}
		if(cde.offset > rd->size
		|| cde.offset + cde.ressize > rd->size)
			parser_error("Cursor resource data corrupt");
		cur->width = cde.width;
		cur->height = cde.height;
		cur->nclr = cde.nclr;
		memcpy(&info, rd->data + cde.offset, sizeof(info));
         convert_bitmap((char *)&info, 0);
         memcpy(rd->data + cde.offset, &info, sizeof(info));
		/* The bitmap is in destination byteorder. We want native for our structures */
		switch(byteorder)
		{
#ifdef WORDS_BIGENDIAN
		case WRC_BO_LITTLE:
#else
		case WRC_BO_BIG:
#endif
			cur->planes = BYTESWAP_WORD(info.biPlanes);
			cur->bits = BYTESWAP_WORD(info.biBitCount);
			break;
		default:
			cur->planes = info.biPlanes;
			cur->bits = info.biBitCount;
		}
		if(!win32 && (cur->planes != 1 || cur->bits != 1))
			parser_warning("Win16 cursor contains colors\n");
		cur->xhot = swap ? BYTESWAP_WORD(cde.xhot) : cde.xhot;
		cur->yhot = swap ? BYTESWAP_WORD(cde.yhot) : cde.yhot;
		cur->data = new_raw_data();
		copy_raw_data(cur->data, rd, cde.offset, cde.ressize);
		if(!list)
		{
			list = cur;
		}
		else
		{
			cur->next = list;
			list->prev = cur;
			list = cur;
		}
	}
	curg->cursorlist = list;
	*ncur = cnt;
}
Example #11
0
static int convert_bitmap(char *data, int size)
{
	BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)data;
	BITMAPV4HEADER *b4h = (BITMAPV4HEADER *)data;
	BITMAPOS2HEADER *boh = (BITMAPOS2HEADER *)data;
	int type = 0;
	int returnSize = 0;           /* size to be returned */
#ifdef WORDS_BIGENDIAN
	DWORD bisizel = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
	DWORD b4sizel = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
	DWORD bosizel = BYTESWAP_DWORD(sizeof(BITMAPOS2HEADER));
	DWORD bisizeb = sizeof(BITMAPINFOHEADER);
	DWORD b4sizeb = sizeof(BITMAPV4HEADER);
	DWORD bosizeb = sizeof(BITMAPOS2HEADER);
#else
	DWORD bisizel = sizeof(BITMAPINFOHEADER);
	DWORD b4sizel = sizeof(BITMAPV4HEADER);
	DWORD bosizel = sizeof(BITMAPOS2HEADER);
	DWORD bisizeb = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER));
	DWORD b4sizeb = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER));
	DWORD bosizeb = BYTESWAP_DWORD(sizeof(BITMAPOS2HEADER));
#endif


    /*
     * Originally the bih and b4h pointers were simply incremented here,
     * and memmoved at the end of the function.  This causes alignment
     * issues on solaris, so we do the memmove here rather than at the end.
     */
	if(data[0] == 'B' && data[1] == 'M')
	{
		/* Little endian signature */
         memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER));
         returnSize = sizeof(BITMAPFILEHEADER);
	}
	else if(data[0] == 'M' && data[1] == 'B')
	{
		type |= FL_SIGBE;	/* Big endian signature */
         memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER));
         returnSize = sizeof(BITMAPFILEHEADER);

	}

	if(bih->biSize == bisizel)
	{
		/* Little endian */
	}
	else if(bih->biSize == bisizeb)
	{
		type |= FL_SIZEBE;
	}
	else if(bih->biSize == b4sizel)
	{
		type |= FL_V4;
	}
	else if(bih->biSize == b4sizeb)
	{
		type |= FL_SIZEBE | FL_V4;
	}
	else if(!bih->biSize || bih->biSize == bosizel)
	{
		type |= FL_OS2;
	}
	else if(bih->biSize == bosizeb)
	{
		type |= FL_SIZEBE | FL_OS2;
	}
	else
		parser_error("Invalid bitmap format, bih->biSize = %d", bih->biSize);

	switch(type)
	{
	default:
		break;
	case FL_SIZEBE:
	case FL_SIZEBE | FL_V4:
	case FL_SIZEBE | FL_OS2:
		parser_warning("Bitmap v%c signature little-endian, but size big-endian\n", type & FL_V4 ? '4' : '3');
		break;
	case FL_SIGBE:
	case FL_SIGBE | FL_V4:
	case FL_SIGBE | FL_OS2:
		parser_warning("Bitmap v%c signature big-endian, but size little-endian\n", type & FL_V4 ? '4' : '3');
		break;
	}

	switch(byteorder)
	{
#ifdef WORDS_BIGENDIAN
	default:
#endif
	case WRC_BO_BIG:
		if(!(type & FL_SIZEBE))
		{
			if(type & FL_V4)
				convert_bitmap_swap_v4(b4h);
			else if(type & FL_OS2)
			{
				convert_bitmap_swap_os2(boh);
			}
			else
				convert_bitmap_swap_v3(bih);
		}
		break;
#ifndef WORDS_BIGENDIAN
	default:
#endif
	case WRC_BO_LITTLE:
		if(type & FL_SIZEBE)
		{
			if(type & FL_V4)
				convert_bitmap_swap_v4(b4h);
			else if(type & FL_OS2)
			{
				convert_bitmap_swap_os2(boh);
			}
			else
				convert_bitmap_swap_v3(bih);
		}
		break;
	}

	if(size && (void *)data != (void *)bih)
	{
		/* We have the fileheader still attached, remove it */
		memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER));
		return sizeof(BITMAPFILEHEADER);
	}
    return returnSize;
}
Example #12
0
static void
types_new_rec_handler(struct ir_unit *iu, int op,
                      unsigned int argc, const ir_arg_t *argv)
{
  ir_type_t it;
  const char *ctx = "types";

  assert(iu->iu_types_created == 0);

  switch(op) {
  case TYPE_CODE_NUMENTRY:
    if(argc < 1)
      parser_error(iu, "%s: Short NUMENTRY record", ctx);

    VECTOR_SET_CAPACITY(&iu->iu_types, argv[0].i64);
    return;

  case TYPE_CODE_VOID:
    it.it_code = IR_TYPE_VOID;
    break;
  case TYPE_CODE_FLOAT:
    it.it_code = IR_TYPE_FLOAT;
    break;
  case TYPE_CODE_DOUBLE:
    it.it_code = IR_TYPE_DOUBLE;
    break;
  case TYPE_CODE_INTEGER:
    if(argv[0].i64 == 1) {
      it.it_code = IR_TYPE_INT1;
    } else if(argv[0].i64 == 8) {
      it.it_code = IR_TYPE_INT8;
    } else if(argv[0].i64 == 16) {
      it.it_code = IR_TYPE_INT16;
    } else if(argv[0].i64 == 32) {
      it.it_code = IR_TYPE_INT32;
    } else if(argv[0].i64 == 64) {
      it.it_code = IR_TYPE_INT64;
    } else if(argv[0].i64 < 64) {
      it.it_code = IR_TYPE_INTx;
      it.it_bits = argv[0].i64;
    } else {
      parser_error(iu, "%s: Integer width %d bit not supported",
                   ctx, (int)argv[0].i64);
    }
    break;
  case TYPE_CODE_ARRAY:
    it.it_code = IR_TYPE_ARRAY;
    it.it_array.num_elements = argv[0].i64;
    it.it_array.element_type = argv[1].i64;
    break;

  case TYPE_CODE_STRUCT_NAME:
    free(iu->iu_current_struct_name);
    iu->iu_current_struct_name = read_str_from_argv(argc, argv);
    return;

  case TYPE_CODE_STRUCT_NAMED:

    it.it_struct.name = iu->iu_current_struct_name;
    iu->iu_current_struct_name = NULL;

    if(0)
  case TYPE_CODE_STRUCT_ANON:
      it.it_struct.name = NULL;

    it.it_code = IR_TYPE_STRUCT;

    it.it_struct.num_elements = argc - 1;
    it.it_struct.elements = malloc(it.it_struct.num_elements *
                                   sizeof(it.it_struct.elements[0]));
    {
      const int packed = !!argv[0].i64;
      int offset = 0;
      int ba = 1; // Biggest alignment

      for(int i = 0; i < it.it_struct.num_elements; i++) {
        int t = argv[i + 1].i64;
        it.it_struct.elements[i].type = t;
        int s = type_sizeof(iu, t);

        if(!packed) {
          int a = type_alignment(iu ,t);
          offset = VMIR_ALIGN(offset, a);
          ba = MAX(ba, a);
        }
        it.it_struct.elements[i].offset = offset;
        offset += s;
      }
      it.it_struct.size = packed ? offset : VMIR_ALIGN(offset, ba);
      it.it_struct.alignment = ba;
    }
    break;


  case TYPE_CODE_POINTER:
    it.it_code = IR_TYPE_POINTER;
    it.it_pointer.pointee = argv[0].i64;
    break;

  case TYPE_CODE_FUNCTION:
    if(argc < 2)
      parser_error(iu, "%s: Invalid # of args (%d) for function type",
                   ctx, argc);

    it.it_code = IR_TYPE_FUNCTION;
    it.it_function.varargs = argv[0].i64;
    it.it_function.return_type = argv[1].i64;
    it.it_function.num_parameters = argc - 2;
    it.it_function.parameters =
      malloc(it.it_function.num_parameters * sizeof(int));
    for(int i = 0; i < it.it_function.num_parameters; i++)
      it.it_function.parameters[i] = argv[2 + i].i64;
    break;

  case TYPE_CODE_METADATA:
    it.it_code = IR_TYPE_METADATA;
    break;

  case TYPE_CODE_LABEL:
    it.it_code = IR_TYPE_LABEL;
    break;

  case TYPE_CODE_OPAQUE:
    it.it_code = IR_TYPE_OPAQUE;
    break;

  case TYPE_CODE_VECTOR:
    printf("Vector of %s x %d\n",
           type_str_index(iu, argv[1].i64),
           (int)argv[0].i64);

           //    break;

  default:
    printargs(argv, argc);
    parser_error(iu, "%s: Unknown op %d", ctx, op);
  }

  VECTOR_PUSH_BACK(&iu->iu_types, it);
}
Example #13
0
char parser_eat( parser_data *pd ){
	if( pd->pos < pd->len )
		return pd->str[pd->pos++];
	parser_error( pd, "Tried to read past end of string!" );
	return '\0';
}
Example #14
0
void config_parse(char *filename) {
	int fd
	  , nameStart
	  , nameStop
	  , valueStart
	  , valueStop
	  , lineR	// Counting \r's
	  , lineN	// Counting \n's
	  , lineT	// Highest of \r's and \n's
	  , lineC	// Character in line
	  , pos;	// Byte position in file
	char *name
	   , *value
	   , *config;
	state state;
	letter l;
	size_t filesize;

	filesize = getFilesize(filename);

	/* Open file */
	fd = open(filename, O_RDONLY, 0);
	if (fd == -1) {
		/* Do not throw an error on EACCES, to allow blindly reading
		 * the 'global' followed by the 'root only' configurations to
		 * simplify overall code.
		 */
		if (errno != EACCES) {
			parser_error("readable file", "unreadable file", -1, -1);
		}

		return;
	}

	/* Execute mmap */
	config = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0);
	if (config == MAP_FAILED) {
		parser_error("mmapable file", "error mmapping file", -1, -1);
		goto abort_mmap;
	}

	name = value = NULL;
	nameStart = nameStop = valueStart = valueStop = pos = 0;
	lineR = lineN = lineC = lineT = 1;
	state = STATE_START_OF_LINE;
	do {
		switch(config[pos]) {
			case '\r':
				lineR++;
				lineT = max(lineR, lineN);
				lineC = 1;
				l = LETTER_END_OF_LINE;
				break;
			case '\n':
				lineN++;
				lineT = max(lineR, lineN);
				lineC = 1;
				l = LETTER_END_OF_LINE;
				break;
			case ' ':
			case '\t':
				l = LETTER_WHITESPACE;
				break;
			case '=':
				l = LETTER_EQUAL;
				break;
			case '#':
				l = LETTER_COMMENT;
				break;
			default:
				if ((config[pos] < ' ')
				 || (config[pos] > '~')) {
					l = LETTER_INVALID;
					parser_error("valid character", "invalid character", lineT, lineC);
					state = STATE_COMMENT_OR_ERROR;
					break;
				}
				l = LETTER_LETTER;
				break;
		}

		switch(state) {
		case STATE_COMMENT_OR_ERROR: switch(l) {
			case LETTER_END_OF_LINE:
				state = STATE_START_OF_LINE;
				break;
			default:
				break;
			} break;
		case STATE_START_OF_LINE: switch(l) {
			case LETTER_END_OF_LINE:
			case LETTER_WHITESPACE:
				break;
			case LETTER_EQUAL:
				parser_error("option name", "=", lineT, lineC);
				state = STATE_COMMENT_OR_ERROR;
				break;
			case LETTER_COMMENT:
				state = STATE_COMMENT_OR_ERROR;
				break;
			case LETTER_LETTER:
			default:
				nameStart = pos;
				nameStop = pos;
				state = STATE_NAME;
				break;
			} break;
		case STATE_NAME: switch(l) {
			case LETTER_END_OF_LINE:
				parser_error("=", "end of line", lineT, lineC);
				state = STATE_COMMENT_OR_ERROR;
				break;
			case LETTER_WHITESPACE:
				state = STATE_PRE_EQUAL;
				break;
			case LETTER_EQUAL:
				state = STATE_POST_EQUAL;
				break;
			case LETTER_COMMENT:
				parser_error("=", "comment", lineT, lineC);
				state = STATE_COMMENT_OR_ERROR;
				break;
			case LETTER_LETTER:
			default:
				nameStop = pos;
				break;
			} break;
		case STATE_PRE_EQUAL: switch(l) {
			case LETTER_WHITESPACE:
				break;
			case LETTER_EQUAL:
				state = STATE_POST_EQUAL;
				break;
			default:
				parser_error("= or more whitespace", "gibberish", lineT, lineC);
				state = STATE_COMMENT_OR_ERROR;
				break;
			} break;
		case STATE_POST_EQUAL: switch(l) {
			case LETTER_END_OF_LINE:
				parser_error("option value or more whitespace", "end of line", lineT, lineC);
				state = STATE_COMMENT_OR_ERROR;
				break;
			case LETTER_WHITESPACE:
				break;
			case LETTER_EQUAL:
			case LETTER_COMMENT:
			case LETTER_LETTER:
			default:
				valueStart = pos;
				valueStop = pos;
				state = STATE_VALUE;
				break;
			} break;
		case STATE_VALUE: switch(l) {
			case LETTER_END_OF_LINE:
				name = strndup((char *)config + nameStart, nameStop - nameStart + 1);
				value = strndup((char *)config + valueStart, valueStop - valueStart + 1);
				option_set(name, value);
				free(name);
				free(value);
				state = STATE_START_OF_LINE;
				break;
			case LETTER_WHITESPACE:
			case LETTER_EQUAL:
			case LETTER_COMMENT:
			case LETTER_LETTER:
			default:
				valueStop = pos;
				break;
			} break;
		}
		pos++;
		lineC++;
	} while (pos < filesize);

	/* End-of-File handling. */
	switch(state) {
	case STATE_NAME:
	case STATE_PRE_EQUAL:
		parser_error("=", "end of file", lineT, lineC);
		break;
	case STATE_POST_EQUAL:
		parser_error("option value", "end of file", lineT, lineC);
		break;
	case STATE_START_OF_LINE:
	case STATE_COMMENT_OR_ERROR:
	case STATE_VALUE:
	default:
		/* Valid end of file location, no issue. */
		break;
	}

	/* Cleanup */

	munmap(config, filesize);

abort_mmap:
	close(fd);
}
Example #15
0
messagetable_t *new_messagetable(raw_data_t *rd, int *memopt)
{
	messagetable_t *msg = xmalloc(sizeof(messagetable_t));
 	msgtab_block_t *mbp;
	DWORD nblk;
	DWORD i;
	WORD lo;
	WORD hi;

	msg->data = rd;
	if(memopt)
	{
		msg->memopt = *memopt;
		free(memopt);
	}
	else
		msg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;

	if(rd->size < sizeof(DWORD))
		parser_error("Invalid messagetable, size too small");

	nblk = *(DWORD *)rd->data;
	lo = WRC_LOWORD(nblk);
	hi = WRC_HIWORD(nblk);

	/* FIXME:
	 * This test will fail for all n*2^16 blocks in the messagetable.
	 * However, no sane person would want to have so many blocks
	 * and have a table of megabytes attached.
	 * So, I will assume that we have less than 2^16 blocks in the table
	 * and all will just work out fine. Otherwise, we would need to test
	 * the ID, offset and length (and flag) fields to be very sure.
	 */
	if(hi && lo)
		internal_error(__FILE__, __LINE__, "Messagetable contains more than 65535 blocks; cannot determine endian\n");
	if(!hi && !lo)
		parser_error("Invalid messagetable block count 0");

	if(!hi && lo)  /* Messagetable byteorder == native byteorder */
	{
#ifdef WORDS_BIGENDIAN
		if(byteorder != WRC_BO_LITTLE) goto out;
#else
		if(byteorder != WRC_BO_BIG) goto out;
#endif
		/* Resource byteorder != native byteorder */

		mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]);
		if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp)))
			parser_error("Messagetable's blocks are outside of defined data");
		for(i = 0; i < nblk; i++)
		{
			msgtab_entry_t *mep, *next_mep;
			DWORD id;

			mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset);

			for(id = mbp[i].idlo; id <= mbp[i].idhi; id++)
			{
				if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length))
					parser_error("Messagetable's data for block %d, ID 0x%08x is outside of defined data", i, id);
				if(mep->flags == 1)	/* Docu says 'flags == 0x0001' for unicode */
				{
					WORD *wp = (WORD *)&mep[1];
					int l = mep->length/2 - 2; /* Length included header */
					int n;

					if(mep->length & 1)
						parser_error("Message 0x%08x is unicode (block %d), but has odd length (%d)", id, i, mep->length);
					for(n = 0; n < l; n++)
						wp[n] = BYTESWAP_WORD(wp[n]);

				}
				next_mep = (msgtab_entry_t *)(((char *)mep) + mep->length);
				mep->length = BYTESWAP_WORD(mep->length);
				mep->flags  = BYTESWAP_WORD(mep->flags);
				mep = next_mep;
			}

			mbp[i].idlo   = BYTESWAP_DWORD(mbp[i].idlo);
			mbp[i].idhi   = BYTESWAP_DWORD(mbp[i].idhi);
			mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset);
		}
	}
	if(hi && !lo)  /* Messagetable byteorder != native byteorder */
	{
#ifdef WORDS_BIGENDIAN
		if(byteorder == WRC_BO_LITTLE) goto out;
#else
		if(byteorder == WRC_BO_BIG) goto out;
#endif
		/* Resource byteorder == native byteorder */

		mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]);
		nblk = BYTESWAP_DWORD(nblk);
		if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp)))
			parser_error("Messagetable's blocks are outside of defined data");
		for(i = 0; i < nblk; i++)
		{
			msgtab_entry_t *mep;
			DWORD id;

			mbp[i].idlo   = BYTESWAP_DWORD(mbp[i].idlo);
			mbp[i].idhi   = BYTESWAP_DWORD(mbp[i].idhi);
			mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset);
			mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset);

			for(id = mbp[i].idlo; id <= mbp[i].idhi; id++)
			{
				mep->length = BYTESWAP_WORD(mep->length);
				mep->flags  = BYTESWAP_WORD(mep->flags);

				if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length))
					parser_error("Messagetable's data for block %d, ID 0x%08x is outside of defined data", i, id);
				if(mep->flags == 1)	/* Docu says 'flags == 0x0001' for unicode */
				{
					WORD *wp = (WORD *)&mep[1];
					int l = mep->length/2 - 2; /* Length included header */
					int n;

					if(mep->length & 1)
						parser_error("Message 0x%08x is unicode (block %d), but has odd length (%d)", id, i, mep->length);
					for(n = 0; n < l; n++)
						wp[n] = BYTESWAP_WORD(wp[n]);

				}
				mep = (msgtab_entry_t *)(((char *)mep) + mep->length);
			}
		}
	}

 out:
	return msg;
}
Example #16
0
pointer parse_number(parser* parse)
{
    size_t len = 0;
    bool isFloat = false;
    bool isHex = false;
    bool isBinary = false;

    const char* Start = parse->curr;

    while(!is_delimiter(*parse->curr))
    {
        if(*parse->curr == '.')
            isFloat = true;

        if(is_number_char(*parse->curr) ||
           (isHex && is_extended_hex_char(*parse->curr)))
            len++;
        else if(len == 1 &&
                *parse->curr == 'x' &&
                *Start == '0')
        {
            len++;
            isHex = true;
        }
        else if(len == 0 && *parse->curr == 'b')
            isBinary = true;
        else
            return parser_error(parse, "Unexpected char '%c' in number literal.", *parse->curr);
        parse->curr++;
    }

    {
        int TotalIs = isHex + isBinary + isFloat;
        if(TotalIs > true)
        {
            char* buffer = new char[len+1];

            strncpy(buffer, Start, len);
            buffer[len] = '\0';
            parser_error(parse, "Unexpected number literal: %s.", buffer);
            delete buffer;
            return NIL;

        }
    }

    if(isFloat)
    {
        char* buffer = new char[len+1];

        strncpy(buffer, Start, len);
        buffer[len] = '\0';

        float ret = atof(buffer);
        delete buffer;

        return create_real(ret);
    }
    else
    {
        // Might be smart to use a buffer here, in case strtol doesn't see all delimiters as we do.
        int ret;
        if(isHex)
            ret  = strtol(Start + 2, NULL,  16);
        else if(isBinary)
            ret = strtol(Start + 1, NULL, 2);
        else
            ret = strtol(Start, NULL, 10);

        return create_int(ret);
    }


}
Example #17
0
/* Invoke the argument FTL function with <addr> <buf> arguments for each of
   the ELF file's program segments */
static const value_t *
elf_load_with_fn(const value_t *this_fn, parser_state_t *state,
                 const char *filename, int binfd,
                 Elf *e, GElf_Ehdr *ehdr, void *arg)
{
   elf_loadfn_args_t *fnarg = (elf_loadfn_args_t *)arg;
   const value_t *hdrcheckfn = fnarg->hdrcheckfn;
   const value_t *memwrfn = fnarg->memwrfn;
   const value_t *resval = value_false;
   size_t n;

   if (elf_getphdrnum(e, &n) != 0)
      parser_report(state, "ELF file has unknown number of segments - %s\n",
                    elf_errmsg(-1));
   else {
      size_t i;
      bool ok = FALSE;

      if (hdrcheckfn != NULL) {
         const value_t *ehdrval = elf_get_ehdr(this_fn, state, filename, binfd,
                                               e, ehdr, /*arg*/NULL);
         if (ehdrval != NULL) {
            const value_t *code = value_closure_bind(hdrcheckfn, ehdrval);

            if (code == NULL) {
               parser_error(state, "couldn't apply "
                            "header argument to check function\n");
            } else {
               const value_t *fnres = invoke(code, state);
               /* we expect this to return a TRUE/FALSE value */
               ok = (fnres == value_true);
               /*if (!ok) printf("%s: check fn returns non-TRUE\n", codeid());*/
            }
         }
      } else
         ok = TRUE;

      resval = ok? value_true: value_false;

      if (ok && memwrfn != NULL) {
         for (i = 0; ok && i < n; i++) {
            GElf_Phdr phdr;

            if (gelf_getphdr(e, i, &phdr) != &phdr)
               parser_report(state, "ELF segment %d unretrievable - %s\n",
                             i, elf_errmsg(-1));
            else {
               long offset = (long)phdr.p_offset;
               if (phdr.p_offset != (Elf64_Off)offset)
                  parser_report(state, "ELF segment %d - "
                                 "offset does not fit in 32-bits\n", i);
               else
               if (-1 == fe_lseek(binfd, offset))
                  parser_report(state, "ELF segment %d - "
                                 "offset 0X%lX is outside file\n",
                                 i, offset);
               else
               if (phdr.p_memsz < phdr.p_filesz)
                  parser_report(state,
                                "ELF segment %d - smaller size in memory (%d)"
                                "than on file (%d) - corrupt header?\n",
                                i, phdr.p_memsz, phdr.p_filesz);
               else {
                  number_t addr = phdr.p_vaddr; /* where to load segment */
                  char *buf = NULL;
                  size_t buflen = (size_t)phdr.p_memsz;
                  value_t *addrval = value_int_new(addr);
                  value_t *dataval = value_string_alloc_new(buflen, &buf);

                  if (phdr.p_memsz != (Elf64_Xword)buflen)
                     parser_report(state, "ELF segment %d - "
                                    "size does not fit in 32-bits\n", i);
                  else
                  if (dataval == NULL)
                     parser_report(state,
                                   "ELF segment %d - no memory for "
                                   "next %d bytes\n",
                                   i, buflen);
                  else {
                     ssize_t readbytes = fe_read(binfd, buf, buflen);

                     if (readbytes < buflen)
                        parser_report(state,
                                      "ELF segment %d - "
                                      "only %d bytes of %d read\n",
                                      i, readbytes);
                     else {
                        const value_t *code;
                        ok = TRUE;

                        /* zero any uninitialized area */
                        if (phdr.p_memsz > phdr.p_filesz) {
                           size_t extra_bytes = (size_t)
                                                (phdr.p_memsz - phdr.p_filesz);
                           if ((Elf64_Xword)extra_bytes !=
                               phdr.p_memsz-phdr.p_filesz) {
                              ok = FALSE;
                              parser_report(state, "ELF segment %d - "
                                            "BSS area larger than 32-bits\n",
                                            i);
                           } else
                              memset(&buf[phdr.p_filesz], '\0', extra_bytes);
                        }

                        code = value_closure_bind_2(state, memwrfn,
                                                    "address", addrval,
                                                    "data", dataval);

                        if (NULL != code) {
                           const value_t *fnres = invoke(code, state);
                           /* we expect this to return a TRUE/FALSE value */
                           if (fnres != value_true) {
                              /*printf("%s: seg fn returns non-TRUE\n",
                                       codeid());*/
                              ok = FALSE;
                           }
                           /* we rely on garbage collection to collect the data
                            * buffer */
                        } else
                           value_delete(&dataval);
                     }
                  }
               }
            }
         }

         if (!ok)
            resval = value_false;
      }
   }
   return resval;
}
Example #18
0
[[ noreturn ]] void parser_imp::not_implemented_yet() {
    // TODO(Leo)
    throw parser_error("not implemented yet", pos());
}
Example #19
0
/*
 * Parse next entry from ini-file.
 */
const parser_entry * parser_get_next(struct inifile *inf)
{
	token_data data;
	memset(&data, 0, sizeof(token_data));
	
	/*
	 * Label where we continue if end of string or
	 * multiline token is found in input stream.
	 */
	next:
	
	if(data.prev != MLINE) {								
		/*
		 * Reset scan data.
		 */
		if(inf->entry->key) {
			free(inf->entry->key);
			inf->entry->key = NULL;
		}
		if(inf->entry->val) {
			free(inf->entry->val);
			inf->entry->val = NULL;
		}
	}
	
	/*
	 * Get next line from input stream.
	 */
	while((inf->len = getline(&(inf->str), &(inf->size), inf->fs)) != -1) {
		
		/*
		 * Count up one more line.
		 */
		inf->entry->line++;
			
		/*
		 * Skip empty and commented lines.
		 */
		if(inf->str[0] == '\n' || strchr(inf->comment, inf->str[0])) {
			continue;
		}
		if(inf->str[inf->len - 1] == '\n') {
			inf->str[inf->len - 1] = '\0';
		}
		
		/*
		 * Fill line scanning data object.
		 */
		data.pos  = 0;
		data.line = inf->entry->line;
		if(data.prev != MLINE) {
			data.curr = NONE;
			data.prev = NONE;
			data.seen = NONE;
			data.cls  = GLOBAL;
			memset(&data.quote, 0, sizeof(token_quote));
		}
		
		switch(parser_tokenize(inf, &data, inf->entry)) {
		case PARSE_ERROR:
			return NULL;
		case PARSE_NEXT:
			goto next;
		case PARSE_DONE:
			if(inf->options & INIFILE_CHECK_SYNTAX) {
				/* 
				 * Handle syntax error that would require more context (i.e. look-ahead) 
				 * than whats available to the lexer when its doing its syntax check.
				 */
				if(data.seen == ASSIGN && (inf->entry->val == NULL || strlen(inf->entry->val) == 0)) {
					return parser_error(inf, &data, "assign without value");
				}
			}
			return inf->entry;
		}
			
	}
		
	/*
	 * Nothing found.
	 */
	return NULL;
}