FAUST compiler  0.9.9.6b8
description.cpp
Go to the documentation of this file.
00001 //------------------------------------
00002 // generation of an xml description
00003 //------------------------------------
00004 #include <map>
00005 #include <set>
00006 #include <string>
00007 
00008 #include "description.hh"
00009 #include "Text.hh"
00010 
00015 static string rmWhiteSpaces(const string& s)
00016 {
00017     size_t i = s.find_first_not_of(" \t");
00018     size_t j = s.find_last_not_of(" \t");
00019 
00020     if ( (i != string::npos) & (j != string::npos) ) {
00021         return s.substr(i, 1+j-i);
00022     } else {
00023         return "";
00024     }
00025 }
00026 
00030 void extractMetadata(const string& fulllabel, string& label, map<string, set<string> >& metadata)
00031 {
00032     enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue};
00033     int state = kLabel; int deep = 0;
00034     string key, value;
00035 
00036     for (size_t i=0; i < fulllabel.size(); i++) {
00037         char c = fulllabel[i];
00038         switch (state) {
00039             case kLabel :
00040                 assert (deep == 0);
00041                 switch (c) {
00042                     case '\\' : state = kEscape1; break;
00043                     case '[' : state = kKey; deep++; break;
00044                     default : label += c;
00045                 }
00046                 break;
00047 
00048             case kEscape1 :
00049                 label += c;
00050                 state = kLabel;
00051                 break;
00052 
00053             case kEscape2 :
00054                 key += c;
00055                 state = kKey;
00056                 break;
00057 
00058             case kEscape3 :
00059                 value += c;
00060                 state = kValue;
00061                 break;
00062 
00063             case kKey :
00064                 assert (deep > 0);
00065                 switch (c) {
00066                     case '\\' :  state = kEscape2;
00067                                 break;
00068 
00069                     case '[' :  deep++;
00070                                 key += c;
00071                                 break;
00072 
00073                     case ':' :  if (deep == 1) {
00074                                     state = kValue;
00075                                 } else {
00076                                     key += c;
00077                                 }
00078                                 break;
00079                     case ']' :  deep--;
00080                                 if (deep < 1) {
00081                                     metadata[rmWhiteSpaces(key)].insert("");
00082                                     state = kLabel;
00083                                     key="";
00084                                     value="";
00085                                 } else {
00086                                     key += c;
00087                                 }
00088                                 break;
00089                     default :   key += c;
00090                 }
00091                 break;
00092 
00093             case kValue :
00094                 assert (deep > 0);
00095                 switch (c) {
00096                     case '\\' : state = kEscape3;
00097                                 break;
00098 
00099                     case '[' :  deep++;
00100                                 value += c;
00101                                 break;
00102 
00103                     case ']' :  deep--;
00104                                 if (deep < 1) {
00105                                     metadata[rmWhiteSpaces(key)].insert(rmWhiteSpaces(value));
00106                                     state = kLabel;
00107                                     key="";
00108                                     value="";
00109                                 } else {
00110                                     value += c;
00111                                 }
00112                                 break;
00113                     default :   value += c;
00114                 }
00115                 break;
00116 
00117             default :
00118                 cerr << "ERROR unrecognized state " << state << endl;
00119         }
00120     }
00121     label = rmWhiteSpaces(label);
00122 }
00123 
00124 //------------------------ specific schema -------------------------
00125 
00126 string extractName(Tree fulllabel)
00127 {
00128     string name;
00129     map<string, set<string> >   metadata;
00130 
00131     extractMetadata(tree2str(fulllabel), name, metadata);
00132     return name;
00133 }
00134 
00135 
00139 static string xmlize(const string& fullsrc)
00140 {
00141     map<string, set<string> > metadata;
00142     string dst;
00143     string src;
00144 
00145     extractMetadata(fullsrc, src, metadata);
00146     
00147     for (size_t i=0; i<src.size(); i++) {
00148         if (src[i] == '"' & (i==0 | i==src.size()-1)) {
00149             // nothing to do just skip the quotes
00150         } else {
00151             switch (src[i]) {
00152                 case '<' : dst += "&lt;"; break;
00153                 case '>' : dst += "&gt;"; break;
00154                 case '&' : dst += "&amp;"; break;
00155                 default :  dst += src[i];
00156             }
00157         }
00158     }
00159     return dst;
00160 }
00161 
00162 void Description::print(int n, ostream& fout)
00163 {
00164     list<string>::iterator  s;
00165     list<int>::iterator     t;
00166     
00167     tab(n,fout); fout << "<faust>";
00168         
00169         tab(n+1,fout);  fout << "<name>"        << xmlize(fName)        << "</name>";
00170         tab(n+1,fout);  fout << "<author>"      << xmlize(fAuthor)      << "</author>";
00171         tab(n+1,fout);  fout << "<copyright>"   << xmlize(fCopyright)   << "</copyright>";
00172         tab(n+1,fout);  fout << "<license>"     << xmlize(fLicense)     << "</license>";
00173         tab(n+1,fout);  fout << "<version>"     << xmlize(fVersion)     << "</version>";
00174         tab(n+1,fout);  fout << "<inputs>"      << fInputs              << "</inputs>";
00175         tab(n+1,fout);  fout << "<outputs>"     << fOutputs             << "</outputs>";
00176     
00177         tab(n+1,fout);  fout << "<ui>";
00178 
00179             // active widget list
00180             tab(n+2,fout);  fout << "<activewidgets>";
00181                 tab(n+3,fout);  fout << "<count>" << fActiveWidgetCount << "</count>";
00182                 for (s = fActiveLines.begin(); s != fActiveLines.end(); s++) {
00183                     tab(n+3, fout); fout << *s;
00184                 }
00185             tab(n+2,fout);  fout << "</activewidgets>";
00186 
00187             tab(n+2,fout);
00188             
00189             // passive widget list
00190             tab(n+2,fout);  fout << "<passivewidgets>";
00191                 tab(n+3,fout);  fout << "<count>" << fPassiveWidgetCount << "</count>";
00192                 for (s = fPassiveLines.begin(); s != fPassiveLines.end(); s++) {
00193                     tab(n+3, fout); fout << *s;
00194                 }
00195             tab(n+2,fout);  fout << "</passivewidgets>";
00196     
00197             
00198             tab(n+2,fout);
00199             
00200             // widget layout 
00201             tab(n+2,fout);  fout << "<layout>";
00202                 for (   t = fLayoutTabs.begin(), s = fLayoutLines.begin();
00203                         s != fLayoutLines.end(); t++, s++) {
00204                     tab(n+3+*t, fout); fout << *s;
00205                 }
00206             tab(n+2,fout);  fout << "</layout>";
00207         
00208         tab(n+1,fout);  fout << "</ui>";
00209 
00210 
00211     tab(n,fout); fout << "</faust>" << endl;
00212      
00213 }
00214  
00215 void Description::ui(Tree t)
00216 {
00217     addGroup(0,t);
00218 }
00219 
00220 
00221 void Description::addGroup(int level, Tree t)
00222 {
00223     Tree    label, elements, varname, sig;
00224     const char* groupnames[] = {"vgroup", "hgroup", "tgroup"};
00225     
00226     if (isUiFolder(t, label, elements)) {
00227     
00228         const int       orient = tree2int(left(label));
00229         const char *    str = tree2str(right(label));
00230 
00231         addLayoutLine(level, subst("<group type=\"$0\">", groupnames[orient]));
00232         addLayoutLine(level+1, subst("<label>$0</label>", xmlize(str)));
00233         while (!isNil(elements)) {
00234             addGroup(level+1, right(hd(elements)));
00235             elements = tl(elements);
00236         }       
00237         addLayoutLine(level, "</group>");
00238         
00239     } else if (isUiWidget(t, label, varname, sig)) {
00240             
00241         int w = addWidget(label, varname, sig);
00242         addLayoutLine(level, subst("<widgetref id=\"$0\" />", T(w)));
00243         
00244     } else {
00245         
00246         fprintf(stderr, "error in user interface generation 2\n");
00247         exit(1);
00248         
00249     }
00250 }
00251 
00252 void Description::tab (int n, ostream& fout)
00253 {
00254     fout << '\n';
00255     while (n--) fout << '\t'; 
00256 }
00257     
00258 int Description::addWidget(Tree label, Tree varname, Tree sig)
00259 {
00260     Tree path, c, x, y, z;
00261     
00262     // add an active widget description
00263     
00264     if ( isSigButton(sig, path) )                   {
00265     
00266         fWidgetID++;
00267         fActiveWidgetCount++;
00268         addActiveLine(subst("<widget type=\"button\" id=\"$0\">", T(fWidgetID)));
00269             addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
00270             addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
00271         addActiveLine("</widget>");
00272             
00273     } else if ( isSigCheckbox(sig, path) )          {
00274     
00275         fWidgetID++;
00276         fActiveWidgetCount++;
00277         addActiveLine(subst("<widget type=\"checkbox\" id=\"$0\">", T(fWidgetID)));
00278             addActiveLine(subst("\t<label>$0</label>", xmlize(tree2str(label))));
00279             addActiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
00280         addActiveLine("</widget>");
00281             
00282     } else if ( isSigVSlider(sig, path,c,x,y,z) )   {
00283     
00284         fWidgetID++;
00285         fActiveWidgetCount++;
00286         addActiveLine(subst("<widget type=\"vslider\" id=\"$0\">", T(fWidgetID)));
00287             addActiveLine(subst("\t<label>$0</label>",      xmlize(tree2str(label))));
00288             addActiveLine(subst("\t<varname>$0</varname>",  tree2str(varname)));
00289             addActiveLine(subst("\t<init>$0</init>",        T(tree2double(c))));
00290             addActiveLine(subst("\t<min>$0</min>",          T(tree2double(x))));
00291             addActiveLine(subst("\t<max>$0</max>",          T(tree2double(y))));
00292             addActiveLine(subst("\t<step>$0</step>",        T(tree2double(z))));
00293         addActiveLine("</widget>");
00294             
00295     } else if ( isSigHSlider(sig, path,c,x,y,z) )   {
00296     
00297         fWidgetID++;
00298         fActiveWidgetCount++;
00299         addActiveLine(subst("<widget type=\"hslider\" id=\"$0\">", T(fWidgetID)));
00300             addActiveLine(subst("\t<label>$0</label>",      xmlize(tree2str(label))));
00301             addActiveLine(subst("\t<varname>$0</varname>",  tree2str(varname)));
00302             addActiveLine(subst("\t<init>$0</init>",        T(tree2double(c))));
00303             addActiveLine(subst("\t<min>$0</min>",          T(tree2double(x))));
00304             addActiveLine(subst("\t<max>$0</max>",          T(tree2double(y))));
00305             addActiveLine(subst("\t<step>$0</step>",        T(tree2double(z))));
00306         addActiveLine("</widget>");
00307             
00308     } else if ( isSigNumEntry(sig, path,c,x,y,z) )  {
00309     
00310         fWidgetID++;
00311         fActiveWidgetCount++;
00312         addActiveLine(subst("<widget type=\"nentry\" id=\"$0\">", T(fWidgetID)));
00313             addActiveLine(subst("\t<label>$0</label>",      xmlize(tree2str(label))));
00314             addActiveLine(subst("\t<varname>$0</varname>",  tree2str(varname)));
00315             addActiveLine(subst("\t<init>$0</init>",        T(tree2double(c))));
00316             addActiveLine(subst("\t<min>$0</min>",          T(tree2double(x))));
00317             addActiveLine(subst("\t<max>$0</max>",          T(tree2double(y))));
00318             addActiveLine(subst("\t<step>$0</step>",        T(tree2double(z))));
00319         addActiveLine("</widget>");
00320 
00321             
00322     // add a passive widget description
00323     
00324     } else if ( isSigVBargraph(sig,path,x,y,z) )    {
00325     
00326         fWidgetID++;
00327         fPassiveWidgetCount++;
00328         addPassiveLine(subst("<widget type=\"vbargraph\" id=\"$0\">", T(fWidgetID)));
00329             addPassiveLine(subst("\t<label>$0</label>",     xmlize(tree2str(label))));
00330             addPassiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
00331             addPassiveLine(subst("\t<min>$0</min>",         T(tree2double(x))));
00332             addPassiveLine(subst("\t<max>$0</max>",         T(tree2double(y))));
00333         addPassiveLine("</widget>");
00334         
00335     } else if ( isSigHBargraph(sig,path,x,y,z) )    {
00336     
00337         fWidgetID++;
00338         fPassiveWidgetCount++;
00339         addPassiveLine(subst("<widget type=\"hbargraph\" id=\"$0\">", T(fWidgetID)));
00340             addPassiveLine(subst("\t<label>$0</label>",     xmlize(tree2str(label))));
00341             addPassiveLine(subst("\t<varname>$0</varname>", tree2str(varname)));
00342             addPassiveLine(subst("\t<min>$0</min>",         T(tree2double(x))));
00343             addPassiveLine(subst("\t<max>$0</max>",         T(tree2double(y))));
00344         addPassiveLine("</widget>");
00345         
00346     } else {
00347         fprintf(stderr, "Error describing widget : unrecognized expression\n");
00348         exit(1);
00349     }
00350 
00351     return fWidgetID;
00352 }
00353 
00354 
00355