Skip to content

Instantly share code, notes, and snippets.

@TheVice
Last active May 6, 2019 23:55
Show Gist options
  • Save TheVice/421cb7df499b7515e6f5e278e4335b87 to your computer and use it in GitHub Desktop.
Save TheVice/421cb7df499b7515e6f5e278e4335b87 to your computer and use it in GitHub Desktop.
glew_generator - tool that take path to glew and glfixes repositories and generate glew snapshot. More described here https://github.com/nigels-com/glew/issues/13#issuecomment-260712955
.vs/
Debug/
Release/
x64/
build/
include/
src/
googletest-release-*/
pugixml-*/
Visual_Studio_*/
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "blacklist.h"
#include "input_output.h"
#include "common.h"
void read_black_list(const std::string& black_list_file, std::list<std::string>& black_list)
{
std::string content;
read_from_file(black_list_file, content);
black_list = split(content, '\n', true);
}
void apply_black_list(const std::list<std::string>& black_list, std::list<std::string>& extension_list)
{
for (const auto& path : black_list)
{
extension_list.remove_if([&path](const std::string & ext)
{
return ends_with(ext, path);
});
}
}
void apply_black_list(const std::string& black_list_file, std::list<std::string>& extension_list)
{
std::list<std::string> lines;
read_black_list(black_list_file, lines);
apply_black_list(lines, extension_list);
}
void apply_black_list(std::istream& black_list_stream, std::list<std::string>& extension_list)
{
//TODO: change return of function to bool type and monitor if command was apply.
for (std::string line; std::getline(black_list_stream, line);)
{
extension_list.remove_if([&line](const std::string & ext)
{
return ends_with(ext, line);
});
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _BLACK_LIST_H_
#define _BLACK_LIST_H_
#include <list>
#include <string>
#include <istream>
void read_black_list(const std::string& black_list_file, std::list<std::string>& black_list);
void apply_black_list(const std::list<std::string>& black_list, std::list<std::string>& extension_list);
void apply_black_list(const std::string& black_list_file, std::list<std::string>& extension_list);
void apply_black_list(std::istream& black_list_stream, std::list<std::string>& extension_list);
#endif
#tool nuget:?package=CMake&version=3.5.2
#addin nuget:?package=Cake.Git&version=0.19.0
#addin nuget:?package=Cake.CMake&version=0.2.2
#addin nuget:?package=ClangSharp&version=3.8.0
//////////////////////////////////////////////////////////////////////
// ARGUMENTS
//////////////////////////////////////////////////////////////////////
var target = Argument("target", "Default");
var gitUserName = Argument("GitUserName", string.Empty);
var gitUserPassword = Argument("GitUserPassword", string.Empty);
var generator = Argument("generator", string.Empty);
var platforms = Argument("platforms", "Win32");
var configs = Argument("configs", "Debug, Release");
var targets = Argument("targets", "glew_generator_app, tests_xml, tests_xml_by_version, tests_parse_xml, tests_parse_xml_alternative");
var versions = Argument("versions", "1.13");
var test_filter = Argument("test_filter", string.Empty);
var glew_url = Argument("glew_url", "https://github.com/nigels-com/glew.git");
var glfixes_url = Argument("glfixes_url", "https://github.com/nigels-com/glfixes.git");
var open_gl_registry_url = Argument("open_gl_registry_url", "https://github.com/KhronosGroup/OpenGL-Registry.git");
var egl_registry_url = Argument("egl_registry_url", "https://github.com/KhronosGroup/EGL-Registry.git");
var pugixml_url = Argument("pugixml_url", "https://github.com/zeux/pugixml.git");
var gtest_url = Argument("gtest_url", "https://github.com/google/googletest.git");
//////////////////////////////////////////////////////////////////////
// CLASSES
//////////////////////////////////////////////////////////////////////
using System.Runtime.InteropServices;
using System.Reflection;
using LibGit2Sharp;
using ClangSharp;
public static class Misc
{
public static char[] SplitSeparator { private set { } get { return new char[] { ',', ' ', ';', '\t', '\n' }; } }
}
public static class Versions
{
public static ISet<System.Version> FromArgumentToArray(string argument)
{
var str_versions = argument.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries);
var versions = new SortedSet<System.Version>();
for (var i = 0; i < str_versions.Length; ++i)
{
versions.Add(new System.Version(str_versions[i]));
}
return versions;
}
public static System.Version ver_1_13 { private set { } get { return new System.Version(1, 13); } }
public static System.Version ver_2_1 { private set { } get { return new System.Version(2, 1); } }
public static System.Version ver_2_2 { private set { } get { return new System.Version(2, 2); } }
public static System.Version GetHighestVersion(IEnumerable<System.Version> versions)
{
var highest_version = new System.Version();
foreach (var version in versions)
{
if (highest_version < version)
{
highest_version = version;
}
}
return highest_version;
}
public static string ToString(System.Version version)
{
return $"{version}".Replace(".", "_");
}
}
public static class Hashes
{
public static string pugixml_hash { private set { } get { return "8436f2a69b9331f8e99a52772e93ba0dbb68dafe"; } }
public static string gtest_hash { private set { } get { return "2fe3bd994b3189899d93f1d5a881e725e046fdc2"; } }
//
public static string open_gl_registry_hash_2_2 { private set { } get { return "7457d2c708a49bd92d9c0b121740dec10bf7b5b6"; } }
public static string egl_registry_hash_2_2 { private set { } get { return "0555f6db15b61a99e5091d6826fb6fb67d9661c8"; } }
//
public static string glew_1_10 { private set { } get { return "a6c3e7dad0d1ae34e8016cf086ba6109d6fb4e4a"; } }
public static string glew_1_11 { private set { } get { return "83a2bae026289a8d4cdce0061b1c52595b3c9338"; } }
public static string glew_1_12 { private set { } get { return "9fedd9e053c973ef85cfc830c74a26d0cdd8c99a"; } }
public static string glew_1_13 { private set { } get { return "f0067bb1151d36b37bd43948ce5a399844afb313"; } }
public static string glew_2_0 { private set { } get { return "7d72257b0ff2aadab92d9b627beb44c36b072e52"; } }
public static string glew_2_1 { private set { } get { return "3a8eff77da3658c13fbd3634c943d5251d76322c"; } }
public static string glew_2_2 { private set { } get { return "61d167422c86735514e713eeea70e0477a979b26"; } }
//
public static string glfixes_1_10 { private set { } get { return "909400fa310f1eee70fcfd444630518cbfdce6f3"; } }
public static string glfixes_1_11 { private set { } get { return "c948e0dcdbb4aeb617da351c70887a79b94cdded"; } }
public static string glfixes_1_12 { private set { } get { return "d3ae5b802bf057e06f94d9c30b92e192e2316d7f"; } }
public static string glfixes_1_13 { private set { } get { return "6482cec77a49f12c20b2be0b17e0a537c043b64e"; } }
public static string glfixes_2_0 { private set { } get { return "c0e1bb4f7c49ffa844d930091d3ccb197feb42ee"; } }
public static string glfixes_2_1 { private set { } get { return "970b8145acd42ebd86ff025e1eb8c8cbcd1fc6a2"; } }
//
public static string get_property_value_by_name(string name)
{
var props = typeof(Hashes).GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (var prop in props)
{
if (prop.Name == name)
{
return (string)prop.GetValue(null, null);
}
}
throw new ArgumentException($"Can not find property with name '{name}'.");
}
}
public class PathComparer : IComparer<Cake.Core.IO.Path>
{
public int Compare(Cake.Core.IO.Path x, Cake.Core.IO.Path y)
{
return StringComparer.Ordinal.Compare(x.FullPath, y.FullPath);
}
}
public class Paths
{
public static Paths paths;
public DirectoryPath root { private set; get; }
public FilePath tests_xml { private set; get; }
public DirectoryPath output { private set; get; }
public DirectoryPath cmake_output_path { set; get; }
public DirectoryPath reference { private set; get; }
public DirectoryPath tools { private set; get; }
public DirectoryPath cmake_bin { private set; get; }
public FilePath cmake_exe { private set; get; }
public DirectoryPath repositories { private set; get; }
public DirectoryPath glew_dir { private set; get; }
public DirectoryPath glfixes_dir { private set; get; }
public DirectoryPath open_gl_registry_dir { private set; get; }
public DirectoryPath egl_registry_dir { private set; get; }
public DirectoryPath pugixml_dir { private set; get; }
public DirectoryPath gtest_dir { private set; get; }
public FilePath egl_xml { private set; get; }
public ICollection<DirectoryPath> bin_paths { private set; get; }
public SortedDictionary<System.Version, SortedSet<DirectoryPath>> version_and_outputs { private set; get; }
public static string Normalize(string path)
{
if ('/' != System.IO.Path.DirectorySeparatorChar)
{
path = path.Replace('/', System.IO.Path.DirectorySeparatorChar);
}
return path;
}
public static string Normalize(Cake.Core.IO.Path path)
{
return Normalize(path.FullPath);
}
private Paths(ICakeContext context)
{
root = context.Environment.WorkingDirectory;
//
tests_xml = root.CombineWithFilePath("tests.xml");
output = root.Combine("output");
cmake_output_path = output;
reference = root.Combine("reference");
tools = root.Combine("tools");
if (PlatformID.Unix == Environment.OSVersion.Platform)
{
var unix_cmake_canditates = new FilePath[] { "/usr/bin/cmake",
"/usr/local/bin/cmake" };
foreach (var path in unix_cmake_canditates)
{
if (FileAliases.FileExists(context, path))
{
cmake_exe = path;
break;
}
}
}
else
{
cmake_bin = tools.Combine("CMake.3.5.2").Combine("bin");
cmake_exe = cmake_bin.CombineWithFilePath("cmake.exe");
}
repositories = root.Combine("repositories");
glew_dir = repositories.Combine("glew");
glfixes_dir = repositories.Combine("glfixes");
open_gl_registry_dir = repositories.Combine("OpenGL-Registry");
egl_registry_dir = repositories.Combine("EGL-Registry");
//
pugixml_dir = repositories.Combine("pugixml");
gtest_dir = repositories.Combine("gtest");
//
egl_xml = egl_registry_dir.Combine("api").CombineWithFilePath("egl.xml");
//
bin_paths = new SortedSet<DirectoryPath>(new PathComparer());
version_and_outputs = new SortedDictionary<System.Version, SortedSet<DirectoryPath>>();
}
public static bool Init(ICakeContext context)
{
if (null == paths)
{
paths = new Paths(context);
}
return (null != paths);
}
}
public static class Git
{
public static bool IsRepositoryExists(string aPath, out Repository aRepository, ICakeContext context)
{
aRepository = null;
if (!DirectoryAliases.DirectoryExists(context, aPath))
{
return false;
}
try
{
aRepository = new Repository(aPath);
}
catch (RepositoryNotFoundException)
{
return false;
}
return true;
}
public static bool IsRepositoryContainsCommit(Repository aRepository, ObjectId aCommit)
{
var commit = aRepository.Lookup(aCommit);
if (null == commit)
{
return false;
}
if (commit is Commit)
{
return true;
}
return false;
}
public static bool IsRepositoryContainsCommit(Repository aRepository, string aCommit)
{
ObjectId commit = null;
try
{
commit = new ObjectId(aCommit);
}
catch (ArgumentException)
{
return false;
}
return IsRepositoryContainsCommit(aRepository, commit);
}
public static LibGit2Sharp.Handlers.CredentialsHandler CreateCredential(string aUserName, string aPassword)
{
return new LibGit2Sharp.Handlers.CredentialsHandler(
(url, usernameFromUrl, types) => new UsernamePasswordCredentials()
{
Username = aUserName,
Password = aPassword
});
}
public static string Clone(string aSourceUrl, string aWorkdirPath, string aUserName = null, string aPassword = null)
{
var cloneOptions = new CloneOptions();
if (!string.IsNullOrEmpty(aUserName) && !string.IsNullOrEmpty(aPassword))
{
cloneOptions.CredentialsProvider = CreateCredential(aUserName, aPassword);
}
var pathToTheCreatedRepository = Repository.Clone(aSourceUrl, aWorkdirPath, cloneOptions);
return pathToTheCreatedRepository;
}
public static MergeResult Pull(Repository aRepository, string aUserName = null, string aPassword = null)
{
var options = new PullOptions();
if (!string.IsNullOrEmpty(aUserName) && !string.IsNullOrEmpty(aPassword))
{
options.FetchOptions = new FetchOptions();
options.FetchOptions.CredentialsProvider = CreateCredential(aUserName, aPassword);
}
var merger = new Signature(Environment.UserName, $"{Environment.UserName}@{Environment.MachineName}", DateTimeOffset.UtcNow);
return Commands.Pull(aRepository, merger, options);
}
public static void EnsureRepositoriesExists(string[] urls, string[] dirs, string[] hashes,
string gitUserName, string gitUserPassword, ICakeContext context)
{
if (dirs.Length != urls.Length || hashes.Length != urls.Length)
{
throw new CakeException($"Length of dirs array '{dirs.Length}' not equal to the length of urls '{urls.Length}'.");
}
for (var i = 0; i < dirs.Length; ++i)
{
Repository repository = null;
if (!Git.IsRepositoryExists(dirs[i], out repository, context))
{
context.Information($"'{dirs[i]}' not exists. Cloning from '{urls[i]}'.");
if (!string.IsNullOrEmpty(gitUserName) && !string.IsNullOrEmpty(gitUserPassword))
{
context.Information($"Will be used git user name '{gitUserName}'.");
}
var dir = Git.Clone(urls[i], dirs[i], gitUserName, gitUserPassword);
context.Information($"Cloned into '{dir}'.");
if (!Git.IsRepositoryExists(dirs[i], out repository, context))
{
throw new CakeException($"Could not find repository at '{dirs[i]}'.");
}
}
if (!Git.IsRepositoryContainsCommit(repository, hashes[i]))
{
context.Information($"Commit with hash '{hashes[i]}' not exists at '{dirs[i]}'. Pull.");
if (!string.IsNullOrEmpty(gitUserName) && !string.IsNullOrEmpty(gitUserPassword))
{
context.Information($"Will be used git user name '{gitUserName}'.");
}
Git.Pull(repository, gitUserName, gitUserPassword);
if (!Git.IsRepositoryContainsCommit(repository, hashes[i]))
{
throw new CakeException($"Could not find commit with hash '{hashes[i]}' at '{dirs[i]}' even after pull was provided. "
+ "That may indicate that commit with such hash not from that repository or from branch that actually not merged into master.");
}
}
}
}
public static bool Checkout(string path_to_repository, string commit_sha, ICakeContext context)
{
Repository repository = null;
if (!IsRepositoryExists(path_to_repository, out repository, context))
{
return false;
}
var oid = new ObjectId(commit_sha);
var commit = repository.Lookup(oid);
if (!(commit is Commit))
{
return false;
}
var real_commit = commit as Commit;
if (repository.Head.Tip == real_commit)
{
return true;
}
context.Information($"Checkout of '{path_to_repository}' onto '{commit_sha}'.");
Commands.Checkout(repository, real_commit);
return (repository.Head.Tip == real_commit);
}
private static long GetBlobContent(Blob blob, System.IO.Stream content)
{
var blob_size = blob.Size;
if (0 < blob_size)
{
blob.GetContentStream().CopyTo(content);
}
else
{
blob_size = 0;
}
return blob_size;
}
private static void Walk(Tree tree, string real_root)
{
foreach (var element in tree)
{
var full_name = string.IsNullOrEmpty(real_root) ? element.Name : System.IO.Path.Combine(real_root, element.Name);
var element_target = element.Target;
if (TreeEntryTargetType.Tree == element.TargetType)
{
Walk(element_target as Tree, full_name);
}
else if (TreeEntryTargetType.Blob == element.TargetType)
{
if (!string.IsNullOrEmpty(real_root))
{
System.IO.Directory.CreateDirectory(real_root);
}
using (var fs = new System.IO.FileStream(full_name, System.IO.FileMode.Create))
{
GetBlobContent(element_target as Blob, fs);
}
}
}
}
public static bool SaveFilesFromRevision(
string path_to_repository,
string commit_sha,
string output_directory,
ICakeContext context)
{
if (string.IsNullOrEmpty(path_to_repository) ||
string.IsNullOrEmpty(commit_sha) ||
string.IsNullOrEmpty(output_directory))
{
return false;
}
var oid = new ObjectId(commit_sha);
var repository = new Repository(path_to_repository);
var commit = repository.Lookup(oid);
if (!(commit is Commit))
{
return false;
}
context.Information($"Extracting from '{path_to_repository}' by hash '{commit_sha}' into '{output_directory}'.");
context.EnsureDirectoryExists(output_directory);
//
var real_commit = commit as Commit;
context.Information($"Repository : '{path_to_repository}'");
context.Information($"Commit : '{commit_sha}'");
context.Information($"Author : '{real_commit.Author.Name}'");
context.Information($"Committer : '{real_commit.Committer.Name}'");
context.Information($"Summary : '{real_commit.MessageShort}'");
context.Information($"Will be stored at : '{output_directory}'");
//
Walk(real_commit.Tree, output_directory);
return true;
}
}
public class SameFileNameStorage : ICollection<FilePath>
{
private ICollection<FilePath> Storage = new SortedSet<FilePath>(new PathComparer());
public int Count { get { return Storage.Count; } }
public bool IsReadOnly { get { return false; } }
public void Add(ICollection<string> item)
{
var a = 0;
var itemToStorage = new FilePath[item.Count];
foreach (var i in item)
{
itemToStorage[a++] = new FilePath(i);
}
Add(itemToStorage);
}
public void Add(ICollection<FilePath> item)
{
if (Storage.Count == 0)
{
foreach (var i in item)
{
Storage.Add(i);
}
}
else
{
var pathsToAdd = new List<FilePath>();
var pathsToRemove = new List<FilePath>();
foreach (var storageItem in Storage)
{
var exists = false;
foreach (var i in item)
{
if (storageItem.GetFilename().FullPath == i.GetFilename().FullPath)
{
exists = true;
pathsToAdd.Add(i);
break;
}
}
if (!exists)
{
pathsToRemove.Add(storageItem);
}
}
foreach (var storageItem in pathsToRemove)
{
Storage.Remove(storageItem);
}
foreach (var i in pathsToAdd)
{
Storage.Add(i);
}
}
if (Storage.Count == 0)
{
throw new Exception("Nothing to compare. Used collections with no common names.");
}
}
public void Add(FilePath item)
{
Add(new FilePath[] { item });
}
public void Clear()
{
Storage.Clear();
}
public bool Contains(FilePath item)
{
return Storage.Contains(item);
}
public void CopyTo(FilePath[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public IEnumerator<FilePath> GetEnumerator()
{
return Storage.GetEnumerator();
}
public bool Remove(FilePath item)
{
if (Contains(item))
{
return Storage.Remove(item);
}
return false;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
public static void AddExecPermission(FilePath path, ICakeContext context)
{
var bash_arguments = new ProcessArgumentBuilder();
bash_arguments.Append("-c");
bash_arguments.Append($"\"chmod +x {path.GetFilename()}\"");
//
var processSettings = new ProcessSettings();
processSettings.Timeout = (int)((new TimeSpan(0, 0, 15)).TotalMilliseconds);
processSettings.WorkingDirectory = path.GetDirectory();
processSettings.Arguments = bash_arguments;
//
var fullPath = "bash";
context.Information($"{fullPath} {processSettings.Arguments.Render()}");
var exitCode = context.StartProcess(fullPath, processSettings);
if (0 != exitCode)
{
context.Warning($"Exit code was '{exitCode}'.");
}
}
private static CXToken[] ToTokens(IntPtr rawTokens, uint countOfTokens)
{
var tokens = new CXToken[countOfTokens];
for (int i = 0; i < countOfTokens; i++)
{
tokens[i] = Marshal.PtrToStructure<CXToken>(rawTokens + i * Marshal.SizeOf<CXToken>());
}
return tokens;
}
public static string GetLexicalAnalyze(string fileName)
{
var index = clang.createIndex(0, 0);
CXUnsavedFile unsavedFiles;
var translationUnit = clang.parseTranslationUnit(index, fileName, null, 0,
out unsavedFiles, 0, (uint)CXTranslationUnit_Flags.CXTranslationUnit_None);
//
var translationUnitCursor = clang.getTranslationUnitCursor(translationUnit);
var cursorExtent = clang.getCursorExtent(translationUnitCursor);
IntPtr rawTokens = IntPtr.Zero;
uint countOfTokens = 0;
clang.tokenize(translationUnit, cursorExtent, out rawTokens, out countOfTokens);
var tokens = ToTokens(rawTokens, countOfTokens);
var output = new StringBuilder();
for (uint i = 0; i < countOfTokens; ++i)
{
var kind = clang.getTokenKind(tokens[i]);
switch (kind)
{
case CXTokenKind.CXToken_Punctuation:
output.Append("A token that contains some kind of punctuation.");
break;
case CXTokenKind.CXToken_Keyword:
output.Append("A language keyword.");
break;
case CXTokenKind.CXToken_Identifier:
output.Append("An identifier (that is not a keyword).");
break;
case CXTokenKind.CXToken_Literal:
output.Append("A numeric, string, or character literal.");
break;
case CXTokenKind.CXToken_Comment:
output.Append("A comment.");
break;
default:
output.Append("Unknown enum value of CXTokenKind.");
break;
}
var name = clang.getTokenSpelling(translationUnit, tokens[i]).ToString();
output.AppendLine($" '{name}'");
}
//clang.disposeTokens(translationUnit, out rawTokens, countOfTokens);
clang.disposeTranslationUnit(translationUnit);
clang.disposeIndex(index);
//
return output.ToString();
}
//////////////////////////////////////////////////////////////////////
// TASKS
//////////////////////////////////////////////////////////////////////
var generator_name = string.Empty;
string[] array_with_platforms = null;
string[] array_with_configs = null;
string[] array_with_targets = null;
ISet<System.Version> array_with_versions = null;
Setup(context =>
{
Paths.Init(context);
if (string.IsNullOrEmpty(generator))
{
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
generator_name = "Visual Studio 14 2015";
}
else if (PlatformID.Unix == Environment.OSVersion.Platform)
{
generator_name = "Eclipse CDT4 - Unix Makefiles";
}
}
else
{
generator_name = generator;
}
Paths.paths.cmake_output_path = Paths.paths.output.Combine(generator_name.Replace(" ", "_"));
if (generator_name.EndsWith("Makefiles"))
{
array_with_platforms = new string[] { string.Empty };
}
else
{
array_with_platforms = platforms.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries);
}
if (generator_name.StartsWith("Visual") && 0 == array_with_platforms.Length)
{
if (Environment.Is64BitOperatingSystem)
{
array_with_platforms = new string[] { "x64", "Win32" };
}
else
{
array_with_platforms = new string[] { "Win32" };
}
}
array_with_configs = configs.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries);
if (0 == array_with_configs.Length)
{
array_with_configs = new string[] { "Debug", "Release" };
}
array_with_targets = targets.Split(Misc.SplitSeparator, StringSplitOptions.RemoveEmptyEntries);
if (array_with_targets.Length == 0)
{
array_with_targets = new string[] { string.Empty };
}
array_with_versions = Versions.FromArgumentToArray(versions);
if (array_with_versions.Count == 0)
{
array_with_versions.Add(Versions.ver_1_13);
}
});
Task("clean")
.Does(content =>
{
var files = new List<string>();
foreach (var folder in new DirectoryPath[] { Paths.paths.output })
{
if (!DirectoryExists(folder))
{
continue;
}
files.AddRange(System.IO.Directory.GetFiles(Paths.Normalize(folder), "*.*", System.IO.SearchOption.AllDirectories));
}
foreach (var file in files)
{
if (file.StartsWith(Paths.paths.cmake_output_path.FullPath))
{
continue;
}
Information(file);
var empty = false;
using (var fs = new FileStream(file, FileMode.Open))
{
if (0 == fs.Length)
{
empty = true;
}
}
if (empty)
{
System.IO.File.Delete(file);
}
else
{
System.IO.File.WriteAllText(file, string.Empty);
}
}
});
Task("get_data_repositories")
.Does(context =>
{
var urls = new string[] { glew_url, glfixes_url, open_gl_registry_url, egl_registry_url };
var dirs = new string[] { Paths.Normalize(Paths.paths.glew_dir),
Paths.Normalize(Paths.paths.glfixes_dir),
Paths.Normalize(Paths.paths.open_gl_registry_dir),
Paths.Normalize(Paths.paths.egl_registry_dir) };
//
var highest_version = Versions.GetHighestVersion(array_with_versions);
var str_ver = Versions.ToString(highest_version);
//
var glew_hash = Hashes.get_property_value_by_name($"glew_{str_ver}");
var glfixes_hash = ((Versions.ver_2_1 < highest_version) ? Hashes.glfixes_2_1 : Hashes.get_property_value_by_name($"glfixes_{str_ver}"));
//
var hashes = new string[] { glew_hash,
glfixes_hash,
Hashes.open_gl_registry_hash_2_2,
Hashes.egl_registry_hash_2_2 };
//
Git.EnsureRepositoriesExists(urls, dirs, hashes, gitUserName, gitUserPassword, context);
});
Task("git_extractor")
.IsDependentOn("get_data_repositories")
.Does(context =>
{
foreach (var version in array_with_versions)
{
Information($"Version - '{version}'.");
var str_ver = Versions.ToString(version);
//
var glew_output_dir = $"glew_{str_ver}";
var glew_hash = Hashes.get_property_value_by_name(glew_output_dir);
glew_output_dir = Paths.Normalize(Paths.paths.repositories.Combine(glew_output_dir));
if (!DirectoryExists(glew_output_dir))
{
if (!Git.SaveFilesFromRevision(Paths.Normalize(Paths.paths.glew_dir), glew_hash, glew_output_dir, context))
{
throw new CakeException($"Extracting was failed.");
}
}
/*TODO: if (Versions.ver_2_1 < version)
{
continue;
}*/
var glfixes_output_dir = $"glfixes_{str_ver}";
var glfixes_hash = ((Versions.ver_2_1 < version) ? Hashes.glfixes_2_1 : Hashes.get_property_value_by_name($"glfixes_{str_ver}"));
glfixes_output_dir = System.IO.Path.Combine(glew_output_dir, "auto", "registry");
if (!DirectoryExists(glfixes_output_dir))
{
if (!Git.SaveFilesFromRevision(Paths.Normalize(Paths.paths.glfixes_dir), glfixes_hash, glfixes_output_dir, context))
{
throw new CakeException($"Extracting was failed.");
}
}
}
//var highest_version = Versions.GetHighestVersion(array_with_versions);
//if (Versions.ver_2_1 < highest_version)
{
if (!Git.Checkout(Paths.Normalize(Paths.paths.open_gl_registry_dir), Hashes.open_gl_registry_hash_2_2, context))
{
throw new CakeException($"Checkout was failed.");
}
if (!Git.Checkout(Paths.Normalize(Paths.paths.egl_registry_dir), Hashes.egl_registry_hash_2_2, context))
{
throw new CakeException($"Checkout was failed.");
}
}
});
Task("get_pugixml_and_gtest")
.WithCriteria(() => FileExists(Paths.paths.tests_xml))
.Does(context =>
{
var urls = new string[] { pugixml_url, gtest_url };
var dirs = new string[] { Paths.Normalize(Paths.paths.pugixml_dir), Paths.Normalize(Paths.paths.gtest_dir) };
var hashes = new string[] { Hashes.pugixml_hash, Hashes.gtest_hash };
//
Git.EnsureRepositoriesExists(urls, dirs, hashes, gitUserName, gitUserPassword, context);
for (var i = 0; i < dirs.Length; ++i)
{
if (!Git.Checkout(dirs[i], hashes[i], context))
{
throw new CakeException($"Checkout was failed.");
}
}
});
Task("config")
.IsDependentOn("get_pugixml_and_gtest")
.Does(context =>
{
var cmakeSettings = new CMakeSettings();
if (PlatformID.Unix == Environment.OSVersion.Platform)
{
if (string.IsNullOrEmpty(Paths.paths.cmake_exe.FullPath))
{
throw new CakeException("Could not find cmake.");
}
cmakeSettings.ToolPath = Paths.paths.cmake_exe;
}
cmakeSettings.ToolTimeout = new TimeSpan(0, 1, 0);
cmakeSettings.Generator = generator_name;
if (FileExists(Paths.paths.tests_xml))
{
cmakeSettings.Options = new string[] { $"-DPUGIXML_PATH={Paths.paths.pugixml_dir}",
$"-DGTEST_PATH={Paths.paths.gtest_dir}" };
}
foreach (var platform in array_with_platforms)
{
cmakeSettings.OutputPath = Paths.paths.cmake_output_path;
if (cmakeSettings.Generator.StartsWith("Visual"))
{
cmakeSettings.Platform = platform;
cmakeSettings.OutputPath = cmakeSettings.OutputPath.Combine(platform);
//
EnsureDirectoryExists(cmakeSettings.OutputPath);
Information($"Platform - '{platform}', output path - '{cmakeSettings.OutputPath}'.");
CMakeAliases.CMake(context, Paths.paths.root, cmakeSettings);
}
else if (cmakeSettings.Generator.EndsWith("Makefiles"))
{
foreach (var config in array_with_configs)
{
var currentOutputPath = cmakeSettings.OutputPath;
cmakeSettings.OutputPath = currentOutputPath.Combine(config);
//
var options = new string[1 + cmakeSettings.Options.Count];
Array.Copy((cmakeSettings.Options as string[]), options, cmakeSettings.Options.Count);
options[options.Length - 1] = $"-DCMAKE_BUILD_TYPE=\"{config}\"";
//
EnsureDirectoryExists(cmakeSettings.OutputPath);
Information($"Platform - '{platform}', config - '{config}', output path - '{cmakeSettings.OutputPath}'.");
CMakeAliases.CMake(context, Paths.paths.root, cmakeSettings);
//
cmakeSettings.Options = new string[options.Length - 1];
Array.Copy(options, (cmakeSettings.Options as string[]), cmakeSettings.Options.Count);
cmakeSettings.OutputPath = currentOutputPath;
}
}
}
});
Task("make_binaries")
.IsDependentOn("config")
.Does(context =>
{
foreach (var target in array_with_targets)
{
var outputPath = Paths.paths.cmake_output_path;
foreach (var platform in array_with_platforms)
{
DirectoryPath outputPathWithPlatform = string.Empty;
if (generator_name.StartsWith("Visual"))
{
outputPathWithPlatform = outputPath.Combine(platform);
}
else
{
outputPathWithPlatform = outputPath;
}
foreach (var config in array_with_configs)
{
DirectoryPath outputPathWithPlatformAndConfig = string.Empty;
if (generator_name.EndsWith("Makefiles"))
{
outputPathWithPlatformAndConfig = outputPathWithPlatform.Combine(config);
}
else
{
outputPathWithPlatformAndConfig = outputPathWithPlatform;
}
var processArgumentBuilder = new ProcessArgumentBuilder();
processArgumentBuilder.Append("--build");
processArgumentBuilder.Append(Paths.Normalize(outputPathWithPlatformAndConfig).Quote());
if (!string.IsNullOrEmpty(target))
{
processArgumentBuilder.Append("--target");
processArgumentBuilder.Append(target);
}
if (!generator_name.EndsWith("Makefiles"))
{
processArgumentBuilder.Append("--config");
processArgumentBuilder.Append(config);
}
var processSettings = new ProcessSettings();
processSettings.Arguments = processArgumentBuilder;
processSettings.Timeout = (int)((new TimeSpan(0, 2, 0)).TotalMilliseconds);
processSettings.WorkingDirectory = outputPathWithPlatformAndConfig;
//
Information($"Platform - '{platform}', target - '{target}', config - '{config}' at '{outputPathWithPlatformAndConfig}'.");
var exitCode = StartProcess(Paths.Normalize(Paths.paths.cmake_exe), processSettings);
if (0 != exitCode)
{
throw new CakeException($"Build of '{outputPathWithPlatformAndConfig}' was failed.");
}
if (generator_name.EndsWith("Makefiles"))
{
Paths.paths.bin_paths.Add(outputPathWithPlatformAndConfig);
}
else
{
Paths.paths.bin_paths.Add(outputPathWithPlatformAndConfig.Combine(config));
}
}
}
}
});
Task("glew_generator_app")
.IsDependentOn("make_binaries")
.IsDependentOn("git_extractor")
.Does(context =>
{
foreach (var version in array_with_versions)
{
var str_ver = Versions.ToString(version);
//
var glew_dir = Paths.paths.repositories.Combine($"glew_{str_ver}");
var glfixes_dir = glew_dir.Combine("auto").Combine("registry");
//
var glew_generator_arguments = new ProcessArgumentBuilder();
glew_generator_arguments.Append(Paths.Normalize(glew_dir).Quote());
glew_generator_arguments.Append(Paths.Normalize(glfixes_dir).Quote()); //TODO: Will be removed for Versions.ver_2_2
if (Versions.ver_2_1 < version)
{
glew_generator_arguments.Append(Paths.Normalize(Paths.paths.open_gl_registry_dir).Quote());
glew_generator_arguments.Append(Paths.Normalize(Paths.paths.egl_registry_dir).Quote());
}
var output = Paths.paths.output.Combine(str_ver);
if (generator_name.StartsWith("Visual"))
{
output = output.Combine(generator_name.Replace(" ", "_"));
}
if (!Paths.paths.version_and_outputs.ContainsKey(version))
{
Paths.paths.version_and_outputs.Add(version, new SortedSet<DirectoryPath>(new PathComparer()));
}
foreach (var bin_path in Paths.paths.bin_paths)
{
var full_output = output;
if (2 < bin_path.Segments.Length)
{
for (var i = bin_path.Segments.Length - 2; i < bin_path.Segments.Length; ++i)
{
full_output = full_output.Combine(bin_path.Segments[i]);
}
}
EnsureDirectoryExists(full_output);
var arguments = ProcessArgumentBuilder.FromString(glew_generator_arguments.Render());
arguments.Append(Paths.Normalize(full_output).Quote());
var processSettings = new ProcessSettings();
processSettings.Timeout = (int)((new TimeSpan(0, 2, 0)).TotalMilliseconds);
processSettings.WorkingDirectory = bin_path;
var fullPath = System.IO.Path.Combine(bin_path.FullPath, "glew_generator_app");
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe");
}
fullPath = Paths.Normalize(fullPath);
processSettings.Arguments = arguments;
Information($"{fullPath} {processSettings.Arguments.Render()}");
var exitCode = StartProcess(fullPath, processSettings);
if (0 != exitCode)
{
throw new CakeException($"Run of '{fullPath}' was failed.");
}
Paths.paths.version_and_outputs[version].Add(full_output);
}
}
});
Task("tests_xml")
.IsDependentOn("make_binaries")
.WithCriteria(() => FileExists(Paths.paths.tests_xml))
.Does(context =>
{
var tests_xml_arguments = new ProcessArgumentBuilder();
tests_xml_arguments.Append($"--tests.xml={Paths.Normalize(Paths.paths.tests_xml).Quote()}");
if (!string.IsNullOrEmpty(test_filter))
{
tests_xml_arguments.Append($"--gtest_filter={test_filter.Quote()}");
}
foreach (var bin_path in Paths.paths.bin_paths)
{
var processSettings = new ProcessSettings();
processSettings.Timeout = (int)((new TimeSpan(0, 1, 0)).TotalMilliseconds);
processSettings.WorkingDirectory = bin_path;
//
var fullPath = System.IO.Path.Combine(bin_path.FullPath, "tests_xml");
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe");
}
fullPath = Paths.Normalize(fullPath);
processSettings.Arguments = tests_xml_arguments;
Information($"{fullPath} {processSettings.Arguments.Render()}");
var exitCode = StartProcess(fullPath, processSettings);
if (0 != exitCode)
{
throw new CakeException($"Run of '{fullPath}' was failed.");
}
}
});
Task("tests_xml_by_version")
.IsDependentOn("make_binaries")
.IsDependentOn("git_extractor")
.WithCriteria(() => FileExists(Paths.paths.tests_xml))
.Does(context =>
{
foreach (var version in array_with_versions)
{
var str_ver = Versions.ToString(version);
//
var tests_xml = Paths.paths.tests_xml.GetDirectory().CombineWithFilePath($"tests_{str_ver}.xml");
var glew_dir = Paths.paths.repositories.Combine($"glew_{str_ver}");
var glfixes_dir = glew_dir.Combine("auto").Combine("registry");
//
var tests_xml_arguments = new ProcessArgumentBuilder();
tests_xml_arguments.Append($"--tests.xml={Paths.Normalize(tests_xml).Quote()}");
tests_xml_arguments.Append($"--glew_path={Paths.Normalize(glew_dir).Quote()}");
tests_xml_arguments.Append($"--glfixes_path={Paths.Normalize(glfixes_dir).Quote()}");
if (!string.IsNullOrEmpty(test_filter))
{
tests_xml_arguments.Append($"--gtest_filter={test_filter.Quote()}");
}
foreach (var bin_path in Paths.paths.bin_paths)
{
var processSettings = new ProcessSettings();
processSettings.Timeout = (int)((new TimeSpan(0, 2, 0)).TotalMilliseconds);
processSettings.WorkingDirectory = bin_path;
//
var fullPath = System.IO.Path.Combine(bin_path.FullPath, "tests_xml_by_version");
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe");
}
fullPath = Paths.Normalize(fullPath);
processSettings.Arguments = tests_xml_arguments;
Information($"{fullPath} {processSettings.Arguments.Render()}");
var exitCode = StartProcess(fullPath, processSettings);
if (0 != exitCode)
{
throw new CakeException($"Run of '{fullPath}' was failed.");
}
}
}
});
Task("tests_parse_xml")
.IsDependentOn("make_binaries")
.IsDependentOn("git_extractor")
.WithCriteria(() => FileExists(Paths.paths.tests_xml))
.Does(context =>
{
//foreach (var version in array_with_versions)
{
var version = Versions.ver_2_2;
var str_ver = Versions.ToString(version);
var tests_parse_xml = Paths.paths.root.CombineWithFilePath($"tests_parse_xml_{str_ver}.xml");
if (!FileExists(tests_parse_xml))
{
return;
}
var tests_parse_xml_arguments = new ProcessArgumentBuilder();
tests_parse_xml_arguments.Append($"--tests.xml={Paths.Normalize(tests_parse_xml).Quote()}");
tests_parse_xml_arguments.Append($"--input.xml={Paths.Normalize(Paths.paths.egl_xml).Quote()}");
if (!string.IsNullOrEmpty(test_filter))
{
tests_parse_xml_arguments.Append($"--gtest_filter={test_filter.Quote()}");
}
foreach (var bin_path in Paths.paths.bin_paths)
{
var processSettings = new ProcessSettings();
processSettings.Timeout = (int)((new TimeSpan(0, 5, 0)).TotalMilliseconds);
processSettings.WorkingDirectory = bin_path;
foreach (var target in ((array_with_targets.Length == 0) ? new string[] { "tests_parse_xml" } : array_with_targets))
{
if (!target.StartsWith("tests_parse_xml"))
{
continue;
}
var fullPath = System.IO.Path.Combine(bin_path.FullPath, target);
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
fullPath = System.IO.Path.ChangeExtension(fullPath, ".exe");
}
fullPath = Paths.Normalize(fullPath);
processSettings.Arguments = tests_parse_xml_arguments;
Information($"{fullPath} {processSettings.Arguments.Render()}");
var exitCode = StartProcess(fullPath, processSettings);
if (0 != exitCode)
{
throw new CakeException($"Run of '{fullPath}' was failed.");
}
}
}
}
});
Task("reference_output")
.IsDependentOn("git_extractor")
.WithCriteria(() => ((PlatformID.Unix == Environment.OSVersion.Platform) && FileExists("/usr/bin/make")))
.Does(context =>
{
foreach (var version in array_with_versions)
{
if (Versions.ver_2_1 < version)
{
Warning($"Processing of version '{version}' not implemented in this task. Try to use version below or equal to the '{Versions.ver_2_1}'.");
continue;
}
if (!Paths.paths.version_and_outputs.ContainsKey(version))
{
Paths.paths.version_and_outputs.Add(version, new SortedSet<DirectoryPath>(new PathComparer()));
}
var str_ver = Versions.ToString(version);
//
var glew_dir = Paths.paths.repositories.Combine($"glew_{str_ver}");
var auto_dir = glew_dir.Combine("auto");
//
var file_list = new List<string>();
file_list.AddRange(System.IO.Directory.GetFiles(Paths.Normalize(auto_dir), "*.sh", System.IO.SearchOption.AllDirectories));
file_list.AddRange(System.IO.Directory.GetFiles(Paths.Normalize(auto_dir), "*.pl", System.IO.SearchOption.AllDirectories));
foreach (var script in file_list)
{
AddExecPermission(script, context);
}
var make_arguments = new ProcessArgumentBuilder();
//make_arguments.Append($"-C {auto_dir.Quote()}");
make_arguments.Append("--environment-overrides GIT_CLONE=@echo");
//
var processSettings = new ProcessSettings();
processSettings.Timeout = (int)((new TimeSpan(0, 5, 0)).TotalMilliseconds);
processSettings.WorkingDirectory = auto_dir;
processSettings.Arguments = make_arguments;
//
var fullPath = "/usr/bin/make";
Information($"{fullPath} {processSettings.Arguments.Render()}");
var exitCode = StartProcess(fullPath, processSettings);
if (0 != exitCode)
{
throw new CakeException($"Run of '{fullPath}' was failed.");
}
Paths.paths.version_and_outputs[version].Add(glew_dir);
}
});
Task("fix_ClangSharp.3.8.0")
.WithCriteria(() => (PlatformID.Win32NT == Environment.OSVersion.Platform))
.Does(()=>
{
var input_directory = Paths.paths.tools.Combine("Addins").Combine("ClangSharp.3.8.0").Combine("content");
if (Environment.Is64BitOperatingSystem)
{
input_directory = input_directory.Combine("x64");
}
else
{
input_directory = input_directory.Combine("x86");
}
var value = Environment.GetEnvironmentVariable("PATH");
value += $";{input_directory}";
Environment.SetEnvironmentVariable("PATH", value);
value = Environment.GetEnvironmentVariable("PATH");
});
Task("analyze_sources")
.IsDependentOn("reference_output")
.IsDependentOn("glew_generator_app")
.IsDependentOn("fix_ClangSharp.3.8.0")
.Does(()=>
{
foreach (var version_and_outputs in Paths.paths.version_and_outputs)
{
var str_ver = Versions.ToString(version_and_outputs.Key);
var files = new SameFileNameStorage();
foreach (var path in version_and_outputs.Value)
{
files.Add(System.IO.Directory.GetFiles(path.FullPath, "*.*", System.IO.SearchOption.AllDirectories));
}
if (PlatformID.Win32NT == Environment.OSVersion.Platform)
{
var path = Paths.Normalize(Paths.paths.reference.Combine($"glew_{str_ver}"));
files.Add(System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories));
}
foreach (var file in files)
{
var fileExtension = file.GetExtension();
if (fileExtension != ".c" && fileExtension != ".h")
{
continue;
}
if (PlatformID.Win32NT != Environment.OSVersion.Platform)
{
if (!file.FullPath.StartsWith(Paths.paths.output.FullPath))
{
var reference_output = Paths.paths.reference;
if (3 < file.Segments.Length)
{
for (var i = file.Segments.Length - 4; i < file.Segments.Length - 1; ++i)
{
if ("repositories" == file.Segments[i])
{
continue;
}
reference_output = reference_output.Combine(file.Segments[i]);
}
}
EnsureDirectoryExists(reference_output);
var reference_file_name = reference_output.CombineWithFilePath(file.GetFilename());
Information($"Reference file - '{file}'.");
CopyFile(file, reference_file_name);
}
continue;
}
var analyze = GetLexicalAnalyze(file.FullPath);
var outputFile = file.ChangeExtension($"{file.GetExtension()}.txt");
//
Information($"Analyze of '{file}' will be saved at '{outputFile}'.");
System.IO.File.WriteAllText(outputFile.FullPath, analyze);
}
}
});
Task("Default")
.IsDependentOn("clean")
.IsDependentOn("tests_xml")
.IsDependentOn("tests_xml_by_version")
.IsDependentOn("tests_parse_xml")
.IsDependentOn("analyze_sources");
//////////////////////////////////////////////////////////////////////
// EXECUTION
//////////////////////////////////////////////////////////////////////
RunTarget(target);
<?xml version="1.0" encoding="utf-8"?>
<!--
##########################################################################
# This is the Cake bootstrapper script for MSBuild environment.
# This file was downloaded from https://github.com/cake-build/resources (at current time under review https://github.com/cake-build/resources/pull/67 )
# Feel free to change this file to fit your needs.
##########################################################################
-->
<Project DefaultTargets="Bootstrap" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CakeId Condition="'$(MSBuildRuntimeType)'=='Full'">Cake</CakeId>
<CakeId Condition="'$(MSBuildRuntimeType)'=='Core'">Cake.CoreCLR</CakeId>
<CakeVersion>0.32.1</CakeVersion>
</PropertyGroup>
<ItemGroup Condition="'$(ForceDownloaPackagesConfig)'==''">
<packages_config Include="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>" />
<packages_config Include="&lt;packages>" />
<packages_config Include=" &lt;package id=&quot;$(CakeId)&quot; version=&quot;$(CakeVersion)&quot; />" />
<packages_config Include="&lt;/packages>" />
</ItemGroup>
<PropertyGroup Condition="'$(ForceDownloadNuGetFile)'==''">
<NuGetVersion>4.9.4</NuGetVersion>
</PropertyGroup>
<PropertyGroup>
<NuGetCommandArguments></NuGetCommandArguments>
<NuGet_ConfigFile></NuGet_ConfigFile>
</PropertyGroup>
<PropertyGroup Label="Define directories">
<SCRIPT_DIR>$(MSBuildThisFileDirectory)</SCRIPT_DIR>
<TOOLS_DIR>$([System.IO.Path]::Combine($(SCRIPT_DIR), tools))</TOOLS_DIR>
<ADDINS_DIR>$([System.IO.Path]::Combine($(TOOLS_DIR), Addins))</ADDINS_DIR>
<MODULES_DIR>$([System.IO.Path]::Combine($(TOOLS_DIR), Modules))</MODULES_DIR>
<NUGET_EXE>$([System.IO.Path]::Combine($(TOOLS_DIR), nuget.exe))</NUGET_EXE>
<CAKE_EXE Condition="'$(CakeId)'=='Cake'">$([System.IO.Path]::Combine($(TOOLS_DIR), Cake, Cake.exe))</CAKE_EXE>
<CAKE_EXE Condition="'$(CakeId)'=='Cake.CoreCLR'">$([System.IO.Path]::Combine($(TOOLS_DIR), Cake.CoreCLR, Cake.dll))</CAKE_EXE>
<PACKAGES_CONFIG>$([System.IO.Path]::Combine($(TOOLS_DIR), packages.config))</PACKAGES_CONFIG>
<PACKAGES_CONFIG_MD5>$([System.IO.Path]::Combine($(TOOLS_DIR), packages.config.md5sum))</PACKAGES_CONFIG_MD5>
<ADDINS_PACKAGES_CONFIG>$([System.IO.Path]::Combine($(ADDINS_DIR), packages.config))</ADDINS_PACKAGES_CONFIG>
<MODULES_PACKAGES_CONFIG>$([System.IO.Path]::Combine($(MODULES_DIR), packages.config))</MODULES_PACKAGES_CONFIG>
</PropertyGroup>
<PropertyGroup Label="Define default arguments">
<SCRIPT>build.cake</SCRIPT>
<SCRIPT_FULL_PATH>$([System.IO.Path]::Combine($(SCRIPT_DIR), $(SCRIPT)))</SCRIPT_FULL_PATH>
<CAKE_ARGUMENTS></CAKE_ARGUMENTS>
</PropertyGroup>
<!-- Define md5 -->
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core'">
<NetCoreAppVersion>netcoreapp2.1</NetCoreAppVersion>
</PropertyGroup>
<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Full'">
<csproj Include="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>" />
<csproj Include="&lt;Project DefaultTargets=&quot;Build&quot; xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;>" />
</ItemGroup>
<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Core'">
<csproj Include="&lt;Project Sdk=&quot;Microsoft.NET.Sdk&quot;>" />
<csproj Include=" " />
<csproj Include=" &lt;PropertyGroup>" />
<csproj Include=" &lt;OutputType>Exe&lt;/OutputType>" />
<csproj Include=" &lt;TargetFramework>$(NetCoreAppVersion)&lt;/TargetFramework>" />
<csproj Include=" &lt;/PropertyGroup>" />
<csproj Include=" " />
</ItemGroup>
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'=='' And '$(MSBuildRuntimeType)'=='Full'">
<csproj Include=" &lt;Import Project=&quot;$(MSBuildBinPath)\Microsoft.Common.CurrentVersion.targets&quot; />" />
</ItemGroup>
<!-- Cake.Bakery -Version 0.3.0 / 0.2.0 / 0.1.2 / 0.1.1 / 0.1.0 -->
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'==''">
<csproj Include=" &lt;ItemGroup>" />
<csproj Include=" &lt;PackageReference Include=&quot;NuGet.CommandLine&quot; Version=&quot;$(NuGetVersion)&quot; />" />
<csproj Include=" &lt;/ItemGroup>" />
</ItemGroup>
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'=='' And '$(MSBuildRuntimeType)'=='Full'">
<csproj Include=" &lt;Target Name=&quot;Build&quot; DependsOnTargets=&quot;Restore&quot;>" />
</ItemGroup>
<ItemGroup Condition="'$(ForceDownloadNuGetFile)'!='' And '$(MSBuildRuntimeType)'=='Full'">
<csproj Include=" &lt;Target Name=&quot;Build&quot;>" />
</ItemGroup>
<ItemGroup Condition="'$(MSBuildRuntimeType)'=='Full'">
<csproj Include=" &lt;Csc" />
<csproj Include=" Sources=&quot;$([System.IO.Path]::Combine($(SCRIPT_DIR), tools, MD5HashFile.cs))&quot;" />
<csproj Include=" OutputAssembly=&quot;$([System.IO.Path]::Combine($(SCRIPT_DIR), tools, MD5HashFile.exe))&quot; />" />
<csproj Include=" &lt;/Target> "/>
</ItemGroup>
<ItemGroup>
<csproj Include="&lt;/Project>" />
</ItemGroup>
<ItemGroup>
<cs Include="using System%3b" />
<cs Include="using System.IO%3b" />
<cs Include=" " />
<cs Include="namespace ConsoleApplication" />
<cs Include="{" />
<cs Include=" class Program" />
<cs Include=" {" />
<cs Include=" public static string MD5HashFile(string filePath)" />
<cs Include=" {" />
<cs Include=" if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))" />
<cs Include=" {" />
<cs Include=" return string.Empty%3b" />
<cs Include=" }" />
<cs Include=" " />
<cs Include=" using (var md5 = System.Security.Cryptography.MD5.Create())" />
<cs Include=" {" />
<cs Include=" using (var file = File.OpenRead(filePath))" />
<cs Include=" {" />
<cs Include=" return BitConverter.ToString(md5.ComputeHash(file))%3b" />
<cs Include=" }" />
<cs Include=" }" />
<cs Include=" }" />
<cs Include=" " />
<cs Include=" public static void SaveContents(string filePath, string contents)" />
<cs Include=" {" />
<cs Include=" if (string.IsNullOrEmpty(filePath))" />
<cs Include=" {" />
<cs Include=" return%3b" />
<cs Include=" }" />
<cs Include=" " />
<cs Include=" File.WriteAllText(filePath, contents)%3b" />
<cs Include=" }" />
<cs Include=" " />
<cs Include=" public static void Main(string[] args)" />
<cs Include=" {" />
<cs Include=" if (2 == args.Length) SaveContents(args[1], MD5HashFile(args[0]))%3b" />
<cs Include=" }" />
<cs Include=" }" />
<cs Include="}" />
</ItemGroup>
<PropertyGroup Label="MD5HashFile Project">
<MD5HashFile_cs>$([System.IO.Path]::Combine($(TOOLS_DIR), MD5HashFile.cs))</MD5HashFile_cs>
<MD5HashFile_csproj>$([System.IO.Path]::Combine($(TOOLS_DIR), MD5HashFile.csproj))</MD5HashFile_csproj>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Full'">
<MD5_Binary>$([System.IO.Path]::Combine($(TOOLS_DIR), MD5HashFile.exe))</MD5_Binary>
<MD5>&quot;$(MD5_Binary)&quot;</MD5>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core'">
<BuildTool Condition="Exists('$(DOTNET_HOST_PATH)')">$(DOTNET_HOST_PATH)</BuildTool>
<MD5_Binary>$([System.IO.Path]::Combine($(TOOLS_DIR), bin, Release, $(NetCoreAppVersion), MD5HashFile.dll))</MD5_Binary>
<MD5>&quot;$(BuildTool)&quot; &quot;$(MD5_Binary)&quot;</MD5>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core' And '$(OS)'=='Unix'">
<UnixExecutor>mono</UnixExecutor>
</PropertyGroup>
<PropertyGroup>
<Verbosity>-verbosity=</Verbosity>
</PropertyGroup>
<Target Name="ValidateVerbosity" Condition="$(CAKE_ARGUMENTS.Contains('$(Verbosity)'))">
<PropertyGroup>
<Length>$(Verbosity.Length)</Length>
<Index>$(CAKE_ARGUMENTS.IndexOf('$(Verbosity)'))</Index>
<Index>$([MSBuild]::Add($(Index), $(Length)))</Index>
<IndexOfSpace>$(CAKE_ARGUMENTS.IndexOf(' ', $(Index)))</IndexOfSpace>
<Length Condition="'$(IndexOfSpace)'!='-1'">$([MSBuild]::Subtract($(IndexOfSpace), $(Index)))</Length>
<VerbosityValue Condition="'$(IndexOfSpace)'!='-1'">$(CAKE_ARGUMENTS.Substring($(Index), $(Length)))</VerbosityValue>
<VerbosityValue Condition="'$(IndexOfSpace)'=='-1'">$(CAKE_ARGUMENTS.Substring($(Index)))</VerbosityValue>
</PropertyGroup>
<Error
Text="'$(Verbosity)' can be set to one of the following values: 'Quiet', 'Minimal', 'Normal', 'Verbose' or 'Diagnostic'. Instead it equal to the '$(VerbosityValue)'."
Condition="'$(VerbosityValue)'!='Quiet' And '$(VerbosityValue)'!='Minimal' And '$(VerbosityValue)'!='Normal' And '$(VerbosityValue)'!='Verbose' And '$(VerbosityValue)'!='Diagnostic'" />
</Target>
<Target Name="MD5Tool" Condition="!Exists('$(MD5_Binary)')">
<WriteLinesToFile
File="$(MD5HashFile_csproj)"
Lines="@(csproj)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<WriteLinesToFile
File="$(MD5HashFile_cs)"
Lines="@(cs)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<MSBuild
Condition="'$(MSBuildRuntimeType)'=='Full'"
BuildInParallel="true"
Projects="$(MD5HashFile_csproj)"
Properties="Configuration=Release;OutputPath=$(TOOLS_DIR)" />
<MSBuild
Condition="'$(MSBuildRuntimeType)'=='Core'"
BuildInParallel="true"
Projects="$(MD5HashFile_csproj)"
Targets="Restore;Build"
Properties="Configuration=Release" />
</Target>
<Import Project="$(MSBuildBinPath)\Microsoft.Common.CurrentVersion.targets" Condition="'$(MSBuildRuntimeType)'=='Full'"/>
<Import Project="$(MSBuildToolsPath)/NuGet.targets" Condition="'$(MSBuildRuntimeType)'=='Core'"/>
<Target Name="Bootstrap" DependsOnTargets="ValidateVerbosity">
<!-- Make sure the tools folder exist -->
<MakeDir
Condition="!Exists('$(TOOLS_DIR)')"
Directories="$(TOOLS_DIR)" />
<CallTarget Targets="MD5Tool" />
<Error
Text="Version of MSBuild should be 15.8 or above - instead it equal to the '$(MSBuildVersion)'."
Condition="$(MSBuildVersion) &lt; 15.8" />
<!-- Make sure that packages.config exist -->
<DownloadFile
Condition="!Exists('$(PACKAGES_CONFIG)') And '$(ForceDownloaPackagesConfig)'!=''"
SourceUrl="https://cakebuild.net/download/bootstrapper/packages"
DestinationFolder="$(TOOLS_DIR)">
<Output TaskParameter="DownloadedFile" PropertyName="DOWNLOADED_PACKAGES_CONFIG" />
</DownloadFile>
<Move
Condition="!Exists('$(PACKAGES_CONFIG)') And '$(ForceDownloaPackagesConfig)'!='' And Exists('$(DOWNLOADED_PACKAGES_CONFIG)') And '$(DOWNLOADED_PACKAGES_CONFIG)'!='$(PACKAGES_CONFIG)'"
SourceFiles="$(DOWNLOADED_PACKAGES_CONFIG)"
DestinationFiles="$(PACKAGES_CONFIG)" />
<WriteLinesToFile
Condition="!Exists('$(PACKAGES_CONFIG)') And '$(ForceDownloaPackagesConfig)'==''"
File="$(PACKAGES_CONFIG)"
Lines="@(packages_config)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<!-- Make sure that packages.config exist at this point -->
<Error
Text="Could not find packages.config at '$(PACKAGES_CONFIG)'."
Condition="!Exists('$(PACKAGES_CONFIG)')" />
<!-- Download NuGet if it does not exist -->
<DownloadFile
Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'!=''"
SourceUrl="https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
DestinationFolder="$(TOOLS_DIR)">
<Output TaskParameter="DownloadedFile" PropertyName="DOWNLOADED_NUGET_EXE" />
</DownloadFile>
<Move
Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'!='' And Exists('$(DOWNLOADED_NUGET_EXE)') And '$(DOWNLOADED_NUGET_EXE)'!='$(NUGET_EXE)'"
SourceFiles="$(DOWNLOADED_NUGET_EXE)"
DestinationFiles="$(NUGET_EXE)" />
<GetRestoreSettingsTask
Condition="'$(ForceDownloadNuGetFile)'==''"
ProjectUniqueName="$(MSBuildProjectFullPath)"
MSBuildStartupDirectory="$(MSBuildStartupDirectory)">
<Output
TaskParameter="OutputPackagesPath"
PropertyName="_OutputPackagesPath" />
</GetRestoreSettingsTask>
<PropertyGroup Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'==''">
<DOWNLOADED_NUGET_EXE>$([System.IO.Path]::Combine($(_OutputPackagesPath), nuget.commandline, $(NuGetVersion), tools, NuGet.exe))</DOWNLOADED_NUGET_EXE>
</PropertyGroup>
<Copy
Condition="!Exists('$(NUGET_EXE)') And '$(ForceDownloadNuGetFile)'=='' And Exists('$(DOWNLOADED_NUGET_EXE)') And '$(DOWNLOADED_NUGET_EXE)'!='$(NUGET_EXE)'"
SourceFiles="$(DOWNLOADED_NUGET_EXE)"
DestinationFiles="$(NUGET_EXE)" />
<ReadLinesFromFile
Condition="Exists('$(PACKAGES_CONFIG_MD5)')"
File="$(PACKAGES_CONFIG_MD5)">
<Output
TaskParameter="Lines"
ItemName="currentMd5Hash" />
</ReadLinesFromFile>
<Exec
Command="$(MD5) &quot;$(PACKAGES_CONFIG)&quot; &quot;$(PACKAGES_CONFIG_MD5)&quot;"
WorkingDirectory="$(TOOLS_DIR)" />
<ReadLinesFromFile
Condition="Exists('$(PACKAGES_CONFIG_MD5)')"
File="$(PACKAGES_CONFIG_MD5)">
<Output
TaskParameter="Lines"
ItemName="newMd5Hash" />
</ReadLinesFromFile>
<Message Condition="'@(currentMd5Hash)'!='@(newMd5Hash)'" Text="Missing or changed package.config hash..." />
<ItemGroup Condition="'@(currentMd5Hash)'!='@(newMd5Hash)'">
<AllFiles Include="$(TOOLS_DIR)\**" />
<AllFiles Remove="$(TOOLS_DIR)\bin\**" />
<AllFiles Remove="$(TOOLS_DIR)\obj\**" />
<AllFiles Remove="$(MD5HashFile_cs)" />
<AllFiles Remove="$(MD5HashFile_csproj)" />
<AllFiles Condition="'$(MSBuildRuntimeType)'=='Full'" Remove="$(MD5_Binary)" />
<AllFiles Remove="$(PACKAGES_CONFIG)" />
<AllFiles Remove="$(PACKAGES_CONFIG_MD5)" />
<AllFiles Remove="$(ADDINS_PACKAGES_CONFIG)" />
<AllFiles Remove="$(MODULES_PACKAGES_CONFIG)" />
<AllFiles Remove="$(NUGET_EXE)" />
<AllFiles Remove="$([System.IO.Path]::Combine($(TOOLS_DIR), Cake.Bakery))" />
</ItemGroup>
<Delete
Condition="'@(AllFiles)'!=''"
Files="@(AllFiles)"
TreatErrorsAsWarnings="true">
<Output
TaskParameter="DeletedFiles"
ItemName="DeletedFiles" />
</Delete>
<Message Condition="'@(DeletedFiles)'!='' And '@(DeletedFiles)'!='@(AllFiles)'" Text="Some files was not be deleted." />
<Message Condition="'@(currentMd5Hash)'!='@(newMd5Hash)'" Text="Restoring tools from NuGet..." />
<!-- Make sure that NuGet has been installed -->
<Error
Text="Could not find nuget.exe at '$(NUGET_EXE)'."
Condition="!Exists('$(NUGET_EXE)')" />
<Exec
Condition="'@(currentMd5Hash)'!='@(newMd5Hash)' And '$(OS)'!='Unix' And Exists('$(NUGET_EXE)')"
ContinueOnError="True"
Command="&quot;$(NUGET_EXE)&quot; install -ExcludeVersion -OutputDirectory &quot;$(TOOLS_DIR)&quot; $(NuGetCommandArguments)"
WorkingDirectory="$(TOOLS_DIR)">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Exec
Condition="'@(currentMd5Hash)'!='@(newMd5Hash)' And '$(OS)'=='Unix' And Exists('$(NUGET_EXE)')"
ContinueOnError="True"
Command="$(UnixExecutor) &quot;$(NUGET_EXE)&quot; install -ExcludeVersion -OutputDirectory &quot;$(TOOLS_DIR)&quot; $(NuGetCommandArguments)"
WorkingDirectory="$(TOOLS_DIR)">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<WriteLinesToFile
Condition="Exists('$(PACKAGES_CONFIG_MD5)') And '@(currentMd5Hash)'!='@(newMd5Hash)' And '$(ErrorCode)'!='0'"
File="$(PACKAGES_CONFIG_MD5)"
Lines="@(currentMd5Hash)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<Error
Text="Failed to restore tools from NuGet."
Condition="'@(currentMd5Hash)'!='@(newMd5Hash)' And '$(ErrorCode)'!='0'" />
<Message Condition="Exists('$(ADDINS_PACKAGES_CONFIG)')" Text="Restoring addins from NuGet..." />
<Exec
Condition="Exists('$(ADDINS_PACKAGES_CONFIG)') And '$(OS)'!='Unix' And Exists('$(NUGET_EXE)')"
Command="&quot;$(NUGET_EXE)&quot; install -ExcludeVersion -OutputDirectory &quot;$(ADDINS_DIR)&quot; $(NuGetCommandArguments)"
WorkingDirectory="$(TOOLS_DIR)" />
<Exec
Condition="Exists('$(ADDINS_PACKAGES_CONFIG)') And '$(OS)'=='Unix' And Exists('$(NUGET_EXE)')"
Command="$(UnixExecutor) &quot;$(NUGET_EXE)&quot; install -ExcludeVersion -OutputDirectory &quot;$(ADDINS_DIR)&quot; $(NuGetCommandArguments)"
WorkingDirectory="$(TOOLS_DIR)" />
<Message Condition="Exists('$(MODULES_PACKAGES_CONFIG)')" Text="Restoring modules from NuGet..." />
<Exec
Condition="Exists('$(MODULES_PACKAGES_CONFIG)') And '$(OS)'!='Unix' And Exists('$(NUGET_EXE)')"
Command="&quot;$(NUGET_EXE)&quot; install -ExcludeVersion -OutputDirectory &quot;$(MODULES_DIR)&quot; $(NuGetCommandArguments)"
WorkingDirectory="$(TOOLS_DIR)" />
<Exec
Condition="Exists('$(MODULES_PACKAGES_CONFIG)') And '$(OS)'=='Unix' And Exists('$(NUGET_EXE)')"
Command="$(UnixExecutor) &quot;$(NUGET_EXE)&quot; install -ExcludeVersion -OutputDirectory &quot;$(MODULES_DIR)&quot; $(NuGetCommandArguments)"
WorkingDirectory="$(TOOLS_DIR)" />
<!-- Make sure that Cake has been installed -->
<Error
Text="Could not find Cake.exe at '$(CAKE_EXE)'."
Condition="!Exists('$(CAKE_EXE)')" />
<PropertyGroup Condition="'$(OS)'!='Unix' And Exists('$(CAKE_EXE)') And Exists('$(SCRIPT_FULL_PATH)')">
<CakeCommand>&quot;$(CAKE_EXE)&quot; &quot;$(SCRIPT_FULL_PATH)&quot; $(CAKE_ARGUMENTS)</CakeCommand>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core' And '$(OS)'=='Unix' And Exists('$(CAKE_EXE)') And Exists('$(SCRIPT_FULL_PATH)') And '$(CakeId)'=='Cake'">
<CakeCommand>$(UnixExecutor) &quot;$(CAKE_EXE)&quot; &quot;$(SCRIPT_FULL_PATH)&quot; $(CAKE_ARGUMENTS)</CakeCommand>
</PropertyGroup>
<PropertyGroup Condition="'$(MSBuildRuntimeType)'=='Core' And '$(OS)'=='Unix' And Exists('$(CAKE_EXE)') And Exists('$(SCRIPT_FULL_PATH)') And '$(CakeId)'=='Cake.CoreCLR'">
<CakeCommand>$(BuildTool) &quot;$(CAKE_EXE)&quot; &quot;$(SCRIPT_FULL_PATH)&quot; $(CAKE_ARGUMENTS)</CakeCommand>
</PropertyGroup>
<PropertyGroup Condition="'$(NuGet_ConfigFile)'!=''">
<CakeCommand>$(CakeCommand) --NuGet_ConfigFile=&quot;$(NuGet_ConfigFile)&quot;</CakeCommand>
</PropertyGroup>
<!-- Start Cake -->
<Exec
Command="$(CakeCommand)"
WorkingDirectory="$(TOOLS_DIR)" />
</Target>
</Project>
cmake_minimum_required(VERSION 2.8.12)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "Configuration process cannot start from project source directory.")
endif()
project("glew_generator")
# glew_generator
add_library(glew_generator STATIC
"${CMAKE_SOURCE_DIR}/blacklist.cpp"
"${CMAKE_SOURCE_DIR}/blacklist.h"
"${CMAKE_SOURCE_DIR}/common.cpp"
"${CMAKE_SOURCE_DIR}/common.h"
"${CMAKE_SOURCE_DIR}/descriptor.cpp"
"${CMAKE_SOURCE_DIR}/descriptor.h"
"${CMAKE_SOURCE_DIR}/input_output.cpp"
"${CMAKE_SOURCE_DIR}/input_output.h"
"${CMAKE_SOURCE_DIR}/interpreter.cpp"
"${CMAKE_SOURCE_DIR}/interpreter.h"
"${CMAKE_SOURCE_DIR}/parse_xml.cpp"
"${CMAKE_SOURCE_DIR}/parse_xml.h"
"${CMAKE_SOURCE_DIR}/path.cpp"
"${CMAKE_SOURCE_DIR}/path.h"
"${CMAKE_SOURCE_DIR}/procedure.cpp"
"${CMAKE_SOURCE_DIR}/procedure.h"
"${CMAKE_SOURCE_DIR}/version.cpp"
"${CMAKE_SOURCE_DIR}/version.h")
# glew_generator_app
add_executable(glew_generator_app
"${CMAKE_SOURCE_DIR}/descriptors.cpp"
"${CMAKE_SOURCE_DIR}/descriptors.h"
"${CMAKE_SOURCE_DIR}/filler.cpp"
"${CMAKE_SOURCE_DIR}/filler.h"
"${CMAKE_SOURCE_DIR}/generator.cpp"
"${CMAKE_SOURCE_DIR}/generator.h"
"${CMAKE_SOURCE_DIR}/main.cpp")
target_link_libraries(glew_generator_app glew_generator)
if((NOT MSVC) AND (${CMAKE_VERSION} GREATER 3.0))
set_target_properties(glew_generator PROPERTIES CXX_STANDARD 11)
set_target_properties(glew_generator_app PROPERTIES CXX_STANDARD 11)
endif()
#
if(DEFINED ENV{PUGIXML_PATH})
string(REPLACE "\\" "/" pugixml_Path $ENV{PUGIXML_PATH})
elseif(DEFINED PUGIXML_PATH)
string(REPLACE "\\" "/" pugixml_Path ${PUGIXML_PATH})
else()
message(WARNING "PUGIXML_PATH not set. Targets that use pugixml will not be avaliable.")
endif()
if(pugixml_Path)
if (EXISTS ${pugixml_Path}/CMakeLists.txt)
add_subdirectory(${pugixml_Path} ${CMAKE_BINARY_DIR}/pugixml)
else()
add_subdirectory(${pugixml_Path}/scripts ${CMAKE_BINARY_DIR}/pugixml)
endif()
add_executable(glew_generator_xml_app
"${CMAKE_SOURCE_DIR}/descriptors.cpp"
"${CMAKE_SOURCE_DIR}/descriptors.h"
"${CMAKE_SOURCE_DIR}/filler.cpp"
"${CMAKE_SOURCE_DIR}/filler.h"
"${CMAKE_SOURCE_DIR}/generator.cpp"
"${CMAKE_SOURCE_DIR}/generator.h"
"${CMAKE_SOURCE_DIR}/main.cpp")
target_include_directories(glew_generator_xml_app SYSTEM PRIVATE ${pugixml_Path}/src)
target_link_libraries(glew_generator_xml_app glew_generator pugixml)
target_compile_definitions(glew_generator_xml_app PRIVATE PUGIXML)
if((NOT MSVC) AND (${CMAKE_VERSION} GREATER 3.0))
set_target_properties(glew_generator_xml_app PROPERTIES CXX_STANDARD 11)
endif()
endif()
if(MSVC)
set(FLAGS "${FLAGS} /W4 /GS")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFAULT_CMAKE_C_FLAGS} ${FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS}")
if(CMAKE_CL_64)
set(LINK_FLAGS "${LINK_FLAGS} /DynamicBase /NXCompat")
else()
set(LINK_FLAGS "${LINK_FLAGS} /SafeSEH /DynamicBase /NXCompat")
endif()
else()
set(FLAGS "${FLAGS} -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unknown-pragmas")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFAULT_CMAKE_C_FLAGS} ${FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFAULT_CMAKE_CXX_FLAGS} ${FLAGS}")
if(${CMAKE_VERSION} LESS 3.0)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
endif()
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "common.h"
#include <cctype>
#include <sstream>
#include <iterator>
void remove(std::string& string, char to_be_removed)
{
if (string.empty())
{
return;
}
auto match = string.size();
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match; i < count; ++i)
{
if (to_be_removed == string[i])
{
--match;
if (std::string::npos == current)
{
current = i;
}
continue;
}
if (std::string::npos != current && current != i)
{
string[current++] = string[i];
}
}
if (match != string.size())
{
string.resize(match);
}
}
void remove(std::string& string, const std::set<char>& to_be_removed)
{
if (string.empty() || to_be_removed.empty())
{
return;
}
auto match = string.size();
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match; i < count; ++i)
{
if (to_be_removed.count(string[i]))
{
--match;
if (std::string::npos == current)
{
current = i;
}
continue;
}
if (std::string::npos != current && current != i)
{
string[current++] = string[i];
}
}
if (match != string.size())
{
string.resize(match);
}
}
void remove(std::string& string, const std::string& to_be_removed)
{
if (string.empty() || to_be_removed.empty())
{
return;
}
auto match = string.size();
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match,
count_2 = to_be_removed.size(); i < count; ++i)
{
if (i + count_2 - 1 < count)
{
auto j = i;
bool isMatch = false;
for (const auto& ch : to_be_removed)
{
isMatch = (ch == string[j++]);
if (!isMatch)
{
break;
}
}
if (isMatch)
{
match -= count_2;
if (std::string::npos == current)
{
current = i;
}
i += count_2 - 1;
continue;
}
}
if (std::string::npos != current && current != i)
{
string[current++] = string[i];
}
}
if (match != string.size())
{
string.resize(match);
}
}
void replace_double_char_by_single(std::string& string, char to_be_replaced)
{
if (string.empty())
{
return;
}
auto match = string.size();
for (auto i = static_cast<std::size_t>(0), current = std::string::npos, count = match; i < count; ++i)
{
if (i + 1 < count && to_be_replaced == string[i + 1] && to_be_replaced == string[i])
{
--match;
if (std::string::npos == current)
{
current = i;
}
continue;
}
if (std::string::npos != current && current != i)
{
string[current++] = string[i];
}
}
if (match != string.size())
{
string.resize(match);
}
}
void replace(std::string& string, const std::string& to_be_replaced, const std::string& by_replacement)
{
const auto to_be_replaced_length = to_be_replaced.size();
const auto by_replacement_length = by_replacement.size();
auto previous_position = static_cast<std::size_t>(0);
auto current_position = previous_position;
if (to_be_replaced_length < by_replacement_length)
{
auto string_length = string.size();
const auto diff = by_replacement_length - to_be_replaced_length;
string.resize(string_length + string_length * diff);
while ((current_position = string.find(to_be_replaced, previous_position)) < string_length)
{
previous_position = current_position + by_replacement_length;
std::copy(string.cbegin() + current_position + to_be_replaced_length,
string.cbegin() + string_length,
string.begin() + previous_position);
std::copy(by_replacement.cbegin(), by_replacement.cend(), string.begin() + current_position);
string_length += diff;
}
string.resize(string_length);
}
else if (to_be_replaced_length == by_replacement_length)
{
while (std::string::npos != (current_position = string.find(to_be_replaced, previous_position)))
{
std::copy(by_replacement.cbegin(), by_replacement.cend(), string.begin() + current_position);
previous_position = current_position + to_be_replaced_length;
}
}
else
{
auto string_length = string.size();
const auto diff = to_be_replaced_length - by_replacement_length;
while (std::string::npos != (current_position = string.find(to_be_replaced, previous_position)))
{
std::copy(by_replacement.cbegin(), by_replacement.cend(), string.begin() + current_position);
previous_position = current_position + to_be_replaced_length;
if (string_length > previous_position)
{
std::copy(string.cbegin() + previous_position,
string.cbegin() + string_length,
string.begin() + current_position + by_replacement_length);
}
string_length -= diff;
string.resize(string_length);
}
}
}
void replace(std::string& string, char to_be_replaced, char by_replacement)
{
auto previous_position = static_cast<std::size_t>(0);
auto current_position = previous_position;
while (std::string::npos != (current_position = string.find(to_be_replaced, previous_position)))
{
string[current_position] = by_replacement;
previous_position = current_position + 1;
}
}
std::string::const_iterator find_phrase_start(const std::string& input, const char& value)
{
return std::find_if(input.cbegin(), input.cend(), [&value](const char& ch)
{
return ch == value;
});
}
std::string::const_iterator find_phrase_start(const
std::pair<std::string::const_iterator, std::string::const_iterator>& input, const char& value)
{
return std::find_if(std::get<0>(input), std::get<1>(input), [&value](const char& ch)
{
return ch == value;
});
}
template <class T>
std::list<std::string> split_T(const std::pair<std::string::const_iterator, std::string::const_iterator>&
input,
const std::set<T>& separators, bool do_not_add_empty_strings)
{
std::list<std::string> result;
std::set<std::string::const_iterator> offs;
for (const auto& separator : separators)
{
auto off = std::get<0>(input);
while (std::get<1>(input) != (off = find_phrase_start(std::make_pair(off, std::get<1>(input)), separator)))
{
offs.insert(off);
std::advance(off, 1);
}
}
if (offs.empty())
{
if (!do_not_add_empty_strings || std::get<0>(input) != std::get<1>(input))
{
result.push_back(std::string(std::get<0>(input), std::get<1>(input)));
}
}
else
{
auto prev_off = std::get<0>(input);
for (auto off = offs.cbegin(); off != offs.cend();)
{
if (!do_not_add_empty_strings || prev_off != (*off))
{
result.push_back(std::string(prev_off, (*off)));
}
prev_off = (*off);
do
{
std::advance(prev_off, 1);
off = offs.erase(off);
}
while (0 != offs.count(prev_off) && std::get<1>(input) != prev_off);
}
if (!do_not_add_empty_strings || prev_off != std::get<1>(input))
{
result.push_back(std::string(prev_off, std::get<1>(input)));
}
}
return result;
}
template <class T>
std::list<std::string> split_T(const std::string& input,
const std::set<T>& separators, bool do_not_add_empty_strings)
{
std::list<std::string> result;
std::set<std::size_t> offs;
for (const auto& separator : separators)
{
auto off = static_cast<std::size_t>(0);
while (std::string::npos != (off = input.find(separator, off)))
{
offs.insert(off);
++off;
}
}
if (offs.empty())
{
if (!do_not_add_empty_strings || !input.empty())
{
result.push_back(input);
}
}
else
{
auto prev_off = static_cast<std::size_t>(0);
for (auto off = offs.cbegin(); off != offs.cend();)
{
if (!do_not_add_empty_strings || prev_off != (*off))
{
result.push_back(input.substr(prev_off, (*off) - prev_off));
}
prev_off = (*off);
do
{
++prev_off;
off = offs.erase(off);
}
while (0 != offs.count(prev_off) && input.size() != prev_off);
}
if (!do_not_add_empty_strings || prev_off != input.size())
{
result.push_back(input.substr(prev_off, input.size() - prev_off));
}
}
return result;
}
template <class T>
std::list<std::string> split_T(const std::pair<std::string::const_iterator, std::string::const_iterator>&
input,
const T& separator, bool do_not_add_empty_strings)
{
std::list<std::string> result;
auto off = find_phrase_start(input, separator);
if (std::get<1>(input) == off)
{
if (!do_not_add_empty_strings || std::get<0>(input) != std::get<1>(input))
{
result.push_back(std::string(std::get<0>(input), std::get<1>(input)));
}
}
else
{
auto prev_off = std::get<0>(input);
do
{
if (!do_not_add_empty_strings || prev_off != off)
{
result.push_back(std::string(prev_off, off));
}
prev_off = off;
std::advance(prev_off, 1);
}
while (std::get<1>(input) != (off = find_phrase_start(std::make_pair(prev_off, std::get<1>(input)),
separator)));
if (!do_not_add_empty_strings || prev_off != std::get<1>(input))
{
result.push_back(std::string(prev_off, std::get<1>(input)));
}
}
return result;
}
template <class T>
std::list<std::string> split_T(const std::string& input, const T& separator,
bool do_not_add_empty_strings)
{
std::list<std::string> result;
auto off = input.find(separator);
if (std::string::npos == off)
{
if (!do_not_add_empty_strings || !input.empty())
{
result.push_back(input);
}
}
else
{
auto prev_off = static_cast<std::size_t>(0);
do
{
if (!do_not_add_empty_strings || prev_off != off)
{
result.push_back(input.substr(prev_off, off - prev_off));
}
prev_off = off + 1;
}
while (std::string::npos != (off = input.find(separator, prev_off)));
if (!do_not_add_empty_strings || prev_off != input.size())
{
result.push_back(input.substr(prev_off));
}
}
return result;
}
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::set<std::string>& separators, bool do_not_add_empty_strings)
{
return split_T(input, separators, do_not_add_empty_strings);
}
std::list<std::string> split(const std::string& input,
const std::set<std::string>& separators, bool do_not_add_empty_strings)
{
return split_T(input, separators, do_not_add_empty_strings);
}
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::string& separator, bool do_not_add_empty_strings)
{
return split_T(input, separator, do_not_add_empty_strings);
}
std::list<std::string> split(const std::string& input, const std::string& separator,
bool do_not_add_empty_strings)
{
return split_T(input, separator, do_not_add_empty_strings);
}
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::set<char>& separators, bool do_not_add_empty_strings)
{
return split_T(input, separators, do_not_add_empty_strings);
}
std::list<std::string> split(const std::string& input,
const std::set<char>& separators, bool do_not_add_empty_strings)
{
return split_T(input, separators, do_not_add_empty_strings);
}
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const char& separator, bool do_not_add_empty_strings)
{
return split_T(input, separator, do_not_add_empty_strings);
}
std::list<std::string> split(const std::string& input, const char& separator,
bool do_not_add_empty_strings)
{
return split_T(input, separator, do_not_add_empty_strings);
}
bool starts_with(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::string& value)
{
const auto input_size = static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input)));
if (value.empty())
{
return true;
}
if (input_size < value.size())
{
return false;
}
return 0 == std::memcmp(&(*std::get<0>(input)), value.c_str(), value.size());
}
bool starts_with(const std::string& input, const std::string& value)
{
if (value.empty())
{
return true;
}
if (value.size() > input.size())
{
return false;
}
return 0 == std::memcmp(input.c_str(), value.c_str(), value.size());
}
bool starts_with(const std::string& input, std::size_t position, const std::string& value)
{
if (value.empty())
{
return true;
}
if (input.size() < position || input.size() - position < value.size())
{
return false;
}
return 0 == std::memcmp(&input[position], value.c_str(), value.size());
}
bool ends_with(const std::string& input, const std::string& value)
{
if (value.empty())
{
return true;
}
if (value.size() > input.size())
{
return false;
}
return 0 == std::memcmp(&input[input.size() - value.size()], value.c_str(), value.size());
}
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::pair<std::string::const_iterator, std::string::const_iterator>& value)
{
if (std::get<0>(value) > std::get<1>(value))
{
return false;
}
if (std::get<0>(value) == std::get<1>(value))
{
return true;
}
if (!(std::get<0>(input) < std::get<1>(input)))
{
return false;
}
const auto input_size = static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input)));
const auto value_size = static_cast<std::size_t>(std::distance(std::get<0>(value), std::get<1>(value)));
if (value_size > input_size)
{
return false;
}
if (value_size == input_size)
{
return (0 == std::memcmp(&(*std::get<0>(input)), &(*std::get<0>(value)), value_size));
}
for (auto i = static_cast<std::size_t>(0);
i < 1 + input_size - value_size; ++i)
{
if (0 == std::memcmp(&(*std::get<0>(input)) + i, &(*std::get<0>(value)), value_size))
{
return true;
}
}
return false;
}
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::string& value)
{
if (value.empty())
{
return true;
}
if (!(std::get<0>(input) < std::get<1>(input)))
{
return false;
}
const auto input_size = static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input)));
const auto value_size = value.size();
if (value_size > input_size)
{
return false;
}
if (value_size == input_size)
{
return (0 == std::memcmp(&(*std::get<0>(input)), value.c_str(), value_size));
}
for (auto i = static_cast<std::size_t>(0);
i < 1 + input_size - value_size; ++i)
{
if (0 == std::memcmp(&(*std::get<0>(input)) + i, value.c_str(), value_size))
{
return true;
}
}
return false;
}
bool contains(const std::string& input, const std::string& value)
{
if (value.empty())
{
return true;
}
if (value.size() > input.size())
{
return false;
}
if (value.size() == input.size())
{
return (0 == std::memcmp(&input.front(), value.c_str(), value.size()));
}
for (auto i = static_cast<std::size_t>(0),
count = input.size(),
value_count = value.size();
i < 1 + count - value_count; ++i)
{
if (0 == std::memcmp(&input[i], value.c_str(), value_count))
{
return true;
}
}
return false;
}
void trim(std::string& string)
{
const auto chars_to_trim = std::set<char>({ '\0', '\t', ' ', '\n' });
//
const auto pos = std::find_if(string.cbegin(), string.cend(),
[&chars_to_trim](const char& ch)
{
return 0 == chars_to_trim.count(ch);
});
//
const auto rpos = std::find_if(string.crbegin(), string.crend(),
[&chars_to_trim](const char& ch)
{
return 0 == chars_to_trim.count(ch);
});
//
const auto start_from = static_cast<std::size_t>(std::distance(string.cbegin(), pos));
const auto finish_at = static_cast<std::size_t>(std::distance(string.crbegin(), rpos));
if (start_from > 0 || finish_at > 0)
{
auto count = static_cast<std::size_t>(0);
if (0 == start_from)
{
count = string.size() - finish_at;
}
else
{
for (auto i = start_from; i < string.size() - finish_at; ++i, ++count)
{
string[i - start_from] = string[i];
}
}
string.resize(count);
}
}
std::string join(const std::string& separator,
const std::list<std::pair<std::string::const_iterator, std::string::const_iterator>>& values)
{
if (values.empty())
{
return std::string();
}
auto value = values.cbegin();
if (1 == values.size())
{
return std::string(std::get<0>(*value), std::get<1>(*value));
}
std::ostringstream oss;
for (auto i = static_cast<std::size_t>(0), count = values.size() - 1; i < count; ++i, ++value)
{
oss << std::string(std::get<0>(*value), std::get<1>(*value)) << separator;
}
oss << std::string(std::get<0>(*value), std::get<1>(*value));
return oss.str();
}
std::string join(const std::string& separator, const std::list<std::string>& values)
{
if (values.empty())
{
return std::string();
}
auto value = values.cbegin();
if (1 == values.size())
{
return (*value);
}
std::ostringstream oss;
for (auto i = static_cast<std::size_t>(0), count = values.size() - 1; i < count; ++i, ++value)
{
oss << (*value) << separator;
}
oss << (*value);
return oss.str();
}
std::string tolower(const std::string& input)
{
std::string result(input.size(), '\0');
result.clear();
for (const auto& ch : input)
{
result.push_back(static_cast<char>(std::tolower(ch)));
}
return result;
}
std::string toupper(const std::string& input)
{
std::string result(input.size(), '\0');
result.clear();
for (const auto& ch : input)
{
result.push_back(static_cast<char>(std::toupper(ch)));
}
return result;
}
std::string::const_iterator find_phrase_start(const std::string& input, const std::string& value)
{
auto result = input.cbegin();
if (input.empty() || value.empty() || input.size() < value.size())
{
return input.cend();
}
do
{
result = std::find_if(result, input.cend(), [&value](const char& ch)
{
return ch == value.front();
});
if (result == input.cend())
{
break;
}
if (value.size() <= static_cast<std::size_t>(std::distance(result, input.cend())))
{
if (0 == std::memcmp(value.c_str(), &(*result), value.size()))
{
break;
}
}
std::advance(result, 1);
}
while (result != input.cend());
return result;
}
std::string::const_iterator find_phrase_start(const
std::pair<std::string::const_iterator, std::string::const_iterator>& input, const std::string& value)
{
auto result = std::get<0>(input);
if ((std::get<0>(input) == std::get<1>(input)) ||
value.empty() ||
static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))) < value.size())
{
return std::get<1>(input);
}
do
{
result = std::find_if(result, std::get<1>(input), [&value](const char& ch)
{
return ch == value.front();
});
if (result == std::get<1>(input))
{
break;
}
if (value.size() <= static_cast<std::size_t>(std::distance(result, std::get<1>(input))))
{
if (0 == std::memcmp(value.c_str(), &(*result), value.size()))
{
break;
}
}
std::advance(result, 1);
}
while (result != std::get<1>(input));
return result;
}
std::string::const_reverse_iterator rfind_phrase_start(
const std::pair<std::string::const_reverse_iterator, std::string::const_reverse_iterator>& input,
const std::string& value)
{
if ((std::get<0>(input) == std::get<1>(input)) ||
value.empty() ||
static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))) < value.size())
{
return std::get<1>(input);
}
auto result = std::get<0>(input);
std::advance(result, value.size() - 1);
do
{
if (0 == std::memcmp(value.c_str(), &(*result), value.size()))
{
break;
}
std::advance(result, 1);
}
while (result != std::get<1>(input));
return result;
}
std::pair<std::string::const_iterator, std::string::const_iterator> get_line(
const std::pair<std::string::const_iterator, std::string::const_iterator>& range,
std::string::const_iterator& next_line)
{
auto result = range;
//
std::get<1>(result) = std::find_if(std::get<0>(range), std::get<1>(range),
[](const char& ch)
{
return '\n' == ch;
});
//
next_line = std::get<1>(result);
if (std::get<1>(range) != next_line)
{
std::advance(next_line, 1);
}
return result;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#include <set>
#include <list>
#include <string>
#include <cstring>
#include <utility>
#include <algorithm>
void remove(std::string& string, char to_be_removed);
void remove(std::string& string, const std::set<char>& to_be_removed);
void remove(std::string& string, const std::string& to_be_removed);
void replace_double_char_by_single(std::string& string, char to_be_replaced);
void replace(std::string& string, const std::string& to_be_replaced, const std::string& by_replacement);
void replace(std::string& string, char to_be_replaced, char by_replacement);
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::set<std::string>& separators, bool do_not_add_empty_strings);
std::list<std::string> split(const std::string& input,
const std::set<std::string>& separators, bool do_not_add_empty_strings);
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::string& separator, bool do_not_add_empty_strings);
std::list<std::string> split(const std::string& input, const std::string& separator,
bool do_not_add_empty_strings);
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::set<char>& separators, bool do_not_add_empty_strings);
std::list<std::string> split(const std::string& input,
const std::set<char>& separators, bool do_not_add_empty_strings);
std::list<std::string> split(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const char& separator, bool do_not_add_empty_strings);
std::list<std::string> split(const std::string& input, const char& separator,
bool do_not_add_empty_strings);
bool starts_with(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::string& value);
bool starts_with(const std::string& input, const std::string& value);
bool starts_with(const std::string& input, std::size_t position, const std::string& value);
template <class T>
bool starts_with_T(const std::string& input, const T& value)
{
for (const auto& v : value)
{
if (starts_with(input, v))
{
return true;
}
}
return false;
}
bool ends_with(const std::string& input, const std::string& value);
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::pair<std::string::const_iterator, std::string::const_iterator>& value);
bool contains(const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
const std::string& value);
bool contains(const std::string& input, const std::string& value);
void trim(std::string& string);
std::string join(const std::string& separator,
const std::list<std::pair<std::string::const_iterator, std::string::const_iterator>>& values);
std::string join(const std::string& separator, const std::list<std::string>& values);
std::string tolower(const std::string& input);
std::string toupper(const std::string& input);
std::string::const_iterator find_phrase_start(const std::string& input, const std::string& value);
std::string::const_iterator find_phrase_start(
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, const std::string& value);
std::string::const_reverse_iterator rfind_phrase_start(
const std::pair<std::string::const_reverse_iterator, std::string::const_reverse_iterator>& input,
const std::string& value);
std::pair<std::string::const_iterator, std::string::const_iterator> get_line(
const std::pair<std::string::const_iterator, std::string::const_iterator>& range,
std::string::const_iterator& next_line);
template <class T>
T find_any_symbol_like_or_not_like_that(const std::pair<T, T>& input, const std::set<char>& that, bool like)
{
return std::find_if(std::get<0>(input), std::get<1>(input), [&that, &like](const char& ch)
{
return (like == (0 != that.count(ch)));
});
}
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "descriptor.h"
#include "input_output.h"
#include "path.h"
#include "common.h"
#include "blacklist.h"
#include "interpreter.h"
#include "procedure.h"
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iterator>
#include <algorithm>
enum class SECTION_TYPE
{
NAME = 1,
NAME_STRINGS,
PROCEDURES_AND_FUNCTIONS,
TYPES,
TOKENS,
UNKNOWN
};
static std::list<std::pair<std::string, std::string>> type_map;
static std::list<std::pair<std::string, std::string>> taboo_tokens;
static std::list<std::pair<std::string, std::string>> fnc_ignore_list;
bool init_typemap(std::istream& content_stream)
{
if (type_map.empty() && taboo_tokens.empty() && fnc_ignore_list.empty())
{
content_stream.seekg(0);
type_map = get_typemap(content_stream);
content_stream.seekg(0);
taboo_tokens = get_taboo_tokens(content_stream);
content_stream.seekg(0);
fnc_ignore_list = get_fnc_ignore_list(content_stream);
return true;
}
return false;
}
void release_typemap()
{
type_map.clear();
taboo_tokens.clear();
fnc_ignore_list.clear();
}
std::pair<std::string, std::pair<std::string, long>> str_to_token(
const std::string::const_iterator& token_begin,
const std::string::const_iterator& token_end)
{
auto token = std::make_pair(std::string(), std::make_pair(std::string(), static_cast<long>(0)));
auto space_position = std::find_if(token_begin, token_end, [](const char& ch)
{
return (ch == ' ' || ch == '\t');
});
if (space_position != token_end)
{
std::get<0>(token) = std::string(token_begin, space_position);
space_position = std::find_if(space_position, token_end, [](const char& ch)
{
return (ch != '=' && ch != ' ' && ch != '\t');
});
const auto value = std::string(space_position, token_end);
auto new_value = std::string(value.size(), '\0');
const char* start_ch = value.c_str();
char* ch = nullptr;
std::get<1>(std::get<1>(token)) = std::strtol(start_ch, &ch, 16);
if ((ch == start_ch) && std::isdigit(*start_ch))
{
new_value.clear();
do
{
new_value += (*start_ch);
++start_ch;
}
while (std::isdigit(*start_ch) && new_value.size() < value.size());
start_ch = new_value.c_str();
std::get<1>(std::get<1>(token)) = std::strtol(start_ch, &ch, 16);
}
const std::size_t str_size = ch - start_ch;
if (0 < str_size)
{
std::get<0>(std::get<1>(token)) = std::string(start_ch, str_size);
}
else
{
std::get<0>(std::get<1>(token)) = value;
}
}
else
{
std::get<0>(token) = std::string(token_begin, token_end);
}
return token;
}
SECTION_TYPE determine_section_type(const std::string::const_iterator& name_begin,
const std::string::const_iterator& name_end)
{
switch (std::distance(name_begin, name_end))
{
case 4:
if (!std::memcmp(&(*name_begin), "Name", 4))
{
return SECTION_TYPE::NAME;
}
break;
case 9:
if (!std::memcmp(&(*name_begin), "New Types", 9))
{
return SECTION_TYPE::TYPES;
}
break;
case 10:
if (!std::memcmp(&(*name_begin), "New Tokens", 10))
{
return SECTION_TYPE::TOKENS;
}
break;
case 11:
if (!std::memcmp(&(*name_begin), "Name String", 11))
{
return SECTION_TYPE::NAME_STRINGS;
}
break;
case 12:
if (!std::memcmp(&(*name_begin), "Name Strings", 12))
{
return SECTION_TYPE::NAME_STRINGS;
}
break;
case 27:
if (!std::memcmp(&(*name_begin), "New Procedure and Functions", 27))
{
return SECTION_TYPE::PROCEDURES_AND_FUNCTIONS;
}
break;
case 28:
if (!std::memcmp(&(*name_begin), "New Procedures And Functions", 28)
|| !std::memcmp(&(*name_begin), "New Functions and Procedures", 28)
|| !std::memcmp(&(*name_begin), "New Procedures and Functions", 28))
{
return SECTION_TYPE::PROCEDURES_AND_FUNCTIONS;
}
break;
case 41:
if (!std::memcmp(&(*name_begin), "New Procedures, Functions and Structures:", 41))
{
return SECTION_TYPE::PROCEDURES_AND_FUNCTIONS;
}
break;
default:
break;
}
return SECTION_TYPE::UNKNOWN;
}
std::string::const_iterator get_section_start(const std::string& content,
const std::string::const_iterator& offset)
{
auto setction_start = offset;
while (content.cend() != setction_start)
{
setction_start = std::find_if(setction_start, content.cend(), [](const char& ch)
{
return ('A' <= ch && ch <= 'Z');
});
if (content.cend() == setction_start)
{
break;
}
if ((0 == std::distance(content.cbegin(), setction_start)) || (*(setction_start - 1)) == '\n')
{
break;
}
std::advance(setction_start, 1);
}
return setction_start;
}
#ifndef NDEBUG
std::string::const_iterator get_section(const std::string& content, SECTION_TYPE section_type)
{
auto offset = content.cbegin();
while (offset != content.cend())
{
offset = get_section_start(content, offset);
if (content.cend() == offset)
{
break;
}
const auto new_line = std::find_if(offset, content.cend(), [](const char& ch)
{
return '\n' == ch;
});
if (content.cend() == new_line)
{
return new_line;
}
if (section_type == determine_section_type(offset, new_line))
{
break;
}
offset = new_line;
}
return offset;
}
#endif
void get_name(const std::string::const_iterator& first,
const std::string::const_iterator& last,
std::string& name)
{
const auto section_begin = std::find_if(first, last, [](const char& ch)
{
return (ch != ' ' && ch != '\t' && ch != '\n');
});
if (section_begin == last)
{
return;
}
const auto section_end = std::find_if(section_begin, last, [](const char& ch)
{
return (ch == ' ' || ch == '\t' || ch == '\n');
});
//
std::copy(section_begin, (section_end != last) ? section_end : last, std::back_inserter(name));
}
void get_name_strings(const std::string::const_iterator& first,
const std::string::const_iterator& last,
std::list<std::string>& name_strings)
{
const auto section_begin = std::find_if(first, last, [](const char& ch)
{
return (ch != ' ' && ch != '\t' && ch != '\n');
});
if (section_begin == last)
{
return;
}
auto section_end = last;
while (section_end != section_begin)
{
const auto ch = (*section_end);
if (ch != ' ' && ch != '\t' && ch != '\n')
{
break;
}
std::advance(section_end, -1);
}
if (section_end == section_begin)
{
return;
}
auto section_text = std::string(section_begin, section_end);
auto character_position = section_text.find("none");
if (std::string::npos != character_position)
{
section_text = section_text.substr(0, character_position);
}
character_position = section_text.find("None");
if (std::string::npos != character_position)
{
section_text = section_text.substr(0, character_position);
}
character_position = section_text.find("NOTE");
if (std::string::npos != character_position)
{
section_text = section_text.substr(0, character_position);
}
character_position = section_text.find("Note");
if (std::string::npos != character_position)
{
section_text = section_text.substr(0, character_position);
}
character_position = section_text.find("(legacy)");
if (std::string::npos != character_position)
{
section_text = section_text.substr(0, character_position);
}
remove(section_text, std::set<char>({ '\t', ' ', '(' }));
name_strings = split(section_text, std::set<char>({ '\n', ',' }), true);
}
std::pair<std::string::const_iterator, std::string::const_iterator> get_function_name(
const std::set<char>& white_space,
const std::string::const_iterator& return_start,
const std::string::const_iterator& function_start)
{
auto function_name = std::make_pair(return_start, function_start);
while (std::get<1>(function_name) != return_start)
{
std::advance(std::get<1>(function_name), -1);
if (0 == white_space.count(*std::get<1>(function_name)))
{
std::advance(std::get<1>(function_name), +1);
break;
}
}
std::get<0>(function_name) = std::get<1>(function_name);
while (std::get<0>(function_name) != return_start)
{
std::advance(std::get<0>(function_name), -1);
if (0 != white_space.count(*std::get<0>(function_name)))
{
std::advance(std::get<0>(function_name), +1);
break;
}
}
return function_name;
}
bool is_function_end_correct(
const std::string::const_iterator& function_start,
const std::string::const_iterator& function_end)
{
if (')' == (*function_end))
{
return true;
}
auto position = function_end;
while (position != function_start)
{
std::advance(position, -1);
if (')' == (*position))
{
break;
}
else if (std::isdigit(*position) ||
('a' <= (*position) && (*position) <= 'z') ||
('A' <= (*position) && (*position) <= 'Z'))
{
return false;
}
}
return true;
}
void get_procedures_functions(const std::string::const_iterator& first,
const std::string::const_iterator& last,
const char function_should_start_from,
std::list<_procedure>& procedures)
{
const auto tab_space_new_line = std::set<char>({ '\t', ' ', '\n' });
const auto chars_at_line_end = std::set<char>({ '\n', '/', ';' });
const auto chars_not_for_procedure = std::set<char>({ '"', '&', '/', ':', ';', '<', '=', '>' });
for (auto position = first; position != last;)
{
auto function_start = std::find_if(position, last, [&function_should_start_from](const char& ch)
{
return function_should_start_from == ch;
});
if (function_start != last)
{
auto return_start = function_start;
auto is_only_white_space = true;
do
{
std::advance(return_start, -1);
if (is_only_white_space)
{
is_only_white_space = (0 != tab_space_new_line.count(*return_start));
}
}
while ((is_only_white_space && position != return_start) ||
('\n' != (*return_start) && position != return_start));
return_start = std::find_if(return_start, function_start, [&tab_space_new_line](const char& ch)
{
return 0 == tab_space_new_line.count(ch);
});
if ('*' != (*return_start) && return_start != function_start)
{
auto function_end = std::find_if(function_start, last, [](const char& ch)
{
return ')' == ch;
});
const auto function_name = get_function_name(tab_space_new_line, return_start, function_start);
if (function_end != last && !std::isdigit(*(std::get<0>(function_name))))
{
const auto function_end_ = std::find_if(function_start, last, [](const char& ch)
{
return ';' == ch;
});
if (function_end_ != last && function_end_ < function_end)
{
function_end = function_end_;
}
auto line_end = std::find_if(function_end, last, [&chars_at_line_end](const char& ch)
{
return 0 != chars_at_line_end.count(ch);
});
if (line_end != last)
{
std::advance(line_end, -1);
function_end = line_end;
}
const auto find_result = std::find_if(return_start, function_end, [&chars_not_for_procedure](const char& ch)
{
return 0 != chars_not_for_procedure.count(ch);
});
if (find_result == function_end && 0 == chars_not_for_procedure.count(*function_end))
{
std::advance(function_end, 1);
auto opened = 0;
auto closed = 0;
for (auto p = return_start; p != function_end; ++p)
{
if (function_should_start_from == (*p))
{
++opened;
}
else if (')' == (*p))
{
++closed;
}
}
if ((function_end_ <= function_end) || (opened == closed &&
is_function_end_correct(function_start, function_end)))
{
if (1 == opened && std::get<0>(function_name) == return_start &&
contains(std::make_pair(function_start, function_end), "*"))
{
for (auto i = 0; i < 2 && return_start != position; ++i)
{
do
{
std::advance(return_start, -1);
if ('\n' == (*return_start))
{
break;
}
}
while (return_start != position);
}
return_start = std::find_if(return_start, std::get<0>(function_name), [&tab_space_new_line](const char& ch)
{
return 0 == tab_space_new_line.count(ch);
});
}
std::string procedure(std::distance(return_start, function_end), '\0');
procedure.clear();
for (auto p = return_start; p != function_end; ++p)
{
if ('\t' != (*p) && '\n' != (*p))
{
if (procedure.empty() && ' ' == (*p))
{
continue;
}
else if (' ' == (*p) && !procedure.empty() && (' ' == procedure[procedure.size() - 1] ||
'(' == procedure[procedure.size() - 1]))
{
continue;
}
else if (' ' == (*p) && p + 1 != function_end && ')' == *(p + 1))
{
continue;
}
procedure += (*p);
if (contains(procedure, "(") && p + 1 != function_end && ',' == procedure.back() && ' ' != *(p + 1))
{
procedure += ' ';
}
}
}
if (!procedure.empty())
{
const auto procedure_ = disassemble_procedure(procedure);
if (!procedure_.name.empty())
{
const auto exists_procedure = std::find_if(procedures.cbegin(), procedures.cend(),
[&procedure_](const _procedure & _procedure)
{
return procedure_ == _procedure;
});
if (exists_procedure == procedures.cend())
{
procedures.push_back(procedure_);
}
}
}
}
}
else
{
std::advance(function_end, 1);
}
}
position = function_end;
}
else
{
position = function_start;
std::advance(position, 1);
}
}
else
{
break;
}
}
}
void get_procedures_functions_structures_types(const std::string::const_iterator& first,
const std::string::const_iterator& last,
specification& spec, SECTION_TYPE section_type)
{
auto prev_border = first;
for (auto i = first; i < last; ++i)
{
auto new_line = std::find_if(i, last, [](const char& ch)
{
return '\n' == ch;
});
if (last != new_line)
{
std::advance(new_line, 1);
auto next_line = std::find_if(new_line, last, [](const char& ch)
{
return '\n' == ch;
});
if (last != next_line)
{
auto is_border = true;
for (auto j = new_line; j < next_line; j++)
{
const auto ch = (*j);
if (ch != ' ' && ch != '\t' && ch != '\n')
{
is_border = false;
break;
}
}
if (is_border)
{
i = next_line;
prev_border = std::find_if(prev_border, next_line, [](const char& ch)
{
return ch != ' ' && ch != '\t' && ch != '\n';
});
if (prev_border == next_line)
{
continue;
}
while (next_line != prev_border)
{
const auto ch = (*next_line);
if (ch != ' ' && ch != '\t' && ch != '\n')
{
std::advance(next_line, 1);
break;
}
std::advance(next_line, -1);
}
if (prev_border == next_line)
{
continue;
}
auto procedures_or_types = split(std::string(prev_border, next_line), ';', true);
prev_border = i;
if (!procedures_or_types.empty() && (starts_with(procedures_or_types.front(), "None") ||
starts_with(procedures_or_types.front(), "none") ||
starts_with(procedures_or_types.front(), "(None") ||
starts_with(procedures_or_types.front(), "NOTE:")))
{
continue;
}
auto enough = false;
while (!enough)
{
for (auto& pot : procedures_or_types)
{
replace(pot, '\t', ' ');
replace(pot, '\n', ' ');
replace_double_char_by_single(pot, ' ');
trim(pot);
auto sub_pot = split(pot, ") ", true);
if (sub_pot.size() > 1)
{
procedures_or_types.remove(pot);
for (auto& spot : sub_pot)
{
if (!spot.empty() && spot[spot.size() - 1] != ')')
{
spot += ')';
}
trim(spot);
}
std::copy(sub_pot.cbegin(), sub_pot.cend(), std::back_inserter(procedures_or_types));
enough = true;
break;
}
}
enough = !enough;
}
procedures_or_types.remove_if([&section_type](const std::string & pot)
{
return pot.empty() || starts_with(pot, "<") ||
((SECTION_TYPE::PROCEDURES_AND_FUNCTIONS == section_type) &&
(!contains(pot, "(") || !contains(pot, ")") ||
contains(pot, "\"") || contains(pot, "(if any)") ||
(!contains(pot, "...") && contains(pot, "."))));
});
if (SECTION_TYPE::PROCEDURES_AND_FUNCTIONS == section_type)
{
//spec._procedures.insert(spec._procedures.end(), procedures_or_types.cbegin(), procedures_or_types.cend());
}
else if (SECTION_TYPE::TYPES == section_type)
{
spec._types.insert(spec._types.end(), procedures_or_types.cbegin(), procedures_or_types.cend());
}
}
}
}
}
}
void get_tokens(const std::string::const_iterator& first,
const std::string::const_iterator& last,
specification& spec)
{
for (auto i = first; i < last; ++i)
{
auto line_begin = std::find_if(i, last, [](const char& ch)
{
return (ch == '\n');
});
if (line_begin == last)
{
break;
}
std::advance(line_begin, 1);
auto line_end = line_begin;
line_end = std::find_if(line_end, last, [](const char& ch)
{
return (ch == '\n' || ch == '(' || ch == '/');
});
i = line_end;
std::advance(i, -1);
auto token_begin = std::find_if(line_begin, line_end, [](const char& ch)
{
return std::isupper(ch) || std::isdigit(ch);
});
if (token_begin == line_end)
{
continue;
}
auto token_begin_ = token_begin;
std::advance(token_begin_, -1);
if (std::isdigit(*token_begin_))
{
token_begin = token_begin_;
}
auto token_end = std::find_if(line_begin, token_begin, [](const char& ch)
{
return (ch != ' ' && ch != '\t');
});
if (token_end != token_begin)
{
continue;
}
bool wrong_token = false;
for (; token_end != line_end; ++token_end)
{
char ch = *token_end;
if (!std::isupper(ch) && ch != '_' &&
ch != ' ' && ch != '\t' &&
ch != '=' && !std::isdigit(ch) && ch != 'x' &&
ch != 'u' && ch != 'l')
{
wrong_token = true;
break;
}
}
if (wrong_token)
{
continue;
}
spec._tokens.push_back(str_to_token(token_begin, token_end));
}
}
void read_spec(const std::string& content, bool read_types, specification& spec)
{
for (auto section_start = content.cbegin(); section_start != content.cend();)
{
section_start = get_section_start(content, section_start);
if (content.cend() == section_start)
{
break;
}
auto new_line = std::find_if(section_start, content.cend(), [](const char& ch)
{
return '\n' == ch;
});
if (content.cend() == new_line)
{
break;
}
auto next_section_start = get_section_start(content, new_line);
while (new_line != section_start)
{
const auto ch = (*new_line);
if (ch != ' ' && ch != '\t' && ch != '\n')
{
std::advance(new_line, 1);
break;
}
std::advance(new_line, -1);
}
switch (determine_section_type(section_start, new_line))
{
case SECTION_TYPE::NAME:
get_name(new_line, next_section_start, spec._name);
break;
case SECTION_TYPE::NAME_STRINGS:
get_name_strings(new_line, next_section_start, spec._name_strings);
break;
case SECTION_TYPE::PROCEDURES_AND_FUNCTIONS:
{
const auto next_section_start_ = std::find_if(new_line, next_section_start, [](const char& ch)
{
return '#' == ch;
});
//TODO:
get_procedures_functions(new_line, next_section_start_, '(', spec._procedures);
get_procedures_functions(new_line, next_section_start_, '{', spec._procedures);
//
spec._procedures.sort([](const _procedure & a, const _procedure & b)
{
return a.name < b.name;
});
}
break;
case SECTION_TYPE::TYPES:
if (read_types)
{
get_procedures_functions_structures_types(new_line, next_section_start, spec,
SECTION_TYPE::TYPES);
}
break;
case SECTION_TYPE::TOKENS:
get_tokens(new_line, next_section_start, spec);
prepare_tokens(spec._tokens); //TODO:
break;
default:
break;
}
section_start = next_section_start;
}
}
void read_ext(const std::string& content, extension& ext)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
auto start_position = content.cbegin();
auto line_begin = start_position;
char i = 0;
while (content.cend() != (start_position = find_any_symbol_like_or_not_like_that(
std::make_pair(start_position, content.cend()), tab_space, false)))
{
auto line_end = std::find_if(start_position, content.cend(), [](const char& ch)
{
return '\n' == ch;
});
switch (i)
{
case 0:
++i;
ext._name = std::string(start_position, line_end);
break;
case 1:
++i;
ext._url = std::string(start_position, line_end);
break;
case 2:
++i;
if (start_position != line_end)
{
ext._name_strings.push_back(std::string(start_position, line_end));
}
break;
case 3:
++i;
#if defined(__GNUC__) && 7 <= __GNUC__
#pragma message("Not implemented!")
break;
#else
if (!starts_with(std::make_pair(line_begin, line_end), "\t") &&
!starts_with(std::make_pair(line_begin, line_end), " "))
{
ext._reuse = split(
std::make_pair(start_position, line_end), std::set<char>({ '\t', ' ', ',' }), true);
break;
}
#endif
default:
if (start_position == line_end)
{
break;
}
if (contains(std::make_pair(start_position, line_end), "typedef"))
{
ext._types.push_back(std::string(start_position, line_end));
}
else if (contains(std::make_pair(start_position, line_end), "("))
{
const auto procedure = disassemble_procedure(std::make_pair(start_position, line_end));
if (contains(procedure.name, "[") && contains(procedure.name, "]"))
{
break;
}
if (!contains(procedure.return_type, "(") && !procedure.name.empty())
{
auto is_parameters_only_digital = false;
for (const auto& param : procedure.parameters)
{
for (const auto& ch : param)
{
if (' ' == ch || '\t' == ch)
{
continue;
}
is_parameters_only_digital = ('-' == ch || ('0' <= ch && ch <= '9'));
break;
}
if (is_parameters_only_digital)
{
break;
}
}
if (!is_parameters_only_digital)
{
ext._procedures.push_back(procedure);
}
}
else if (!procedure.parameters.empty())
{
ext._types.push_back(std::string(start_position, line_end));
}
}
else
{
ext._tokens.push_back(str_to_token(start_position, line_end));
}
break;
}
if (content.cend() != line_end)
{
std::advance(line_end, 1);
}
start_position = line_end;
line_begin = start_position;
}
ext._procedures.sort([](const _procedure & a, const _procedure & b)
{
return a.name < b.name;
});
//
ext._types.sort(); //TODO:
prepare_tokens(ext._tokens); //TODO:
}
bool is_procedure_should_be_ignored(const std::string& extension_name, const std::string& procedure_name)
{
assert(!fnc_ignore_list.empty());
//
const auto find_result = std::find_if(fnc_ignore_list.cbegin(), fnc_ignore_list.cend(),
[&procedure_name, &extension_name](const std::pair<std::string, std::string>& procedure_to_ignore)
{
return (procedure_name == std::get<0>(procedure_to_ignore) &&
extension_name != std::get<1>(procedure_to_ignore));
});
//
return fnc_ignore_list.cend() != find_result;
}
bool is_token_taboo(const std::pair<std::string, std::pair<std::string, long>>& token)
{
assert(!taboo_tokens.empty());
//
const auto find_result = std::find_if(taboo_tokens.cbegin(), taboo_tokens.cend(),
[&token](const std::pair<std::string, std::string>& taboo_token)
{
return (std::get<0>(token) == std::get<0>(taboo_token) &&
std::get<0>(std::get<1>(token)) == std::get<1>(taboo_token));
});
return taboo_tokens.cend() != find_result;
}
struct internal_extension
{
std::string _name_string;
std::string _prefix;
std::list<std::string> _tokens;
std::list<_procedure> _procedures;
};
std::list<std::pair<std::string, std::string>> specification_to_extensions(
const specification& spec, const std::string& url, std::string& tmp_output)
{
static const std::set<std::string> common_prefix({ /*"agl",*/ "gl", /*"glu",*/ "glX", "wgl" });
static const std::set<std::string> common_tprefix({ /*"AGL",*/ "GL", /*"GLU",*/ "GLX", "WGL" });
std::list<internal_extension> extensions_;
const auto name_strings = (spec._name_strings.empty() ? std::list<std::string>({ spec._name }) :
spec._name_strings);
for (const auto& name_string : name_strings)
{
if (name_string.empty())
{
continue;
}
internal_extension ext;
ext._name_string = name_string;
//
const auto prefix_end = std::find_if(name_string.cbegin(), name_string.cend(),
[](const char& ch)
{
return '_' == ch;
});
//
ext._prefix = std::string(name_string.cbegin(), prefix_end);
extensions_.push_back(ext);
}
std::list<std::string> not_used_tokens;
for (const auto& token : spec._tokens)
{
if (is_token_taboo(token))
{
continue;
}
const auto str_token = std::get<0>(token) + ' ' + std::get<0>(std::get<1>(token));
auto added = false;
for (auto& ext : extensions_)
{
if (ext._prefix.length() < std::get<0>(token).length() &&
std::get<0>(token)[ext._prefix.length()] == '_' &&
starts_with(std::get<0>(token), ext._prefix))
{
ext._tokens.push_back(str_token);
added = true;
}
}
if (!added)
{
not_used_tokens.push_back((*common_tprefix.cbegin()) + "_" + str_token);
}
}
if (1 == extensions_.size() &&
0 == common_tprefix.count(extensions_.front()._prefix))
{
extensions_.front()._prefix = (*common_tprefix.cbegin());
extensions_.front()._name_string = (*common_tprefix.cbegin()) + "_" + extensions_.front()._name_string;
}
for (const auto& str_token : not_used_tokens)
{
for (auto& ext : extensions_)
{
if ((*common_tprefix.cbegin()) == ext._prefix)
{
ext._tokens.push_back(str_token);
}
}
}
auto procedures = spec._procedures; //TODO: work direct with procedures from specification
for (auto& ext : extensions_)
{
for (auto& procedure : procedures)
{
if (is_procedure_template(procedure) || is_procedure_should_be_ignored(
((*common_tprefix.crbegin()) == ext._prefix ||
ext._name_string.size() <= ext._prefix.size()) ? ext._name_string : ext._name_string.substr(
ext._prefix.size() + 1),
procedure.name))
{
continue;
}
if (!starts_with_T(procedure.name, common_prefix))
{
procedure.name = (*common_prefix.cbegin()) + procedure.name;
}
if (starts_with(tolower(procedure.name), tolower(ext._prefix)))
{
ext._procedures.push_back(procedure);
}
}
}
for (auto& ext1 : extensions_)
{
for (auto& ext2 : extensions_)
{
if (ext1._prefix == ext2._prefix)
{
continue;
}
for (auto p1 = ext1._procedures.cbegin(); p1 != ext1._procedures.cend();)
{
auto step1 = false;
for (auto p2 = ext2._procedures.cbegin(); p1 != ext1._procedures.cend() && p2 != ext2._procedures.cend();)
{
if (p1->return_type == p2->return_type && p1->name == p2->name && p1->parameters == p2->parameters)
{
if (ext1._prefix.size() > ext2._prefix.size())
{
p2 = ext2._procedures.erase(p2);
}
else
{
p1 = ext1._procedures.erase(p1);
step1 = true;
}
}
else
{
++p2;
}
}
if (!step1)
{
++p1;
}
}
}
}
std::list<std::pair<std::string, std::string>> extensions;
for (const auto& ext : extensions_)
{
tmp_output.clear();
if (!ext._name_string.empty() && !url.empty())
{
tmp_output += ext._name_string + '\n';
tmp_output += url + '\n';
tmp_output += ext._name_string + '\n';
}
if (!ext._tokens.empty())
{
tmp_output += '\t' + join("\n\t", ext._tokens) + '\n';
}
for (auto procedure : ext._procedures)
{
if (ext._prefix == (*common_tprefix.cbegin()))
{
replace_parameters_type(type_map, procedure.return_type);
replace_parameters_type(type_map, procedure.parameters);
}
tmp_output += '\t' + procedure.return_type + ' ' + procedure.name +
" (" + join(", ", procedure.parameters) + ")\n";
}
extensions.push_back(std::make_pair(ext._name_string, tmp_output));
}
return extensions;
}
void prepare_tokens(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens)
{
tokens.remove_if([&tokens](const std::pair<std::string, std::pair<std::string, long>>& token)
{
for (const auto& _token : tokens)
{
if ((&_token) == (&token))
{
continue;
}
if (std::get<0>(_token) == std::get<0>(token) &&
((!(std::get<0>(std::get<1>(_token)).empty()) && std::get<0>(std::get<1>(token)).empty()) ||
(std::get<1>(std::get<1>(_token)) == std::get<1>(std::get<1>(token)))))
{
return true;
}
}
return false;
});
tokens.sort();
tokens.sort([](const std::pair<std::string, std::pair<std::string, long>>& token1,
const std::pair<std::string, std::pair<std::string, long>>& token2)
{
return std::get<1>(std::get<1>(token1)) < std::get<1>(std::get<1>(token2));
});
}
void prepare_tokens2(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens)
{
tokens.remove_if([](const std::pair<std::string, std::pair<std::string, long>>& token)
{
return (std::get<0>(std::get<1>(token)).empty() ||
contains(std::get<0>(std::get<1>(token)), "XXXX"));
});
}
std::list<std::pair<std::string, std::string>> update_ext(
std::list<std::string>& registry_list,
std::istream& blacklist,
std::istream& parse_spec,
std::string& tmp_output,
std::ostream& log)
{
std::list<std::pair<std::string, std::string>> extensions;
if (registry_list.empty())
{
return extensions;
}
registry_list.remove_if([](const std::string & file_path)
{
return !ends_with(file_path, ".txt");
});
if (registry_list.empty())
{
return extensions;
}
apply_black_list(blacklist, registry_list);
if (registry_list.empty())
{
return extensions;
}
auto reg_http = get_reg_http(parse_spec);
remove(reg_http, '"');
init_typemap(parse_spec);
for (const auto& file_path : registry_list)
{
tmp_output.clear();
if (!read_from_file(file_path, tmp_output))
{
log << "[Warning]: Unable to read from file '"
<< file_path << "'." << std::endl;
continue;
}
specification spec;
read_spec(tmp_output, false, spec);
prepare_tokens2(spec._tokens);
//
static const auto count_of_path_components = 2;
const auto url = reg_http + get_relative_path(file_path, count_of_path_components);
add_extensions(extensions, specification_to_extensions(spec, url, tmp_output), log);
}
return extensions;
}
bool filter(std::istream& script_stream,
std::list<std::pair<std::string, std::string>>& extensions, std::ostream& log)
{
return execute_script(script_stream, extensions, log);
}
std::list<std::pair<std::string, std::string>> get_core_ext(const std::string& core,
std::list<std::pair<std::string, std::string>>& gl_core_spec)
{
std::list<std::pair<std::string, std::string>> extensions;
//
std::list<std::string> file_list;
get_files_by_pattern(core, file_list);
if (file_list.empty())
{
return extensions;
}
file_list.sort();
std::string content(1024 * 1024, '\0');
file_list.remove_if([&content, &gl_core_spec](const std::string & file_path)
{
const auto file_name = get_file_name(file_path);
if (starts_with(file_name, "GL_VERSION"))
{
content.clear();
read_from_file(file_path, content);
if (!content.empty())
{
gl_core_spec.push_back(std::make_pair(file_name, content));
}
return true;
}
return contains(file_path, "~");
});
if (file_list.empty())
{
return extensions;
}
for (const auto& file_path : file_list)
{
content.clear();
read_from_file(file_path, content);
if (!content.empty())
{
extensions.push_back(std::make_pair(get_file_name(file_path), content));
}
}
return extensions;
}
std::list<std::pair<std::string, std::string>> get_ext_spec(
const std::string& name_prefix,
const std::list<std::pair<std::string, std::string>>& extensions)
{
std::list<std::pair<std::string, std::string>> gl_ext_spec;
for (const auto& ext : extensions)
{
if (starts_with(std::get<0>(ext), name_prefix))
{
gl_ext_spec.push_back(ext);
}
}
return gl_ext_spec;
}
void add_extensions(std::list<std::pair<std::string, std::string>>& extensions,
const std::list<std::pair<std::string, std::string>>& addition_extensions, std::ostream& log)
{
for (const auto& addition_extension : addition_extensions)
{
const auto name = std::get<0>(addition_extension);
//
const auto find_result = std::find_if(extensions.begin(), extensions.end(),
[&name](const std::pair<std::string, std::string>& element)
{
return name == std::get<0>(element);
});
if (extensions.cend() == find_result)
{
extensions.push_back(addition_extension);
}
else
{
log << "[Warning]: extension '";
log << name;
log << "' already exists. Content will be replaced with last one." << std::endl;
std::get<1>(*find_result) = std::get<1>(addition_extension);
}
}
}
std::list<extension> str_extensions_to_extensions(
const std::list<std::pair<std::string, std::string>>& str_extensions)
{
std::list<extension> extensions;
for (const auto& str_ext : str_extensions)
{
extension ext;
read_ext(std::get<1>(str_ext), ext);
if (!ext._name.empty() && std::get<0>(str_ext) == ext._name)
{
extensions.push_back(ext);
}
}
return extensions;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _DESCRIPTOR_H_
#define _DESCRIPTOR_H_
#include <set>
#include <list>
#include <string>
#include <utility>
#include <istream>
#include <ostream>
struct _procedure
{
std::string return_type;
std::string name;
std::list<std::string> parameters;
//std::list<std::pair<std::string, std::string>> parameters;
friend inline bool operator==(const _procedure& lhs, const _procedure& rhs)
{
if (lhs.name != rhs.name ||
lhs.return_type != rhs.return_type ||
lhs.parameters.size() != rhs.parameters.size())
{
return false;
}
if (lhs.parameters.empty())
{
return true;
}
for (auto lhs_parameter = lhs.parameters.cbegin(),
rhs_parameter = rhs.parameters.cbegin();
lhs_parameter != lhs.parameters.cend() &&
rhs_parameter != rhs.parameters.cend();
++lhs_parameter, ++rhs_parameter)
{
if ((*lhs_parameter) != (*rhs_parameter))
{
return false;
}
}
return true;
}
};
struct specification
{
std::string _name;
std::list<std::string> _name_strings;
std::list<std::string> _reuse;
std::list<_procedure> _procedures;
std::list<std::string> _types;
std::list<std::pair<std::string, std::pair<std::string, long>>> _tokens;
};
struct extension : specification
{
std::string _url;
};
bool init_typemap(std::istream& content_stream);
void release_typemap();
std::pair<std::string, std::pair<std::string, long>> str_to_token(
const std::string::const_iterator& token_begin,
const std::string::const_iterator& token_end);
/*SECTION_TYPE determine_section_type(
const std::string::const_iterator& name_begin,
const std::string::const_iterator& name_end);*/
std::string::const_iterator get_section_start(
const std::string& content, const std::string::const_iterator& offset);
//std::string::const_iterator get_section(const std::string& content, SECTION_TYPE section_type);
void get_name(
const std::string::const_iterator& first,
const std::string::const_iterator& last,
std::string& name);
void get_name_strings(
const std::string::const_iterator& first,
const std::string::const_iterator& last,
std::list<std::string>& name_strings);
std::pair<std::string::const_iterator, std::string::const_iterator> get_function_name(
const std::set<char>& white_space,
const std::string::const_iterator& return_start,
const std::string::const_iterator& function_start);
bool is_function_end_correct(
const std::string::const_iterator& function_start,
const std::string::const_iterator& function_end);
void get_procedures_functions(
const std::string::const_iterator& first,
const std::string::const_iterator& last,
const char function_should_start_from,
std::list<std::string>& procedures);
/*void get_procedures_functions_structures_types(
const std::string::const_iterator& first,
const std::string::const_iterator& last,
specification& spec, SECTION_TYPE section_type);*/
void get_tokens(
const std::string::const_iterator& first,
const std::string::const_iterator& last,
specification& spec);
void read_spec(const std::string& content, bool read_types, specification& spec);
void read_ext(const std::string& content, extension& ext);
bool is_procedure_should_be_ignored(const std::string& extension_name, const std::string& procedure_name);
bool is_token_taboo(const std::pair<std::string, std::pair<std::string, long>>& token);
std::list<std::pair<std::string, std::string>> specification_to_extensions(
const specification& spec, const std::string& url, std::string& tmp_output);
void prepare_tokens(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens);
void prepare_tokens2(std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens);
std::list<std::pair<std::string, std::string>> update_ext(
std::list<std::string>& registry_list,
std::istream& blacklist,
std::istream& parse_spec,
std::string& tmp_output,
std::ostream& log);
bool filter(std::istream& script_stream,
std::list<std::pair<std::string, std::string>>& extensions, std::ostream& log);
std::list<std::pair<std::string, std::string>> get_core_ext(const std::string& core,
std::list<std::pair<std::string, std::string>>& gl_core_spec);
std::list<std::pair<std::string, std::string>> get_ext_spec(
const std::string& name_prefix,
const std::list<std::pair<std::string, std::string>>& extensions);
void add_extensions(std::list<std::pair<std::string, std::string>>& extensions,
const std::list<std::pair<std::string, std::string>>& addition_extensions, std::ostream& log);
std::list<extension> str_extensions_to_extensions(
const std::list<std::pair<std::string, std::string>>& str_extensions);
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "descriptors.h"
#include "descriptor.h"
#include "path.h"
#include "common.h"
#include "parse_xml.h"
#include <cassert>
#include <fstream>
#include <utility>
#include <iterator>
#include <algorithm>
std::list<std::list<extension>> create_descriptors(
const std::string& glew_path,
const std::string& glfixes_path,
std::string& tmp_output,
std::ostream& log)
{
std::list<std::list<extension>> result;
//
const auto registry = combine(std::list<std::string>({ glfixes_path, "/gl/specs/*" }));
auto blacklist = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/blacklist" })));
if (!blacklist.is_open())
{
return result;
}
auto parse_spec = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/parse_spec.pl" })));
if (!parse_spec.is_open())
{
blacklist.close();
return result;
}
std::list<std::string> registry_list;
get_files_by_pattern(registry, registry_list);
//
auto extensions = update_ext(
registry_list,
blacklist,
parse_spec,
tmp_output,
log);
//
blacklist.close();
parse_spec.close();
//
auto filter_gl_ext = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/filter_gl_ext.sh" })));
if (!filter_gl_ext.is_open())
{
return result;
}
filter(filter_gl_ext, extensions, log);
filter_gl_ext.close();
//
std::list<std::pair<std::string, std::string>> gl_core_spec;
add_extensions(extensions,
get_core_ext(combine(std::list<std::string>({ glew_path, "/auto/core/gl/*" })), gl_core_spec),
log);
//
result.push_back(str_extensions_to_extensions(gl_core_spec));
//
extensions.sort([](const std::pair<std::string, std::string>& a, const std::pair<std::string, std::string>& b)
{
return std::get<0>(a) < std::get<0>(b);
});
//
result.push_back(str_extensions_to_extensions(get_ext_spec("GL_", extensions)));
result.push_back(str_extensions_to_extensions(get_ext_spec("WGL_", extensions)));
result.push_back(str_extensions_to_extensions(get_ext_spec("GLX_", extensions)));
//
std::list<extension> sub_extensions;
//
result.back().remove_if([&sub_extensions](const extension & ext)
{
if (starts_with(ext._name, "GLX_VERSION"))
{
sub_extensions.push_back(ext);
return true;
}
return false;
});
//
auto pos = result.begin();
std::advance(pos, result.size() - 1);
result.insert(pos, sub_extensions);
sub_extensions.clear();
//
sub_extensions = str_extensions_to_extensions(get_ext_spec("EGL_", extensions));
if (!sub_extensions.empty())
{
result.push_back(sub_extensions);
sub_extensions.clear();
//
result.back().remove_if([&sub_extensions](const extension & ext)
{
if (starts_with(ext._name, "EGL_VERSION"))
{
sub_extensions.push_back(ext);
return true;
}
return false;
});
//
pos = result.begin();
std::advance(pos, result.size() - 1);
result.insert(pos, sub_extensions);
sub_extensions.clear();
}
#ifndef NDEBUG
auto count = static_cast<std::size_t>(0);
for (const auto& ext : result)
{
assert(!ext.empty());
count += ext.size();
}
assert(!gl_core_spec.empty());
assert(gl_core_spec.size() < count);
count -= gl_core_spec.size();
assert(count == extensions.size());
#endif
return result;
}
bool mv(std::list<std::string>& src, std::list<std::string>& dst)
{
const auto is_src_empty = src.empty();
dst.splice(dst.cend(), src);
return !is_src_empty && src.empty() && !dst.empty();
}
std::list<std::list<extension>> create_descriptors(
const std::string& glew_path,
const std::string& glfixes_path,
const std::string& opengl_registry_path,
const std::string& egl_registry_path,
std::string& tmp_output,
std::ostream& log)
{
std::list<std::list<extension>> result;
//
std::list<std::string> registry_list;
get_files_by_pattern(combine(std::list<std::string>({ opengl_registry_path, "/extensions/*" })),
registry_list);
//
std::list<std::string> glfixes_files;
get_files_by_pattern(combine(std::list<std::string>({ glfixes_path, "/gl/specs/ANGLE/*" })), glfixes_files);
mv(glfixes_files, registry_list);
//
get_files_by_pattern(combine(std::list<std::string>({ glfixes_path, "/gl/specs/REGAL/*" })), glfixes_files);
mv(glfixes_files, registry_list);
//
auto blacklist = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/blacklist" })));
if (!blacklist.is_open())
{
return result;
}
auto parse_spec = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/parse_spec.pl" })));
if (!parse_spec.is_open())
{
blacklist.close();
return result;
}
registry_list.sort();
auto extensions = update_ext(registry_list, blacklist, parse_spec, tmp_output, log);
//
const auto egl_xml = combine(std::list<std::string>({ egl_registry_path, "/api/egl.xml" }));
add_extensions(extensions, parse_xml(egl_xml, parse_xml_option::extensions, tmp_output, log), log);
//
auto filter_gl_ext = std::ifstream(combine(std::list<std::string>({ glew_path, "/auto/bin/filter_gl_ext.sh" })));
if (!filter_gl_ext.is_open())
{
return result;
}
filter(filter_gl_ext, extensions, log);
filter_gl_ext.close();
//
std::list<std::pair<std::string, std::string>> gl_core_spec;
add_extensions(extensions,
get_core_ext(combine(std::list<std::string>({ glew_path, "/auto/core/gl/*" })), gl_core_spec),
log);
//
result.push_back(str_extensions_to_extensions(gl_core_spec));
//
extensions.sort([](const std::pair<std::string, std::string>& a, const std::pair<std::string, std::string>& b)
{
return std::get<0>(a) < std::get<0>(b);
});
//
result.push_back(str_extensions_to_extensions(get_ext_spec("GL_", extensions)));
result.push_back(str_extensions_to_extensions(get_ext_spec("WGL_", extensions)));
result.push_back(str_extensions_to_extensions(get_ext_spec("GLX_", extensions)));
//
std::list<extension> sub_extensions;
//
result.back().remove_if([&sub_extensions](const extension & ext)
{
if (starts_with(ext._name, "GLX_VERSION"))
{
sub_extensions.push_back(ext);
return true;
}
return false;
});
//
auto pos = result.begin();
std::advance(pos, result.size() - 1);
result.insert(pos, sub_extensions);
sub_extensions.clear();
//
sub_extensions = str_extensions_to_extensions(get_ext_spec("EGL_", extensions));
if (!sub_extensions.empty())
{
result.push_back(sub_extensions);
sub_extensions.clear();
//
result.back().remove_if([&sub_extensions](const extension & ext)
{
if (starts_with(ext._name, "EGL_VERSION"))
{
sub_extensions.push_back(ext);
return true;
}
return false;
});
if (!sub_extensions.empty())
{
pos = result.begin();
std::advance(pos, result.size() - 1);
result.insert(pos, sub_extensions);
sub_extensions.clear();
}
}
#ifndef NDEBUG
auto count = static_cast<std::size_t>(0);
for (const auto& ext : result)
{
assert(!ext.empty());
count += ext.size();
}
assert(!gl_core_spec.empty());
assert(gl_core_spec.size() < count);
count -= gl_core_spec.size();
assert(count == extensions.size());
#endif
return result;
}
std::list<extension> get_extensions_by_group_name(
const std::list<std::list<extension>>& extensions,
const std::string& extensions_group_name)
{
const auto find_result = std::find_if(extensions.cbegin(), extensions.cend(),
[&extensions_group_name](const std::list<extension>& sub_extensions)
{
return !sub_extensions.empty() &&
starts_with(sub_extensions.cbegin()->_name, extensions_group_name);
});
if (extensions.cend() != find_result)
{
return (*find_result);
}
return std::list<extension>();
}
std::list<extension> get_extensions_by_group_name(
const std::list<std::list<extension>>& extensions,
const std::string& extensions_group_name,
const std::string& except_group_name)
{
const auto find_result = std::find_if(extensions.cbegin(), extensions.cend(),
[&extensions_group_name, &except_group_name](const std::list<extension>& sub_extensions)
{
return !sub_extensions.empty() &&
starts_with(sub_extensions.cbegin()->_name, extensions_group_name) &&
!starts_with(sub_extensions.cbegin()->_name, except_group_name);
});
if (extensions.cend() != find_result)
{
return (*find_result);
}
return std::list<extension>();
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
#include <list>
#include <string>
#include <ostream>
struct extension;
std::list<std::list<extension>> create_descriptors(
const std::string& glew_path,
const std::string& glfixes_path,
std::string& tmp_output,
std::ostream& log);
std::list<std::list<extension>> create_descriptors(
const std::string& glew_path,
const std::string& glfixes_path,
const std::string& opengl_registry_path,
const std::string& egl_registry_path,
std::string& tmp_output,
std::ostream& log);
std::list<extension> get_extensions_by_group_name(
const std::list<std::list<extension>>& extensions,
const std::string& extensions_group_name);
std::list<extension> get_extensions_by_group_name(
const std::list<std::list<extension>>& extensions,
const std::string& extensions_group_name,
const std::string& except_group_name);
#define get_gl_core_spec(A) (get_extensions_by_group_name((A), "GL_VERSION"))
#define get_gl_ext_spec(A) (get_extensions_by_group_name((A), "GL_", "GL_VERSION"))
#define get_egl_core_spec(A) (get_extensions_by_group_name((A), "EGL_VERSION"))
#define get_egl_ext_spec(A) (get_extensions_by_group_name((A), "EGL", "EGL_VERSION"))
#define get_wgl_ext_spec(A) (get_extensions_by_group_name((A), "WGL_"))
#define get_glx_core_spec(A) (get_extensions_by_group_name((A), "GLX_VERSION"))
#define get_glx_ext_spec(A) (get_extensions_by_group_name((A), "GLX_", "GLX_VERSION"))
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "filler.h"
#include "common.h"
#include "version.h"
#include "procedure.h"
#include "descriptor.h"
#include <set>
#include <list>
#include <iterator>
#include <algorithm>
void add_define_start(const std::string& name, std::string& content)
{
content += '\n';
content += '\n';
content += "#ifndef " + name + "\n";
content += "#define " + name + " 1\n";
content += '\n';
}
void add_define_finish(const std::string& name, std::string& content)
{
content += '\n';
content += "#endif /* " + name + " */\n";
content += '\n';
}
void add_types(const std::list<std::string>& types, std::string& content)
{
for (const auto& type_ : types)
{
auto pos1 = type_.find(';');
auto pos2 = pos1;
if (std::string::npos != pos1)
{
pos2++;
pos2 = type_.find(';', pos2);
}
if (std::string::npos != pos2 && pos1 < pos2 && contains(type_, "{"))
{
auto start = type_.cbegin();
pos2 = type_.find('{');
if (pos2 < pos1)
{
pos2++;
std::advance(start, pos2);
std::copy(type_.cbegin(),
start,
std::back_inserter(content));
content.push_back('\n');
}
do
{
auto finish = type_.cbegin();
if (pos1 < type_.size() - 1)
{
pos1 += 2;
}
else
{
++pos1;
}
std::advance(finish, pos1);
std::copy(start,
finish,
std::back_inserter(content));
content.push_back('\n');
start = finish;
}
while (pos1 < type_.size() - 1 && std::string::npos != (pos1 = type_.find(';', pos1)));
if (0 < std::distance(start, type_.cend()))
{
std::copy(start,
type_.cend(),
std::back_inserter(content));
auto pos = std::find_if(start, type_.cend(),
[](const char& ch)
{
return ';' == ch;
});
if (type_.cend() == pos)
{
content.push_back(';');
}
else
{
const auto tab_space_new_line = std::set<char>({ '\t', ' ', '\n' });
std::advance(pos, 1);
//
pos = std::find_if(pos, type_.cend(),
[&tab_space_new_line](const char& ch)
{
return 0 == tab_space_new_line.count(ch);
});
if (type_.cend() != pos)
{
content.push_back(';');
}
}
content.push_back('\n');
}
}
else
{
content += type_;
if (std::string::npos == type_.rfind(';'))
{
content += ';';
}
}
content += '\n';
}
}
void add_tokens(const std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens,
std::string& content)
{
for (const auto& token : tokens)
{
content += "#define " + std::get<0>(token) +
(std::get<0>(std::get<1>(token)).empty() ? "" : " " + std::get<0>(std::get<1>(token)));
content += '\n';
}
}
std::string get_glew_name(const std::string& name, const std::string& type)
{
std::string glew_name(2 + name.size(), '\0');
glew_name.clear();
if (type.size() < name.size())
{
if (!type.empty())
{
std::copy(type.cbegin(), type.cend(), std::back_inserter(glew_name));
}
glew_name += "EW";
std::copy(name.cbegin() + type.size(), name.cend(), std::back_inserter(glew_name));
}
return glew_name;
}
std::pair<std::string, std::string> serialize_procedure(
const _procedure& procedure, const std::string& api, const std::string& type)
{
static const auto gl_word = std::string("gl");
//
std::string gl_name_upper(7 + procedure.name.size(), '\0');
gl_name_upper.clear();
gl_name_upper += "PFN";
gl_name_upper += toupper(procedure.name);
gl_name_upper += "PROC";
//
std::string typedef_("typedef ");
typedef_ += procedure.return_type + " (" + api + " * " + gl_name_upper + ") " + "(" + join(", ",
procedure.parameters);
if (')' != typedef_.back())
{
typedef_ += ')';
}
if (std::string::npos == typedef_.rfind(';'))
{
typedef_ += ';';
}
std::string glew_name(4 + procedure.name.size(), '\0');
glew_name.clear();
glew_name += "__";
const auto pos = procedure.name.find(gl_word);
if (std::string::npos != pos)
{
for (auto i = static_cast<std::size_t>(0); i < pos; ++i)
{
glew_name += procedure.name[i];
}
glew_name += "glew";
for (auto i = gl_word.size() + pos, count = procedure.name.size(); i < count; ++i)
{
glew_name += procedure.name[i];
}
}
auto define_ = "#define " + procedure.name + " " + type + "EW_GET_FUN(" + glew_name + ")";
return std::make_pair(typedef_, define_);
}
void add_procedures(const std::list<_procedure>& procedures, const std::string& api, const std::string& type,
std::string& content)
{
std::list<std::pair<std::string, std::string>> typedefs_and_defines;
for (const auto& procedure : procedures)
{
typedefs_and_defines.push_back(serialize_procedure(procedure, api, type));
}
typedefs_and_defines.sort([](const std::pair<std::string, std::string>& a,
const std::pair<std::string, std::string>& b)
{
return std::get<1>(a) < std::get<1>(b);
});
//
typedefs_and_defines.unique();
for (const auto& typedef_ : typedefs_and_defines)
{
content += std::get<0>(typedef_);
content += '\n';
}
if (!typedefs_and_defines.empty())
{
content += '\n';
}
for (const auto& define_ : typedefs_and_defines)
{
content += std::get<1>(define_);
content += '\n';
}
}
void add_variable(const std::string& name, const std::string& type, std::string& content)
{
const auto glew_name = get_glew_name(name, type);
content += "#define " + glew_name + " " + type + "EW_GET_VAR(__" + glew_name + ")\n";
}
void add_section_head(const std::string& head, std::string& content)
{
if (head.empty())
{
content.push_back('/');
content.push_back('*');
content.push_back(' ');
std::string head_(73, '-');
std::copy(head_.cbegin(), head_.cend(), std::back_inserter(content));
content.push_back(' ');
content.push_back('*');
content.push_back('/');
}
else if (head.size() < 72)
{
std::string head_(79, '-');
head_[0] = '/';
head_[1] = '*';
head_[2] = ' ';
std::size_t start_position = static_cast<std::size_t>(39) -
static_cast<std::size_t>(0.5f + static_cast<float>(head.size()) / 2);
head_[start_position++] = ' ';
std::copy(head.cbegin(), head.cend(), head_.begin() + start_position);
head_[start_position + head.size()] = ' ';
head_[76] = ' ';
head_[77] = '*';
head_[78] = '/';
std::copy(head_.cbegin(), head_.cend(), std::back_inserter(content));
}
else
{
content.push_back('/');
content.push_back('*');
content.push_back(' ');
std::copy(head.cbegin(), head.cend(), std::back_inserter(content));
content.push_back(' ');
content.push_back('*');
content.push_back('/');
}
}
void add_content_separator(std::string& content)
{
if (content.size() < 2)
{
content += "\n\n";
}
else if (content.size() - 2 != content.rfind("\n\n", content.size() - 2))
{
content += '\n';
if (content.size() - 2 != content.rfind("\n\n", content.size() - 2))
{
content += '\n';
}
}
}
void make_head_content_from_ext(const specification& spec, const std::string& api, const std::string& type,
std::string& content)
{
add_section_head(spec._name, content);
add_define_start(spec._name, content);
//
add_tokens(spec._tokens, content);
add_content_separator(content);
add_types(spec._types, content);
add_content_separator(content);
add_procedures(spec._procedures, api, type, content);
add_content_separator(content);
add_variable(spec._name, type, content);
//
add_define_finish(spec._name, content);
}
void make_header(const std::string& api, const std::string& type,
const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
make_head_content_from_ext(ext, api, type, output);
}
}
void make_struct_fun(const std::string& prefix, const std::string& suffix,
const std::list<extension>& extensions, std::ostream& output)
{
static const auto gl_word = std::string("gl");
for (const auto& ext : extensions)
{
if (ext._procedures.empty())
{
continue;
}
for (const auto& procedure : ext._procedures)
{
if (!prefix.empty())
{
output << prefix << ' ';
}
output << "PFN";
output << toupper(procedure.name);
output << "PROC ";
output << "__";
//
const auto pos = procedure.name.find(gl_word);
if (std::string::npos != pos)
{
for (auto i = static_cast<std::size_t>(0); i < pos; ++i)
{
output << procedure.name[i];
}
output << "glew";
for (auto i = gl_word.size() + pos, count = procedure.name.size(); i < count; ++i)
{
output << procedure.name[i];
}
}
if (!suffix.empty())
{
output << ' ' << suffix;
}
output << ";" << std::endl;
}
output << std::endl;
}
}
void make_struct_fun(const std::string& prefix, const std::string& suffix,
const std::list<extension>& extensions, std::string& output)
{
static const auto gl_word = std::string("gl");
for (const auto& ext : extensions)
{
if (ext._procedures.empty())
{
continue;
}
for (const auto& procedure : ext._procedures)
{
const auto current_size = output.size();
if (!prefix.empty())
{
output += prefix + ' ';
}
output += "PFN";
output += toupper(procedure.name);
output += "PROC ";
output += "__";
//
const auto pos = procedure.name.find(gl_word);
if (std::string::npos != pos)
{
for (auto i = static_cast<std::size_t>(0); i < pos; ++i)
{
output += procedure.name[i];
}
output += "glew";
for (auto i = gl_word.size() + pos, count = procedure.name.size(); i < count; ++i)
{
output += procedure.name[i];
}
}
if (!suffix.empty())
{
output += ' ' + suffix;
}
output += ";\n";
const auto str_procedure = output.substr(current_size);
const auto procedure_position = output.find(str_procedure);
if (procedure_position != current_size)
{
output.resize(current_size);
//TODO: deal with GL_VERSION_4_5 and GL_KHR_robustness that both have GetGraphicsResetStatus function.
//TODO: Reference implementation deal with this moment.
}
}
output.push_back('\n');
}
}
void make_struct_var(const std::string& prefix, const std::string& suffix,
const std::string& type,
const std::list<extension>& extensions, std::ostream& output)
{
for (const auto& ext : extensions)
{
if (!prefix.empty())
{
output << prefix << ' ';
}
output << "GLboolean __";
output << get_glew_name(ext._name, type);
if (!suffix.empty())
{
output << ' ' << suffix;
}
output << ";" << std::endl;
}
}
void make_struct_var(const std::string& prefix, const std::string& suffix,
const std::string& type,
const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
if (!prefix.empty())
{
output += prefix + ' ';
}
output += "GLboolean __";
output += get_glew_name(ext._name, type);
if (!suffix.empty())
{
output += ' ' + suffix;
}
output += ";\n";
}
}
void make_init(const std::string& type, const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
if (ext._procedures.empty())
{
continue;
}
output += "#ifdef " + ext._name + "\n\n";
output += "static GLboolean _glewInit_" + ext._name;
if (type.empty())
{
output += " ()\n{\n ";
}
else
{
output += " (" + type;
output += "EW_CONTEXT_ARG_DEF_INIT)\n{\n ";
}
output += "GLboolean r = GL_FALSE;\n";
output.push_back('\n');
if (!ext._reuse.empty())
{
output += " r = _glewInit_";
output += join("() || r;\n r = _glewInit_", ext._reuse);
output += "() || r;\n\n";
}
for (const auto& procedure : ext._procedures)
{
output += " r = ((" + procedure.name +
" = (PFN" + toupper(procedure.name) +
"PROC)glewGetProcAddress((const GLubyte*)\"" + procedure.name +
"\")) == NULL) || r;";
output.push_back('\n');
}
output += "\n return r;\n}\n\n";
output += "#endif /* " + ext._name + " */\n\n";
}
}
void make_init(const std::list<extension>& extensions, std::string& output)
{
make_init("", extensions, output);
}
void make_initd(const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
if (ext._procedures.empty())
{
continue;
}
output += "static GLboolean _glewInit_" + ext._name + " ();\n";
}
}
std::string get_ext_var(const std::string& name)
{
static const std::list<std::string> prefixes({ "EGL_", "WGL_", "GLX_", "GL_" });
for (const auto& prefix : prefixes)
{
if (starts_with(name, prefix))
{
return get_glew_name(name, prefix.substr(0, prefix.size() - 1));
}
}
return get_glew_name(name, "");
}
void make_list(const extension& ext, std::string& output)
{
output += "#ifdef " + ext._name + '\n';
const auto ext_var = get_ext_var(ext._name);
if (!ext._name_strings.empty())
{
output += " " + ext_var + " = _glewSearchExtension(\"" +
ext._name_strings.front() + "\", extStart, extEnd);\n";
}
if (!ext._procedures.empty())
{
if (starts_with(ext._name, "WGL_"))
{
output += " if (glewExperimental || " + ext_var + "|| crippled) "
+ ext_var + "= !_glewInit_" + ext._name + "(GLEW_CONTEXT_ARG_VAR_INIT);\n";
}
else
{
output += " if (glewExperimental || " + ext_var + ") "
+ ext_var + " = !_glewInit_" + ext._name + "(GLEW_CONTEXT_ARG_VAR_INIT);\n";
}
}
output += "#endif /* " + ext._name + " */\n";
}
void make_list_2_2_2(const extension& ext, std::string& output)
{
if (ext._procedures.empty() && starts_with(ext._name, "GL_"))
{
return;
}
if (!ext._name_strings.empty() || !ext._procedures.empty())
{
output += "#ifdef " + ext._name + '\n';
const auto ext_var = get_ext_var(ext._name);
if (!ext._name_strings.empty() && !starts_with(ext._name, "GL_"))
{
output += " " + ext_var + " = _glewSearchExtension(\"" + ext._name_strings.front() +
"\", extStart, extEnd);\n";
}
if (!ext._procedures.empty())
{
if (starts_with(ext._name, "WGL_"))
{
output += " if (glewExperimental || " + ext_var + "|| crippled) "
+ ext_var + "= !_glewInit_" + ext._name + "();\n";
}
else
{
output += " if (glewExperimental || " + ext_var + ") "
+ ext_var + " = !_glewInit_" + ext._name + "();\n";
}
}
output += "#endif /* " + ext._name + " */\n";
}
}
void make_list(const std::list<extension>& extensions, std::string& output, const _version& version)
{
if (version_1_13_0 == version)
{
for (const auto& ext : extensions)
{
make_list(ext, output);
}
}
else if (version_2_2_2 == version)
{
for (const auto& ext : extensions)
{
make_list_2_2_2(ext, output);
}
}
}
void make_list(const std::string& extension_name, const std::list<extension>& extensions, std::string& output,
const _version& version)
{
const auto required_extension = std::find_if(extensions.cbegin(), extensions.cend(),
[&extension_name](const extension & ext)
{
return extension_name == ext._name;
});
if (extensions.cbegin() != required_extension)
{
if (version_1_13_0 == version)
{
make_list(*required_extension, output);
}
else if (version_2_2_2 == version)
{
make_list_2_2_2(*required_extension, output);
}
}
}
void make_list2(const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
if (ext._name_strings.empty() || ext._name_strings.front() == ext._name)
{
continue;
}
const auto ext_var = get_ext_var(ext._name);
const auto parent = get_ext_var(ext._name_strings.front());
//
output += "#ifdef " + ext._name + "\n";
output += " " + ext_var + " = " + parent + ";\n";
output += "#endif /* " + ext._name + " */\n";
}
}
void make_str(const std::list<extension>& extensions, std::string& output)
{
std::string exttype;
for (const auto& ext : extensions)
{
std::string extrem(ext._name.size(), '\0');
extrem.clear();
//
auto pos = std::find_if(ext._name.cbegin(), ext._name.cend(),
[](const char& ch)
{
return '_' == ch;
});
if (ext._name.cend() != pos)
{
std::advance(pos, 1);
auto prev_pos = pos;
//
pos = std::find_if(pos, ext._name.cend(),
[](const char& ch)
{
return '_' == ch;
});
if (ext._name.cend() != pos)
{
std::advance(pos, 1);
if (static_cast<std::size_t>(std::distance(prev_pos, pos)) != exttype.size() ||
!contains(std::make_pair(prev_pos, pos), exttype))
{
if (!exttype.empty())
{
output += " }\n";
}
exttype.clear();
std::copy(prev_pos,
pos,
std::back_inserter(exttype));
//
output += " if (_glewStrSame2(&pos, &len, (const GLubyte*)\"" + exttype + "\", " + std::to_string(
exttype.size()) + "))\n";
output += " {\n";
}
}
}
std::copy(pos,
ext._name.cend(),
std::back_inserter(extrem));
//
const auto ext_var = get_ext_var(ext._name);
output += "#ifdef " + ext._name + "\n";
output += " if (_glewStrSame3(&pos, &len, (const GLubyte*)\"" + extrem + "\", " + std::to_string(
extrem.size()) + "))\n";
output += " {\n";
output += " ret = " + ext_var + ";\n";
output += " continue;\n";
output += " }\n";
output += "#endif\n";
}
output += " }\n";
}
void make_info(const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
output += "#ifdef " + ext._name + "\n\n";
output += "static void _glewInfo_" + ext._name + " (void)\n{\n";
const auto ext_var = get_ext_var(ext._name);
if (contains(ext_var, "VERSION"))
{
output += " glewPrintExt(\"" + ext._name + "\", " + ext_var + ", " + ext_var + ", " + ext_var + ");\n";
}
else
{
static const std::list<std::string> prefixes({ "GLX", "GLW", "GL" });
std::string extpre;
for (const auto& prefix : prefixes)
{
const auto pos = find_phrase_start(ext._name, prefix);
if (ext._name.cend() != pos)
{
if (ext._name.cbegin() != pos)
{
std::copy(
ext._name.cbegin(),
pos,
std::back_inserter(extpre));
}
std::copy(
prefix.cbegin(),
prefix.cend(),
std::back_inserter(extpre));
//
extpre = tolower(extpre);
break;
}
}
output += std::string(" glewPrintExt(\"" + ext._name + "\", " + ext_var + ", " + extpre) +
std::string("ewIsSupported(\"" + ext._name + "\"), " + extpre) +
std::string("ewGetExtension(\"" + join("", ext._name_strings) + "\"));\n");
}
if (!ext._procedures.empty())
{
output.push_back('\n');
}
for (const auto& procedure : ext._procedures)
{
output += " glewInfoFunc(\"" + procedure.name + "\", " + procedure.name + " == NULL);";
output.push_back('\n');
}
output += "}\n\n";
output += "#endif /* " + ext._name + " */\n\n";
}
}
void make_info_list(const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
output += "#ifdef " + ext._name + "\n";
output += " _glewInfo_" + ext._name + "();\n";
output += "#endif /* " + ext._name + " */\n";
}
}
void make_index(const std::list<extension>& extensions, std::string& output)
{
for (const auto& ext : extensions)
{
output += "#ifdef " + ext._name + "\n";
output += " \"" + ext._name + "\",\n";
output += "#endif\n";
}
}
void make_index(const std::list<extension>& extensions1, const std::list<extension>& extensions2,
std::string& output)
{
for (auto a = extensions1.cbegin(), b = extensions2.cbegin(); ;)
{
const std::string* ext_name = nullptr;
if (extensions1.cend() != a && extensions2.cend() != b)
{
if (a->_name < b->_name)
{
ext_name = &(a->_name);
++a;
}
else
{
ext_name = &(b->_name);
++b;
}
}
else if (extensions1.cend() != a)
{
ext_name = &(a->_name);
++a;
}
else if (extensions2.cend() != b)
{
ext_name = &(b->_name);
++b;
}
else
{
break;
}
output += "#ifdef " + (*ext_name) + "\n";
output += " \"" + (*ext_name) + "\",\n";
output += "#endif\n";
}
}
void make_enable_index(const std::list<extension>& extensions1, const std::list<extension>& extensions2,
std::string& output)
{
output += "/* Detected in the extension string or strings */\n";
output += "static GLboolean _glewExtensionString[" +
std::to_string(extensions1.size() + extensions2.size()) + "];\n";
output += "/* Detected via extension string or experimental mode */\n";
output += "static GLboolean* _glewExtensionEnabled[] = {\n";
for (auto a = extensions1.cbegin(), b = extensions2.cbegin(); ;)
{
const std::string* ext_name = nullptr;
if (extensions1.cend() != a && extensions2.cend() != b)
{
if (a->_name < b->_name)
{
ext_name = &(a->_name);
++a;
}
else
{
ext_name = &(b->_name);
++b;
}
}
else if (extensions1.cend() != a)
{
ext_name = &(a->_name);
++a;
}
else if (extensions2.cend() != b)
{
ext_name = &(b->_name);
++b;
}
else
{
break;
}
const auto ext_var = get_ext_var(*ext_name);
output += "#ifdef " + (*ext_name) + "\n";
output += " &__" + ext_var + ",\n";
output += "#endif\n";
}
output += " NULL\n};\n\n";
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _FILLER_H_
#define _FILLER_H_
#include <list>
#include <string>
#include <utility>
#include <ostream>
struct _procedure;
struct specification;
struct extension;
struct _version;
void add_define_start(const std::string& name, std::string& content);
void add_define_finish(const std::string& name, std::string& content);
void add_types(const std::list<std::string>& types, std::string& content);
void add_tokens(const std::list<std::pair<std::string, std::pair<std::string, long>>>& tokens,
std::string& content);
std::string get_glew_name(const std::string& name, const std::string& type);
std::pair<std::string, std::string> serialize_procedure(
const _procedure& procedure, const std::string& api, const std::string& type);
void add_procedures(const std::list<_procedure>& procedures, const std::string& api, const std::string& type,
std::string& content);
void add_variable(const std::string& name, const std::string& type, std::string& content);
void add_section_head(const std::string& head, std::string& content);
void add_content_separator(std::string& content);
void make_head_content_from_ext(const specification& spec, const std::string& api, const std::string& type,
std::string& content);
void make_header(const std::string& api, const std::string& type,
const std::list<extension>& extensions, std::string& output);
void make_struct_fun(const std::string& prefix, const std::string& suffix,
const std::list<extension>& extensions, std::ostream& output);
void make_struct_fun(const std::string& prefix, const std::string& suffix,
const std::list<extension>& extensions, std::string& output);
void make_struct_var(const std::string& prefix, const std::string& suffix,
const std::string& type,
const std::list<extension>& extensions, std::ostream& output);
void make_struct_var(const std::string& prefix, const std::string& suffix,
const std::string& type,
const std::list<extension>& extensions, std::string& output);
#define make_def_fun(extensions, output) make_struct_fun("", "= NULL", (extensions), (output))
#define make_def_var(type, extensions, output) make_struct_var("", "= GL_FALSE", (type), (extensions), (output))
void make_init(const std::string& type, const std::list<extension>& extensions, std::string& output);
void make_init(const std::list<extension>& extensions, std::string& output);
void make_initd(const std::list<extension>& extensions, std::string& output);
std::string get_ext_var(const std::string& name);
void make_list(const extension& ext, std::string& output);
void make_list(const std::list<extension>& extensions, std::string& output, const _version& version);
void make_list(const std::string& extension_name, const std::list<extension>& extensions,
std::string& output, const _version& version);
void make_list2(const std::list<extension>& extensions, std::string& output);
void make_str(const std::list<extension>& extensions, std::string& output);
void make_info(const std::list<extension>& extensions, std::string& output);
void make_info_list(const std::list<extension>& extensions, std::string& output);
void make_index(const std::list<extension>& extensions, std::string& output);
void make_index(const std::list<extension>& extensions1,
const std::list<extension>& extensions2, std::string& output);
void make_enable_index(const std::list<extension>& extensions1,
const std::list<extension>& extensions2, std::string& output);
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "generator.h"
#include "filler.h"
#include "common.h"
#include "input_output.h"
#include "path.h"
#include "version.h"
#include "interpreter.h"
#include <fstream>
#include <iterator>
std::list<std::list<extension>>::const_iterator get_next_extensions(
const std::list<std::list<extension>>::const_iterator& current_extensions,
const std::list<std::list<extension>>& extensions,
const std::string& extensions_group_name,
std::ostream& log)
{
if (extensions.size() <
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), current_extensions)))
{
log << "[Error]: there is no '"
<< extensions_group_name
<< "' at extensions list."
<< std::endl;
return current_extensions;
}
auto next = current_extensions;
std::advance(next, 1);
return next;
}
bool glew_h(const std::string& src,
const std::list<std::list<extension>>& extensions,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log)
{
auto result = true;
const auto ver = str_version_to_version(version);
//
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "mesa_license.h" })),
combine(std::list<std::string>({ src, "khronos_license.h" })),
combine(std::list<std::string>({ src, "glew_head.h" }))
});
for (const auto& file_path : start_content_files)
{
read_from_file(file_path, output);
}
if (extensions.empty())
{
log << "[Error]: no extensions passed. Generation of content halted." << std::endl;
return false;
}
const auto gl_core_spec = extensions.cbegin();
if (extensions.size() <
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), gl_core_spec)))
{
log << "[Error]: there is no 'GL_EXT_SPEC' at extensions list. Generation of content halted." <<
std::endl;
return false;
}
auto gl_ext_spec = gl_core_spec;
std::advance(gl_ext_spec, 1);
//
make_header("GLAPIENTRY", "GL", *gl_core_spec, output);
make_header("GLAPIENTRY", "GL", *gl_ext_spec, output);
if (ver == version_1_13_0)
{
echo("/* ------------------------------------------------------------------------- */\n\n#if defined(GLEW_MX) && defined(_WIN32)\n#define GLEW_FUN_EXPORT\n#else\n#define GLEW_FUN_EXPORT GLEWAPI\n#endif /* GLEW_MX */\n",
output);
echo("#if defined(GLEW_MX)\n#define GLEW_VAR_EXPORT\n#else\n#define GLEW_VAR_EXPORT GLEWAPI\n#endif /* GLEW_MX */\n",
output);
echo("#if defined(GLEW_MX) && defined(_WIN32)\nstruct GLEWContextStruct\n{\n#endif /* GLEW_MX */", output);
}
else
{
echo("/* ------------------------------------------------------------------------- */\n\n", output);
output.push_back('\n');
}
make_struct_fun("GLEW_FUN_EXPORT", "", *gl_core_spec, output);
make_struct_fun("GLEW_FUN_EXPORT", "", *gl_ext_spec, output);
//
output.pop_back();
if (ver == version_1_13_0)
{
echo("\n#if defined(GLEW_MX) && !defined(_WIN32)\nstruct GLEWContextStruct\n{\n#endif /* GLEW_MX */\n",
output);
}
make_struct_var("GLEW_VAR_EXPORT", "", "GL", *gl_core_spec, output);
make_struct_var("GLEW_VAR_EXPORT", "", "GL", *gl_ext_spec, output);
if (ver == version_1_13_0)
{
echo("\n#ifdef GLEW_MX\n}; /* GLEWContextStruct */\n#endif /* GLEW_MX */\n", output);
}
static const auto parameter =
std::string("s/GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;/GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1;\nGLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;/");
if (!perl(output, parameter))
{
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl;
}
const auto glew_tail = combine(std::list<std::string>({ src, "glew_tail.h" }));
std::ifstream file_stream(glew_tail);
if (file_stream.is_open())
{
std::list<std::string> parameters;
parameters.push_back(std::string("s/GLEW_VERSION_STRING/$(GLEW_VERSION)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MAJOR_STRING/$(GLEW_MAJOR)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MINOR_STRING/$(GLEW_MINOR)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MICRO_STRING/$(GLEW_MICRO)/g"));
if (!perl(file_stream, parameters, version, output, log))
{
log << "[Warning]: Command 'perl -e " << join("\nperl -e ",
parameters) << "' was not be applied." << std::endl;
result = false;
}
file_stream.close();
}
else
{
log << "[Warning]: Unable to open '" << glew_tail << "'." << std::endl;
result = false;
}
return result;
}
bool glew_c_2_2_2(const std::string& src,
const std::list<std::list<extension>>& extensions,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log)
{
auto result = true;
//
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "glew_head.c" }))
});
for (const auto& file_path : start_content_files)
{
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
}
if (extensions.empty())
{
log << "[Error]: no extensions passed. Generation of content halted." << std::endl;
return false;
}
output.push_back('\n');
const auto gl_core_spec = extensions.cbegin();
make_def_fun(*gl_core_spec, output);
//
const auto gl_ext_spec = get_next_extensions(gl_core_spec, extensions, "GL_EXT_SPEC", log);
if (gl_core_spec == gl_ext_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_def_fun(*gl_ext_spec, output);
//
output.pop_back();
echo("\nGLboolean __GLEW_VERSION_1_1 = GL_FALSE;", output);
//
make_def_var("GL", *gl_core_spec, output);
make_def_var("GL", *gl_ext_spec, output);
//
echo("\nstatic const char * _glewExtensionLookup[] = {", output);
//
make_index(*gl_core_spec, *gl_ext_spec, output);
//
echo(" NULL\n};\n\n", output);
//
make_enable_index(*gl_core_spec, *gl_ext_spec, output);
//
make_initd(*gl_core_spec, output);
make_initd(*gl_ext_spec, output);
//
echo("", output);
//
make_init(*gl_core_spec, output);
make_init(*gl_ext_spec, output);
//
auto file_path = combine(std::list<std::string>({ src, "glew_init_gl.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_list(*gl_core_spec, output, version_2_2_2); //| grep - v '\"GL_VERSION' >> $@
make_list(*gl_ext_spec, output, version_2_2_2);
make_list2(*gl_ext_spec, output);
//
echo("\n return GLEW_OK;\n}\n", output);
echo("\n#if defined(GLEW_OSMESA)", output);
echo("\n#elif defined(GLEW_EGL)", output);
output.push_back('\n');
//
auto egl_core_spec = extensions.crbegin();
std::advance(egl_core_spec, 1);
const auto egl_ext_spec = extensions.crbegin();
//
make_def_fun(*egl_core_spec, output);
make_def_fun(*egl_ext_spec, output);
//
make_def_var("EGL", *egl_core_spec, output);
make_def_var("EGL", *egl_ext_spec, output);
//
make_init(*egl_core_spec, output);
make_init(*egl_ext_spec, output);
//
file_path = combine(std::list<std::string>({ src, "glew_init_egl.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_list(*egl_core_spec, output, version_2_2_2);
make_list(*egl_ext_spec, output, version_2_2_2);
//
echo("\n return GLEW_OK;\n}", output);
echo("\n#elif defined(_WIN32)", output);
//
output.push_back('\n');
//
const auto wgl_ext_spec = get_next_extensions(gl_ext_spec, extensions, "WGL_EXT_SPEC", log);
if (gl_ext_spec == wgl_ext_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_def_fun(*wgl_ext_spec, output);
make_def_var("WGL", *wgl_ext_spec, output);
make_init(*wgl_ext_spec, output);
//
file_path = combine(std::list<std::string>({ src, "glew_init_wgl.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_list(*wgl_ext_spec, output, version_2_2_2);
//
echo("\n return GLEW_OK;\n}", output);
echo("\n#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))",
output);
//
const auto glx_core_spec = get_next_extensions(wgl_ext_spec, extensions, "GLX_CORE_SPEC", log);
if (wgl_ext_spec == glx_core_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
output.push_back('\n');
make_def_fun(*glx_core_spec, output);
const auto glx_ext_spec = get_next_extensions(glx_core_spec, extensions, "GLX_EXT_SPEC", log);
if (glx_core_spec == glx_ext_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_def_fun(*glx_ext_spec, output);
//
output.pop_back();
echo("\nGLboolean __GLXEW_VERSION_1_0 = GL_FALSE;", output);
echo("GLboolean __GLXEW_VERSION_1_1 = GL_FALSE;", output);
//
make_def_var("GLX", *glx_core_spec, output);
make_def_var("GLX", *glx_ext_spec, output);
//
make_init(*glx_core_spec, output);
make_init(*glx_ext_spec, output);
//
file_path = combine(std::list<std::string>({ src, "glew_init_glx.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
std::string sub_output;
make_list("GLX_VERSION_1_3", *glx_core_spec, sub_output, version_2_2_2);
grep(sub_output, "\"GLX_VERSION", true, output);
sub_output.clear();
//
make_list(*glx_ext_spec, output, version_2_2_2);
//
echo("\n return GLEW_OK;\n}", output);
echo("\n#endif /* !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */\n",
output);
//
file_path = combine(std::list<std::string>({ src, "glew_init_tail.c" }));
std::ifstream file_stream(file_path);
if (file_stream.is_open())
{
std::list<std::string> parameters;
parameters.push_back(std::string("s/GLEW_VERSION_STRING/$(GLEW_VERSION)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MAJOR_STRING/$(GLEW_MAJOR)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MINOR_STRING/$(GLEW_MINOR)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MICRO_STRING/$(GLEW_MICRO)/g"));
if (!perl(file_stream, parameters, version, output, log))
{
log << "[Warning]: Command 'perl -e "
<< join("\nperl -e ", parameters)
<< "' was not be applied." << std::endl;
result = false;
}
file_stream.close();
}
else
{
log << "[Warning]: Unable to open '" << file_path << "'." << std::endl;
result = false;
}
file_path = combine(std::list<std::string>({ src, "glew_str_head.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_str(*gl_core_spec, output);
make_str(*gl_ext_spec, output);
file_path = combine(std::list<std::string>({ src, "glew_str_wgl.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_str(*wgl_ext_spec, output);
file_path = combine(std::list<std::string>({ src, "glew_str_glx.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_str(*glx_core_spec, output);
make_str(*glx_ext_spec, output);
file_path = combine(std::list<std::string>({ src, "glew_str_egl.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
make_str(*egl_core_spec, output);
make_str(*egl_ext_spec, output);
file_path = combine(std::list<std::string>({ src, "glew_str_tail.c" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
file_path =
"s/GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader\\(\\);/{ GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader(); _glewInit_GL_ARB_vertex_program(); }/g";
if (!perl(output, file_path))
{
log << "[Warning]: Command 'perl -e " << file_path << "' was not be applied." << std::endl;
result = false;
}
file_path =
"s/\\(\\(glColorSubTable = /((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)\"glBlendEquation\")) == NULL) || r;\n r = ((glColorSubTable = /g";
if (!perl(output, file_path))
{
log << "[Warning]: Command 'perl -e " << file_path << "' was not be applied." << std::endl;
result = false;
}
return result;
}
bool glew_c(const std::string& src,
const std::list<std::list<extension>>& extensions,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log)
{
auto result = true;
//
const auto ver = str_version_to_version(version);
if (version_2_2_2 == ver)
{
return glew_c_2_2_2(src, extensions, version, output, log);
}
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "glew_head.c" }))
});
for (const auto& file_path : start_content_files)
{
read_from_file(file_path, output);
}
echo("\n#if !defined(_WIN32) || !defined(GLEW_MX)", output);
//
output.push_back('\n');
if (extensions.empty())
{
log << "[Error]: no extensions passed. Generation of content halted." << std::endl;
return false;
}
const auto gl_core_spec = extensions.cbegin();
if (extensions.size() <
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), gl_core_spec)))
{
log << "[Error]: there is no 'GL_EXT_SPEC' at extensions list. Generation of content halted." <<
std::endl;
return false;
}
auto gl_ext_spec = gl_core_spec;
std::advance(gl_ext_spec, 1);
//
make_def_fun(*gl_core_spec, output);
make_def_fun(*gl_ext_spec, output);
//
output.pop_back();
//
echo("\n#endif /* !WIN32 || !GLEW_MX */", output);
//
echo("\n#if !defined(GLEW_MX)", output);
echo("\nGLboolean __GLEW_VERSION_1_1 = GL_FALSE;", output);
//
make_def_var("GL", *gl_core_spec, output);
make_def_var("GL", *gl_ext_spec, output);
//
echo("\n#endif /* !GLEW_MX */\n", output);
//
make_init("GL", *gl_core_spec, output);
make_init("GL", *gl_ext_spec, output);
//
read_from_file(
combine(std::list<std::string>({ src, "glew_init_gl.c" })),
output);
//
make_list(*gl_core_spec, output, ver);//| grep -v '\"GL_VERSION'
make_list(*gl_ext_spec, output, ver);
//
echo("\n return GLEW_OK;\n}\n", output);
echo("\n#if defined(_WIN32)", output);
echo("\n#if !defined(GLEW_MX)", output);
//
output.push_back('\n');
if (extensions.size() <
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), gl_ext_spec)))
{
log << "[Error]: there is no 'WGL_EXT_SPEC' at extensions list. Generation of content halted." <<
std::endl;
return false;
}
auto wgl_ext_spec = gl_ext_spec;
std::advance(wgl_ext_spec, 1);
//
make_def_fun(*wgl_ext_spec, output);//"WGL",
output.pop_back();
make_def_var("WGL", *wgl_ext_spec, output);
//
echo("\n#endif /* !GLEW_MX */\n", output);
make_init("WGL", *wgl_ext_spec, output);
//
read_from_file(
combine(std::list<std::string>({ src, "glew_init_wgl.c" })),
output);
make_list(*wgl_ext_spec, output, ver);
//
echo("\n return GLEW_OK;\n}", output);
echo("\n#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))",
output);
if (extensions.size() <
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), wgl_ext_spec)))
{
log << "[Error]: there is no 'GLX_CORE_SPEC' at extensions list. Generation of content halted." <<
std::endl;
return false;
}
auto glx_core_spec = wgl_ext_spec;
std::advance(glx_core_spec, 1);
if (extensions.size() <
static_cast<std::size_t>(1 + std::distance(extensions.cbegin(), glx_core_spec)))
{
log << "[Error]: there is no 'GLX_EXT_SPEC' at extensions list. Generation of content halted." <<
std::endl;
return false;
}
auto glx_ext_spec = glx_core_spec;
std::advance(glx_ext_spec, 1);
//
output.push_back('\n');
//
make_def_fun(*glx_core_spec, output);//"GLX",
make_def_fun(*glx_ext_spec, output);//"GLX",
//
output.pop_back();
//
echo("\n#if !defined(GLEW_MX)", output);
echo("\nGLboolean __GLXEW_VERSION_1_0 = GL_FALSE;", output);
echo("GLboolean __GLXEW_VERSION_1_1 = GL_FALSE;", output);
//
make_def_var("GLX", *glx_core_spec, output);
make_def_var("GLX", *glx_ext_spec, output);
//
echo("\n#endif /* !GLEW_MX */\n", output);
//
make_init("GLX", *glx_core_spec, output);
make_init("GLX", *glx_ext_spec, output);
//
read_from_file(
combine(std::list<std::string>({ src, "glew_init_glx.c" })),
output);
//
std::string sub_output;
make_list("GLX_VERSION_1_3", *glx_core_spec, sub_output, ver);
grep(sub_output, "\"GLX_VERSION", true, output);
sub_output.clear();
//
make_list(*glx_ext_spec, output, ver);
//
echo("\n return GLEW_OK;\n}", output);
echo("\n#endif /* !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX)) */\n",
output);
//
const auto glew_init_tail = combine(std::list<std::string>({ src, "glew_init_tail.c" }));
std::ifstream file_stream(glew_init_tail);
if (file_stream.is_open())
{
std::list<std::string> parameters;
parameters.push_back(std::string("s/GLEW_VERSION_STRING/$(GLEW_VERSION)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MAJOR_STRING/$(GLEW_MAJOR)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MINOR_STRING/$(GLEW_MINOR)/g"));
parameters.push_back(std::string("s/GLEW_VERSION_MICRO_STRING/$(GLEW_MICRO)/g"));
if (!perl(file_stream, parameters, version, output, log))
{
log << "[Warning]: Command 'perl -e "
<< join("\nperl -e ", parameters)
<< "' was not be applied." << std::endl;
result = false;
}
file_stream.close();
}
else
{
log << "[Warning]: Unable to open '" << glew_init_tail << "'." << std::endl;
result = false;
}
read_from_file(
combine(std::list<std::string>({ src, "glew_str_head.c" })),
output);
//
make_str(*gl_core_spec, output);
make_str(*gl_ext_spec, output);
//
read_from_file(
combine(std::list<std::string>({ src, "glew_str_wgl.c" })),
output);
//
make_str(*wgl_ext_spec, output);
//
read_from_file(
combine(std::list<std::string>({ src, "glew_str_glx.c" })),
output);
//
make_str(*glx_core_spec, output);
make_str(*glx_ext_spec, output);
//
read_from_file(
combine(std::list<std::string>({ src, "glew_str_tail.c" })),
output);
//
auto parameter =
std::string("s/GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader\\(GLEW_CONTEXT_ARG_VAR_INIT\\);/{ GLEW_ARB_vertex_shader = !_glewInit_GL_ARB_vertex_shader(GLEW_CONTEXT_ARG_VAR_INIT); _glewInit_GL_ARB_vertex_program(GLEW_CONTEXT_ARG_VAR_INIT); }/g");
if (!perl(output, parameter))
{
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl;
result = false;
}
parameter =
std::string("s/\\(\\(glColorSubTable = /((glBlendEquation = (PFNGLBLENDEQUATIONPROC)glewGetProcAddress((const GLubyte*)\"glBlendEquation\")) == NULL) || r;\n r = ((glColorSubTable = /g");
if (!perl(output, parameter))
{
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl;
result = false;
}
return result;
}
bool wglew_h(const std::string& src,
const std::list<extension>& wgl_ext_spec,
const _version& version,
std::string& output,
std::ostream& log)
{
auto result = true;
//
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "khronos_license.h" })),
combine(std::list<std::string>({ src, "wglew_head.h" }))
});
for (const auto& file_path : start_content_files)
{
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
}
make_header("WINAPI", "WGL", wgl_ext_spec, output);
//
auto file_path = combine(std::list<std::string>({ src, "wglew_mid.h" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
if (version == version_1_13_0)
{
echo("\n#ifdef GLEW_MX\nstruct WGLEWContextStruct\n{\n#endif /* GLEW_MX */", output);
}
output.push_back('\n');
make_struct_fun("WGLEW_FUN_EXPORT", "", wgl_ext_spec, output);
output.pop_back();
make_struct_var("WGLEW_VAR_EXPORT", "", "WGL", wgl_ext_spec, output);
if (version == version_1_13_0)
{
echo("\n#ifdef GLEW_MX\n}; /* WGLEWContextStruct */\n#endif /* GLEW_MX */\n", output);
}
file_path = combine(std::list<std::string>({ src, "wglew_tail.h" }));
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
return result;
}
bool glxew_h(const std::string& src,
const std::list<extension>& glx_core_spec,
const std::list<extension>& glx_ext_spec,
const _version& version,
std::string& output,
std::ostream& log)
{
auto result = true;
//
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "mesa_license.h" })),
combine(std::list<std::string>({ src, "khronos_license.h" })),
combine(std::list<std::string>({ src, "glxew_head.h" }))
});
for (const auto& file_path : start_content_files)
{
read_from_file(file_path, output);
}
make_header("", "GLX", glx_core_spec, output);
make_header("", "GLX", glx_ext_spec, output);
//
read_from_file(combine(std::list<std::string>({ src, "glxew_mid.h" })), output);
//
output.push_back('\n');
make_struct_fun("GLXEW_FUN_EXPORT", "", glx_core_spec, output);
make_struct_fun("GLXEW_FUN_EXPORT", "", glx_ext_spec, output);
//
output.pop_back();
if (version == version_1_13_0)
{
echo("\n#if defined(GLEW_MX)\nstruct GLXEWContextStruct\n{\n#endif /* GLEW_MX */\n", output);
}
make_struct_var("GLXEW_VAR_EXPORT", "", "GLX", glx_core_spec, output);
make_struct_var("GLXEW_VAR_EXPORT", "", "GLX", glx_ext_spec, output);
if (version == version_1_13_0)
{
echo("\n#ifdef GLEW_MX\n}; /* GLXEWContextStruct */\n#endif /* GLEW_MX */\n", output);
}
static const auto parameter =
std::string("s/GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;/GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_0;\nGLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_1;\nGLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;/");
if (!perl(output, parameter))
{
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl;
result = false;
}
read_from_file(combine(std::list<std::string>({ src, "glxew_tail.h" })), output);
//
return result;
}
bool eglew_h(const std::string& src,
const std::list<extension>& egl_core_spec,
const std::list<extension>& egl_ext_spec,
std::string& output,
std::ostream& log)
{
auto result = true;
//
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "mesa_license.h" })),
combine(std::list<std::string>({ src, "khronos_license.h" })),
combine(std::list<std::string>({ src, "eglew_head.h" }))
});
for (const auto& file_path : start_content_files)
{
if (!read_from_file(file_path, output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
result = false;
}
}
make_header("", "EGL", egl_core_spec, output);
make_header("", "EGL", egl_ext_spec, output);
if (!read_from_file(combine(std::list<std::string>({ src, "eglew_mid.h" })), output))
{
log << "[Warning]: Unable to read from file '";
log << combine(std::list<std::string>({ src, "eglew_mid.h" }));
log << "'." << std::endl;
result = false;
}
//
output.push_back('\n');
make_struct_fun("EGLEW_FUN_EXPORT", "", egl_core_spec, output);
make_struct_fun("EGLEW_FUN_EXPORT", "", egl_ext_spec, output);
//
output.pop_back();
make_struct_var("EGLEW_VAR_EXPORT", "", "EGL", egl_core_spec, output);
make_struct_var("EGLEW_VAR_EXPORT", "", "EGL", egl_ext_spec, output);
if (!read_from_file(combine(std::list<std::string>({ src, "eglew_tail.h" })), output))
{
log << "[Warning]: Unable to read from file '";
log << combine(std::list<std::string>({ src, "eglew_tail.h" }));
log << "'." << std::endl;
result = false;
}
return result;
}
bool glewinfo_c(const std::string& src,
const std::list<std::list<extension>>& extensions,
const _version& version,
std::string& output,
std::ostream& log)
{
auto result = true;
//
const std::list<std::string> start_content_files(
{
combine(std::list<std::string>({ src, "glew_license.h" })),
combine(std::list<std::string>({ src, "glewinfo_head.c" }))
});
for (const auto& file_path : start_content_files)
{
read_from_file(file_path, output);
}
if (extensions.empty())
{
log << "[Error]: no extensions passed. Generation of content halted." << std::endl;
return false;
}
const auto gl_core_spec = extensions.cbegin();
make_info(*gl_core_spec, output);
//
const auto gl_ext_spec = get_next_extensions(gl_core_spec, extensions, "GL_EXT_SPEC", log);
if (gl_core_spec == gl_ext_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_info(*gl_ext_spec, output);
//
auto egl_core_spec = extensions.crbegin();
std::advance(egl_core_spec, 1);
const auto egl_ext_spec = extensions.crbegin();
if (version_2_2_2 == version)
{
echo("#if defined(GLEW_EGL)\n", output);
//
make_info(*egl_core_spec, output);
make_info(*egl_ext_spec, output);
//
echo("#elif _WIN32\n", output);
}
else if (version_1_13_0 == version)
{
echo("#ifdef _WIN32\n", output);
}
const auto wgl_ext_spec = get_next_extensions(gl_ext_spec, extensions, "WGL_EXT_SPEC", log);
if (gl_ext_spec == wgl_ext_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_info(*wgl_ext_spec, output);
echo("#else /* _UNIX */\n", output);
//
const auto glx_core_spec = get_next_extensions(wgl_ext_spec, extensions, "GLX_CORE_SPEC", log);
if (wgl_ext_spec == glx_core_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_info(*glx_core_spec, output);
//
const auto glx_ext_spec = get_next_extensions(glx_core_spec, extensions, "GLX_EXT_SPEC", log);
if (glx_core_spec == glx_ext_spec)
{
log << "[Error]: generation of content halted." << std::endl;
return false;
}
make_info(*glx_ext_spec, output);
echo("#endif /* _WIN32 */\n", output);
//
read_from_file(combine(std::list<std::string>({ src, "glewinfo_gl.c" })), output);
//
make_info_list(*gl_core_spec, output);
make_info_list(*gl_ext_spec, output);
//
read_from_file(combine(std::list<std::string>({ src, "glewinfo_wgl.c" })), output);
//
make_info_list(*wgl_ext_spec, output);
//
read_from_file(combine(std::list<std::string>({ src, "glewinfo_glx.c" })), output);
//
make_info_list(*glx_core_spec, output);
make_info_list(*glx_ext_spec, output);
if (version_2_2_2 == version)
{
read_from_file(combine(std::list<std::string>({ src, "glewinfo_egl.c" })), output);
//
make_info_list(*egl_core_spec, output);
make_info_list(*egl_ext_spec, output);
}
read_from_file(combine(std::list<std::string>({ src, "glewinfo_tail.c" })), output);
//
static const auto parameter =
std::string("s/\"glColorSubTable\"/\"glBlendEquation\", glBlendEquation == NULL);\n glewInfoFunc(\"glColorSubTable\"/g");
if (!perl(output, parameter))
{
log << "[Warning]: Command 'perl -e " << parameter << "' was not be applied." << std::endl;
result = false;
}
return result;
}
bool rc(const std::string& src,
const std::string& dst,
const std::list<std::pair<std::string, std::string>>& version,
std::string& tmp_output,
std::ostream& log)
{
auto result = true;
//
std::list<std::string> parameters;
parameters.push_back("s/GLEW_MAJOR/$(GLEW_MAJOR)/g");
parameters.push_back("s/GLEW_MINOR/$(GLEW_MINOR)/g");
parameters.push_back("s/GLEW_MICRO/$(GLEW_MICRO)/g");
//
std::list<std::string> file_list;
get_files_by_pattern(combine(std::list<std::string>({ src, "*.rc" })), file_list);
#ifndef _WIN32
file_list.remove_if(
[](const std::string & file_parth)
{
return !ends_with(file_parth, ".rc");
});
#endif
for (const auto& file_path : file_list)
{
std::ifstream file_stream(file_path);
if (file_stream.is_open())
{
tmp_output.clear();
if (!perl(file_stream, parameters, version, tmp_output, log))
{
log << "[Warning]: Command 'perl -e "
<< join("\nperl -e ", parameters)
<< "' was not be applied to file '" << file_path << "'." << std::endl;
result = false;
}
file_stream.close();
const auto file_dst = combine(std::list<std::string>({ dst, get_file_name(file_path) }));
if (!write_to_file(file_dst, tmp_output))
{
log << "[Warning]: Unable write to file '" << file_dst << "'." << std::endl;
result = false;
}
}
else
{
log << "[Warning]: Unable to open '" << file_path << "'." << std::endl;
result = false;
}
}
return result;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _GENERATOR_H_
#define _GENERATOR_H_
#include <list>
#include <string>
#include <utility>
#include <ostream>
struct extension;
struct _version;
bool glew_h(const std::string& src,
const std::list<std::list<extension>>& extensions,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log);
bool glew_c(const std::string& src,
const std::list<std::list<extension>>& extensions,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log);
bool wglew_h(const std::string& src,
const std::list<extension>& wgl_ext_spec,
const _version& version,
std::string& output,
std::ostream& log);
bool glxew_h(const std::string& src,
const std::list<extension>& glx_core_spec,
const std::list<extension>& glx_ext_spec,
const _version& version,
std::string& output,
std::ostream& log);
bool eglew_h(const std::string& src,
const std::list<extension>& egl_core_spec,
const std::list<extension>& egl_ext_spec,
std::string& output,
std::ostream& log);
bool glewinfo_c(const std::string& src,
const std::list<std::list<extension>>& extensions,
const _version& version,
std::string& output,
std::ostream& log);
bool rc(const std::string& src,
const std::string& dst,
const std::list<std::pair<std::string, std::string>>& version,
std::string& tmp_output,
std::ostream& log);
#endif
<?xml version="1.0" encoding="utf-8"?>
<Project InitialTargets="OpenGL-Registry" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)'==''">
<Configuration>Release</Configuration>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'==''">
<Platform>Win32</Platform>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<!--PlatformToolset>v120</PlatformToolset-->
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ItemGroup>
<ClInclude Include="$(ProjectDir)blacklist.h" />
<ClInclude Include="$(ProjectDir)common.h" />
<ClInclude Include="$(ProjectDir)descriptor.h" />
<ClInclude Include="$(ProjectDir)descriptors.h" />
<ClInclude Include="$(ProjectDir)filler.h" />
<ClInclude Include="$(ProjectDir)generator.h" />
<ClInclude Include="$(ProjectDir)interpreter.h" />
<ClInclude Include="$(ProjectDir)parse_xml.h" />
<ClInclude Include="$(ProjectDir)procedure.h" />
<ClInclude Include="$(ProjectDir)version.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(ProjectDir)blacklist.cpp" />
<ClCompile Include="$(ProjectDir)common.cpp" />
<ClCompile Include="$(ProjectDir)descriptor.cpp" />
<ClCompile Include="$(ProjectDir)descriptors.cpp" />
<ClCompile Include="$(ProjectDir)filler.cpp" />
<ClCompile Include="$(ProjectDir)generator.cpp" />
<ClCompile Include="$(ProjectDir)interpreter.cpp" />
<ClCompile Include="$(ProjectDir)main.cpp" />
<ClCompile Include="$(ProjectDir)parse_xml.cpp" />
<ClCompile Include="$(ProjectDir)procedure.cpp" />
<ClCompile Include="$(ProjectDir)version.cpp" />
</ItemGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<PropertyGroup Label="glew_repository">
<glew_url Condition="'$(LOCAL_FOLDER)'==''">https://github.com/nigels-com/glew.git</glew_url>
<glew_url Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\glew</glew_url>
<glew_destination>$(ProjectDir)..\glew</glew_destination>
<glew_destination Condition="''!='$(NO_GIT)'">$(glew_url)</glew_destination>
<glew_hash>7f65a36866f4e24dd1446fe1c9d21424f28bcabd</glew_hash>
</PropertyGroup>
<PropertyGroup Label="OpenGL-Registry_repository">
<url_1 Condition="'$(LOCAL_FOLDER)'==''">https://github.com/KhronosGroup/OpenGL-Registry.git</url_1>
<url_1 Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\OpenGL-Registry</url_1>
<destination_1>$(ProjectDir)..\OpenGL-Registry</destination_1>
<destination_1 Condition="''!='$(NO_GIT)'">$(url_1)</destination_1>
<hash_1>39e37f83823d5d04dd727ab1c146158a9888adb7</hash_1>
</PropertyGroup>
<PropertyGroup Label="EGL-Registry_repository">
<url_2 Condition="'$(LOCAL_FOLDER)'==''">https://github.com/KhronosGroup/EGL-Registry.git</url_2>
<url_2 Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\EGL-Registry</url_2>
<destination_2>$(ProjectDir)..\EGL-Registry</destination_2>
<destination_2 Condition="''!='$(NO_GIT)'">$(url_2)</destination_2>
<hash_2>9ed2ec4c6746e622207f48c898a92fda8b122da5</hash_2>
</PropertyGroup>
<PropertyGroup Label="glfixes_repository">
<glfixes_url Condition="'$(LOCAL_FOLDER)'==''">https://github.com/nigels-com/glfixes</glfixes_url>
<glfixes_url Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\glfixes</glfixes_url>
<glfixes_destination>$(ProjectDir)..\glfixes</glfixes_destination>
<glfixes_destination Condition="''!='$(NO_GIT)'">$(glfixes_url)</glfixes_destination>
<glfixes_hash>970b8145acd42ebd86ff025e1eb8c8cbcd1fc6a2</glfixes_hash>
</PropertyGroup>
<PropertyGroup>
<Index Condition="''!='$(MSBuildThisFileDirectory)'">$(MSBuildThisFileDirectory.LastIndexOf('\'))</Index>
<ParentDirectory Condition="-1!=$(Index)">$(MSBuildThisFileDirectory.Substring(0, $(Index)))</ParentDirectory>
<Index Condition="''!='$(ParentDirectory)'">$(ParentDirectory.LastIndexOf('\'))</Index>
<ParentDirectory Condition="-1!=$(Index)">$(ParentDirectory.Substring(0, $(Index)))</ParentDirectory>
</PropertyGroup>
<PropertyGroup Condition="$(ParentDirectory.EndsWith('auto'))">
<Index Condition="''!='$(ParentDirectory)'">$(ParentDirectory.LastIndexOf('\'))</Index>
<ParentDirectory Condition="-1!=$(Index)">$(ParentDirectory.Substring(0, $(Index)))</ParentDirectory>
<glew_destination>$(ParentDirectory)</glew_destination>
</PropertyGroup>
<PropertyGroup Label="Destination_folder">
<DestinationFolder>$(ProjectDir)</DestinationFolder>
<DestinationFolder Condition="Exists('$(ProjectDir)..\..\auto')">$([System.IO.Path]::GetFullPath('$(ProjectDir)..\..\'))</DestinationFolder>
</PropertyGroup>
<Target Name="OpenGL-Registry" Condition="''=='$(NO_GIT)'">
<Message Importance="normal" Text="--------------------------------------------------------------------" />
<Message Importance="normal" Text="Downloading OpenGL-Registry" />
<Message Importance="normal" Text="--------------------------------------------------------------------" />
<Message Importance="low" Text="git clone $(glew_url) $(glew_destination)" />
<Message Importance="low" Text="git clone $(url_1) $(destination_1)" />
<Message Importance="low" Text="git clone $(url_2) $(destination_2)" />
<Message Importance="low" Text="git clone --branch glew $(glfixes_url) $(glfixes_destination)" />
<Exec
Command="git --version"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="!$(ParentDirectory.EndsWith('auto')) And !Exists('$(glew_destination)\.git\HEAD')"
Command="git clone $(glew_url) $(glew_destination)"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="!Exists('$(destination_1)\.git\HEAD')"
Command="git clone $(url_1) $(destination_1)"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="!Exists('$(destination_2)\.git\HEAD')"
Command="git clone $(url_2) $(destination_2)"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="!Exists('$(glfixes_destination)\.git\HEAD')"
Command="git clone $(glfixes_url) $(glfixes_destination)"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="$(ParentDirectory.EndsWith('auto')) And Exists('$(glew_destination)\.git\HEAD')"
Command="git log -1 --pretty=oneline"
WorkingDirectory="$(glew_destination)" />
<Exec
Condition="Exists('$(destination_1)\.git\HEAD')"
Command="git log -1 --pretty=oneline"
WorkingDirectory="$(destination_1)" />
<Exec
Condition="Exists('$(destination_2)\.git\HEAD')"
Command="git log -1 --pretty=oneline"
WorkingDirectory="$(destination_2)" />
<Exec
Condition="Exists('$(glfixes_destination)\.git\HEAD')"
Command="git log -1 --pretty=oneline"
WorkingDirectory="$(glfixes_destination)" />
</Target>
<Target Name="AfterBuild" Condition="Exists('$(TargetPath)')">
<Message Importance="normal" Text="Executing '$(TargetPath) $(glew_destination) $(glfixes_destination) $(destination_1) $(destination_2) $(DestinationFolder)' at '$(OutDir)'" />
<Exec
Command="$(TargetPath) $(glew_destination) $(glfixes_destination) $(destination_1) $(destination_2) $(DestinationFolder)"
WorkingDirectory="$(OutDir)" />
</Target>
</Project>
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "input_output.h"
#include <cstring>
#include <utility>
#include <ostream>
#include <sstream>
#include <istream>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
void read_from_stream(std::istream& stream, std::string& content)
{
std::copy(std::istreambuf_iterator<char>(stream),
std::istreambuf_iterator<char>(), std::back_inserter(content));
}
bool write_to_stream(std::ostream& stream, const std::string& content)
{
return !std::copy(content.cbegin(), content.cend(),
std::ostreambuf_iterator<char>(stream)).failed();
}
void read_from_cin(std::string& content)
{
read_from_stream(std::cin, content);
}
bool write_to_cout(const std::string& content)
{
return write_to_stream(std::cout, content);
}
#if 0
void read_from_file(const std::string& file_name, std::stringstream& content)
{
std::ifstream file_stream(file_name);
if (file_stream.is_open())
{
content << file_stream.rdbuf();
}
}
bool write_to_file(const std::string& file_name, const std::stringstream& content)
{
std::ofstream file_stream(file_name);
if (file_stream.is_open())
{
file_stream << content.str();
return true;
/*
const auto str = content.str();
return !std::copy(str.cbegin(), str.cend(),
std::ostreambuf_iterator<char>(file_stream)).failed();*/
}
return false;
}
#endif
bool read_from_file(const std::string& file_name, std::string& content)
{
std::ifstream file_stream(file_name);
if (file_stream.is_open())
{
read_from_stream(file_stream, content);
file_stream.close();
return true;
}
return false;
}
bool write_to_file(const std::string& file_name, const std::string& content)
{
std::ofstream file_stream(file_name);
if (file_stream.is_open())
{
return write_to_stream(file_stream, content);
}
return false;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include <string>
#ifndef _INPUT_OUTPUT_H_
#define _INPUT_OUTPUT_H_
void read_from_cin(std::string& content);
bool write_to_cout(const std::string& content);
bool read_from_file(const std::string& file_name, std::string& content);
bool write_to_file(const std::string& file_name, const std::string& content);
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "interpreter.h"
#include "input_output.h"
#include "path.h"
#include "common.h"
#include <set>
#include <regex>
#include <cctype>
#include <cassert>
#include <cstdlib>
#include <iterator>
#include <algorithm>
std::regex create_regex(const std::string& str_pattern, bool& is_created) //TODO: add std::ostream& log
{
is_created = false;
try
{
const auto pattern = std::regex(str_pattern);
is_created = true;
return pattern;
}
catch (const std::regex_error& exc)
{
write_to_cout(
std::string("[Error]: std::regex_error caught '") + exc.what() + "' for expression '" + str_pattern + "'.\n");
switch (exc.code())
{
case std::regex_constants::error_collate:
write_to_cout(std::string("\tThe expression contains an invalid collating element name.\n"));
break;
case std::regex_constants::error_ctype:
write_to_cout(std::string("\tThe expression contains an invalid character class name.\n"));
break;
case std::regex_constants::error_escape:
write_to_cout(std::string("\tThe expression contains an invalid escaped character or a trailing escape.\n"));
break;
case std::regex_constants::error_backref:
write_to_cout(std::string("\tThe expression contains an invalid back reference.\n"));
break;
case std::regex_constants::error_brack:
write_to_cout(std::string("\tThe expression contains mismatched square brackets ('[' and ']').\n"));
break;
case std::regex_constants::error_paren:
write_to_cout(std::string("\tThe expression contains mismatched parentheses ('(' and ')').\n"));
break;
case std::regex_constants::error_brace:
write_to_cout(std::string("\tThe expression contains mismatched curly braces ('{' and '}').\n"));
break;
case std::regex_constants::error_badbrace:
write_to_cout(std::string("\tThe expression contains an invalid range in a {} expression.\n"));
break;
case std::regex_constants::error_range:
write_to_cout(std::string("\tThe expression contains an invalid character range (e.g. [b-a]).\n"));
break;
case std::regex_constants::error_space:
write_to_cout(
std::string("\tThere was not enough memory to convert the expression into a finite state machine.\n"));
break;
case std::regex_constants::error_badrepeat:
write_to_cout(std::string("\tOne of *?+{ was not preceded by a valid regular expression.\n"));
break;
case std::regex_constants::error_complexity:
write_to_cout(std::string("\tThe complexity of an attempted match exceeded a predefined level.\n"));
break;
case std::regex_constants::error_stack:
write_to_cout(std::string("\tThere was not enough memory to perform a match.\n"));
break;
default:
//std::regex_constants::error_parse:
//std::regex_constants::error_syntax:
break;
}
}
return std::regex();
}
std::string get_name_of_output(
const std::pair<std::string::const_iterator, std::string::const_iterator>& command, bool& create_new_content)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
auto pos = find_phrase_start(command, ">>");
if (std::get<1>(command) == pos)
{
pos = std::find_if(std::get<0>(command), std::get<1>(command),
[](const char& ch)
{
return '>' == ch;
});
if (std::get<1>(command) == pos)
{
return std::string();
}
create_new_content = true;
std::advance(pos, 1);
}
else
{
create_new_content = false;
std::advance(pos, 2);
}
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, true);
if (std::get<1>(command) == pos)
{
return std::string();
}
std::advance(pos, 1);
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, false);
if (std::get<1>(command) == pos)
{
return std::string();
}
const auto value_start = pos;
std::advance(pos, 1);
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, true);
if (std::get<1>(command) == pos)
{
return std::string(value_start, std::get<1>(command));
}
std::advance(pos, 1);
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(command)), tab_space, false);
if (std::get<1>(command) == pos)
{
auto tmp = std::string(pos, std::get<1>(command));
trim(tmp);
return tmp;
}
return std::string();
}
std::string get_name_of_output(const std::string& command, bool& create_new_content)
{
return get_name_of_output(std::make_pair(command.cbegin(), command.cend()), create_new_content);
}
bool echo(const std::string& text, std::ostream& output)
{
output << text << std::endl;
return true;
}
bool echo(const std::string& text, std::string& output)
{
output += text + '\n';
return true;
}
bool grep(std::istream& input, const std::string& target, bool should_be_contains, std::ostream& output)
{
auto was_command_be_apply = false;
for (std::string line; std::getline(input, line);)
{
if (should_be_contains == contains(line, target))
{
continue;
}
output << line << std::endl;
was_command_be_apply = true;
}
return was_command_be_apply;
}
bool grep(const std::string& input, const std::string& target, bool should_be_contains, std::string& output)
{
auto was_command_be_apply = false;
auto value_pair = std::make_pair(input.cbegin(), input.cend());
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
if (should_be_contains == contains(line, target))
{
continue;
}
std::copy(std::get<0>(line),
std::get<1>(line),
std::back_inserter(output));
output.push_back('\n');
was_command_be_apply = true;
}
return was_command_be_apply;
}
bool grep(std::istream& source, std::istream& target, std::ostream& output)
{
auto was_command_be_apply = false;
std::set<std::string> source_lines;
for (std::string source_line; std::getline(source, source_line);)
{
source_lines.insert(source_line);
}
for (std::string taget_line; std::getline(target, taget_line);)
{
if (0 != source_lines.count(taget_line))
{
continue;
}
output << taget_line << std::endl;
was_command_be_apply = true;
}
return was_command_be_apply;
}
bool grep(const std::string& source, const std::string& target, std::string& output)
{
auto was_command_be_apply = false;
auto value_pair = make_pair(source.cbegin(), source.cend());
std::list<std::pair<std::size_t, std::pair<std::string::const_iterator, std::string::const_iterator>>>
source_lines;
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
const auto line_size = static_cast<std::size_t>(std::distance(std::get<0>(line), std::get<1>(line)));
//
const auto exists_line = std::find_if(source_lines.cbegin(), source_lines.cend(),
[&line, &line_size](const
std::pair<std::size_t, std::pair<std::string::const_iterator, std::string::const_iterator>>& source_line)
{
return line_size == std::get<0>(source_line) && contains(line, std::get<1>(source_line));
});
if (source_lines.cend() == exists_line)
{
source_lines.push_back(std::make_pair(line_size, line));
}
}
value_pair = make_pair(target.cbegin(), target.cend());
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
const auto line_size = static_cast<std::size_t>(std::distance(std::get<0>(line), std::get<1>(line)));
//
const auto exists_line = std::find_if(source_lines.cbegin(), source_lines.cend(),
[&line, &line_size](const
std::pair<std::size_t, std::pair<std::string::const_iterator, std::string::const_iterator>>& source_line)
{
return line_size == std::get<0>(source_line) && contains(line, std::get<1>(source_line));
});
if (source_lines.cend() != exists_line)
{
continue;
}
std::copy(std::get<0>(line),
std::get<1>(line),
std::back_inserter(output));
output.push_back('\n');
was_command_be_apply = true;
}
return was_command_be_apply;
}
bool egrep(std::istream& input, const std::string& pattern_target, std::ostream& output)
{
auto was_command_be_apply = false;
const auto pattern = create_regex(pattern_target, was_command_be_apply);
if (!was_command_be_apply)
{
return was_command_be_apply;
}
was_command_be_apply = false;
for (std::string line; std::getline(input, line);)
{
if (std::regex_search(line, pattern))
{
continue;
}
output << line << std::endl;
was_command_be_apply = true;
}
return was_command_be_apply;
}
bool egrep(const std::string& input, const std::string& pattern_target, std::string& output)
{
auto was_command_be_apply = false;
const auto pattern = create_regex(pattern_target, was_command_be_apply);
if (!was_command_be_apply)
{
return was_command_be_apply;
}
was_command_be_apply = false;
auto value_pair = std::make_pair(input.cbegin(), input.cend());
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
if (std::regex_search(std::string(std::get<0>(line), std::get<1>(line)), pattern))
{
continue;
}
std::copy(std::get<0>(line),
std::get<1>(line),
std::back_inserter(output));
output.push_back('\n');
was_command_be_apply = true;
}
return was_command_be_apply;
}
bool cat(std::istream& input, const std::string& text, std::ostream& output)
{
const auto copy_ok = !std::copy(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(output)).failed();
if (copy_ok && !text.empty())
{
output << text;
}
return copy_ok;
}
bool cat(const std::string& input, std::string& output)
{
std::copy(
input.cbegin(),
input.cend(),
std::back_inserter(output));
return !input.empty() && !output.empty();
}
bool head(std::istream& input, const std::string& command, std::ostream& output)
{
static const auto key_n = std::string("-n");
auto command_start = find_phrase_start(command, key_n);
if (command_start != command.cend())
{
std::advance(command_start, key_n.size());
//
command_start = std::find_if(command_start, command.cend(), [](const char& ch)
{
return std::isdigit(ch);
});
if (command_start != command.cend())
{
char* ch = nullptr;
const auto count = std::strtol(&(*command_start), &ch, 10);
if (ch != &(*command_start))
{
auto i = static_cast<long>(0);
for (std::string line; std::getline(input, line) && i < count; ++i)
{
output << line << std::endl;
}
return (0 != count);
}
}
}
return false;
}
bool head(const std::string& input, const std::string& command, std::string& output)
{
auto n = static_cast<long>(0);
for (auto i = static_cast<std::size_t>(0), count = command.size(); i < count; ++i)
{
if (!std::isdigit(command[i]))
{
continue;
}
char* ch = nullptr;
n = std::strtol(&command[i], &ch, 10);
if (ch != &command[i])
{
break;
}
}
auto step = static_cast<long>(0);
auto value_pair = std::make_pair(input.cbegin(), input.cend());
while ((std::get<1>(value_pair) != std::get<0>(value_pair)) && step < n)
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
std::copy(std::get<0>(line),
std::get<1>(line),
std::back_inserter(output));
output.push_back('\n');
++step;
}
return (0 != n);
}
bool tail(std::istream& input, const std::string& command, std::ostream& output)
{
auto was_command_be_apply = false;
auto n = static_cast<long>(0);
for (auto i = static_cast<std::size_t>(0), count = command.size(); i < count; ++i)
{
if (!std::isdigit(command[i]))
{
continue;
}
char* ch = nullptr;
n = std::strtol(&command[i], &ch, 10);
if (ch != &command[i])
{
break;
}
}
auto line_num = static_cast<long>(1);
for (std::string line; std::getline(input, line);)
{
if (was_command_be_apply || n == line_num || 0 == n)
{
was_command_be_apply = true;
output << line << std::endl;
}
else
{
++line_num;
}
}
return was_command_be_apply;
}
bool tail(const std::string& input, const std::string& command, std::string& output)
{
auto was_command_be_apply = false;
auto n = static_cast<long>(0);
for (auto i = static_cast<std::size_t>(0), count = command.size(); i < count; ++i)
{
if (!std::isdigit(command[i]))
{
continue;
}
char* ch = nullptr;
n = std::strtol(&command[i], &ch, 10);
if (ch != &command[i])
{
break;
}
}
auto line_num = static_cast<long>(1);
auto value_pair = std::make_pair(input.cbegin(), input.cend());
while ((std::get<1>(value_pair) != std::get<0>(value_pair)))
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
if (was_command_be_apply || n == line_num || 0 == n)
{
was_command_be_apply = true;
std::copy(std::get<0>(line),
std::get<1>(line),
std::back_inserter(output));
output.push_back('\n');
}
else
{
++line_num;
}
}
return was_command_be_apply;
}
std::pair<std::string, std::string> disassemble_perl_parameter(
const std::pair<std::string::const_iterator, std::string::const_iterator>& parameter)
{
const auto parameter_size = static_cast<std::size_t>(std::distance(std::get<0>(parameter),
std::get<1>(parameter)));
auto result = std::make_pair(std::string(parameter_size, '\0'), std::string(parameter_size, '\0'));
std::get<0>(result).clear();
std::get<1>(result).clear();
if (parameter_size < 2 || 's' != *std::get<0>(parameter))
{
return result;
}
auto split_position = std::get<0>(parameter);
std::advance(split_position, 1);
const auto split_symbol = std::string(1, *split_position);
auto value_pair = std::make_pair(find_phrase_start(parameter, split_symbol), std::get<1>(parameter));
auto current = &(std::get<0>(result));
for (auto i = 0; i < 2; ++i)
{
std::advance(std::get<0>(value_pair), 1);
auto value_start = std::get<0>(value_pair);
std::get<0>(value_pair) = find_phrase_start(value_pair, split_symbol);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return result;
}
auto prev_symbol = std::get<0>(value_pair);
std::advance(prev_symbol, -1);
if ('\\' == (*prev_symbol))
{
--i;
(*current) += std::string(value_start, std::get<0>(value_pair)) + split_symbol;
continue;
}
(*current) += std::string(value_start, std::get<0>(value_pair));
current = &(std::get<1>(result));
}
replace(std::get<0>(result), std::string("\\") + split_symbol, split_symbol);
replace(std::get<1>(result), std::string("\\") + split_symbol, split_symbol);
//
return result;
}
std::pair<std::string, std::string> disassemble_perl_parameter(const std::string& parameter)
{
return disassemble_perl_parameter(std::make_pair(parameter.cbegin(), parameter.cend()));
}
bool perl(std::istream& input, const std::string& command, std::ostream& output)
{
static const auto key_s = std::string("'s");
static const auto key_s_ = std::string("\"s");
assert(key_s.size() == key_s_.size());
auto was_command_be_apply = false;
auto command_start = find_phrase_start(command, key_s);
if (command_start == command.cend())
{
command_start = find_phrase_start(command, key_s_);
}
if (command_start != command.cend())
{
std::advance(command_start, 1);
const auto parameter_elements = disassemble_perl_parameter(std::make_pair(command_start, command.cend()));
const auto pattern = create_regex(std::get<0>(parameter_elements), was_command_be_apply);
if (!was_command_be_apply)
{
return was_command_be_apply;
}
was_command_be_apply = false;
for (std::string line, old_line; std::getline(input, line);)
{
if (!was_command_be_apply)
{
old_line = line;
}
line = std::regex_replace(line, pattern, std::get<1>(parameter_elements));
if (!was_command_be_apply)
{
if (old_line != line)
{
was_command_be_apply = true;
old_line.clear();
}
}
output << line << std::endl;
}
}
return was_command_be_apply;
}
bool perl(const std::string& input, const std::string& parameter, std::string& output)
{
auto was_command_be_apply = false;
const auto parameter_elements = disassemble_perl_parameter(parameter);
if (std::get<0>(parameter_elements).empty())
{
return was_command_be_apply;
}
const auto pattern = create_regex(std::get<0>(parameter_elements), was_command_be_apply);
if (!was_command_be_apply)
{
return was_command_be_apply;
}
was_command_be_apply = false;
auto value_pair = std::make_pair(input.cbegin(), input.cend());
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
const auto line = get_line(value_pair, std::get<0>(value_pair));
const auto new_line = std::regex_replace(
std::string(std::get<0>(line), std::get<1>(line)),
pattern, std::get<1>(parameter_elements));
if (!was_command_be_apply)
{
if (std::string(std::get<0>(line), std::get<1>(line)) != new_line)
{
was_command_be_apply = true;
}
}
output += new_line;
output.push_back('\n');
}
return was_command_be_apply;
}
bool perl(std::string& content, const std::string& parameter)
{
auto was_command_be_apply = false;
const auto parameter_elements = disassemble_perl_parameter(parameter);
if (std::get<0>(parameter_elements).empty())
{
return was_command_be_apply;
}
const auto pattern = create_regex(std::get<0>(parameter_elements), was_command_be_apply);
if (!was_command_be_apply)
{
return was_command_be_apply;
}
was_command_be_apply = false;
auto content_position = content.cbegin();
std::sregex_iterator pos(content_position, content.cend(), pattern);
std::sregex_iterator end;
for (; pos != end;)
{
was_command_be_apply = true;
const auto absolute_position = std::distance(content.cbegin(), content_position) + pos->position();
const auto distance = absolute_position + std::get<1>(parameter_elements).size();
if (static_cast<std::size_t>(pos->length()) < std::get<1>(parameter_elements).size())
{
const auto delta = std::get<1>(parameter_elements).size() - pos->length();
const auto count = content.size() + delta;
content.resize(count);
//
std::copy(content.cbegin() + absolute_position + pos->length(),
content.cbegin() + count - delta,
content.begin() + absolute_position + std::get<1>(parameter_elements).size());
//
std::copy(std::get<1>(parameter_elements).cbegin(),
std::get<1>(parameter_elements).cend(),
content.begin() + absolute_position);
}
else
{
std::copy(std::get<1>(parameter_elements).cbegin(),
std::get<1>(parameter_elements).cend(),
content.begin() + absolute_position);
if (std::get<1>(parameter_elements).size() < static_cast<std::size_t>(pos->length()))
{
const auto delta = pos->length() - std::get<1>(parameter_elements).size();
const auto count = content.size() - delta;
for (auto i = distance; i < count; ++i)
{
content[i] = content[i + delta];
}
content.resize(count);
}
}
content_position = content.cbegin();
std::advance(content_position, distance);
pos = std::sregex_iterator(content_position, content.cend(), pattern);
}
return was_command_be_apply;
}
#define process_target(value_pair, value_start, quote, tab_space) \
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \
\
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \
{ \
return false; \
} \
\
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); \
\
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \
{ \
return false; \
} \
\
if (0 != quote.count(*std::get<0>(value_pair))) \
{ \
const auto key_symbol = std::string(1, *std::get<0>(value_pair)); \
std::advance(std::get<0>(value_pair), 1); \
value_start = std::get<0>(value_pair); \
std::get<0>(value_pair) = find_phrase_start(value_pair, key_symbol); \
\
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \
{ \
return false; \
} \
} \
else \
{ \
value_start = std::get<0>(value_pair); \
std::advance(std::get<0>(value_pair), 1); \
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \
\
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \
{ \
return false; \
} \
} \
\
const auto target = std::string(value_start, std::get<0>(value_pair));
#define process_input(value_pair, value_start, data, tab_space) \
std::advance(std::get<0>(value_pair), 1); \
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \
\
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \
{ \
return false; \
} \
\
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false); \
\
if (std::get<1>(value_pair) == std::get<0>(value_pair)) \
{ \
return false; \
} \
\
value_start = std::get<0>(value_pair); \
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true); \
\
const auto path_separator = find_phrase_start( \
std::make_pair(value_start, std::get<0>(value_pair)), "/"); \
if (std::get<0>(value_pair) != path_separator) \
{ \
value_start = path_separator; \
std::advance(value_start, 1); \
} \
\
const auto input_name = std::string(value_start, std::get<0>(value_pair)); \
const auto input = std::find_if(data.cbegin(), data.cend(), \
[&input_name](const std::pair<std::string, std::string>& element) \
{ \
return element_name(element) == input_name; \
}); \
\
if (data.end() == input) \
{ \
return false; \
}
#define process_output(value_pair, data) \
auto create_new_content = true; \
const auto output_name = get_name_of_output(value_pair, create_new_content); \
\
if (output_name.empty()) \
{ \
return false; \
} \
\
auto output = std::find_if(data.begin(), data.end(), \
[&output_name](const std::pair<std::string, std::string>& element) \
{ \
return element_name(element) == output_name; \
}); \
\
if (data.end() == output) \
{ \
output = data.begin(); \
data.push_back(std::make_pair(output_name, std::string())); \
std::advance(output, data.size() - 1); \
} \
\
else if (create_new_content) \
{ \
std::get<1>(*output).clear(); \
}
bool grep(const std::string& command, IEnumerableData& data)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
static const auto quote = std::set<char>({ '"', '\'' });
//
auto positions = std::set<std::string::const_iterator>(
{
find_phrase_start(command, "-v"),
find_phrase_start(command, "-f"),
find_phrase_start(command, "-F"),
command.cend()
});
positions.erase(positions.find(command.cend()));
if (positions.empty())
{
auto value_pair = std::make_pair(command.cbegin(), command.cend());
std::string::const_iterator value_start;
process_target(value_pair, value_start, quote, tab_space)
process_input(value_pair, value_start, data, tab_space)
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return grep(std::get<1>(*input), target, false, std::get<1>(*output));
}
#ifndef NDEBUG
else
{
std::string str_output(std::get<1>(*input).size(), '\0');
str_output.clear();
const auto was_command_be_apply = grep(std::get<1>(*input), target, false, str_output);
write_to_cout(str_output);
return was_command_be_apply;
}
#endif
}
else if (1 == positions.size())
{
auto value_pair = std::make_pair(*positions.crbegin(), command.cend());
std::string::const_iterator value_start;
process_target(value_pair, value_start, quote, tab_space)
std::advance(std::get<0>(value_pair), -1); //TODO:
process_input(value_pair, value_start, data, tab_space)
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return grep(std::get<1>(*input), target, true, std::get<1>(*output));
}
#ifndef NDEBUG
else
{
std::string str_output(std::get<1>(*input).size(), '\0');
str_output.clear();
const auto was_command_be_apply = grep(std::get<1>(*input), target, true, str_output);
write_to_cout(str_output);
return was_command_be_apply;
}
#endif
}
else if (3 == positions.size())
{
auto value_pair = std::make_pair(*positions.crbegin(), command.cend());
std::string::const_iterator value_start;
std::list<IEnumerableData::const_iterator> source_target;
for (auto i = 0; i < 2; ++i)
{
process_input(value_pair, value_start, data, tab_space)
std::advance(std::get<0>(value_pair), -1);
source_target.push_back(input);
}
std::advance(std::get<0>(value_pair), 1);
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return grep(std::get<1>(*(*source_target.cbegin())), std::get<1>(*(*source_target.crbegin())),
std::get<1>(*output));
}
#ifndef NDEBUG
else
{
const auto size = std::max(std::get<1>(*(*source_target.cbegin())).size(),
std::get<1>(*(*source_target.crbegin())).size());
std::string str_output(size, '\0');
str_output.clear();
const auto was_command_be_apply = grep(std::get<1>(*(*source_target.cbegin())),
std::get<1>(*(*source_target.crbegin())), str_output);
write_to_cout(str_output);
return was_command_be_apply;
}
#endif
}
#ifndef NDEBUG
else
{
write_to_cout("[Warning]: Used non supported scenario of command: '" + command + "'\n");
}
#endif
return false;
}
bool egrep(const std::string& command, IEnumerableData& data)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
//
auto value_pair = std::make_pair(find_phrase_start(command, "'"), command.cend());
//TODO: use process_target, that have several variants for quote symbol
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
std::advance(std::get<0>(value_pair), 1);
auto value_start = std::get<0>(value_pair);
std::get<0>(value_pair) = find_phrase_start(value_pair, "'");
if (std::get<1>(value_pair) == std::get<0>(value_pair) || value_start == std::get<0>(value_pair))
{
return false;
}
const auto pattern_target = std::string(value_start, std::get<0>(value_pair));
process_input(value_pair, value_start, data, tab_space)
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return egrep(std::get<1>(*input), pattern_target, std::get<1>(*output));
}
#ifndef NDEBUG
std::string str_output(std::get<1>(*input).size(), '\0');
str_output.clear();
const auto was_command_be_apply = egrep(std::get<1>(*input), pattern_target, str_output);
write_to_cout(str_output);
return was_command_be_apply;
#else
return false;
#endif
}
bool cat(const std::string& command, IEnumerableData& data)
{
static const auto key_shift = std::string(">>");
static const auto key_EOT_start = std::string("<<EOT");
static const auto key_EOT_finish = std::string("EOT");
//
static const auto tab_space = std::set<char>({ '\t', ' ' });
static const auto tab_space_new_line = std::set<char>({ '\t', ' ', '\n' });
if (contains(command, key_shift) && contains(command, key_EOT_start))
{
auto value_pair = std::make_pair(find_phrase_start(command, key_shift), command.cend());
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
std::advance(std::get<0>(value_pair), key_shift.size());
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
auto value_end = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true);
if (std::get<1>(value_pair) == value_end)
{
return false;
}
auto value_start = find_phrase_start(std::make_pair(std::get<0>(value_pair), value_end), "/");
if (value_start != value_end)
{
std::advance(value_start, 1);
std::get<0>(value_pair) = value_start;
}
if (value_start == value_end)
{
return false;
}
const auto target_element = std::string(value_start, value_end);
std::get<0>(value_pair) = find_phrase_start(value_pair, key_EOT_start);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
std::advance(std::get<0>(value_pair), key_EOT_start.size());
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space_new_line, true);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
std::advance(std::get<0>(value_pair), 1);
const auto value_end_ = rfind_phrase_start(std::make_pair(command.crbegin(), command.crend()),
key_EOT_finish);
if (command.crend() == value_end_)
{
return false;
}
const auto off = command.size() - 1 - static_cast<std::size_t>(std::distance(command.crbegin(), value_end_));
value_end = command.cbegin();
std::advance(value_end, off);
if (std::get<0>(value_pair) == value_end)
{
return false;
}
const auto text = std::string(std::get<0>(value_pair), value_end);
const auto find_result = std::find_if(data.begin(), data.end(),
[&target_element](const std::pair<std::string, std::string>& element)
{
return element_name(element) == target_element;
});
if (data.cend() == find_result)
{
return false;
}
std::get<1>(*find_result) += text;
return true;
}
else
{
auto value_pair = std::make_pair(command.cbegin(), command.cend());
auto value_start = command.cbegin();
process_input(value_pair, value_start, data, tab_space)
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return cat(std::get<1>(*input), std::get<1>(*output));
}
}
return false;
}
bool head(const std::string& command, IEnumerableData& data)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
static const std::set<char> quote;
//
auto value_pair = std::make_pair(command.cbegin(), command.cend());
std::string::const_iterator value_start;
process_target(value_pair, value_start, quote, tab_space)
std::advance(std::get<0>(value_pair), -1);
process_input(value_pair, value_start, data, tab_space)
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return head(std::get<1>(*input), target, std::get<1>(*output));
}
#ifndef NDEBUG
else
{
std::string str_output(std::get<1>(*input).size(), '\0');
str_output.clear();
const auto was_command_be_apply = head(std::get<1>(*input), target, str_output);
write_to_cout(str_output);
return was_command_be_apply;
}
#endif
return false;
}
bool tail(const std::string& command, IEnumerableData& data)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
static const std::set<char> quote;
//
auto value_pair = std::make_pair(command.cbegin(), command.cend());
std::string::const_iterator value_start;
{
process_target(value_pair, value_start, quote, tab_space)
}
process_target(value_pair, value_start, quote, tab_space)
std::advance(std::get<0>(value_pair), -1);
process_input(value_pair, value_start, data, tab_space)
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
process_output(value_pair, data)
return tail(std::get<1>(*input), target, std::get<1>(*output));
}
#ifndef NDEBUG
else
{
std::string str_output(std::get<1>(*input).size(), '\0');
str_output.clear();
const auto was_command_be_apply = tail(std::get<1>(*input), target, str_output);
write_to_cout(str_output);
return was_command_be_apply;
}
#endif
return false;
}
bool perl(const std::string& command, IEnumerableData& data)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
static const auto quote = std::string(1, '\'');
//
auto value_pair = std::make_pair(command.cbegin(), command.cend());
std::get<0>(value_pair) = find_phrase_start(value_pair, quote);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
std::advance(std::get<0>(value_pair), 1);
auto value_start = std::get<0>(value_pair);
std::get<0>(value_pair) = find_phrase_start(value_pair, quote);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
return false;
}
const auto target = std::string(value_start, std::get<0>(value_pair));
std::advance(std::get<0>(value_pair), 1);
process_input(value_pair, value_start, data, tab_space)
if (!std::get<1>(*input).empty())
{
std::string str_output(2 * std::get<1>(*input).size(), '\0');
str_output.clear();
const auto was_command_be_apply = perl(std::get<1>(*input), target, str_output);
if (was_command_be_apply)
{
const auto off = std::distance(data.cbegin(), input);
auto output = data.begin();
std::advance(output, off);
assert(std::get<0>(*input) == std::get<0>(*output));
if (std::get<0>(*input) != std::get<0>(*output))
{
return false;
}
std::get<1>(*output) = str_output;
}
return was_command_be_apply;
}
return false;
}
bool mv(const std::string& command, IEnumerableData& data)
{
const auto command_components = split(command, std::set<char>({ '\t', ' ' }), true);
if (3 != command_components.size())
{
return false;
}
auto skip = true;
auto mv_pair = std::make_pair(std::string(), std::string());
for (const auto& name : command_components)
{
if (skip)
{
skip = false;
continue;
}
auto name_components = split(name, '/', true);
if (name_components.empty() || name_components.back().empty())
{
continue;
}
if (std::get<0>(mv_pair).empty())
{
std::get<0>(mv_pair) = name_components.back();
}
else
{
std::get<1>(mv_pair) = name_components.back();
break;
}
}
if (std::get<0>(mv_pair).empty() || std::get<1>(mv_pair).empty())
{
return false;
}
const auto extension_to_rename = std::find_if(data.begin(), data.end(),
[&mv_pair](const std::pair<std::string, std::string>& element)
{
return std::get<0>(mv_pair) == element_name(element);
});
if (extension_to_rename != data.cend())
{
const auto extension_with_exists_name = std::find_if(data.begin(), data.end(),
[&mv_pair](const std::pair<std::string, std::string>& element)
{
return std::get<1>(mv_pair) == element_name(element);
});
if (extension_with_exists_name != data.cend())
{
data.erase(extension_with_exists_name);
}
std::get<0>(*extension_to_rename) = std::get<1>(mv_pair);
return true;
}
return false;
}
bool rm(const std::string& command, IEnumerableData& data)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
//
const auto current_size = data.size();
std::set<std::string> targets;
auto value_pair = std::make_pair(command.cbegin(), command.cend());
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true);
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair) && '-' != *std::get<0>(value_pair))
{
const auto value_start = std::get<0>(value_pair);
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true);
targets.insert(std::string(value_start, std::get<0>(value_pair)));
}
}
for (const auto& target : targets)
{
auto name = get_file_name(target);
//TODO: in a future 'make interpreter' required full path.
if (1 < name.size() && '*' == name.front())
{
std::copy(
name.cbegin() + 1,
name.cend(),
name.begin());
name.resize(name.size() - 1);
//
data.remove_if([&name](const std::pair<std::string, std::string>& element)
{
return ends_with(element_name(element), name);
});
}
else
{
data.remove_if([&name](const std::pair<std::string, std::string>& element)
{
return name == element_name(element);
});
}
}
return current_size > data.size();
}
std::pair<std::string, std::string> get_pipeline_names(const IEnumerableData& data,
const std::string& exit_pipeline_command)
{
auto create_new_content = true;
auto name_size = get_name_of_output(exit_pipeline_command, create_new_content).size();
for (const auto& element : data)
{
name_size = std::max(name_size, element_name(element).size());
}
++name_size;
return std::make_pair(std::string(name_size, 'i'), std::string(name_size, 'o'));
}
bool pipeline(const std::string& command, IEnumerableData& data, std::ostream& log)
{
auto was_command_be_apply = false;
auto pipeline_commands = split(command, '|', true);
if (pipeline_commands.empty())
{
return was_command_be_apply;
}
const auto pipeline_names = get_pipeline_names(data, *pipeline_commands.crbegin());
data.push_back(std::make_pair(std::get<0>(pipeline_names), std::string()));
data.push_back(std::make_pair(std::get<1>(pipeline_names), std::string()));
std::list<std::string> commands;
for (auto i = pipeline_commands.begin(); i != pipeline_commands.end(); ++i)
{
if (i == pipeline_commands.cbegin())
{
if (!contains(*i, ">"))
{
(*i) += " > " + std::get<1>(pipeline_names);
}
}
else if (1 == static_cast<std::size_t>(std::distance(i, pipeline_commands.end())))
{
auto pos = find_phrase_start(*i, ">");
if (i->cend() != pos)
{
const auto off = static_cast<std::size_t>(std::distance(i->cbegin(), pos));
const auto data_size = i->size() - off;
const auto delta = std::get<0>(pipeline_names).size() + 2;
//
i->resize(i->size() + delta);
pos = i->cbegin();
std::advance(pos, off);
//
std::fill(i->begin() + off + data_size, i->end(), ' ');
//
std::copy(
pos,
i->cbegin() + (i->size() - delta),
i->begin() + (i->size() - data_size));
//
std::copy(
std::get<0>(pipeline_names).cbegin(),
std::get<0>(pipeline_names).cend(),
i->begin() + off);
}
}
else
{
(*i) += " " + std::get<0>(pipeline_names);
(*i) += " > " + std::get<1>(pipeline_names);
}
trim(*i);
commands.clear();
commands.push_back(*i);
//
was_command_be_apply = execute_bash_commands(commands, data, log);
const auto input = std::find_if(data.begin(), data.end(),
[&pipeline_names](const std::pair<std::string, std::string>& element)
{
return std::get<0>(pipeline_names) == element_name(element);
});
//
assert(data.end() != input);
if (data.end() == input)
{
was_command_be_apply = false;
break;
}
const auto output = std::find_if(data.begin(), data.end(),
[&pipeline_names](const std::pair<std::string, std::string>& element)
{
return std::get<1>(pipeline_names) == element_name(element);
});
//
assert(data.end() != output);
if (data.end() == output)
{
was_command_be_apply = false;
break;
}
std::get<1>(*input).clear();
std::copy(
std::get<1>(*output).cbegin(),
std::get<1>(*output).cend(),
std::back_inserter(std::get<1>(*input)));
std::get<1>(*output).clear();
}
auto current = &std::get<0>(pipeline_names);
for (auto i = 0; i < 2; ++i, current = &std::get<1>(pipeline_names))
{
const auto find_result = std::find_if(data.cbegin(), data.cend(),
[&current](const std::pair<std::string, std::string>& element)
{
return *current == element_name(element);
});
//
assert(data.cend() != find_result);
if (data.cend() != find_result)
{
data.erase(find_result);
}
else
{
log << "[Error]: Pipeline unable to remove itself buffer '";
log << (*current) << "' while execute command '";
log << command << "'." << std::endl;
was_command_be_apply = false;
}
}
return was_command_be_apply;
}
std::list<std::string> for_operator(const std::string& command, const IEnumerableData& data)
{
std::list<std::string> result;
const auto command_components = split(command, ';', true);
if (3 != command_components.size())
{
return result;
}
auto command_component = command_components.cbegin();
const auto variable_environment = split((*command_component), std::set<char>({ '\t', ' ' }), true);
if (4 != variable_environment.size())
{
return result;
}
auto v = variable_environment.cbegin();
std::advance(v, 1);
auto variable_name = (*v);
std::advance(v, 1);
if ("in" != (*v))
{
return result;
}
std::advance(v, 1);
auto name_mask = (*v);
auto nmc = split(name_mask, '/', true);
if (nmc.size() < 2)
{
return result;
}
name_mask = (*nmc.crbegin());
if (name_mask.empty() || '*' != name_mask.back())
{
return result;
}
name_mask.resize(name_mask.size() - 1);
variable_name = '$' + variable_name;
//
std::advance(command_component, 1);
static const auto key_do = std::string("do");
auto for_command_start = find_phrase_start((*command_component), key_do);
if (for_command_start == command_component->cend())
{
return result;
}
std::advance(for_command_start, key_do.size());
do
{
std::advance(for_command_start, 1);
}
while (((*for_command_start) == ' ' || (*for_command_start) == '\t') &&
for_command_start != command_component->cend());
if (for_command_start == command_component->cend())
{
return result;
}
const auto for_command = std::string(for_command_start, command_component->cend());
for (const auto& element : data)
{
if (!starts_with(element_name(element), name_mask))
{
continue;
}
auto current_command = for_command;
replace(current_command, variable_name, element_name(element));
result.push_back(current_command);
}
std::advance(command_component, 1);
auto done = (*command_component);
trim(done);
if ("done" != done)
{
result.clear();
}
return result;
}
bool execute_bash_commands(std::list<std::string>& bash_commands, IEnumerableData& data, std::ostream& log)
{
auto result = true;
for (auto command = bash_commands.cbegin(); command != bash_commands.cend(); ++command)
{
auto was_command_be_apply = false;
const auto str_command = *command;
if (contains(str_command, "|"))
{
was_command_be_apply = pipeline(str_command, data, log);
}
else if (starts_with(str_command, "egrep"))
{
was_command_be_apply = egrep(str_command, data);
}
else if (starts_with(str_command, "grep"))
{
was_command_be_apply = grep(str_command, data);
}
else if (starts_with(str_command, "head"))
{
was_command_be_apply = head(str_command, data);
}
else if (starts_with(str_command, "tail"))
{
was_command_be_apply = tail(str_command, data);
}
else if (starts_with(str_command, "perl"))
{
was_command_be_apply = perl(str_command, data);
}
else if (starts_with(str_command, "cat"))
{
was_command_be_apply = cat(str_command, data);
}
else if (starts_with(str_command, "for"))
{
auto commands = for_operator(str_command, data);
if (!commands.empty())
{
//TODO: add function append_commands.
const auto off = -1 * static_cast<long>(1 + commands.size());
bash_commands.splice(command, commands);
command = bash_commands.erase(command);
std::advance(command, off);
was_command_be_apply = true;
}
}
else if (starts_with(str_command, "set"))
{
continue;
}
else if (starts_with(str_command, "mv"))
{
was_command_be_apply = mv(str_command, data);
}
else if (starts_with(str_command, "rm"))
{
was_command_be_apply = rm(str_command, data);
}
#ifndef NDEBUG
else
{
log << "[Warning]: Command '" << str_command << "' is unknown." << std::endl;
}
#endif
if (!was_command_be_apply)
{
#ifndef NDEBUG
log << "[Warning]: Command '" << str_command << "' was not be applied." << std::endl;
#endif
result = was_command_be_apply;
}
}
return result;
}
bool execute_script(std::istream& script, IEnumerableData& data, std::ostream& log)
{
auto bash_commands = get_bash_commands_from_stream(script);
return execute_bash_commands(bash_commands, data, log);
}
std::list<std::string> get_bash_commands_from_stream(std::istream& content_stream)
{
static const auto key_EOT_start = std::string("<<EOT");
static const auto key_EOT_finish = std::string("EOT");
std::list<std::string> commands;
const std::set<char> command_should_not_start_from({ '\t', ' ', '\n', '#' });
for (std::string line; std::getline(content_stream, line);)
{
const auto command_begin = std::find_if(line.cbegin(), line.cend(),
[&command_should_not_start_from](const char& ch)
{
return 0 == command_should_not_start_from.count(ch);
});
if (line.cend() == command_begin)
{
continue;
}
const auto comment_symbol = std::find_if(line.cbegin(), command_begin,
[](const char& ch)
{
return '#' == ch;
});
if (command_begin != comment_symbol)
{
continue;
}
auto pos = find_phrase_start(std::make_pair(command_begin, line.cend()), key_EOT_start);
if (pos != line.cend())
{
std::advance(pos, key_EOT_start.size());
std::string command(5 * line.size(), '\0');
command.clear();
command += std::string(command_begin, line.cend());
command += '\n';
while (std::getline(content_stream, line))
{
pos = find_phrase_start(std::make_pair(line.cbegin(), line.cend()), key_EOT_finish);
if (line.cend() != pos)
{
std::advance(pos, key_EOT_finish.size());
command += std::string(line.cbegin(), pos);
commands.push_back(command);
break;
}
else
{
command += line + '\n';
}
}
continue;
}
else
{
const auto use_next_line_symbol = std::find_if(command_begin, line.cend(), [](const char& ch)
{
return '\\' == ch;
});
if (line.cend() != use_next_line_symbol)
{
const auto find_result = std::find_if(use_next_line_symbol, line.cend(), [](const char& ch)
{
return '\\' != ch && '\t' != ch && ' ' != ch;
});
if (find_result == line.cend())
{
std::string command(2 * line.size(), '\0');
command.clear();
command += std::string(command_begin, line.cend());
if (std::getline(content_stream, line))
{
command += '\n' + line;
commands.push_back(command);
continue;
}
}
}
}
commands.push_back(std::string(command_begin, line.cend()));
trim(commands.back());
}
return commands;
}
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_bash_commands(
const std::string& content)
{
static const auto key_EOT_start = std::string("<<EOT");
static const auto key_EOT_finish = std::string("EOT");
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> commands;
const std::set<char> command_should_not_start_from({ '\t', ' ', '\n', '#' });
for (auto i = content.cbegin(); i != content.cend(); ++i)
{
const auto command_begin = std::find_if(i, content.cend(), [&command_should_not_start_from](const char& ch)
{
return 0 == command_should_not_start_from.count(ch);
});
if (content.cend() == command_begin)
{
break;
}
auto line_begin = command_begin;
while ((*line_begin) != '\n' && line_begin != i)
{
line_begin--;
}
const auto comment_symbol = std::find_if(line_begin, command_begin, [](const char& ch)
{
return '#' == ch;
});
//
auto line_end = std::find_if(command_begin, content.cend(), [](const char& ch)
{
return '\n' == ch;
});
if (content.cend() == line_end)
{
break;
}
if (command_begin != comment_symbol)
{
i = line_end;
continue;
}
auto pos = find_phrase_start(std::make_pair(command_begin, line_end), key_EOT_start);
if (pos != line_end)
{
std::advance(pos, key_EOT_start.size());
pos = find_phrase_start(std::make_pair(pos, content.cend()), key_EOT_finish);
if (pos != content.cend())
{
std::advance(pos, key_EOT_finish.size());
line_end = pos;
}
}
else
{
const auto use_next_line_symbol = std::find_if(command_begin, line_end, [](const char& ch)
{
return '\\' == ch;
});
if (line_end != use_next_line_symbol)
{
const auto find_result = std::find_if(use_next_line_symbol, line_end, [](const char& ch)
{
return '\\' != ch && '\t' != ch && ' ' != ch;
});
if (line_end == find_result)
{
std::advance(line_end, 1);
line_end = std::find_if(line_end, content.cend(), [](const char& ch)
{
return '\n' == ch;
});
}
}
}
do
{
std::advance(line_end, -1);
}
while (((*line_end) == '\n' || (*line_end) == ' ' || (*line_end) == '\t') && line_end != command_begin);
std::advance(line_end, 1);
commands.push_back(std::make_pair(command_begin, line_end));
i = line_end;
}
return commands;
}
std::list<std::pair<std::string, std::string>> _get_map(
const std::string& content,
const std::string& start_phrase)
{
static const auto pattern = std::regex("\\w+"); //TODO: std::regex("[\\w+ \\t\\*]*");
std::list<std::pair<std::string, std::string>> map;
auto map_start = content.find(start_phrase);
if (std::string::npos != map_start)
{
map_start += start_phrase.size();
const auto map_end = content.find(");", map_start);
if (std::string::npos != map_end)
{
const auto raw_map = split(std::make_pair(content.cbegin() + map_start,
content.cbegin() + map_end), '\n', true);
for (const auto& value : raw_map)
{
if (contains(value, "#"))
{
continue;
}
std::sregex_iterator pos(value.cbegin(), value.cend(), pattern);
std::sregex_iterator end;
const auto distance = std::distance(pos, end);
if (distance != 2)
{
continue;
}
map.push_back(std::make_pair(std::string(), std::string()));
for (auto i = static_cast<char>(0); ; ++i, ++pos)
{
if (!i)
{
std::get<0>(map.back()) = pos->str();
}
else
{
std::get<1>(map.back()) = pos->str();
break;
}
}
}
}
}
return map;
}
void add_pair_to_map(const std::string::const_iterator& cbegin,
const std::string::const_iterator& cend,
std::list<std::pair<std::string, std::string>>& map)
{
static const auto pattern = std::regex("\\w+");
const auto comment = find_if(cbegin, cend, [](const char& ch)
{
return '#' == ch;
});
if (cend != comment)
{
auto find_result = find_if(cbegin, comment, [](const char& ch)
{
return ' ' != ch && '\t' != ch;
});
if (find_result == comment)
{
return;
}
}
std::sregex_iterator pos(cbegin, cend, pattern);
std::sregex_iterator end;
if (2 == std::distance(pos, end))
{
auto pair_to_add = std::make_pair(pos->str(), std::string());
std::advance(pos, 1);
std::get<1>(pair_to_add) = pos->str();
map.push_back(pair_to_add);
}
}
std::list<std::pair<std::string, std::string>> _get_map(std::istream& content_stream,
const std::string& start_phrase)
{
static const auto map_end_phrase = std::string(");");
std::list<std::pair<std::string, std::string>> map;
for (std::string line; std::getline(content_stream, line);)
{
auto map_start = line.cend();
if (line.cend() != (map_start = find_phrase_start(line, start_phrase)))
{
std::advance(map_start, start_phrase.size());
auto map_end = find_phrase_start(std::make_pair(map_start, line.cend()), map_end_phrase);
add_pair_to_map(map_start, map_end, map);
for (; std::getline(content_stream, line) &&
line.cend() == (map_end = find_phrase_start(line, map_end_phrase));)
{
add_pair_to_map(line.cbegin(), map_end, map);
}
if (map_end != line.cend())
{
std::advance(map_end, map_end_phrase.size());
}
add_pair_to_map(line.cbegin(), map_end, map);
break;
}
}
return map;
}
std::string get_variable(const std::string& content, const std::string& start_phrase)
{
std::string result;
const auto variable_start = content.find(start_phrase);
if (std::string::npos != variable_start)
{
const auto variable_end = content.find('\n', variable_start + start_phrase.length());
if (std::string::npos != variable_start)
{
result = content.substr(variable_start + start_phrase.size(),
variable_end - variable_start - start_phrase.size());
remove(result, std::set<char>({ ' ', '=', ';' }));
}
}
return result;
}
std::string get_variable(std::istream& content_stream, const std::string& start_phrase)
{
std::string result;
for (std::string line; std::getline(content_stream, line);)
{
auto variable_start = line.cend();
if (line.cend() != (variable_start = find_phrase_start(line, start_phrase)))
{
std::advance(variable_start, start_phrase.size());
result.reserve(std::distance(variable_start, line.cend()));
//
std::for_each(variable_start, line.cend(), [&result](const char& ch)
{
if (ch != ' ' && ch != '=' && ch != ';')
{
result += ch;
}
});
//
break;
}
}
return result;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _INTERPRETER_H_
#define _INTERPRETER_H_
#include <list>
#include <string>
#include <utility>
#include <istream>
#include <ostream>
using IEnumerableData = std::list<std::pair<std::string, std::string>>;
#define element_name(element) std::get<0>((element))
std::string get_name_of_output(const
std::pair<std::string::const_iterator, std::string::const_iterator>& command, bool& create_new_content);
bool echo(const std::string& text, std::ostream& output);
bool echo(const std::string& text, std::string& output);
bool grep(std::istream& input, const std::string& target, bool should_be_contains, std::ostream& output);
bool grep(const std::string& input, const std::string& target, bool should_be_contains, std::string& output);
bool grep(std::istream& source, std::istream& target, std::ostream& output);
bool grep(const std::string& source, const std::string& target, std::string& output);
bool egrep(std::istream& input, const std::string& pattern_target, std::ostream& output);
bool egrep(const std::string& input, const std::string& pattern_target, std::string& output);
bool cat(std::istream& input, const std::string& text, std::ostream& output);
bool cat(const std::string& input, std::string& output);
bool head(std::istream& input, const std::string& command, std::ostream& output);
bool head(const std::string& input, const std::string& command, std::string& output);
bool tail(std::istream& input, const std::string& command, std::ostream& output);
bool tail(const std::string& input, const std::string& command, std::string& output);
bool perl(std::istream& input, const std::string& command, std::ostream& output);
bool perl(const std::string& input, const std::string& parameter, std::string& output);
bool perl(std::string& content, const std::string& parameter);
bool grep(const std::string& command, IEnumerableData& data);
bool egrep(const std::string& command, IEnumerableData& data);
bool cat(const std::string& command, IEnumerableData& data);
bool head(const std::string& command, IEnumerableData& data);
bool tail(const std::string& command, IEnumerableData& data);
bool perl(const std::string& command, IEnumerableData& data);
bool mv(const std::string& command, IEnumerableData& data);
bool rm(const std::string& command, IEnumerableData& data);
bool pipeline(const std::string& command, IEnumerableData& data, std::ostream& log);
std::list<std::string> for_operator(const std::string& command, const IEnumerableData& data);
bool execute_bash_commands(std::list<std::string>& bash_commands, IEnumerableData& data, std::ostream& log);
bool execute_script(std::istream& script, IEnumerableData& data, std::ostream& log);
std::list<std::string> get_bash_commands_from_stream(std::istream& content_stream);
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_bash_commands(
const std::string& content);
std::list<std::pair<std::string, std::string>> _get_map(const std::string& content,
const std::string& start_phrase);
std::list<std::pair<std::string, std::string>> _get_map(std::istream& content_stream,
const std::string& start_phrase);
std::string get_variable(const std::string& content, const std::string& start_phrase);
std::string get_variable(std::istream& content_stream, const std::string& start_phrase);
#define get_typemap(A) _get_map((A), "my %typemap")
//#define get_void_typemap(A) _get_map((A), "my %void_typemap")
#define get_taboo_tokens(A) _get_map((A), "my %taboo_tokens")
#define get_fnc_ignore_list(A) _get_map((A), "my %fnc_ignore_list")
#define get_reg_http(A) get_variable((A), "my $reg_http")
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "input_output.h"
#include "path.h"
#include "common.h"
#include "version.h"
#include "generator.h"
#include "descriptor.h"
#include "descriptors.h"
#include <list>
#include <string>
#include <cassert>
#include <cstdlib>
#include <ostream>
#include <utility>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
#define log std::cout
#define err_log std::cerr
std::list<std::pair<std::string, std::string>> read_version(const std::string& glew_path)
{
std::list<std::pair<std::string, std::string>> result;
//
const auto version_file = combine(std::list<std::string>({ glew_path, "/config/version" }));
std::ifstream file_stream(version_file);
if (file_stream.is_open())
{
result = read_version(file_stream);
file_stream.close();
}
else
{
log << "[Warning]: Unable to open '" << version_file << "'." << std::endl;
}
return result;
}
int main(int argc, char** argv)
{
if (argc < 4 || 6 < argc)
{
std::cout << "Sample using: " << std::endl;
std::cout << argv[0];
std::cout << "\t<path to glew> <path to glfixes> <destination>";
std::cout << std::endl;
std::cout << argv[0];
std::cout <<
"\t<path to glew> <path to glfixes> <path to OpenGL-Registry> <path to EGL-Registry> <destination>";
std::cout << std::endl;
//
return EXIT_FAILURE;
}
std::string content(1024 * 1024, '\0');
const auto glew_path = combine(std::list<std::string>({ argv[1] }));
const auto glfixes_path = combine(std::list<std::string>({ argv[2] }));
//
std::list<std::list<extension>> extensions;
if (argc == 6)
{
const auto opengl_registry_path = combine(std::list<std::string>({ argv[3] }));
const auto egl_registry_path = combine(std::list<std::string>({ argv[4] }));
//
extensions = create_descriptors(glew_path,
glfixes_path,
opengl_registry_path,
egl_registry_path,
content,
log);
//
content.clear();
content += glew_path;
content.push_back('\n');
content += glfixes_path;
content.push_back('\n');
content += opengl_registry_path;
content.push_back('\n');
content += egl_registry_path;
}
else if (argc == 4)
{
extensions = create_descriptors(glew_path, glfixes_path, content, log);
//
content.clear();
content += glew_path;
content.push_back('\n');
content += glfixes_path;
}
assert(!extensions.empty());
if (extensions.empty())
{
err_log << "[Error]: there are no extensions. Check input paths." << std::endl;
err_log << content << std::endl;
err_log << " Unable to continue any work. Exiting.";
err_log << std::endl;
//
return EXIT_FAILURE;
}
const auto destination = combine(std::list<std::string>({ argv[argc - 1] }));
const auto src = combine(std::list<std::string>({ glew_path, "/auto/src/" }));
//
const auto gl_core_spec = get_gl_core_spec(extensions);
const auto gl_ext_spec = get_gl_ext_spec(extensions);
const auto egl_core_spec = get_egl_core_spec(extensions);
const auto egl_ext_spec = get_egl_ext_spec(extensions);
const auto wgl_ext_spec = get_wgl_ext_spec(extensions);
const auto glx_core_spec = get_glx_core_spec(extensions);
const auto glx_ext_spec = get_glx_ext_spec(extensions);
//
assert(!gl_core_spec.empty());
assert(!gl_ext_spec.empty());
assert(!wgl_ext_spec.empty());
assert(!glx_core_spec.empty());
assert(!glx_ext_spec.empty());
//
//auto count = gl_core_spec.size();
//count += gl_ext_spec.size();
//count += egl_core_spec.size();
//count += egl_ext_spec.size();
//count += wgl_ext_spec.size();
//count += glx_core_spec.size();
//count += glx_ext_spec.size();
//
//assert(extensions_count == count);
//
const auto version = read_version(glew_path);
//
const auto i_dest = combine(std::list<std::string>({ destination, "/include/GL" }));
const auto s_dest = combine(std::list<std::string>({ destination, "/src" }));
//const auto d_dest = combine(std::list<std::string>({ destination, "/doc" }));
const auto b_dest = combine(std::list<std::string>({ destination, "/build" }));
if (!create_a_directory(i_dest))
{
log << "[Warning]: Unable to create a directory '" << i_dest << "'." << std::endl;
}
if (!create_a_directory(s_dest))
{
log << "[Warning]: Unable to create a directory '" << s_dest << "'." << std::endl;
}
/*if (!create_a_directory(d_dest))
{
log << "[Warning]: Unable to create a directory '" << d_dest << "'." << std::endl;
}*/
if (!create_a_directory(b_dest))
{
log << "[Warning]: Unable to create a directory '" << b_dest << "'." << std::endl;
}
auto file_path = combine(std::list<std::string>({ i_dest, "glew.h" }));
content.clear();
glew_h(src, extensions, version, content, log);
if (!write_to_file(file_path, content))
{
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl;
}
file_path = combine(std::list<std::string>({ s_dest, "glew.c" }));
content.clear();
glew_c(src, extensions, version, content, log);
if (!write_to_file(file_path, content))
{
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl;
}
const auto ver = str_version_to_version(version);
if (!wgl_ext_spec.empty())
{
file_path = combine(std::list<std::string>({ i_dest, "wglew.h" }));
content.clear();
wglew_h(src, wgl_ext_spec, ver, content, log);
if (!write_to_file(file_path, content))
{
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl;
}
}
else
{
err_log << "[Error]: there is no 'WGL_EXT_SPEC' at extensions list. ";
err_log << "Generation of file '" << file_path << "' impossible." << std::endl;
}
if (!glx_core_spec.empty() && !glx_ext_spec.empty())
{
file_path = combine(std::list<std::string>({ i_dest, "glxew.h" }));
content.clear();
glxew_h(src, glx_core_spec, glx_ext_spec, ver, content, log);
if (!write_to_file(file_path, content))
{
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl;
}
}
else
{
err_log << "[Error]: there are no 'GLX_CORE_SPEC' or/and 'GLX_EXT_SPEC' at extensions list. ";
err_log << "Generation of file '" << file_path << "' impossible." << std::endl;
}
#ifndef NDEBUG
if (version_1_13_0 < ver)
{
assert(!egl_core_spec.empty());
assert(!egl_ext_spec.empty());
}
#endif
if (version_1_13_0 < ver && !egl_core_spec.empty() && !egl_ext_spec.empty())
{
file_path = combine(std::list<std::string>({ i_dest, "eglew.h" }));
content.clear();
eglew_h(src, egl_core_spec, egl_ext_spec, content, log);
if (!write_to_file(file_path, content))
{
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl;
}
}
else if (version_1_13_0 < ver)
{
err_log << "[Error]: there are no 'EGL_CORE_SPEC' or/and 'EGL_EXT_SPEC' at extensions list. ";
err_log << "Generation of file '" << file_path << "' impossible." << std::endl;
}
file_path = combine(std::list<std::string>({ s_dest, "glewinfo.c" }));
content.clear();
glewinfo_c(src, extensions, ver, content, log);
if (!write_to_file(file_path, content))
{
log << "[Warning]: Unable to write a file '" << file_path << "'." << std::endl;
}
content.clear();
rc(src, b_dest, version, content, log);
//
return EXIT_SUCCESS;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "parse_xml.h"
#include "common.h"
#include "input_output.h"
#include <regex>
#include <cassert>
#include <algorithm>
#ifndef PUGIXML
#include <set>
#include <iterator>
bool get_path_segment(
const std::pair<std::string::const_iterator, std::string::const_iterator>& path,
std::pair<std::string::const_iterator, std::string::const_iterator>& segment)
{
std::get<0>(segment) = std::find_if(std::get<0>(path), std::get<1>(path), [](const char& ch)
{
return '/' != ch;
});
//
std::get<1>(segment) = std::find_if(std::get<0>(segment), std::get<1>(path), [](const char& ch)
{
return '/' == ch;
});
//
return std::get<1>(segment) != std::get<0>(segment);
}
bool go_to_comment_end_if_it_exists(std::string::const_iterator& current_position,
const std::string::const_iterator& end_position)
{
static const std::string comment_start("<!--");
static const std::string comment_end("-->");
if (comment_start.size() < static_cast<std::size_t>(std::distance(current_position, end_position)))
{
if (0 == std::memcmp(&(*current_position), comment_start.c_str(), comment_start.size()))
{
std::advance(current_position, comment_start.size());
current_position = find_phrase_start(std::make_pair(current_position, end_position), comment_end);
if (end_position != current_position)
{
std::advance(current_position, comment_end.size());
}
current_position = std::find_if(current_position, end_position, [](const char& ch)
{
return '<' == ch;
});
//
return go_to_comment_end_if_it_exists(current_position, end_position);
}
}
return end_position != current_position;
}
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_sub_nodes_elements(
const std::pair<std::string::const_iterator, std::string::const_iterator>& node)
{
static const char declaration_start('?');
static const char tag_close('/');
//
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result;
std::size_t depth(0);
auto pos = std::get<0>(node);
while (std::get<1>(node) != (pos = std::find_if(pos, std::get<1>(node), [](const char& ch)
{
return '<' == ch;
})))
{
if (!go_to_comment_end_if_it_exists(pos, std::get<1>(node)))
{
return result;
}
else
{
std::advance(pos, 1);
}
const auto tag_finish_pos = std::find_if(pos, std::get<1>(node), [](const char& ch)
{
return '>' == ch;
});
if (declaration_start == (*pos))
{
pos = tag_finish_pos;
continue;
}
if (tag_close == (*pos))
{
if (0 == depth)
{
break;
}
--depth;
}
else
{
if (0 == depth)
{
result.push_back(std::make_pair(pos, tag_finish_pos));
}
auto tag_finish_prev_pos = tag_finish_pos;
std::advance(tag_finish_prev_pos, -1);
if (tag_close != (*tag_finish_prev_pos))
{
++depth;
}
}
if (0 == depth)
{
std::get<1>(*result.rbegin()) = tag_finish_pos;
}
pos = tag_finish_pos;
}
//
return result;
}
std::pair<std::string::const_iterator, std::string::const_iterator> tag_name(
const std::pair<std::string::const_iterator, std::string::const_iterator>& tag)
{
static const auto tab_space_close_tag = std::set<char>({ '\t', ' ', '/', '>' });
return std::make_pair(
std::get<0>(tag), find_any_symbol_like_or_not_like_that(tag, tab_space_close_tag, true));
}
bool is_string_equal(const std::pair<std::string::const_iterator, std::string::const_iterator>& a,
const std::pair<std::string::const_iterator, std::string::const_iterator>& b)
{
const auto length = std::distance(std::get<0>(a), std::get<1>(a));
return ((0 < length) &&
(length == std::distance(std::get<0>(b), std::get<1>(b))) &&
(0 == std::memcmp(&(*std::get<0>(b)), &(*std::get<0>(a)), length)));
}
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> find_children(
const std::pair<std::string::const_iterator, std::string::const_iterator>& node,
const std::pair<std::string::const_iterator, std::string::const_iterator>& path,
std::size_t count)
{
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result;
std::pair<std::string::const_iterator, std::string::const_iterator> segment;
if ((0 == count) || !get_path_segment(path, segment))
{
return result;
}
const auto sub_path = std::make_pair(std::get<1>(segment), std::get<1>(path));
if (std::get<1>(sub_path) == std::get<0>(sub_path))
{
for (const auto& element : get_sub_nodes_elements(node))
{
if (count == result.size())
{
return result;
}
if (is_string_equal(tag_name(element), segment))
{
result.push_back(element);
}
}
}
else
{
for (const auto& element : get_sub_nodes_elements(node))
{
if (count == result.size())
{
return result;
}
if (is_string_equal(tag_name(element), segment))
{
result.splice(result.cend(), find_children(element, sub_path, count));
}
}
}
return result;
}
std::pair<std::string::const_iterator, std::string::const_iterator> get_child_value(
const std::pair<std::string::const_iterator, std::string::const_iterator>& i)
{
std::pair<std::string::const_iterator, std::string::const_iterator> value;
//
std::get<0>(value) = std::find_if(std::get<0>(i), std::get<1>(i), [](const char& ch)
{
return '>' == ch;
});
//
std::get<1>(value) = std::get<1>(i);
if (std::get<1>(i) == std::get<0>(value))
{
return value;
}
std::advance(std::get<0>(value), 1);
while (std::get<1>(value) != std::get<0>(value))
{
if ('<' == *std::get<1>(value))
{
break;
}
std::advance(std::get<1>(value), -1);
}
return value;
}
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> find_data(
const std::pair<std::string::const_iterator, std::string::const_iterator>& node,
const std::pair<std::string::const_iterator, std::string::const_iterator>& path,
std::size_t count)
{
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result;
for (const auto& i : find_children(node, path, count))
{
result.push_back(get_child_value(i));
}
return result;
}
std::pair<std::string, std::string> find_params(
const std::pair<std::string::const_iterator, std::string::const_iterator>& node)
{
static const std::regex pointer_pattern("(.*)([ ]+)([*]+)");
static const std::string name("name");
static const std::string ptype("ptype");
static const std::set<char> tag_chars({ '>', '<' });
//
const auto n = find_data(node, std::make_pair(name.cbegin(), name.cend()), 1);
std::string t(std::distance(std::get<0>(node), std::get<1>(node)), '\0');
t.clear();
//
auto pos = std::find_if(std::get<0>(node), std::get<1>(node), [](const char& ch)
{
return '>' == ch;
});
//
pos = find_any_symbol_like_or_not_like_that(std::make_pair(pos, std::get<1>(node)), tag_chars, false);
for (const auto& element : get_sub_nodes_elements(node))
{
auto tag_position = std::get<0>(element);
std::advance(tag_position, -1);
if (0 < std::distance(pos, tag_position))
{
std::copy(pos, tag_position, std::back_inserter(t));
}
if (is_string_equal(tag_name(element), std::make_pair(ptype.cbegin(), ptype.cend())))
{
const auto child_value = get_child_value(element);
std::copy(std::get<0>(child_value), std::get<1>(child_value), std::back_inserter(t));;
}
pos = find_any_symbol_like_or_not_like_that(std::make_pair(std::get<1>(element), std::get<1>(node)),
tag_chars, false);
}
if (t.empty())
{
auto child_value = get_child_value(node);
std::copy(pos, std::get<1>(child_value), std::back_inserter(t));
}
trim(t);
std::smatch m;
if (std::regex_match(t, m, pointer_pattern) && 3 < m.size())
{
auto t_ = std::string(std::get<0>(m[1]), std::get<1>(m[1]));
t_ += std::string(std::get<0>(m[3]), std::get<1>(m[3]));
trim(t_);
t.clear();
std::copy(t_.cbegin(), t_.cend(), std::back_inserter(t));
}
return std::make_pair(t, (n.empty() ? "" : std::string(std::get<0>(n.front()), std::get<1>(n.front()))));
}
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> get_attributes(
const std::pair<std::string::const_iterator, std::string::const_iterator>& input)
{
static const auto quote = std::set<char>({ '"' });
//
std::list<std::pair<std::string::const_iterator, std::string::const_iterator>> result;
auto value_pair = input;
std::get<1>(value_pair) = std::find_if(std::get<0>(input), std::get<1>(input),
[](const char& ch)
{
return '>' == ch;
});
static const auto tab_space = std::set<char>({ '\t', ' ' });
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
std::advance(std::get<0>(value_pair), 1);
}
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true);
while (std::get<1>(value_pair) != std::get<0>(value_pair))
{
std::advance(std::get<0>(value_pair), 1);
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, false);
if (std::get<1>(value_pair) == std::get<0>(value_pair))
{
break;
}
const auto value_start = std::get<0>(value_pair);
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, quote, true);
if (std::get<1>(value_pair) != std::get<0>(value_pair))
{
std::advance(std::get<0>(value_pair), 1);
}
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, quote, true);
//
result.push_back(std::make_pair(value_start, std::get<0>(value_pair)));
//
std::get<0>(value_pair) = find_any_symbol_like_or_not_like_that(value_pair, tab_space, true);
}
return result;
}
std::pair<std::string::const_iterator, std::string::const_iterator> get_attribute_value(
const std::list<std::pair<std::string::const_iterator, std::string::const_iterator>>& input,
const std::string& name)
{
static const auto quote = std::set<char>({ '"' });
static const auto tab_space_equal = std::set<char>({ '\t', ' ', '=' });
//
std::pair<std::string::const_iterator, std::string::const_iterator> value;
for (const auto& i : input)
{
if (!starts_with(i, name))
{
continue;
}
const auto size = static_cast<std::size_t>(std::distance(std::get<0>(i), std::get<1>(i)));
if (size < name.size() + 1)
{
continue;
}
std::get<0>(value) = std::get<0>(i);
std::advance(std::get<0>(value), name.size());
if (0 == tab_space_equal.count(*std::get<0>(value)))
{
continue;
}
std::get<0>(value) = find_any_symbol_like_or_not_like_that(std::make_pair(std::get<0>(value), std::get<1>(i)),
quote, true);
if (std::get<1>(i) != std::get<0>(value))
{
std::advance(std::get<0>(value), 1);
}
std::get<1>(value) = std::get<1>(i);
break;
}
return value;
}
std::list<enum_> find_enums(const std::pair<std::string::const_iterator, std::string::const_iterator>& node)
{
static const std::string path("registry/enums/enum");
static const std::string name("name");
static const std::string value("value");
//
std::list<enum_> result;
for (const auto& i : find_children(node, std::make_pair(path.cbegin(), path.cend()), std::string::npos))
{
const auto attributes = get_attributes(i);
const auto n = get_attribute_value(attributes, name);
const auto v = get_attribute_value(attributes, value);
result.push_back(std::make_pair(n, v));
}
return result;
}
std::list<command> find_commands(const std::pair<std::string::const_iterator, std::string::const_iterator>&
node)
{
static const std::string path("registry/commands/command");
static const std::string proto("proto");
static const std::string param("param");
//
std::list<command> result;
const auto proto_ = std::make_pair(proto.cbegin(), proto.cend());
const auto param_ = std::make_pair(param.cbegin(), param.cend());
for (const auto& i : find_children(node, std::make_pair(path.cbegin(), path.cend()), std::string::npos))
{
const auto proto_node = find_children(i, proto_, 1);
if (proto_node.empty())
{
continue;
}
const auto r_n = find_params(proto_node.front());
std::list<params> p;
for (const auto& j : find_children(i, param_, std::string::npos))
{
p.push_back(find_params(j));
}
const auto c = std::make_pair(std::get<0>(r_n), p);
result.push_back(std::make_pair(std::get<1>(r_n), c));
}
return result;
}
std::list<std::pair<range_, feature_extension>> find_features_extensions(
const range_& node, const range_& path)
{
static const std::string enum_("require/enum");
static const std::string command("require/command");
static const std::string name("name");
//
std::list<std::pair<range_, feature_extension>> result;
const auto enum__ = std::make_pair(enum_.cbegin(), enum_.cend());
const auto command_ = std::make_pair(command.cbegin(), command.cend());
for (const auto& i : find_children(node, path, std::string::npos))
{
const auto n = get_attribute_value(get_attributes(i), name);
std::list<range_> e;
std::list<range_> c;
for (const auto& j : find_children(i, enum__, std::string::npos))
{
e.push_back(get_attribute_value(get_attributes(j), name));
}
for (const auto& j : find_children(i, command_, std::string::npos))
{
c.push_back(get_attribute_value(get_attributes(j), name));
}
const auto f_e = std::make_pair(e, c);
result.push_back(std::make_pair(n, f_e));
}
return result;
}
api find_api(const range_& node)
{
static const std::string features_str("registry/feature");
static const std::string extensions_str("registry/extensions/extension");
//
const auto enums = find_enums(node);
const auto commands = find_commands(node);
const auto features = find_features_extensions(node, std::make_pair(features_str.cbegin(),
features_str.cend()));
const auto extensions = find_features_extensions(node, std::make_pair(extensions_str.cbegin(),
extensions_str.cend()));
//
return{ enums, commands, features, extensions };
}
bool is_string_equal_slow_version(const std::pair<std::string::const_iterator, std::string::const_iterator>&
a,
const std::pair<std::string::const_iterator, std::string::const_iterator>& b)
{
//TODO:
const auto length = std::distance(std::get<0>(a), std::get<1>(a));
if ((0 < length) && (length == std::distance(std::get<0>(b), std::get<1>(b))))
{
return std::string(std::get<0>(a), std::get<1>(a)) == std::string(std::get<0>(b), std::get<1>(b));
}
return false;
}
bool is_string_equal_slow_version(const std::pair<std::string::const_iterator, std::string::const_iterator>&
a, const std::string& b)
{
//TODO:
const auto length = std::distance(std::get<0>(a), std::get<1>(a));
if ((0 < length) && (static_cast<std::size_t>(length) == b.size()))
{
return std::string(std::get<0>(a), std::get<1>(a)) == b;
}
return false;
}
void write_extension(const range_& name,
const feature_extension& extension,
const std::list<enum_>& enums,
const std::list<command>& commands,
std::string& output)
{
static const std::regex WGL_pattern("WGL_([A-Z0-9]+)_.*");
//
output.clear();
const std::string name_(std::get<0>(name), std::get<1>(name));
output += name_;
output.push_back('\n');
auto url = std::string("https://www.khronos.org/registry/egl/specs/eglspec.1.5.pdf");
std::smatch m;
if (std::regex_match(name_, m, WGL_pattern) && 1 < m.size())
{
url.clear();
url += "https://www.khronos.org/registry/OpenGL/extensions/";
url += m[1];
url.push_back('/');
url += name_;
url + ".txt";
}
output += url;
output.push_back('\n');
if (!contains(name_, "_VERSION_"))
{
output += name_;
output.push_back('\n');
}
else
{
output.push_back('\n');
}
output.push_back('\n');
std::list<enum_> enum_lines;
for (const auto& j : std::get<0>(extension))
{
const auto find_result = std::find_if(enums.cbegin(), enums.cend(),
[&j](const enum_ & e)
{
//TODO: is_string_equal() is failed at operator* on const_iterator of string.
return is_string_equal_slow_version(j, std::get<0>(e));
});
if (enums.cend() == find_result)
{
continue;
}
enum_lines.push_back(*find_result);
}
if (!enum_lines.empty())
{
enum_lines.sort([](const enum_ & a, const enum_ & b)
{
//return std::get<1>(a) < std::get<1>(b); //TODO: direct comparing may failed for const_iterator. For more see TODO below.
return std::string(std::get<0>(std::get<1>(a)), std::get<1>(std::get<1>(a))) <
std::string(std::get<0>(std::get<1>(b)), std::get<1>(std::get<1>(b)));
});
for (const auto& line : enum_lines)
{
output.push_back('\t');
std::copy(std::get<0>(std::get<0>(line)), std::get<1>(std::get<0>(line)), std::back_inserter(output));
output.push_back(' ');
std::copy(std::get<0>(std::get<1>(line)), std::get<1>(std::get<1>(line)), std::back_inserter(output));
output.push_back('\n');
}
enum_lines.clear();
}
std::list<command> commands_lines;
for (const auto& j : std::get<1>(extension))
{
const auto find_result = std::find_if(commands.cbegin(), commands.cend(),
[&j](const command & c)
{
return is_string_equal_slow_version(j, std::get<0>(c));
});
if (commands.cend() == find_result)
{
continue;
}
commands_lines.push_back(*find_result);
}
if (!commands_lines.empty())
{
commands_lines.sort([](const command & a, const command & b)
{
return std::get<0>(a) < std::get<0>(b);
});
for (const auto& line : commands_lines)
{
std::list<std::string> params;
for (const auto& p : std::get<1>(std::get<1>(line)))
{
params.push_back(std::get<0>(p) + ' ' + std::get<1>(p));
}
output.push_back('\t');
output += std::get<0>(std::get<1>(line));
output.push_back(' ');
//
output += std::get<0>(line);
output.push_back(' ');
output.push_back('(');
//
output += (params.empty() ? "void" : join(", ", params));
output.push_back(')');
output.push_back('\n');
}
commands_lines.clear();
}
}
std::list<std::pair<std::string, std::string>> parse_xml(
const std::string& file_path,
parse_xml_option option,
std::string& tmp_output,
std::ostream& log)
{
std::list<std::pair<std::string, std::string>> result;
tmp_output.clear();
if (!read_from_file(file_path, tmp_output))
{
log << "[Warning]: Unable to read from file '";
log << file_path;
log << "'." << std::endl;
return result;
}
const auto api_ = find_api(std::make_pair(tmp_output.cbegin(), tmp_output.cend()));
if (api_.features.empty() && api_.extensions.empty())
{
log << "[Warning]: File '";
log << file_path;
log << "' do not have information for parse_xml. Exiting." << std::endl;
return result;
}
log << "[Information]: Found ";
log << api_.enums.size() << " enums, ";
log << api_.commands.size() << " commands, ";
log << api_.features.size() << " features and ";
log << api_.extensions.size() << " extensions." << std::endl;
if (parse_xml_option::core == option || parse_xml_option::all == option)
{
for (const auto& feature : api_.features)
{
tmp_output.clear();
write_extension(std::get<0>(feature), std::get<1>(feature), api_.enums, api_.commands, tmp_output);
result.push_back(
std::make_pair(
std::string(std::get<0>(std::get<0>(feature)), std::get<1>(std::get<0>(feature))), tmp_output));
}
}
if (parse_xml_option::extensions == option || parse_xml_option::all == option)
{
for (const auto& ext : api_.extensions)
{
tmp_output.clear();
write_extension(std::get<0>(ext), std::get<1>(ext), api_.enums, api_.commands, tmp_output);
result.push_back(
std::make_pair(
std::string(std::get<0>(std::get<0>(ext)), std::get<1>(std::get<0>(ext))), tmp_output));
}
}
return result;
}
#else
std::list<pugi::xml_node> find_children(
const pugi::xml_node& node, const std::string& path, std::size_t count)
{
std::list<pugi::xml_node> result;
if (0 == count)
{
return result;
}
const auto path_size = path.find('/');
for (const auto& i : node)
{
if (pugi::xml_node_type::node_element != i.type())
{
continue;
}
const auto name_size = std::strlen(i.name());
if (std::string::npos != path_size
&& (path_size == name_size)
&& (0 == std::memcmp(i.name(), path.c_str(), path_size)))
{
result.splice(result.cend(), find_children(i, path.substr(path_size + 1), count));
}
else if ((path.size() == name_size)
&& (0 == std::memcmp(i.name(), path.c_str(), path.size())))
{
result.push_back(i);
}
if (count == result.size())
{
break;
}
}
return result;
}
std::list<std::string> find_data(const pugi::xml_node& node, const std::string& path, std::size_t count)
{
std::list<std::string> result;
if (0 == count)
{
return result;
}
const auto nodes = find_children(node, path, count);
for (const auto& i : nodes)
{
result.push_back(std::string(i.first_child().value()));
if (count == result.size())
{
break;
}
}
return result;
}
std::pair<std::string, std::string> find_params(const pugi::xml_node& node)
{
static const std::regex pointer_pattern("(.*)([ ]+)([*]+)");
static const std::string ptype("ptype");
//
const auto n = find_data(node, "name");
std::string t;
for (const auto& i : node)
{
if (pugi::xml_node_type::node_pcdata == i.type())
{
t += i.value();
}
else if (pugi::xml_node_type::node_element == i.type()
&& ptype.size() == std::strlen(i.name())
&& 0 == std::memcmp(i.name(), ptype.c_str(), ptype.size()))
{
t += i.first_child().value();
}
}
trim(t);
std::smatch m;
if (std::regex_match(t, m, pointer_pattern) && 3 < m.size())
{
auto t_ = std::string(std::get<0>(m[1]), std::get<1>(m[1]));
t_ += std::string(std::get<0>(m[3]), std::get<1>(m[3]));
trim(t_);
t.clear();
std::copy(t_.cbegin(), t_.cend(), std::back_inserter(t));
}
return std::make_pair(t, (n.empty() ? "" : n.front()));
}
std::list<enum_> find_enums(const pugi::xml_node& node)
{
static const std::string path("registry/enums/enum");
//
std::list<std::pair<std::string, std::string>> result;
for (const auto& i : find_children(node, path, std::string::npos))
{
const auto n = std::string(i.attribute("name").value());
const auto v = std::string(i.attribute("value").value());
result.push_back(std::make_pair(n, v));
}
return result;
}
std::list<command> find_commands(const pugi::xml_node& node)
{
static const std::string path("registry/commands/command");
static const std::string proto("proto");
static const std::string param("param");
//
std::list<command> result;
for (const auto& i : find_children(node, path, std::string::npos))
{
const auto proto_node = find_children(i, proto, 1);
if (proto_node.empty())
{
continue;
}
const auto r_n = find_params(proto_node.front());
std::list<std::pair<std::string, std::string>> p;
for (const auto& j : find_children(i, param, std::string::npos))
{
p.push_back(find_params(j));
}
const auto c = std::make_pair(std::get<0>(r_n), p);
result.push_back(std::make_pair(std::get<1>(r_n), c));
}
return result;
}
std::list<std::pair<std::string, feature_extension>> find_features_extensions(
const pugi::xml_node& node, const std::string& path)
{
static const std::string _enum("require/enum");
static const std::string _command("require/command");
//
std::list<std::pair<std::string, feature_extension>> result;
for (const auto& i : find_children(node, path, std::string::npos))
{
const auto n = std::string(i.attribute("name").value());
std::list<std::string> e;
std::list<std::string> c;
for (const auto& j : find_children(i, _enum, std::string::npos))
{
e.push_back(std::string(j.attribute("name").value()));
}
for (const auto& j : find_children(i, _command, std::string::npos))
{
c.push_back(std::string(j.attribute("name").value()));
}
const auto f_e = std::make_pair(e, c);
result.push_back(std::make_pair(n, f_e));
}
return result;
}
api find_api(const pugi::xml_node& node)
{
const auto enums = find_enums(node);
const auto commands = find_commands(node);
const auto features = find_features(node);
const auto extensions = find_extensions(node);
//
return{ enums, commands, features, extensions };
}
void write_extension(const std::string& name,
const feature_extension& extension,
const std::list<enum_>& enums,
const std::list<command>& commands,
std::ostream& output)
{
output << name << std::endl;
output << "https://www.khronos.org/registry/egl/specs/eglspec.1.5.pdf" << std::endl;
if (!contains(name, "_VERSION_"))
{
output << name << std::endl;
}
else
{
output << std::endl;
}
output << std::endl;
std::list<enum_> enum_lines;
for (const auto& j : std::get<0>(extension))
{
const auto find_result = std::find_if(enums.cbegin(), enums.cend(),
[&j](const enum_ & e)
{
return j == std::get<0>(e);
});
if (enums.cend() == find_result)
{
continue;
}
enum_lines.push_back(*find_result);
}
if (!enum_lines.empty())
{
enum_lines.sort([](const enum_ & a, const enum_ & b)
{
return std::get<1>(a) < std::get<1>(b);
});
for (const auto& line : enum_lines)
{
output << '\t' << std::get<0>(line) << ' ' << std::get<1>(line) << std::endl;
}
enum_lines.clear();
}
std::list<command> commands_lines;
for (const auto& j : std::get<1>(extension))
{
const auto find_result = std::find_if(commands.cbegin(), commands.cend(),
[&j](const command & c)
{
return j == std::get<0>(c);
});
if (commands.cend() == find_result)
{
continue;
}
commands_lines.push_back(*find_result);
}
if (!commands_lines.empty())
{
commands_lines.sort([](const command & a, const command & b)
{
return std::get<0>(a) < std::get<0>(b);
});
for (const auto& line : commands_lines)
{
std::list<std::string> params;
for (const auto& p : std::get<1>(std::get<1>(line)))
{
params.push_back(std::get<0>(p) + ' ' + std::get<1>(p));
}
output << '\t' << std::get<0>(std::get<1>(line));
output << ' ' << std::get<0>(line) << ' ';
output << '(' << (params.empty() ? "void" : join(", ", params)) << ')' << std::endl;
}
commands_lines.clear();
}
}
void write_extension(const std::string& name,
const feature_extension& extension,
const std::list<enum_>& enums,
const std::list<command>& commands,
std::string& output)
{
output += name;
output.push_back('\n');
output += "https://www.khronos.org/registry/egl/specs/eglspec.1.5.pdf";
output.push_back('\n');
if (!contains(name, "_VERSION_"))
{
output += name;
output.push_back('\n');
}
else
{
output.push_back('\n');
}
output.push_back('\n');
std::list<enum_> enum_lines;
for (const auto& j : std::get<0>(extension))
{
const auto find_result = std::find_if(enums.cbegin(), enums.cend(),
[&j](const enum_ & e)
{
return j == std::get<0>(e);
});
if (enums.cend() == find_result)
{
continue;
}
enum_lines.push_back(*find_result);
}
if (!enum_lines.empty())
{
enum_lines.sort([](const enum_ & a, const enum_ & b)
{
return std::get<1>(a) < std::get<1>(b);
});
for (const auto& line : enum_lines)
{
output.push_back('\t');
output += std::get<0>(line);
output.push_back(' ');
output += std::get<1>(line);
output.push_back('\n');
}
enum_lines.clear();
}
std::list<command> commands_lines;
for (const auto& j : std::get<1>(extension))
{
const auto find_result = std::find_if(commands.cbegin(), commands.cend(),
[&j](const command & c)
{
return j == std::get<0>(c);
});
if (commands.cend() == find_result)
{
continue;
}
commands_lines.push_back(*find_result);
}
if (!commands_lines.empty())
{
commands_lines.sort([](const command & a, const command & b)
{
return std::get<0>(a) < std::get<0>(b);
});
for (const auto& line : commands_lines)
{
std::list<std::string> params;
for (const auto& p : std::get<1>(std::get<1>(line)))
{
params.push_back(std::get<0>(p) + ' ' + std::get<1>(p));
}
output.push_back('\t');
output += std::get<0>(std::get<1>(line));
output.push_back(' ');
//
output += std::get<0>(line);
output.push_back(' ');
output.push_back('(');
//
output += (params.empty() ? "void" : join(", ", params));
output.push_back(')');
output.push_back('\n');
}
commands_lines.clear();
}
}
std::list<std::pair<std::string, std::string>> parse_xml(
const std::string& file_path,
parse_xml_option option,
std::string& tmp_output,
std::ostream& log)
{
std::list<std::pair<std::string, std::string>> result;
pugi::xml_document doc;
const auto load_result = doc.load_file(
file_path.c_str(), pugi::parse_default | pugi::parse_ws_pcdata);
assert(pugi::xml_parse_status::status_ok == load_result.status);
if (pugi::status_ok != load_result.status)
{
log << "[Warning]: Unable to read file '";
log << file_path;
log << "' as xml." << std::endl;
return result;
}
const auto api_ = find_api(doc);
if (api_.features.empty() && api_.extensions.empty())
{
log << "[Warning]: File '";
log << file_path;
log << "' do not have information for parse_xml. Exiting." << std::endl;
return result;
}
log << "[Information]: Found ";
log << api_.enums.size() << " enums, ";
log << api_.commands.size() << " commands, ";
log << api_.features.size() << " features and ";
log << api_.extensions.size() << " extensions." << std::endl;
if (parse_xml_option::core == option || parse_xml_option::all == option)
{
for (const auto& feature : api_.features)
{
tmp_output.clear();
write_extension(std::get<0>(feature), std::get<1>(feature), api_.enums, api_.commands, tmp_output);
result.push_back(std::make_pair(std::get<0>(feature), tmp_output));
}
}
if (parse_xml_option::extensions == option || parse_xml_option::all == option)
{
for (const auto& ext : api_.extensions)
{
tmp_output.clear();
write_extension(std::get<0>(ext), std::get<1>(ext), api_.enums, api_.commands, tmp_output);
result.push_back(std::make_pair(std::get<0>(ext), tmp_output));
}
}
return result;
}
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _PARSE_XML_H_
#define _PARSE_XML_H_
#ifdef PUGIXML
#include <pugixml.hpp>
#endif
#include <list>
#include <string>
#include <cstring>
#include <utility>
#include <ostream>
enum class parse_xml_option : char
{
core = 1,
extensions,
all
};
using params = std::pair<std::string, std::string>;
using command = std::pair<std::string, std::pair<std::string, std::list<params>>>;
#ifndef PUGIXML
using range_ = std::pair<std::string::const_iterator, std::string::const_iterator>;
using enum_ = std::pair<range_, range_>;
using feature_extension = std::pair<std::list<range_>, std::list<range_>>;
struct api
{
const std::list<enum_> enums;
const std::list<command> commands;
const std::list<std::pair<range_, feature_extension>> features;
const std::list<std::pair<range_, feature_extension>> extensions;
};
std::list<range_> find_children(
const range_& node,
const range_& path,
std::size_t count = std::string::npos);
std::list<range_> find_data(
const range_& node,
const range_& path,
std::size_t count = 1);
params find_params(const range_& node);
std::list<enum_> find_enums(const range_& node);
std::list<command> find_commands(const range_& node);
std::list<std::pair<range_, feature_extension>> find_features_extensions(
const range_& node, const range_& path);
api find_api(const range_& node);
void write_extension(const range_& name,
const feature_extension& extension,
const std::list<enum_>& enums,
const std::list<command>& commands,
std::string& output);
#else
using enum_ = params;
using feature_extension = std::pair<std::list<std::string>, std::list<std::string>>;
struct api
{
const std::list<enum_> enums;
const std::list<command> commands;
const std::list<std::pair<std::string, feature_extension>> features;
const std::list<std::pair<std::string, feature_extension>> extensions;
};
std::list<pugi::xml_node> find_children(
const pugi::xml_node& node, const std::string& path, std::size_t count = std::string::npos);
std::list<std::string> find_data(const pugi::xml_node& node, const std::string& path, std::size_t count = 1);
params find_params(const pugi::xml_node& node);
std::list<enum_> find_enums(const pugi::xml_node& node);
std::list<command> find_commands(const pugi::xml_node& node);
std::list<std::pair<std::string, feature_extension>> find_features_extensions(
const pugi::xml_node& node, const std::string& path);
#define find_features(A) find_features_extensions((A), "registry/feature")
#define find_extensions(A) find_features_extensions((A), "registry/extensions/extension")
api find_api(const pugi::xml_node& node);
void write_extension(const std::string& name,
const feature_extension& extension,
const std::list<enum_>& enums,
const std::list<command>& commands,
std::ostream& output);
void write_extension(const std::string& name,
const feature_extension& extension,
const std::list<enum_>& enums,
const std::list<command>& commands,
std::string& output);
#endif
std::list<std::pair<std::string, std::string>> parse_xml(
const std::string& file_path,
parse_xml_option option,
std::string& tmp_output,
std::ostream& log);
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "path.h"
#include "common.h"
#include <sstream>
#include <utility>
#include <iterator>
#include <algorithm>
#ifdef _WIN32
#include <windows.h>
#else
#include <ftw.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif
std::string combine(const std::list<std::string>& paths)
{
auto path = join("/", paths);
#ifdef _WIN32
replace(path, '\\', '/');
#endif
replace_double_char_by_single(path, '/');
#ifdef _WIN32
if (!path.empty() && '/' == path.front())
{
if (path.size() == 1)
{
path.clear();
}
else
{
auto pos = path.cbegin();
std::advance(pos, 1);
std::copy(
pos,
path.cend(),
path.begin());
path.resize(path.size() - 1);
}
}
#endif
return path;
}
std::string get_directory_name(const std::string& path)
{
const auto pos = path.rfind('/');
if (std::string::npos != pos)
{
return path.substr(0, pos);
}
return path;
}
std::string get_file_name(const std::string& path)
{
const auto pos = path.rfind('/');
if (std::string::npos != pos)
{
return path.substr(1 + pos);
}
return path;
}
std::string get_relative_path(const std::string& path, std::size_t count_of_components)
{
const auto elements_from_paths = split(path, '/', true);
std::ostringstream relative_path;
if (0 != count_of_components && count_of_components < elements_from_paths.size())
{
auto component = elements_from_paths.crbegin();
std::advance(component, count_of_components - 1);
for (; component != elements_from_paths.crbegin(); --component)
{
relative_path << (*component) << '/';
}
relative_path << (*component);
}
else if (0 != count_of_components)
{
return path;
}
return relative_path.str();
}
#ifdef _WIN32
void get_files_by_pattern(
const std::string& file_pattern, std::list<std::string>& file_list)
{
WIN32_FIND_DATAA file_data;
std::memset(&file_data, 0, sizeof(file_data));
auto file_handle = FindFirstFileA(file_pattern.c_str(), &file_data);
if (INVALID_HANDLE_VALUE != file_handle)
{
std::string directory_name(MAX_PATH, '\0');
directory_name.clear();
const auto character_position = file_pattern.rfind('/');
if (std::string::npos != character_position)
{
directory_name += file_pattern.substr(0, 1 + character_position); //TODO: made copy instead substr
}
const auto current_size = directory_name.size();
do
{
if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
directory_name += file_data.cFileName;
file_list.push_back(directory_name);
}
else if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
std::memcmp(".", file_data.cFileName, 1) &&
std::memcmp("..", file_data.cFileName, 2))
{
directory_name += file_data.cFileName;
directory_name += '/';
if (std::string::npos != character_position)
{
directory_name += file_pattern.substr(1 + character_position); //TODO: made copy instead substr
}
get_files_by_pattern(directory_name, file_list);
}
directory_name.resize(current_size);
std::memset(&file_data, 0, sizeof(file_data));
}
while (FindNextFileA(file_handle, &file_data));
FindClose(file_handle);
file_handle = INVALID_HANDLE_VALUE;
}
}
bool is_path_a_directory(const std::string& path)
{
auto is_directory = false;
WIN32_FIND_DATAA file_data;
std::memset(&file_data, 0, sizeof(file_data));
auto file_handle = FindFirstFileA(path.c_str(), &file_data);
if (INVALID_HANDLE_VALUE != file_handle)
{
is_directory = (0 != (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
FindClose(file_handle);
std::memset(&file_data, 0, sizeof(file_data));
file_handle = INVALID_HANDLE_VALUE;
}
return is_directory;
}
bool create_a_directory_(const std::string& path)
{
const auto status = CreateDirectoryA(path.c_str(), nullptr);
return 0 != status;
}
#else
static std::list<std::string> gFile_list;
static std::string gFile_pattern;
int fn(const char* fpath, const struct stat* sb, int typeflag)
{
(void)sb;
const auto fpath_ = std::string(fpath);
if (FTW_F == typeflag && std::string::npos != fpath_.find(gFile_pattern))
{
gFile_list.push_back(fpath_);
}
return 0;
}
void get_files_by_pattern(const std::string& file_pattern, std::list<std::string>& file_list)
{
gFile_list.clear();
//gFile_pattern.clear();
//gFile_pattern.reserve(file_pattern.size());
auto character_position = file_pattern.rfind('*');
if (std::string::npos != character_position)
{
gFile_pattern = file_pattern.substr(0, character_position);
//std::copy(file_pattern.cbegin(),
// file_pattern.cbegin() + character_position,
// std::back_inserter(gFile_pattern));
auto character_position_ = character_position;
character_position = file_pattern.rfind('/');
if (std::string::npos != character_position)
{
ftw(file_pattern.substr(0, character_position).c_str(), fn, 1);
}
else
{
ftw(file_pattern.substr(0, character_position_).c_str(), fn, 1);
}
}
else
{
gFile_pattern = file_pattern;
ftw(file_pattern.c_str(), fn, 1);
}
std::copy(gFile_list.cbegin(), gFile_list.cend(), std::back_inserter(file_list));
}
bool is_path_a_directory(const std::string& path)
{
auto is_directory = false;
DIR* dir = nullptr;
if (nullptr != (dir = opendir(path.c_str())))
{
closedir(dir);
dir = nullptr;
is_directory = true;
}
return is_directory;
}
bool create_a_directory_(const std::string& path)
{
static const auto mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
const auto status = mkdir(path.c_str(), mode);
return 0 == status;
}
#endif // _WIN32
bool create_a_directory(const std::string& path)
{
if (path.empty() ||
"/" == path ||
is_path_a_directory(path) ||
create_a_directory_(path))
{
return true;
}
auto pos = path.cbegin();
auto is_created = false;
std::string current_directory(FILENAME_MAX, '\0');
while (path.cend() != (pos = find_phrase_start(std::make_pair(pos, path.cend()), "/")))
{
current_directory.clear();
//
std::copy(
path.cbegin(),
pos,
std::back_inserter(current_directory));
//
std::advance(pos, 1);
if (current_directory.empty() || is_path_a_directory(current_directory))
{
continue;
}
if (false == (is_created = create_a_directory_(current_directory)))
{
break;
}
}
if (!is_created)
{
return false;
}
return create_a_directory_(path);
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include <list>
#include <string>
#include <cstring>
#ifndef _PATH_H_
#define _PATH_H_
std::string combine(const std::list<std::string>& paths);
std::string get_directory_name(const std::string& path);
std::string get_file_name(const std::string& path);
std::string get_relative_path(const std::string& path, std::size_t count_of_components);
void get_files_by_pattern(const std::string& file_pattern, std::list<std::string>& file_list);
bool is_path_a_directory(const std::string& path);
bool create_a_directory(const std::string& path);
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "procedure.h"
#include "common.h"
#include "descriptor.h"
#include <set>
#include <cctype>
#include <cassert>
#include <iterator>
#include <algorithm>
void get_return_type_and_name(
const std::pair<std::string::const_iterator, std::string::const_iterator>& input, std::string& return_type,
std::string& name)
{
static const auto tab_space = std::set<char>({ '\t', ' ' });
//
return_type.clear();
name.clear();
if (std::get<0>(input) == std::get<1>(input))
{
return;
}
return_type.reserve(static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))));
name.reserve(static_cast<std::size_t>(std::distance(std::get<0>(input), std::get<1>(input))));
//
auto pos = std::get<1>(input);
std::set<std::string::const_iterator> positions;
do
{
std::advance(pos, -1);
if (positions.empty())
{
if (0 != tab_space.count(*pos))
{
while (std::get<0>(input) != pos)
{
std::advance(pos, -1);
if (0 == tab_space.count(*pos))
{
break;
}
}
}
std::advance(pos, 1);
positions.insert(pos);
}
else if (0 != tab_space.count(*pos))
{
std::advance(pos, 1);
positions.insert(pos);
break;
}
}
while (std::get<0>(input) != pos);
if (positions.size() == 2 && std::get<0>(input) != *positions.cbegin())
{
pos = *positions.cbegin();
while ('*' == *pos && pos != *positions.crbegin())
{
std::advance(pos, 1);
}
name += std::string(pos, *positions.crbegin());
do
{
std::advance(pos, -1);
if (0 == tab_space.count(*pos))
{
break;
}
}
while (std::get<0>(input) != pos);
std::advance(pos, 1);
return_type += std::string(std::get<0>(input), pos);
}
}
void get_parameters(
const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
std::list<std::string>& parameters)
{
auto input_ = input;
parameters.clear();
//
std::get<0>(input_) = std::find_if(std::get<0>(input), std::get<1>(input),
[](const char& ch)
{
return '(' == ch;
});
if (std::get<1>(input) == std::get<0>(input_))
{
return;
}
std::advance(std::get<0>(input_), 1);
std::get<1>(input_) = std::find_if(std::get<0>(input_), std::get<1>(input),
[](const char& ch)
{
return ')' == ch;
});
//
parameters = split(input_, ',', false);
for (auto& parameter : parameters)
{
trim(parameter);
}
}
_procedure disassemble_procedure(const std::pair<std::string::const_iterator, std::string::const_iterator>&
procedure)
{
_procedure procedure_;
//TODO: See next commented code, check closed symbol - instead this contains.
if (contains(procedure, "typedef"))
{
return procedure_;
}
static const std::set<char> function_should_start_from({ '(', '{' });
//static const std::set<char> function_should_finish_with({ ')', '}' });
std::set<std::string::const_iterator> positions;
for (const auto& ch : function_should_start_from)
{
for (auto pos = std::get<0>(procedure); pos != std::get<1>(procedure); ++pos)
{
if (ch == (*pos))
{
positions.insert(pos);
}
}
if (!positions.empty())
{
break;
}
}
if (positions.empty())
{
return procedure_;
}
else if (positions.size() == 1)
{
get_return_type_and_name(std::make_pair(std::get<0>(procedure), *positions.cbegin()), procedure_.return_type,
procedure_.name);
get_parameters(std::make_pair(*positions.cbegin(), std::get<1>(procedure)), procedure_.parameters);
}
else if (3 == positions.size())
{
auto pos = positions.cbegin();
std::advance(pos, 1);
//
get_return_type_and_name(std::make_pair(std::get<0>(procedure), *pos), procedure_.return_type,
procedure_.name);
get_parameters(std::make_pair(*pos, std::get<1>(procedure)), procedure_.parameters);
}
#ifndef NDEBUG
else
{
//TODO:
}
#endif
return procedure_;
}
_procedure disassemble_procedure(const std::string& procedure)
{
return disassemble_procedure(std::make_pair(procedure.cbegin(), procedure.cend()));
}
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map,
std::string& parameter)
{
assert(!type_map.empty());
auto next_param = false;
for (const auto& type_pair : type_map)
{
auto parameter_begin = std::find_if(parameter.cbegin(), parameter.cend(), [](const char& ch)
{
return ' ' != ch;
});
while (parameter_begin != parameter.cend())
{
if (starts_with(std::make_pair(parameter_begin, parameter.cend()), std::get<0>(type_pair)) &&
(static_cast<std::size_t>(std::distance(parameter_begin, parameter.cend())) == std::get<0>(type_pair).size()
|| ' ' == *(parameter_begin + std::get<0>(type_pair).size())
|| '*' == *(parameter_begin + std::get<0>(type_pair).size())))
{
parameter = std::string(parameter.cbegin(),
parameter_begin) + std::get<1>(type_pair) + (&parameter[std::distance(parameter.cbegin(),
parameter_begin) + std::get<0>(type_pair).size()]);
next_param = true;
break;
}
parameter_begin = std::find_if(parameter_begin, parameter.cend(), [](const char& ch)
{
return ' ' == ch;
});
//
parameter_begin = std::find_if(parameter_begin, parameter.cend(), [](const char& ch)
{
return ' ' != ch;
});
}
if (next_param)
{
break;
}
}
}
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map,
std::list<std::string>& parameters)
{
for (auto& parameter : parameters)
{
replace_parameters_type(type_map, parameter);
}
}
bool is_procedure_template(const std::string& procedure)
{
const auto i = procedure.find('{');
if (std::string::npos != i && 2 < procedure.size() && 1 < i && i < procedure.size() - 1 &&
!std::isspace(procedure[i - 1]) && !std::isspace(procedure[i + 1]))
{
const auto j = procedure.find('}', i + 1);
if (std::string::npos != j && j < procedure.size() - 1 && !std::isspace(procedure[j - 1]) &&
!std::isspace(procedure[j + 1]))
{
const auto k = procedure.find('(', j + 1);
if (std::string::npos != k)
{
const auto m = procedure.find('T', k);
if (m < procedure.size() - 1)
{
return true;
}
}
}
}
return false;
}
bool is_procedure_template(const _procedure& procedure)
{
return is_procedure_template(
std::string(procedure.return_type + ' ' + procedure.name + '(' + join(", ", procedure.parameters) + ')'));
/*auto is_template = is_procedure_template(procedure.return_type);
if (is_template)
{
return is_template;
}
return is_procedure_template(procedure.name);*/
}
void get_type_name(char prefix, std::string& type_name)
{
switch (prefix)
{
case 'b':
case 'B':
type_name += "byte";
break;
case 'd':
case 'D':
type_name += "double";
break;
case 'f':
case 'F':
type_name += "float";
break;
case 'i':
case 'I':
type_name += "int";
break;
case 's':
case 'S':
type_name += "short";
break;
default:
break;
}
}
void realize_template_procedure(std::list<std::string>& procedures)
{
for (auto procedure = procedures.cbegin(); procedure != procedures.cend(); ++procedure)
{
std::list<std::string> procedures_;
realize_template_procedure(*procedure, procedures_);
if (!procedures_.empty())
{
procedures.splice(procedure, procedures_);
procedure = procedures.erase(procedure);
std::advance(procedure, -1);
}
}
}
void realize_template_procedure(const std::string& procedure, std::list<std::string>& procedures)
{
const auto i = procedure.find('{');
if (std::string::npos != i && 2 < procedure.size() && 1 < i && i < procedure.size() - 1 &&
!std::isspace(procedure[i - 1]) && !std::isspace(procedure[i + 1]))
{
const auto j = procedure.find('}', i + 1);
if (std::string::npos != j && j < procedure.size() - 1 && !std::isspace(procedure[j - 1]) &&
!std::isspace(procedure[j + 1]))
{
const auto k = procedure.find('(', j + 1);
if (std::string::npos != k)
{
const auto m = procedure.find('T', k);
if (m < procedure.size() - 1)
{
std::string type_name(24, '\0');
std::string new_procedure(128, '\0');
for (auto l = i + 1; l < j; ++l)
{
if (',' == procedure[l])
{
continue;
}
else if (std::isdigit((int)procedure[l]))
{
new_procedure.clear();
new_procedure += procedure.substr(0, i) + procedure[l] + procedure.substr(j + 1);
realize_template_procedure(new_procedure, procedures);
}
else
{
type_name.clear();
get_type_name(procedure[l], type_name);
if (type_name.empty() && (
starts_with(procedure, l, "ub") ||
starts_with(procedure, l, "us") ||
starts_with(procedure, l, "ui")))
{
type_name += "unsigned ";
++l;
get_type_name(procedure[l], type_name);
}
else if (type_name.empty())
{
continue;
}
new_procedure.clear();
new_procedure += procedure.substr(0, i) + procedure[l] + procedure.substr(j + 1,
m - 1 - j) + type_name + procedure.substr(m + 1);
procedures.push_back(new_procedure);
}
}
}
}
}
}
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _PROCEDURE_H_
#define _PROCEDURE_H_
#include <list>
#include <string>
#include <utility>
struct _procedure;
void get_return_type_and_name(
const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
std::string& return_type, std::string& name);
void get_parameters(
const std::pair<std::string::const_iterator, std::string::const_iterator>& input,
std::list<std::string>& parameters);
_procedure disassemble_procedure(const std::pair<std::string::const_iterator, std::string::const_iterator>&
procedure);
_procedure disassemble_procedure(const std::string& procedure);
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map,
std::string& parameter);
void replace_parameters_type(const std::list<std::pair<std::string, std::string>>& type_map,
std::list<std::string>& parameters);
bool is_procedure_template(const std::string& procedure);
bool is_procedure_template(const _procedure& procedure);
void get_type_name(char prefix, std::string& type_name);
void realize_template_procedure(std::list<std::string>& procedures);
void realize_template_procedure(const std::string& procedure,
std::list<std::string>& procedures);
#endif
<?xml version="1.0" encoding="utf-8"?>
<Project InitialTargets="download_glew_generator;glew_generator" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)'==''">
<Configuration>Release</Configuration>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'==''">
<Platform>Win32</Platform>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<PropertyGroup Label="glew_generator_repository">
<glew_generator_url Condition="'$(LOCAL_FOLDER)'==''">https://gist.github.com/421cb7df499b7515e6f5e278e4335b87.git</glew_generator_url>
<glew_generator_url Condition="'$(LOCAL_FOLDER)'!=''">$(LOCAL_FOLDER)\glew_generator</glew_generator_url>
<glew_generator_destination>$(ProjectDir)glew_generator</glew_generator_destination>
<glew_generator_destination Condition="Exists('$(ProjectDir)..\..\auto')">$(ProjectDir)..\..\auto\glew_generator</glew_generator_destination>
<glew_generator_destination Condition="''!='$(NO_GIT)'">$(glew_generator_url)</glew_generator_destination>
<glew_generator_hash>...</glew_generator_hash>
</PropertyGroup>
<Target Name="download_glew_generator" Condition="''=='$(NO_GIT)'">
<Message Importance="normal" Text="--------------------------------------------------------------------" />
<Message Importance="normal" Text="Downloading glew_generator" />
<Message Importance="normal" Text="--------------------------------------------------------------------" />
<Message Importance="low" Text="git clone $(glew_generator_url) $(glew_generator_destination)" />
<Exec
Command="git --version"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="!Exists('$(glew_generator_destination)\.git\HEAD')"
Command="git clone $(glew_generator_url) $(glew_generator_destination)"
WorkingDirectory="$(ProjectDir)" />
<Exec
Condition="Exists('$(glew_generator_destination)\.git\HEAD')"
Command="git log -1 --pretty=oneline"
WorkingDirectory="$(glew_generator_destination)" />
</Target>
<ItemGroup Label="ProjectsToBuild">
<ProjectsToBuild Include="$(glew_generator_destination)\glew_generator.vcxproj" />
</ItemGroup>
<Target Name="glew_generator">
<Message Importance="low" Text="MSBuildToolsVersion is $(MSBuildToolsVersion)" />
<Message Importance="low" Text="Platform is $(Platform)" />
<Message Importance="low" Text="PlatformToolset is $(PlatformToolset)" />
<Message Importance="low" Text="LOCAL_FOLDER is $(LOCAL_FOLDER)" />
<Message Importance="low" Text="NO_GIT is $(NO_GIT)" />
<MSBuild
Condition="'$(Platform)' == 'Win32' Or '$(Platform)' == 'x64'"
BuildInParallel="true"
Projects="@(ProjectsToBuild)"
Properties="Configuration=Release;Platform=$(Platform);PlatformToolset=$(PlatformToolset);LOCAL_FOLDER=$(LOCAL_FOLDER);NO_GIT=$(NO_GIT)" />
<MSBuild
Condition="'$(Platform)' != 'Win32' And '$(Platform)' != 'x64'"
BuildInParallel="true"
Projects="@(ProjectsToBuild)"
Properties="Configuration=Release;Platform=Win32;PlatformToolset=$(PlatformToolset);LOCAL_FOLDER=$(LOCAL_FOLDER);NO_GIT=$(NO_GIT)" />
</Target>
</Project>
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#include "version.h"
#include "common.h"
#include "interpreter.h"
#include <cstdlib>
#include <iterator>
#include <algorithm>
//TODO: in a future probably will be a part of hypothetic "make interpreter".
void assign_variable(const std::list<std::pair<std::string, std::string>>& variables, std::string& variable)
{
static const auto key_phrase = std::string("$(");
//
auto pos1 = variable.cbegin();
while (variable.cend() != (pos1 = find_phrase_start(
std::make_pair(pos1, variable.cend()), key_phrase)))
{
std::advance(pos1, key_phrase.size());
//
const auto pos2 = std::find_if(pos1, variable.cend(), [](const char& ch)
{
return ')' == ch;
});
//
auto key = std::string(pos1, pos2);
//
const auto early_added_pair = std::find_if(variables.cbegin(), variables.cend(),
[&key](const std::pair<std::string, std::string>& version_pair)
{
return std::get<0>(version_pair) == key;
});
if (variables.cend() == early_added_pair)
{
break;
}
key = key_phrase + key + ')';
replace(variable, key, std::get<1>(*early_added_pair));
pos1 = variable.cbegin();
}
}
std::list<std::pair<std::string, std::string>> read_version(std::istream& input)
{
std::list<std::pair<std::string, std::string>> result;
for (std::string line; std::getline(input, line);)
{
if (line.empty())
{
continue;
}
auto raw_pair = split(line, '=', true);
if (raw_pair.size() != 2)
{
continue;
}
trim(raw_pair.front());
trim(raw_pair.back());
//
assign_variable(result, raw_pair.back());
//
auto exists_pair = std::find_if(result.begin(), result.end(),
[&raw_pair](const std::pair<std::string, std::string>& version_pair)
{
return std::get<0>(version_pair) == raw_pair.front();
});
if (result.end() != exists_pair)
{
std::get<1>(*exists_pair) = raw_pair.back();
}
else
{
result.push_back(std::make_pair(raw_pair.front(), raw_pair.back()));
}
}
return result;
}
_version str_version_to_version(const std::list<std::pair<std::string, std::string>>& version)
{
const auto version_info = std::find_if(version.cbegin(), version.cend(),
[](const std::pair<std::string, std::string> element)
{
return ends_with(std::get<0>(element), "_VERSION");
});
//
auto ver = _version{ 0, 0, 0 };
if (version.cend() != version_info && !std::get<1>(*version_info).empty())
{
auto str_ver = std::get<1>(*version_info).cbegin();
for (auto i = 0; i < 3 && str_ver != std::get<1>(*version_info).cend(); ++i)
{
if ('.' == (*str_ver))
{
--i;
++str_ver;
continue;
}
char* ch = nullptr;
const auto l = std::strtol(&(*str_ver), &ch, 10);
const auto distance = static_cast<size_t>(const_cast<const char*>(ch) - (&(*str_ver)));
if (0 == distance ||
static_cast<size_t>(std::distance(str_ver, std::get<1>(*version_info).cend())) < distance)
{
return ver;
}
std::advance(str_ver, distance);
switch (i)
{
case 0:
ver.major = l;
break;
case 1:
ver.minor = l;
break;
case 2:
ver.micro = l;
break;
default:
break;
}
}
}
return ver;
}
bool perl(std::istream& input,
std::list<std::string>& parameters,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log)
{
(void)log;
auto was_command_be_apply = false;
for (auto& parameter : parameters)
{
if (parameter.empty())
{
continue;
}
assign_variable(version, parameter);
}
for (std::string line; std::getline(input, line);)
{
for (const auto& parameter : parameters)
{
//was_command_be_apply = perl(line, parameter);
//TODO: one of parameter may failed,
//add log to this function to monitor which exactly.
const auto result = perl(line, parameter);
if (!was_command_be_apply && result)
{
was_command_be_apply = result;
}
}
output += line + '\n';
}
return was_command_be_apply;
}
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 - 2019 https://github.com/TheVice/
*
*/
#ifndef _VERSION_H_
#define _VERSION_H_
#include <list>
#include <string>
#include <utility>
#include <istream>
#include <ostream>
struct _version
{
int major;
int minor;
int micro;
friend bool operator==(const _version& a, const _version& b)
{
return (a.major == b.major && a.minor == b.minor && a.micro == b.micro);
}
friend bool operator!=(const _version& a, const _version& b)
{
return !(operator==(a, b));
}
friend bool operator<(const _version& a, const _version& b)
{
if (a.major < b.major)
{
return true;
}
else if (a.major == b.major && a.minor < b.minor)
{
return true;
}
else if (a.major == b.major && a.minor == b.minor && a.micro < b.micro)
{
return true;
}
return false;
}
friend bool operator>(const _version& a, const _version& b)
{
return !(operator<(a, b));
}
};
static const _version version_1_3_0{ 1, 3, 0 };
static const _version version_1_13_0{ 1, 13, 0 };
static const _version version_2_2_0{ 2, 2, 0 };
static const _version version_2_2_2{ 2, 2, 2 };
void assign_variable(const std::list<std::pair<std::string, std::string>>& variables, std::string& variable);
std::list<std::pair<std::string, std::string>> read_version(std::istream& input);
_version str_version_to_version(const std::list<std::pair<std::string, std::string>>& version);
bool perl(std::istream& input,
std::list<std::string>& parameters,
const std::list<std::pair<std::string, std::string>>& version,
std::string& output,
std::ostream& log);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment