home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / gnu / gdb / bug / 891 < prev    next >
Encoding:
Text File  |  1992-07-25  |  18.5 KB  |  761 lines

  1. Newsgroups: gnu.gdb.bug
  2. Path: sparky!uunet!cis.ohio-state.edu!foxtrot.ccmrc.ucsb.edu!doug
  3. From: doug@foxtrot.ccmrc.ucsb.edu (Douglas Scott)
  4. Subject: Gdb 4.6 bug report
  5. Message-ID: <9207222351.AA18283@foxtrot.ccmrc.ucsb.edu>
  6. Sender: gnulists@ai.mit.edu
  7. Organization: GNUs Not Usenet
  8. Distribution: gnu
  9. Date: Wed, 22 Jul 1992 23:51:03 GMT
  10. Approved: bug-gdb@prep.ai.mit.edu
  11. Lines: 748
  12.  
  13. System:  Sun 4/330 Running SunOS 4.1
  14. Compiler: gcc/g++ 2.2.2
  15. Gdb version: 4.6, compiled with GCC_MANGLE_BUG flag
  16. Problems:
  17. 1)  Gdb will not print value returned from overloaded operator [](int), claiming  
  18. structure has no such component (see log).
  19.  
  20. 2)  Gdb dumps core when attempting to print return value of a virtual function called  
  21. from a reference to an object (see log).
  22.  
  23. Here is a log of two problems, followed by the code.  I
  24. apologize for the length of the code, but it is an extract
  25. from a 14,000 line program, and I couldnt take the time to
  26. strip any more out of it.  If it is too long for you to deal
  27. with, let me know, and I will try to extract the problem
  28. part out. 
  29.  
  30.  
  31. ---
  32. Douglas Scott                              (805)893-8352
  33. Center for Computer Music Research and Composition
  34. University of California, Santa Barbara
  35. Internet: (NeXTMail ok)   <doug@foxtrot.ccmrc.ucsb.edu>
  36.  
  37. ######################################################
  38. (gdb) run
  39. Starting program: /home/doug/C++/a.out 
  40.  
  41.  
  42. Breakpoint 2, Request::retrieveValues (this=0xf7fffbb8, v=@0xf7fffb78)
  43.     at testit.c:520
  44. 520                             v[valsReturned] = *(valueList->value());
  45. (gdb) ptype v
  46. type = class ValueArray {
  47.   private:
  48.     void *array;
  49.     int length_;
  50.     int offset;
  51.  
  52.   public:
  53.     ValueArray(QueryValue *, int);
  54.     struct QueryValue & operator[](int) const;
  55.     int length(void) const;
  56. } &
  57. (gdb) print v[valsReturned]
  58. Structure has no component named operator[].
  59.  
  60. ######################################################
  61. gdb a.out
  62. GDB is free software and you are welcome to distribute copies of it
  63.  under certain conditions; type "show copying" to see the conditions.
  64. There is absolutely no warranty for GDB; type "show warranty" for details.
  65. GDB 4.6, Copyright 1992 Free Software Foundation, Inc...
  66. (gdb) break 291
  67. Breakpoint 1 at 0x2a48: file testit.c, line 291.
  68. (gdb) run
  69. Starting program: /home/doug/C++/a.out 
  70.  
  71.  
  72. Breakpoint 1, QueryValue::operator= (this=0xf7fffb88, rhs=@0x36040)
  73.     at testit.c:291
  74. 291             set(rhs.value());
  75. Warning: the current language does not match this frame.
  76. (gdb) print rhs
  77. $1 = (struct QueryValue &) @0x36040: {
  78.     <QueryLabel> = {
  79.       label_ = 0x36060, 
  80.  
  81.       _vptr$QueryLabel = 0x32340 <IntValue virtual table>
  82.     }, 
  83.  
  84.     members of QueryValue: 
  85.  
  86.     checkFun = 0x3d64 <posNumsOnly(char)>, 
  87.  
  88.     legalValue = 0x3e24 <checkDouble(char *)>
  89.   }
  90. (gdb) ptype rhs
  91. type = class QueryValue : public QueryLabel {
  92.   protected:
  93.     int (*checkFun)();
  94.     int (*legalValue)();
  95.  
  96.   public:
  97.     virtual ~QueryValue(void);
  98.     QueryValue(const char *, int (*)(char), int (*)(const char *));
  99.   protected:
  100.     QueryValue(void);
  101.   public:
  102.     virtual char * value(void) const;
  103.     virtual int intValue(void) const;
  104.     virtual double doubleValue(void) const;
  105.     virtual int set(const char *);
  106.     int (*)() charCheckFunction(void);
  107.   protected:
  108.     void operator=(const QueryValue &);
  109.   private:
  110.     virtual int size(void);
  111. } &
  112. (gdb) print rhs.value()
  113. Segmentation fault (core dumped)
  114.  
  115. tango> gdb ./gdb ~doug/C++/core
  116. GDB is free software and you are welcome to distribute copies of it
  117.  under certain conditions; type "show copying" to see the conditions.
  118. There is absolutely no warranty for GDB; type "show warranty" for details.
  119. GDB 4.6, Copyright 1992 Free Software Foundation, Inc...
  120. Core was generated by `gdb'.
  121. Program terminated with signal 11, Segmentation fault.
  122. #0  0x13f88 in unpack_field_as_long (type=0x136518, valaddr=0xf4630 "", 
  123.  
  124.     fieldno=-16) at values.c:1222
  125. 1222      memcpy (&val, valaddr + bitpos / 8, sizeof (val));
  126. Setting up the environment for debugging gdb.
  127. Breakpoint 1 at 0x33bd4: file utils.c, line 274.
  128. Breakpoint 2 at 0x4774: file main.c, line 1658.
  129. (top-gdb) bt
  130. #0  0x13f88 in unpack_field_as_long (type=0x136518, valaddr=0xf4630 "", 
  131.  
  132.     fieldno=-16) at values.c:1222
  133. #1  0x137d8 in value_primitive_field (arg1=0xf4608, offset=170831022, 
  134.  
  135.     fieldno=-1, arg_type=0x136518) at values.c:863
  136. #2  0x138a8 in value_field (arg1=0xf4608, fieldno=-1) at values.c:898
  137. #3  0x13a04 in value_virtual_fn_field (arg1=0xf4608, f=0x136740, j=1271064, 
  138.  
  139.     type=0x136518) at values.c:971
  140. #4  0x181d8 in search_struct_method (name=0xf44b0 "value", arg1=0xf4608, 
  141.  
  142.     args=0xf7fff6f4, offset=0, static_memfuncp=0xf7fff768, type=0x136518)
  143.     at valops.c:1095
  144. #5  0x18690 in value_struct_elt (argp=0xf7fff76c, args=0xf7fff6f4, 
  145.  
  146.     name=0xf44b0 "value", static_memfuncp=0xf7fff768, err=0x14928 "structure")
  147.     at valops.c:1222
  148. #6  0x15224 in evaluate_subexp (expect_type=0x0, exp=0xf4488, pos=0xf7fff7e4, 
  149.  
  150.     noside=EVAL_NORMAL) at eval.c:385
  151. #7  0x148b4 in evaluate_expression (exp=0xf4488) at eval.c:142
  152. #8  0x1fec4 in print_command_1 (exp=0xe600e "rhs.value()", inspect=0, 
  153.  
  154.     voidprint=1) at printcmd.c:752
  155. #9  0x20020 in print_command (exp=0xe600e "rhs.value()", from_tty=1)
  156.     at printcmd.c:803
  157. #10 0x3930 in execute_command (p=0xe600e "rhs.value()", from_tty=1)
  158.     at main.c:915
  159. #11 0x3ae4 in command_loop () at main.c:976
  160. #12 0x3734 in main (argc=2, argv=0xf7fffc54) at main.c:853
  161.  
  162.  
  163. ////////////////////////// source for gdb test //////////////////////////
  164. #include <String.h>
  165.  
  166. typedef int (*CharCheckFun)(const char);
  167. typedef int (*LegalValueFun)(const char *);
  168.  
  169. enum Response {
  170.         Cancel = 0, Yes = 1, No = 2
  171. };
  172.  
  173. class String;
  174.  
  175. struct QueryLabelInfo {
  176.     char *label;
  177. };
  178.  
  179. struct QueryButtonInfo {
  180.     char *label;        // label for button
  181.     Response response;    // behavior for this button (yes, no, cancel)
  182. };
  183.  
  184. enum ValueType { None, VString, VInt, VDouble };
  185.  
  186. struct QueryValueInfo {
  187.     ValueType type;
  188.     char *label;
  189.     char *defaultVal;
  190.     CharCheckFun check;
  191.     LegalValueFun legal;
  192. };
  193.  
  194. struct QueryInfo {
  195.     QueryLabelInfo *labelInfo;
  196.     char *valueListLabel;
  197.     QueryValueInfo *valueInfo;
  198.     QueryButtonInfo *buttonInfo;
  199. };
  200.  
  201. // base class for all query items, and also used for plain labels
  202.  
  203. class QueryLabel {
  204. public:
  205.     QueryLabel(const char *);
  206.     virtual ~QueryLabel();
  207.     const char* label();
  208. private:
  209.     String *label_;
  210. };
  211.  
  212. // class for response buttons (confirm, cancel, etc.)
  213.  
  214. class QueryButton : public QueryLabel {
  215. public:
  216.     QueryButton(const char *, Response resp=Yes);
  217.     virtual ~QueryButton();
  218.     virtual Response response() { return response_; }
  219.     virtual int set(Response r) { response_ = r; return 1; }
  220. private:
  221.     Response response_;
  222. };
  223.  
  224. class ValueArray;
  225.  
  226. // class for querying string, int, or double values
  227.  
  228. class QueryValue : public QueryLabel {
  229. public:
  230.     QueryValue(const char *, CharCheckFun ccf, LegalValueFun lvf);
  231.     virtual ~QueryValue();
  232.     virtual const char* value() const = 0;
  233.     virtual const int intValue()  const = 0;
  234.     virtual const double doubleValue() const = 0;
  235.     virtual int set(const char *) = 0;
  236.     CharCheckFun charCheckFunction() { return checkFun; }
  237.     void operator = (const QueryValue& rhs);
  238. protected:
  239.     QueryValue();
  240.     CharCheckFun checkFun;
  241.     LegalValueFun legalValue;
  242. private:
  243.     friend ValueArray;
  244.     virtual int size() { return sizeof(*this); }
  245. };
  246.  
  247. class StringValue : public QueryValue {
  248. public:
  249.     StringValue(const char *, const char *, CharCheckFun ccf, LegalValueFun lvf);
  250.     StringValue(const char *value=0);
  251.     virtual ~StringValue();
  252.     virtual const char* value() const;
  253.     virtual const int intValue() const;
  254.     virtual const double doubleValue() const;
  255.     virtual int set(const char *);
  256. private:
  257.     friend ValueArray;
  258.     virtual int size() { return sizeof(*this); }
  259.     String *string;
  260. };
  261.  
  262. class IntValue : public QueryValue {
  263. public:
  264.     IntValue(const char *, const int, CharCheckFun ccf, LegalValueFun lvf);
  265.     IntValue(int value=0);
  266.     virtual ~IntValue();
  267.     virtual const char* value() const;
  268.     virtual const int intValue() const;
  269.     virtual const double doubleValue() const;
  270.     virtual int set(const char *);
  271. private:
  272.     friend ValueArray;
  273.     virtual int size() { return sizeof(*this); }
  274.     int value_;
  275. };
  276.  
  277. class DoubleValue : public QueryValue {
  278. public:
  279.     DoubleValue(const char *, const double, CharCheckFun ccf, LegalValueFun  
  280. lvf);
  281.     DoubleValue(double value=0.0);
  282.     virtual ~DoubleValue();
  283.     virtual const char* value() const;
  284.     virtual const int intValue() const;
  285.     virtual const double doubleValue() const;
  286.     virtual int set(const char *);
  287. private:
  288.     friend ValueArray;
  289.     virtual int size() { return sizeof(*this); }
  290.     double value_;
  291. };
  292.  
  293. // this allows me to create a virtual array, i.e., it fixes the problem with
  294. // the array index not adding the correct offset for the derived virtual class
  295.  
  296. class ValueArray {
  297. public:
  298.     ValueArray(QueryValue *qa, int len) : array(qa), length_(len) {
  299.         offset = qa->size();
  300.     }
  301.     QueryValue & operator [] (int index) const {
  302.         // check index and return reference to the base class
  303.         index = index < length_ ? index : length_ - 1;
  304.         return *((QueryValue *)(array + offset * index));
  305.     }
  306.     int length() const { return length_; }
  307. private:
  308.     void *array;    // raw pointer to beginning of array
  309.     int length_;
  310.     int offset;    // the proper size of each array element
  311. };
  312.  
  313. class QueryLabel;
  314.  
  315. struct QueryLink {
  316.     QueryLink(QueryLabel *q);
  317.     virtual ~QueryLink();
  318.     QueryLabel *element;
  319.     QueryLink *next;
  320. };
  321.  
  322. class String;
  323.  
  324. // linked list container/manipulator for QueryLabel and its derived classes
  325.  
  326. class QueryList {
  327. public:
  328.     QueryList(const char *lbl);
  329.     virtual ~QueryList();
  330.     void append(QueryLabel *);
  331.     void start() { current = head; }
  332.     int more() { return current != 0; }
  333.     void next() { current = current->next; }
  334.     const char *label();
  335.     QueryLabel *value() { return current->element; }
  336. private:
  337.     QueryLink *tail();
  338. private:
  339.     String *listLabel;
  340.     QueryLink *current;
  341.     QueryLink *head;
  342. };
  343.  
  344. class QueryButton;
  345.  
  346. class ButtonList : public QueryList {
  347. public:
  348.     ButtonList(const char *lbl=0) : (lbl ? lbl : "") {}
  349.     virtual ~ButtonList() {}
  350.     QueryButton *value() { return (QueryButton *) QueryList::value(); }
  351. };
  352.  
  353. class QueryValue;
  354.  
  355. class ValueList : public QueryList {
  356. public:
  357.     ValueList(const char *lbl=0) : (lbl ? lbl : "") {}
  358.     virtual ~ValueList() {}
  359.     QueryValue *value() { return (QueryValue *) QueryList::value(); }
  360. };
  361.  
  362. enum RequestType { AlertType, ConfirmerType, ChoiceType, InputType };
  363.  
  364. class DialogConstructor;
  365. class ValueArray;
  366.  
  367. class Request {
  368.     friend DialogConstructor;
  369. public:
  370.     Request() { init(); }
  371.     Request(QueryInfo *);
  372.     virtual ~Request();
  373.     
  374.     int hasLabels() { return labelList != 0; }
  375.     int hasValues() { return valueList != 0; }
  376.     int useBell() { return bell; }
  377.     virtual RequestType type() { return InputType; } 
  378.     // default
  379.     void appendLabel(const char *);
  380.     void appendValue(const char *, const char *value, CharCheckFun, 
  381.  
  382.         LegalValueFun);
  383.     void appendValue(const char *, int value, CharCheckFun, 
  384.  
  385.         LegalValueFun);
  386.     void appendValue(const char *, double value, CharCheckFun,
  387.         LegalValueFun);
  388.     void appendValue(ValueType, const char *, const char *,
  389.         CharCheckFun ccf, LegalValueFun lvf);
  390.     void appendButton(const char *, Response);
  391.     void retrieveValues(ValueArray &v);
  392. protected:
  393.     virtual void createLabelList(QueryLabelInfo *);
  394.     virtual void createValueList(const char *, QueryValueInfo *);
  395.     virtual void createButtonList(QueryButtonInfo *);
  396.     void setBell(int b) { bell = b; }
  397. protected:
  398.     QueryList *labelList;
  399.     ValueList *valueList;
  400.     ButtonList *buttonList;
  401. private:
  402.     void init();
  403. private:
  404.     int bell;    // flag for bell ring
  405. };
  406.  
  407. QueryLabel::QueryLabel(const char* lbl) {
  408.      label_ = new String(lbl);
  409. }
  410.  
  411. QueryLabel::~QueryLabel() {
  412.      delete label_;
  413. }
  414.  
  415. const char*
  416. QueryLabel::label() { return *label_; }
  417.  
  418. /////////
  419.  
  420. QueryButton::QueryButton(const char *lbl, Response r) : (lbl), response_(r) {}
  421.  
  422. QueryButton::~QueryButton() {}
  423.  
  424. /////////
  425.  
  426. // default functions for QueryValue
  427.  
  428. static int anychar(const char c) { return 1; }
  429. static int anyvalue(const char *v) { return 1; }
  430.  
  431. QueryValue::QueryValue(const char* lbl, CharCheckFun ccf, LegalValueFun lvf)
  432.     : (lbl), checkFun(ccf), legalValue(lvf) {}
  433.  
  434. QueryValue::QueryValue() : (""), checkFun(anychar), legalValue(anyvalue) {}
  435.  
  436. QueryValue::~QueryValue() {}
  437.  
  438. void
  439. QueryValue::operator = (const QueryValue& rhs) {
  440.     // this allows any of the derived classes to be assigned to any other
  441.     // via use of character strings passed between virtual functions
  442.     set(rhs.value());
  443. }
  444.  
  445. /////////
  446.  
  447. StringValue::StringValue(const char *lbl, const char *s, CharCheckFun ccf,
  448.         LegalValueFun lvf) : (lbl, ccf, lvf) {
  449.      string = new String(s ? s : "");
  450. }
  451.  
  452. StringValue::StringValue(const char *value) {
  453.      string = new String(value ? value : "");
  454. }
  455.  
  456. StringValue::~StringValue() {
  457.      delete string;
  458. }
  459.  
  460. int
  461. StringValue::set(const char *s) {
  462.     register int good = 0;
  463.     if(good = legalValue(s)) {
  464.         *string = (s && strlen(s)) ? s : "0";
  465.     }
  466.     return good;
  467. }
  468.  
  469. const char *
  470. StringValue::value() const {
  471.     return *string;
  472. }
  473.  
  474. int
  475. StringValue::intValue() const {
  476.     return atoi(strlen(*string) > 0 ? *string : "0");
  477. }
  478.  
  479. double
  480. StringValue::doubleValue() const {
  481.     return atof(strlen(*string) > 0 ? *string : "0");
  482. }
  483.  
  484. IntValue::IntValue(const char *lbl, const int i, CharCheckFun ccf,
  485.         LegalValueFun lvf) : (lbl, ccf, lvf), value_(i) {}
  486.  
  487. IntValue::IntValue(int value) : value_(value) {}
  488.  
  489. IntValue::~IntValue() {}
  490.  
  491. const char *
  492. IntValue::value() const {
  493.     static char string[64];
  494.     sprintf(string, "%d", value_);
  495.     return string;
  496. }
  497.  
  498. int
  499. IntValue::intValue() const {
  500.     return value_;
  501. }
  502.  
  503. double
  504. IntValue::doubleValue() const {
  505.     return value_;
  506. }
  507.  
  508. int
  509. IntValue::set(const char *s) {
  510.     register int good = 0;
  511.     if(good = legalValue(s)) {
  512.         value_ = (s && strlen(s)) ? atoi(s) : 0;
  513.     }
  514.     return good;
  515. }
  516.     
  517. DoubleValue::DoubleValue(const char *lbl, const double d, CharCheckFun ccf,
  518.         LegalValueFun lvf) : (lbl, ccf, lvf), value_(d) {}
  519.     
  520. DoubleValue::DoubleValue(double value) : value_(value) {}
  521.  
  522. DoubleValue::~DoubleValue() {}
  523.  
  524. const char *
  525. DoubleValue::value() const {
  526.     static char string[128];
  527.     sprintf(string, "%f", value_);
  528.     return string;
  529. }
  530.  
  531. int
  532. DoubleValue::intValue() const {
  533.     return int(value_);
  534. }
  535.  
  536. double
  537. DoubleValue::doubleValue() const {
  538.     return value_;
  539. }
  540.  
  541. int
  542. DoubleValue::set(const char *s) {
  543.     register int good = 0;
  544.     if(good = legalValue(s)) {
  545.         value_ = (s && strlen(s)) ? atof(s) : 0;
  546.     }
  547.     return good;
  548. }
  549.  
  550. QueryLink::QueryLink(QueryLabel *q) {
  551.     element = q;
  552.     next = 0;
  553. }
  554.  
  555. QueryLink::~QueryLink() { delete element; }
  556.  
  557.  
  558. QueryList::QueryList(const char *label) {
  559.     listLabel = new String(label);
  560.     head = 0;
  561. }
  562.  
  563. QueryList::~QueryList() {
  564.     delete listLabel;
  565.     start();
  566.     while(current) {
  567.         register QueryLink *next = current->next;
  568.         delete current;
  569.         current = next;
  570.     }
  571. }
  572.  
  573. QueryLink *
  574. QueryList::tail() {
  575.     start();
  576.     while(current && current->next)
  577.         current = current->next;
  578.     return current;
  579. }
  580.     
  581. void
  582. QueryList::append(QueryLabel *q) {
  583.     register QueryLink *link = new QueryLink(q);
  584.     if(!head)
  585.         head = link;
  586.     else
  587.         tail()->next = link;
  588.     current = link;
  589. }
  590.  
  591. const char *
  592. QueryList::label() { return *listLabel; }
  593.  
  594. ////////
  595.  
  596. Request::Request(QueryInfo *qinfo) {
  597.     init();
  598.     if(qinfo->labelInfo)
  599.         createLabelList(qinfo->labelInfo);
  600.     if(qinfo->valueInfo)
  601.         createValueList(qinfo->valueListLabel, qinfo->valueInfo);
  602.     if(qinfo->buttonInfo)
  603.         createButtonList(qinfo->buttonInfo);
  604. }
  605.  
  606. void
  607. Request::init() {
  608.     labelList = 0;
  609.     valueList = 0;
  610.     buttonList = 0;
  611.     bell = 0;
  612. }
  613.  
  614. Request::~Request() {
  615.     delete labelList;
  616.     delete valueList;
  617.     delete buttonList;
  618. }
  619.  
  620. void
  621. Request::appendLabel(const char *lbl) {
  622.     if(!labelList) labelList = new QueryList("");
  623.     labelList->append(new QueryLabel(lbl));
  624. }
  625.  
  626. void
  627. Request::appendButton(const char *lbl, Response response) {
  628.     if(!buttonList) buttonList = new ButtonList;
  629.     buttonList->append(new QueryButton(lbl, response));
  630. }
  631.  
  632. void
  633. Request::appendValue(const char *label, const char *value, CharCheckFun ccf,
  634.         LegalValueFun lvf) {
  635.     if(!valueList) valueList = new ValueList;
  636.     valueList->append(new StringValue(label, value, ccf, lvf));
  637. }
  638.  
  639. void
  640. Request::appendValue(const char *label, int value, CharCheckFun ccf,
  641.         LegalValueFun lvf) {
  642.     if(!valueList) valueList = new ValueList;
  643.     valueList->append(new IntValue(label, value, ccf, lvf));
  644. }
  645.  
  646. void
  647. Request::appendValue(const char *label, double value, CharCheckFun ccf,
  648.         LegalValueFun lvf) {
  649.     if(!valueList) valueList = new ValueList;
  650.     valueList->append(new DoubleValue(label, value, ccf, lvf));
  651. }
  652.  
  653. void
  654. Request::appendValue(ValueType type, const char *label, const char *defval,
  655.         CharCheckFun ccf, LegalValueFun lvf) {
  656.     if(!valueList) valueList = new ValueList;
  657.     valueList->append(
  658.         type == VString ? new StringValue(label, defval, ccf, lvf)
  659.         : type == VInt ?  new IntValue(label, atoi(defval), ccf, lvf)
  660.         :               new DoubleValue(label, atof(defval), ccf, lvf)
  661.     );
  662. }
  663.  
  664. void
  665. Request::retrieveValues(ValueArray &v) {
  666.     int valsReturned = 0, nvals = v.length();
  667.     if(hasValues()) {
  668.         for(valueList->start();
  669.                 valueList->more() && valsReturned != nvals; 
  670.  
  671.                 valueList->next(), ++valsReturned) {
  672.             v[valsReturned] = *(valueList->value());
  673.         }
  674.     }
  675. }
  676.     
  677. void
  678. Request::createLabelList(QueryLabelInfo *qlist) {
  679.     for(QueryLabelInfo *i = qlist; i->label != 0; i++) {
  680.         appendLabel(i->label);
  681.     }
  682. }
  683.  
  684. void
  685. Request::createButtonList(QueryButtonInfo *qbilist) {
  686.     for(QueryButtonInfo *i = qbilist; i->label != None; i++) {
  687.         appendButton(i->label, i->response);
  688.     }
  689. }
  690.  
  691. void
  692. Request::createValueList(const char *vlistlabel, QueryValueInfo *qvilist) {
  693.     valueList = new ValueList(vlistlabel);
  694.     for(QueryValueInfo *i = qvilist; i->type != None; i++) {
  695.         appendValue(i->type, i->label, i->defaultVal, i->check,
  696.             i->legal);
  697.     }
  698. }
  699.  
  700. // here are the char test functions for checking user input
  701.  
  702. int
  703. posIntsOnly(char c) {    // control chars and integers only
  704.     return (iscntrl(c) || isdigit(c));
  705. }
  706.  
  707. int
  708. intsOnly(char c) {
  709.     return (c == '-' || posIntsOnly(c));
  710. }
  711.  
  712. int
  713. posNumsOnly(char c) {    // control chars, '.',  and integers only
  714.     return (c == '.' || posIntsOnly(c));
  715. }
  716.  
  717. int
  718. numsOnly(char c) {
  719.     return (c == '.' || intsOnly(c));
  720. }
  721.  
  722. int
  723. checkDouble(char *s) {
  724.     return 1;
  725. }
  726.  
  727. static QueryButtonInfo defaultInputButtonInfo[] = {
  728.         { "confirm", Yes },
  729.         { "cancel", Cancel },
  730.         { 0 }
  731. };
  732.  
  733. main() {
  734.     static QueryLabelInfo labels[] = {
  735.         { "Set Endpoints for Horizontal Display: " }, { 0 }
  736.     };
  737.     static QueryInfo info[] = {
  738.         labels, "", 0, defaultInputButtonInfo
  739.     };
  740.     int start = 0;
  741.     int end = 50;
  742.     // create and load a Request object with default values
  743.     Request request(info);
  744.     request.appendValue("Minimum Samp: ", start, posNumsOnly, checkDouble);
  745.     request.appendValue("Maximum Samp: ", end, posNumsOnly, checkDouble);
  746.     
  747.     // normally at this point, the request object would be passed to a
  748.     // dialog creation and display object that queries the user for input
  749.     
  750.     const int nvals = 2;
  751.     IntValue vr[nvals];
  752.     
  753.     // now get the newly set values and load them into vr[]
  754.     // (in this case they are still set to the default values)
  755.     
  756.     request.retrieveValues(ValueArray(vr, nvals));
  757.     printf("Values retrieved are %d and %d\n",
  758.         vr[0].intValue(), vr[1].intValue());
  759. }
  760.  
  761.