Back to index

texmacs  1.0.7.15
concat_macro.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : concat_macro.cpp
00004 * DESCRIPTION: Typesetting markup around macro expansion mechanisms
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "concater.hpp"
00013 
00014 /******************************************************************************
00015 * Typesetting environment changes
00016 ******************************************************************************/
00017 
00018 void
00019 concater_rep::typeset_assign (tree t, path ip) {
00020   if (N(t) != 2) { typeset_error (t, ip); return; }
00021   tree r= env->exec (t[0]);
00022   if (!is_atomic (r)) return;
00023   string var= r->label;
00024   env->assign (var, copy (t[1]));
00025   if (env->var_type [var] == Env_Paragraph)
00026     control (tuple ("env_par", var, env->read (var)), ip);
00027   else if (env->var_type [var] == Env_Page)
00028     control (tuple ("env_page", var, env->read (var)), ip);
00029   else control (t, ip);
00030 }
00031 
00032 void
00033 concater_rep::typeset_with (tree t, path ip) {
00034   int i, n= N(t), k= (n-1)>>1; // is k=0 allowed ?
00035   if ((n&1) != 1) { typeset_error (t, ip); return; }
00036 
00037   STACK_NEW_ARRAY(vars,string,k);
00038   STACK_NEW_ARRAY(oldv,tree,k);
00039   STACK_NEW_ARRAY(newv,tree,k);
00040   for (i=0; i<k; i++) {
00041     tree var_t= env->exec (t[i<<1]);
00042     if (is_atomic (var_t)) {
00043       string var= var_t->label;
00044       vars[i]= var;
00045       oldv[i]= env->read (var);
00046       newv[i]= env->exec (t[(i<<1)+1]);
00047     }
00048     else {
00049       STACK_DELETE_ARRAY(vars);
00050       STACK_DELETE_ARRAY(oldv);
00051       STACK_DELETE_ARRAY(newv);
00052       return;
00053     }
00054   }
00055 
00056   marker (descend (ip, 0));
00057   // for (i=0; i<k; i++) env->monitored_write_update (vars[i], newv[i]);
00058   for (i=0; i<k; i++) env->write_update (vars[i], newv[i]);
00059   typeset (t[n-1], descend (ip, n-1));
00060   for (i=k-1; i>=0; i--) env->write_update (vars[i], oldv[i]);
00061   marker (descend (ip, 1));
00062   STACK_DELETE_ARRAY(vars);
00063   STACK_DELETE_ARRAY(oldv);
00064   STACK_DELETE_ARRAY(newv);
00065 }
00066 
00067 void
00068 concater_rep::typeset_compound (tree t, path ip) {
00069   int d; tree f;
00070   if (L(t) == COMPOUND) {
00071     if (N(t) == 0) { typeset_error (t, ip); return; }
00072     d= 1;
00073     f= t[0];
00074     if (is_compound (f)) f= env->exec (f);
00075     if (is_atomic (f)) {
00076       string var= f->label;
00077       if (!env->provides (var)) {
00078        typeset_error (t, ip);
00079        return;
00080       }
00081       f= env->read (var);
00082     }
00083   }
00084   else {
00085     string var= as_string (L(t));
00086     if (!env->provides (var)) {
00087       typeset_error (t, ip);
00088       return;
00089     }
00090     d= 0;
00091     f= env->read (var);
00092   }
00093 
00094   if (is_applicable (f)) {
00095     int i, n=N(f)-1, m=N(t)-d;
00096     env->macro_arg= list<hashmap<string,tree> > (
00097       hashmap<string,tree> (UNINIT), env->macro_arg);
00098     env->macro_src= list<hashmap<string,path> > (
00099       hashmap<string,path> (path (DECORATION)), env->macro_src);
00100     if (L(f) == XMACRO) {
00101       if (is_atomic (f[0])) {
00102        string var= f[0]->label;
00103        env->macro_arg->item (var)= t;
00104        env->macro_src->item (var)= ip;
00105       }
00106     }
00107     else for (i=0; i<n; i++)
00108       if (is_atomic (f[i])) {
00109        string var= f[i]->label;
00110        env->macro_arg->item (var)=
00111          i<m? t[i+d]: attach_dip (tree (UNINIT), decorate_right(ip));
00112        env->macro_src->item (var)= i<m? descend (ip,i+d): decorate_right(ip);
00113       }
00114     if (is_decoration (ip))
00115       typeset (attach_here (f[n], ip));
00116     else {
00117       /*IF_NON_CHILD_ENFORCING(t)*/ marker (descend (ip, 0));
00118       typeset (attach_right (f[n], ip));
00119       /*IF_NON_CHILD_ENFORCING(t)*/ marker (descend (ip, 1));
00120     }
00121     env->macro_arg= env->macro_arg->next;
00122     env->macro_src= env->macro_src->next;
00123   }
00124   else {
00125     if (is_decoration (ip)) typeset (attach_here (f, ip));
00126     else {
00127       /*IF_NON_CHILD_ENFORCING(t)*/ marker (descend (ip, 0));
00128       typeset (attach_right (f, ip));
00129       /*IF_NON_CHILD_ENFORCING(t)*/ marker (descend (ip, 1));
00130     }
00131   }
00132 }
00133 
00134 void
00135 concater_rep::typeset_auto (tree t, path ip, tree f) {
00136   env->macro_arg= list<hashmap<string,tree> > (
00137     hashmap<string,tree> (UNINIT), env->macro_arg);
00138   env->macro_src= list<hashmap<string,path> > (
00139     hashmap<string,path> (path (DECORATION)), env->macro_src);
00140   string var= f[0]->label;
00141   env->macro_arg->item (var)= t;
00142   env->macro_src->item (var)= ip;
00143   typeset (attach_right (f[1], ip));
00144   env->macro_arg= env->macro_arg->next;
00145   env->macro_src= env->macro_src->next;
00146 }
00147 
00148 void
00149 concater_rep::typeset_include (tree t, path ip) {
00150   if (N(t) != 1) { typeset_error (t, ip); return; }
00151   url file_name= as_string (t[0]);
00152   url incl_file= relative (env->base_file_name, file_name);
00153   tree incl= load_inclusion (incl_file);
00154   url save_name= env->cur_file_name;
00155   env->cur_file_name= incl_file;
00156   env->secure= is_secure (env->cur_file_name);
00157   typeset_dynamic (incl, ip);
00158   env->cur_file_name= save_name;
00159   env->secure= is_secure (env->cur_file_name);
00160 }
00161 
00162 void
00163 concater_rep::typeset_drd_props (tree t, path ip) {
00164   (void) env->exec (t);
00165   flag ("drd-properties", ip, brown);
00166   control (t, ip);
00167 }
00168 
00169 void
00170 concater_rep::typeset_eval (tree t, path ip) {
00171   if (N(t) != 1) { typeset_error (t, ip); return; }
00172   tree r= env->exec (t[0]);
00173   typeset_dynamic (r, ip);
00174 }
00175 
00176 void
00177 concater_rep::typeset_value (tree t, path ip) {
00178   // cout << "Value " << t << ", " << ip << "\n";
00179   if (N(t) != 1) { typeset_error (t, ip); return; }
00180   tree r= env->exec (t[0]);
00181   if (is_compound (r)) {
00182     typeset_error (t, ip);
00183     return;
00184   }
00185   string name= r->label;
00186   if (!env->provides (name)) {
00187     typeset_error (t, ip);
00188     return;
00189   }
00190   typeset_dynamic (env->read (name), ip);
00191 }
00192 
00193 void
00194 concater_rep::typeset_argument (tree t, path ip) {
00195   // cout << "Argument " << t << ", " << ip << "\n";
00196   if (N(t) == 0) { typeset_error (t, ip); return; }
00197   tree r= t[0];
00198   if (is_compound (r) ||
00199       is_nil (env->macro_arg) ||
00200       (!env->macro_arg->item->contains (r->label)))
00201     {
00202       typeset_error (t, ip);
00203       return;
00204     }
00205 
00206   string name = r->label;
00207   tree   value= env->macro_arg->item [name];
00208   path   valip= decorate_right (ip);
00209   if (!is_func (value, BACKUP)) {
00210     path new_valip= env->macro_src->item [name];
00211     if (is_accessible (new_valip)) valip= new_valip;
00212   }
00213   // cout << "Src   " << name << "=\t " << valip << "\n";
00214 
00215   marker (descend (ip, 0));
00216   list<hashmap<string,tree> > old_var= env->macro_arg;
00217   list<hashmap<string,path> > old_src= env->macro_src;
00218   if (!is_nil (env->macro_arg)) env->macro_arg= env->macro_arg->next;
00219   if (!is_nil (env->macro_src)) env->macro_src= env->macro_src->next;
00220 
00221   if (N(t) > 1) {
00222     int i, n= N(t);
00223     for (i=1; i<n; i++) {
00224       tree r= env->exec (t[i]);
00225       if (!is_int (r)) {
00226         value= tree (ERROR, "arg " * name);
00227         valip= decorate_right (ip);
00228         break;
00229       }
00230       int nr= as_int (r);
00231       if ((!is_compound (value)) || (nr<0) || (nr>=N(value))) {
00232         value= tree (ERROR, "arg " * name);
00233         valip= decorate_right (ip);
00234         break;
00235       }
00236       value= value[nr];
00237       valip= descend (valip, nr);
00238     }
00239   }
00240   typeset (attach_here (value, valip));
00241 
00242   env->macro_arg= old_var;
00243   env->macro_src= old_src;
00244   marker (descend (ip, 1));
00245 }
00246 
00247 void
00248 concater_rep::typeset_eval_args (tree t, path ip) { 
00249   if (N(t) != 1) { typeset_error (t, ip); return; }
00250   marker (descend (ip, 0));
00251   typeset_inactive (attach_right (env->exec (t), ip));
00252   marker (descend (ip, 1));
00253 }
00254 
00255 void
00256 concater_rep::typeset_mark (tree t, path ip) {
00257   // cout << "Mark: " << t << ", " << ip << "\n\n";
00258   if (N(t) != 2) { typeset_error (t, ip); return; }
00259   if (is_func (t[0], ARG) &&
00260       is_atomic (t[0][0]) &&
00261       (!is_nil (env->macro_arg)) &&
00262       env->macro_arg->item->contains (t[0][0]->label))
00263     {
00264       string name = t[0][0]->label;
00265       tree   value= env->macro_arg->item [name];
00266       path   valip= decorate_right (ip);
00267       if (!is_func (value, BACKUP)) {
00268        path new_valip= env->macro_src->item [name];
00269        if (is_accessible (new_valip)) valip= new_valip;
00270       }
00271       // cout << "Src   " << name << "=\t " << valip << "\n";
00272 
00273       if (N(t[0]) > 1) {
00274        int i, n= N(t[0]);
00275        for (i=1; i<n; i++) {
00276          tree r= env->exec (t[0][i]);
00277          if (!is_int (r)) break;
00278          int nr= as_int (r);
00279          if ((!is_compound (value)) || (nr<0) || (nr>=N(value))) break;
00280          value= value[nr];
00281          valip= descend (valip, nr);
00282        }
00283       }
00284 
00285       marker (descend (valip, 0));
00286       typeset (t[1], descend (ip, 1));
00287       marker (descend (valip, right_index (value)));
00288     }
00289   else typeset (t[1], descend (ip, 1));
00290 }
00291 
00292 void
00293 concater_rep::typeset_expand_as (tree t, path ip) {
00294   // cout << "Mark: " << t << ", " << ip << "\n\n";
00295   if (N(t) != 2) { typeset_error (t, ip); return; }
00296   marker (descend (ip, 0));
00297   typeset (t[1], descend (ip, 1));
00298   marker (descend (ip, 1));
00299 }
00300 
00301 void
00302 concater_rep::typeset_executable (tree t, path ip) {
00303   tree r= env->exec (t);
00304   typeset_dynamic (r, ip);
00305 }
00306 
00307 void
00308 concater_rep::typeset_rewrite (tree t, path ip) {
00309   tree r= env->rewrite (t);
00310   typeset_dynamic (r, ip);
00311 }
00312 
00313 void
00314 concater_rep::typeset_dynamic (tree t, path ip) {
00315   // ATTENTION: in the future, the ip should still be passed to
00316   // this routine, since the typesetting depends on whether ip
00317   // is a decoration or not
00318 
00319   // cout << "Dynamic " << t << ", " << ip << "\n";
00320   if (is_decoration (ip)) {
00321     typeset (attach_here (t, ip));
00322     return;
00323   }
00324 
00325   marker (descend (ip, 0));
00326   // int start= N(a);
00327   typeset (attach_right (t, ip));
00328   // int end= N(a), i;
00329 
00330   /* Old style unaccessible text, using left and middle decorations
00331   SI total= 0, half= 0, mid;
00332   for (i=start; i<end; i++)
00333     total += a[i]->b->w();
00334   for (mid=start; mid<end; mid++) {
00335     half += a[mid]->b->w();
00336     if (half >= (total>>1)) break;
00337   }
00338   for (i=start; i<mid; i++)
00339     a[i]->b->relocate (decorate_left (ip));
00340   if (i<end) {
00341     if (a[i]->b->decoration ())
00342       if ((a[i]->type==STD_ITEM) ||
00343           (a[i]->type == MARKER_ITEM) ||
00344          (a[i]->type==STRING_ITEM))
00345        a[i]->b= macro_box (decorate_right (ip), a[i]->b);
00346     a[i]->b->relocate (decorate_middle (ip));
00347     i++;
00348   }
00349   */
00350 
00351   marker (descend (ip, 1));
00352 
00353   /*
00354   for (i=start-1; i<end+1; i++)
00355     cout << i << ": " << a[i]->b
00356         << ", " << a[i]->b->find_lip ()
00357         << ", " << a[i]->b->find_rip () << "\n";
00358   */
00359 
00360   /*
00361   for (i=start; i<end; i++)
00362     cout << i << ": " << a[i]->b << ", " << a[i]->b->ip << "\n";
00363   */
00364 }
00365 
00366 void
00367 concater_rep::typeset_range (tree t, path ip) {
00368   if (N(t) != 3) { typeset_error (t, ip); return; }
00369   tree t1= env->exec (t[0]);
00370   tree t2= env->exec (t[1]);
00371   tree t3= env->exec (t[2]);
00372   if (!(is_int (t2) && is_int (t3)))
00373     typeset_dynamic (tree (ERROR, "bad range"), ip);
00374   else if (is_compound (t1)) {
00375     if (is_tuple (t1)) {
00376       int i1= max (0, as_int (t2));
00377       int i2= min (N (t1), as_int (t3));
00378       i2 = max (i1, i2);
00379       typeset_dynamic (t1 (i1, i2), ip);
00380     }
00381     else typeset_dynamic (tree (ERROR, "bad range"), ip);
00382   }
00383   else {
00384     int i1= max (0, as_int (t2));
00385     int i2= min (N(t1->label), as_int (t3));
00386     i2 = max (i1, i2);
00387     path ip1= obtain_ip (t1);
00388     if (is_decoration (ip1))
00389       typeset_dynamic (t1->label (i1, i2), ip);
00390     else {
00391       marker (descend (ip, 0));
00392       if (env->mode == 1)
00393         typeset_text_string (t1->label, ip1, i1, i2);
00394       else if (env->mode == 2)
00395         typeset_math_string (t1->label, ip1, i1, i2);
00396       else if (env->mode == 3)
00397         typeset_prog_string (t1       , ip1, i1, i2);
00398       else
00399         typeset_text_string (t1->label, ip1, i1, i2);
00400       marker (descend (ip, 1));
00401     }
00402   }
00403 }