1151497Sru// -*- C++ -*-
2151497Sru/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3151497Sru     Written by Gaius Mulley (gaius@glam.ac.uk)
4151497Sru
5151497SruThis file is part of groff.
6151497Sru
7151497Srugroff is free software; you can redistribute it and/or modify it under
8151497Sruthe terms of the GNU General Public License as published by the Free
9151497SruSoftware Foundation; either version 2, or (at your option) any later
10151497Sruversion.
11151497Sru
12151497Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY
13151497SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
14151497SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15151497Srufor more details.
16151497Sru
17151497SruYou should have received a copy of the GNU General Public License along
18151497Sruwith groff; see the file COPYING.  If not, write to the Free Software
19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
20151497Sru
21151497Sru#define DEBUGGING
22151497Sru
23151497Sruextern int debug_state;
24151497Sru
25151497Sru#include "troff.h"
26151497Sru#include "hvunits.h"
27151497Sru#include "stringclass.h"
28151497Sru#include "mtsm.h"
29151497Sru#include "env.h"
30151497Sru
31151497Srustatic int no_of_statems = 0;	// debugging aid
32151497Sru
33151497Sruint_value::int_value()
34151497Sru: value(0), is_known(0)
35151497Sru{
36151497Sru}
37151497Sru
38151497Sruint_value::~int_value()
39151497Sru{
40151497Sru}
41151497Sru
42151497Sruvoid int_value::diff(FILE *fp, const char *s, int_value compare)
43151497Sru{
44151497Sru  if (differs(compare)) {
45151497Sru    fputs("x X ", fp);
46151497Sru    fputs(s, fp);
47151497Sru    fputs(" ", fp);
48151497Sru    fputs(i_to_a(compare.value), fp);
49151497Sru    fputs("\n", fp);
50151497Sru    value = compare.value;
51151497Sru    is_known = 1;
52151497Sru    if (debug_state)
53151497Sru      fflush(fp);
54151497Sru  }
55151497Sru}
56151497Sru
57151497Sruvoid int_value::set(int v)
58151497Sru{
59151497Sru  is_known = 1;
60151497Sru  value = v;
61151497Sru}
62151497Sru
63151497Sruvoid int_value::unset()
64151497Sru{
65151497Sru  is_known = 0;
66151497Sru}
67151497Sru
68151497Sruvoid int_value::set_if_unknown(int v)
69151497Sru{
70151497Sru  if (!is_known)
71151497Sru    set(v);
72151497Sru}
73151497Sru
74151497Sruint int_value::differs(int_value compare)
75151497Sru{
76151497Sru  return compare.is_known
77151497Sru	 && (!is_known || value != compare.value);
78151497Sru}
79151497Sru
80151497Srubool_value::bool_value()
81151497Sru{
82151497Sru}
83151497Sru
84151497Srubool_value::~bool_value()
85151497Sru{
86151497Sru}
87151497Sru
88151497Sruvoid bool_value::diff(FILE *fp, const char *s, bool_value compare)
89151497Sru{
90151497Sru  if (differs(compare)) {
91151497Sru    fputs("x X ", fp);
92151497Sru    fputs(s, fp);
93151497Sru    fputs("\n", fp);
94151497Sru    value = compare.value;
95151497Sru    is_known = 1;
96151497Sru    if (debug_state)
97151497Sru      fflush(fp);
98151497Sru  }
99151497Sru}
100151497Sru
101151497Sruunits_value::units_value()
102151497Sru{
103151497Sru}
104151497Sru
105151497Sruunits_value::~units_value()
106151497Sru{
107151497Sru}
108151497Sru
109151497Sruvoid units_value::diff(FILE *fp, const char *s, units_value compare)
110151497Sru{
111151497Sru  if (differs(compare)) {
112151497Sru    fputs("x X ", fp);
113151497Sru    fputs(s, fp);
114151497Sru    fputs(" ", fp);
115151497Sru    fputs(i_to_a(compare.value), fp);
116151497Sru    fputs("\n", fp);
117151497Sru    value = compare.value;
118151497Sru    is_known = 1;
119151497Sru    if (debug_state)
120151497Sru      fflush(fp);
121151497Sru  }
122151497Sru}
123151497Sru
124151497Sruvoid units_value::set(hunits v)
125151497Sru{
126151497Sru  is_known = 1;
127151497Sru  value = v.to_units();
128151497Sru}
129151497Sru
130151497Sruint units_value::differs(units_value compare)
131151497Sru{
132151497Sru  return compare.is_known
133151497Sru	 && (!is_known || value != compare.value);
134151497Sru}
135151497Sru
136151497Srustring_value::string_value()
137151497Sru: value(string("")), is_known(0)
138151497Sru{
139151497Sru}
140151497Sru
141151497Srustring_value::~string_value()
142151497Sru{
143151497Sru}
144151497Sru
145151497Sruvoid string_value::diff(FILE *fp, const char *s, string_value compare)
146151497Sru{
147151497Sru  if (differs(compare)) {
148151497Sru    fputs("x X ", fp);
149151497Sru    fputs(s, fp);
150151497Sru    fputs(" ", fp);
151151497Sru    fputs(compare.value.contents(), fp);
152151497Sru    fputs("\n", fp);
153151497Sru    value = compare.value;
154151497Sru    is_known = 1;
155151497Sru  }
156151497Sru}
157151497Sru
158151497Sruvoid string_value::set(string v)
159151497Sru{
160151497Sru  is_known = 1;
161151497Sru  value = v;
162151497Sru}
163151497Sru
164151497Sruvoid string_value::unset()
165151497Sru{
166151497Sru  is_known = 0;
167151497Sru}
168151497Sru
169151497Sruint string_value::differs(string_value compare)
170151497Sru{
171151497Sru  return compare.is_known
172151497Sru	 && (!is_known || value != compare.value);
173151497Sru}
174151497Sru
175151497Srustatem::statem()
176151497Sru{
177151497Sru  issue_no = no_of_statems;
178151497Sru  no_of_statems++;
179151497Sru}
180151497Sru
181151497Srustatem::statem(statem *copy)
182151497Sru{
183151497Sru  int i;
184151497Sru  for (i = 0; i < LAST_BOOL; i++)
185151497Sru    bool_values[i] = copy->bool_values[i];
186151497Sru  for (i = 0; i < LAST_INT; i++)
187151497Sru    int_values[i] = copy->int_values[i];
188151497Sru  for (i = 0; i < LAST_UNITS; i++)
189151497Sru    units_values[i] = copy->units_values[i];
190151497Sru  for (i = 0; i < LAST_STRING; i++)
191151497Sru    string_values[i] = copy->string_values[i];
192151497Sru  issue_no = copy->issue_no;
193151497Sru}
194151497Sru
195151497Srustatem::~statem()
196151497Sru{
197151497Sru}
198151497Sru
199151497Sruvoid statem::flush(FILE *fp, statem *compare)
200151497Sru{
201151497Sru  int_values[MTSM_FI].diff(fp, "devtag:.fi",
202151497Sru			   compare->int_values[MTSM_FI]);
203151497Sru  int_values[MTSM_RJ].diff(fp, "devtag:.rj",
204151497Sru			   compare->int_values[MTSM_RJ]);
205151497Sru  int_values[MTSM_SP].diff(fp, "devtag:.sp",
206151497Sru			   compare->int_values[MTSM_SP]);
207151497Sru  units_values[MTSM_IN].diff(fp, "devtag:.in",
208151497Sru			     compare->units_values[MTSM_IN]);
209151497Sru  units_values[MTSM_LL].diff(fp, "devtag:.ll",
210151497Sru			     compare->units_values[MTSM_LL]);
211151497Sru  units_values[MTSM_PO].diff(fp, "devtag:.po",
212151497Sru			     compare->units_values[MTSM_PO]);
213151497Sru  string_values[MTSM_TA].diff(fp, "devtag:.ta",
214151497Sru			      compare->string_values[MTSM_TA]);
215151497Sru  units_values[MTSM_TI].diff(fp, "devtag:.ti",
216151497Sru			     compare->units_values[MTSM_TI]);
217151497Sru  int_values[MTSM_CE].diff(fp, "devtag:.ce",
218151497Sru			   compare->int_values[MTSM_CE]);
219151497Sru  bool_values[MTSM_EOL].diff(fp, "devtag:.eol",
220151497Sru			     compare->bool_values[MTSM_EOL]);
221151497Sru  bool_values[MTSM_BR].diff(fp, "devtag:.br",
222151497Sru			    compare->bool_values[MTSM_BR]);
223151497Sru  if (debug_state) {
224151497Sru    fprintf(stderr, "compared state %d\n", compare->issue_no);
225151497Sru    fflush(stderr);
226151497Sru  }
227151497Sru}
228151497Sru
229151497Sruvoid statem::add_tag(int_value_state t, int v)
230151497Sru{
231151497Sru  int_values[t].set(v);
232151497Sru}
233151497Sru
234151497Sruvoid statem::add_tag(units_value_state t, hunits v)
235151497Sru{
236151497Sru  units_values[t].set(v);
237151497Sru}
238151497Sru
239151497Sruvoid statem::add_tag(bool_value_state t)
240151497Sru{
241151497Sru  bool_values[t].set(1);
242151497Sru}
243151497Sru
244151497Sruvoid statem::add_tag(string_value_state t, string v)
245151497Sru{
246151497Sru  string_values[t].set(v);
247151497Sru}
248151497Sru
249151497Sruvoid statem::add_tag_if_unknown(int_value_state t, int v)
250151497Sru{
251151497Sru  int_values[t].set_if_unknown(v);
252151497Sru}
253151497Sru
254151497Sruvoid statem::sub_tag_ce()
255151497Sru{
256151497Sru  int_values[MTSM_CE].unset();
257151497Sru}
258151497Sru
259151497Sru/*
260151497Sru *  add_tag_ta - add the tab settings to the minimum troff state machine
261151497Sru */
262151497Sru
263151497Sruvoid statem::add_tag_ta()
264151497Sru{
265151497Sru  if (is_html) {
266151497Sru    string s = string("");
267151497Sru    hunits d, l;
268151497Sru    enum tab_type t;
269151497Sru    do {
270151497Sru      t = curenv->tabs.distance_to_next_tab(l, &d);
271151497Sru      l += d;
272151497Sru      switch (t) {
273151497Sru      case TAB_LEFT:
274151497Sru	s += " L ";
275151497Sru	s += as_string(l.to_units());
276151497Sru	break;
277151497Sru      case TAB_CENTER:
278151497Sru	s += " C ";
279151497Sru	s += as_string(l.to_units());
280151497Sru	break;
281151497Sru      case TAB_RIGHT:
282151497Sru	s += " R ";
283151497Sru	s += as_string(l.to_units());
284151497Sru	break;
285151497Sru      case TAB_NONE:
286151497Sru	break;
287151497Sru      }
288151497Sru    } while (t != TAB_NONE && l < curenv->get_line_length());
289151497Sru    s += '\0';
290151497Sru    string_values[MTSM_TA].set(s);
291151497Sru  }
292151497Sru}
293151497Sru
294151497Sruvoid statem::update(statem *older, statem *newer, int_value_state t)
295151497Sru{
296151497Sru  if (newer->int_values[t].differs(older->int_values[t])
297151497Sru      && !newer->int_values[t].is_known)
298151497Sru    newer->int_values[t].set(older->int_values[t].value);
299151497Sru}
300151497Sru
301151497Sruvoid statem::update(statem *older, statem *newer, units_value_state t)
302151497Sru{
303151497Sru  if (newer->units_values[t].differs(older->units_values[t])
304151497Sru      && !newer->units_values[t].is_known)
305151497Sru    newer->units_values[t].set(older->units_values[t].value);
306151497Sru}
307151497Sru
308151497Sruvoid statem::update(statem *older, statem *newer, bool_value_state t)
309151497Sru{
310151497Sru  if (newer->bool_values[t].differs(older->bool_values[t])
311151497Sru      && !newer->bool_values[t].is_known)
312151497Sru    newer->bool_values[t].set(older->bool_values[t].value);
313151497Sru}
314151497Sru
315151497Sruvoid statem::update(statem *older, statem *newer, string_value_state t)
316151497Sru{
317151497Sru  if (newer->string_values[t].differs(older->string_values[t])
318151497Sru      && !newer->string_values[t].is_known)
319151497Sru    newer->string_values[t].set(older->string_values[t].value);
320151497Sru}
321151497Sru
322151497Sruvoid statem::merge(statem *newer, statem *older)
323151497Sru{
324151497Sru  if (newer == 0 || older == 0)
325151497Sru    return;
326151497Sru  update(older, newer, MTSM_EOL);
327151497Sru  update(older, newer, MTSM_BR);
328151497Sru  update(older, newer, MTSM_FI);
329151497Sru  update(older, newer, MTSM_LL);
330151497Sru  update(older, newer, MTSM_PO);
331151497Sru  update(older, newer, MTSM_RJ);
332151497Sru  update(older, newer, MTSM_SP);
333151497Sru  update(older, newer, MTSM_TA);
334151497Sru  update(older, newer, MTSM_TI);
335151497Sru  update(older, newer, MTSM_CE);
336151497Sru}
337151497Sru
338151497Srustack::stack()
339151497Sru: next(0), state(0)
340151497Sru{
341151497Sru}
342151497Sru
343151497Srustack::stack(statem *s, stack *n)
344151497Sru: next(n), state(s)
345151497Sru{
346151497Sru}
347151497Sru
348151497Srustack::~stack()
349151497Sru{
350151497Sru  if (state)
351151497Sru    delete state;
352151497Sru  if (next)
353151497Sru    delete next;
354151497Sru}
355151497Sru
356151497Srumtsm::mtsm()
357151497Sru: sp(0)
358151497Sru{
359151497Sru  driver = new statem();
360151497Sru}
361151497Sru
362151497Srumtsm::~mtsm()
363151497Sru{
364151497Sru  delete driver;
365151497Sru  if (sp)
366151497Sru    delete sp;
367151497Sru}
368151497Sru
369151497Sru/*
370151497Sru *  push_state - push the current troff state and use `n' as
371151497Sru *               the new troff state.
372151497Sru */
373151497Sru
374151497Sruvoid mtsm::push_state(statem *n)
375151497Sru{
376151497Sru  if (is_html) {
377151497Sru#if defined(DEBUGGING)
378151497Sru    if (debug_state)
379151497Sru      fprintf(stderr, "--> state %d pushed\n", n->issue_no) ; fflush(stderr);
380151497Sru#endif
381151497Sru    sp = new stack(n, sp);
382151497Sru  }
383151497Sru}
384151497Sru
385151497Sruvoid mtsm::pop_state()
386151497Sru{
387151497Sru  if (is_html) {
388151497Sru#if defined(DEBUGGING)
389151497Sru    if (debug_state)
390151497Sru      fprintf(stderr, "--> state popped\n") ; fflush(stderr);
391151497Sru#endif
392151497Sru    if (sp == 0)
393151497Sru      fatal("empty state machine stack");
394151497Sru    if (sp->state)
395151497Sru      delete sp->state;
396151497Sru    sp->state = 0;
397151497Sru    stack *t = sp;
398151497Sru    sp = sp->next;
399151497Sru    t->next = 0;
400151497Sru    delete t;
401151497Sru  }
402151497Sru}
403151497Sru
404151497Sru/*
405151497Sru *  inherit - scan the stack and collects inherited values.
406151497Sru */
407151497Sru
408151497Sruvoid mtsm::inherit(statem *s, int reset_bool)
409151497Sru{
410151497Sru  if (sp && sp->state) {
411151497Sru    if (s->units_values[MTSM_IN].is_known
412151497Sru	&& sp->state->units_values[MTSM_IN].is_known)
413151497Sru      s->units_values[MTSM_IN].value += sp->state->units_values[MTSM_IN].value;
414151497Sru    s->update(sp->state, s, MTSM_FI);
415151497Sru    s->update(sp->state, s, MTSM_LL);
416151497Sru    s->update(sp->state, s, MTSM_PO);
417151497Sru    s->update(sp->state, s, MTSM_RJ);
418151497Sru    s->update(sp->state, s, MTSM_TA);
419151497Sru    s->update(sp->state, s, MTSM_TI);
420151497Sru    s->update(sp->state, s, MTSM_CE);
421151497Sru    if (sp->state->bool_values[MTSM_BR].is_known
422151497Sru	&& sp->state->bool_values[MTSM_BR].value) {
423151497Sru      if (reset_bool)
424151497Sru	sp->state->bool_values[MTSM_BR].set(0);
425151497Sru      s->bool_values[MTSM_BR].set(1);
426151497Sru      if (debug_state)
427151497Sru	fprintf(stderr, "inherited br from pushed state %d\n",
428151497Sru		sp->state->issue_no);
429151497Sru    }
430151497Sru    else if (s->bool_values[MTSM_BR].is_known
431151497Sru	     && s->bool_values[MTSM_BR].value)
432151497Sru      if (! s->int_values[MTSM_CE].is_known)
433151497Sru	s->bool_values[MTSM_BR].unset();
434151497Sru    if (sp->state->bool_values[MTSM_EOL].is_known
435151497Sru	&& sp->state->bool_values[MTSM_EOL].value) {
436151497Sru      if (reset_bool)
437151497Sru	sp->state->bool_values[MTSM_EOL].set(0);
438151497Sru      s->bool_values[MTSM_EOL].set(1);
439151497Sru    }
440151497Sru  }
441151497Sru}
442151497Sru
443151497Sruvoid mtsm::flush(FILE *fp, statem *s, string tag_list)
444151497Sru{
445151497Sru  if (is_html && s) {
446151497Sru    inherit(s, 1);
447151497Sru    driver->flush(fp, s);
448151497Sru    // Set rj, ce, ti to unknown if they were known and
449151497Sru    // we have seen an eol or br.  This ensures that these values
450151497Sru    // are emitted during the next glyph (as they step from n..0
451151497Sru    // at each newline).
452151497Sru    if ((driver->bool_values[MTSM_EOL].is_known
453151497Sru	 && driver->bool_values[MTSM_EOL].value)
454151497Sru	|| (driver->bool_values[MTSM_BR].is_known
455151497Sru	    && driver->bool_values[MTSM_BR].value)) {
456151497Sru      if (driver->units_values[MTSM_TI].is_known)
457151497Sru	driver->units_values[MTSM_TI].is_known = 0;
458151497Sru      if (driver->int_values[MTSM_RJ].is_known
459151497Sru	  && driver->int_values[MTSM_RJ].value > 0)
460151497Sru	driver->int_values[MTSM_RJ].is_known = 0;
461151497Sru      if (driver->int_values[MTSM_CE].is_known
462151497Sru	  && driver->int_values[MTSM_CE].value > 0)
463151497Sru	driver->int_values[MTSM_CE].is_known = 0;
464151497Sru    }
465151497Sru    // reset the boolean values
466151497Sru    driver->bool_values[MTSM_BR].set(0);
467151497Sru    driver->bool_values[MTSM_EOL].set(0);
468151497Sru    // reset space value
469151497Sru    driver->int_values[MTSM_SP].set(0);
470151497Sru    // lastly write out any direct tag entries
471151497Sru    if (tag_list != string("")) {
472151497Sru      string t = tag_list + '\0';
473151497Sru      fputs(t.contents(), fp);
474151497Sru    }
475151497Sru  }
476151497Sru}
477151497Sru
478151497Sru/*
479151497Sru *  display_state - dump out a synopsis of the state to stderr.
480151497Sru */
481151497Sru
482151497Sruvoid statem::display_state()
483151497Sru{
484151497Sru  fprintf(stderr, " <state ");
485257263Ssbruno  if (bool_values[MTSM_BR].is_known) {
486151497Sru    if (bool_values[MTSM_BR].value)
487151497Sru      fprintf(stderr, "[br]");
488151497Sru    else
489151497Sru      fprintf(stderr, "[!br]");
490257263Ssbruno  }
491257263Ssbruno  if (bool_values[MTSM_EOL].is_known) {
492151497Sru    if (bool_values[MTSM_EOL].value)
493151497Sru      fprintf(stderr, "[eol]");
494151497Sru    else
495151497Sru      fprintf(stderr, "[!eol]");
496257263Ssbruno  }
497257263Ssbruno  if (int_values[MTSM_SP].is_known) {
498151497Sru    if (int_values[MTSM_SP].value)
499151497Sru      fprintf(stderr, "[sp %d]", int_values[MTSM_SP].value);
500151497Sru    else
501151497Sru      fprintf(stderr, "[!sp]");
502257263Ssbruno  }
503151497Sru  fprintf(stderr, ">");
504151497Sru  fflush(stderr);
505151497Sru}
506151497Sru
507151497Sruint mtsm::has_changed(int_value_state t, statem *s)
508151497Sru{
509151497Sru  return driver->int_values[t].differs(s->int_values[t]);
510151497Sru}
511151497Sru
512151497Sruint mtsm::has_changed(units_value_state t, statem *s)
513151497Sru{
514151497Sru  return driver->units_values[t].differs(s->units_values[t]);
515151497Sru}
516151497Sru
517151497Sruint mtsm::has_changed(bool_value_state t, statem *s)
518151497Sru{
519151497Sru  return driver->bool_values[t].differs(s->bool_values[t]);
520151497Sru}
521151497Sru
522151497Sruint mtsm::has_changed(string_value_state t, statem *s)
523151497Sru{
524151497Sru  return driver->string_values[t].differs(s->string_values[t]);
525151497Sru}
526151497Sru
527151497Sruint mtsm::changed(statem *s)
528151497Sru{
529151497Sru  if (s == 0 || !is_html)
530151497Sru    return 0;
531151497Sru  s = new statem(s);
532151497Sru  inherit(s, 0);
533151497Sru  int result = has_changed(MTSM_EOL, s)
534151497Sru	       || has_changed(MTSM_BR, s)
535151497Sru	       || has_changed(MTSM_FI, s)
536151497Sru	       || has_changed(MTSM_IN, s)
537151497Sru	       || has_changed(MTSM_LL, s)
538151497Sru	       || has_changed(MTSM_PO, s)
539151497Sru	       || has_changed(MTSM_RJ, s)
540151497Sru	       || has_changed(MTSM_SP, s)
541151497Sru	       || has_changed(MTSM_TA, s)
542151497Sru	       || has_changed(MTSM_CE, s);
543151497Sru  delete s;
544151497Sru  return result;
545151497Sru}
546151497Sru
547151497Sruvoid mtsm::add_tag(FILE *fp, string s)
548151497Sru{
549151497Sru  fflush(fp);
550151497Sru  s += '\0';
551151497Sru  fputs(s.contents(), fp);
552151497Sru}
553151497Sru
554151497Sru/*
555151497Sru *  state_set class
556151497Sru */
557151497Sru
558151497Srustate_set::state_set()
559151497Sru: boolset(0), intset(0), unitsset(0), stringset(0)
560151497Sru{
561151497Sru}
562151497Sru
563151497Srustate_set::~state_set()
564151497Sru{
565151497Sru}
566151497Sru
567151497Sruvoid state_set::incl(bool_value_state b)
568151497Sru{
569151497Sru  boolset |= 1 << (int)b;
570151497Sru}
571151497Sru
572151497Sruvoid state_set::incl(int_value_state i)
573151497Sru{
574151497Sru  intset |= 1 << (int)i;
575151497Sru}
576151497Sru
577151497Sruvoid state_set::incl(units_value_state u)
578151497Sru{
579151497Sru  unitsset |= 1 << (int)u;
580151497Sru}
581151497Sru
582151497Sruvoid state_set::incl(string_value_state s)
583151497Sru{
584151497Sru  stringset |= 1 << (int)s;
585151497Sru}
586151497Sru
587151497Sruvoid state_set::excl(bool_value_state b)
588151497Sru{
589151497Sru  boolset &= ~(1 << (int)b);
590151497Sru}
591151497Sru
592151497Sruvoid state_set::excl(int_value_state i)
593151497Sru{
594151497Sru  intset &= ~(1 << (int)i);
595151497Sru}
596151497Sru
597151497Sruvoid state_set::excl(units_value_state u)
598151497Sru{
599151497Sru  unitsset &= ~(1 << (int)u);
600151497Sru}
601151497Sru
602151497Sruvoid state_set::excl(string_value_state s)
603151497Sru{
604151497Sru  stringset &= ~(1 << (int)s);
605151497Sru}
606151497Sru
607151497Sruint state_set::is_in(bool_value_state b)
608151497Sru{
609151497Sru  return (boolset & (1 << (int)b)) != 0;
610151497Sru}
611151497Sru
612151497Sruint state_set::is_in(int_value_state i)
613151497Sru{
614151497Sru  return (intset & (1 << (int)i)) != 0;
615151497Sru}
616151497Sru
617222083Sbenl// Note: this used to have a bug s.t. it always tested for bit 0 (benl 18/5/11)
618151497Sruint state_set::is_in(units_value_state u)
619151497Sru{
620222083Sbenl  return (unitsset & (1 << (int)u)) != 0;
621151497Sru}
622151497Sru
623222083Sbenl// Note: this used to have a bug s.t. it always tested for bit 0 (benl 18/5/11)
624151497Sruint state_set::is_in(string_value_state s)
625151497Sru{
626222083Sbenl  return (stringset & (1 << (int)s)) != 0;
627151497Sru}
628151497Sru
629151497Sruvoid state_set::add(units_value_state, int n)
630151497Sru{
631151497Sru  unitsset += n;
632151497Sru}
633151497Sru
634151497Sruunits state_set::val(units_value_state)
635151497Sru{
636151497Sru  return unitsset;
637151497Sru}
638