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