Rename interpretor to interpreter.
[Faustine.git] / interpreter / preprocessor / faust-0.9.47mr3 / compiler / generator / description.cpp
diff --git a/interpreter/preprocessor/faust-0.9.47mr3/compiler/generator/description.cpp b/interpreter/preprocessor/faust-0.9.47mr3/compiler/generator/description.cpp
new file mode 100644 (file)
index 0000000..eacd9a0
--- /dev/null
@@ -0,0 +1,339 @@
+//------------------------------------
+// generation of an xml description
+//------------------------------------
+#include <map>
+#include <set>
+#include <string>
+
+#include "description.hh"
+#include "Text.hh"
+
+/**
+ * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata
+ */
+void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata)
+{
+    enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
+    int state = kLabel; int deep = 0;
+    string key, value;
+
+    for (size_t i=0; i < fulllabel.size(); i++) {
+        char c = fulllabel[i];
+        switch (state) {
+            case kLabel :
+                assert (deep == 0);
+                switch (c) {
+                    case '\\' : state = kEscape1; break;
+                    case '[' : state = kKey; deep++; break;
+                    default : label += c;
+                }
+                break;
+
+            case kEscape1 :
+                label += c;
+                state = kLabel;
+                break;
+
+            case kEscape2 :
+                key += c;
+                state = kKey;
+                break;
+
+            case kEscape3 :
+                value += c;
+                state = kValue;
+                break;
+
+            case kKey :
+                assert (deep > 0);
+                switch (c) {
+                    case '\\' :  state = kEscape2;
+                                break;
+
+                    case '[' :  deep++;
+                                key += c;
+                                break;
+
+                    case ':' :  if (deep == 1) {
+                                    state = kValue;
+                                } else {
+                                    key += c;
+                                }
+                                break;
+                    case ']' :  deep--;
+                                if (deep < 1) {
+                                    metadata[rmWhiteSpaces(key)].insert("");
+                                    state = kLabel;
+                                    key="";
+                                    value="";
+                                } else {
+                                    key += c;
+                                }
+                                break;
+                    default :   key += c;
+                }
+                break;
+
+            case kValue :
+                assert (deep > 0);
+                switch (c) {
+                    case '\\' : state = kEscape3;
+                                break;
+
+                    case '[' :  deep++;
+                                value += c;
+                                break;
+
+                    case ']' :  deep--;
+                                if (deep < 1) {
+                                    metadata[rmWhiteSpaces(key)].insert(rmWhiteSpaces(value));
+                                    state = kLabel;
+                                    key="";
+                                    value="";
+                                } else {
+                                    value += c;
+                                }
+                                break;
+                    default :   value += c;
+                }
+                break;
+
+            default :
+                cerr << "ERROR unrecognized state " << state << endl;
+        }
+    }
+    label = rmWhiteSpaces(label);
+}
+
+//------------------------ specific schema -------------------------
+
+string extractName(Tree fulllabel)
+{
+    string name;
+    map<string, set<string> >   metadata;
+
+    extractMetadata(tree2str(fulllabel), name, metadata);
+    return name;
+}
+
+
+/**
+ * removes enclosing quotes and transforms '<', '>' and '&' characters
+ */
+static string xmlize(const string& fullsrc)
+{
+    map<string, set<string> > metadata;
+    string dst;
+    string src;
+
+    extractMetadata(fullsrc, src, metadata);
+
+    for (size_t i=0; i<src.size(); i++) {
+        if (src[i] == '"' & (i==0 | i==src.size()-1)) {
+            // nothing to do just skip the quotes
+        } else {
+            switch (src[i]) {
+                case '<' : dst += "&lt;"; break;
+                case '>' : dst += "&gt;"; break;
+                case '&' : dst += "&amp;"; break;
+                default :  dst += src[i];
+            }
+        }
+    }
+    return dst;
+}
+
+void Description::print(int n, ostream& fout)
+{
+       list<string>::iterator  s;
+       list<int>::iterator     t;
+
+       tab(n,fout); fout << "<faust>";
+
+               tab(n+1,fout);  fout << "<name>"                << xmlize(fName)                << "</name>";
+               tab(n+1,fout);  fout << "<author>"          << xmlize(fAuthor)          << "</author>";
+               tab(n+1,fout);  fout << "<copyright>"   << xmlize(fCopyright)   << "</copyright>";
+               tab(n+1,fout);  fout << "<license>"     << xmlize(fLicense)     << "</license>";
+               tab(n+1,fout);  fout << "<version>"     << xmlize(fVersion)     << "</version>";
+               tab(n+1,fout);  fout << "<inputs>"          << fInputs                  << "</inputs>";
+               tab(n+1,fout);  fout << "<outputs>"     << fOutputs             << "</outputs>";
+
+               tab(n+1,fout);  fout << "<ui>";
+
+                       // active widget list
+                       tab(n+2,fout);  fout << "<activewidgets>";
+                               tab(n+3,fout);  fout << "<count>" << fActiveWidgetCount << "</count>";
+                               for (s = fActiveLines.begin(); s != fActiveLines.end(); s++) {
+                                       tab(n+3, fout); fout << *s;
+                               }
+                       tab(n+2,fout);  fout << "</activewidgets>";
+
+                       tab(n+2,fout);
+
+                       // passive widget list
+                       tab(n+2,fout);  fout << "<passivewidgets>";
+                               tab(n+3,fout);  fout << "<count>" << fPassiveWidgetCount << "</count>";
+                               for (s = fPassiveLines.begin(); s != fPassiveLines.end(); s++) {
+                                       tab(n+3, fout); fout << *s;
+                               }
+                       tab(n+2,fout);  fout << "</passivewidgets>";
+
+
+                       tab(n+2,fout);
+
+                       // widget layout
+                       tab(n+2,fout);  fout << "<layout>";
+                               for (   t = fLayoutTabs.begin(), s = fLayoutLines.begin();
+                                               s != fLayoutLines.end(); t++, s++) {
+                                       tab(n+3+*t, fout); fout << *s;
+                               }
+                       tab(n+2,fout);  fout << "</layout>";
+
+               tab(n+1,fout);  fout << "</ui>";
+
+
+       tab(n,fout); fout << "</faust>" << endl;
+
+}
+
+void Description::ui(Tree t)
+{
+       addGroup(0,t);
+}
+
+
+void Description::addGroup(int level, Tree t)
+{
+       Tree    label, elements, varname, sig;
+       const char*     groupnames[] = {"vgroup", "hgroup", "tgroup"};
+
+       if (isUiFolder(t, label, elements)) {
+
+               const int               orient = tree2int(left(label));
+               const char *    str = tree2str(right(label));
+
+               addLayoutLine(level, subst("<group type=\"$0\">", groupnames[orient]));
+               addLayoutLine(level+1, subst("<label>$0</label>", xmlize(str)));
+               while (!isNil(elements)) {
+                       addGroup(level+1, right(hd(elements)));
+                       elements = tl(elements);
+               }
+               addLayoutLine(level, "</group>");
+
+       } else if (isUiWidget(t, label, varname, sig)) {
+
+               int w = addWidget(label, varname, sig);
+               addLayoutLine(level, subst("<widgetref id=\"$0\" />", T(w)));
+
+       } else {
+
+               fprintf(stderr, "error in user interface generation 2\n");
+               exit(1);
+
+       }
+}
+
+void Description::tab (int n, ostream& fout)
+{
+       fout << '\n';
+       while (n--)     fout << '\t';
+}
+
+int Description::addWidget(Tree label, Tree varname, Tree sig)
+{
+       Tree path, c, x, y, z;
+
+       // add an active widget description
+
+       if ( isSigButton(sig, path) )                                   {
+
+               fWidgetID++;
+               fActiveWidgetCount++;
+               addActiveLine(subst("<widget type=\"button\" id=\"$0\">", T(fWidgetID)));
+                       addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
+                       addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
+               addActiveLine("</widget>");
+
+       } else if ( isSigCheckbox(sig, path) )                  {
+
+               fWidgetID++;
+               fActiveWidgetCount++;
+               addActiveLine(subst("<widget type=\"checkbox\" id=\"$0\">", T(fWidgetID)));
+                       addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
+                       addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
+               addActiveLine("</widget>");
+
+       } else if ( isSigVSlider(sig, path,c,x,y,z) )   {
+
+               fWidgetID++;
+               fActiveWidgetCount++;
+               addActiveLine(subst("<widget type=\"vslider\" id=\"$0\">", T(fWidgetID)));
+                       addActiveLine(subst("\t<label>$0</label>",              xmlize(tree2str(label))));
+                       addActiveLine(subst("\t<varname>$0</varname>",  tree2str(varname)));
+                       addActiveLine(subst("\t<init>$0</init>",                T(tree2double(c))));
+                       addActiveLine(subst("\t<min>$0</min>",                  T(tree2double(x))));
+                       addActiveLine(subst("\t<max>$0</max>",                  T(tree2double(y))));
+                       addActiveLine(subst("\t<step>$0</step>",                T(tree2double(z))));
+               addActiveLine("</widget>");
+
+       } else if ( isSigHSlider(sig, path,c,x,y,z) )   {
+
+               fWidgetID++;
+               fActiveWidgetCount++;
+               addActiveLine(subst("<widget type=\"hslider\" id=\"$0\">", T(fWidgetID)));
+                       addActiveLine(subst("\t<label>$0</label>",              xmlize(tree2str(label))));
+                       addActiveLine(subst("\t<varname>$0</varname>",  tree2str(varname)));
+                       addActiveLine(subst("\t<init>$0</init>",                T(tree2double(c))));
+                       addActiveLine(subst("\t<min>$0</min>",                  T(tree2double(x))));
+                       addActiveLine(subst("\t<max>$0</max>",                  T(tree2double(y))));
+                       addActiveLine(subst("\t<step>$0</step>",                T(tree2double(z))));
+               addActiveLine("</widget>");
+
+       } else if ( isSigNumEntry(sig, path,c,x,y,z) )  {
+
+               fWidgetID++;
+               fActiveWidgetCount++;
+               addActiveLine(subst("<widget type=\"nentry\" id=\"$0\">", T(fWidgetID)));
+                       addActiveLine(subst("\t<label>$0</label>",              xmlize(tree2str(label))));
+                       addActiveLine(subst("\t<varname>$0</varname>",  tree2str(varname)));
+                       addActiveLine(subst("\t<init>$0</init>",                T(tree2double(c))));
+                       addActiveLine(subst("\t<min>$0</min>",                  T(tree2double(x))));
+                       addActiveLine(subst("\t<max>$0</max>",                  T(tree2double(y))));
+                       addActiveLine(subst("\t<step>$0</step>",                T(tree2double(z))));
+               addActiveLine("</widget>");
+
+
+       // add a passive widget description
+
+       } else if ( isSigVBargraph(sig,path,x,y,z) )    {
+
+               fWidgetID++;
+               fPassiveWidgetCount++;
+               addPassiveLine(subst("<widget type=\"vbargraph\" id=\"$0\">", T(fWidgetID)));
+                       addPassiveLine(subst("\t<label>$0</label>",     xmlize(tree2str(label))));
+                       addPassiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
+                       addPassiveLine(subst("\t<min>$0</min>",                 T(tree2double(x))));
+                       addPassiveLine(subst("\t<max>$0</max>",                 T(tree2double(y))));
+               addPassiveLine("</widget>");
+
+       } else if ( isSigHBargraph(sig,path,x,y,z) )    {
+
+               fWidgetID++;
+               fPassiveWidgetCount++;
+               addPassiveLine(subst("<widget type=\"hbargraph\" id=\"$0\">", T(fWidgetID)));
+                       addPassiveLine(subst("\t<label>$0</label>",     xmlize(tree2str(label))));
+                       addPassiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
+                       addPassiveLine(subst("\t<min>$0</min>",                 T(tree2double(x))));
+                       addPassiveLine(subst("\t<max>$0</max>",                 T(tree2double(y))));
+               addPassiveLine("</widget>");
+
+       } else {
+               fprintf(stderr, "Error describing widget : unrecognized expression\n");
+               exit(1);
+       }
+
+       return fWidgetID;
+}
+
+
+