home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / VSLBuiltin.C < prev    next >
C/C++ Source or Header  |  1998-11-26  |  16KB  |  792 lines

  1. // $Id: VSLBuiltin.C,v 1.19 1998/11/26 09:35:02 zeller Exp $
  2. // Predefined VSL functions
  3.  
  4. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char VSLBuiltin_rcsid[] = 
  30.     "$Id: VSLBuiltin.C,v 1.19 1998/11/26 09:35:02 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "VSLBuiltin.h"
  37.  
  38. #include "assert.h"
  39.  
  40. #include <limits.h>
  41. #include <math.h>
  42. #include <iostream.h>
  43.  
  44. #include "bool.h"
  45. #include "VSLLib.h"
  46.  
  47. // Zillions of boxes...
  48. #include "AlignBox.h"
  49. #include "ArcBox.h"
  50. #include "BinBox.h"
  51. #include "ColorBox.h"
  52. #include "DiagBox.h"
  53. #include "FixBox.h"
  54. #include "FontFixBox.h"
  55. #include "PrimitiveB.h"
  56. #include "SlopeBox.h"
  57. #include "StringBox.h"
  58. #include "TrueBox.h"
  59. #include "DummyBox.h"
  60.  
  61.  
  62. // Type checks
  63.  
  64. #ifndef NDEBUG
  65. // True iff all args are atoms
  66. static bool checkAtoms(ListBox *args)
  67. {
  68.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  69.     {
  70.     Box *box = b->head();
  71.     if (box->isListBox() && !box->isDummyBox())
  72.     {
  73.         VSLLib::eval_error("invalid argument -- argument is list");
  74.         return false;
  75.     }
  76.     }
  77.  
  78.     return true;
  79. }
  80. #define CHECK_ATOMS(args) { if (!checkAtoms(args)) return 0; }
  81. #else
  82. #define CHECK_ATOMS(args)
  83. #endif
  84.  
  85.  
  86. // True iff all args have some size
  87. static bool checkSize(ListBox *args)
  88. {
  89.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  90.     {
  91.     Box *box = b->head();
  92.     if (!box->size().isValid())
  93.         return false;
  94.     }
  95.  
  96.     return true;
  97. }
  98.  
  99. #define CHECK_SIZE(args) { if (!checkSize(args)) return new DummyBox; }
  100.  
  101.  
  102. // Predefined VSL functions
  103.  
  104. // Logical ops
  105.  
  106. // Logical `not'
  107. static Box *op_not(ListBox *args)
  108. {
  109.     CHECK_ATOMS(args);
  110.     CHECK_SIZE(args);
  111.  
  112.     if ((*args)[0]->size(X) == 0)
  113.     return new TrueBox;
  114.  
  115.     return new FalseBox;
  116. }
  117.  
  118.  
  119. // Graphical ops
  120.  
  121. // Normalize alignment
  122. static Box *normalize(AlignBox *box)
  123. {
  124.     // Replace (&)(A) by A
  125.     if (box->nchildren() == 1)
  126.     {
  127.     // Replace by single child
  128.         Box *new_box = (*box)[0]->link();
  129.     box->unlink();
  130.     return new_box;
  131.     }
  132.  
  133.     // Replace (&)(A, (&)(B, C)) by (&)(A, B, C)
  134.     bool need_assoc_restructuring = false;
  135.  
  136.     for (int i = 0; i < box->nchildren(); i++)
  137.     {
  138.     Box *child = (*box)[i];
  139.     if (ptr_type_info(box) == ptr_type_info(child))
  140.     {
  141.         need_assoc_restructuring = true;
  142.         break;
  143.     }
  144.     }
  145.  
  146.     if (need_assoc_restructuring)
  147.     {
  148.     // Replace this box by NEW_ALIGN
  149.     Box *new_box = box->dup0();
  150.     AlignBox *new_align = ptr_cast(AlignBox, new_box);
  151.     assert(new_align != 0);
  152.  
  153.     for (int i = 0; i < box->nchildren(); i++)
  154.     {
  155.         Box *child = (*box)[i];
  156.         if (ptr_type_info(box) == ptr_type_info(child))
  157.         {
  158.         AlignBox *a = ptr_cast(AlignBox, child);
  159.         assert(a != 0);
  160.         for (int j = 0; j < a->nchildren(); j++)
  161.             *new_align += (*a)[j];
  162.         }
  163.         else
  164.         *new_align += child;
  165.     }
  166.  
  167.     box->unlink();
  168.     return new_align;
  169.     }
  170.  
  171.     return box;
  172. }
  173.  
  174. // Horizontal alignment
  175. static Box *op_halign(ListBox *args)
  176. {
  177.     CHECK_ATOMS(args);
  178.  
  179.     HAlignBox *ret = 0;     // Return value
  180.  
  181.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  182.     {
  183.     Box *box = b->head();
  184.     if (ret == 0)
  185.         ret = new HAlignBox;
  186.     *ret &= box;
  187.     }
  188.  
  189.     // No child?  Return null box.
  190.     if (ret == 0)
  191.     return new NullBox;
  192.  
  193.     // One child?  Return it.
  194.     if (ret->nchildren() == 1)
  195.     {
  196.     Box *child = (*ret)[0]->link();
  197.     ret->unlink();
  198.     return child;
  199.     }
  200.  
  201.     // Return normalized alignment
  202.     return normalize(ret);
  203. }
  204.  
  205. // Textual alignment
  206. static Box *op_talign(ListBox *args)
  207. {
  208.     CHECK_ATOMS(args);
  209.  
  210.     TAlignBox *ret = 0;     // Return value
  211.  
  212.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  213.     {
  214.     Box *box = b->head();
  215.     if (ret == 0)
  216.         ret = new TAlignBox;
  217.     *ret &= box;
  218.     }
  219.  
  220.     // No child?  Return null box.
  221.     if (ret == 0)
  222.     return new NullBox;
  223.  
  224.     // One child?  Return it.
  225.     if (ret->nchildren() == 1)
  226.     {
  227.     Box *child = (*ret)[0]->link();
  228.     ret->unlink();
  229.     return child;
  230.     }
  231.  
  232.     // Return normalized alignment
  233.     return normalize(ret);
  234. }
  235.  
  236. // Vertical alignment
  237. static Box *op_valign(ListBox *args)
  238. {
  239.     CHECK_ATOMS(args);
  240.  
  241.     VAlignBox *ret = 0;
  242.  
  243.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  244.     {
  245.     Box *box = b->head();
  246.     if (ret == 0)
  247.         ret = new VAlignBox;
  248.     *ret |= box;
  249.     }
  250.  
  251.     // No child?  Return null box.
  252.     if (ret == 0)
  253.     return new NullBox;
  254.  
  255.     // One child?  Return it.
  256.     if (ret->nchildren() == 1)
  257.     {
  258.     Box *child = (*ret)[0]->link();
  259.     ret->unlink();
  260.     return child;
  261.     }
  262.  
  263.     // Return normalized alignment
  264.     return normalize(ret);
  265. }
  266.  
  267. // Stacked alignment
  268. static Box *op_ualign(ListBox *args)
  269. {
  270.     CHECK_ATOMS(args);
  271.  
  272.     UAlignBox *ret = 0;
  273.  
  274.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  275.     {
  276.     Box *box = b->head();
  277.     if (ret == 0)
  278.         ret = new UAlignBox;
  279.     *ret ^= box;
  280.     }
  281.  
  282.     // No child?  Return null box.
  283.     if (ret == 0)
  284.     return new NullBox;
  285.  
  286.     // One child?  Return it.
  287.     if (ret->nchildren() == 1)
  288.     {
  289.     Box *child = (*ret)[0]->link();
  290.     ret->unlink();
  291.     return child;
  292.     }
  293.  
  294.     // Return normalized alignment
  295.     return normalize(ret);
  296. }
  297.  
  298.  
  299.  
  300. // Arithmetic ops
  301.  
  302. // Addition
  303. static Box *op_plus(ListBox *args)
  304. {
  305.     CHECK_ATOMS(args);
  306.     CHECK_SIZE(args);
  307.  
  308.     BoxSize sum(0,0);
  309.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  310.     {
  311.     Box *box = b->head();
  312.     sum += box->size();
  313.     }
  314.  
  315.     return new SpaceBox(sum);
  316. }
  317.  
  318. // Multiplication
  319. static Box *op_mult(ListBox *args)
  320. {
  321.     CHECK_ATOMS(args);
  322.     CHECK_SIZE(args);
  323.  
  324.     BoxSize product(1,1);
  325.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  326.     {
  327.     Box *box = b->head();
  328.     product *= box->size();
  329.     }
  330.  
  331.     return new SpaceBox(product);
  332. }
  333.  
  334. // Subtraction
  335. static Box *op_minus(ListBox *args)
  336. {
  337.     CHECK_ATOMS(args);
  338.     CHECK_SIZE(args);
  339.  
  340.     return new SpaceBox(
  341.     (*args)[0]->size() - (*args)[1]->size());
  342. }
  343.  
  344. // (Integer) division
  345. static Box *op_div(ListBox *args)
  346. {
  347.     CHECK_ATOMS(args);
  348.     CHECK_SIZE(args);
  349.  
  350.     if ((*args)[1]->size(X) == 0 || (*args)[1]->size(Y) == 0)
  351.     {
  352.     VSLLib::eval_error("division by zero");
  353.     return 0;
  354.     }
  355.  
  356.     return new SpaceBox(
  357.     (*args)[0]->size() / (*args)[1]->size());
  358. }
  359.  
  360. // Remainder
  361. static Box *op_mod(ListBox *args)
  362. {
  363.     CHECK_ATOMS(args);
  364.     CHECK_SIZE(args);
  365.  
  366.     if ((*args)[1]->size(X) == 0 || (*args)[1]->size(Y) == 0)
  367.     {
  368.     VSLLib::eval_error("division by zero");
  369.     return 0;
  370.     }
  371.  
  372.     return new SpaceBox(
  373.     (*args)[0]->size() % (*args)[1]->size());
  374. }
  375.  
  376.  
  377.  
  378. // Comparison
  379.  
  380. // Equality
  381. static Box *op_eq(ListBox *args)
  382. {
  383.     if (*(*args)[0] == *(*args)[1])
  384.     return new TrueBox;
  385.     else
  386.     return new FalseBox;
  387. }
  388.  
  389. // Inequality
  390. static Box *op_ne(ListBox *args)
  391. {
  392.     if (*(*args)[0] != *(*args)[1])
  393.     return new TrueBox;
  394.     else
  395.     return new FalseBox;
  396. }
  397.  
  398. // Greater than
  399. static Box *op_gt(ListBox *args)
  400. {
  401.     CHECK_ATOMS(args);
  402.     CHECK_SIZE(args);
  403.  
  404.     if ((*args)[0]->size() > (*args)[1]->size())
  405.     return new TrueBox;
  406.     else
  407.     return new FalseBox;
  408. }
  409.  
  410. // Greater or equal
  411. static Box *op_ge(ListBox *args)
  412. {
  413.     CHECK_ATOMS(args);
  414.     CHECK_SIZE(args);
  415.  
  416.     if ((*args)[0]->size() >= (*args)[1]->size())
  417.     return new TrueBox;
  418.     else
  419.     return new FalseBox;
  420. }
  421.  
  422. // Less than
  423. static Box *op_lt(ListBox *args)
  424. {
  425.     CHECK_ATOMS(args);
  426.     CHECK_SIZE(args);
  427.  
  428.     if ((*args)[0]->size() < (*args)[1]->size())
  429.     return new TrueBox;
  430.     else
  431.     return new FalseBox;
  432. }
  433.  
  434. // Less or equal
  435. static Box *op_le(ListBox *args)
  436. {
  437.     CHECK_ATOMS(args);
  438.     CHECK_SIZE(args);
  439.  
  440.     if ((*args)[0]->size() <= (*args)[1]->size())
  441.     return new TrueBox;
  442.     else
  443.     return new FalseBox;
  444. }
  445.  
  446.  
  447. // List ops
  448.  
  449. // Cons lists
  450. static Box *op_cons(ListBox *args)
  451. {
  452.     ListBox *ret = 0;
  453.  
  454.     for (ListBox *b = args; !b->isEmpty(); b = b->tail())
  455.     {
  456.     Box *box = b->head();
  457.  
  458.     if (!box->isListBox())
  459.     {
  460.         VSLLib::eval_error("invalid argument -- argument is list");
  461.         if (ret)
  462.         ret->unlink();
  463.         return 0;
  464.     }
  465.  
  466.     if (!((ListBox *)box)->isEmpty())
  467.     {
  468.         // Create list to append
  469.         // If box is last arg, a link suffices
  470.         ListBox *box2;
  471.         if (b->tail()->isEmpty())
  472.         box2 = (ListBox *)box->link();
  473.         else
  474.         box2 = (ListBox *)box->dup();
  475.  
  476.         // Append list: 
  477.         // If box is first arg, copy box
  478.         if (ret == 0)
  479.         ret = box2;
  480.         else
  481.         {
  482.         ret->cons(box2);
  483.         box2->unlink();
  484.         }
  485.     }
  486.     }
  487.  
  488.     // No args? return []
  489.     if (ret == 0)
  490.     ret = new ListBox;
  491.  
  492.     return ret;
  493. }
  494.  
  495.  
  496. // Standard functions
  497.  
  498. // hspace(box)
  499. static Box *hspace(ListBox *args)
  500. {
  501.     CHECK_ATOMS(args);
  502.     CHECK_SIZE(args);
  503.  
  504.     const Box *child = (*args)[0];
  505.     return new SpaceBox(BoxSize(child->size(X), 0));
  506. }
  507.  
  508. // vspace(box)
  509. static Box *vspace(ListBox *args)
  510. {
  511.     CHECK_ATOMS(args);
  512.     CHECK_SIZE(args);
  513.  
  514.     const Box *child = (*args)[0];
  515.     return new SpaceBox(BoxSize(0, child->size(Y)));
  516. }
  517.  
  518. // hfix(box)
  519. static Box *hfix(ListBox *args)
  520. {
  521.     CHECK_ATOMS(args);
  522.  
  523.     return new HFixBox((Box *)(*args)[0]);
  524. }
  525.  
  526. // vfix(box)
  527. static Box *vfix(ListBox *args)
  528. {
  529.     CHECK_ATOMS(args);
  530.  
  531.     return new VFixBox((Box *)(*args)[0]);
  532. }
  533.  
  534. // bin(box)
  535. static Box *op_bin(ListBox *args)
  536. {
  537.     CHECK_ATOMS(args);
  538.  
  539.     return new BinBox((Box *)(*args)[0]);
  540. }
  541.  
  542. // tag(box)
  543. static Box *tag(ListBox *args)
  544. {
  545.     return new StringBox((*args)[0]->name());
  546. }
  547.  
  548.  
  549. // Return string from box
  550.  
  551. // str(box)
  552. static Box *str(ListBox *args)
  553. {
  554.     return new StringBox((*args)[0]->str());
  555. }
  556.  
  557.  
  558. // Set font
  559.  
  560. // font(box, font)
  561. static Box *font(ListBox *args)
  562. {
  563.     // Copy first arg and set its font
  564.  
  565.     Box *ret = ((Box *)(*args)[0])->dup();
  566.     ret->newFont((*args)[1]->str());
  567.  
  568.     return ret;
  569. }
  570.  
  571. // fontfix(box)
  572. static Box *fontfix(ListBox *args)
  573. {
  574.     return new FontFixBox((Box *)(*args)[0]);
  575. }
  576.  
  577.  
  578. // Set color
  579.  
  580. // background(box, color_name)
  581. static Box *background(ListBox *args)
  582. {
  583.     return new BackgroundColorBox((Box *)(*args)[0], (*args)[1]->str());
  584. }
  585.  
  586. // foreground(box, color_name)
  587. static Box *foreground(ListBox *args)
  588. {
  589.     return new ForegroundColorBox((Box *)(*args)[0], (*args)[1]->str());
  590. }
  591.  
  592.  
  593. // Standard boxes
  594.  
  595. // rise(linethickness)
  596. static Box *rise(ListBox *args)
  597. {
  598.     CHECK_ATOMS(args);
  599.     CHECK_SIZE(args);
  600.  
  601.     return new RiseBox((*args)[0]->size(X));
  602. }
  603.  
  604. // fall(linethickness)
  605. static Box *fall(ListBox *args)
  606. {
  607.     CHECK_ATOMS(args);
  608.     CHECK_SIZE(args);
  609.  
  610.     return new FallBox((*args)[0]->size(X));
  611. }
  612.  
  613. // arc(start, length, linethickness)
  614. static Box *arc(ListBox *args)
  615. {
  616.     CHECK_ATOMS(args);
  617.     CHECK_SIZE(args);
  618.  
  619.     return new ArcBox((*args)[0]->size(X),
  620.     (*args)[1]->size(X),
  621.     (*args)[2]->size(X));
  622. }
  623.  
  624. // Square box from maximal height and width
  625. static Box *square(ListBox *args)
  626. {
  627.     CHECK_ATOMS(args);
  628.     CHECK_SIZE(args);
  629.  
  630.     Box *arg = (Box *)(*args)[0];
  631.     return new SquareBox(max(arg->size(X), arg->size(Y)));
  632. }
  633.  
  634. // fill()
  635. static Box *fill(ListBox *)
  636. {
  637.     return new FillBox;
  638. }
  639.  
  640. // rule()
  641. static Box *rule(ListBox *)
  642. {
  643.     return new RuleBox;
  644. }
  645.  
  646. // diag()
  647. static Box *diag(ListBox *)
  648. {
  649.     return new DiagBox;
  650. }
  651.  
  652.  
  653. // Default boxes
  654.  
  655. // Place holder for an undefined box
  656. static Box *undef(ListBox *)
  657. {
  658.     return new StringBox("???");
  659. }
  660.  
  661.  
  662. // Error handling
  663.  
  664. // Make evaluation fail; issue error message
  665. static Box *fail(ListBox *args)
  666. {
  667.     CHECK_ATOMS(args);
  668.  
  669.     if ((*args)[0])
  670.     VSLLib::eval_error((*args)[0]->str());
  671.     else
  672.     VSLLib::eval_error("evaluation failed");
  673.  
  674.     return 0;
  675. }
  676.  
  677.  
  678. // Table of predefined functions
  679.  
  680. struct BuiltinRec {
  681.     char* ext_name;         // Function name (external; 0 = func_name)
  682.     char* func_name;        // Function name (internal)
  683.     bool isAssoc;           // Flag: associative?
  684.     bool hasSideEffects;    // Flag: side effects?
  685.     bool isInfix;           // Flag: dump infix?
  686.     BuiltinFunc eval_func;  // Function to be called
  687.  
  688. };
  689.  
  690. static BuiltinRec builtins[] = {
  691.  
  692. // n-ary ops
  693. { "(&)",    "__op_halign",  true,   false,  false,  op_halign },
  694. { "(|)",    "__op_valign",  true,   false,  false,  op_valign },
  695. { "(^)",    "__op_ualign",  true,   false,  false,  op_ualign },
  696. { "(~)",    "__op_talign",  true,   false,  false,  op_talign },
  697. { "(+)",    "__op_plus",    true,   false,  false,  op_plus },
  698. { "(*)",    "__op_mult",    true,   false,  false,  op_mult },
  699. { "(::)",   "__op_cons",    true,   false,  false,  op_cons },
  700.  
  701. // binary ops
  702. { "(-)",    "__op_minus",   false,  false,  false,  op_minus },
  703. { "(/)",    "__op_div",     false,  false,  false,  op_div },
  704. { "(%)",    "__op_mod",     false,  false,  false,  op_mod },
  705. { "(=)",    "__op_eq",      false,  false,  false,  op_eq },
  706. { "(<>)",   "__op_ne",      false,  false,  false,  op_ne },
  707. { "(>)",    "__op_gt",      false,  false,  false,  op_gt },
  708. { "(>=)",   "__op_ge",      false,  false,  false,  op_ge },
  709. { "(<)",    "__op_lt",      false,  false,  false,  op_lt },
  710. { "(<=)",   "__op_le",      false,  false,  false,  op_le },
  711. { 0,        "__op_bin",     false,  false,  false,  op_bin },
  712.  
  713. // unary ops
  714. { "not",    "__op_not",     false,  false,  false,  op_not },
  715.  
  716. // functions
  717. { 0,    "__hspace",     false,  false,  false,  hspace },
  718. { 0,    "__vspace",     false,  false,  false,  vspace },
  719. { 0,    "__hfix",       false,  false,  false,  hfix },
  720. { 0,    "__vfix",       false,  false,  false,  vfix },
  721. { 0,    "__rise",       false,  false,  false,  rise },
  722. { 0,    "__fall",       false,  false,  false,  fall },
  723. { 0,    "__arc",        false,  false,  false,  arc },
  724. { 0,    "__square",     false,  false,  false,  square },
  725. { 0,    "__tag",        false,  false,  false,  tag },
  726. { 0,    "__string",     false,  false,  false,  str },
  727. { 0,    "__font",       false,  false,  false,  font },
  728. { 0,    "__fontfix",    false,  false,  false,  fontfix },
  729. { 0,    "__background", false,  false,  false,  background },
  730. { 0,    "__foreground", false,  false,  false,  foreground },
  731.  
  732. // functions with side effects
  733. { 0,    "__fail",       false,  true,   false,  fail },
  734.  
  735. // constants
  736. { 0,    "__fill",       false,  false,  false,  fill },
  737. { 0,    "__rule",       false,  false,  false,  rule },
  738. { 0,    "__diag",       false,  false,  false,  diag },
  739. { 0,    "__undef",      false,  false,  false,  undef },
  740.  
  741. };
  742.  
  743.  
  744. // Access functions
  745.  
  746. // Return function name index for FUNC_NM; or -1 if not found
  747. int VSLBuiltin::resolve(const string& func_nm)
  748. {
  749.     for (int i = 0; i < int(sizeof(builtins) / sizeof(builtins[0])); i++)
  750.     if (func_nm == builtins[i].func_name)
  751.         return i;
  752.  
  753.     return -1;            // not found
  754. }
  755.  
  756. BuiltinFunc VSLBuiltin::func(int idx)
  757. {
  758.     assert (idx >= 0 && idx < int(sizeof(builtins) / sizeof(builtins[0])));
  759.     return builtins[idx].eval_func;
  760. }
  761.  
  762. bool VSLBuiltin::isAssoc(int idx)
  763. {
  764.     assert (idx >= 0 && idx < int(sizeof(builtins) / sizeof(builtins[0])));
  765.     return builtins[idx].isAssoc;
  766. }
  767.  
  768. bool VSLBuiltin::hasSideEffects(int idx)
  769. {
  770.     assert (idx >= 0 && idx < int(sizeof(builtins) / sizeof(builtins[0])));
  771.     return builtins[idx].hasSideEffects;
  772. }
  773.  
  774. bool VSLBuiltin::isInfix(int idx)
  775. {
  776.     assert (idx >= 0 && idx < int(sizeof(builtins) / sizeof(builtins[0])));
  777.     return builtins[idx].isInfix;
  778. }
  779.  
  780. char *VSLBuiltin::func_name(int idx)
  781. {
  782.     assert (idx >= 0 && idx < int(sizeof(builtins) / sizeof(builtins[0])));
  783.     return builtins[idx].func_name;
  784. }
  785.  
  786. char *VSLBuiltin::ext_name(int idx)
  787. {
  788.     assert (idx >= 0 && idx < int(sizeof(builtins) / sizeof(builtins[0])));
  789.     char *s = builtins[idx].ext_name;
  790.     return s != 0 ? s : builtins[idx].func_name;
  791. }
  792.