// nlatexdb Version 0.03 // Database Access in LaTeX // Copyright (C) 2011 Robin Höns, Integranova GmbH // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // For more information see the web page http://hoens.net/robin using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace nlatexdb { class Processer { public Processer() { m_verbosity = 0; m_encoding = Encoding.GetEncoding(1252); m_commandlineargs = new List(); m_activecommand = null; m_cmds = new List(); m_cmds.Add(new CommandParser("texdbconnectionnet", 2, false, texdbconnection)); m_cmds.Add(new CommandParser("texdbdef", 3, false, texdbdef)); m_cmds.Add(new CommandParser("texdbfor", 2, true, texdbfor)); m_cmds.Add(new CommandParser("texdbforfile", 3, true, texdbforfile)); m_cmds.Add(new CommandParser("texdbif", 2, true, texdbif)); m_cmds.Add(new CommandParser("texdbcommand", 1, false, texdbcommand)); m_qrys = new Dictionary(); m_varvalues = new Dictionary(); m_latexpostprocess_wholefile = true; m_cmdlineargvarprefix = "##"; SqlQueryVar.ClearLatexReplace(); SqlQueryVar.AddLatexReplace('\\', @"\ensuremath{\backslash}"); SqlQueryVar.AddLatexReplace('_', @"\_"); SqlQueryVar.AddLatexReplace('$', @"\$"); SqlQueryVar.AddLatexReplace('&', @"\&"); SqlQueryVar.AddLatexReplace('#', @"\#"); SqlQueryVar.AddLatexReplace('{', @"\{"); SqlQueryVar.AddLatexReplace('}', @"\}"); SqlQueryVar.AddLatexReplace('~', @"\~{}"); SqlQueryVar.AddLatexReplace('%', @"\%"); ReadAppConfig(); } private void ReadAppConfig() { NlatexdbSettings settings = System.Configuration.ConfigurationManager.GetSection("NlatexdbSettings") as NlatexdbSettings; if (settings != null) { string cmdl2 = settings.CmdLineArgumentVarPrefix; if (!String.IsNullOrEmpty(cmdl2)) { m_cmdlineargvarprefix = cmdl2; Debug("prefix: {0}", cmdl2); } string regexsplitter = settings.RegexSplitter; if (!String.IsNullOrEmpty(regexsplitter)) { SqlQueryVar.SetRegexSplitter(regexsplitter); } string varsplitter = settings.VariableSplitter; if (!String.IsNullOrEmpty(varsplitter)) { SqlQuery.SetVariableSplitter(varsplitter); } LatexCharReplaceCollection lrcoll = settings.LatexCharReplaceItems; foreach (LatexCharReplaceElement lrelem in lrcoll) { Debug("replace: {0} by: {1}", lrelem.Char[0], lrelem.Replace); SqlQueryVar.AddLatexReplace(lrelem.Char[0], lrelem.Replace); } } } public void setInpath(string path) { m_inpath = path; } public void setOutpath(string path) { m_outpath = path; } public void setLatexbefehl(string befehl) { m_latexbefehl = befehl; } public void setEncoding(string enc) { if (enc.Equals("utf-8", StringComparison.InvariantCultureIgnoreCase)) { m_encoding = new UTF8EncodingWithoutPreamble(); } else { try { m_encoding = Encoding.GetEncoding(enc); } catch (Exception ex) { Console.WriteLine(ex.Message); Debug(ex.ToString()); } } } public void incVerbosity() { m_verbosity++; } public void addCmdlineArg(string arg) { m_commandlineargs.Add(arg); string key = m_cmdlineargvarprefix + m_commandlineargs.Count.ToString(); m_varvalues[key] = new SqlQueryVar(key, arg); ; } public int Go() { int ergebnis = 0; try { if (String.IsNullOrEmpty(m_inpath)) { throw new Exception("No input file given!"); } string outpath = m_outpath; if (String.IsNullOrEmpty(outpath)) { outpath = m_inpath.Replace(".tex", "1.tex"); if (String.IsNullOrEmpty(outpath)) { outpath = String.Concat(m_inpath, "1"); } } using (StreamReader sr = new StreamReader(m_inpath, m_encoding)) { try { OpenOutstream(outpath); string line; while ((line = sr.ReadLine()) != null) { HandleLine(line); } } finally { CloseOutstream(); } } LatexPostprocess(outpath, true); } catch (Exception ex) { Console.WriteLine(ex.Message); Debug(ex.ToString()); ergebnis = 1; } finally { if (m_conn != null) { try { m_conn.Close(); } catch { } } if (m_outstream != null) { try { m_outstream.Close(); } catch { } } } return ergebnis; } public void OpenOutstream(string outpath) { CloseOutstream(); // just in case System.IO.FileStream outstream = new System.IO.FileStream(outpath, System.IO.FileMode.Create, System.IO.FileAccess.Write); m_outstream = new System.IO.StreamWriter(outstream, m_encoding); } public void CloseOutstream() { if (m_outstream != null) { m_outstream.Close(); m_outstream=null; } } public void LatexPostprocess(string texinputpath, bool renametoinpath) { if (renametoinpath && !m_latexpostprocess_wholefile) { // If there was a \texdbforfile command, don't postprocess the // top file: It is expected to be empty. return; } if (!String.IsNullOrEmpty(m_latexbefehl)) { System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.FileName = m_latexbefehl; p.StartInfo.CreateNoWindow = true; p.StartInfo.Arguments = texinputpath; p.Start(); p.WaitForExit(); string extension = null; if (m_latexbefehl.Equals("latex")) { extension = "dvi"; } else if (m_latexbefehl.Equals("pdflatex")) { extension = "pdf"; } if (renametoinpath && !String.IsNullOrEmpty(extension)) { string filefromlatex = System.IO.Path.ChangeExtension(texinputpath, extension); string filetorename = System.IO.Path.ChangeExtension(m_inpath, extension); System.IO.File.Delete(filetorename); System.IO.File.Move(filefromlatex, filetorename); } } } public void ListProviders() { System.Data.DataTable providers = System.Data.Common.DbProviderFactories.GetFactoryClasses(); foreach (System.Data.DataRow provider in providers.Rows) { foreach (System.Data.DataColumn c in providers.Columns) Console.WriteLine(c.ColumnName + ":" + provider[c]); Console.WriteLine("---"); } } // private void HandleLineUnlessEmpty(string line) // { // if (!String.IsNullOrEmpty(line)) // { // HandleLine(line); // } // } private void HandleRestOfLine(string line, int hintercmd) { if (hintercmd >= 0 && hintercmd < line.Length) { HandleLine(line.Substring(hintercmd)); } } public void HandleLine(string line) { if (m_activecommand != null) { // Aha, ein Kommando ist aktiv. Sammele die Zeilen. int hintercmd = m_activecommand.ProcessLine(line); HandleRestOfLine(line, hintercmd); return; } // Erstmal schauen nach Kommentar int prozentsuche = 0; int prozentindex = -1; while (prozentsuche >= 0) { prozentindex = line.IndexOf('%', prozentsuche); if (prozentindex > 0 && line[prozentindex - 1] == '\\') { // Dieses % ist auskommentiert. Dahinter weitersuchen. prozentsuche = prozentindex + 1; prozentindex = -1; } else { break; } } int firstcommandindex = line.Length + 1; foreach (CommandParser c in m_cmds) { int cmdindex = c.FirstIndexIn(line, prozentindex); if (cmdindex >= 0 && cmdindex < firstcommandindex) { m_activecommand = c; firstcommandindex = cmdindex; } } if (m_activecommand != null) { // Aha, Kommando gefunden. if (firstcommandindex > 0) { // Da ist noch Text davor. HandleLine(line.Substring(0, firstcommandindex)); } // Rufe Kommando auf. Bzw. erstmal die Klammern suchen. int hintercmd = m_activecommand.StartProcess(line, firstcommandindex); HandleRestOfLine(line, hintercmd); } else { // Kein Kommando in dieser Zeile. Einfach ausgeben. Erst aber Variablen einfügen. line = VariablenEinfuegen(line); m_outstream.WriteLine(line); } } public string VariablenEinfuegen(string inputline) { string line = inputline; foreach (KeyValuePair var in m_varvalues) { line = line.Replace(var.Key, var.Value.getValueLatex()); } return line; } private string listtostr(List lines) { StringBuilder sb = new StringBuilder(); foreach (string s in lines) { if (sb.Length > 0) { sb.Append(" "); } sb.Append(s); } return sb.ToString(); } private void texdbconnection(List> pars) { m_activecommand = null; string provider = listtostr(pars[0]); string connstring = listtostr(pars[1]); Debug("texdbconnection provider: {0} connstring: {1}", provider, connstring); System.Data.Common.DbProviderFactory dbfac = System.Data.Common.DbProviderFactories.GetFactory(provider); m_conn = dbfac.CreateConnection(); m_conn.ConnectionString = connstring; m_conn.Open(); } private void texdbdef(List> pars) { m_activecommand = null; string queryname = listtostr(pars[0]); string querytext = listtostr(pars[1]); string queryvars = listtostr(pars[2]); Debug("texdbdef name: {0} sql: {1} vars: {2}", queryname, querytext, queryvars); m_qrys.Add(queryname, new SqlQuery(querytext, queryvars)); } private void texdbfor(List> pars) { m_activecommand = null; string queryname = listtostr(pars[0]); List texstuff = pars[1]; Debug("texdbfor query: {0} tex lines: {1}", queryname, texstuff.Count); SqlQuery qry = m_qrys[queryname]; if (qry == null) { throw new Exception("Query " + queryname + " not found"); } qry.Execute(texstuff, m_conn, m_varvalues, this, null); } private void texdbforfile(List> pars) { m_activecommand = null; m_latexpostprocess_wholefile = false; string queryname = listtostr(pars[0]); string filepattern = listtostr(pars[1]); List texstuff = pars[2]; Debug("texdbforfile query: {0} filepattern: {1} tex lines: {2}", queryname, filepattern, texstuff.Count); SqlQuery qry = m_qrys[queryname]; if (qry == null) { throw new Exception("Query " + queryname + " not found"); } qry.Execute(texstuff, m_conn, m_varvalues, this, filepattern); } private void texdbif(List> pars) { m_activecommand = null; string queryname = listtostr(pars[0]); List texstuff = pars[1]; Debug("texdbif query: {0} tex lines: {1}", queryname, texstuff.Count); SqlQuery qry = m_qrys[queryname]; if (qry == null) { throw new Exception("Query " + queryname + " not found"); } qry.ExecuteIf(texstuff, m_conn, m_varvalues, this); } private void texdbcommand(List> pars) { m_activecommand = null; string cmd = listtostr(pars[0]); Debug("texdbcommand sql: {0}", cmd); using (System.Data.Common.DbCommand comm = m_conn.CreateCommand()) { comm.CommandText = cmd; comm.ExecuteNonQuery(); } } public static void Debug(string format, params object[] pars) { if (m_verbosity >= 1) { Console.WriteLine(format, pars); } } private string m_cmdlineargvarprefix; private static int m_verbosity = 0; private string m_outpath; private string m_latexbefehl; private bool m_latexpostprocess_wholefile; private Encoding m_encoding; private string m_inpath; private List m_commandlineargs; private System.Data.Common.DbConnection m_conn; private List m_cmds; private CommandParser m_activecommand; private System.IO.StreamWriter m_outstream; private System.Collections.Generic.Dictionary m_qrys; private System.Collections.Generic.Dictionary m_varvalues; } } // Latex can't handle the BOM (EF BB BF) that is prepended to UTF-8 by default. // So here's a UTF-8 encoding without BOM. public class UTF8EncodingWithoutPreamble : System.Text.UTF8Encoding { public static UTF8EncodingWithoutPreamble Instance = new UTF8EncodingWithoutPreamble(); private static byte[] _preamble = new byte[0]; public override byte[] GetPreamble() { return _preamble; } }