Example #1
0
void dump_stack(Context& ctx) {
	std::list<const TreeNode *>::reverse_iterator it(ctx.stack.rbegin()), itEnd(ctx.stack.rend());

	printf("Current execution stack:\n");
	int indent = 3;
	for(++it; it!=itEnd; ++it) {
		const TreeNode& tag = **it;
		printf("%*c%s(%d): processing <%s>\n", indent, ' ', tag.mpLocation->mName.c_str(), tag.mLineno, tag.mName.c_str());
		indent += 3;
	}

	indent = 3;
	std::list<TreeNode *>::reverse_iterator it2(ctx.construction_stack.rbegin()), it2End(ctx.construction_stack.rend());
	for(; it2!=it2End; ++it2) {
		const TreeNode& tag = **it2;
		printf("%*c%s(%d): while creating tag <%s>\n", indent, ' ', tag.mpLocation->mName.c_str(), tag.mLineno, tag.mName.c_str());
		indent += 3;
	}

	indent = 3;
	for(it=ctx.invocation_stack.rbegin(), itEnd=ctx.invocation_stack.rend(); it!=itEnd; ++it) {
		const TreeNode& tag = **it;
		printf("%*c%s(%d): while invoked from tag <%s>\n", indent, ' ', tag.mpLocation->mName.c_str(), tag.mLineno, tag.mName.c_str());
		indent += 3;
	}
}
Example #2
0
	void HACD::CreateGraph()
    {
		// vertex to triangle adjacency information
		std::vector< std::set<long> >  vertexToTriangles;
		vertexToTriangles.resize(m_nPoints);
		for(size_t t = 0; t < m_nTriangles; ++t)
		{
			vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t));
			vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t));
			vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t));
		}

		m_graph.Clear();
		m_graph.Allocate(m_nTriangles, 5 * m_nTriangles);
		unsigned long long tr1[3];
		unsigned long long tr2[3];
        long i1, j1, k1, i2, j2, k2;
        long t1, t2;
        for (size_t v = 0; v < m_nPoints; v++)
		{
			std::set<long>::const_iterator it1(vertexToTriangles[v].begin()), itEnd(vertexToTriangles[v].end());
			for(; it1 != itEnd; ++it1)
			{
                t1 = *it1;
                i1 = m_triangles[t1].X();
                j1 = m_triangles[t1].Y();
                k1 = m_triangles[t1].Z();
				tr1[0] = GetEdgeIndex(i1, j1);
				tr1[1] = GetEdgeIndex(j1, k1);
				tr1[2] = GetEdgeIndex(k1, i1);
				std::set<long>::const_iterator it2(it1);
				for(++it2; it2 != itEnd; ++it2)
				{
                    t2 = *it2;
                    i2 = m_triangles[t2].X();
                    j2 = m_triangles[t2].Y();
                    k2 = m_triangles[t2].Z();
					tr2[0] = GetEdgeIndex(i2, j2);
					tr2[1] = GetEdgeIndex(j2, k2);
					tr2[2] = GetEdgeIndex(k2, i2);
					int shared = 0;
					for(int i = 0; i < 3; ++i)
					{
						for(int j = 0; j < 3; ++j)
						{
							if (tr1[i] == tr2[j])
							{
								shared++;
							}
						}
					}
					if (shared == 1) // two triangles are connected if they share exactly one edge
					{
						m_graph.AddEdge(t1, t2);
					}
				}
			}
        }
        if (m_ccConnectDist >= 0.0)
        {
            m_graph.ExtractCCs();
            if (m_callBack)
            {
                char msg[1024];
                sprintf(msg, "nCC %lu\n", static_cast<long unsigned int>(m_graph.m_nCCs));
                (*m_callBack)(msg, 0.0, 0.0,  m_graph.GetNVertices());

            }

            if (m_graph.m_nCCs > 1)
            {
                std::vector< std::set<long> > cc2V;
                cc2V.resize(m_graph.m_nCCs);
                long cc;
                for(size_t t = 0; t < m_nTriangles; ++t)
                {
                    cc = m_graph.m_vertices[t].m_cc;
                    cc2V[cc].insert(m_triangles[t].X());
                    cc2V[cc].insert(m_triangles[t].Y());
                    cc2V[cc].insert(m_triangles[t].Z());
                }

                for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1)
                {
                    for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2)
                    {
                        std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end());
                        for(; itV1 != itVEnd1; ++itV1)
                        {
							double distC1C2 = std::numeric_limits<double>::max();
                            double dist;
                            t1 = -1;
                            t2 = -1;
                            std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end());
                            for(; itV2 != itVEnd2; ++itV2)
                            {
                                dist = (m_points[*itV1] - m_points[*itV2]).GetNorm();
                                if (dist < distC1C2)
                                {
                                    distC1C2 = dist;
                                    t1 = *vertexToTriangles[*itV1].begin();

									std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()),
																   it2End(vertexToTriangles[*itV2].end());
									t2 = -1;
									for(; it2 != it2End; ++it2)
									{
										if (*it2 != t1)
										{
											t2 = *it2;
											break;
										}
									}
                                }
                            }
                            if (distC1C2 <= m_ccConnectDist && t1 >= 0 && t2 >= 0)
                            {
                                m_graph.AddEdge(t1, t2);
                            }
                        }
                    }
                }
            }
        }
    }
Example #3
0
void output_special_tag(Context& ctx, std::string *out, const TreeNode& tag) {
	if (tag.mName == "lina:fireball") {
		const TreeAttribute *a1 = tag.Attrib("src");
		const TreeAttribute *a2 = tag.Attrib("dst");

		if (!a1 || !a2)
			error(ctx, "<lina:fireball> requires SRC and DST attributes");

		g_fileCopies[a2->mValue] = a1->mValue;
	} else if (tag.mName == "lina:write") {
		const TreeAttribute *a = tag.Attrib("file");

		if (!a)
			error(ctx, "<lina:write> must specify FILE");

		std::string s;

		std::list<TreeNode *> tempStack;
		ctx.construction_stack.swap(tempStack);
		int cdataCount = ctx.cdata_count;
		int preCount = ctx.pre_count;
		ctx.cdata_count = 0;
		ctx.pre_count = 0;
		bool bHoldingSpace = ctx.holding_space;
		bool bEatNextSpace = ctx.eat_next_space;
		ctx.holding_space = false;
		ctx.eat_next_space = true;
		output_tag_contents(ctx, &s, tag);
		ctx.holding_space = bHoldingSpace;
		ctx.eat_next_space = bEatNextSpace;
		ctx.pre_count = cdataCount;
		ctx.cdata_count = preCount;
		ctx.construction_stack.swap(tempStack);

		std::string filename(create_output_filename(a->mValue));

		FILE *f = fopen(filename.c_str(), "wb");
		if (!f)
			error(ctx, "couldn't create \"%s\"", a->mValue.c_str());
		fwrite(s.data(), s.length(), 1, f);
		fclose(f);

		printf("created file: %s\n", a->mValue.c_str());
	} else if (tag.mName == "lina:body") {

//		printf("outputting:\n");
//		dump_parse_tree(*ctx.invocation_stack.back(), 4);

		output_tag_contents(ctx, out, *ctx.invocation_stack.back());
	} else if (tag.mName == "lina:tag") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:tag> must have NAME attribute");

		ctx.construction_stack.push_back(ctx.mpDocument->AllocNode());
		TreeNode *new_tag = ctx.construction_stack.back();

		new_tag->mpLocation = tag.mpLocation;
		new_tag->mLineno = tag.mLineno;
		new_tag->mName = a->mValue;
		new_tag->mbIsText = false;
		new_tag->mbIsControl = false;

		// compatibility
		if (!new_tag->mName.compare(0, 2, "w:"))
			new_tag->mName.replace(0, 2, "lina:");

		output_tag_contents(ctx, NULL, tag);

		ctx.construction_stack.pop_back();
		output_tag(ctx, out, *new_tag);
	} else if (tag.mName == "lina:arg") {
		if (!out && ctx.construction_stack.empty())
			error(ctx, "<lina:arg> can only be used in an output context");
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:arg> must have NAME attribute");

		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:arg> can only be used during macro expansion");

		std::list<const TreeNode *>::const_iterator it(ctx.invocation_stack.end());
		--it;

		int levels = 1;
		const char *name = a->mValue.c_str();
		while(*name == '^') {
			++levels;
			++name;

			if (it == ctx.invocation_stack.begin())
				error(ctx, "Number of up-scope markers in name exceeds macro nesting level");

			--it;
		}

		const TreeNode& macrotag = **it;
		const TreeAttribute *a2 = macrotag.Attrib(name);
		if (!a2)
			error(ctx, "macro invocation <%s> does not have an attribute \"%s\"", macrotag.mName.c_str(), name);

		if (out) {
			*out += a2->mValue;

			ctx.eat_next_space = false;
			ctx.holding_space = false;
		} else {
			TreeNode *t = ctx.mpDocument->AllocNode();

			t->mpLocation = tag.mpLocation;
			t->mLineno = tag.mLineno;
			t->mbIsControl = false;
			t->mbIsText = true;
			t->mName = a2->mValue;

			ctx.construction_stack.back()->mChildren.push_back(t);
		}
	} else if (tag.mName == "lina:if-arg") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-arg> must have NAME attribute");

		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-arg> can only be used during macro expansion");

		const TreeNode& macrotag = *ctx.invocation_stack.back();
		const TreeAttribute *a2 = macrotag.Attrib(a->mValue);
		if (a2)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:if-not-arg") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-not-arg> must have NAME attribute");

		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-not-arg> can only be used during macro expansion");

		const TreeNode& macrotag = *ctx.invocation_stack.back();
		const TreeAttribute *a2 = macrotag.Attrib(a->mValue);
		if (!a2)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:attrib") {
		if (ctx.construction_stack.empty())
			error(ctx, "<lina:attrib> can only be used in a <lina:tag> element");

		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:attrib> must have NAME attribute");

		std::string s;
		std::list<TreeNode *> tempStack;
		ctx.construction_stack.swap(tempStack);
		++ctx.cdata_count;
		++ctx.pre_count;
		bool bHoldingSpace = ctx.holding_space;
		bool bEatNextSpace = ctx.eat_next_space;
		ctx.holding_space = false;
		ctx.eat_next_space = true;
		output_tag_contents(ctx, &s, tag);
		ctx.holding_space = bHoldingSpace;
		ctx.eat_next_space = bEatNextSpace;
		--ctx.pre_count;
		--ctx.cdata_count;
		ctx.construction_stack.swap(tempStack);

		TreeNode *t = ctx.construction_stack.back();
		TreeAttribute new_att;
		if (tag.Attrib("novalue")) {
			new_att.mbNoValue = true;
		} else {
			new_att.mbNoValue = false;
			new_att.mValue = s;
		}
		new_att.mName = a->mValue;
		t->mAttribs.push_back(new_att);
	} else if (tag.mName == "lina:pull") {
		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:pull> can only be used during macro expansion");

		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:pull> must have NAME attribute");

		const TreeNode *t = ctx.find_tag(a->mValue);
		
		if (!t)
			error(ctx, "cannot find tag <%s> referenced in <lina:pull>", a->mValue.c_str());

		output_tag_contents(ctx, out, *t);		
	} else if (tag.mName == "lina:for-each") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:for-each> must have NAME attribute");
		
		std::string node_name;
		const TreeNode *parent;
		if (ctx.invocation_stack.empty()) {
			if (!a->mValue.empty() && a->mValue[0] == '/')
				parent = ctx.mpDocument->mpRoot->ResolvePath(a->mValue.substr(1), node_name);
			else
				error(ctx, "path must be absolute if not in macro context");
		} else {
			std::list<const TreeNode *>::reverse_iterator it(ctx.invocation_stack.rbegin()), itEnd(ctx.invocation_stack.rend());
			
			for(; it!=itEnd; ++it) {
				parent = (*it)->ResolvePath(a->mValue, node_name);
				if(parent)
					break;
				if (!a->mValue.empty() && a->mValue[0] == '/')
					break;
			}
		}

		if (!parent)
			error(ctx, "cannot resolve path \"%s\"", a->mValue.c_str());

		std::list<TreeNode *>::const_iterator it2(parent->mChildren.begin()), it2End(parent->mChildren.end());

		ctx.invocation_stack.push_back(NULL);
		for(; it2!=it2End; ++it2) {
			if ((*it2)->mName == node_name) {
				ctx.invocation_stack.back() = *it2;
				output_tag_contents(ctx, out, tag);
			}
		}
		ctx.invocation_stack.pop_back();
	} else if (tag.mName == "lina:apply") {
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:apply> must have NAME attribute");

		std::map<std::string, TreeNode *>::const_iterator it(ctx.mpDocument->mMacros.find(a->mValue));

		if (it == ctx.mpDocument->mMacros.end())
			error(ctx, "macro \"%s\" undeclared", a->mValue.c_str());
		
		std::list<TreeNode *>::const_iterator it2(tag.mChildren.begin()), it2End(tag.mChildren.end());

		ctx.invocation_stack.push_back(NULL);
		for(; it2!=it2End; ++it2) {
			if (!(*it2)->mbIsText) {
				ctx.invocation_stack.back() = *it2;
				output_tag_contents(ctx, out, *(*it).second);
			}
		}
		ctx.invocation_stack.pop_back();
	} else if (tag.mName == "lina:if-present") {
		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-present> can only be used during macro expansion");
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-present> must have NAME attribute");

		const TreeNode *t = ctx.find_tag(a->mValue);
		if (t)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:if-not-present") {
		if (ctx.invocation_stack.empty())
			error(ctx, "<lina:if-not-present> can only be used during macro expansion");
		const TreeAttribute *a = tag.Attrib("name");
		if (!a)
			error(ctx, "<lina:if-not-present> must have NAME attribute");

		const TreeNode *t = ctx.find_tag(a->mValue);
		if (!t)
			output_tag_contents(ctx, out, tag);
	} else if (tag.mName == "lina:pre") {
		++ctx.pre_count;
		++ctx.cdata_count;
		if (!out)
			output_standard_tag(ctx, out, tag);
		else {
			output_tag_contents(ctx, out, tag);
		}
		--ctx.cdata_count;
		--ctx.pre_count;
	} else if (tag.mName == "lina:cdata") {
		++ctx.cdata_count;
		if (!out)
			output_standard_tag(ctx, out, tag);
		else
			output_tag_contents(ctx, out, tag);
		--ctx.cdata_count;
	} else if (tag.mName == "lina:delay") {
		std::list<TreeNode *>::const_iterator it(tag.mChildren.begin()), itEnd(tag.mChildren.end());
		for(; it!=itEnd; ++it) {
			output_standard_tag(ctx, out, **it);
		}
	} else if (tag.mName == "lina:dump-stack") {
		dump_stack(ctx);
	} else if (tag.mName == "lina:replace") {
		const TreeAttribute *a = tag.Attrib("from");
		if (!a || a->mbNoValue)
			error(ctx, "<lina:replace> must have FROM attribute");
		const TreeAttribute *a2 = tag.Attrib("to");
		if (!a2 || a2->mbNoValue)
			error(ctx, "<lina:replace> must have TO attribute");

		const std::string& x = a->mValue;
		const std::string& y = a2->mValue;

		std::string s, t;
		std::string::size_type i = 0;

		output_tag_contents(ctx, &s, tag);

		for(;;) {
			std::string::size_type j = s.find(x, i);
			if (j != i)
				t.append(s, i, j-i);
			if (j == std::string::npos)
				break;
			t.append(y);
			i = j + x.size();
		}

		TreeNode *new_tag = ctx.mpDocument->AllocNode();

		new_tag->mpLocation = tag.mpLocation;
		new_tag->mLineno = tag.mLineno;
		new_tag->mbIsText = true;
		new_tag->mbIsControl = false;
		new_tag->mName = t;

		output_tag(ctx, out, *new_tag);
	} else if (tag.mName == "lina:set-option") {
		const TreeAttribute *a_name = tag.Attrib("name");
		if (!a_name)
			error(ctx, "<lina:set-option> must have NAME attribute");

		if (a_name->mValue == "link-truncate") {
			const TreeAttribute *a_val = tag.Attrib("baseurl");
			if (!a_val || a_val->mbNoValue)
				error(ctx, "option \"link-truncate\" requires BASEURL attribute");

			bool bTruncate = !tag.Attrib("notruncate");

			g_truncateURLs.push_back(std::make_pair(a_val->mValue, bTruncate));
		} else if (a_name->mValue == "output-dir") {
			const TreeAttribute *a_val = tag.Attrib("target");
			if (!a_val || a_val->mbNoValue)
				error(ctx, "option \"output-dir\" requires TARGET attribute");

			g_outputDir = a_val->mValue;
		} else if (a_name->mValue == "tag-info") {
			const TreeAttribute *a_tagname = tag.Attrib("tag");
			if (!a_tagname || a_tagname->mbNoValue)
				error(ctx, "option \"tag-info\" requires TAG attribute");

			const TreeAttribute *a_cdata = tag.Attrib("cdata");

			if (!a_cdata || a_cdata->mbNoValue)
				error(ctx, "option \"tag-info\" requires CDATA attribute");

			TreeNode::SetSupportsCDATA(a_tagname->mValue, is_true(a_cdata->mValue));
		} else
			error(ctx, "option \"%s\" unknown\n", a_name->mValue.c_str());

	} else if (tag.mName == "lina:data") {
		// do nothing
	} else if (tag.mName == "lina:source") {
		if (out) {
			std::list<TreeNode *>::const_iterator itBegin(tag.mChildren.begin()), it(itBegin), itEnd(tag.mChildren.end());
			for(; it!=itEnd; ++it) {
				output_source_tags(ctx, out, **it);
			}
		}
	} else if (tag.mName == "lina:htmlhelp-toc") {
		const TreeAttribute *a_val = tag.Attrib("file");
		if (!a_val || a_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-toc> requires FILE attribute");

		const std::string filename(create_output_filename(a_val->mValue));

		// build new tag with TOC contents
		ctx.construction_stack.push_back(ctx.mpDocument->AllocNode());
		TreeNode *new_tag = ctx.construction_stack.back();

		new_tag->mpLocation = tag.mpLocation;
		new_tag->mLineno = tag.mLineno;
		new_tag->mName = a_val->mValue;
		new_tag->mbIsText = false;
		new_tag->mbIsControl = false;

		output_tag_contents(ctx, NULL, tag);

		ctx.construction_stack.pop_back();
		output_tag(ctx, out, *new_tag);

		FILE *f = fopen(filename.c_str(), "wb");
		if (!f)
			error(ctx, "couldn't create htmlhelp toc \"%s\"", a_val->mValue.c_str());
		output_toc(f, *new_tag);
		fclose(f);

	} else if (tag.mName == "lina:htmlhelp-project") {
		const TreeAttribute *file_val = tag.Attrib("file");
		if (!file_val || file_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires FILE attribute");

		const TreeAttribute *output_val = tag.Attrib("output");
		if (!output_val || output_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires OUTPUT attribute");

		const TreeAttribute *toc_val = tag.Attrib("toc");
		if (!toc_val || toc_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires TOC attribute");

		const TreeAttribute *title_val = tag.Attrib("title");
		if (!title_val || title_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-project> requires TITLE attribute");

		const std::string filename(create_output_filename(file_val->mValue));

		FILE *f = fopen(filename.c_str(), "wb");
		if (!f)
			error(ctx, "couldn't create htmlhelp project \"%s\"", file_val->mValue.c_str());
		fprintf(f,
			"[OPTIONS]\n"
			"Auto Index=Yes\n"
			"Compatibility=1.1 or later\n"
			"Compiled file=%s\n"
			"Contents file=%s\n"
			"Default topic=index.html\n"
			"Display compile progress=no\n"
			"Full-text search=Yes\n"
			, output_val->mValue.c_str()
			, toc_val->mValue.c_str()
			);


		const TreeAttribute *fullstop_val = tag.Attrib("fullstop");
		if (fullstop_val && !fullstop_val->mbNoValue)
			fprintf(f, "Full text search stop list file=%s\n", fullstop_val->mValue.c_str());

		fprintf(f,
			"Language=0x0409 English (United States)\n"
			"Title=%s\n"
			"\n"
			"[FILES]\n"
			, title_val->mValue.c_str()
			);

		std::list<std::string>::const_iterator it(g_htmlHelpFiles.begin()), itEnd(g_htmlHelpFiles.end());
		for(; it!=itEnd; ++it) {
			fprintf(f, "%s\n", (*it).c_str());
		}

		fclose(f);		
	} else if (tag.mName == "lina:htmlhelp-addfile") {
		const TreeAttribute *file_val = tag.Attrib("file");
		if (!file_val || file_val->mbNoValue)
			error(ctx, "<lina:htmlhelp-addfile> requires FILE attribute");

		g_htmlHelpFiles.push_back(file_val->mValue);
	} else {
		std::string macroName(tag.mName, 5, std::string::npos);
		std::map<std::string, TreeNode *>::const_iterator it = ctx.mpDocument->mMacros.find(macroName);

		if (it == ctx.mpDocument->mMacros.end())
			error(ctx, "macro <lina:%s> not found", macroName.c_str());

//		dump_stack(ctx);
//		printf("executing macro: %s (%s:%d)\n", tag.mName.c_str(), tag.mLocation->name.c_str(), tag.mLineno);

		ctx.invocation_stack.push_back(&tag);
		output_tag_contents(ctx, out, *(*it).second);
		ctx.invocation_stack.pop_back();

//		printf("exiting macro: %s (%s:%d)\n", tag.mName.c_str(), tag.mLocation->name.c_str(), tag.mLineno);
	}
}