From a600bd1bd7a15059374e6d527b23403a8133b410 Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Wed, 10 Jul 2024 10:11:07 +0000 Subject: Deploy mate-desktop/mate-calc to github.com/mate-desktop/mate-calc.git:gh-pages --- .../0.html | 1441 +++++++ .../1.html | 441 +++ .../10.html | 2227 +++++++++++ .../11.html | 773 ++++ .../2.html | 2511 ++++++++++++ .../3.html | 767 ++++ .../4.html | 3021 ++++++++++++++ .../5.html | 4161 ++++++++++++++++++++ .../6.html | 1001 +++++ .../7.html | 933 +++++ .../8.html | 959 +++++ .../9.html | 2785 +++++++++++++ .../index.html | 251 ++ .../stats.html | 179 + .../style.css | 177 + 15 files changed, 21627 insertions(+) create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/0.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/1.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/10.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/11.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/2.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/3.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/4.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/5.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/6.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/7.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/8.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/9.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/index.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/stats.html create mode 100644 2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/style.css (limited to '2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master') diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/0.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/0.html new file mode 100644 index 0000000..c5da97d --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/0.html @@ -0,0 +1,1441 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "lexer.h"
+#include "parserfunc.h"
+#include "mp-equation.h"
+
+static gboolean
+l_check_if_function(LexerState* state)
+{
+    gchar* name = pl_get_marked_substring(state->prelexer);
+    if(!state->parent->function_is_defined)
+    {
+        free(name);
+        return FALSE;
+    }
+    if ((*(state->parent->function_is_defined))(state->parent, name))
+    {
+        free(name);
+        return TRUE;
+    }
+    else
+    {
+        free(name);
+        return FALSE;
+    }
+}
+
+static gboolean
+l_check_if_number(LexerState* state)
+{
+    MPNumber tmp = mp_new();
+    int count = 0;
+    gchar* text = pl_get_marked_substring(state->prelexer);
+    if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
+    {
+        free(text);
+        mp_clear(&tmp);
+        return TRUE;
+    }
+    else
+    {
+        /* Try to rollback several characters to see, if that yeilds any number. */
+        while(strlen (text) > 0)
+        {
+            if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
+            {
+                free(text);
+                mp_clear(&tmp);
+                return TRUE;
+            }
+            free(text);
+            count++;
+            pl_roll_back(state->prelexer);
+            text = pl_get_marked_substring(state->prelexer);
+        }
+        /* Undo all rollbacks. */
+        while(count--)
+            pl_get_next_token (state->prelexer);
+        free(text);
+        mp_clear(&tmp);
+        return FALSE;
+    }
+}
+
+/* Insert generated token to the LexerState structure. */
+static LexerToken*
+l_insert_token(LexerState* state, const LexerTokenType type)
+{
+    state->tokens = (LexerToken *) realloc(state->tokens, (state->token_count + 1) * sizeof(LexerToken));
+    assert(state->tokens != NULL);
+    state->tokens[state->token_count].string = pl_get_marked_substring(state->prelexer);
+    state->tokens[state->token_count].start_index = state->prelexer->mark_index;
+    state->tokens[state->token_count].end_index = state->prelexer->next_index;
+    state->tokens[state->token_count].token_type = type;
+    state->token_count++;
+    return &state->tokens[state->token_count - 1];
+}
+
+/* Generates next token from pre-lexer stream and call l_insert_token() to insert it at the end. */
+static LexerToken*
+l_insert_next_token(LexerState* lstate)
+{
+    PreLexerState* state = lstate->prelexer;
+    LexerTokenType type;
+    gchar* tmp;
+    pl_set_marker(state);
+    /* Ignore all blank spaces. :) */
+    while((type = pl_get_next_token(state)) == PL_SKIP)
+        /* Set marker. Beginning of new token. */
+        pl_set_marker(state);
+    if(type == T_AND
+     ||type == T_OR
+     ||type == T_XOR
+     ||type == T_NOT
+     ||type == T_ADD
+     ||type == T_SUBTRACT
+     ||type == T_MULTIPLY
+     ||type == T_DIV
+     ||type == T_L_FLOOR
+     ||type == T_R_FLOOR
+     ||type == T_L_CEILING
+     ||type == T_R_CEILING
+     ||type == T_ROOT
+     ||type == T_ROOT_3
+     ||type == T_ROOT_4
+     ||type == T_ASSIGN
+     ||type == T_L_R_BRACKET
+     ||type == T_R_R_BRACKET
+     ||type == T_L_S_BRACKET
+     ||type == T_R_S_BRACKET
+     ||type == T_L_C_BRACKET
+     ||type == T_R_C_BRACKET
+     ||type == T_ABS
+     ||type == T_POWER
+     ||type == T_FACTORIAL
+     ||type == T_PERCENTAGE)
+    {
+        return l_insert_token(lstate, type);
+    }
+    /* [PL_SUPER_MINUS][PL_SUPER_DIGIT]+ */
+    if(type == PL_SUPER_MINUS)
+    {
+        if((type = pl_get_next_token(state)) != PL_SUPER_DIGIT)<--- Variable 'type' is assigned a value that is never used.
+        {
+            /* ERROR: expected PL_SUP_DIGIT */
+            set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
+            free(tmp);
+            return l_insert_token(lstate, T_UNKNOWN);
+        }
+        /* Get all PL_SUPER_DIGITs. */
+        while (pl_get_next_token(state) == PL_SUPER_DIGIT);
+        pl_roll_back(state);
+        return l_insert_token(lstate, T_NSUP_NUMBER);
+    }
+    /* [PL_SUPER_DIGIT]+ */
+    if(type == PL_SUPER_DIGIT)
+    {
+        while(pl_get_next_token(state) == PL_SUPER_DIGIT);
+        pl_roll_back(state);
+        return l_insert_token(lstate, T_SUP_NUMBER);
+    }
+    /* [PL_SUB_DIGIT]+ */
+    if(type == PL_SUB_DIGIT)
+    {
+        while(pl_get_next_token(state) == PL_SUB_DIGIT);
+        pl_roll_back(state);
+        return l_insert_token(lstate, T_SUB_NUMBER);
+    }
+    /* [PL_FRACTION] */
+    if(type == PL_FRACTION)
+    {
+        return l_insert_token(lstate, T_NUMBER);
+    }
+    if(type == PL_DIGIT)
+    {
+        while((type = pl_get_next_token(state)) == PL_DIGIT);
+        if(type == PL_FRACTION)
+        {
+            return l_insert_token(lstate, T_NUMBER);
+        }
+        else if(type == PL_SUB_DIGIT)
+        {
+            while(pl_get_next_token(state) == PL_SUB_DIGIT);
+            pl_roll_back(state);
+            return l_insert_token(lstate, T_NUMBER);
+        }
+        else if(type == PL_DEGREE)
+        {
+            type = pl_get_next_token(state);
+            if(type == PL_DIGIT)
+            {
+                while((type = pl_get_next_token(state)) == PL_DIGIT);
+                if(type == PL_DECIMAL)
+                {
+                    goto ANGLE_NUM_DM_STATE;
+                }
+                else if(type == PL_MINUTE)
+                {
+                    type = pl_get_next_token(state);
+                    if(type == PL_DIGIT)
+                    {
+                        while((type = pl_get_next_token(state)) == PL_DIGIT);
+                        if(type == PL_DECIMAL)
+                        {
+                            goto ANGLE_NUM_DMS_STATE;
+                        }
+                        else if(type == PL_SECOND)
+                        {
+                            return l_insert_token(lstate, T_NUMBER);
+                        }
+                        else
+                        {
+                            /* ERROR: expected PL_SECOND */
+                            set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
+                            free(tmp);
+                            return l_insert_token(lstate, T_UNKNOWN);
+                        }
+                    }
+                    else if(type == PL_DECIMAL)
+                    {
+ANGLE_NUM_DMS_STATE:
+                        if((type = pl_get_next_token (state)) != PL_DIGIT)
+                        {
+                            /* ERROR: expected PL_DIGIT */
+                            set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                            free(tmp);
+                            return l_insert_token(lstate, T_UNKNOWN);
+                        }
+                        while((type = pl_get_next_token(state)) == PL_DIGIT);
+                        if(type == PL_SECOND)
+                        {
+                            return l_insert_token(lstate, T_NUMBER);
+                        }
+                        else
+                        {
+                            /* ERROR: expected PL_SECOND */
+                            set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                            free(tmp);
+                            return l_insert_token(lstate, T_UNKNOWN);
+                        }
+                    }
+                    else
+                    {
+                        pl_roll_back(state);
+                        return l_insert_token(lstate, T_NUMBER);
+                    }
+                }
+                else
+                {
+                    /* ERROR: expected PL_MINUTE | PL_DIGIT */
+                    set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                    free(tmp);
+                    return l_insert_token(lstate, T_UNKNOWN);
+                }
+            }
+            else if(type == PL_DECIMAL)
+            {
+ANGLE_NUM_DM_STATE:
+                if((type = pl_get_next_token(state)) != PL_DIGIT)
+                {
+                    /* ERROR: expected PL_DIGIT */
+                    set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                    free(tmp);
+                    return l_insert_token(lstate, T_UNKNOWN);
+                }
+                while((type = pl_get_next_token(state)) == PL_DIGIT);
+                if(type == PL_MINUTE)
+                {
+                    return l_insert_token(lstate, T_NUMBER);
+                }
+                else
+                {
+                    /* ERROR: expected PL_MINUTE */
+                    set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                    free(tmp);
+                    return l_insert_token(lstate, T_UNKNOWN);
+                }
+            }
+            else
+            {
+                return l_insert_token(lstate, T_NUMBER);
+            }
+        }
+        else if(type == PL_DECIMAL)
+        {
+            goto DECIMAL_STATE;
+        }
+        else if(type == PL_HEX)
+        {
+            goto HEX_DEC_STATE;
+        }
+        else
+        {
+            pl_roll_back(state);
+            return l_insert_token(lstate, T_NUMBER);
+        }
+    }
+    if(type == PL_DECIMAL)
+    {
+DECIMAL_STATE:
+        type = pl_get_next_token(state);
+        if(type == PL_DIGIT)
+        {
+            while((type = pl_get_next_token(state)) == PL_DIGIT);
+            if(type == PL_DEGREE)
+            {
+                return l_insert_token(lstate, T_NUMBER);
+            }
+            else if(type == PL_HEX)
+            {
+                goto DECIMAL_HEX_STATE;
+            }
+            else if(type == PL_SUB_DIGIT)
+            {
+                while(pl_get_next_token(state) == PL_SUB_DIGIT);
+                pl_roll_back(state);
+                return l_insert_token(lstate, T_NUMBER);
+            }
+            else
+            {
+                pl_roll_back(state);
+                return l_insert_token(lstate, T_NUMBER);
+            }
+        }
+        else if(type == PL_HEX)
+        {
+            goto DECIMAL_HEX_STATE;
+        }
+        else
+        {
+            /* ERROR: expected PL_DIGIT | PL_HEX */
+            set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+            free(tmp);
+            return l_insert_token(lstate, T_UNKNOWN);
+        }
+    }
+    if(type == PL_HEX)
+    {
+        while((type = pl_get_next_token(state)) == PL_HEX);
+        if(type == PL_DIGIT)
+        {
+HEX_DEC_STATE:
+            while(1)
+            {
+                type = pl_get_next_token(state);
+                if(type == PL_DIGIT || type == PL_HEX)
+                {
+                    continue;
+                }
+                else if(type == PL_DECIMAL)
+                {
+                    goto DECIMAL_HEX_STATE;
+                }
+                else if(type == PL_SUB_DIGIT)
+                {
+                    while(pl_get_next_token(state) == PL_SUB_DIGIT);
+                    pl_roll_back(state);
+                    return l_insert_token(lstate, T_NUMBER);
+                }
+                else
+                {
+                    if(l_check_if_number(lstate))
+                        return l_insert_token(lstate, T_NUMBER);
+                    /* ERROR: expected PL_DECIMAL | PL_DIGIT | PL_HEX */
+                    set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                    free(tmp);
+                    return l_insert_token(lstate, T_UNKNOWN);
+                }
+            }
+        }
+        else if(type == PL_DECIMAL)
+        {
+DECIMAL_HEX_STATE:
+            type = pl_get_next_token(state);
+            if(!(type == PL_DIGIT || type == PL_HEX))
+            {
+                /* ERROR: expected PL_DIGIT | PL_HEX */
+                set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
+                free(tmp);
+                return l_insert_token(lstate, T_UNKNOWN);
+            }
+            while(1)
+            {
+                type = pl_get_next_token(state);
+                if(type == PL_DIGIT || type == PL_HEX)
+                {
+                    continue;
+                }
+                else if(type == PL_SUB_DIGIT)
+                {
+                    while(pl_get_next_token(state) == PL_SUB_DIGIT);
+                    pl_roll_back(state);
+                    return l_insert_token(lstate, T_NUMBER);
+                }
+                else
+                {
+                    pl_roll_back(state);
+                    return l_insert_token(lstate, T_NUMBER);
+                }
+            }
+        }
+        else if(type == PL_SUB_DIGIT)
+        {
+            while(pl_get_next_token(state) == PL_SUB_DIGIT);
+            pl_roll_back(state);
+            if(l_check_if_number(lstate))
+            {
+                /* NUMBER */
+                return l_insert_token(lstate, T_NUMBER);
+            }
+            else
+            {
+                /* VARIABLE */
+                if(l_check_if_function(lstate))
+                {
+                    return l_insert_token(lstate, T_FUNCTION);
+                }
+                else
+                {
+                    return l_insert_token(lstate, T_VARIABLE);
+                }
+            }
+        }
+        else if(type == PL_LETTER)
+        {
+            goto LETTER_STATE;
+        }
+        else
+        {
+            pl_roll_back(state);
+            if(l_check_if_number(lstate))
+            {
+                /* NUMBER */
+                return l_insert_token(lstate, T_NUMBER);
+            }
+            else
+            {
+                /* VARIABLE */
+                if(l_check_if_function(lstate))
+                {
+                    return l_insert_token(lstate, T_FUNCTION);
+                }
+                else
+                {
+                    return l_insert_token(lstate, T_VARIABLE);
+                }
+            }
+        }
+    }
+    if(type == PL_LETTER)
+    {
+LETTER_STATE:
+        while(1)
+        {
+            type = pl_get_next_token(state);
+            if(type == PL_LETTER || type == PL_HEX)
+            {
+                continue;
+            }
+            else if(type == PL_SUB_DIGIT)
+            {
+                while(pl_get_next_token(state) == PL_SUB_DIGIT);
+                pl_roll_back(state);
+                tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
+                if(g_strcmp0(tmp, "mod") == 0)
+                {
+                    return l_insert_token(lstate, T_MOD);
+                }
+                if(g_strcmp0(tmp, "and") == 0)
+                {
+                    return l_insert_token(lstate, T_AND);
+                }
+                if(g_strcmp0(tmp, "or") == 0)
+                {
+                    return l_insert_token(lstate, T_OR);
+                }
+                if(g_strcmp0(tmp, "xor") == 0)
+                {
+                    return l_insert_token(lstate, T_XOR);
+                }
+                if(g_strcmp0(tmp, "not") == 0)
+                {
+                    return l_insert_token(lstate, T_NOT);
+                }
+                if(g_strcmp0(tmp, "in") == 0)
+                {
+                    return l_insert_token(lstate, T_IN);
+                }
+                if(l_check_if_function(lstate))
+                {
+                    return l_insert_token(lstate, T_FUNCTION);
+                }
+                else
+                {
+                    return l_insert_token(lstate, T_VARIABLE);
+                }
+            }
+            else
+            {
+                pl_roll_back(state);
+                tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
+                if(g_strcmp0(tmp, "mod") == 0)
+                {
+                    return l_insert_token(lstate, T_MOD);
+                }
+                if(g_strcmp0(tmp, "and") == 0)
+                {
+                    return l_insert_token(lstate, T_AND);
+                }
+                if(g_strcmp0(tmp, "or") == 0)
+                {
+                    return l_insert_token(lstate, T_OR);
+                }
+                if(g_strcmp0(tmp, "xor") == 0)
+                {
+                    return l_insert_token(lstate, T_XOR);
+                }
+                if(g_strcmp0(tmp, "not") == 0)
+                {
+                    return l_insert_token(lstate, T_NOT);
+                }
+                if(g_strcmp0(tmp, "in") == 0)
+                {
+                    return l_insert_token(lstate, T_IN);
+                }
+                if(l_check_if_function(lstate))
+                {
+                    return l_insert_token(lstate, T_FUNCTION);
+                }
+                else
+                {
+                    return l_insert_token(lstate, T_VARIABLE);
+                }
+            }
+        }
+    }
+    if(type == PL_EOS)
+    {
+        return l_insert_token(lstate, PL_EOS);
+    }
+    /* ERROR: Unexpected token.. X( */
+    set_error(lstate->parent, PARSER_ERR_INVALID, tmp = pl_get_marked_substring(state));
+    free(tmp);
+    return l_insert_token(lstate, T_UNKNOWN);
+}
+
+/* Call l_insert_next_token() as many times as needed to completely tokenize the string. */
+void
+l_insert_all_tokens(LexerState* state)
+{
+    LexerToken* token;
+    while(1)
+    {
+        token = l_insert_next_token(state);
+        assert(token != NULL);
+        if(token->token_type == PL_EOS)
+        {
+            break;
+        }
+    }
+}
+
+/* Create a lexer state from given input string. This will take care of pre-lexer state. */
+LexerState*
+l_create_lexer(const gchar* input, struct parser_state* parent)
+{
+    LexerState* ret;
+    ret = (LexerState *) malloc(sizeof(LexerState));
+    assert(ret != NULL);
+    ret->prelexer = pl_create_scanner(input);
+    ret->tokens = NULL;
+    ret->token_count = 0;
+    ret->next_token = 0;
+    ret->parent = parent;
+    return ret;
+}
+
+/* Destroy lexer state and free memory. */
+void
+l_destroy_lexer(LexerState* state)
+{
+    int l;
+    pl_destroy_scanner(state->prelexer);
+    for(l = 0; l < state->token_count; l++)
+    {
+        free(state->tokens[l].string);
+    }
+    free(state->tokens);
+    free(state);
+}
+
+/* Get next token interface. Will be called by parser to get pointer to next token in token stream. */
+LexerToken*
+l_get_next_token(LexerState* state)
+{
+    /* Return PL_EOS token after token stream reaches to its end. */
+    if(state->next_token >= state->token_count)
+        return &state->tokens[state->token_count - 1];
+    return &state->tokens[state->next_token++];
+}
+
+/* Roll back one lexer token. */
+void
+l_roll_back(LexerState* state)
+{
+    if(state->next_token > 0)
+        state->next_token--;
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/1.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/1.html new file mode 100644 index 0000000..bfb92ce --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/1.html @@ -0,0 +1,441 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
/*
+ * Copyright (C) 2009 Rich Burridge
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+#include <locale.h>
+
+#include "mp-equation.h"
+#include "mp-serializer.h"
+
+#define MAXLINE 1024
+
+static MpSerializer *result_serializer;
+
+static void
+solve(const char *equation)
+{
+    int ret;
+    MPEquationOptions options;
+    MPNumber z = mp_new();
+    gchar *result_str = NULL;
+
+    memset(&options, 0, sizeof(options));
+    options.base = 10;
+    options.wordlen = 32;
+    options.angle_units = MP_DEGREES;
+
+    ret = mp_equation_parse(equation, &options, &z, NULL);
+
+    if (ret == PARSER_ERR_MP)
+        fprintf(stderr, "Error %s\n", mp_get_error());
+    else if (ret)
+        fprintf(stderr, "Error %d\n", ret);
+    else {
+        result_str = mp_serializer_to_string(result_serializer, &z);
+        printf("%s\n", result_str);
+    }
+    g_free(result_str);
+    mp_clear(&z);
+}
+
+/* Adjust user input equation string before solving it. */
+static void
+str_adjust(char *str)
+{
+    int i, j = 0;
+
+    str[strlen(str)-1] = '\0';        /* Remove newline at end of string. */
+    for (i = 0; str[i] != '\0'; i++) {        /* Remove whitespace. */
+        if (str[i] != ' ' && str[i] != '\t')
+            str[j++] = str[i];
+    }
+    str[j] = '\0';
+    if (j > 0 && str[j-1] == '=')     /* Remove trailing '=' (if present). */
+        str[j-1] = '\0';
+}
+
+int
+main(void)
+{
+    char *equation, *line;
+
+    /* Seed random number generator. */
+    srand48((long) time((time_t *) 0));
+
+    setlocale(LC_ALL, "");
+
+    result_serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9);
+
+    equation = (char *) malloc(MAXLINE * sizeof(char));
+    while (1) {
+        printf("> ");
+        line = fgets(equation, MAXLINE, stdin);
+
+        if (line != NULL)
+            str_adjust(equation);
+
+        if (line == NULL || strcmp(equation, "exit") == 0 || strcmp(equation, "quit") == 0 || strlen(equation) == 0)
+            break;
+
+        solve(equation);
+    }
+    free(equation);
+
+    return 0;
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/10.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/10.html new file mode 100644 index 0000000..b6d5629 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/10.html @@ -0,0 +1,2227 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+969
+970
+971
#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "parser.h"
+#include "parserfunc.h"
+
+/* Register error variables in ParserState structure. */
+void
+set_error(ParserState* state, gint errorno, const gchar *token)
+{
+    state->error = errorno;
+    if(token)
+        state->error_token = strdup(token);
+}
+
+/* Unused function pointer. This won't be called anytime. */
+void*
+pf_none(ParseNode* self)
+{
+    return NULL;
+}
+
+/* Set variable. */
+void*
+pf_set_var(ParseNode* self)
+{
+    MPNumber* val;
+    val = (MPNumber *) (*(self->right->evaluate))(self->right);
+    if(!val || !(self->state->set_variable))
+    {
+        if(val)
+            mp_free(val);
+        return NULL;
+    }
+    (*(self->state->set_variable))(self->state, self->left->token->string, val);
+    return val;
+}
+
+/* Converts Number from one unit to other. */
+void*
+pf_convert_number(ParseNode* self)
+{
+    gchar* from;
+    gchar* to;
+    gint free_from = 0;
+    gint free_to = 0;
+    MPNumber tmp = mp_new();
+    MPNumber* ans = mp_new_ptr();
+    if(self->left->value)
+    {
+        from = (gchar*) self->left->value;
+        free_from = 1;
+    }
+    else
+        from = self->left->token->string;
+    if(self->right->value)
+    {
+        to = (gchar*) self->right->value;
+        free_to = 1;
+    }
+    else
+        to = self->right->token->string;
+
+    if(mp_set_from_string(self->left->left->token->string, self->state->options->base, &tmp) != 0)
+    {
+        mp_free(ans);
+        ans = NULL;
+        goto END_PF_CONVERT_NUMBER;
+    }
+    if(!(self->state->convert))
+    {
+        mp_free(ans);
+        ans = NULL;
+        goto END_PF_CONVERT_NUMBER;
+    }
+    if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
+    {
+        set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
+        mp_free(ans);
+        ans = NULL;
+    }
+END_PF_CONVERT_NUMBER:
+    if(free_from)
+    {
+        g_free(self->left->value);
+        self->left->value = NULL;
+    }
+    if(free_to)
+    {
+        g_free(self->right->value);
+        self->right->value = NULL;
+    }
+    mp_clear(&tmp);
+    return ans;
+}
+
+/* Conversion rate. */
+void*
+pf_convert_1(ParseNode* self )
+{
+    gchar* from;
+    gchar* to;
+    gint free_from = 0;
+    gint free_to = 0;
+    MPNumber tmp = mp_new();
+    MPNumber* ans = mp_new_ptr();
+    if(self->left->value)
+    {
+        from = (gchar*) self->left->value;
+        free_from = 1;
+    }
+    else
+        from = self->left->token->string;
+    if(self->right->value)
+    {
+        to = (gchar*) self->right->value;
+        free_to = 1;
+    }
+    else
+        to = self->right->token->string;
+    mp_set_from_integer(1, &tmp);
+    if(!(self->state->convert))
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
+    {
+        set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
+        mp_free(ans);
+        ans = NULL;
+    }
+    if(free_from)
+    {
+        g_free(self->left->value);
+        self->left->value = NULL;
+    }
+    if(free_to)
+    {
+        g_free(self->right->value);
+        self->right->value = NULL;
+    }
+    mp_clear(&tmp);
+    return ans;
+}
+
+/* Join source unit and power. */
+gchar*
+pf_make_unit(gchar* source, gchar* power)
+{
+    return g_strjoin(NULL, source, power, NULL);
+}
+
+static gchar *
+utf8_next_char(const gchar *c)
+{
+    c++;
+    while((*c & 0xC0) == 0x80)
+        c++;
+    return(gchar *) c;
+}
+
+/* Get value of variable. */
+void*
+pf_get_variable(ParseNode* self)
+{
+    gint result = 0;
+
+    const gchar *c, *next;
+    gchar *buffer;
+    MPNumber value = mp_new();
+
+    MPNumber t = mp_new();
+    MPNumber* ans = mp_new_ptr();
+
+    if(!(self->state->get_variable))
+    {
+        free(ans);
+        return NULL;
+    }
+
+    /* If defined, then get the variable */
+    if((*(self->state->get_variable))(self->state, self->token->string, ans))
+    {
+        return ans;
+    }
+
+    /* If has more than one character then assume a multiplication of variables */
+    if(utf8_next_char(self->token->string)[0] != '\0')
+    {
+        result = 1;
+        buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
+        mp_set_from_integer(1, &value);
+        for(c = self->token->string; *c != '\0'; c = next)
+        {
+            next = utf8_next_char(c);
+            snprintf(buffer, next - c + 1, "%s", c);
+            if(!(*(self->state->get_variable))(self->state, buffer, &t))
+            {
+                result = 0;
+                break;
+            }
+            mp_multiply(&value, &t, &value);
+        }
+        free(buffer);
+        if(result)
+            mp_set_from_mp(&value, ans);
+    }
+    if(!result)
+    {
+        free (ans);
+        ans = NULL;
+        set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
+    }
+    return ans;
+}
+
+/* Get value of variable with power. */
+void*
+pf_get_variable_with_power(ParseNode* self)
+{
+    gint result = 0;
+    gint pow;
+
+    const gchar *c, *next;
+    gchar *buffer;
+    MPNumber value = mp_new();
+
+    MPNumber t = mp_new();
+    MPNumber* ans = mp_new_ptr();
+    pow = super_atoi(((LexerToken*) self->value)->string);
+
+    /* No need to free the memory. It is allocated and freed somewhere else. */
+    self->value = NULL;
+
+    if(!(self->state->get_variable))
+    {
+        free(ans);
+        return NULL;
+    }
+
+    /* If defined, then get the variable */
+    if((*(self->state->get_variable))(self->state, self->token->string, ans))
+    {
+        mp_xpowy_integer(ans, pow, ans);
+        return ans;
+    }
+
+    /* If has more than one character then assume a multiplication of variables */
+    if(utf8_next_char(self->token->string)[0] != '\0')
+    {
+        result = 1;
+        buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
+        mp_set_from_integer(1, &value);
+        for(c = self->token->string; *c != '\0'; c = next)
+        {
+            next = utf8_next_char(c);
+            snprintf(buffer, next - c + 1, "%s", c);
+            if(!(*(self->state->get_variable))(self->state, buffer, &t))
+            {
+                result = 0;
+                break;
+            }
+
+            /* If last term do power */
+            if(*next == '\0')
+                mp_xpowy_integer(&t, pow, &t);
+            mp_multiply(&value, &t, &value);
+        }
+        free(buffer);
+        if(result)
+            mp_set_from_mp(&value, ans);
+    }
+    if(!result)
+    {
+        free(ans);
+        ans = NULL;
+        set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
+    }
+    return ans;
+}
+
+/* Apply function on child. */
+void*
+pf_apply_func(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!(self->state->get_function))
+    {
+        free(val);
+        free(ans);
+        return NULL;
+    }
+    if(!val)
+    {
+        free(ans);
+        return NULL;
+    }
+    if(!(*(self->state->get_function))(self->state, self->token->string, val, ans))
+    {
+        free(val);
+        free(ans);
+        set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+        return NULL;
+    }
+    free(val);
+    return ans;
+}
+
+/* Apply function with +ve power. */
+void*
+pf_apply_func_with_power(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* tmp = mp_new_ptr();
+    MPNumber* ans = mp_new_ptr();
+    gint pow;
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!(self->state->get_function))
+    {
+        mp_free(tmp);
+        mp_free(ans);
+        mp_free(val);
+        self->value = NULL;
+        return NULL;
+    }
+    if(!val)
+    {
+        mp_free(tmp);
+        mp_free(ans);
+        self->value = NULL;
+        return NULL;
+    }
+    if(!(*(self->state->get_function))(self->state, self->token->string, val, tmp))
+    {
+        mp_free(tmp);
+        mp_free(ans);
+        mp_free(val);
+        self->value = NULL;
+        set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+        return NULL;
+    }
+    pow = super_atoi(((LexerToken*) self->value)->string);
+    mp_xpowy_integer(tmp, pow, ans);
+    mp_free(val);
+    mp_free(tmp);
+    self->value = NULL;
+    return ans;
+}
+
+/* Apply function with -ve power. */
+void*
+pf_apply_func_with_npower(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* tmp = mp_new_ptr();
+    MPNumber* ans = mp_new_ptr();
+    gint pow;
+    gchar* inv_name;
+    inv_name = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string) + strlen("⁻¹") + 1);
+    strcpy(inv_name, self->token->string);
+    strcat(inv_name, "⁻¹");
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(tmp);
+        free(inv_name);
+        mp_free(ans);
+        self->value = NULL;
+        return NULL;
+    }
+    if(!(self->state->get_function))
+    {
+        mp_free(tmp);
+        mp_free(ans);
+        free(inv_name);
+        self->value = NULL;
+        return NULL;
+    }
+    if(!(*(self->state->get_function))(self->state, inv_name, val, tmp))
+    {
+        mp_free(tmp);
+        mp_free(ans);
+        mp_free(val);
+        free(inv_name);
+        self->value = NULL;
+        set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+        return NULL;
+    }
+    pow = super_atoi(((LexerToken*) self->value)->string);
+    mp_xpowy_integer(tmp, -pow, ans);
+    mp_free(val);
+    mp_free(tmp);
+    free(inv_name);
+    self->value = NULL;
+    return ans;
+}
+
+/* Find nth root of child. */
+void*
+pf_do_nth_root(ParseNode* self)
+{
+    MPNumber* val;
+    gint pow;
+    MPNumber* ans = mp_new_ptr();
+    pow = sub_atoi(((LexerToken*) self->value)->string);
+    self->value = NULL;
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_root(val, pow, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Find sqrt of child. */
+void*
+pf_do_sqrt(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        free(ans);
+        return NULL;
+    }
+    mp_sqrt(val, ans);
+    free(val);
+    return ans;
+}
+
+/* Find 3rd root of child. */
+void*
+pf_do_root_3(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_root(val, 3, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Find 4th root of child. */
+void*
+pf_do_root_4(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_root(val, 4, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Apply floor function. */
+void*
+pf_do_floor(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_floor(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Apply ceiling function. */
+void* pf_do_ceiling (ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_ceiling(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Round off. */
+void*
+pf_do_round(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_round(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Fraction. */
+void*
+pf_do_fraction(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_fractional_part(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Absolute value. */
+void*
+pf_do_abs(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_abs(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Find x^y for x and y being MPNumber. */
+void*
+pf_do_x_pow_y(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* pow;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->left->evaluate))(self->left);
+    pow = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val || !pow)
+    {
+        if(val)
+            mp_free(val);
+        if(pow)
+            mp_free(pow);
+        mp_free(ans);
+        return NULL;
+    }
+    mp_xpowy(val, pow, ans);
+    mp_free(val);
+    mp_free(pow);
+    return ans;
+}
+
+/* Find x^y for MPNumber x and integer y. */
+void*
+pf_do_x_pow_y_int(ParseNode* self)
+{
+    MPNumber* val;
+    long pow;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->left->evaluate))(self->left);
+
+    if(!val)
+    {
+        val = mp_new_ptr();
+        mp_set_from_integer(super_atoi(self->left->token->string), val);
+    }
+
+    if (self->right->token != NULL)
+    {
+        pow = super_atoi(self->right->token->string);
+    }
+    else
+    {
+        MPNumber* aux = (MPNumber*) (*(self->right->evaluate))(self->right);
+        pow = mp_to_integer(aux);
+        mp_free(aux);
+    }
+
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_xpowy_integer(val, pow, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Find factorial. */
+void*
+pf_do_factorial(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_factorial(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Apply unary minus. */
+void*
+pf_unary_minus(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_invert_sign(val, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* Divide. */
+void*
+pf_do_divide(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        mp_free(ans);
+        return NULL;
+    }
+    mp_divide(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* Modulus. */
+void*
+pf_do_mod(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        mp_free(ans);
+        return NULL;
+    }
+    if (self->left->evaluate == pf_do_x_pow_y)
+    {
+        MPNumber* base_value = (MPNumber*) (*(self->left->left->evaluate))(self->left->left);
+        MPNumber* exponent = (MPNumber*) (*(self->left->right->evaluate))(self->left->right);
+        if(!base_value || !exponent)
+        {
+            if(base_value)
+                mp_free(base_value);
+            if(exponent)
+                mp_free(exponent);
+            mp_free(ans);
+            return NULL;
+        }
+        mp_modular_exponentiation(base_value, exponent, right, ans);
+        mp_free(base_value);
+        mp_free(exponent);
+    }
+    else
+        mp_modulus_divide(left, right, ans);
+
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* Multiply two numbers. */
+void*
+pf_do_multiply(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        mp_free(ans);
+        return NULL;
+    }
+    mp_multiply(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* Subtract two numbers. */
+void*
+pf_do_subtract(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        free(ans);
+        return NULL;
+    }
+    mp_subtract(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* Add two numbers. */
+void*
+pf_do_add(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        free(ans);
+        return NULL;
+    }
+    mp_add(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* Add (x) Percentage to value. */
+void*
+pf_do_add_percent(ParseNode* self)
+{
+    MPNumber* ans = mp_new_ptr();
+    MPNumber* val;
+    MPNumber* per;
+    val = (MPNumber*) (*(self->left->evaluate))(self->left);
+    per = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val || !per)
+    {
+        if(val)
+            mp_free(val);
+        if(per)
+            mp_free(per);
+        mp_free(ans);
+        return NULL;
+    }
+    mp_add_integer(per, 100, per);
+    mp_divide_integer(per, 100, per);
+    mp_multiply(val, per, ans);
+    mp_free(val);
+    mp_free(per);
+    return ans;
+}
+
+/* Subtract (x) Percentage to value. */
+void*
+pf_do_subtract_percent(ParseNode* self)
+{
+    MPNumber* ans = mp_new_ptr();
+    MPNumber* val;
+    MPNumber* per;
+    val = (MPNumber*) (*(self->left->evaluate))(self->left);
+    per = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val || !per)
+    {
+        if(val)
+            mp_free(val);
+        if(per)
+            mp_free(per);
+        free(ans);
+        return NULL;
+    }
+    mp_add_integer(per, -100, per);
+    mp_divide_integer(per, -100, per);
+    mp_multiply(val, per, ans);
+    mp_free(val);
+    mp_free(per);
+    return ans;
+}
+
+/* Converts a constant into percentage. */
+void*
+pf_do_percent(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    mp_divide_integer(val, 100, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* NOT. */
+void*
+pf_do_not(ParseNode* self)
+{
+    MPNumber* val;
+    MPNumber* ans = mp_new_ptr();
+    val = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!val)
+    {
+        mp_free(ans);
+        return NULL;
+    }
+    if(!mp_is_overflow(val, self->state->options->wordlen))
+    {
+        set_error(self->state, PARSER_ERR_OVERFLOW, NULL);
+        mp_free(ans);
+        mp_free(val);
+        return NULL;
+    }
+    mp_not(val, self->state->options->wordlen, ans);
+    mp_free(val);
+    return ans;
+}
+
+/* AND. */
+void*
+pf_do_and(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        mp_free(ans);
+        return NULL;
+    }
+    mp_and(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* OR. */
+void*
+pf_do_or(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        mp_free(ans);
+        return NULL;
+    }
+    mp_or(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* XOR. */
+void*
+pf_do_xor(ParseNode* self)
+{
+    MPNumber* left;
+    MPNumber* right;
+    MPNumber* ans = mp_new_ptr();
+    left = (MPNumber*) (*(self->left->evaluate))(self->left);
+    right = (MPNumber*) (*(self->right->evaluate))(self->right);
+    if(!left || !right)
+    {
+        if(left)
+            mp_free(left);
+        if(right)
+            mp_free(right);
+        free(ans);
+        return NULL;
+    }
+    mp_xor(left, right, ans);
+    mp_free(left);
+    mp_free(right);
+    return ans;
+}
+
+/* Constant value. Convert into MPNumber and return. */
+void*
+pf_constant(ParseNode* self)
+{
+    MPNumber* ans = mp_new_ptr();
+    if(mp_set_from_string(self->token->string, self->state->options->base, ans) != 0)
+    {
+        /* This should never happen, as l_check_if_number() has already passed the string once. */
+        /* If the code reaches this point, something is really wrong. X( */
+        mp_free(ans);
+        set_error(self->state, PARSER_ERR_INVALID, self->token->string);
+        return NULL;
+    }
+    return ans;
+}
+
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/11.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/11.html new file mode 100644 index 0000000..4c5c268 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/11.html @@ -0,0 +1,773 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
/*
+ * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2011 Robert Ancell.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <string.h>
+#include <glib/gi18n.h> // FIXME: Move out of here
+
+#include "unit-manager.h"
+#include "currency-manager.h" // FIXME: Move out of here
+
+struct UnitManagerPrivate
+{
+    GList *categories;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (UnitManager, unit_manager, G_TYPE_OBJECT);
+
+static UnitManager *default_unit_manager = NULL;
+
+static gint
+compare_currencies(gconstpointer a, gconstpointer b)
+{
+    return strcmp(currency_get_display_name((Currency *)a), currency_get_display_name((Currency *)b));
+}
+
+UnitManager *
+unit_manager_get_default(void)
+{
+    UnitCategory *category = NULL;
+    GList *currencies, *iter;
+    int i;
+    const struct
+    {
+        gchar *category;
+        gchar *name;
+        gchar *display_name;
+        gchar *format;
+        gchar *from_function;
+        gchar *to_function;
+        gchar *symbols;
+    } units[] =
+    {
+        /* FIXME: Approximations of 1/(units in a circle), therefore, 360 deg != 400 grads */
+        {"angle",    "degree",              N_("Degrees"),           NC_("unit-format", "%s degrees"),  "π*x/180",            "180x/π",         NC_("unit-symbols", "degree,degrees,deg")},
+        {NULL,       "radian",              N_("Radians"),           NC_("unit-format", "%s radians"),  "x",                  "x",              NC_("unit-symbols", "radian,radians,rad")},
+        {NULL,       "gradian",             N_("Gradians"),          NC_("unit-format", "%s gradians"), "π*x/200",            "200x/π",         NC_("unit-symbols", "gradian,gradians,grad")},
+        {"length",   "parsec",              N_("Parsecs"),           NC_("unit-format", "%s pc"),       "30857000000000000x", "x/30857000000000000", NC_("unit-symbols", "parsec,parsecs,pc")},
+        {NULL,       "lightyear",           N_("Light Years"),       NC_("unit-format", "%s ly"),       "9460730472580800x",  "x/9460730472580800",  NC_("unit-symbols", "lightyear,lightyears,ly")},
+        {NULL,       "astronomical-unit",   N_("Astronomical Units"), NC_("unit-format", "%s au"),      "149597870700x",      "x/149597870700", NC_("unit-symbols", "au")},
+        {NULL,       "nautical-mile",       N_("Nautical Miles"),    NC_("unit-format", "%s nmi"),      "1852x",              "x/1852",         NC_("unit-symbols", "nmi")},
+        {NULL,       "mile",                N_("Miles"),             NC_("unit-format", "%s mi"),       "1609.344x",          "x/1609.344",     NC_("unit-symbols", "mile,miles,mi")},
+        {NULL,       "kilometer",           N_("Kilometers"),        NC_("unit-format", "%s km"),       "1000x",              "x/1000",         NC_("unit-symbols", "kilometer,kilometers,km,kms")},
+        {NULL,       "cable",               N_("Cables"),            NC_("unit-format", "%s cb"),       "219.456x",           "x/219.456",      NC_("unit-symbols", "cable,cables,cb")},
+        {NULL,       "fathom",              N_("Fathoms"),           NC_("unit-format", "%s ftm"),      "1.8288x",            "x/1.8288",       NC_("unit-symbols", "fathom,fathoms,ftm")},
+        {NULL,       "meter",               N_("Meters"),            NC_("unit-format", "%s m"),        "x",                  "x",              NC_("unit-symbols", "meter,meters,m")},
+        {NULL,       "yard",                N_("Yards"),             NC_("unit-format", "%s yd"),       "0.9144x",            "x/0.9144",       NC_("unit-symbols", "yard,yards,yd")},
+        {NULL,       "foot",                N_("Feet"),              NC_("unit-format", "%s ft"),       "0.3048x",            "x/0.3048",       NC_("unit-symbols", "foot,feet,ft")},
+        {NULL,       "inch",                N_("Inches"),            NC_("unit-format", "%s in"),       "0.0254x",            "x/0.0254",       NC_("unit-symbols", "inch,inches,in")},
+        {NULL,       "centimeter",          N_("Centimeters"),       NC_("unit-format", "%s cm"),       "x/100",              "100x",           NC_("unit-symbols", "centimeter,centimeters,cm,cms")},
+        {NULL,       "millimeter",          N_("Millimeters"),       NC_("unit-format", "%s mm"),       "x/1000",             "1000x",          NC_("unit-symbols", "millimeter,millimeters,mm")},
+        {NULL,       "micrometer",          N_("Micrometers"),       NC_("unit-format", "%s μm"),       "x/1000000",          "1000000x",       NC_("unit-symbols", "micrometer,micrometers,um")},
+        {NULL,       "nanometer",           N_("Nanometers"),        NC_("unit-format", "%s nm"),       "x/1000000000",       "1000000000x",    NC_("unit-symbols", "nanometer,nanometers,nm")},
+        {"area",     "hectare",             N_("Hectares"),          NC_("unit-format", "%s ha"),       "10000x",             "x/10000",        NC_("unit-symbols", "hectare,hectares,ha")},
+        {NULL,       "acre",                N_("Acres"),             NC_("unit-format", "%s acres"),    "4046.8564224x",      "x/4046.8564224", NC_("unit-symbols", "acre,acres")},
+        {NULL,       "square-meter",        N_("Square Meters"),      NC_("unit-format", "%s m²"),       "x",                  "x",              NC_("unit-symbols", "m²")},
+        {NULL,       "square-centimeter",   N_("Square Centimeters"), NC_("unit-format", "%s cm²"),      "0.0001x",            "10000x",         NC_("unit-symbols", "cm²")},
+        {NULL,       "square-millimeter",   N_("Square Millimeters"), NC_("unit-format", "%s mm²"),      "0.000001x",          "1000000x",       NC_("unit-symbols", "mm²")},
+        {"volume",   "cubic-meter",         N_("Cubic Meters"),      NC_("unit-format", "%s m³"),       "1000x",              "x/1000",         NC_("unit-symbols", "m³")},
+        {NULL,       "gallon",              N_("Gallons"),           NC_("unit-format", "%s gal"),      "3.785412x",          "x/3.785412",     NC_("unit-symbols", "gallon,gallons,gal")},
+        {NULL,       "litre",               N_("Litres"),            NC_("unit-format", "%s L"),        "x",                  "x",              NC_("unit-symbols", "litre,litres,liter,liters,L")},
+        {NULL,       "quart",               N_("Quarts"),            NC_("unit-format", "%s qt"),       "0.9463529x",         "x/0.9463529",    NC_("unit-symbols", "quart,quarts,qt")},
+        {NULL,       "pint",                N_("Pints"),             NC_("unit-format", "%s pt"),       "0.4731765x",         "x/0.4731765",    NC_("unit-symbols", "pint,pints,pt")},
+        {NULL,       "millilitre",          N_("Millilitres"),       NC_("unit-format", "%s mL"),       "0.001x",             "1000x",          NC_("unit-symbols", "millilitre,millilitres,milliliter,milliliters,mL,cm³")},
+        {NULL,       "microlitre",          N_("Microlitres"),       NC_("unit-format", "%s μL"),       "0.000001x",          "1000000x",       NC_("unit-symbols", "mm³,μL,uL")},
+        {"weight",   "tonne",               N_("Tonnes"),            NC_("unit-format", "%s T"),        "1000x",             "x/1000",          NC_("unit-symbols", "tonne,tonnes")},
+        {NULL,       "kilograms",           N_("Kilograms"),         NC_("unit-format", "%s kg"),       "x",                  "x",              NC_("unit-symbols", "kilogram,kilograms,kilogramme,kilogrammes,kg,kgs")},
+        {NULL,       "pound",               N_("Pounds"),            NC_("unit-format", "%s lb"),       "0.45359237x",        "x/0.45359237",   NC_("unit-symbols", "pound,pounds,lb")},
+        {NULL,       "ounce",               N_("Ounces"),            NC_("unit-format", "%s oz"),       "0.02834952x",        "x/0.02834952",   NC_("unit-symbols", "ounce,ounces,oz")},
+        {NULL,       "gram",                N_("Grams"),             NC_("unit-format", "%s g"),        "0.001x",             "1000x",          NC_("unit-symbols", "gram,grams,gramme,grammes,g")},
+        {"duration", "year",                N_("Years"),             NC_("unit-format", "%s years"),    "31557600x",          "x/31557600",     NC_("unit-symbols", "year,years")},
+        {NULL,       "day",                 N_("Days"),              NC_("unit-format", "%s days"),     "86400x",             "x/86400",        NC_("unit-symbols", "day,days")},
+        {NULL,       "hour",                N_("Hours"),             NC_("unit-format", "%s hours"),    "3600x",              "x/3600",         NC_("unit-symbols", "hour,hours")},
+        {NULL,       "minute",              N_("Minutes"),           NC_("unit-format", "%s minutes"),  "60x",                "x/60",           NC_("unit-symbols", "minute,minutes")},
+        {NULL,       "second",              N_("Seconds"),           NC_("unit-format", "%s s"),        "x",                  "x",              NC_("unit-symbols", "second,seconds,s")},
+        {NULL,       "millisecond",         N_("Milliseconds"),      NC_("unit-format", "%s ms"),       "0.001x",             "1000x",          NC_("unit-symbols", "millisecond,milliseconds,ms")},
+        {NULL,       "microsecond",         N_("Microseconds"),      NC_("unit-format", "%s μs"),       "0.000001x",          "1000000x",       NC_("unit-symbols", "microsecond,microseconds,us,μs")},
+        {"temperature", "degree-celcius",   N_("Celsius"),           NC_("unit-format", "%s ˚C"),       "x+273.15",           "x-273.15",       NC_("unit-symbols", "degC,˚C")},
+        {NULL,          "degree-farenheit", N_("Farenheit"),         NC_("unit-format", "%s ˚F"),       "(x+459.67)*5/9",     "x*9/5-459.67",   NC_("unit-symbols", "degF,˚F")},
+        {NULL,          "degree-kelvin",    N_("Kelvin"),            NC_("unit-format", "%s K"),        "x",                  "x",              NC_("unit-symbols", "K")},
+        {NULL,          "degree-rankine",   N_("Rankine"),           NC_("unit-format", "%s ˚R"),       "x*5/9",              "x*9/5",          NC_("unit-symbols", "degR,˚R,˚Ra")},
+        { NULL, NULL, NULL, NULL, NULL, NULL }
+    };
+
+    if (default_unit_manager)
+        return default_unit_manager;
+
+    default_unit_manager = g_object_new(unit_manager_get_type(), NULL);
+
+    unit_manager_add_category(default_unit_manager, "angle",    _("Angle"));
+    unit_manager_add_category(default_unit_manager, "length",   _("Length"));
+    unit_manager_add_category(default_unit_manager, "area",     _("Area"));
+    unit_manager_add_category(default_unit_manager, "volume",   _("Volume"));
+    unit_manager_add_category(default_unit_manager, "weight",   _("Weight"));
+    unit_manager_add_category(default_unit_manager, "duration", _("Duration"));
+    unit_manager_add_category(default_unit_manager, "temperature", _("Temperature"));
+
+    for (i = 0; units[i].name; i++) {
+        if (units[i].category)
+            category = unit_manager_get_category(default_unit_manager, units[i].category);
+        unit_category_add_unit(category, unit_new(units[i].name,
+                                                  _(units[i].display_name),
+                                                  g_dpgettext2(NULL, "unit-format", units[i].format),
+                                                  units[i].from_function, units[i].to_function,
+                                                  g_dpgettext2(NULL, "unit-symbols", units[i].symbols)));
+    }
+
+    category = unit_manager_add_category(default_unit_manager, "currency", _("Currency"));
+    currencies = g_list_copy(currency_manager_get_currencies(currency_manager_get_default()));
+    currencies = g_list_sort(currencies, compare_currencies);
+    for (iter = currencies; iter; iter = iter->next)
+    {
+        Currency *currency = iter->data;
+        gchar *format;
+        Unit *unit;
+
+        /* Translators: result of currency conversion, %s is the symbol, %%s is the placeholder for amount, i.e.: USD100 */
+        format = g_strdup_printf(_("%s%%s"), currency_get_symbol(currency));
+        unit = unit_new(currency_get_name(currency), currency_get_display_name(currency), format, NULL, NULL, currency_get_name(currency));
+        g_free(format);
+
+        unit_category_add_unit(category, unit);
+    }
+    g_list_free(currencies);
+
+    return default_unit_manager;
+}
+
+UnitCategory *
+unit_manager_add_category(UnitManager *manager, const gchar *name, const gchar *display_name)
+{
+    UnitCategory *category;
+
+    g_return_val_if_fail(manager != NULL, NULL);
+    g_return_val_if_fail(name != NULL, NULL);
+    g_return_val_if_fail(display_name != NULL, NULL);
+    g_return_val_if_fail(unit_manager_get_category(manager, name) == NULL, NULL);
+
+    category = unit_category_new(name, display_name);
+    manager->priv->categories = g_list_append(manager->priv->categories, category);
+
+    return category;
+}
+
+const GList *
+unit_manager_get_categories(UnitManager *manager)
+{
+    g_return_val_if_fail(manager != NULL, NULL);
+    return manager->priv->categories;
+}
+
+UnitCategory *
+unit_manager_get_category(UnitManager *manager, const gchar *category)
+{
+    GList *iter;
+
+    g_return_val_if_fail(manager != NULL, NULL);
+    g_return_val_if_fail(category != NULL, NULL);
+
+    for (iter = manager->priv->categories; iter; iter = iter->next) {
+        UnitCategory *c = iter->data;
+        if (strcmp(unit_category_get_name(c), category) == 0)
+            return c;
+    }
+
+    return NULL;
+}
+
+Unit *
+unit_manager_get_unit_by_name(UnitManager *manager, const gchar *name)
+{
+    GList *iter;
+    Unit *u;
+
+    g_return_val_if_fail(manager != NULL, NULL);
+    g_return_val_if_fail(name != NULL, NULL);
+
+    for (iter = manager->priv->categories; iter; iter = iter->next) {
+        UnitCategory *c = iter->data;
+        u = unit_category_get_unit_by_name(c, name);
+        if (u)
+            return u;
+    }
+
+    return NULL;
+}
+
+Unit *
+unit_manager_get_unit_by_symbol(UnitManager *manager, const gchar *symbol)
+{
+    GList *iter;
+    Unit *u;
+
+    g_return_val_if_fail(manager != NULL, NULL);
+    g_return_val_if_fail(symbol != NULL, NULL);
+
+    for (iter = manager->priv->categories; iter; iter = iter->next) {
+        UnitCategory *c = iter->data;
+        u = unit_category_get_unit_by_symbol(c, symbol);
+        if (u)
+            return u;
+    }
+
+    return NULL;
+}
+
+gboolean
+unit_manager_convert_by_symbol(UnitManager *manager, const MPNumber *x, const char *x_symbol, const char *z_symbol, MPNumber *z)
+{
+    GList *iter;
+
+    g_return_val_if_fail(manager != NULL, FALSE);
+    g_return_val_if_fail(x != NULL, FALSE);
+    g_return_val_if_fail(x_symbol != NULL, FALSE);
+    g_return_val_if_fail(z_symbol != NULL, FALSE);
+    g_return_val_if_fail(z != NULL, FALSE);
+
+    for (iter = manager->priv->categories; iter; iter = iter->next) {
+        UnitCategory *c = iter->data;
+        Unit *x_units, *z_units;
+
+        x_units = unit_category_get_unit_by_symbol(c, x_symbol);
+        z_units = unit_category_get_unit_by_symbol(c, z_symbol);
+        if (x_units && z_units && unit_category_convert(c, x, x_units, z_units, z))
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static void
+unit_manager_class_init(UnitManagerClass *klass)
+{
+}
+
+static void
+unit_manager_init(UnitManager *manager)
+{
+    manager->priv = unit_manager_get_instance_private (manager);
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/2.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/2.html new file mode 100644 index 0000000..acd466b --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/2.html @@ -0,0 +1,2511 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
#include <gio/gio.h>
+
+#if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+# define SECTION __attribute__ ((section (".gresource.calculator"), aligned (8)))
+#else
+# define SECTION
+#endif
+
+static const SECTION union { const guint8 data[14931]; const double alignment; void * const ptr;}  calculator_resource_data = { {<--- union member 'Anonymous0::alignment' is never used.<--- union member 'Anonymous0::ptr' is never used.
+  0107, 0126, 0141, 0162, 0151, 0141, 0156, 0164, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0030, 0000, 0000, 0000, 0160, 0001, 0000, 0000, 0000, 0000, 0000, 0050, 0014, 0000, 0000, 0000, 
+  0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 0003, 0000, 0000, 0000, 
+  0004, 0000, 0000, 0000, 0005, 0000, 0000, 0000, 0006, 0000, 0000, 0000, 0007, 0000, 0000, 0000, 
+  0010, 0000, 0000, 0000, 0012, 0000, 0000, 0000, 0012, 0000, 0000, 0000, 0013, 0000, 0000, 0000, 
+  0205, 0246, 0306, 0274, 0003, 0000, 0000, 0000, 0160, 0001, 0000, 0000, 0016, 0000, 0166, 0000, 
+  0200, 0001, 0000, 0000, 0130, 0007, 0000, 0000, 0145, 0112, 0236, 0026, 0003, 0000, 0000, 0000, 
+  0130, 0007, 0000, 0000, 0023, 0000, 0166, 0000, 0160, 0007, 0000, 0000, 0175, 0017, 0000, 0000, 
+  0021, 0233, 0356, 0164, 0003, 0000, 0000, 0000, 0175, 0017, 0000, 0000, 0020, 0000, 0166, 0000, 
+  0220, 0017, 0000, 0000, 0361, 0023, 0000, 0000, 0047, 0275, 0327, 0315, 0012, 0000, 0000, 0000, 
+  0361, 0023, 0000, 0000, 0003, 0000, 0114, 0000, 0364, 0023, 0000, 0000, 0020, 0024, 0000, 0000, 
+  0144, 0005, 0305, 0271, 0003, 0000, 0000, 0000, 0020, 0024, 0000, 0000, 0020, 0000, 0166, 0000, 
+  0040, 0024, 0000, 0000, 0075, 0026, 0000, 0000, 0201, 0321, 0040, 0031, 0007, 0000, 0000, 0000, 
+  0075, 0026, 0000, 0000, 0005, 0000, 0114, 0000, 0104, 0026, 0000, 0000, 0110, 0026, 0000, 0000, 
+  0362, 0233, 0121, 0203, 0003, 0000, 0000, 0000, 0110, 0026, 0000, 0000, 0026, 0000, 0166, 0000, 
+  0140, 0026, 0000, 0000, 0240, 0044, 0000, 0000, 0113, 0120, 0220, 0013, 0010, 0000, 0000, 0000, 
+  0240, 0044, 0000, 0000, 0004, 0000, 0114, 0000, 0244, 0044, 0000, 0000, 0250, 0044, 0000, 0000, 
+  0324, 0265, 0002, 0000, 0377, 0377, 0377, 0377, 0250, 0044, 0000, 0000, 0001, 0000, 0114, 0000, 
+  0254, 0044, 0000, 0000, 0260, 0044, 0000, 0000, 0224, 0227, 0342, 0142, 0003, 0000, 0000, 0000, 
+  0260, 0044, 0000, 0000, 0024, 0000, 0166, 0000, 0310, 0044, 0000, 0000, 0070, 0067, 0000, 0000, 
+  0372, 0007, 0066, 0115, 0005, 0000, 0000, 0000, 0070, 0067, 0000, 0000, 0013, 0000, 0114, 0000, 
+  0104, 0067, 0000, 0000, 0110, 0067, 0000, 0000, 0367, 0356, 0116, 0135, 0003, 0000, 0000, 0000, 
+  0110, 0067, 0000, 0000, 0017, 0000, 0166, 0000, 0130, 0067, 0000, 0000, 0122, 0072, 0000, 0000, 
+  0160, 0162, 0145, 0146, 0145, 0162, 0145, 0156, 0143, 0145, 0163, 0056, 0165, 0151, 0000, 0000, 
+  0147, 0047, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0132, 0315, 0216, 0333, 0066, 
+  0020, 0276, 0347, 0051, 0130, 0136, 0123, 0305, 0053, 0357, 0306, 0330, 0056, 0154, 0005, 0151, 
+  0212, 0004, 0005, 0202, 0240, 0300, 0246, 0350, 0221, 0240, 0045, 0256, 0315, 0204, 0042, 0125, 
+  0222, 0132, 0257, 0363, 0022, 0075, 0366, 0375, 0372, 0044, 0035, 0122, 0362, 0217, 0144, 0332, 
+  0336, 0365, 0217, 0222, 0024, 0075, 0331, 0242, 0206, 0234, 0031, 0316, 0067, 0177, 0244, 0206, 
+  0257, 0036, 0162, 0201, 0356, 0231, 0066, 0134, 0311, 0021, 0216, 0137, 0134, 0140, 0304, 0144, 
+  0252, 0062, 0056, 0047, 0043, 0374, 0373, 0307, 0267, 0321, 0065, 0176, 0225, 0074, 0033, 0376, 
+  0020, 0105, 0350, 0035, 0223, 0114, 0123, 0313, 0062, 0064, 0343, 0166, 0212, 0046, 0202, 0146, 
+  0014, 0135, 0276, 0350, 0367, 0137, 0304, 0050, 0212, 0200, 0210, 0113, 0313, 0364, 0035, 0115, 
+  0131, 0062, 0324, 0354, 0317, 0222, 0153, 0146, 0220, 0340, 0343, 0021, 0236, 0330, 0317, 0317, 
+  0361, 0212, 0213, 0233, 0203, 0173, 0311, 0120, 0215, 0077, 0261, 0324, 0242, 0124, 0120, 0143, 
+  0106, 0370, 0235, 0375, 0374, 0236, 0033, 0173, 0153, 0225, 0146, 0030, 0361, 0154, 0204, 0251, 
+  0234, 0010, 0106, 0112, 0311, 0055, 0311, 0125, 0306, 0004, 0116, 0206, 0251, 0022, 0145, 0056, 
+  0115, 0342, 0005, 0252, 0036, 0042, 0111, 0163, 0206, 0004, 0035, 0063, 0341, 0304, 0250, 0111, 
+  0220, 0235, 0027, 0014, 0070, 0247, 0123, 0252, 0251, 0326, 0164, 0356, 0030, 0266, 0047, 0271, 
+  0245, 0115, 0140, 0022, 0050, 0342, 0310, 0173, 0113, 0156, 0275, 0112, 0324, 0200, 0310, 0257, 
+  0263, 0117, 0245, 0261, 0071, 0203, 0031, 0136, 0346, 0214, 0245, 0074, 0247, 0202, 0024, 0002, 
+  0366, 0301, 0020, 0272, 0172, 0235, 0014, 0013, 0255, 0012, 0246, 0355, 0034, 0071, 0346, 0043, 
+  0134, 0026, 0360, 0204, 0223, 0370, 0342, 0142, 0330, 0133, 0274, 0332, 0040, 0062, 0226, 0025, 
+  0204, 0313, 0124, 0263, 0152, 0221, 0170, 0007, 0155, 0101, 0047, 0154, 0053, 0355, 0166, 0025, 
+  0176, 0315, 0141, 0136, 0045, 0075, 0167, 0177, 0343, 0115, 0121, 0357, 0271, 0341, 0143, 0301, 
+  0160, 0362, 0121, 0227, 0154, 0207, 0004, 0051, 0225, 0344, 0116, 0245, 0245, 0301, 0311, 0133, 
+  0052, 0314, 0056, 0122, 0236, 0052, 0111, 0334, 0137, 0234, 0314, 0270, 0314, 0324, 0054, 0112, 
+  0205, 0152, 0316, 0330, 0056, 0162, 0013, 0050, 0262, 0314, 0307, 0114, 0003, 0147, 0235, 0323, 
+  0163, 0141, 0245, 0132, 0374, 0070, 0260, 0264, 0304, 0236, 0051, 0235, 0021, 0303, 0277, 0260, 
+  0063, 0211, 0354, 0226, 0176, 0214, 0300, 0031, 0265, 0024, 0134, 0126, 0315, 0074, 0245, 0027, 
+  0015, 0302, 0200, 0325, 0124, 0032, 0001, 0257, 0300, 0360, 0043, 0074, 0147, 0006, 0303, 0342, 
+  0271, 0103, 0026, 0050, 0363, 0007, 0210, 0136, 0255, 0017, 0143, 0143, 0165, 0203, 0256, 0321, 
+  0030, 0174, 0011, 0047, 0327, 0021, 0374, 0372, 0265, 0127, 0213, 0001, 0240, 0256, 0353, 0241, 
+  0236, 0347, 0162, 0034, 0253, 0170, 0120, 0363, 0212, 0007, 0141, 0146, 0361, 0340, 0204, 0334, 
+  0056, 0373, 0065, 0267, 0313, 0176, 0230, 0333, 0145, 0377, 0204, 0334, 0006, 0127, 0065, 0267, 
+  0301, 0125, 0230, 0333, 0340, 0252, 0301, 0255, 0127, 0331, 0156, 0073, 0344, 0176, 0341, 0124, 
+  0250, 0111, 0205, 0267, 0102, 0263, 0073, 0246, 0041, 0274, 0103, 0140, 0312, 0252, 0361, 0143, 
+  0074, 0170, 0014, 0302, 0203, 0327, 0315, 0170, 0146, 0247, 0336, 0302, 0133, 0051, 0055, 0267, 
+  0020, 0074, 0002, 0133, 0221, 0374, 0266, 0022, 0151, 0327, 0174, 0000, 0056, 0231, 0072, 0334, 
+  0046, 0322, 0271, 0241, 0130, 0247, 0065, 0174, 0042, 0251, 0250, 0051, 0301, 0215, 0230, 0145, 
+  0021, 0273, 0367, 0001, 0171, 0112, 0145, 0046, 0230, 0016, 0151, 0116, 0052, 0112, 0222, 0216, 
+  0061, 0062, 0063, 0012, 0241, 0330, 0305, 0021, 0345, 0034, 0243, 0261, 0040, 0344, 0260, 0102, 
+  0111, 0303, 0266, 0054, 0266, 0170, 0035, 0132, 0047, 0235, 0162, 0221, 0201, 0056, 0056, 0023, 
+  0114, 0225, 0200, 0275, 0362, 0136, 0127, 0215, 0372, 0037, 0344, 0063, 0046, 0060, 0213, 0374, 
+  0043, 0304, 0331, 0261, 0172, 0300, 0001, 0053, 0376, 0014, 0303, 0125, 0172, 0361, 0302, 0107, 
+  0216, 0356, 0252, 0223, 0060, 0255, 0064, 0207, 0255, 0244, 0026, 0022, 0067, 0116, 0040, 0203, 
+  0133, 0236, 0066, 0267, 0277, 0235, 0257, 0012, 0232, 0102, 0355, 0200, 0223, 0227, 0353, 0104, 
+  0141, 0155, 0151, 0352, 0226, 0045, 0124, 0063, 0032, 0124, 0272, 0264, 0126, 0311, 0266, 0352, 
+  0153, 0223, 0272, 0331, 0001, 0101, 0347, 0252, 0264, 0304, 0330, 0271, 0133, 0227, 0311, 0154, 
+  0103, 0261, 0255, 0262, 0127, 0202, 0217, 0375, 0377, 0100, 0126, 0365, 0101, 0075, 0350, 0026, 
+  0344, 0115, 0073, 0027, 0036, 0257, 0347, 0036, 0112, 0315, 0122, 0306, 0357, 0235, 0177, 0260, 
+  0073, 0132, 0012, 0273, 0167, 0202, 0257, 0025, 0160, 0122, 0225, 0014, 0073, 0350, 0112, 0343, 
+  0152, 0070, 0100, 0277, 0340, 0062, 0040, 0360, 0062, 0164, 0001, 0160, 0076, 0003, 0162, 0066, 
+  0346, 0263, 0207, 0002, 0074, 0157, 0277, 0235, 0356, 0270, 0020, 0373, 0251, 0012, 0145, 0170, 
+  0005, 0346, 0106, 0325, 0325, 0133, 0162, 0137, 0070, 0150, 0327, 0162, 0001, 0027, 0342, 0342, 
+  0334, 0006, 0304, 0016, 0125, 0140, 0033, 0064, 0337, 0151, 0236, 0155, 0346, 0003, 0217, 0276, 
+  0116, 0374, 0251, 0231, 0066, 0136, 0356, 0202, 0244, 0232, 0221, 0145, 0074, 0211, 0373, 0273, 
+  0330, 0373, 0122, 0146, 0105, 0074, 0170, 0214, 0217, 0276, 0257, 0334, 0317, 0355, 0204, 0367, 
+  0304, 0353, 0216, 0302, 0311, 0026, 0247, 0137, 0053, 0013, 0326, 0262, 0042, 0252, 0302, 0336, 
+  0015, 0362, 0322, 0272, 0052, 0024, 0371, 0266, 0310, 0367, 0056, 0125, 0325, 0200, 0174, 0322, 
+  0040, 0257, 0227, 0303, 0346, 0346, 0160, 0167, 0154, 0121, 0347, 0222, 0345, 0112, 0362, 0324, 
+  0231, 0153, 0302, 0040, 0050, 0254, 0365, 0144, 0236, 0071, 0360, 0336, 0061, 0375, 0201, 0012, 
+  0110, 0246, 0155, 0250, 0356, 0363, 0054, 0301, 0356, 0054, 0241, 0326, 0322, 0164, 0332, 0232, 
+  0332, 0256, 0013, 0124, 0261, 0244, 0353, 0037, 0346, 0015, 0155, 0020, 0374, 0364, 0235, 0200, 
+  0040, 0343, 0006, 0012, 0213, 0371, 0242, 0055, 0131, 0003, 0302, 0007, 0337, 0014, 0041, 0362, 
+  0326, 0277, 0071, 0043, 0024, 0232, 0135, 0327, 0267, 0205, 0206, 0003, 0143, 0343, 0033, 0247, 
+  0304, 0262, 0342, 0010, 0140, 0275, 0023, 0164, 0324, 0335, 0140, 0373, 0370, 0143, 0153, 0321, 
+  0013, 0115, 0240, 0234, 0260, 0154, 0255, 0104, 0015, 0110, 0116, 0152, 0252, 0120, 0245, 0372, 
+  0064, 0033, 0304, 0347, 0365, 0310, 0246, 0015, 0302, 0040, 0353, 0322, 0014, 0201, 0303, 0205, 
+  0047, 0130, 0042, 0054, 0177, 0367, 0306, 0070, 0211, 0103, 0254, 0016, 0054, 0276, 0206, 0041, 
+  0132, 0307, 0045, 0117, 0060, 0302, 0246, 0334, 0335, 0033, 0340, 0362, 0064, 0371, 0051, 0216, 
+  0277, 0351, 0004, 0045, 0226, 0011, 0152, 0326, 0074, 0332, 0250, 0162, 0223, 0077, 0357, 0360, 
+  0226, 0070, 0143, 0136, 0332, 0264, 0366, 0267, 0221, 0223, 0016, 0104, 0300, 0153, 0047, 0340, 
+  0352, 0200, 0231, 0056, 0036, 0343, 0216, 0252, 0165, 0150, 0136, 0163, 0122, 0320, 0054, 0333, 
+  0254, 0254, 0103, 0273, 0262, 0244, 0154, 0026, 0354, 0373, 0273, 0021, 0017, 0262, 0176, 0047, 
+  0112, 0065, 0032, 0213, 0107, 0365, 0012, 0157, 0246, 0054, 0155, 0064, 0365, 0340, 0031, 0034, 
+  0340, 0071, 0041, 0137, 0230, 0126, 0320, 0077, 0245, 0216, 0000, 0237, 0301, 0217, 0314, 0124, 
+  0315, 0320, 0202, 0033, 0252, 0270, 0041, 0317, 0015, 0125, 0007, 0013, 0070, 0271, 0155, 0220, 
+  0324, 0022, 0175, 0345, 0303, 0203, 0175, 0046, 0230, 0326, 0176, 0147, 0054, 0325, 0366, 0144, 
+  0261, 0040, 0323, 0164, 0106, 0270, 0314, 0170, 0112, 0255, 0322, 0233, 0344, 0215, 0074, 0141, 
+  0325, 0004, 0252, 0244, 0365, 0074, 0021, 0064, 0052, 0251, 0351, 0216, 0117, 0025, 0217, 0015, 
+  0024, 0361, 0201, 0271, 0172, 0003, 0243, 0123, 0125, 0032, 0320, 0315, 0020, 0303, 0012, 0252, 
+  0335, 0226, 0234, 0033, 0247, 0013, 0216, 0150, 0311, 0061, 0204, 0125, 0022, 0240, 0373, 0037, 
+  0260, 0207, 0000, 0166, 0233, 0205, 0273, 0007, 0355, 0201, 0325, 0376, 0262, 0266, 0234, 0102, 
+  0236, 0356, 0046, 0245, 0035, 0174, 0112, 0324, 0272, 0333, 0255, 0352, 0261, 0056, 0313, 0261, 
+  0225, 0057, 0176, 0120, 0166, 0351, 0254, 0054, 0103, 0343, 0071, 0002, 0121, 0237, 0377, 0210, 
+  0270, 0131, 0037, 0246, 0006, 0051, 0311, 0220, 0261, 0332, 0353, 0353, 0174, 0357, 0174, 0145, 
+  0127, 0153, 0167, 0114, 0301, 0345, 0311, 0353, 0256, 0247, 0235, 0271, 0356, 0321, 0340, 0350, 
+  0223, 0324, 0133, 0120, 0161, 0075, 0336, 0006, 0166, 0000, 0167, 0020, 0313, 0270, 0254, 0327, 
+  0164, 0115, 0015, 0304, 0220, 0177, 0376, 0376, 0153, 0007, 0365, 0372, 0027, 0011, 0133, 0077, 
+  0126, 0330, 0032, 0202, 0356, 0251, 0050, 0131, 0264, 0331, 0141, 0005, 0124, 0257, 0133, 0054, 
+  0342, 0247, 0034, 0024, 0207, 0316, 0144, 0355, 0370, 0350, 0116, 0054, 0024, 0010, 0372, 0337, 
+  0121, 0040, 0250, 0345, 0107, 0265, 0002, 0377, 0215, 0230, 0260, 0107, 0266, 0047, 0202, 0244, 
+  0177, 0344, 0355, 0320, 0071, 0116, 0055, 0227, 0114, 0317, 0053, 0305, 0256, 0023, 0215, 0372, 
+  0326, 0246, 0337, 0351, 0335, 0331, 0251, 0074, 0173, 0143, 0377, 0252, 0273, 0344, 0250, 0102, 
+  0253, 0151, 0075, 0243, 0305, 0335, 0276, 0373, 0214, 0043, 0251, 0057, 0161, 0207, 0275, 0006, 
+  0115, 0322, 0172, 0136, 0377, 0372, 0247, 0267, 0372, 0034, 0356, 0331, 0277, 0355, 0222, 0140, 
+  0076, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0142, 0165, 0164, 0164, 0157, 0156, 0163, 0055, 
+  0141, 0144, 0166, 0141, 0156, 0143, 0145, 0144, 0056, 0165, 0151, 0000, 0000, 0000, 0000, 0000, 
+  0343, 0177, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0135, 0335, 0156, 0333, 0066, 
+  0024, 0276, 0357, 0123, 0150, 0272, 0050, 0122, 0024, 0116, 0374, 0227, 0064, 0355, 0142, 0027, 
+  0151, 0261, 0026, 0005, 0072, 0014, 0330, 0322, 0355, 0322, 0240, 0044, 0132, 0146, 0115, 0223, 
+  0032, 0111, 0305, 0366, 0320, 0213, 0135, 0015, 0275, 0135, 0167, 0121, 0140, 0057, 0262, 0007, 
+  0350, 0003, 0354, 0035, 0372, 0044, 0043, 0345, 0377, 0237, 0230, 0212, 0103, 0123, 0216, 0307, 
+  0233, 0104, 0226, 0050, 0221, 0074, 0337, 0371, 0016, 0217, 0016, 0017, 0251, 0213, 0347, 0203, 
+  0036, 0366, 0256, 0041, 0343, 0210, 0222, 0206, 0137, 0071, 0056, 0373, 0036, 0044, 0041, 0215, 
+  0020, 0211, 0033, 0376, 0273, 0253, 0127, 0245, 0163, 0377, 0171, 0363, 0301, 0305, 0067, 0245, 
+  0222, 0367, 0032, 0022, 0310, 0200, 0200, 0221, 0327, 0107, 0242, 0343, 0305, 0030, 0104, 0320, 
+  0253, 0035, 0127, 0253, 0307, 0025, 0257, 0124, 0222, 0205, 0020, 0021, 0220, 0265, 0101, 0010, 
+  0233, 0027, 0014, 0376, 0232, 0042, 0006, 0271, 0207, 0121, 0320, 0360, 0143, 0321, 0175, 0354, 
+  0317, 0152, 0121, 0367, 0370, 0047, 0315, 0013, 0032, 0274, 0207, 0241, 0360, 0102, 0014, 0070, 
+  0157, 0370, 0257, 0105, 0367, 0027, 0104, 0042, 0332, 0367, 0075, 0024, 0065, 0374, 0176, 0166, 
+  0134, 0361, 0233, 0027, 0011, 0243, 0011, 0144, 0142, 0350, 0021, 0320, 0203, 0015, 0077, 0004, 
+  0244, 0325, 0246, 0141, 0312, 0375, 0346, 0053, 0200, 0071, 0274, 0070, 0231, 0024, 0150, 0136, 
+  0204, 0035, 0204, 0043, 0117, 0014, 0023, 0131, 0116, 0040, 0201, 0141, 0000, 0230, 0172, 0002, 
+  0226, 0215, 0352, 0120, 0034, 0101, 0046, 0253, 0075, 0311, 0112, 0215, 0013, 0257, 0151, 0305, 
+  0153, 0206, 0242, 0121, 0033, 0202, 0124, 0010, 0112, 0132, 0011, 0040, 0020, 0257, 0066, 0344, 
+  0032, 0161, 0024, 0140, 0350, 0067, 0257, 0130, 0272, 0320, 0212, 0133, 0064, 0170, 0251, 0050, 
+  0243, 0375, 0126, 0207, 0366, 0150, 0054, 0105, 0115, 0325, 0015, 0272, 0107, 0123, 0234, 0366, 
+  0310, 0346, 0133, 0156, 0352, 0346, 0213, 0254, 0163, 0243, 0216, 0206, 0000, 0207, 0055, 0211, 
+  0234, 0240, 0254, 0065, 0352, 0364, 0152, 0167, 0061, 0010, 0224, 0024, 0300, 0227, 0317, 0301, 
+  0206, 0026, 0155, 0041, 0024, 0115, 0311, 0254, 0124, 0113, 0302, 0020, 0142, 0024, 0166, 0163, 
+  0310, 0020, 0206, 0020, 0135, 0103, 0336, 0212, 0140, 0033, 0244, 0130, 0150, 0053, 0110, 0071, 
+  0154, 0245, 0104, 0352, 0006, 0106, 0144, 0115, 0303, 0071, 0212, 0011, 0300, 0223, 0146, 0253, 
+  0066, 0100, 0251, 0036, 0035, 0100, 0042, 0014, 0231, 0154, 0136, 0046, 0065, 0364, 0033, 0154, 
+  0205, 0201, 0357, 0361, 0076, 0110, 0022, 0050, 0045, 0112, 0250, 0322, 0360, 0221, 0076, 0146, 
+  0274, 0220, 0317, 0050, 0145, 0077, 0033, 0076, 0010, 0103, 0310, 0307, 0142, 0132, 0302, 0345, 
+  0122, 0164, 0177, 0310, 0116, 0334, 0204, 0113, 0011, 0210, 0356, 0350, 0226, 0125, 0204, 0246, 
+  0067, 0077, 0173, 0066, 0253, 0242, 0244, 0256, 0371, 0236, 0140, 0200, 0160, 0014, 0004, 0220, 
+  0247, 0032, 0376, 0020, 0162, 0337, 0013, 0151, 0257, 0007, 0211, 0120, 0265, 0116, 0113, 0147, 
+  0117, 0362, 0332, 0224, 0171, 0242, 0043, 0377, 0117, 0372, 0346, 0115, 0224, 0342, 0325, 0344, 
+  0314, 0274, 0204, 0116, 0106, 0015, 0232, 0061, 0153, 0172, 0042, 0001, 0141, 0127, 0132, 0222, 
+  0125, 0135, 0202, 0155, 0321, 0002, 0102, 0200, 0260, 0343, 0067, 0117, 0067, 0140, 0043, 0150, 
+  0062, 0055, 0127, 0137, 0250, 0163, 0372, 0150, 0035, 0235, 0127, 0364, 0034, 0365, 0100, 0214, 
+  0010, 0140, 0303, 0126, 0102, 0231, 0220, 0026, 0111, 0247, 0362, 0157, 0172, 0116, 0341, 0147, 
+  0012, 0077, 0066, 0212, 0153, 0264, 0375, 0166, 0260, 0077, 0051, 0014, 0366, 0233, 0340, 0166, 
+  0120, 0056, 0032, 0256, 0065, 0122, 0175, 0233, 0061, 0042, 0023, 0352, 0114, 0236, 0143, 0232, 
+  0130, 0030, 0037, 0307, 0065, 0075, 0304, 0342, 0133, 0364, 0060, 0126, 0177, 0344, 0321, 0111, 
+  0166, 0250, 0021, 0122, 0017, 0260, 0156, 0232, 0254, 0266, 0345, 0216, 0266, 0253, 0152, 0131, 
+  0211, 0353, 0072, 0133, 0125, 0167, 0246, 0152, 0246, 0337, 0021, 0212, 0221, 0270, 0273, 0245, 
+  0052, 0347, 0004, 0271, 0152, 0010, 0344, 0047, 0072, 0220, 0237, 0070, 0220, 0013, 0003, 0271, 
+  0142, 0010, 0344, 0163, 0035, 0310, 0347, 0016, 0144, 0343, 0040, 0127, 0054, 0203, 0374, 0124, 
+  0007, 0362, 0123, 0007, 0262, 0161, 0220, 0253, 0226, 0101, 0076, 0325, 0201, 0174, 0352, 0100, 
+  0056, 0214, 0311, 0246, 0306, 0344, 0063, 0035, 0310, 0147, 0016, 0344, 0302, 0230, 0154, 0012, 
+  0344, 0010, 0135, 0243, 0010, 0352, 0220, 0376, 0362, 0217, 0203, 0332, 0174, 0070, 0240, 0146, 
+  0331, 0152, 0127, 0165, 0060, 0127, 0035, 0312, 0205, 0131, 0355, 0232, 0041, 0220, 0111, 0332, 
+  0203, 0014, 0205, 0255, 0204, 0042, 0042, 0064, 0200, 0317, 0305, 0103, 0263, 0050, 0207, 0207, 
+  0270, 0307, 0241, 0360, 0020, 0361, 0142, 0321, 0075, 0016, 0075, 0101, 0125, 0221, 0004, 0017, 
+  0107, 0363, 0037, 0157, 0137, 0172, 0155, 0014, 0142, 0011, 0355, 0261, 0323, 0224, 0231, 0246, 
+  0054, 0212, 0334, 0232, 0306, 0230, 0012, 0260, 0324, 0164, 0146, 0241, 0346, 0300, 0056, 0154, 
+  0234, 0067, 0145, 0026, 0172, 0122, 0062, 0110, 0022, 0131, 0073, 0322, 0177, 0166, 0140, 0027, 
+  0067, 0322, 0233, 0362, 0352, 0170, 0032, 0010, 0006, 0102, 0235, 0375, 0157, 0176, 0375, 0370, 
+  0311, 0301, 0075, 0203, 0173, 0052, 0066, 0153, 0200, 0233, 0242, 0067, 0210, 0042, 0035, 0326, 
+  0217, 0035, 0322, 0305, 0021, 0333, 0324, 0130, 0315, 0040, 0227, 0302, 0321, 0271, 0165, 0033, 
+  0147, 0276, 0107, 0236, 0036, 0045, 0331, 0164, 0067, 0247, 0370, 0172, 0062, 0325, 0355, 0035, 
+  0145, 0162, 0222, 0015, 0223, 0227, 0224, 0047, 0250, 0256, 0361, 0254, 0130, 0204, 0170, 0202, 
+  0301, 0020, 0106, 0236, 0152, 0105, 0052, 0037, 0215, 0050, 0171, 0344, 0067, 0033, 0116, 0247, 
+  0346, 0254, 0207, 0222, 0327, 0072, 0225, 0342, 0142, 0210, 0241, 0004, 0131, 0301, 0072, 0276, 
+  0233, 0247, 0161, 0014, 0271, 0200, 0121, 0111, 0232, 0033, 0051, 0313, 0114, 0363, 0306, 0345, 
+  0156, 0247, 0201, 0165, 0313, 0032, 0030, 0142, 0010, 0330, 0355, 0025, 0260, 0371, 0122, 0335, 
+  0167, 0317, 0325, 0105, 0243, 0000, 0043, 0321, 0344, 0123, 0200, 0110, 0242, 0317, 0122, 0211, 
+  0375, 0065, 0274, 0263, 0012, 0344, 0315, 0046, 0051, 0033, 0122, 0001, 0070, 0110, 0050, 0221, 
+  0306, 0004, 0001, 0354, 0022, 0013, 0046, 0340, 0117, 0204, 0262, 0145, 0152, 0101, 0106, 0234, 
+  0252, 0315, 0214, 0202, 0057, 0237, 0053, 0145, 0225, 0113, 0300, 0323, 0104, 0045, 0023, 0114, 
+  0023, 0014, 0206, 0263, 0004, 0203, 0354, 0150, 0174, 0335, 0124, 0262, 0201, 0221, 0374, 0260, 
+  0125, 0015, 0264, 0232, 0044, 0306, 0103, 0244, 0052, 0157, 0243, 0320, 0233, 0264, 0144, 0232, 
+  0056, 0366, 0323, 0354, 0332, 0167, 0343, 0153, 0005, 0044, 0137, 0230, 0242, 0172, 0217, 0106, 
+  0051, 0226, 0264, 0313, 0027, 0046, 0226, 0245, 0235, 0103, 0120, 0234, 0223, 0151, 0012, 0164, 
+  0056, 0000, 0023, 0255, 0230, 0321, 0064, 0321, 0041, 0176, 0344, 0360, 0066, 0217, 0167, 0335, 
+  0362, 0274, 0000, 0044, 0121, 0076, 0264, 0037, 0071, 0264, 0315, 0243, 0175, 0152, 0031, 0355, 
+  0036, 0354, 0321, 0173, 0236, 0021, 0252, 0101, 0146, 0334, 0303, 0133, 0070, 0142, 0057, 0350, 
+  0140, 0044, 0241, 0116, 0100, 0007, 0325, 0362, 0156, 0334, 0260, 0334, 0136, 0140, 0315, 0242, 
+  0033, 0270, 0331, 0001, 0272, 0222, 0316, 0016, 0236, 0217, 0027, 0214, 0104, 0073, 0165, 0166, 
+  0006, 0363, 0317, 0227, 0212, 0312, 0220, 0274, 0002, 0371, 0334, 0361, 0344, 0175, 0127, 0275, 
+  0327, 0370, 0336, 0065, 0300, 0251, 0374, 0205, 0004, 0220, 0240, 0145, 0124, 0231, 0277, 0111, 
+  0313, 0033, 0351, 0154, 0111, 0214, 0365, 0012, 0207, 0060, 0326, 0026, 0112, 0050, 0107, 0331, 
+  0153, 0327, 0266, 0303, 0346, 0045, 0143, 0223, 0205, 0073, 0100, 0035, 0126, 0352, 0126, 0140, 
+  0313, 0352, 0152, 0251, 0365, 0076, 0176, 0063, 0242, 0175, 0262, 0326, 0271, 0324, 0011, 0120, 
+  0127, 0311, 0055, 0045, 0250, 0061, 0115, 0273, 0171, 0007, 0130, 0260, 0143, 0126, 0335, 0377, 
+  0045, 0022, 0174, 0237, 0375, 0064, 0350, 0344, 0327, 0267, 0231, 0055, 0130, 0052, 0327, 0107, 
+  0221, 0060, 0070, 0241, 0300, 0240, 0174, 0323, 0312, 0271, 0166, 0344, 0107, 0350, 0334, 0004, 
+  0363, 0156, 0302, 0231, 0355, 0070, 0037, 0045, 0357, 0323, 0030, 0010, 0355, 0113, 0237, 0052, 
+  0350, 0000, 0067, 0017, 0370, 0271, 0145, 0300, 0011, 0020, 0051, 0223, 0054, 0307, 0064, 0006, 
+  0014, 0211, 0116, 0117, 0007, 0074, 0046, 0016, 0166, 0363, 0260, 0077, 0265, 0074, 0163, 0230, 
+  0037, 0156, 0032, 0037, 0166, 0370, 0336, 0066, 0161, 0115, 0041, 0070, 0220, 0003, 0163, 0277, 
+  0165, 0320, 0157, 0164, 0167, 0132, 0265, 0067, 0221, 0117, 0161, 0153, 0366, 0006, 0213, 0041, 
+  0365, 0373, 0030, 0161, 0137, 0124, 0062, 0253, 0356, 0366, 0054, 0330, 0257, 0274, 0117, 0357, 
+  0150, 0240, 0322, 0022, 0325, 0005, 0331, 0042, 0310, 0074, 0332, 0366, 0206, 0217, 0246, 0316, 
+  0370, 0016, 0142, 0356, 0147, 0226, 0371, 0314, 0050, 0315, 0221, 0270, 0363, 0267, 0033, 0174, 
+  0213, 0133, 0240, 0155, 0012, 0152, 0331, 0143, 0272, 0305, 0134, 0372, 0073, 0171, 0333, 0141, 
+  0217, 0305, 0231, 0140, 0254, 0005, 0322, 0115, 0115, 0234, 0044, 0310, 0315, 0207, 0033, 0031, 
+  0262, 0245, 0040, 0255, 0217, 0326, 0377, 0376, 0136, 0314, 0172, 0372, 0272, 0145, 0233, 0003, 
+  0123, 0211, 0017, 0127, 0353, 0004, 0002, 0310, 0234, 0276, 0032, 0321, 0327, 0105, 0231, 0026, 
+  0347, 0150, 0302, 0242, 0067, 0207, 0070, 0335, 0255, 0062, 0317, 0366, 0251, 0312, 0206, 0303, 
+  0312, 0341, 0357, 0120, 0025, 0122, 0056, 0265, 0131, 0037, 0203, 0343, 0356, 0335, 0334, 0344, 
+  0226, 0007, 0306, 0122, 0051, 0162, 0200, 0047, 0313, 0070, 0360, 0114, 0056, 0214, 0062, 0005, 
+  0236, 0000, 0044, 0206, 0332, 0105, 0164, 0115, 0131, 0314, 0341, 0267, 0217, 0311, 0153, 0235, 
+  0241, 0174, 0106, 0100, 0145, 0177, 0362, 0362, 0260, 0343, 0200, 0334, 0307, 0075, 0105, 0346, 
+  0200, 0314, 0317, 0111, 0207, 0345, 0136, 0156, 0035, 0202, 0210, 0332, 0024, 0025, 0346, 0141, 
+  0344, 0272, 0320, 0007, 0160, 0243, 0345, 0236, 0156, 0027, 0062, 0001, 0066, 0037, 0103, 0327, 
+  0142, 0353, 0106, 0322, 0075, 0335, 0045, 0144, 0316, 0000, 0347, 0176, 0041, 0161, 0366, 0167, 
+  0057, 0067, 0141, 0233, 0320, 0064, 0027, 0216, 0153, 0131, 0352, 0136, 0066, 0355, 0156, 0242, 
+  0270, 0233, 0331, 0252, 0262, 0076, 0171, 0154, 0123, 0144, 0262, 0003, 0121, 0334, 0021, 0346, 
+  0242, 0222, 0355, 0224, 0204, 0033, 0223, 0313, 0016, 0100, 0257, 0246, 0175, 0334, 0072, 0063, 
+  0271, 0330, 0304, 0344, 0123, 0233, 0061, 0315, 0366, 0321, 0340, 0321, 0126, 0271, 0255, 0373, 
+  0231, 0034, 0354, 0162, 0203, 0155, 0346, 0006, 0057, 0131, 0023, 0273, 0213, 0003, 0005, 0145, 
+  0160, 0224, 0351, 0076, 0133, 0024, 0250, 0316, 0031, 0014, 0263, 0127, 0154, 0307, 0061, 0047, 
+  0136, 0203, 0313, 0061, 0332, 0264, 0160, 0243, 0274, 0107, 0331, 0105, 0137, 0077, 0176, 0252, 
+  0030, 0310, 0046, 0132, 0052, 0372, 0076, 0345, 0002, 0265, 0207, 0322, 0301, 0207, 0212, 0241, 
+  0273, 0317, 0073, 0132, 0124, 0074, 0253, 0104, 0036, 0127, 0075, 0045, 0361, 0233, 0321, 0357, 
+  0042, 0150, 0154, 0312, 0371, 0037, 0177, 0335, 0342, 0236, 0257, 0333, 0337, 0071, 0221, 0055, 
+  0055, 0345, 0331, 0100, 0344, 0157, 0366, 0052, 0371, 0157, 0131, 0155, 0212, 0370, 0042, 0213, 
+  0004, 0174, 0351, 0213, 0054, 0000, 0027, 0101, 0105, 0123, 0041, 0025, 0020, 0160, 0227, 0174, 
+  0141, 0220, 0262, 0066, 0031, 0373, 0141, 0035, 0145, 0077, 0354, 0025, 0145, 0147, 0352, 0145, 
+  0225, 0254, 0262, 0132, 0212, 0325, 0262, 0317, 0105, 0377, 0367, 0162, 0162, 0372, 0147, 0165, 
+  0272, 0010, 0332, 0032, 0333, 0150, 0215, 0305, 0272, 0330, 0347, 0045, 0213, 0135, 0156, 0156, 
+  0161, 0013, 0143, 0266, 0134, 0017, 0165, 0105, 0343, 0030, 0303, 0065, 0073, 0051, 0312, 0047, 
+  0361, 0220, 0241, 0104, 0034, 0262, 0317, 0304, 0241, 0130, 0350, 0352, 0035, 0054, 0261, 0315, 
+  0325, 0353, 0315, 0257, 0177, 0374, 0111, 0366, 0312, 0356, 0256, 0352, 0213, 0335, 0340, 0303, 
+  0254, 0172, 0257, 0107, 0243, 0271, 0010, 0304, 0354, 0202, 0111, 0363, 0273, 0333, 0060, 0304, 
+  0215, 0234, 0014, 0376, 0057, 0214, 0014, 0356, 0316, 0307, 0272, 0135, 0076, 0376, 0265, 0157, 
+  0174, 0014, 0212, 0144, 0143, 0260, 0236, 0213, 0201, 0161, 0046, 0332, 0016, 0010, 0126, 0164, 
+  0136, 0120, 0305, 0371, 0100, 0205, 0175, 0260, 0313, 0224, 0263, 0133, 0326, 0201, 0254, 0235, 
+  0104, 0154, 0251, 0257, 0042, 0103, 0056, 0345, 0173, 0132, 0166, 0012, 0121, 0230, 0102, 0030, 
+  0334, 0024, 0202, 0037, 0364, 0250, 0073, 0352, 0340, 0266, 0363, 0263, 0265, 0042, 0346, 0147, 
+  0013, 0335, 0053, 0252, 0231, 0011, 0354, 0160, 0346, 0151, 0153, 0156, 0236, 0066, 0347, 0074, 
+  0355, 0216, 0342, 0064, 0365, 0155, 0233, 0161, 0222, 0071, 0212, 0155, 0020, 0302, 0346, 0203, 
+  0377, 0000, 0216, 0314, 0365, 0242, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0142, 0165, 0164, 
+  0164, 0157, 0156, 0163, 0055, 0142, 0141, 0163, 0151, 0143, 0056, 0165, 0151, 0000, 0000, 0000, 
+  0126, 0061, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0133, 0335, 0156, 0333, 0066, 
+  0024, 0276, 0357, 0123, 0160, 0002, 0126, 0044, 0050, 0374, 0237, 0264, 0151, 0153, 0251, 0350, 
+  0212, 0065, 0067, 0001, 0166, 0323, 0142, 0227, 0002, 0115, 0036, 0313, 0234, 0151, 0122, 0045, 
+  0051, 0377, 0274, 0301, 0256, 0167, 0063, 0140, 0057, 0262, 0007, 0330, 0233, 0354, 0111, 0106, 
+  0312, 0212, 0355, 0304, 0261, 0351, 0244, 0232, 0264, 0016, 0272, 0123, 0304, 0103, 0362, 0360, 
+  0373, 0276, 0163, 0016, 0111, 0053, 0303, 0167, 0313, 0031, 0107, 0163, 0120, 0232, 0111, 0021, 
+  0006, 0275, 0166, 0067, 0100, 0040, 0210, 0244, 0114, 0044, 0141, 0360, 0371, 0323, 0307, 0326, 
+  0125, 0360, 0056, 0172, 0066, 0374, 0256, 0325, 0102, 0327, 0040, 0100, 0141, 0003, 0024, 0055, 
+  0230, 0231, 0240, 0204, 0143, 0012, 0150, 0320, 0356, 0367, 0333, 0075, 0324, 0152, 0131, 0043, 
+  0046, 0014, 0250, 0061, 0046, 0020, 0015, 0025, 0174, 0311, 0230, 0002, 0215, 0070, 0033, 0205, 
+  0101, 0142, 0246, 0057, 0202, 0355, 0054, 0256, 0117, 0320, 0211, 0206, 0162, 0364, 0013, 0020, 
+  0203, 0010, 0307, 0132, 0207, 0301, 0265, 0231, 0376, 0314, 0004, 0225, 0213, 0000, 0061, 0032, 
+  0006, 0213, 0374, 0271, 0027, 0104, 0303, 0124, 0311, 0024, 0224, 0131, 0041, 0201, 0147, 0020, 
+  0006, 0004, 0213, 0170, 0054, 0111, 0246, 0203, 0350, 0043, 0346, 0032, 0206, 0235, 0133, 0203, 
+  0150, 0110, 0046, 0214, 0123, 0144, 0126, 0251, 0265, 0063, 0314, 0160, 0030, 0141, 0345, 0106, 
+  0340, 0326, 0251, 0211, 0344, 0024, 0224, 0235, 0266, 0223, 0133, 0025, 0306, 0017, 0170, 0161, 
+  0255, 0030, 0135, 0373, 0060, 0312, 0214, 0221, 0042, 0116, 0261, 0000, 0276, 0357, 0310, 0234, 
+  0151, 0066, 0342, 0020, 0104, 0237, 0124, 0166, 0307, 0213, 0107, 0070, 0174, 0317, 0124, 0311, 
+  0105, 0074, 0221, 0063, 0231, 0130, 0250, 0245, 0353, 0340, 0033, 0132, 0362, 0154, 0046, 0216, 
+  0167, 0071, 0264, 0314, 0037, 0362, 0305, 0255, 0027, 0112, 0060, 0047, 0361, 0105, 0274, 0136, 
+  0357, 0376, 0112, 0071, 0036, 0071, 0000, 0056, 0216, 0170, 0362, 0004, 0060, 0074, 0226, 0271, 
+  0125, 0154, 0341, 0047, 0234, 0221, 0351, 0011, 0330, 0001, 0001, 0066, 0007, 0035, 0123, 0030, 
+  0343, 0214, 0033, 0177, 0217, 0114, 0103, 0234, 0011, 0053, 0012, 0316, 0304, 0003, 0236, 0153, 
+  0226, 0010, 0314, 0157, 0375, 0166, 0116, 0200, 0325, 0305, 0004, 0013, 0312, 0101, 0205, 0001, 
+  0145, 0011, 0063, 0061, 0031, 0005, 0110, 0057, 0160, 0232, 0202, 0205, 0121, 0110, 0047, 0353, 
+  0316, 0032, 0152, 0073, 0035, 0046, 0123, 0033, 0107, 0373, 0160, 0302, 0330, 0304, 0330, 0030, 
+  0114, 0046, 0101, 0324, 0075, 0342, 0240, 0221, 0351, 0306, 0256, 0267, 0153, 0327, 0331, 0014, 
+  0355, 0023, 0363, 0036, 0313, 0127, 0076, 0226, 0257, 0032, 0226, 0313, 0147, 0271, 0167, 0042, 
+  0313, 0335, 0222, 0130, 0176, 0355, 0143, 0371, 0165, 0303, 0162, 0371, 0054, 0367, 0053, 0146, 
+  0371, 0322, 0307, 0362, 0145, 0303, 0162, 0175, 0261, 0134, 0126, 0306, 0176, 0351, 0143, 0371, 
+  0145, 0303, 0162, 0175, 0261, 0134, 0026, 0313, 0224, 0315, 0031, 0005, 0037, 0325, 0177, 0375, 
+  0331, 0160, 0275, 0303, 0165, 0261, 0101, 0377, 0152, 0262, 0007, 0025, 0047, 0356, 0276, 0217, 
+  0347, 0176, 0103, 0163, 0175, 0211, 0273, 0137, 0022, 0313, 0042, 0233, 0201, 0142, 0044, 0116, 
+  0245, 0075, 0031, 0173, 0030, 0107, 0104, 0316, 0146, 0040, 0214, 0035, 0352, 0306, 0275, 0100, 
+  0114, 0043, 0015, 0006, 0061, 0201, 0354, 0351, 0271, 0115, 0220, 0221, 0316, 0044, 0345, 0253, 
+  0365, 0351, 0373, 0346, 0003, 0032, 0163, 0234, 0130, 0156, 0333, 0215, 0124, 0166, 0244, 0162, 
+  0027, 0363, 0312, 0044, 0063, 0050, 0111, 0062, 0166, 0004, 0142, 0125, 0200, 0023, 0157, 0045, 
+  0370, 0376, 0033, 0243, 0335, 0063, 0301, 0177, 0243, 0016, 0364, 0053, 0246, 0173, 0340, 0143, 
+  0171, 0320, 0004, 0167, 0175, 0133, 0273, 0262, 0352, 0300, 0314, 0102, 0303, 0154, 0346, 0366, 
+  0156, 0356, 0176, 0157, 0330, 0256, 0161, 0163, 0127, 0326, 0116, 0136, 0147, 0043, 0243, 0060, 
+  0361, 0125, 0374, 0350, 0357, 0137, 0177, 0153, 0370, 0336, 0341, 0173, 0203, 0133, 0145, 0214, 
+  0227, 0025, 0340, 0230, 0122, 0037, 0331, 0057, 0032, 0252, 0153, 0014, 0355, 0262, 0352, 0265, 
+  0002, 0155, 0321, 0361, 0155, 0345, 0255, 0212, 0205, 0346, 0330, 0140, 0113, 0152, 0030, 0254, 
+  0100, 0357, 0357, 0356, 0245, 0100, 0146, 0002, 0110, 0113, 0076, 0007, 0264, 0036, 0016, 0235, 
+  0345, 0070, 0131, 0307, 0154, 0223, 0333, 0375, 0273, 0066, 0235, 0233, 0121, 0246, 0123, 0216, 
+  0127, 0100, 0221, 0363, 0042, 0263, 0103, 0063, 0051, 0316, 0203, 0050, 0154, 0104, 0265, 0233, 
+  0077, 0034, 0140, 0017, 0151, 0112, 0233, 0025, 0007, 0313, 0262, 0343, 0265, 0350, 0255, 0263, 
+  0044, 0001, 0155, 0200, 0266, 0154, 0302, 0261, 0140, 0346, 0322, 0053, 0354, 0036, 0047, 0301, 
+  0213, 0247, 0110, 0360, 0236, 0335, 0202, 0121, 0123, 0142, 0072, 0322, 0006, 0053, 0023, 0047, 
+  0112, 0146, 0251, 0057, 0055, 0235, 0065, 0247, 0210, 0362, 0263, 0322, 0105, 0305, 0033, 0016, 
+  0020, 0364, 0064, 0266, 0317, 0033, 0266, 0313, 0147, 0373, 0262, 0142, 0266, 0011, 0007, 0254, 
+  0036, 0137, 0202, 0242, 0017, 0256, 0337, 0067, 0056, 0000, 0017, 0245, 0153, 0150, 0116, 0253, 
+  0000, 0324, 0246, 0177, 0225, 0331, 0344, 0077, 0207, 0257, 0256, 0001, 0227, 0025, 0137, 0037, 
+  0353, 0057, 0031, 0126, 0020, 0053, 0051, 0117, 0070, 0144, 0374, 0321, 0004, 0175, 0175, 0101, 
+  0137, 0126, 0111, 0267, 0053, 0226, 0117, 0210, 0371, 0317, 0266, 0133, 0103, 0377, 0226, 0376, 
+  0034, 0306, 0312, 0352, 0173, 0131, 0341, 0376, 0312, 0027, 0344, 0257, 0232, 0163, 0100, 0175, 
+  0037, 0146, 0225, 0305, 0362, 0262, 0110, 0353, 0207, 0257, 0022, 0376, 0007, 0025, 0372, 0160, 
+  0376, 0075, 0204, 0323, 0315, 0072, 0271, 0071, 0230, 0266, 0010, 0025, 0272, 0257, 0340, 0213, 
+  0314, 0142, 0246, 0347, 0334, 0274, 0145, 0317, 0023, 0363, 0166, 0351, 0236, 0072, 0371, 0243, 
+  0173, 0322, 0131, 0172, 0373, 0230, 0277, 0353, 0337, 0155, 0356, 0024, 0355, 0036, 0255, 0317, 
+  0260, 0232, 0146, 0351, 0276, 0333, 0033, 0301, 0336, 0021, 0023, 0312, 0277, 0263, 0265, 0050, 
+  0267, 0362, 0077, 0303, 0000, 0023, 0002, 0272, 0130, 0371, 0075, 0000, 0337, 0233, 0351, 0117, 
+  0371, 0213, 0043, 0102, 0153, 0141, 0063, 0135, 0367, 0332, 0107, 0164, 0323, 0377, 0315, 0233, 
+  0355, 0054, 0055, 0327, 0346, 0271, 0346, 0170, 0277, 0261, 0316, 0107, 0102, 0143, 0251, 0362, 
+  0253, 0014, 0130, 0246, 0122, 0130, 0023, 0226, 0337, 0141, 0240, 0263, 0245, 0373, 0141, 0323, 
+  0065, 0244, 0162, 0001, 0012, 0311, 0061, 0132, 0235, 0243, 0333, 0000, 0370, 0261, 0060, 0076, 
+  0212, 0311, 0277, 0223, 0273, 0313, 0052, 0334, 0075, 0137, 0356, 0356, 0065, 0271, 0273, 0276, 
+  0334, 0135, 0026, 0313, 0135, 0037, 0313, 0135, 0337, 0355, 0117, 0354, 0276, 0230, 0267, 0107, 
+  0022, 0273, 0265, 0354, 0066, 0212, 0250, 0117, 0021, 0236, 0233, 0342, 0303, 0331, 0247, 0263, 
+  0375, 0357, 0207, 0147, 0377, 0000, 0331, 0034, 0031, 0272, 0000, 0050, 0165, 0165, 0141, 0171, 
+  0051, 0165, 0151, 0057, 0001, 0000, 0000, 0000, 0002, 0000, 0000, 0000, 0011, 0000, 0000, 0000, 
+  0006, 0000, 0000, 0000, 0004, 0000, 0000, 0000, 0013, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 
+  0150, 0151, 0163, 0164, 0157, 0162, 0171, 0055, 0145, 0156, 0164, 0162, 0171, 0056, 0165, 0151, 
+  0331, 0011, 0000, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0325, 0126, 0115, 0163, 0233, 0060, 
+  0020, 0275, 0347, 0127, 0250, 0272, 0166, 0060, 0206, 0072, 0235, 0034, 0200, 0314, 0164, 0246, 
+  0361, 0245, 0307, 0364, 0314, 0054, 0322, 0032, 0124, 0013, 0211, 0112, 0302, 0037, 0375, 0365, 
+  0025, 0004, 0307, 0116, 0322, 0142, 0347, 0303, 0231, 0366, 0046, 0055, 0157, 0127, 0117, 0157, 
+  0237, 0166, 0110, 0256, 0067, 0265, 0044, 0053, 0064, 0126, 0150, 0225, 0322, 0150, 0062, 0245, 
+  0004, 0025, 0323, 0134, 0250, 0062, 0245, 0337, 0157, 0157, 0202, 0053, 0172, 0235, 0135, 0044, 
+  0037, 0202, 0200, 0314, 0121, 0241, 0001, 0207, 0234, 0254, 0205, 0253, 0110, 0051, 0201, 0043, 
+  0371, 0064, 0211, 0343, 0111, 0104, 0202, 0300, 0203, 0204, 0162, 0150, 0026, 0300, 0060, 0113, 
+  0014, 0376, 0154, 0205, 0101, 0113, 0244, 0050, 0122, 0132, 0272, 0345, 0107, 0272, 0077, 0245, 
+  0313, 0241, 0141, 0226, 0350, 0342, 0007, 0062, 0107, 0230, 0004, 0153, 0123, 0072, 0167, 0313, 
+  0271, 0021, 0234, 0022, 0301, 0175, 0106, 0267, 0312, 0222, 0306, 0350, 0006, 0215, 0333, 0022, 
+  0005, 0065, 0246, 0164, 0045, 0254, 0050, 0044, 0322, 0354, 0326, 0264, 0230, 0204, 0273, 0257, 
+  0117, 0160, 0014, 0124, 0276, 0320, 0254, 0265, 0064, 0273, 0001, 0151, 0307, 0240, 0065, 0230, 
+  0122, 0250, 0134, 0342, 0302, 0321, 0054, 0212, 0217, 0043, 0215, 0050, 0253, 0016, 0372, 0371, 
+  0070, 0324, 0072, 0060, 0047, 0126, 0105, 0305, 0217, 0324, 0144, 0132, 0266, 0265, 0312, 0053, 
+  0135, 0353, 0322, 0067, 0102, 0167, 0227, 0173, 0054, 0003, 0253, 0204, 0344, 0177, 0320, 0365, 
+  0353, 0012, 0225, 0373, 0242, 0067, 0167, 0332, 0372, 0326, 0200, 0363, 0215, 0310, 0261, 0013, 
+  0027, 0076, 0174, 0026, 0241, 0255, 0050, 0025, 0310, 0001, 0130, 0264, 0316, 0151, 0025, 0064, 
+  0336, 0022, 0066, 0350, 0317, 0245, 0244, 0002, 0305, 0045, 0232, 0003, 0102, 0114, 0012, 0266, 
+  0104, 0236, 0263, 0202, 0022, 0273, 0206, 0246, 0101, 0117, 0127, 0351, 0316, 0053, 0177, 0273, 
+  0332, 0067, 0050, 0120, 0076, 0272, 0227, 0354, 0143, 0357, 0341, 0036, 0224, 0122, 0064, 0126, 
+  0374, 0362, 0105, 0175, 0007, 0107, 0333, 0274, 0311, 0327, 0202, 0273, 0052, 0147, 0025, 0030, 
+  0137, 0071, 0032, 0001, 0157, 0100, 0172, 0355, 0150, 0066, 0035, 0301, 0154, 0167, 0230, 0311, 
+  0345, 0041, 0012, 0234, 0063, 0302, 0213, 0215, 0366, 0140, 0075, 0244, 0364, 0074, 0311, 0012, 
+  0144, 0353, 0067, 0321, 0154, 0072, 0235, 0166, 0302, 0206, 0207, 0051, 0341, 0235, 0276, 0176, 
+  0061, 0350, 0175, 0037, 0150, 0200, 0055, 0375, 0114, 0170, 0302, 0243, 0173, 0070, 0271, 0057, 
+  0001, 0254, 0032, 0047, 0354, 0164, 0163, 0022, 0256, 0127, 0211, 0146, 0263, 0103, 0110, 0170, 
+  0177, 0372, 0216, 0327, 0163, 0354, 0140, 0267, 0165, 0241, 0337, 0307, 0017, 0203, 0363, 0322, 
+  0067, 0167, 0302, 0303, 0056, 0277, 0336, 0013, 0153, 0354, 0307, 0330, 0316, 0015, 0262, 0337, 
+  0205, 0307, 0074, 0023, 0217, 0172, 0346, 0044, 0213, 0314, 0136, 0142, 0221, 0323, 0373, 0377, 
+  0160, 0322, 0201, 0262, 0153, 0064, 0377, 0314, 0234, 0033, 0350, 0274, 0156, 0312, 0015, 0105, 
+  0376, 0213, 0031, 0027, 0237, 0140, 0355, 0350, 0254, 0306, 0366, 0017, 0237, 0037, 0367, 0365, 
+  0071, 0146, 0341, 0345, 0333, 0315, 0302, 0170, 0374, 0055, 0354, 0211, 0356, 0177, 0300, 0056, 
+  0176, 0003, 0003, 0135, 0215, 0340, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0155, 0141, 0164, 
+  0145, 0057, 0000, 0000, 0012, 0000, 0000, 0000, 0142, 0165, 0164, 0164, 0157, 0156, 0163, 0055, 
+  0160, 0162, 0157, 0147, 0162, 0141, 0155, 0155, 0151, 0156, 0147, 0056, 0165, 0151, 0000, 0000, 
+  0146, 0071, 0001, 0000, 0001, 0000, 0000, 0000, 0170, 0332, 0355, 0135, 0313, 0216, 0343, 0066, 
+  0026, 0335, 0347, 0053, 0024, 0055, 0202, 0004, 0201, 0272, 0054, 0311, 0162, 0331, 0235, 0262, 
+  0203, 0112, 0115, 0167, 0243, 0201, 0040, 0001, 0222, 0236, 0307, 0316, 0240, 0045, 0332, 0146, 
+  0112, 0026, 0035, 0221, 0362, 0043, 0310, 0142, 0046, 0213, 0040, 0333, 0311, 0054, 0006, 0230, 
+  0335, 0174, 0305, 0174, 0100, 0376, 0244, 0277, 0144, 0110, 0311, 0157, 0273, 0054, 0333, 0115, 
+  0221, 0125, 0054, 0256, 0312, 0045, 0121, 0022, 0171, 0317, 0341, 0345, 0345, 0021, 0171, 0165, 
+  0363, 0345, 0154, 0024, 0133, 0023, 0230, 0022, 0204, 0223, 0266, 0355, 0276, 0250, 0331, 0026, 
+  0114, 0102, 0034, 0241, 0144, 0320, 0266, 0377, 0374, 0356, 0265, 0323, 0264, 0277, 0354, 0174, 
+  0164, 0363, 0261, 0343, 0130, 0157, 0140, 0002, 0123, 0100, 0141, 0144, 0115, 0021, 0035, 0132, 
+  0203, 0030, 0104, 0320, 0362, 0137, 0370, 0315, 0027, 0236, 0345, 0070, 0254, 0020, 0112, 0050, 
+  0114, 0373, 0040, 0204, 0235, 0233, 0024, 0376, 0230, 0241, 0024, 0022, 0053, 0106, 0275, 0266, 
+  0075, 0240, 0367, 0237, 0333, 0353, 0247, 0370, 0057, 0074, 0317, 0276, 0352, 0334, 0340, 0336, 
+  0017, 0060, 0244, 0126, 0030, 0003, 0102, 0332, 0366, 0033, 0172, 0377, 0047, 0004, 0142, 0074, 
+  0260, 0055, 0024, 0265, 0355, 0160, 0010, 0122, 0020, 0262, 0033, 0166, 0131, 0155, 0140, 0067, 
+  0052, 0116, 0165, 0156, 0306, 0051, 0036, 0303, 0224, 0316, 0255, 0004, 0214, 0040, 0053, 0006, 
+  0022, 0247, 0217, 0303, 0214, 0330, 0235, 0327, 0040, 0046, 0360, 0346, 0152, 0131, 0140, 0257, 
+  0150, 0017, 0247, 0021, 0114, 0235, 0051, 0212, 0350, 0320, 0356, 0064, 0216, 0224, 0244, 0210, 
+  0306, 0320, 0266, 0150, 0012, 0022, 0022, 0003, 0012, 0172, 0061, 0073, 0070, 0207, 0304, 0266, 
+  0102, 0074, 0032, 0301, 0204, 0262, 0352, 0276, 0343, 0145, 0054, 0334, 0267, 0120, 0102, 0330, 
+  0245, 0326, 0252, 0276, 0026, 0257, 0257, 0265, 0254, 0357, 0333, 0342, 0354, 0335, 0352, 0354, 
+  0035, 0073, 0173, 0344, 0321, 0314, 0146, 0350, 0047, 0376, 0300, 0362, 0366, 0240, 0020, 0047, 
+  0016, 0377, 0151, 0167, 0100, 0030, 0102, 0102, 0160, 0212, 0040, 0161, 0102, 0020, 0207, 0031, 
+  0253, 0065, 0116, 0217, 0265, 0160, 0076, 0206, 0316, 0220, 0001, 0146, 0167, 0212, 0232, 0156, 
+  0226, 0045, 0150, 0220, 0200, 0170, 0121, 0062, 0202, 0061, 0244, 0320, 0201, 0023, 0326, 0154, 
+  0333, 0032, 0202, 0044, 0212, 0141, 0372, 0000, 0074, 0335, 0242, 0160, 0067, 0354, 0331, 0026, 
+  0231, 0202, 0361, 0030, 0062, 0040, 0023, 0314, 0261, 0336, 0272, 0047, 0153, 0344, 0030, 0063, 
+  0303, 0224, 0336, 0157, 0131, 0360, 0320, 0035, 0303, 0041, 0212, 0043, 0053, 0347, 0034, 0273, 
+  0263, 0223, 0377, 0333, 0266, 0047, 0075, 0074, 0263, 0017, 0120, 0353, 0053, 0166, 0070, 0347, 
+  0125, 0161, 0147, 0207, 0227, 0363, 0367, 0351, 0064, 0101, 0004, 0345, 0306, 0177, 0227, 0146, 
+  0307, 0154, 0177, 0006, 0355, 0070, 0052, 0011, 0005, 0224, 0121, 0337, 0356, 0260, 0076, 0100, 
+  0021, 0103, 0350, 0110, 0171, 0062, 0006, 0041, 0353, 0175, 0166, 0307, 0365, 0066, 0113, 0035, 
+  0156, 0056, 0063, 0031, 0273, 0157, 0027, 0244, 0020, 0034, 0154, 0165, 0106, 0051, 0116, 0166, 
+  0333, 0276, 0161, 0221, 0034, 0023, 0304, 0140, 0216, 0063, 0352, 0020, 0072, 0347, 0367, 0205, 
+  0111, 0264, 0327, 0260, 0007, 0353, 0136, 0124, 0274, 0227, 0377, 0156, 0331, 0007, 0356, 0334, 
+  0203, 0361, 0241, 0236, 0332, 0351, 0336, 0201, 0044, 0204, 0307, 0014, 0175, 0101, 0103, 0117, 
+  0050, 0031, 0301, 0076, 0310, 0142, 0132, 0132, 0066, 0205, 0041, 0104, 0023, 0326, 0137, 0117, 
+  0275, 0040, 0043, 0320, 0311, 0022, 0346, 0301, 0142, 0224, 0034, 0250, 0364, 0125, 0141, 0100, 
+  0166, 0031, 0010, 0357, 0031, 0177, 0366, 0256, 0207, 0263, 0061, 0353, 0154, 0345, 0140, 0365, 
+  0121, 0034, 0227, 0227, 0032, 0143, 0202, 0012, 0112, 0327, 0266, 0152, 0261, 0172, 0372, 0325, 
+  0002, 0327, 0323, 0341, 0155, 0236, 0001, 0357, 0206, 0043, 0136, 0170, 0330, 0333, 0357, 0357, 
+  0336, 0276, 0135, 0270, 0335, 0227, 0126, 0161, 0167, 0213, 0342, 0245, 0173, 0046, 0314, 0063, 
+  0205, 0174, 0354, 0132, 0071, 0032, 0106, 0221, 0342, 0122, 0103, 0221, 0252, 0051, 0342, 0036, 
+  0247, 0210, 0340, 0172, 0225, 0030, 0211, 0077, 0304, 0341, 0343, 0337, 0236, 0047, 0022, 0116, 
+  0361, 0245, 0337, 0035, 0262, 0301, 0306, 0163, 0245, 0270, 0332, 0355, 0040, 0047, 0270, 0160, 
+  0234, 0071, 0320, 0230, 0257, 0213, 0256, 0310, 0233, 0223, 0367, 0112, 0277, 0045, 0151, 0350, 
+  0270, 0320, 0003, 0344, 0365, 0265, 0172, 0260, 0217, 0123, 0270, 0021, 0234, 0261, 0053, 0322, 
+  0271, 0335, 0271, 0033, 0166, 0027, 0107, 0136, 0136, 0336, 0237, 0166, 0112, 0217, 0022, 0070, 
+  0302, 0011, 0012, 0271, 0361, 0007, 0220, 0365, 0326, 0235, 0230, 0046, 0177, 0364, 0123, 0166, 
+  0331, 0257, 0162, 0333, 0035, 0212, 0316, 0027, 0126, 0255, 0336, 0175, 0216, 0300, 0314, 0211, 
+  0141, 0062, 0340, 0344, 0166, 0037, 0214, 0131, 0171, 0200, 0063, 0141, 0063, 0225, 0322, 0370, 
+  0162, 0131, 0360, 0120, 0174, 0051, 0331, 0053, 0011, 0167, 0226, 0045, 0017, 0254, 0250, 0126, 
+  0313, 0003, 0105, 0214, 0271, 0350, 0012, 0144, 0347, 0177, 0153, 0031, 0327, 0267, 0155, 0247, 
+  0141, 0167, 0026, 0321, 0335, 0315, 0325, 0126, 0241, 0043, 0327, 0004, 0313, 0153, 0232, 0173, 
+  0327, 0134, 0355, 0076, 0170, 0125, 0263, 0075, 0072, 0377, 0025, 0045, 0021, 0236, 0026, 0174, 
+  0236, 0346, 0277, 0335, 0363, 0346, 0227, 0245, 0176, 0277, 0250, 0144, 0227, 0341, 0301, 0174, 
+  0330, 0243, 0236, 0153, 0064, 0316, 0152, 0027, 0037, 0317, 0344, 0014, 0147, 0347, 0125, 0360, 
+  0016, 0217, 0172, 0170, 0155, 0175, 0300, 0047, 0216, 0374, 0220, 0224, 0252, 0346, 0305, 0034, 
+  0106, 0275, 0060, 0106, 0341, 0375, 0201, 0362, 0252, 0034, 0312, 0205, 0336, 0176, 0143, 0300, 
+  0317, 0055, 0131, 0214, 0304, 0022, 0307, 0374, 0365, 0000, 0377, 0152, 0006, 0106, 0343, 0230, 
+  0015, 0343, 0230, 0115, 0177, 0271, 0146, 0361, 0372, 0365, 0373, 0137, 0376, 0361, 0376, 0227, 
+  0137, 0055, 0057, 0150, 0344, 0277, 0376, 0176, 0344, 0166, 0063, 0020, 0263, 0301, 0141, 0327, 
+  0205, 0075, 0156, 0067, 0372, 0064, 0050, 0162, 0313, 0015, 0073, 0312, 0205, 0241, 0234, 0046, 
+  0210, 0112, 0364, 0165, 0063, 0302, 0174, 0033, 0334, 0251, 0373, 0116, 0231, 0371, 0241, 0062, 
+  0213, 0326, 0160, 0111, 0223, 0165, 0126, 0034, 0147, 0243, 0204, 0264, 0375, 0026, 0373, 0047, 
+  0305, 0123, 0322, 0256, 0163, 0061, 0163, 0277, 0255, 0157, 0122, 0024, 0255, 0233, 0111, 0013, 
+  0211, 0256, 0212, 0146, 0076, 0030, 0175, 0161, 0005, 0156, 0355, 0334, 0130, 0045, 0162, 0115, 
+  0216, 0271, 0342, 0156, 0105, 0276, 0170, 0053, 0246, 0052, 0306, 0062, 0147, 0314, 0206, 0141, 
+  0262, 0247, 0006, 0346, 0046, 0301, 0203, 0101, 0374, 0260, 0122, 0127, 0342, 0141, 0330, 0015, 
+  0362, 0156, 0337, 0165, 0045, 0272, 0230, 0216, 0125, 0073, 0301, 0157, 0324, 0016, 0372, 0215, 
+  0223, 0273, 0154, 0014, 0373, 0324, 0001, 0224, 0202, 0160, 0067, 0146, 0335, 0325, 0144, 0361, 
+  0170, 0125, 0356, 0322, 0010, 0375, 0141, 0216, 0170, 0032, 0161, 0304, 0323, 0232, 0043, 0236, 
+  0062, 0216, 0370, 0032, 0161, 0304, 0327, 0232, 0043, 0276, 0062, 0216, 0324, 0065, 0342, 0110, 
+  0135, 0153, 0216, 0004, 0312, 0070, 0022, 0150, 0304, 0221, 0100, 0153, 0216, 0064, 0224, 0161, 
+  0244, 0241, 0021, 0107, 0032, 0132, 0163, 0344, 0132, 0031, 0107, 0256, 0065, 0342, 0310, 0265, 
+  0326, 0034, 0151, 0052, 0343, 0110, 0123, 0043, 0216, 0064, 0365, 0236, 0373, 0326, 0224, 0221, 
+  0244, 0245, 0021, 0111, 0132, 0172, 0223, 0104, 0235, 0102, 0342, 0326, 0164, 0222, 0321, 0152, 
+  0172, 0323, 0104, 0235, 0110, 0342, 0152, 0245, 0266, 0152, 0056, 0267, 0252, 0323, 0111, 0134, 
+  0235, 0004, 0127, 0127, 0157, 0305, 0325, 0125, 0047, 0225, 0270, 0072, 0151, 0256, 0256, 0336, 
+  0242, 0253, 0253, 0116, 0055, 0161, 0165, 0222, 0135, 0135, 0275, 0165, 0127, 0127, 0235, 0140, 
+  0342, 0352, 0244, 0274, 0272, 0172, 0113, 0257, 0256, 0072, 0315, 0304, 0327, 0051, 0204, 0365, 
+  0365, 0016, 0141, 0175, 0205, 0064, 0321, 0151, 0102, 0354, 0353, 0075, 0041, 0366, 0325, 0015, 
+  0072, 0236, 0116, 0352, 0232, 0247, 0267, 0274, 0346, 0253, 0013, 0141, 0075, 0235, 0224, 0172, 
+  0117, 0157, 0251, 0336, 0127, 0067, 0041, 0366, 0164, 0172, 0351, 0347, 0351, 0375, 0326, 0317, 
+  0127, 0047, 0257, 0171, 0072, 0255, 0037, 0360, 0364, 0136, 0100, 0340, 0253, 0023, 0353, 0075, 
+  0235, 0046, 0304, 0236, 0336, 0023, 0142, 0137, 0341, 0342, 0150, 0235, 0344, 0065, 0117, 0157, 
+  0171, 0315, 0127, 0267, 0214, 0300, 0323, 0111, 0254, 0367, 0364, 0026, 0353, 0075, 0165, 0272, 
+  0211, 0247, 0325, 0136, 0013, 0315, 0067, 0133, 0050, 0324, 0115, 0164, 0122, 0141, 0075, 0275, 
+  0125, 0130, 0117, 0241, 0156, 0242, 0223, 0012, 0353, 0351, 0255, 0302, 0172, 0012, 0027, 0022, 
+  0350, 0244, 0302, 0272, 0172, 0253, 0260, 0236, 0302, 0145, 0111, 0072, 0251, 0260, 0256, 0336, 
+  0052, 0254, 0247, 0160, 0221, 0243, 0116, 0052, 0254, 0253, 0267, 0012, 0353, 0051, 0134, 0062, 
+  0255, 0223, 0012, 0353, 0352, 0255, 0302, 0172, 0025, 0353, 0046, 0073, 0066, 0035, 0201, 0364, 
+  0036, 0246, 0205, 0151, 0245, 0116, 0041, 0217, 0252, 0315, 0077, 0144, 0204, 0242, 0376, 0334, 
+  0356, 0204, 0220, 0147, 0122, 0275, 0030, 0002, 0261, 0113, 0067, 0134, 0341, 0026, 0227, 0252, 
+  0024, 0327, 0236, 0234, 0301, 0175, 0361, 0153, 0145, 0264, 0312, 0235, 0340, 0233, 0044, 0054, 
+  0273, 0211, 0070, 0304, 0260, 0104, 0247, 0367, 0014, 0176, 0335, 0244, 0141, 0251, 0206, 0045, 
+  0072, 0275, 0264, 0364, 0003, 0223, 0210, 0245, 0032, 0226, 0350, 0024, 0173, 0373, 0015, 0223, 
+  0212, 0245, 0032, 0226, 0350, 0064, 0221, 0367, 0257, 0115, 0062, 0226, 0152, 0130, 0242, 0223, 
+  0052, 0350, 0067, 0115, 0072, 0226, 0152, 0130, 0242, 0323, 0053, 0006, 0277, 0145, 0022, 0262, 
+  0124, 0302, 0222, 0272, 0116, 0357, 0053, 0353, 0065, 0223, 0222, 0245, 0042, 0232, 0350, 0264, 
+  0372, 0241, 0356, 0232, 0244, 0054, 0025, 0321, 0104, 0247, 0265, 0124, 0165, 0317, 0044, 0145, 
+  0251, 0210, 0046, 0072, 0311, 0257, 0165, 0337, 0044, 0145, 0251, 0210, 0046, 0132, 0145, 0257, 
+  0255, 0233, 0244, 0054, 0025, 0321, 0104, 0047, 0001, 0266, 0036, 0230, 0244, 0054, 0025, 0321, 
+  0104, 0047, 0005, 0266, 0336, 0060, 0111, 0131, 0052, 0242, 0211, 0116, 0022, 0154, 0375, 0332, 
+  0044, 0145, 0251, 0210, 0046, 0072, 0151, 0260, 0365, 0246, 0131, 0113, 0125, 0021, 0115, 0164, 
+  0022, 0141, 0353, 0055, 0263, 0062, 0263, 0032, 0232, 0004, 0072, 0251, 0260, 0101, 0315, 0254, 
+  0363, 0256, 0210, 0046, 0072, 0251, 0260, 0201, 0153, 0166, 0215, 0124, 0104, 0023, 0235, 0124, 
+  0330, 0300, 0063, 0173, 0320, 0052, 0242, 0211, 0116, 0052, 0154, 0340, 0233, 0035, 0255, 0025, 
+  0321, 0104, 0047, 0025, 0066, 0250, 0233, 0375, 0361, 0025, 0321, 0104, 0253, 0317, 0210, 0005, 
+  0046, 0333, 0106, 0105, 0064, 0321, 0111, 0205, 0015, 0032, 0046, 0167, 0117, 0105, 0064, 0321, 
+  0111, 0205, 0015, 0256, 0115, 0046, 0260, 0212, 0150, 0242, 0223, 0012, 0033, 0064, 0115, 0136, 
+  0301, 0212, 0150, 0242, 0223, 0012, 0033, 0264, 0114, 0226, 0322, 0152, 0150, 0322, 0320, 0111, 
+  0205, 0155, 0324, 0114, 0316, 0343, 0212, 0150, 0242, 0223, 0012, 0333, 0160, 0115, 0006, 0365, 
+  0212, 0150, 0242, 0223, 0012, 0333, 0360, 0314, 0367, 0030, 0052, 0242, 0211, 0116, 0052, 0154, 
+  0303, 0067, 0137, 0167, 0371, 0000, 0232, 0034, 0111, 0021, 0042, 0325, 0115, 0327, 0257, 0037, 
+  0113, 0216, 0220, 0223, 0227, 0156, 0210, 0117, 0312, 0042, 0125, 0051, 0076, 0272, 0174, 0366, 
+  0161, 0132, 0334, 0377, 0140, 0213, 0027, 0331, 0206, 0344, 0112, 0255, 0126, 0265, 0326, 0253, 
+  0113, 0313, 0332, 0124, 0030, 0257, 0241, 0223, 0361, 0132, 0222, 0215, 0167, 0255, 0223, 0361, 
+  0134, 0331, 0324, 0153, 0152, 0145, 0075, 0331, 0334, 0153, 0351, 0144, 0075, 0117, 0062, 0367, 
+  0044, 0177, 0035, 0256, 0152, 0353, 0111, 0346, 0236, 0344, 0117, 0060, 0126, 0154, 0075, 0137, 
+  0066, 0367, 0274, 0347, 0030, 0257, 0170, 0202, 0214, 0347, 0077, 0307, 0170, 0105, 0224, 0361, 
+  0352, 0317, 0062, 0136, 0021, 0145, 0275, 0340, 0131, 0306, 0053, 0242, 0254, 0327, 0170, 0226, 
+  0361, 0212, 0050, 0353, 0135, 0077, 0313, 0170, 0105, 0224, 0365, 0232, 0317, 0062, 0136, 0021, 
+  0057, 0065, 0353, 0364, 0172, 0123, 0357, 0267, 0233, 0352, 0222, 0177, 0113, 0265, 0153, 0303, 
+  0177, 0054, 0252, 0247, 0154, 0231, 0171, 0145, 0157, 0251, 0001, 0361, 0321, 0225, 0132, 0217, 
+  0322, 0336, 0025, 0244, 0376, 0326, 0351, 0265, 0254, 0357, 0031, 0067, 0170, 0362, 0120, 0071, 
+  0216, 0101, 0010, 0207, 0070, 0216, 0140, 0172, 0145, 0116, 0232, 0223, 0346, 0244, 0071, 0151, 
+  0116, 0232, 0223, 0346, 0244, 0071, 0271, 0035, 0234, 0234, 0034, 0255, 0300, 0331, 0230, 0105, 
+  0165, 0345, 0001, 0124, 0037, 0305, 0161, 0151, 0100, 0066, 0306, 0004, 0121, 0204, 0223, 0123, 
+  0147, 0031, 0037, 0073, 0216, 0225, 0070, 0041, 0216, 0263, 0121, 0102, 0332, 0156, 0215, 0375, 
+  0223, 0342, 0051, 0151, 0007, 0226, 0343, 0034, 0010, 0040, 0337, 0244, 0050, 0052, 0342, 0107, 
+  0020, 0115, 0100, 0022, 0302, 0250, 0313, 0052, 0317, 0343, 0072, 0011, 0021, 0044, 0253, 0230, 
+  0063, 0304, 0043, 0074, 0200, 0011, 0304, 0374, 0202, 0262, 0133, 0347, 0255, 0072, 0176, 0311, 
+  0103, 0221, 0362, 0127, 0171, 0360, 0135, 0064, 0065, 0004, 0161, 0330, 0115, 0061, 0246, 0335, 
+  0042, 0044, 0267, 0037, 0212, 0155, 0337, 0377, 0366, 0237, 0043, 0325, 0271, 0300, 0042, 0045, 
+  0045, 0363, 0122, 0016, 0233, 0043, 0204, 0061, 0012, 0357, 0117, 0060, 0040, 0014, 0041, 0232, 
+  0100, 0342, 0104, 0260, 0017, 0262, 0230, 0226, 0076, 0040, 0043, 0320, 0311, 0022, 0106, 0360, 
+  0030, 0045, 0007, 0052, 0276, 0065, 0135, 0311, 0353, 0000, 0243, 0315, 0071, 0112, 0156, 0255, 
+  0103, 0363, 0223, 0107, 0225, 0376, 0174, 0017, 0352, 0030, 0017, 0100, 0212, 0350, 0160, 0124, 
+  0206, 0067, 0053, 0370, 0304, 0361, 0176, 0144, 0010, 0372, 0202, 0020, 0354, 0203, 0220, 0342, 
+  0264, 0014, 0076, 0136, 0312, 0364, 0327, 0065, 0332, 0205, 0325, 0320, 0117, 0017, 0113, 0012, 
+  0026, 0342, 0252, 0016, 0273, 0207, 0223, 0377, 0313, 0106, 0201, 0060, 0204, 0144, 0141, 0246, 
+  0035, 0134, 0156, 0351, 0375, 0267, 0371, 0201, 0207, 0160, 0141, 0250, 0337, 0027, 0227, 0354, 
+  0043, 0264, 0272, 0370, 0345, 0313, 0365, 0043, 0034, 0176, 0316, 0266, 0150, 0012, 0022, 0022, 
+  0003, 0012, 0330, 0241, 0266, 0075, 0207, 0304, 0266, 0102, 0074, 0032, 0301, 0204, 0362, 0247, 
+  0256, 0112, 0347, 0167, 0262, 0372, 0070, 0265, 0350, 0220, 0375, 0135, 0266, 0315, 0132, 0222, 
+  0342, 0365, 0362, 0210, 0202, 0017, 0065, 0324, 0005, 0361, 0074, 0001, 0064, 0113, 0101, 0174, 
+  0206, 0307, 0112, 0014, 0341, 0305, 0273, 0267, 0246, 0144, 0367, 0006, 0172, 0344, 0101, 0240, 
+  0015, 0210, 0347, 0250, 0240, 0362, 0227, 0305, 0377, 0374, 0111, 0114, 0277, 0100, 0237, 0014, 
+  0350, 0027, 0063, 0376, 0353, 0052, 0377, 0371, 0163, 0211, 0165, 0370, 0313, 0225, 0154, 0274, 
+  0137, 0233, 0075, 0167, 0045, 0304, 0113, 0257, 0351, 0045, 0325, 0105, 0263, 0307, 0262, 0200, 
+  0235, 0102, 0153, 0002, 0342, 0154, 0355, 0247, 0157, 0227, 0207, 0377, 0302, 0017, 0013, 0164, 
+  0326, 0255, 0152, 0137, 0327, 0354, 0365, 0132, 0216, 0312, 0000, 0246, 0335, 0061, 0116, 0371, 
+  0014, 0255, 0314, 0125, 0263, 0342, 0306, 0127, 0213, 0367, 0325, 0055, 0331, 0241, 0150, 0312, 
+  0342, 0014, 0006, 0067, 0033, 0245, 0117, 0004, 0236, 0137, 0141, 0220, 0127, 0207, 0274, 0250, 
+  0340, 0054, 0102, 0023, 0024, 0301, 0062, 0264, 0377, 0370, 0237, 0301, 0132, 0074, 0326, 0165, 
+  0311, 0276, 0175, 0304, 0114, 0203, 0306, 0361, 0274, 0024, 0355, 0177, 0033, 0264, 0325, 0241, 
+  0055, 0112, 0040, 0042, 0131, 0217, 0162, 0267, 0136, 0256, 0007, 0376, 0156, 0340, 0136, 0303, 
+  0275, 0062, 0233, 0064, 0300, 0205, 0115, 0270, 0242, 0250, 0014, 0353, 0317, 0015, 0322, 0352, 
+  0072, 0266, 0250, 0041, 0073, 0205, 0204, 0031, 0247, 0004, 0352, 0343, 0263, 0233, 0174, 0162, 
+  0151, 0341, 0044, 0237, 0322, 0260, 0231, 0313, 0144, 0071, 0223, 0261, 0076, 0315, 0355, 0304, 
+  0052, 0306, 0116, 0041, 0122, 0234, 0043, 0171, 0261, 0010, 0221, 0161, 0014, 0346, 0060, 0262, 
+  0170, 0055, 0062, 0166, 0153, 0026, 0046, 0176, 0146, 0167, 0332, 0206, 0123, 0033, 0336, 0203, 
+  0333, 0353, 0020, 0245, 0010, 0235, 0307, 0220, 0201, 0314, 0141, 0135, 0134, 0115, 0262, 0301, 
+  0000, 0022, 0012, 0043, 0247, 0010, 0276, 0163, 0346, 0055, 0312, 0125, 0363, 0201, 0136, 0121, 
+  0014, 0014, 0143, 0010, 0322, 0363, 0011, 0330, 0271, 0343, 0327, 0031, 0272, 0254, 0351, 0122, 
+  0030, 0362, 0064, 0272, 0104, 0214, 0053, 0151, 0306, 0230, 0062, 0201, 0322, 0010, 0043, 0152, 
+  0150, 0162, 0313, 0006, 0046, 0327, 0260, 0142, 0315, 0212, 0010, 0015, 0220, 0200, 0370, 0303, 
+  0225, 0354, 0025, 0274, 0062, 0220, 0075, 0003, 0262, 0160, 0220, 0075, 0311, 0040, 0373, 0145, 
+  0040, 0373, 0006, 0144, 0341, 0040, 0373, 0222, 0101, 0016, 0312, 0100, 0016, 0014, 0310, 0312, 
+  0334, 0265, 0250, 0061, 0271, 0121, 0006, 0162, 0303, 0200, 0254, 0314, 0135, 0213, 0002, 0371, 
+  0272, 0014, 0344, 0153, 0003, 0262, 0062, 0167, 0055, 0012, 0344, 0126, 0031, 0310, 0055, 0003, 
+  0262, 0062, 0167, 0055, 0112, 0316, 0165, 0153, 0145, 0050, 0337, 0032, 0224, 0225, 0371, 0153, 
+  0141, 0050, 0227, 0316, 0224, 0277, 0062, 0050, 0053, 0163, 0330, 0302, 0120, 0056, 0235, 0105, 
+  0375, 0311, 0240, 0254, 0314, 0143, 0213, 0172, 0335, 0352, 0326, 0313, 0120, 0176, 0145, 0120, 
+  0126, 0346, 0261, 0205, 0241, 0134, 0072, 0131, 0176, 0155, 0120, 0126, 0346, 0261, 0057, 0104, 
+  0371, 0135, 0276, 0151, 0375, 0300, 0053, 0165, 0166, 0047, 0022, 0246, 0150, 0114, 0237, 0364, 
+  0322, 0326, 0262, 0227, 0130, 0220, 0156, 0065, 0365, 0003, 0126, 0255, 0112, 0115, 0372, 0360, 
+  0376, 0327, 0177, 0046, 0217, 0152, 0215, 0352, 0076, 0137, 0244, 0256, 0125, 0335, 0170, 0274, 
+  0065, 0302, 0321, 0172, 0265, 0352, 0367, 0353, 0023, 0042, 0277, 0121, 0137, 0155, 0052, 0227, 
+  0375, 0175, 0005, 0331, 0010, 0246, 0050, 0354, 0216, 0061, 0203, 0251, 0354, 0155, 0344, 0356, 
+  0273, 0157, 0376, 0156, 0033, 0122, 0006, 0260, 0065, 0240, 0367, 0057, 0102, 0213, 0142, 0136, 
+  0144, 0034, 0317, 0255, 0051, 0242, 0103, 0353, 0353, 0073, 0253, 0037, 0203, 0001, 0343, 0336, 
+  0013, 0343, 0275, 0327, 0236, 0141, 0333, 0344, 0322, 0306, 0152, 0121, 0214, 0031, 0301, 0021, 
+  0116, 0347, 0072, 0273, 0356, 0105, 0013, 0317, 0360, 0330, 0253, 0334, 0061, 0303, 0036, 0236, 
+  0171, 0162, 0222, 0042, 0021, 0006, 0041, 0103, 0160, 0147, 0030, 0077, 0071, 0243, 0260, 0314, 
+  0101, 0345, 0270, 0347, 0175, 0307, 0274, 0154, 0274, 0271, 0226, 0246, 0260, 0377, 0312, 0321, 
+  0316, 0316, 0312, 0033, 0264, 0334, 0143, 0135, 0106, 0252, 0363, 0266, 0130, 0137, 0330, 0171, 
+  0156, 0323, 0024, 0117, 0027, 0273, 0250, 0371, 0117, 0127, 0116, 0116, 0316, 0374, 0131, 0016, 
+  0235, 0217, 0331, 0135, 0043, 0074, 0115, 0056, 0062, 0240, 0334, 0115, 0352, 0325, 0304, 0016, 
+  0133, 0276, 0112, 0156, 0330, 0100, 0161, 0272, 0273, 0277, 0345, 0173, 0176, 0114, 0344, 0367, 
+  0105, 0044, 0173, 0376, 0131, 0371, 0106, 0333, 0277, 0175, 0373, 0235, 0031, 0352, 0305, 0257, 
+  0216, 0014, 0044, 0277, 0273, 0056, 0007, 0332, 0340, 0254, 0022, 0147, 0141, 0253, 0235, 0223, 
+  0322, 0325, 0316, 0267, 0337, 0030, 0031, 0125, 0041, 0322, 0242, 0324, 0162, 0066, 0165, 0315, 
+  0342, 0214, 0234, 0270, 0125, 0211, 0225, 0066, 0240, 0253, 0003, 0135, 0224, 0254, 0112, 0050, 
+  0110, 0151, 0167, 0220, 0342, 0154, 0134, 0206, 0370, 0247, 0006, 0157, 0165, 0233, 0032, 0104, 
+  0005, 0150, 0220, 0271, 0363, 0223, 0320, 0376, 0314, 0240, 0255, 0256, 0167, 0213, 0102, 0233, 
+  0014, 0121, 0237, 0166, 0171, 0025, 0264, 0326, 0321, 0327, 0255, 0274, 0124, 0220, 0161, 0335, 
+  0047, 0040, 0310, 0134, 0313, 0100, 0157, 0321, 0375, 0171, 0072, 0012, 0175, 0104, 0225, 0300, 
+  0150, 0052, 0062, 0065, 0225, 0075, 0267, 0043, 0127, 0127, 0341, 0117, 0267, 0370, 0323, 0327, 
+  0262, 0112, 0176, 0350, 0153, 0166, 0110, 0240, 0266, 0322, 0120, 0342, 0314, 0123, 0064, 0030, 
+  0076, 0003, 0157, 0136, 0064, 0363, 0142, 0167, 0376, 0024, 0364, 0365, 0206, 0114, 0167, 0076, 
+  0320, 0311, 0235, 0033, 0211, 0134, 0201, 0073, 0337, 0164, 0074, 0012, 0374, 0171, 0376, 0370, 
+  0035, 0207, 0376, 0035, 0077, 0246, 0040, 0143, 0237, 0260, 0067, 0353, 0345, 0131, 0144, 0277, 
+  0371, 0366, 0235, 0231, 0210, 0211, 0237, 0210, 0065, 0044, 0153, 0153, 0213, 0214, 0223, 0040, 
+  0326, 0171, 0344, 0026, 0220, 0174, 0117, 0352, 0007, 0011, 0017, 0045, 0337, 0373, 0370, 0121, 
+  0055, 0154, 0332, 0245, 0215, 0212, 0054, 0251, 0014, 0360, 0235, 0054, 0251, 0040, 0026, 0350, 
+  0163, 0233, 0222, 0337, 0133, 0241, 0144, 0002, 0123, 0002, 0115, 0077, 0074, 0272, 0364, 0243, 
+  0246, 0272, 0037, 0362, 0137, 0044, 0033, 0363, 0237, 0357, 0177, 0373, 0335, 0315, 0117, 0054, 
+  0376, 0277, 0260, 0207, 0236, 0376, 0161, 0252, 0152, 0372, 0362, 0066, 0361, 0244, 0366, 0344, 
+  0305, 0243, 0127, 0375, 0370, 0155, 0361, 0277, 0202, 0364, 0231, 0242, 0306, 0323, 0131, 0167, 
+  0214, 0247, 0335, 0271, 0351, 0305, 0017, 0364, 0342, 0245, 0175, 0026, 0075, 0354, 0321, 0364, 
+  0345, 0325, 0351, 0371, 0366, 0351, 0017, 0354, 0333, 0325, 0364, 0330, 0155, 0222, 0111, 0355, 
+  0261, 0154, 0372, 0210, 0023, 0126, 0004, 0345, 0331, 0237, 0254, 0117, 0147, 0174, 0341, 0054, 
+  0077, 0301, 0152, 0004, 0123, 0013, 0367, 0255, 0371, 0147, 0253, 0356, 0374, 0152, 0121, 0130, 
+  0301, 0250, 0054, 0252, 0077, 0263, 0372, 0223, 0156, 0276, 0060, 0030, 0162, 0313, 0224, 0315, 
+  0212, 0170, 0161, 0063, 0055, 0122, 0067, 0055, 0022, 0365, 0366, 0231, 0116, 0361, 0071, 0260, 
+  0363, 0342, 0006, 0166, 0165, 0137, 0344, 0020, 0275, 0313, 0247, 0367, 0134, 0366, 0370, 0364, 
+  0076, 0174, 0207, 0117, 0135, 0356, 0016, 0237, 0177, 0075, 0266, 0035, 0076, 0075, 0225, 0373, 
+  0173, 0172, 0207, 0167, 0367, 0364, 0204, 0357, 0355, 0251, 0111, 0126, 0040, 0335, 0322, 0144, 
+  0142, 0167, 0306, 0341, 0012, 0337, 0125, 0131, 0223, 0074, 0314, 0066, 0313, 0100, 0156, 0032, 
+  0220, 0225, 0201, 0054, 0052, 0204, 0056, 0335, 0005, 0137, 0067, 0040, 0053, 0003, 0131, 0324, 
+  0152, 0354, 0322, 0344, 0064, 0307, 0052, 0064, 0105, 0021, 0035, 0072, 0051, 0374, 0061, 0203, 
+  0204, 0331, 0067, 0250, 0031, 0102, 0050, 0043, 0204, 0260, 0024, 0301, 0103, 0300, 0263, 0250, 
+  0303, 0322, 0335, 0030, 0177, 0374, 0127, 0357, 0257, 0023, 0242, 0204, 0260, 0162, 0033, 0366, 
+  0010, 0131, 0254, 0126, 0331, 0267, 0353, 0166, 0315, 0056, 0131, 0316, 0345, 0115, 0265, 0126, 
+  0165, 0330, 0320, 0165, 0363, 0023, 0167, 0313, 0023, 0012, 0004, 0241, 0323, 0102, 0226, 0017, 
+  0371, 0224, 0256, 0334, 0025, 0053, 0336, 0231, 0013, 0056, 0326, 0007, 0162, 0206, 0365, 0131, 
+  0123, 0072, 0037, 0375, 0037, 0370, 0335, 0211, 0060, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 
+  0157, 0162, 0147, 0057, 0005, 0000, 0000, 0000, 0057, 0000, 0000, 0000, 0007, 0000, 0000, 0000, 
+  0142, 0165, 0164, 0164, 0157, 0156, 0163, 0055, 0146, 0151, 0156, 0141, 0156, 0143, 0151, 0141, 
+  0154, 0056, 0165, 0151, 0000, 0000, 0000, 0000, 0126, 0127, 0001, 0000, 0001, 0000, 0000, 0000, 
+  0170, 0332, 0355, 0135, 0351, 0216, 0343, 0270, 0021, 0376, 0237, 0247, 0140, 0014, 0044, 0331, 
+  0105, 0332, 0335, 0355, 0253, 0217, 0311, 0264, 0203, 0311, 0314, 0356, 0040, 0300, 0154, 0062, 
+  0310, 0116, 0022, 0344, 0227, 0100, 0113, 0264, 0315, 0264, 0044, 0152, 0105, 0311, 0156, 0357, 
+  0023, 0344, 0137, 0200, 0374, 0131, 0040, 0057, 0222, 0007, 0310, 0233, 0344, 0111, 0122, 0044, 
+  0045, 0265, 0344, 0113, 0076, 0144, 0133, 0007, 0007, 0003, 0264, 0114, 0221, 0022, 0305, 0072, 
+  0130, 0254, 0257, 0130, 0174, 0373, 0333, 0027, 0307, 0106, 0063, 0342, 0163, 0312, 0334, 0247, 
+  0126, 0347, 0372, 0266, 0205, 0210, 0153, 0062, 0213, 0272, 0223, 0247, 0326, 0237, 0277, 0174, 
+  0333, 0176, 0150, 0375, 0166, 0370, 0263, 0267, 0077, 0157, 0267, 0321, 0107, 0342, 0022, 0037, 
+  0007, 0304, 0102, 0163, 0032, 0114, 0321, 0304, 0306, 0026, 0101, 0275, 0353, 0156, 0367, 0272, 
+  0203, 0332, 0155, 0250, 0104, 0335, 0200, 0370, 0143, 0154, 0222, 0341, 0133, 0237, 0374, 0020, 
+  0122, 0237, 0160, 0144, 0323, 0321, 0123, 0153, 0022, 0074, 0377, 0272, 0365, 0372, 0026, 0321, 
+  0246, 0165, 0063, 0174, 0313, 0106, 0177, 0047, 0146, 0200, 0114, 0033, 0163, 0376, 0324, 0372, 
+  0030, 0074, 0177, 0240, 0330, 0146, 0223, 0026, 0242, 0326, 0123, 0313, 0014, 0174, 0307, 0260, 
+  0124, 0301, 0360, 0255, 0347, 0063, 0217, 0370, 0301, 0002, 0271, 0330, 0041, 0160, 0023, 0273, 
+  0306, 0230, 0231, 0041, 0157, 0015, 0277, 0305, 0066, 0047, 0157, 0157, 0342, 0012, 0053, 0125, 
+  0107, 0314, 0267, 0210, 0157, 0314, 0251, 0025, 0114, 0133, 0303, 0273, 0055, 0065, 0003, 0032, 
+  0330, 0244, 0205, 0002, 0037, 0273, 0334, 0306, 0001, 0036, 0331, 0120, 0270, 0040, 0274, 0205, 
+  0114, 0346, 0070, 0304, 0015, 0240, 0223, 0137, 0104, 0035, 0304, 0306, 0350, 0075, 0163, 0074, 
+  0026, 0272, 0142, 0234, 0320, 0027, 0342, 0073, 0050, 0356, 0352, 0362, 0215, 0055, 0057, 0204, 
+  0361, 0241, 0077, 0212, 0327, 0344, 0177, 0005, 0065, 0231, 0153, 0210, 0313, 0326, 0020, 0233, 
+  0046, 0341, 0234, 0371, 0224, 0360, 0266, 0211, 0155, 0063, 0204, 0276, 0062, 0177, 0333, 0167, 
+  0055, 0074, 0142, 0114, 0201, 0070, 0255, 0241, 0352, 0144, 0272, 0056, 0247, 0023, 0027, 0333, 
+  0257, 0035, 0362, 0230, 0313, 0141, 0020, 0246, 0330, 0265, 0154, 0342, 0077, 0265, 0306, 0324, 
+  0065, 0215, 0270, 0334, 0060, 0107, 0055, 0304, 0347, 0330, 0363, 0010, 0120, 0310, 0145, 0202, 
+  0210, 0346, 0224, 0332, 0026, 0274, 0323, 0006, 0272, 0117, 0231, 0015, 0143, 0015, 0205, 0067, 
+  0121, 0251, 0374, 0203, 0044, 0137, 0300, 0133, 0332, 0362, 0347, 0123, 0153, 0066, 0142, 0057, 
+  0255, 0065, 0344, 0377, 0035, 0024, 0113, 0332, 0253, 0156, 0266, 0105, 0275, 0316, 0052, 0361, 
+  0147, 0224, 0123, 0071, 0150, 0137, 0374, 0160, 0333, 0230, 0355, 0301, 0044, 0142, 0064, 0335, 
+  0000, 0007, 0300, 0236, 0255, 0041, 0360, 0151, 0100, 0141, 0144, 0323, 0365, 0327, 0177, 0010, 
+  0066, 0105, 0013, 0003, 0373, 0004, 0257, 0375, 0236, 0060, 0010, 0230, 0273, 0374, 0125, 0251, 
+  0106, 0347, 0371, 0070, 0033, 0057, 0130, 0030, 0030, 0074, 0130, 0210, 0347, 0022, 0327, 0132, 
+  0371, 0260, 0215, 0175, 0127, 0035, 0037, 0311, 0353, 0065, 0235, 0265, 0361, 0210, 0330, 0353, 
+  0044, 0146, 0150, 0274, 0307, 0256, 0111, 0354, 0055, 0275, 0072, 0340, 0103, 0167, 0250, 0151, 
+  0221, 0061, 0016, 0355, 0040, 0267, 0256, 0117, 0114, 0102, 0147, 0204, 0277, 0066, 0310, 0033, 
+  0305, 0020, 0330, 0037, 0304, 0232, 0370, 0066, 0165, 0327, 0364, 0372, 0106, 0215, 0040, 0064, 
+  0303, 0346, 0063, 0310, 0376, 0112, 0173, 0362, 0342, 0201, 0114, 0345, 0277, 0147, 0114, 0155, 
+  0073, 0277, 0226, 0307, 0070, 0125, 0334, 0172, 0233, 0351, 0105, 0362, 0366, 0214, 0004, 0356, 
+  0104, 0337, 0356, 0036, 0364, 0115, 0151, 0304, 0025, 0105, 0250, 0224, 0370, 0033, 0364, 0076, 
+  0322, 0115, 0004, 0251, 0347, 0203, 0152, 0064, 0342, 0042, 0315, 0027, 0047, 0347, 0213, 0316, 
+  0166, 0276, 0050, 0270, 0137, 0071, 0303, 0052, 0136, 0142, 0210, 0171, 0150, 0105, 0377, 0024, 
+  0315, 0327, 0037, 0175, 0152, 0051, 0256, 0226, 0354, 0172, 0036, 0015, 0273, 0273, 0215, 0341, 
+  0263, 0271, 0301, 0341, 0143, 0340, 0133, 0266, 0127, 0064, 0231, 0035, 0072, 0356, 0206, 0272, 
+  0233, 0076, 0376, 0033, 0067, 0360, 0027, 0051, 0363, 0311, 0223, 0223, 0376, 0351, 0045, 0214, 
+  0272, 0321, 0063, 0015, 0163, 0212, 0375, 0326, 0360, 0177, 0077, 0375, 0163, 0233, 0075, 0102, 
+  0136, 0202, 0045, 0372, 0056, 0163, 0201, 0117, 0035, 0354, 0057, 0014, 0151, 0365, 0210, 0371, 
+  0162, 0246, 0224, 0117, 0076, 0045, 0070, 0201, 0046, 0326, 0216, 0155, 0063, 0266, 0117, 0124, 
+  0165, 0305, 0366, 0211, 0313, 0327, 0331, 0076, 0271, 0102, 0144, 0223, 0161, 0140, 0340, 0040, 
+  0300, 0346, 0164, 0111, 0042, 0227, 0307, 0204, 0171, 0353, 0353, 0355, 0316, 0371, 0313, 0304, 
+  0037, 0317, 0064, 0351, 0253, 0106, 0372, 0156, 0061, 0244, 0367, 0064, 0351, 0053, 0107, 0372, 
+  0336, 0141, 0244, 0377, 0244, 0114, 0064, 0101, 0172, 0151, 0255, 0075, 0236, 0145, 0302, 0003, 
+  0072, 0115, 0250, 0153, 0100, 0377, 0241, 0343, 0203, 0374, 0212, 0043, 0006, 0026, 0240, 0223, 
+  0123, 0367, 0050, 0153, 0363, 0003, 0341, 0246, 0117, 0075, 0141, 0073, 0210, 0345, 0171, 0274, 
+  0060, 0226, 0246, 0104, 0142, 0211, 0162, 0024, 0114, 0011, 0162, 0103, 0147, 0104, 0174, 0131, 
+  0053, 0365, 0064, 0350, 0011, 0145, 0026, 0107, 0056, 0021, 0313, 0153, 0340, 0045, 0024, 0060, 
+  0130, 0360, 0231, 0260, 0114, 0343, 0004, 0141, 0027, 0256, 0301, 0056, 0014, 0104, 0077, 0104, 
+  0123, 0017, 0326, 0304, 0342, 0162, 0206, 0355, 0220, 0210, 0252, 0030, 0215, 0303, 0040, 0364, 
+  0211, 0052, 0271, 0102, 0070, 0020, 0105, 0364, 0205, 0104, 0313, 0106, 0150, 0213, 0204, 0367, 
+  0104, 0274, 0150, 0315, 0213, 0257, 0267, 0014, 0314, 0334, 0307, 0136, 0056, 0365, 0034, 0374, 
+  0242, 0014, 0020, 0051, 0215, 0100, 0303, 0376, 0355, 0136, 0166, 0150, 0206, 0151, 0157, 0167, 
+  0144, 0332, 0155, 0365, 0042, 0153, 0250, 0133, 0014, 0137, 0337, 0235, 0151, 0251, 0174, 0004, 
+  0013, 0312, 0056, 0243, 0021, 0031, 0063, 0237, 0104, 0124, 0245, 0346, 0022, 0361, 0251, 0353, 
+  0205, 0240, 0006, 0077, 0307, 0167, 0177, 0037, 0337, 0065, 0376, 0004, 0267, 0337, 0034, 0276, 
+  0316, 0130, 0346, 0006, 0227, 0070, 0314, 0245, 0246, 0140, 0211, 0011, 0201, 0067, 0046, 0366, 
+  0340, 0226, 0106, 0057, 0330, 0006, 0335, 0270, 0154, 0172, 0237, 0204, 0161, 0072, 0305, 0160, 
+  0105, 0247, 0152, 0154, 0221, 0326, 0021, 0061, 0063, 0030, 0337, 0252, 0302, 0277, 0210, 0302, 
+  0123, 0263, 0300, 0170, 0126, 0016, 0006, 0050, 0110, 0055, 0014, 0252, 0246, 0026, 0062, 0323, 
+  0106, 0254, 0015, 0242, 0102, 0343, 0054, 0034, 0340, 0225, 0204, 0003, 0172, 0005, 0071, 0050, 
+  0162, 0006, 0141, 0067, 0377, 0304, 0336, 0156, 0223, 0270, 0100, 0171, 0163, 0333, 0152, 0204, 
+  0371, 0322, 0157, 0024, 0073, 0316, 0237, 0132, 0155, 0320, 0124, 0221, 0037, 0365, 0355, 0115, 
+  0246, 0322, 0226, 0066, 0203, 0270, 0115, 0167, 0245, 0315, 0315, 0362, 0213, 0223, 0236, 0155, 
+  0105, 0125, 0054, 0153, 0124, 0142, 0120, 0345, 0003, 0013, 0341, 0176, 0373, 0003, 0061, 0201, 
+  0277, 0205, 0040, 0175, 0040, 0040, 0060, 0046, 0225, 0166, 0134, 0202, 0260, 0154, 0255, 0245, 
+  0341, 0226, 0243, 0340, 0226, 0156, 0235, 0341, 0226, 0156, 0225, 0340, 0226, 0236, 0206, 0133, 
+  0152, 0015, 0267, 0364, 0017, 0203, 0133, 0266, 0253, 0110, 0215, 0275, 0150, 0354, 0245, 0064, 
+  0330, 0113, 0267, 0121, 0330, 0313, 0362, 0312, 0344, 0276, 0336, 0216, 0270, 0335, 0364, 0320, 
+  0036, 0136, 0071, 0053, 0335, 0036, 0333, 0066, 0233, 0213, 0051, 0015, 0211, 0037, 0360, 0237, 
+  0163, 0260, 0214, 0141, 0005, 0205, 0060, 0342, 0036, 0124, 0033, 0123, 0142, 0105, 0076, 0026, 
+  0361, 0340, 0200, 0072, 0344, 0012, 0205, 0134, 0164, 0104, 0076, 0114, 0365, 0316, 0112, 0172, 
+  0067, 0302, 0266, 0174, 0234, 0103, 0202, 0251, 0166, 0266, 0155, 0301, 0017, 0304, 0002, 0301, 
+  0246, 0143, 0242, 0001, 0204, 0346, 0141, 0107, 0202, 0366, 0046, 0343, 0032, 0062, 0156, 0040, 
+  0144, 0054, 0150, 0257, 0364, 0251, 0246, 0176, 0103, 0241, 0303, 0316, 0155, 0151, 0234, 0251, 
+  0273, 0131, 0027, 0031, 0317, 0252, 0230, 0264, 0022, 0217, 0372, 0047, 0370, 0161, 0102, 0077, 
+  0152, 0074, 0111, 0326, 0312, 0225, 0336, 0351, 0124, 0231, 0374, 0221, 0055, 0030, 0063, 0200, 
+  0002, 0330, 0116, 0314, 0002, 0352, 0235, 0225, 0360, 0246, 0357, 0312, 0004, 0017, 0125, 0346, 
+  0001, 0141, 0273, 0304, 0034, 0360, 0336, 0200, 0037, 0047, 0246, 0277, 0170, 0137, 0045, 0340, 
+  0324, 0332, 0142, 0051, 0275, 0003, 0260, 0224, 0176, 0121, 0130, 0312, 0170, 0126, 0142, 0050, 
+  0045, 0215, 0051, 0047, 0310, 0111, 0272, 0120, 0003, 0045, 0107, 0001, 0045, 0275, 0072, 0003, 
+  0045, 0275, 0052, 0001, 0045, 0003, 0015, 0224, 0324, 0032, 0050, 0271, 0073, 0014, 0050, 0311, 
+  0050, 0100, 0215, 0213, 0150, 0134, 0244, 0064, 0270, 0110, 0257, 0251, 0173, 0122, 0300, 0140, 
+  0162, 0265, 0167, 0251, 0041, 0336, 0245, 0054, 0335, 0365, 0116, 0244, 0146, 0102, 0012, 0202, 
+  0364, 0216, 0246, 0174, 0123, 0000, 0205, 0025, 0237, 0142, 0277, 0064, 0376, 0244, 0265, 0366, 
+  0140, 0251, 0103, 0366, 0043, 0265, 0131, 0057, 0047, 0363, 0240, 0102, 0014, 0361, 0272, 0121, 
+  0050, 0336, 0034, 0024, 0273, 0227, 0377, 0220, 0334, 0121, 0154, 0301, 0117, 0313, 0006, 0156, 
+  0255, 0174, 0314, 0235, 0156, 0275, 0103, 0143, 0326, 0062, 0326, 0036, 0221, 0060, 0231, 0075, 
+  0042, 0120, 0067, 0273, 0367, 0154, 0204, 0071, 0261, 0144, 0130, 0014, 0342, 0104, 0070, 0333, 
+  0104, 0025, 0362, 0103, 0010, 0223, 0210, 0207, 0027, 0262, 0013, 0152, 0357, 0331, 0006, 0165, 
+  0306, 0146, 0300, 0270, 0331, 0155, 0160, 0121, 0273, 0024, 0227, 0313, 0012, 0320, 0312, 0321, 
+  0221, 0062, 0071, 0274, 0334, 0253, 0342, 0004, 0027, 0023, 0074, 0213, 0226, 0301, 0215, 0317, 
+  0352, 0306, 0211, 0047, 0065, 0107, 0243, 0046, 0027, 0105, 0115, 0006, 0007, 0240, 0046, 0167, 
+  0105, 0241, 0046, 0023, 0257, 0314, 0151, 0275, 0076, 0372, 0214, 0163, 0364, 0331, 0147, 0143, 
+  0032, 0240, 0357, 0344, 0304, 0220, 0240, 0047, 0153, 0356, 0151, 0020, 0345, 0270, 0344, 0136, 
+  0267, 0265, 0316, 0356, 0165, 0133, 0251, 0364, 0136, 0217, 0032, 0107, 0251, 0167, 0176, 0257, 
+  0333, 0303, 0200, 0224, 0165, 0052, 0121, 0343, 0051, 0032, 0117, 0051, 0117, 0216, 0257, 0333, 
+  0106, 0157, 0064, 0351, 0327, 0174, 0247, 0311, 0066, 0375, 0263, 0307, 0252, 0032, 0314, 0034, 
+  0154, 0213, 0015, 0370, 0324, 0124, 0253, 0152, 0270, 0144, 0126, 0150, 0006, 0127, 0257, 0113, 
+  0152, 0121, 0057, 0052, 0125, 0301, 0144, 0040, 0035, 0262, 0160, 0216, 0135, 0221, 0367, 0166, 
+  0042, 0273, 0342, 0251, 0256, 0250, 0357, 0324, 0013, 0344, 0215, 0276, 0177, 0141, 0351, 0353, 
+  0355, 0004, 0315, 0334, 0116, 0040, 0150, 0257, 0004, 0104, 0123, 0277, 0041, 0250, 0337, 0312, 
+  0274, 0124, 0236, 0130, 0342, 0155, 0123, 0310, 0305, 0042, 0210, 0143, 0365, 0130, 0253, 0204, 
+  0114, 0375, 0307, 0352, 0021, 0135, 0351, 0251, 0304, 0031, 0252, 0252, 0026, 0107, 0370, 0362, 
+  0200, 0164, 0365, 0115, 0251, 0363, 0170, 0110, 0116, 0235, 0333, 0242, 0134, 0232, 0236, 0023, 
+  0224, 0330, 0245, 0271, 0354, 0334, 0117, 0374, 0231, 0313, 0067, 0264, 0063, 0363, 0050, 0147, 
+  0146, 0277, 0316, 0276, 0314, 0176, 0225, 0134, 0231, 0367, 0332, 0223, 0131, 0153, 0117, 0346, 
+  0303, 0141, 0216, 0314, 0025, 0105, 0250, 0275, 0230, 0332, 0213, 0131, 0032, 0057, 0146, 0277, 
+  0321, 0116, 0314, 0116, 0315, 0235, 0230, 0033, 0165, 0317, 0036, 0036, 0114, 0354, 0260, 0120, 
+  0045, 0237, 0226, 0176, 0312, 0345, 0140, 0016, 0351, 0323, 0264, 0031, 0166, 0257, 0320, 0174, 
+  0112, 0104, 0270, 0107, 0022, 0016, 0044, 0027, 0071, 0026, 0021, 0161, 0101, 0242, 0051, 0060, 
+  0266, 0014, 0032, 0202, 0065, 0303, 0122, 0354, 0317, 0065, 0072, 0261, 0073, 0363, 0162, 0153, 
+  0243, 0263, 0270, 0074, 0305, 0112, 0300, 0363, 0265, 0323, 0253, 0211, 0056, 0117, 0111, 0173, 
+  0275, 0315, 0241, 0221, 0333, 0034, 0004, 0355, 0265, 0320, 0067, 0065, 0161, 0116, 0267, 0074, 
+  0231, 0123, 0066, 0332, 0031, 0031, 0217, 0247, 0210, 0354, 0115, 0374, 0235, 0042, 0131, 0371, 
+  0011, 0335, 0334, 0122, 0064, 0352, 0025, 0277, 0376, 0130, 0061, 0162, 0227, 0155, 0143, 0113, 
+  0074, 0123, 0326, 0153, 0147, 0313, 0103, 0325, 0270, 0002, 0354, 0124, 0223, 0172, 0240, 0226, 
+  0223, 0060, 0360, 0270, 0344, 0324, 0264, 0367, 0251, 0253, 0043, 0300, 0057, 0011, 0230, 0334, 
+  0037, 0200, 0227, 0074, 0024, 0006, 0227, 0224, 0071, 0157, 0116, 0174, 0026, 0107, 0066, 0161, 
+  0116, 0246, 0124, 0343, 0044, 0107, 0341, 0044, 0203, 0072, 0343, 0044, 0203, 0052, 0341, 0044, 
+  0072, 0342, 0273, 0336, 0070, 0111, 0347, 0300, 0210, 0357, 0254, 0016, 0324, 0050, 0211, 0106, 
+  0111, 0112, 0203, 0222, 0014, 0032, 0215, 0222, 0364, 0356, 0152, 0216, 0222, 0254, 0125, 0074, 
+  0173, 0100, 0044, 0331, 0343, 0325, 0016, 0332, 0073, 0155, 0121, 0156, 0012, 0234, 0005, 0052, 
+  0026, 0270, 0215, 0132, 0343, 0052, 0307, 0371, 0127, 0165, 0032, 0231, 0246, 0242, 0052, 0072, 
+  0167, 0124, 0143, 0101, 0025, 0235, 0056, 0256, 0301, 0230, 0112, 0171, 0116, 0366, 0135, 0157, 
+  0225, 0224, 0060, 0123, 0220, 0127, 0267, 0114, 0101, 0335, 0101, 0225, 0230, 0240, 0164, 0060, 
+  0113, 0015, 0363, 0207, 0165, 0373, 0225, 0344, 0210, 0013, 0046, 0334, 0361, 0164, 0302, 0235, 
+  0213, 0303, 0055, 0207, 0154, 0117, 0351, 0024, 0266, 0075, 0105, 0150, 0241, 0052, 0354, 0117, 
+  0111, 0024, 0243, 0320, 0213, 0253, 0273, 0124, 0062, 0267, 0065, 0006, 0163, 0024, 0006, 0163, 
+  0127, 0147, 0014, 0346, 0256, 0122, 0151, 0167, 0072, 0032, 0204, 0251, 0067, 0010, 0323, 0075, 
+  0162, 0267, 0112, 0126, 0055, 0152, 0064, 0106, 0243, 0061, 0245, 0101, 0143, 0356, 0032, 0215, 
+  0306, 0164, 0037, 0032, 0262, 0147, 0145, 0275, 0006, 0332, 0007, 0226, 0131, 0131, 0031, 0273, 
+  0104, 0230, 0133, 0330, 0137, 0240, 0200, 0101, 0251, 0011, 0323, 0066, 0047, 0113, 0150, 0015, 
+  0334, 0301, 0231, 0144, 0270, 0127, 0353, 0120, 0027, 0350, 0257, 0307, 0100, 0105, 0210, 0043, 
+  0342, 0042, 0347, 0213, 0106, 0133, 0216, 0163, 0274, 0312, 0005, 0303, 0170, 0246, 0175, 0257, 
+  0315, 0203, 0133, 0044, 0351, 0075, 0115, 0372, 0006, 0302, 0055, 0222, 0364, 0032, 0160, 0151, 
+  0052, 0340, 0322, 0273, 0055, 0137, 0374, 0372, 0172, 0303, 0143, 0051, 0212, 0075, 0035, 0361, 
+  0021, 0373, 0332, 0243, 0102, 0103, 0372, 0146, 0117, 0350, 0134, 0215, 0324, 0145, 0255, 0134, 
+  0354, 0275, 0116, 0045, 0031, 0341, 0234, 0173, 0232, 0224, 0252, 0254, 0027, 0324, 0366, 0130, 
+  0111, 0252, 0147, 0316, 0312, 0210, 0251, 0237, 0076, 0011, 0341, 0324, 0134, 0060, 0236, 0151, 
+  0150, 0345, 0242, 0251, 0277, 0072, 0207, 0140, 0053, 0335, 0242, 0260, 0025, 0156, 0273, 0045, 
+  0206, 0126, 0276, 0207, 0152, 0164, 0062, 0015, 0332, 0237, 0200, 0301, 0263, 0007, 0250, 0307, 
+  0235, 0336, 0134, 0105, 0103, 0054, 0107, 0101, 0054, 0367, 0165, 0206, 0130, 0356, 0053, 0005, 
+  0261, 0364, 0064, 0304, 0122, 0157, 0210, 0245, 0177, 0030, 0304, 0262, 0105, 0075, 0152, 0230, 
+  0105, 0303, 0054, 0245, 0201, 0131, 0356, 0233, 0275, 0351, 0245, 0074, 0107, 0254, 0355, 0240, 
+  0060, 0066, 0246, 0223, 0066, 0336, 0237, 0066, 0235, 0264, 0260, 0104, 0053, 0237, 0116, 0072, 
+  0345, 0216, 0024, 0337, 0303, 0261, 0075, 0303, 0023, 0242, 0175, 0222, 0315, 0363, 0106, 0307, 
+  0354, 0254, 0151, 0337, 0074, 0020, 0112, 0320, 0336, 0246, 0143, 0055, 0367, 0215, 0305, 0042, 
+  0006, 0225, 0235, 0362, 0005, 0337, 0046, 0123, 0376, 0047, 0370, 0161, 0342, 0051, 0137, 0274, 
+  0257, 0126, 0216, 0350, 0136, 0277, 0262, 0264, 0217, 0314, 0225, 0204, 0374, 0337, 0253, 0337, 
+  0047, 0346, 0200, 0350, 0255, 0365, 0302, 0240, 0152, 0176, 0104, 0370, 0016, 0234, 0265, 0107, 
+  0170, 0025, 0217, 0237, 0046, 0230, 0010, 0131, 0351, 0247, 0251, 0055, 0360, 0060, 0314, 0044, 
+  0100, 0300, 0243, 0210, 0271, 0044, 0111, 0365, 0373, 0145, 0245, 0251, 0103, 0202, 0051, 0223, 
+  0271, 0201, 0255, 0254, 0257, 0170, 0106, 0255, 0350, 0135, 0361, 0015, 0370, 0052, 0265, 0274, 
+  0041, 0063, 0342, 0332, 0213, 0327, 0310, 0054, 0340, 0350, 0161, 0150, 0053, 0075, 0230, 0172, 
+  0273, 0172, 0135, 0372, 0046, 0345, 0313, 0373, 0347, 0125, 0364, 0326, 0025, 0202, 0065, 0266, 
+  0160, 0143, 0302, 0123, 0027, 0004, 0373, 0074, 0012, 0373, 0232, 0117, 0251, 0071, 0175, 0375, 
+  0032, 0150, 0236, 0164, 0222, 0350, 0304, 0305, 0315, 0004, 0177, 0172, 0207, 0200, 0077, 0375, 
+  0302, 0300, 0237, 0205, 0125, 0146, 0360, 0047, 0164, 0332, 0154, 0334, 0006, 0031, 0153, 0377, 
+  0115, 0210, 0321, 0257, 0332, 0037, 0350, 0204, 0006, 0174, 0003, 0016, 0264, 0113, 0155, 0015, 
+  0011, 0035, 0005, 0011, 0075, 0324, 0031, 0022, 0172, 0250, 0024, 0044, 0064, 0320, 0220, 0120, 
+  0275, 0041, 0241, 0273, 0003, 0041, 0241, 0235, 0224, 0346, 0052, 0072, 0004, 0132, 0005, 0006, 
+  0136, 0203, 0104, 0032, 0044, 0272, 0024, 0110, 0364, 0320, 0154, 0220, 0350, 0276, 0074, 0136, 
+  0203, 0275, 0124, 0310, 0232, 0174, 0001, 0113, 0131, 0002, 0116, 0351, 0076, 0000, 0003, 0126, 
+  0275, 0263, 0034, 0113, 0235, 0176, 0101, 0336, 0203, 0207, 0072, 0060, 0303, 0131, 0075, 0211, 
+  0300, 0010, 0365, 0363, 0044, 0076, 0326, 0201, 0015, 0056, 0340, 0124, 0004, 0146, 0250, 0243, 
+  0123, 0261, 0177, 0133, 0007, 0176, 0070, 0153, 0114, 0001, 0160, 0102, 0255, 0142, 0012, 0242, 
+  0357, 0321, 0300, 0142, 0003, 0101, 0345, 0127, 0255, 0246, 0311, 0337, 0300, 0170, 0222, 0310, 
+  0302, 0321, 0264, 0157, 0110, 0114, 0301, 0022, 0355, 0325, 0062, 0107, 0123, 0277, 0152, 0324, 
+  0057, 0150, 0111, 0330, 0357, 0324, 0034, 0120, 0336, 0313, 0240, 0334, 0003, 0133, 0316, 0000, 
+  0301, 0330, 0266, 0331, 0134, 0370, 0302, 0145, 0016, 0365, 0064, 0256, 0214, 0021, 0367, 0240, 
+  0332, 0230, 0022, 0053, 0366, 0142, 0210, 0163, 0152, 0251, 0103, 0256, 0120, 0310, 0105, 0156, 
+  0016, 0361, 0260, 0215, 0275, 0124, 0300, 0263, 0300, 0210, 0051, 0337, 0204, 0102, 0013, 0254, 
+  0010, 0070, 0061, 0351, 0231, 0112, 0303, 0236, 0255, 0164, 0205, 0070, 0203, 0233, 0070, 0100, 
+  0216, 0260, 0225, 0063, 0355, 0311, 0213, 0107, 0134, 0016, 0115, 0114, 0063, 0364, 0145, 0166, 
+  0166, 0350, 0202, 0115, 0211, 0237, 0344, 0154, 0205, 0206, 0042, 0001, 0011, 0022, 0137, 0057, 
+  0241, 0162, 0256, 0121, 0153, 0215, 0132, 0027, 0217, 0132, 0017, 0016, 0101, 0255, 0357, 0212, 
+  0102, 0255, 0305, 0106, 0351, 0062, 0247, 0203, 0214, 0122, 0245, 0052, 0347, 0347, 0153, 0032, 
+  0310, 0114, 0261, 0006, 0242, 0217, 0002, 0242, 0037, 0353, 0014, 0104, 0077, 0126, 0012, 0210, 
+  0276, 0327, 0100, 0164, 0275, 0201, 0350, 0207, 0003, 0323, 0077, 0146, 0325, 0140, 0154, 0271, 
+  0251, 0027, 0210, 0324, 0150, 0346, 0022, 0366, 0254, 0101, 0147, 0015, 0072, 0237, 0035, 0164, 
+  0176, 0154, 0024, 0350, 0234, 0162, 0051, 0110, 0043, 0112, 0037, 0114, 0323, 0114, 0177, 0222, 
+  0044, 0276, 0316, 0217, 0330, 0104, 0067, 0262, 0222, 0173, 0175, 0024, 0131, 0143, 0020, 0244, 
+  0025, 0107, 0142, 0211, 0216, 0244, 0131, 0157, 0042, 0226, 0356, 0004, 0222, 0130, 0146, 0052, 
+  0215, 0042, 0257, 0360, 0101, 0277, 0122, 0174, 0260, 0056, 0117, 0132, 0224, 0046, 0355, 0344, 
+  0111, 0022, 0243, 0351, 0262, 0136, 0261, 0044, 0275, 0152, 0252, 0201, 0222, 0034, 0115, 0225, 
+  0230, 0317, 0265, 0012, 0070, 0353, 0327, 0375, 0170, 0336, 0365, 0234, 0266, 0007, 0232, 0264, 
+  0371, 0260, 0134, 0011, 0332, 0140, 0161, 0224, 0136, 0222, 0031, 0336, 0012, 0375, 0030, 0070, 
+  0222, 0311, 0075, 0325, 0156, 0102, 0130, 0013, 0122, 0127, 0334, 0306, 0256, 0033, 0322, 0140, 
+  0161, 0045, 0363, 0304, 0233, 0146, 0350, 0050, 0157, 0310, 0162, 0312, 0370, 0055, 0207, 0370, 
+  0136, 0153, 0364, 0245, 0201, 0350, 0313, 0375, 0041, 0350, 0313, 0303, 0061, 0350, 0313, 0137, 
+  0251, 0153, 0261, 0271, 0122, 0024, 0163, 0171, 0335, 0331, 0017, 0171, 0121, 0216, 0162, 0341, 
+  0340, 0211, 0300, 0224, 0221, 0130, 0017, 0154, 0203, 0007, 0266, 0272, 0156, 0324, 0067, 0031, 
+  0100, 0077, 0020, 0371, 0163, 0150, 0054, 0341, 0226, 0231, 0062, 0207, 0115, 0210, 0113, 0330, 
+  0056, 0056, 0105, 0345, 0235, 0331, 0332, 0144, 0027, 0027, 0254, 0120, 0105, 0206, 0003, 0163, 
+  0017, 0254, 0134, 0342, 0255, 0071, 0247, 0137, 0267, 0311, 0132, 0006, 0014, 0260, 0151, 0123, 
+  0363, 0171, 0207, 0321, 0131, 0161, 0212, 0056, 0277, 0040, 0263, 0244, 0222, 0117, 0045, 0126, 
+  0152, 0105, 0025, 0175, 0341, 0146, 0034, 0151, 0063, 0050, 0064, 0035, 0261, 0227, 0356, 0171, 
+  0342, 0142, 0023, 0137, 0133, 0357, 0240, 0303, 0126, 0312, 0143, 0160, 0211, 0220, 0000, 0131, 
+  0117, 0104, 0101, 0210, 0331, 0111, 0215, 0177, 0262, 0371, 0353, 0045, 0375, 0174, 0320, 0310, 
+  0076, 0205, 0073, 0204, 0247, 0256, 0343, 0021, 0221, 0340, 0221, 0232, 0250, 0140, 0271, 0037, 
+  0300, 0374, 0140, 0312, 0005, 0160, 0272, 0321, 0205, 0024, 0361, 0201, 0376, 0341, 0167, 0276, 
+  0037, 0153, 0072, 0054, 0056, 0073, 0347, 0131, 0046, 0311, 0167, 0105, 0036, 0160, 0120, 0257, 
+  0356, 0011, 0041, 0202, 0223, 0115, 0145, 0233, 0320, 0120, 0141, 0016, 0251, 0361, 0132, 0032, 
+  0356, 0167, 0301, 0363, 0037, 0145, 0301, 0046, 0145, 0327, 0306, 0301, 0263, 0152, 0262, 0112, 
+  0204, 0244, 0361, 0233, 0067, 0257, 0257, 0150, 0113, 0060, 0174, 0073, 0367, 0277, 0113, 0152, 
+  0313, 0047, 0311, 0350, 0237, 0224, 0020, 0250, 0025, 0146, 0054, 0012, 0337, 0311, 0302, 0265, 
+  0324, 0330, 0331, 0320, 0310, 0030, 0100, 0375, 0103, 0226, 0171, 0205, 0236, 0223, 0263, 0062, 
+  0277, 0200, 0015, 0214, 0175, 0032, 0114, 0235, 0215, 0123, 0214, 0122, 0052, 0303, 0245, 0040, 
+  0201, 0372, 0315, 0103, 0221, 0135, 0161, 0264, 0113, 0357, 0356, 0264, 0153, 0371, 0025, 0012, 
+  0076, 0344, 0121, 0356, 0241, 0342, 0164, 0333, 0157, 0361, 0236, 0103, 0145, 0113, 0204, 0354, 
+  0235, 0317, 0157, 0173, 0133, 0020, 0221, 0037, 0363, 0210, 0374, 0250, 0211, 0134, 0070, 0221, 
+  0273, 0147, 0046, 0362, 0040, 0217, 0310, 0003, 0115, 0344, 0213, 0111, 0162, 0247, 0040, 0042, 
+  0337, 0345, 0021, 0371, 0116, 0023, 0371, 0142, 0222, 0134, 0024, 0221, 0125, 0316, 0261, 0074, 
+  0112, 0377, 0367, 0077, 0232, 0324, 0305, 0333, 0137, 0275, 0063, 0153, 0355, 0156, 0036, 0231, 
+  0273, 0232, 0312, 0027, 0323, 0332, 0105, 0031, 0331, 0156, 0350, 0020, 0237, 0232, 0206, 0307, 
+  0140, 0211, 0233, 0103, 0360, 0324, 0162, 0123, 0301, 0130, 0224, 0043, 0271, 0173, 0302, 0105, 
+  0223, 0340, 0371, 0332, 0224, 0361, 0217, 0314, 0361, 0354, 0005, 0232, 0303, 0312, 0013, 0175, 
+  0172, 0217, 0306, 0066, 0236, 0000, 0151, 0257, 0065, 0247, 0274, 0162, 0112, 0166, 0310, 0313, 
+  0036, 0140, 0265, 0302, 0061, 0360, 0004, 0123, 0004, 0220, 0117, 0162, 0247, 0201, 0137, 0150, 
+  0252, 0027, 0077, 0013, 0164, 0317, 0114, 0356, 0136, 0036, 0225, 0173, 0232, 0312, 0027, 0063, 
+  0353, 0212, 0232, 0005, 0034, 0030, 0031, 0012, 0172, 0073, 0327, 0260, 0373, 0111, 0023, 0373, 
+  0162, 0206, 0135, 0121, 0106, 0074, 0017, 0107, 0201, 0217, 0315, 0274, 0351, 0176, 0370, 0277, 
+  0177, 0374, 0113, 0223, 0373, 0225, 0334, 0311, 0260, 0235, 0215, 0340, 0105, 0211, 0067, 0266, 
+  0254, 0074, 0132, 0377, 0132, 0123, 0372, 0162, 0202, 0135, 0324, 0134, 0255, 0266, 0034, 0345, 
+  0131, 0361, 0133, 0161, 0244, 0117, 0151, 0004, 0225, 0063, 0173, 0026, 0243, 0106, 0350, 0053, 
+  0071, 0116, 0052, 0364, 0107, 0030, 0376, 0342, 0136, 0264, 0031, 0235, 0162, 0317, 0306, 0013, 
+  0142, 0245, 0203, 0214, 0276, 0156, 0015, 0237, 0064, 0117, 0245, 0264, 0207, 0030, 0257, 0165, 
+  0054, 0045, 0341, 0146, 0040, 0262, 0040, 0153, 0214, 0100, 0207, 0223, 0011, 0341, 0001, 0261, 
+  0242, 0015, 0224, 0222, 0363, 0242, 0172, 0247, 0001, 0346, 0172, 0347, 0003, 0346, 0170, 0200, 
+  0375, 0300, 0230, 0370, 0054, 0364, 0362, 0224, 0322, 0127, 0232, 0201, 0212, 0127, 0112, 0375, 
+  0063, 0133, 0033, 0304, 0265, 0166, 0243, 0366, 0327, 0232, 0332, 0305, 0123, 0173, 0160, 0146, 
+  0152, 0233, 0066, 0301, 0376, 0376, 0063, 0320, 0360, 0275, 0150, 0127, 0157, 0034, 0136, 0015, 
+  0315, 0156, 0063, 0200, 0005, 0352, 0337, 0017, 0305, 0156, 0034, 0162, 0364, 0034, 0060, 0070, 
+  0263, 0337, 0130, 0356, 0044, 0022, 0176, 0100, 0006, 0354, 0017, 0217, 0060, 0144, 0130, 0371, 
+  0061, 0106, 0311, 0306, 0160, 0345, 0324, 0133, 0222, 0220, 0345, 0327, 0110, 0345, 0200, 0041, 
+  0350, 0212, 0117, 0060, 0047, 0110, 0246, 0220, 0001, 0352, 0005, 0062, 0274, 0131, 0104, 0072, 
+  0203, 0261, 0044, 0056, 0125, 0144, 0214, 0067, 0223, 0361, 0312, 0331, 0015, 0031, 0120, 0153, 
+  0074, 0213, 0102, 0225, 0307, 0364, 0205, 0130, 0113, 0161, 0372, 0160, 0237, 0252, 0130, 0351, 
+  0065, 0035, 0271, 0106, 0337, 0023, 0170, 0255, 0315, 0331, 0033, 0064, 0015, 0002, 0357, 0315, 
+  0315, 0015, 0161, 0257, 0347, 0364, 0231, 0002, 0345, 0051, 0276, 0146, 0376, 0344, 0106, 0374, 
+  0272, 0171, 0037, 0065, 0065, 0342, 0207, 0203, 0060, 0004, 0276, 0243, 0225, 0341, 0322, 0336, 
+  0264, 0243, 0125, 0341, 0375, 0045, 0344, 0300, 0142, 0241, 0330, 0052, 0150, 0021, 0370, 0052, 
+  0127, 0010, 0103, 0072, 0371, 0121, 0221, 0102, 0121, 0150, 0106, 0050, 0325, 0353, 0166, 0322, 
+  0153, 0064, 0302, 0266, 0174, 0134, 0234, 0021, 0152, 0107, 0336, 0116, 0247, 0271, 0152, 0015, 
+  0077, 0130, 0043, 0315, 0325, 0105, 0163, 0365, 0303, 0045, 0270, 0132, 0251, 0111, 0103, 0252, 
+  0311, 0042, 0231, 0170, 0131, 0375, 0146, 0265, 0366, 0010, 0024, 0271, 0045, 0071, 0032, 0161, 
+  0042, 0162, 0002, 0211, 0052, 0344, 0207, 0020, 0306, 0070, 0332, 0267, 0302, 0257, 0020, 0201, 
+  0257, 0225, 0115, 0035, 0120, 0252, 0240, 0234, 0235, 0140, 0353, 0146, 0223, 0110, 0211, 0137, 
+  0275, 0236, 0224, 0265, 0171, 0063, 0014, 0165, 0223, 0135, 0057, 0073, 0113, 0300, 0267, 0251, 
+  0221, 0002, 0016, 0234, 0151, 0001, 0050, 0132, 0000, 0036, 0057, 0041, 0000, 0247, 0063, 0151, 
+  0316, 0264, 0003, 0053, 0143, 0334, 0154, 0025, 0215, 0153, 0364, 0215, 0020, 0251, 0144, 0247, 
+  0062, 0217, 0104, 0116, 0074, 0075, 0221, 0261, 0235, 0345, 0341, 0235, 0352, 0234, 0361, 0025, 
+  0014, 0243, 0230, 0121, 0014, 0370, 0012, 0346, 0057, 0276, 0006, 0346, 0041, 0332, 0350, 0271, 
+  0334, 0364, 0320, 0053, 0122, 0072, 0170, 0350, 0030, 0154, 0054, 0110, 0153, 0310, 0244, 0213, 
+  0206, 0204, 0305, 0170, 0065, 0154, 0037, 0221, 0015, 0363, 0217, 0343, 0366, 0227, 0212, 0145, 
+  0303, 0134, 0071, 0001, 0022, 0072, 0051, 0377, 0266, 0343, 0263, 0012, 0116, 0236, 0065, 0363, 
+  0040, 0243, 0360, 0373, 0205, 0245, 0245, 0376, 0122, 0163, 0142, 0267, 0120, 0251, 0217, 0016, 
+  0055, 0065, 0304, 0207, 0237, 0114, 0326, 0217, 0070, 0125, 0165, 0127, 0021, 0251, 0317, 0351, 
+  0253, 0207, 0111, 0244, 0355, 0152, 0211, 0274, 0324, 0074, 0134, 0250, 0104, 0306, 0166, 0135, 
+  0342, 0132, 0062, 0304, 0174, 0124, 0244, 0064, 0256, 0132, 0216, 0205, 0273, 0337, 0326, 0054, 
+  0314, 0326, 0271, 0375, 0304, 0342, 0154, 0237, 0205, 0131, 0222, 0124, 0143, 0247, 0177, 0255, 
+  0341, 0237, 0316, 0235, 0300, 0121, 0373, 0344, 0116, 0046, 0026, 0212, 0367, 0212, 0167, 0137, 
+  0144, 0231, 0272, 0070, 0377, 0205, 0105, 0271, 0051, 0176, 0101, 0353, 0013, 0272, 0062, 0076, 
+  0247, 0207, 0255, 0065, 0374, 0254, 0175, 0031, 0027, 0263, 0333, 0072, 0047, 0231, 0045, 0042, 
+  0046, 0051, 0122, 0042, 0042, 0056, 0026, 0313, 0254, 0351, 0232, 0264, 0147, 0202, 0317, 0221, 
+  0315, 0060, 0254, 0211, 0346, 0123, 0042, 0062, 0042, 0105, 0162, 0040, 0075, 0036, 0016, 0266, 
+  0210, 0140, 0170, 0321, 0224, 0270, 0322, 0004, 0043, 0151, 0127, 0304, 0236, 0100, 0313, 0073, 
+  0130, 0156, 0005, 0364, 0107, 0145, 0221, 0162, 0163, 0112, 0254, 0120, 0160, 0350, 0347, 0255, 
+  0051, 0320, 0064, 0043, 0237, 0324, 0334, 0051, 0224, 0221, 0047, 0076, 0343, 0034, 0264, 0073, 
+  0033, 0323, 0300, 0210, 0263, 0054, 0025, 0307, 0313, 0240, 0376, 0260, 0055, 0224, 0074, 0065, 
+  0225, 0162, 0207, 0113, 0146, 0205, 0046, 0150, 0334, 0104, 0263, 0253, 0131, 0100, 0226, 0252, 
+  0225, 0000, 0014, 0253, 0054, 0234, 0143, 0251, 0276, 0145, 0027, 0221, 0352, 0042, 0122, 0135, 
+  0334, 0231, 0177, 0077, 0256, 0176, 0136, 0153, 0370, 0321, 0323, 0116, 0263, 0213, 0131, 0045, 
+  0105, 0161, 0357, 0213, 0341, 0261, 0271, 0121, 0353, 0144, 0070, 0233, 0343, 0131, 0166, 0110, 
+  0065, 0023, 0217, 0117, 0024, 0050, 0164, 0266, 0204, 0063, 0303, 0137, 0332, 0301, 0157, 0350, 
+  0057, 0047, 0301, 0157, 0136, 0304, 0325, 0215, 0274, 0024, 0127, 0074, 0364, 0342, 0113, 0131, 
+  0266, 0310, 0336, 0276, 0211, 0356, 0347, 0260, 0071, 0310, 0360, 0163, 0350, 0155, 0311, 0236, 
+  0136, 0150, 0016, 0222, 0054, 0223, 0235, 0065, 0011, 0011, 0171, 0361, 0230, 0013, 0125, 0042, 
+  0327, 0311, 0127, 0057, 0142, 0265, 0047, 0125, 0045, 0233, 0053, 0373, 0164, 0361, 0165, 0222, 
+  0234, 0344, 0233, 0250, 0162, 0201, 0351, 0111, 0356, 0316, 0014, 0021, 0371, 0214, 0355, 0020, 
+  0134, 0377, 0157, 0255, 0270, 0057, 0227, 0244, 0244, 0050, 0325, 0015, 0137, 0314, 0016, 0010, 
+  0167, 0373, 0063, 0064, 0253, 0070, 0371, 0117, 0023, 0165, 0132, 0224, 0010, 0336, 0347, 0311, 
+  0337, 0275, 0226, 0276, 0302, 0267, 0255, 0335, 0236, 0231, 0310, 0375, 0074, 0042, 0367, 0065, 
+  0221, 0057, 0106, 0344, 0242, 0064, 0154, 0047, 0217, 0310, 0035, 0115, 0344, 0213, 0021, 0271, 
+  0050, 0277, 0354, 0155, 0036, 0221, 0163, 0123, 0347, 0032, 0076, 0371, 0041, 0224, 0321, 0263, 
+  0203, 0133, 0315, 0020, 0027, 0143, 0210, 0335, 0342, 0110, 0266, 0246, 0310, 0075, 0340, 0346, 
+  0346, 0365, 0301, 0215, 0134, 0065, 0215, 0241, 0321, 0360, 0147, 0377, 0007, 0226, 0234, 0102, 
+  0101, 0000, 0050, 0165, 0165, 0141, 0171, 0051, 0143, 0141, 0154, 0143, 0165, 0154, 0141, 0164, 
+  0157, 0162, 0057, 0000, 0003, 0000, 0000, 0000, 0155, 0141, 0164, 0145, 0055, 0143, 0141, 0154, 
+  0143, 0056, 0141, 0142, 0157, 0165, 0164, 0000, 0106, 0005, 0000, 0000, 0001, 0000, 0000, 0000, 
+  0170, 0332, 0155, 0124, 0075, 0157, 0033, 0071, 0020, 0355, 0363, 0053, 0330, 0260, 0064, 0213, 
+  0340, 0122, 0131, 0147, 0100, 0166, 0022, 0043, 0147, 0307, 0147, 0304, 0076, 0073, 0110, 0220, 
+  0142, 0166, 0167, 0166, 0227, 0342, 0327, 0142, 0110, 0312, 0222, 0372, 0373, 0117, 0051, 0322, 
+  0371, 0176, 0330, 0015, 0271, 0262, 0043, 0003, 0156, 0264, 0174, 0243, 0307, 0231, 0171, 0363, 
+  0301, 0357, 0313, 0046, 0344, 0364, 0343, 0315, 0062, 0247, 0061, 0120, 0374, 0163, 0331, 0240, 
+  0025, 0237, 0333, 0063, 0213, 0276, 0013, 0136, 0054, 0306, 0326, 0071, 0150, 0345, 0030, 0142, 
+  0154, 0203, 0163, 0212, 0177, 0116, 0216, 0227, 0035, 0070, 0361, 0201, 0072, 0007, 0205, 0201, 
+  0006, 0255, 0004, 0152, 0107, 0253, 0175, 0336, 0050, 0355, 0373, 0300, 0024, 0213, 0033, 0360, 
+  0035, 0222, 0130, 0263, 0233, 0163, 0233, 0133, 0043, 0076, 0335, 0211, 0205, 0001, 0153, 0165, 
+  0114, 0372, 0235, 0314, 0136, 0157, 0166, 0350, 0367, 0036, 0231, 0216, 0132, 0334, 0004, 0012, 
+  0106, 0263, 0323, 0030, 0110, 0101, 0265, 0111, 0207, 0341, 0201, 0024, 0345, 0102, 0262, 0034, 
+  0360, 0052, 0120, 0067, 0076, 0376, 0334, 0212, 0005, 0116, 0041, 0046, 0011, 0076, 0244, 0021, 
+  0011, 0006, 0364, 0355, 0126, 0171, 0216, 0175, 0066, 0022, 0207, 0010, 0023, 0133, 0305, 0307, 
+  0274, 0322, 0076, 0210, 0105, 0373, 0333, 0326, 0127, 0223, 0034, 0034, 0150, 0073, 0107, 0147, 
+  0265, 0016, 0175, 0022, 0227, 0330, 0143, 0263, 0046, 0144, 0372, 0154, 0121, 0166, 0157, 0221, 
+  0125, 0233, 0323, 0154, 0252, 0067, 0076, 0222, 0306, 0216, 0053, 0165, 0037, 0154, 0337, 0213, 
+  0105, 0077, 0103, 0231, 0010, 0174, 0264, 0220, 0120, 0005, 0032, 0324, 0016, 0116, 0216, 0377, 
+  0272, 0026, 0147, 0332, 0001, 0047, 0336, 0161, 0026, 0253, 0351, 0250, 0303, 0265, 0324, 0276, 
+  0011, 0233, 0052, 0351, 0302, 0102, 0216, 0342, 0252, 0334, 0046, 0103, 0217, 0277, 0006, 0116, 
+  0171, 0141, 0374, 0214, 0145, 0166, 0023, 0050, 0364, 0361, 0310, 0156, 0203, 0127, 0075, 0235, 
+  0034, 0137, 0102, 0334, 0331, 0040, 0116, 0271, 0116, 0121, 0054, 0064, 0270, 0210, 0316, 0345, 
+  0103, 0055, 0227, 0220, 0251, 0150, 0271, 0202, 0111, 0003, 0163, 0022, 0270, 0211, 0243, 0313, 
+  0236, 0020, 0253, 0213, 0317, 0334, 0052, 0316, 0374, 0275, 0136, 0231, 0310, 0371, 0212, 0205, 
+  0253, 0006, 0325, 0155, 0053, 0076, 0364, 0305, 0124, 0043, 0156, 0307, 0340, 0212, 0043, 0246, 
+  0231, 0046, 0111, 0354, 0201, 0260, 0127, 0036, 0123, 0375, 0077, 0161, 0267, 0356, 0265, 0233, 
+  0010, 0343, 0314, 0141, 0203, 0164, 0134, 0001, 0026, 0032, 0015, 0027, 0274, 0124, 0202, 0231, 
+  0272, 0035, 0201, 0243, 0336, 0042, 0021, 0167, 0316, 0315, 0120, 0245, 0002, 0145, 0313, 0055, 
+  0364, 0272, 0205, 0247, 0250, 0332, 0240, 0070, 0207, 0206, 0153, 0152, 0013, 0325, 0240, 0032, 
+  0146, 0044, 0073, 0210, 0107, 0034, 0171, 0367, 0300, 0325, 0111, 0010, 0116, 0165, 0170, 0162, 
+  0174, 0245, 0115, 0260, 0260, 0025, 0045, 0233, 0255, 0017, 0353, 0232, 0206, 0142, 0333, 0366, 
+  0205, 0230, 0153, 0150, 0112, 0345, 0130, 0054, 0173, 0142, 0331, 0074, 0317, 0017, 0222, 0207, 
+  0002, 0363, 0064, 0253, 0271, 0106, 0152, 0260, 0326, 0165, 0332, 0237, 0136, 0134, 0327, 0041, 
+  0221, 0170, 0117, 0377, 0375, 0073, 0060, 0241, 0200, 0216, 0147, 0356, 0220, 0361, 0205, 0105, 
+  0211, 0323, 0114, 0244, 0273, 0201, 0107, 0210, 0030, 0252, 0146, 0017, 0145, 0314, 0373, 0111, 
+  0377, 0022, 0330, 0165, 0022, 0113, 0317, 0065, 0147, 0171, 0124, 0241, 0202, 0012, 0137, 0170, 
+  0233, 0171, 0247, 0171, 0365, 0114, 0152, 0362, 0352, 0220, 0161, 0063, 0357, 0327, 0315, 0003, 
+  0042, 0225, 0141, 0360, 0275, 0046, 0235, 0136, 0060, 0332, 0220, 0330, 0005, 0130, 0217, 0260, 
+  0106, 0346, 0304, 0146, 0076, 0277, 0322, 0241, 0247, 0325, 0333, 0157, 0342, 0353, 0033, 0170, 
+  0223, 0270, 0375, 0136, 0334, 0102, 0366, 0145, 0120, 0143, 0205, 0052, 0125, 0310, 0201, 0067, 
+  0012, 0322, 0023, 0051, 0210, 0013, 0040, 0230, 0060, 0305, 0062, 0074, 0063, 0063, 0110, 0363, 
+  0154, 0333, 0147, 0230, 0220, 0127, 0322, 0213, 0013, 0002, 0176, 0200, 0230, 0147, 0376, 0170, 
+  0053, 0343, 0154, 0064, 0317, 0224, 0065, 0212, 0157, 0030, 0333, 0261, 0372, 0131, 0343, 0256, 
+  0234, 0337, 0036, 0012, 0275, 0323, 0155, 0012, 0124, 0042, 0042, 0223, 0326, 0246, 0174, 0345, 
+  0374, 0231, 0173, 0173, 0147, 0241, 0023, 0177, 0223, 0255, 0323, 0021, 0174, 0114, 0160, 0260, 
+  0204, 0145, 0211, 0007, 0360, 0203, 0370, 0307, 0066, 0245, 0153, 0145, 0200, 0022, 0112, 0342, 
+  0232, 0351, 0124, 0107, 0354, 0076, 0213, 0257, 0032, 0102, 0322, 0345, 0301, 0333, 0142, 0342, 
+  0247, 0344, 0060, 0374, 0233, 0377, 0001, 0302, 0121, 0356, 0145, 0000, 0050, 0165, 0165, 0141, 
+  0171, 0051
+} };
+
+static GStaticResource static_resource = { calculator_resource_data.data, sizeof (calculator_resource_data.data) - 1 /* nul terminator */, NULL, NULL, NULL };
+
+G_MODULE_EXPORT
+GResource *calculator_get_resource (void);
+GResource *calculator_get_resource (void)
+{
+  return g_static_resource_get_resource (&static_resource);
+}
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __G_CONSTRUCTOR_H__
+#define __G_CONSTRUCTOR_H__
+
+/*
+  If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
+  destructors, in a usable way, including e.g. on library unload. If not you're on
+  your own.
+
+  Some compilers need #pragma to handle this, which does not work with macros,
+  so the way you need to use this is (for constructors):
+
+  #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+  #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
+  #endif
+  G_DEFINE_CONSTRUCTOR(my_constructor)
+  static void my_constructor(void) {
+   ...
+  }
+
+*/
+
+#ifndef __GTK_DOC_IGNORE__
+
+#if  __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
+#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
+/* Visual studio 2008 and later has _Pragma */
+
+/*
+ * Only try to include gslist.h if not already included via glib.h,
+ * so that items using gconstructor.h outside of GLib (such as
+ * GResources) continue to build properly.
+ */
+#ifndef __G_LIB_H__
+#include "gslist.h"
+#endif
+
+#include <stdlib.h>
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* We do some weird things to avoid the constructors being optimized
+ * away on VS2015 if WholeProgramOptimization is enabled. First we
+ * make a reference to the array from the wrapper to make sure its
+ * references. Then we use a pragma to make sure the wrapper function
+ * symbol is always included at the link stage. Also, the symbols
+ * need to be extern (but not dllexport), even though they are not
+ * really used from another object file.
+ */
+
+/* We need to account for differences between the mangling of symbols
+ * for x86 and x64/ARM/ARM64 programs, as symbols on x86 are prefixed
+ * with an underscore but symbols on x64/ARM/ARM64 are not.
+ */
+#ifdef _M_IX86
+#define G_MSVC_SYMBOL_PREFIX "_"
+#else
+#define G_MSVC_SYMBOL_PREFIX ""
+#endif
+
+#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
+#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
+
+#define G_MSVC_CTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _wrapper(void) { _func(); g_slist_find (NULL,  _array ## _func); return 0; } \
+  __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
+
+#define G_MSVC_DTOR(_func,_sym_prefix) \
+  static void _func(void); \
+  extern int (* _array ## _func)(void);              \
+  int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL,  _array ## _func); return 0; } \
+   __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
+  __pragma(section(".CRT$XCU",read)) \
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined (_MSC_VER)
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* Pre Visual studio 2008 must use #pragma section */
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _wrapper(void) { _func(); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  section(".CRT$XCU",read)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void); \
+  static int _func ## _constructor(void) { atexit (_func); return 0; } \
+  __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined(__SUNPRO_C)
+
+/* This is not tested, but i believe it should work, based on:
+ * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
+ */
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+  init(_func)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+  static void _func(void);
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+  fini(_func)
+#define G_DEFINE_DESTRUCTOR(_func) \
+  static void _func(void);
+
+#else
+
+/* constructors not supported for this compiler */
+
+#endif
+
+#endif /* __GTK_DOC_IGNORE__ */
+#endif /* __G_CONSTRUCTOR_H__ */
+
+#ifdef G_HAS_CONSTRUCTORS
+
+#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(calculatorresource_constructor)
+#endif
+G_DEFINE_CONSTRUCTOR(calculatorresource_constructor)
+#ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(calculatorresource_destructor)
+#endif
+G_DEFINE_DESTRUCTOR(calculatorresource_destructor)
+
+#else
+#warning "Constructor not supported on this compiler, linking in resources will not work"
+#endif
+
+static void calculatorresource_constructor (void)
+{
+  g_static_resource_init (&static_resource);
+}
+
+static void calculatorresource_destructor (void)
+{
+  g_static_resource_fini (&static_resource);
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/3.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/3.html new file mode 100644 index 0000000..15f080b --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/3.html @@ -0,0 +1,767 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
/*
+ * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2011 Robert Ancell
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+#include <glib/gi18n.h>
+
+#include "math-window.h"
+#include "math-preferences.h"
+#include "mp-equation.h"
+#include "unit-manager.h"
+#include "utility.h"
+
+GSettings *g_settings_var = NULL;
+
+static MathWindow *window;
+
+static void
+version(const gchar *progname)
+{
+    /* NOTE: Is not translated so can be easily parsed */
+    fprintf(stderr, "%1$s %2$s\n", progname, VERSION);
+}
+
+static int
+do_convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z, void *data)
+{
+    return unit_manager_convert_by_symbol(unit_manager_get_default(), x, x_units, z_units, z);
+}
+
+static void
+solve(const char *equation)
+{
+    MPEquationOptions options;
+    MPErrorCode error;
+    MPNumber result = mp_new();
+    char *result_str;
+
+    memset(&options, 0, sizeof(options));
+    options.base = 10;
+    options.wordlen = 32;
+    options.angle_units = MP_DEGREES;
+    options.convert = do_convert;
+
+    error = mp_equation_parse(equation, &options, &result, NULL);
+    if(error == PARSER_ERR_MP) {
+        fprintf(stderr, "Error: %s\n", mp_get_error());
+        mp_clear(&result);
+        exit(1);
+    }
+    else if(error != 0) {
+        fprintf(stderr, "Error: %s\n", mp_error_code_to_string(error));
+        mp_clear(&result);
+        exit(1);
+    }
+    else {
+        result_str = mp_serializer_to_string(mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9), &result);
+        printf("%s\n", result_str);
+        mp_clear(&result);
+        exit(0);
+    }
+}
+
+static void
+usage(const gchar *progname, gboolean show_application, gboolean show_gtk)
+{
+    fprintf(stderr,
+            /* Description on how to use mate-calc displayed on command-line */
+            _("Usage:\n"
+              "  %s — Perform mathematical calculations"), progname);
+
+    fprintf(stderr,
+            "\n\n");
+
+    fprintf(stderr,
+            /* Description on mate-calc command-line help options displayed on command-line */
+            _("Help Options:\n"
+              "  -v, --version                   Show release version\n"
+              "  -h, -?, --help                  Show help options\n"
+              "  --help-all                      Show all help options\n"
+              "  --help-gtk                      Show GTK+ options"));
+    fprintf(stderr,
+            "\n\n");
+
+    if (show_gtk) {
+        fprintf(stderr,
+                /* Description on mate-calc command-line GTK+ options displayed on command-line */
+                _("GTK+ Options:\n"
+                  "  --class=CLASS                   Program class as used by the window manager\n"
+                  "  --name=NAME                     Program name as used by the window manager\n"
+                  "  --screen=SCREEN                 X screen to use\n"
+                  "  --sync                          Make X calls synchronous\n"
+                  "  --gtk-module=MODULES            Load additional GTK+ modules\n"
+                  "  --g-fatal-warnings              Make all warnings fatal"));
+        fprintf(stderr,
+                "\n\n");
+    }
+
+    if (show_application) {
+        fprintf(stderr,
+                /* Description on mate-calc application options displayed on command-line */
+                _("Application Options:\n"
+                  "  -s, --solve <equation>          Solve the given equation"));
+        fprintf(stderr,
+                "\n\n");
+    }
+}
+
+static void
+get_options(int argc, char *argv[])
+{
+    int i;
+    char *progname, *arg;
+
+    progname = g_path_get_basename(argv[0]);
+
+    for (i = 1; i < argc; i++) {
+        arg = argv[i];
+
+        if (strcmp(arg, "-v") == 0 ||
+            strcmp(arg, "--version") == 0) {
+            version(progname);
+            g_free(progname);
+            exit(0);
+        }
+        else if (strcmp(arg, "-h") == 0 ||
+                 strcmp(arg, "-?") == 0 ||
+                 strcmp(arg, "--help") == 0) {
+            usage(progname, TRUE, FALSE);
+            g_free(progname);
+            exit(0);
+        }
+        else if (strcmp(arg, "--help-all") == 0) {
+            usage(progname, TRUE, TRUE);
+            g_free(progname);
+            exit(0);
+        }
+        else if (strcmp(arg, "--help-gtk") == 0) {
+            usage(progname, FALSE, TRUE);
+            g_free(progname);
+            exit(0);
+        }
+        else if (strcmp(arg, "-s") == 0 ||
+            strcmp(arg, "--solve") == 0) {
+            i++;
+            if (i >= argc) {
+                fprintf(stderr,
+                        /* Error printed to stderr when user uses --solve argument without an equation */
+                        _("Argument --solve requires an equation to solve"));
+                fprintf(stderr, "\n");
+                g_free(progname);
+                exit(1);
+            }
+            else
+                solve(argv[i]);
+        }
+        else {
+            fprintf(stderr,
+                    /* Error printed to stderr when user provides an unknown command-line argument */
+                    _("Unknown argument '%s'"), arg);
+            fprintf(stderr, "\n");
+            usage(progname, TRUE, FALSE);
+            g_free(progname);
+            exit(1);
+        }
+    }
+
+    g_free(progname);
+}
+
+static void
+quit_cb(MathWindow *win)
+{
+    gtk_main_quit();
+}
+
+int main(int argc, char **argv)
+{
+    MathEquation *equation;
+    MathButtons *buttons;
+    int accuracy = 9, word_size = 64, base = 10;
+    gboolean show_tsep = FALSE, show_zeroes = FALSE, show_hist = FALSE;
+    MpDisplayFormat number_format;
+    MPAngleUnit angle_units;
+    ButtonMode button_mode;
+    gchar *source_currency, *target_currency;
+    gchar *source_units, *target_units;
+
+    setlocale(LC_ALL, "");
+    bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
+    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+    textdomain(GETTEXT_PACKAGE);
+
+    /* Seed random number generator. */
+    srand48((long) time((time_t *) 0));
+
+    gtk_init(&argc, &argv);
+
+    g_settings_var = g_settings_new ("org.mate.calc");
+    accuracy = g_settings_get_int(g_settings_var, "accuracy");
+    word_size = g_settings_get_int(g_settings_var, "word-size");
+    base = g_settings_get_int(g_settings_var, "base");
+    show_tsep = g_settings_get_boolean(g_settings_var, "show-thousands");
+    show_zeroes = g_settings_get_boolean(g_settings_var, "show-zeroes");
+    show_hist = g_settings_get_boolean(g_settings_var, "show-history");
+    number_format = g_settings_get_enum(g_settings_var, "number-format");
+    angle_units = g_settings_get_enum(g_settings_var, "angle-units");
+    button_mode = g_settings_get_enum(g_settings_var, "button-mode");
+    source_currency = g_settings_get_string(g_settings_var, "source-currency");
+    target_currency = g_settings_get_string(g_settings_var, "target-currency");
+    source_units = g_settings_get_string(g_settings_var, "source-units");
+    target_units = g_settings_get_string(g_settings_var, "target-units");
+
+    equation = math_equation_new();
+    math_equation_set_accuracy(equation, accuracy);
+    math_equation_set_word_size(equation, word_size);
+    math_equation_set_show_thousands_separators(equation, show_tsep);
+    math_equation_set_show_trailing_zeroes(equation, show_zeroes);
+    math_equation_set_number_format(equation, number_format);
+    math_equation_set_angle_units(equation, angle_units);
+    math_equation_set_source_currency(equation, source_currency);
+    math_equation_set_target_currency(equation, target_currency);
+    math_equation_set_source_units(equation, source_units);
+    math_equation_set_target_units(equation, target_units);
+    g_free(source_currency);
+    g_free(target_currency);
+    g_free(source_units);
+    g_free(target_units);
+
+    get_options(argc, argv);
+
+    //gtk_window_set_default_icon_name("accessories-calculator");
+
+    window = math_window_new(equation);
+    buttons = math_window_get_buttons(window);
+    g_signal_connect(G_OBJECT(window), "quit", G_CALLBACK(quit_cb), NULL);
+    math_window_set_show_history(window, show_hist);
+    math_buttons_set_programming_base(buttons, base);
+    math_buttons_set_mode(buttons, button_mode); // FIXME: We load the basic buttons even if we immediately switch to the next type
+
+    gtk_widget_show(GTK_WIDGET(window));
+    gtk_main();
+
+    return 0;
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/4.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/4.html new file mode 100644 index 0000000..5e2687d --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/4.html @@ -0,0 +1,3021 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
/*
+ * Copyright (C) 2008-2011 Robert Ancell
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <glib/gi18n.h>
+
+#include "math-buttons.h"
+#include "math-converter.h"
+#include "math-variable-popup.h"
+#include "financial.h"
+#include "mp-serializer.h"
+#include "utility.h"
+
+enum {
+    PROP_0,
+    PROP_EQUATION,
+    PROP_MODE,
+    PROP_PROGRAMMING_BASE
+};
+
+static GType button_mode_type;
+
+#define MAXBITS 64      /* Bit panel: number of bit fields. */
+
+struct MathButtonsPrivate
+{
+    MathEquation *equation;
+
+    ButtonMode mode;
+    gint programming_base;
+
+    MathConverter *converter;
+
+    GtkBuilder *basic_ui, *advanced_ui, *financial_ui, *programming_ui;
+
+    GtkWidget *bas_panel, *adv_panel, *fin_panel, *prog_panel;
+    GtkWidget *active_panel;
+
+    GtkWidget *shift_left_menu, *shift_right_menu;
+
+    GtkWidget *function_menu;
+    GtkWidget *const_menu;
+
+    GList *superscript_toggles;
+    GList *subscript_toggles;
+
+    GtkWidget *base_combo;
+    GtkWidget *base_label;
+    GtkWidget *bit_panel;
+    GtkWidget *bit_labels[MAXBITS];
+
+    GtkWidget *character_code_dialog;
+    GtkWidget *character_code_entry;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (MathButtons, math_buttons, GTK_TYPE_BOX);
+
+#define UI_BASIC_RESOURCE_PATH       "/org/mate/calculator/ui/buttons-basic.ui"
+#define UI_ADVANCED_RESOURCE_PATH    "/org/mate/calculator/ui/buttons-advanced.ui"
+#define UI_FINANCIAL_RESOURCE_PATH   "/org/mate/calculator/ui/buttons-financial.ui"
+#define UI_PROGRAMMING_RESOURCE_PATH "/org/mate/calculator/ui/buttons-programming.ui"
+
+#define GET_WIDGET(ui, name) \
+          GTK_WIDGET(gtk_builder_get_object((ui), (name)))
+
+typedef enum
+{
+    NUMBER,
+    NUMBER_BOLD,
+    OPERATOR,
+    FUNCTION,
+    MEMORY,
+    GROUP,
+    ACTION
+} ButtonClass;
+
+typedef struct {
+    const char *widget_name;
+    const char *data;
+    ButtonClass class;
+    const char *tooltip;
+} ButtonData;
+
+static ButtonData button_data[] = {
+    {"pi",                 "π", NUMBER,
+      /* Tooltip for the Pi button */
+      N_("Pi [Ctrl+P]")},
+    {"eulers_number",      "e", NUMBER,
+      /* Tooltip for the Euler's Number button */
+      N_("Euler’s Number")},
+    {"imaginary",          "i", NUMBER,
+      /* Tooltip for the imaginary number button */
+      N_("Imaginary unit")},
+    {"numeric_point", NULL, NUMBER,
+      /* Tooltip for the numeric point button */
+      N_("Decimal point")},
+    {"subscript", NULL, NUMBER_BOLD,
+      /* Tooltip for the subscript button */
+      N_("Subscript mode [Alt]")},
+    {"superscript", NULL, NUMBER_BOLD,
+      /* Tooltip for the superscript button */
+      N_("Superscript mode [Ctrl]")},
+    {"exponential", NULL, NUMBER_BOLD,
+      /* Tooltip for the scientific exponent button */
+      N_("Scientific exponent [Ctrl+E]")},
+    {"add",                "+", OPERATOR,
+      /* Tooltip for the add button */
+      N_("Add [+]")},
+    {"subtract",           "−", OPERATOR,
+      /* Tooltip for the subtract button */
+      N_("Subtract [-]")},
+    {"multiply",           "×", OPERATOR,
+      /* Tooltip for the multiply button */
+      N_("Multiply [*]")},
+    {"divide",             "÷", OPERATOR,
+      /* Tooltip for the divide button */
+      N_("Divide [/]")},
+    {"modulus_divide",     " mod ", OPERATOR,
+      /* Tooltip for the modulus divide button */
+      N_("Modulus divide")},
+    {"function",           NULL, FUNCTION,
+      /* Tooltip for the additional functions button */
+      N_("Additional Functions")},
+    {"const",           NULL, FUNCTION,
+      /* Tooltip for the additional constant button */
+      N_("Additional constants")},
+    {"x_pow_y",            "^", FUNCTION,
+      /* Tooltip for the exponent button */
+      N_("Exponent [^ or **]")},
+    {"x_squared",          "²", FUNCTION,
+      /* Tooltip for the square button */
+      N_("Square [Ctrl+2]")},
+    {"percentage",         "%", NUMBER,
+      /* Tooltip for the percentage button */
+      N_("Percentage [%]")},
+    {"factorial",          "!", FUNCTION,
+      /* Tooltip for the factorial button */
+      N_("Factorial [!]")},
+    {"abs",                "|", FUNCTION,
+      /* Tooltip for the absolute value button */
+      N_("Absolute value [|]")},
+    {"arg",                "Arg ", FUNCTION,
+      /* Tooltip for the complex argument component button */
+      N_("Complex argument")},
+    {"conjugate",          "conj ", FUNCTION,
+      /* Tooltip for the complex conjugate button */
+      N_("Complex conjugate")},
+    {"root",               "√", FUNCTION,
+      /* Tooltip for the root button */
+      N_("Root [Ctrl+R]")},
+    {"square_root",        "√", FUNCTION,
+      /* Tooltip for the square root button */
+      N_("Square root [Ctrl+R]")},
+    {"logarithm",          "log ", FUNCTION,
+      /* Tooltip for the logarithm button */
+      N_("Logarithm")},
+    {"natural_logarithm",  "ln ", FUNCTION,
+      /* Tooltip for the natural logarithm button */
+      N_("Natural Logarithm")},
+    {"sine",               "sin ", FUNCTION,
+      /* Tooltip for the sine button */
+      N_("Sine")},
+    {"cosine",             "cos ", FUNCTION,
+      /* Tooltip for the cosine button */
+      N_("Cosine")},
+    {"tangent",            "tan ", FUNCTION,
+      /* Tooltip for the tangent button */
+      N_("Tangent")},
+    {"hyperbolic_sine",    "sinh ", FUNCTION,
+      /* Tooltip for the hyperbolic sine button */
+      N_("Hyperbolic Sine")},
+    {"hyperbolic_cosine",  "cosh ", FUNCTION,
+      /* Tooltip for the hyperbolic cosine button */
+      N_("Hyperbolic Cosine")},
+    {"hyperbolic_tangent", "tanh ", FUNCTION,
+      /* Tooltip for the hyperbolic tangent button */
+      N_("Hyperbolic Tangent")},
+    {"inverse_sine", "asin ", FUNCTION,
+      /* Tooltip for the inverse sine button */
+      N_("Inverse Sine")},
+    {"inverse_cosine", "acos ", FUNCTION,
+      /* Tooltip for the inverse cosine button */
+      N_("Inverse Cosine")},
+    {"inverse_tangent", "atan ", FUNCTION,
+      /* Tooltip for the inverse tangent button */
+      N_("Inverse Tangent")},
+    {"inverse",            "⁻¹", FUNCTION,
+      /* Tooltip for the inverse button */
+      N_("Inverse [Ctrl+I]")},
+    {"and",                "∧", OPERATOR,
+      /* Tooltip for the boolean AND button */
+      N_("Boolean AND")},
+    {"or",                 "∨", OPERATOR,
+      /* Tooltip for the boolean OR button */
+      N_("Boolean OR")},
+    {"xor",                "⊻", OPERATOR,
+      /* Tooltip for the exclusive OR button */
+      N_("Boolean Exclusive OR")},
+    {"not",                "¬", FUNCTION,
+      /* Tooltip for the boolean NOT button */
+      N_("Boolean NOT")},
+    {"integer_portion",    "int ", FUNCTION,
+      /* Tooltip for the integer component button */
+      N_("Integer Component")},
+    {"fractional_portion", "frac ", FUNCTION,
+      /* Tooltip for the fractional component button */
+      N_("Fractional Component")},
+    {"real_portion",       "Re ", FUNCTION,
+      /* Tooltip for the real component button */
+      N_("Real Component")},
+    {"imaginary_portion",  "Im ", FUNCTION,
+      /* Tooltip for the imaginary component button */
+      N_("Imaginary Component")},
+    {"ones_complement",    "ones ", FUNCTION,
+      /* Tooltip for the ones' complement button */
+      N_("Ones' Complement")},
+    {"twos_complement",    "twos ", FUNCTION,
+      /* Tooltip for the two's complement button */
+      N_("Two's Complement")},
+    {"start_group",        "(", GROUP,
+      /* Tooltip for the start group button */
+      N_("Start Group [(]")},
+    {"end_group",          ")", GROUP,
+      /* Tooltip for the end group button */
+      N_("End Group [)]")},
+    {"memory", NULL, MEMORY,
+      /* Tooltip for the memory button */
+      N_("Memory")},
+    {"character", NULL, MEMORY,
+      /* Tooltip for the insert character code button */
+      N_("Insert Character Code")},
+    {"result", NULL, ACTION,
+      /* Tooltip for the solve button */
+      N_("Calculate Result")},
+    {"factor", NULL, ACTION,
+      /* Tooltip for the factor button */
+      N_("Factorize [Ctrl+F]")},
+    {"clear", NULL, GROUP,
+      /* Tooltip for the clear button */
+      N_("Clear Display [Escape]")},
+    {"undo", NULL, GROUP,
+      /* Tooltip for the undo button */
+      N_("Undo [Ctrl+Z]")},
+    {"shift_left", NULL, ACTION,
+      /* Tooltip for the shift left button */
+      N_("Shift Left [<<]")},
+    {"shift_right", NULL, ACTION,
+      /* Tooltip for the shift right button */
+      N_("Shift Right [>>]")},
+    {"finc_compounding_term", NULL, FUNCTION,
+      /* Tooltip for the compounding term button */
+      N_("Compounding Term")},
+    {"finc_double_declining_depreciation", NULL, FUNCTION,
+      /* Tooltip for the double declining depreciation button */
+      N_("Double Declining Depreciation")},
+    {"finc_future_value", NULL, FUNCTION,
+      /* Tooltip for the future value button */
+      N_("Future Value")},
+    {"finc_term", NULL, FUNCTION,
+      /* Tooltip for the financial term button */
+      N_("Financial Term")},
+    {"finc_sum_of_the_years_digits_depreciation", NULL, FUNCTION,
+      /* Tooltip for the sum of the years digits depreciation button */
+      N_("Sum of the Years Digits Depreciation")},
+    {"finc_straight_line_depreciation", NULL, FUNCTION,
+      /* Tooltip for the straight line depreciation button */
+      N_("Straight Line Depreciation")},
+    {"finc_periodic_interest_rate", NULL, FUNCTION,
+      /* Tooltip for the periodic interest rate button */
+      N_("Periodic Interest Rate")},
+    {"finc_present_value", NULL, FUNCTION,
+      /* Tooltip for the present value button */
+      N_("Present Value")},
+    {"finc_periodic_payment", NULL, FUNCTION,
+      /* Tooltip for the periodic payment button */
+      N_("Periodic Payment")},
+    {"finc_gross_profit_margin", NULL, FUNCTION,
+      /* Tooltip for the gross profit margin button */
+      N_("Gross Profit Margin")},
+    {NULL, NULL, 0, NULL}
+};
+
+/* The names of each field in the dialogs for the financial functions */
+static char *finc_dialog_fields[][5] = {
+    {"ctrm_pint", "ctrm_fv",     "ctrm_pv",    NULL,         NULL},
+    {"ddb_cost",  "ddb_life",    "ddb_period", NULL,         NULL},
+    {"fv_pmt",    "fv_pint",     "fv_n",       NULL,         NULL},
+    {"gpm_cost",  "gpm_margin",  NULL,         NULL,         NULL},
+    {"pmt_prin",  "pmt_pint",    "pmt_n",      NULL,         NULL},
+    {"pv_pmt",    "pv_pint",     "pv_n",       NULL,         NULL},
+    {"rate_fv",   "rate_pv",     "rate_n",     NULL,         NULL},
+    {"sln_cost",  "sln_salvage", "sln_life",   NULL,         NULL},
+    {"syd_cost",  "syd_salvage", "syd_life",   "syd_period", NULL},
+    {"term_pmt",  "term_fv",     "term_pint",  NULL,         NULL},
+    {NULL,        NULL,          NULL,         NULL,         NULL}
+};
+
+MathButtons *
+math_buttons_new(MathEquation *equation)
+{
+    return g_object_new(math_buttons_get_type(), "equation", equation, NULL);
+}
+
+static void
+set_data(GtkBuilder *ui, const gchar *object_name, const gchar *name, const char *value)
+{
+    GObject *object;
+    object = gtk_builder_get_object(ui, object_name);
+    if (object)
+        g_object_set_data(object, name, GINT_TO_POINTER(value));
+}
+
+static void
+set_int_data(GtkBuilder *ui, const gchar *object_name, const gchar *name, gint value)
+{
+    GObject *object;
+    object = gtk_builder_get_object(ui, object_name);
+    if (object)
+        g_object_set_data(object, name, GINT_TO_POINTER(value));
+}
+
+static void
+load_finc_dialogs(MathButtons *buttons)
+{
+    int i, j;
+
+    set_int_data(buttons->priv->financial_ui, "ctrm_dialog", "finc_dialog", FINC_CTRM_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "ddb_dialog", "finc_dialog", FINC_DDB_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "fv_dialog", "finc_dialog", FINC_FV_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "gpm_dialog", "finc_dialog", FINC_GPM_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "pmt_dialog", "finc_dialog", FINC_PMT_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "pv_dialog", "finc_dialog", FINC_PV_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "rate_dialog", "finc_dialog", FINC_RATE_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "sln_dialog", "finc_dialog", FINC_SLN_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "syd_dialog", "finc_dialog", FINC_SYD_DIALOG);
+    set_int_data(buttons->priv->financial_ui, "term_dialog", "finc_dialog", FINC_TERM_DIALOG);
+
+    for (i = 0; finc_dialog_fields[i][0] != NULL; i++) {
+        for (j = 0; finc_dialog_fields[i][j]; j++) {
+            GObject *o;
+            o = gtk_builder_get_object (buttons->priv->financial_ui, finc_dialog_fields[i][j]);
+            g_object_set_data(o, "finc_field", GINT_TO_POINTER(j));
+            g_object_set_data(o, "finc_dialog", GINT_TO_POINTER(i));
+        }
+    }
+}
+
+static void
+update_bit_panel(MathButtons *buttons)
+{
+    MPNumber x;
+    gboolean enabled;
+    guint64 bits;
+    int i;
+    GString *label;
+    gint base;
+
+    if (!buttons->priv->bit_panel)
+        return;
+
+    x = mp_new();
+    enabled = math_equation_get_number(buttons->priv->equation, &x);
+
+    if (enabled) {
+        MPNumber max = mp_new();
+        MPNumber fraction = mp_new();
+
+        mp_set_from_unsigned_integer(G_MAXUINT64, &max);
+        mp_fractional_part(&x, &fraction);
+        if (mp_is_negative(&x) || mp_is_greater_than(&x, &max) || !mp_is_zero(&fraction))
+            enabled = FALSE;
+        else
+            bits = mp_to_unsigned_integer(&x);
+        mp_clear(&max);
+        mp_clear(&fraction);
+    }
+
+    gtk_widget_set_sensitive(buttons->priv->bit_panel, enabled);
+    gtk_widget_set_sensitive(buttons->priv->base_label, enabled);
+
+    if (!enabled)
+    {
+        mp_clear(&x);
+        return;
+    }
+
+    for (i = 0; i < MAXBITS; i++) {
+        const gchar *bin_label;
+
+        if (bits & (1LLU << (MAXBITS-i-1)))
+            bin_label = " 1";
+        else
+            bin_label = " 0";
+        gtk_label_set_text(GTK_LABEL(buttons->priv->bit_labels[i]), bin_label);
+    }
+
+    base = math_equation_get_base(buttons->priv->equation);
+    label = g_string_new("");
+    if (base != 8) {
+        if (label->len != 0)
+            g_string_append(label, " = ");
+        g_string_append_printf(label, "%" G_GINT64_MODIFIER "o", bits);
+        g_string_append(label, "₈");
+    }
+    if (base != 10) {
+        if (label->len != 0)
+            g_string_append(label, " = ");
+        g_string_append_printf(label, "%" G_GINT64_MODIFIER "u", bits);
+        g_string_append(label, "₁₀");
+    }
+    if (base != 16) {
+        if (label->len != 0)
+            g_string_append(label, " = ");
+        g_string_append_printf(label, "%" G_GINT64_MODIFIER "X", bits);
+        g_string_append(label, "₁₆");
+    }
+
+    gtk_label_set_text(GTK_LABEL(buttons->priv->base_label), label->str);
+    g_string_free(label, TRUE);
+    mp_clear(&x);
+}
+
+static void
+display_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
+{
+    update_bit_panel(buttons);
+}
+
+static void
+base_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
+{
+    gint value;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
+    gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
+    gtk_tree_model_get(model, &iter, 1, &value, -1);
+
+    math_buttons_set_programming_base(buttons, value);
+}
+
+static void
+base_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    gboolean valid;
+
+    if (buttons->priv->mode != PROGRAMMING)
+        return;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->base_combo));
+    valid = gtk_tree_model_get_iter_first(model, &iter);
+    buttons->priv->programming_base = math_equation_get_base(buttons->priv->equation);
+
+    while (valid) {
+        gint v;
+
+        gtk_tree_model_get(model, &iter, 1, &v, -1);
+        if (v == buttons->priv->programming_base)
+            break;
+        valid = gtk_tree_model_iter_next(model, &iter);
+    }
+    if (!valid)
+        valid = gtk_tree_model_get_iter_first(model, &iter);<--- Variable 'valid' is assigned a value that is never used.
+
+    gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->base_combo), &iter);
+}
+
+static GtkWidget *
+load_mode(MathButtons *buttons, ButtonMode mode)
+{
+    GtkBuilder *builder, **builder_ptr;
+    gint i;
+    gchar *name;
+    const gchar *path;
+    static gchar *objects[] = { "button_panel", "character_code_dialog", "currency_dialog",
+                                "ctrm_dialog", "ddb_dialog", "fv_dialog", "gpm_dialog",
+                                "pmt_dialog", "pv_dialog", "rate_dialog", "sln_dialog",
+                                "syd_dialog", "term_dialog", "adjustment1", "adjustment2", NULL };
+    GtkWidget *widget, **panel;
+    GError *error = NULL;
+
+    switch (mode) {
+    default:
+    case BASIC:
+        builder_ptr = &buttons->priv->basic_ui;
+        path = UI_BASIC_RESOURCE_PATH;
+        panel = &buttons->priv->bas_panel;
+        break;
+    case ADVANCED:
+        builder_ptr = &buttons->priv->advanced_ui;
+        path = UI_ADVANCED_RESOURCE_PATH;
+        panel = &buttons->priv->adv_panel;
+        break;
+    case FINANCIAL:
+        builder_ptr = &buttons->priv->financial_ui;
+        path = UI_FINANCIAL_RESOURCE_PATH;
+        panel = &buttons->priv->fin_panel;
+        break;
+    case PROGRAMMING:
+        builder_ptr = &buttons->priv->programming_ui;
+        path = UI_PROGRAMMING_RESOURCE_PATH;
+        panel = &buttons->priv->prog_panel;
+        break;
+    }
+
+    if (*panel)
+        goto out;
+
+    builder = *builder_ptr = gtk_builder_new();
+    // FIXME: Show dialog if failed to load
+    gtk_builder_add_objects_from_resource(builder, path, objects, &error);
+    if (error) {
+        g_warning("Error loading button UI: %s", error->message);
+        g_clear_error(&error);
+    }
+    *panel = GET_WIDGET(builder, "button_panel");
+    gtk_box_pack_end(GTK_BOX(buttons), *panel, TRUE, TRUE, 0);
+
+    /* Configure buttons */
+    for (i = 0; button_data[i].widget_name != NULL; i++) {
+        GObject *object;
+        GtkWidget *button;
+
+        name = g_strdup_printf("calc_%s_button", button_data[i].widget_name);
+        object = gtk_builder_get_object(*builder_ptr, name);
+        g_free(name);
+
+        if (!object)
+            continue;
+        button = GTK_WIDGET(object);
+        if (button_data[i].data)
+            g_object_set_data(object, "calc_text", (gpointer) button_data[i].data);
+
+        if (button_data[i].tooltip)
+            gtk_widget_set_tooltip_text(button, _(button_data[i].tooltip));
+    }
+
+    /* Set special button data */
+    for (i = 0; i < 16; i++) {
+        GtkWidget *button;
+
+        name = g_strdup_printf("calc_%d_button", i);
+        button = GET_WIDGET(builder, name);
+        if (button) {
+            gchar buffer[7];
+            gint len;
+
+            g_object_set_data(G_OBJECT(button), "calc_digit", GINT_TO_POINTER(i));
+            len = g_unichar_to_utf8(math_equation_get_digit_text(buttons->priv->equation, i), buffer);
+            buffer[len] = '\0';
+            gtk_button_set_label(GTK_BUTTON(button), buffer);
+        }
+        g_free(name);
+    }
+    widget = GET_WIDGET(builder, "calc_numeric_point_button");
+    if (widget) {
+        MpSerializer *serializer = math_equation_get_serializer(buttons->priv->equation);
+        gchar buffer[7];
+        gint len;
+        len = g_unichar_to_utf8(mp_serializer_get_radix(serializer), buffer);
+        buffer[len] = '\0';
+        gtk_button_set_label(GTK_BUTTON(widget), buffer);
+    }
+
+    widget = GET_WIDGET(builder, "calc_superscript_button");
+    if (widget) {
+        buttons->priv->superscript_toggles = g_list_append(buttons->priv->superscript_toggles, widget);
+        if (math_equation_get_number_mode(buttons->priv->equation) == SUPERSCRIPT)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
+    }
+    widget = GET_WIDGET(builder, "calc_subscript_button");
+    if (widget) {
+        buttons->priv->subscript_toggles = g_list_append(buttons->priv->subscript_toggles, widget);
+        if (math_equation_get_number_mode(buttons->priv->equation) == SUBSCRIPT)
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
+    }
+
+    /* put the icon name "process-stop" in the buttons
+       button1, button3, button5, button7, button9,
+       button11, button13, button15, button17, button19
+       taken from buttons-financial.ui */
+    for (i = 1; i < 20; i++) {
+        if (i % 2) {
+            widget = GET_WIDGET (builder, g_strdup_printf ("button%d",i));
+            if (GTK_IS_BUTTON(widget))
+                gtk_button_set_image (GTK_BUTTON (widget),
+                                      gtk_image_new_from_icon_name ("process-stop", GTK_ICON_SIZE_BUTTON));
+        }
+    }
+
+    if (mode == PROGRAMMING) {
+        GtkListStore *model;
+        GtkTreeIter iter;
+        GtkCellRenderer *renderer;
+
+        buttons->priv->base_label = GET_WIDGET(builder, "base_label");
+        buttons->priv->character_code_dialog = GET_WIDGET(builder, "character_code_dialog");
+        buttons->priv->character_code_entry = GET_WIDGET(builder, "character_code_entry");
+
+        buttons->priv->bit_panel = GET_WIDGET(builder, "bit_table");
+        for (i = 0; i < MAXBITS; i++) {
+            name = g_strdup_printf("bit_label_%d", i);
+            buttons->priv->bit_labels[i] = GET_WIDGET(builder, name);
+            g_free(name);
+            name = g_strdup_printf("bit_eventbox_%d", i);
+            set_int_data(builder, name, "bit_index", i);
+        }
+
+        buttons->priv->base_combo = GET_WIDGET(builder, "base_combo");
+        model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
+        gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->base_combo), GTK_TREE_MODEL(model));
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                           /* Number display mode combo: Binary, e.g. 10011010010₂ */
+                           _("Binary"), 1, 2, -1);
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                           /* Number display mode combo: Octal, e.g. 2322₈ */
+                           _("Octal"), 1, 8, -1);
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                           /* Number display mode combo: Decimal, e.g. 1234 */
+                           _("Decimal"), 1, 10, -1);
+        gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                           /* Number display mode combo: Hexadecimal, e.g. 4D2₁₆ */
+                           _("Hexadecimal"), 1, 16, -1);
+        renderer = gtk_cell_renderer_text_new();
+        gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons->priv->base_combo), renderer, TRUE);
+        gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons->priv->base_combo), renderer, "text", 0);
+
+        g_signal_connect(buttons->priv->base_combo, "changed", G_CALLBACK(base_combobox_changed_cb), buttons);
+        g_signal_connect(buttons->priv->equation, "notify::base", G_CALLBACK(base_changed_cb), buttons);
+        base_changed_cb(buttons->priv->equation, NULL, buttons);
+    }
+
+    /* Setup financial functions */
+    if (mode == FINANCIAL) {
+        load_finc_dialogs(buttons);
+
+        set_data(builder, "calc_finc_compounding_term_button", "finc_dialog", "ctrm_dialog");
+        set_data(builder, "calc_finc_double_declining_depreciation_button", "finc_dialog", "ddb_dialog");
+        set_data(builder, "calc_finc_future_value_button", "finc_dialog", "fv_dialog");
+        set_data(builder, "calc_finc_gross_profit_margin_button", "finc_dialog", "gpm_dialog");
+        set_data(builder, "calc_finc_periodic_payment_button", "finc_dialog", "pmt_dialog");
+        set_data(builder, "calc_finc_present_value_button", "finc_dialog", "pv_dialog");
+        set_data(builder, "calc_finc_periodic_interest_rate_button", "finc_dialog", "rate_dialog");
+        set_data(builder, "calc_finc_straight_line_depreciation_button", "finc_dialog", "sln_dialog");
+        set_data(builder, "calc_finc_sum_of_the_years_digits_depreciation_button", "finc_dialog", "syd_dialog");
+        set_data(builder, "calc_finc_term_button", "finc_dialog", "term_dialog");
+    }
+
+    gtk_builder_connect_signals(builder, buttons);
+
+    display_changed_cb(buttons->priv->equation, NULL, buttons);
+
+out:
+    return *panel;
+}
+
+static void
+converter_changed_cb(MathConverter *converter, MathButtons *buttons)
+{
+    Unit *from_unit, *to_unit;
+
+    math_converter_get_conversion(converter, &from_unit, &to_unit);
+    if (buttons->priv->mode == FINANCIAL) {
+        math_equation_set_source_currency(buttons->priv->equation, unit_get_name(from_unit));
+        math_equation_set_target_currency(buttons->priv->equation, unit_get_name(to_unit));
+    }
+    else {
+        math_equation_set_source_units(buttons->priv->equation, unit_get_name(from_unit));
+        math_equation_set_target_units(buttons->priv->equation, unit_get_name(to_unit));
+    }
+
+    g_object_unref(from_unit);
+    g_object_unref(to_unit);
+}
+
+static void
+load_buttons(MathButtons *buttons)
+{
+    GtkWidget *panel;
+
+    if (!gtk_widget_get_visible(GTK_WIDGET(buttons)))
+        return;
+
+    if (!buttons->priv->converter) {
+        buttons->priv->converter = math_converter_new(buttons->priv->equation);
+        g_signal_connect(buttons->priv->converter, "changed", G_CALLBACK(converter_changed_cb), buttons);
+        gtk_box_pack_start(GTK_BOX(buttons), GTK_WIDGET(buttons->priv->converter), FALSE, TRUE, 0);
+    }
+
+    panel = load_mode(buttons, buttons->priv->mode);
+    if (buttons->priv->active_panel == panel)
+        return;
+
+    /* Hide old buttons */
+    if (buttons->priv->active_panel)
+        gtk_widget_hide(buttons->priv->active_panel);
+
+    /* Load and display new buttons */
+    buttons->priv->active_panel = panel;
+    if (panel)
+        gtk_widget_show(panel);
+}
+
+void
+math_buttons_set_mode(MathButtons *buttons, ButtonMode mode)
+{
+    g_return_if_fail(buttons != NULL);
+
+    if (buttons->priv->mode == mode)
+        return;
+
+    buttons->priv->mode = mode;
+
+    if (mode == PROGRAMMING)
+        math_equation_set_base(buttons->priv->equation, buttons->priv->programming_base);
+    else
+        math_equation_set_base(buttons->priv->equation, 10);
+
+    load_buttons(buttons);
+
+    gtk_widget_set_visible(GTK_WIDGET(buttons->priv->converter), mode == ADVANCED || mode == FINANCIAL);
+    if (mode == ADVANCED) {
+        math_converter_set_category(buttons->priv->converter, NULL);
+        math_converter_set_conversion(buttons->priv->converter,
+                                      math_equation_get_source_units(buttons->priv->equation),
+                                      math_equation_get_target_units(buttons->priv->equation));
+    }
+    else if (mode == FINANCIAL) {
+        math_converter_set_category(buttons->priv->converter, "currency");
+        math_converter_set_conversion(buttons->priv->converter,
+                                      math_equation_get_source_currency(buttons->priv->equation),
+                                      math_equation_get_target_currency(buttons->priv->equation));
+    }
+
+    g_object_notify(G_OBJECT(buttons), "mode");
+}
+
+ButtonMode
+math_buttons_get_mode(MathButtons *buttons)
+{
+    return buttons->priv->mode;
+}
+
+void
+math_buttons_set_programming_base(MathButtons *buttons, gint base)
+{
+    g_return_if_fail(buttons != NULL);
+
+    if (base == buttons->priv->programming_base)
+        return;
+
+    buttons->priv->programming_base = base;
+
+    g_settings_set_int(g_settings_var, "base", math_buttons_get_programming_base(buttons));
+
+    if (buttons->priv->mode == PROGRAMMING)
+        math_equation_set_base(buttons->priv->equation, base);
+}
+
+gint
+math_buttons_get_programming_base(MathButtons *buttons)
+{
+    g_return_val_if_fail(buttons != NULL, 10);
+    return buttons->priv->programming_base;
+}
+
+void exponent_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+exponent_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert_exponent(buttons->priv->equation);
+}
+
+void subtract_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+subtract_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert_subtract(buttons->priv->equation);
+}
+
+void button_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+button_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget), "calc_text"));
+}
+
+void solve_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+solve_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_solve(buttons->priv->equation);
+}
+
+void clear_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+clear_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_clear(buttons->priv->equation);
+}
+
+void delete_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+delete_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_delete(buttons->priv->equation);
+}
+
+void undo_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+undo_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_undo(buttons->priv->equation);
+}
+
+static void
+shift_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_shift(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "shiftcount")));
+}
+
+static void
+popup_button_menu(GtkWidget *widget, GtkMenu *menu)
+{
+    gtk_menu_popup_at_widget (menu,
+                              widget,
+                              GDK_GRAVITY_SOUTH_WEST,
+                              GDK_GRAVITY_NORTH_WEST,
+                              NULL);
+}
+
+void memory_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+memory_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    MathVariablePopup *popup;
+    GtkAllocation allocation;
+    gint x, y;
+
+    popup = math_variable_popup_new(buttons->priv->equation);
+    gtk_window_set_transient_for(GTK_WINDOW(popup), GTK_WINDOW(gtk_widget_get_toplevel(widget)));
+
+    gtk_widget_get_allocation(widget, &allocation);
+    gdk_window_get_root_coords(gtk_widget_get_window(widget), allocation.x, allocation.y, &x, &y);
+    gtk_window_move(GTK_WINDOW(popup), x, y);
+    gtk_widget_show(GTK_WIDGET(popup));
+}
+
+void shift_left_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+shift_left_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    if (!buttons->priv->shift_left_menu) {
+        gint i;
+        GtkWidget *menu;
+
+        menu = buttons->priv->shift_left_menu = gtk_menu_new();
+        gtk_menu_set_reserve_toggle_size(GTK_MENU(menu), FALSE);
+
+        for (i = 1; i < 16; i++) {
+            GtkWidget *item, *label;
+            gchar *text;
+
+            if (i < 10) {
+                /* Left Shift Popup: Menu item to shift left by n places (n < 10) */
+                text = g_strdup_printf(ngettext("_%d place", "_%d places", i), i);
+            }
+            else {
+                /* Left Shift Popup: Menu item to shift left by n places (n >= 10) */
+                text = g_strdup_printf(ngettext("%d place", "%d places", i), i);
+            }
+            label = gtk_label_new_with_mnemonic(text);
+
+            item = gtk_menu_item_new();
+            g_object_set_data(G_OBJECT(item), "shiftcount", GINT_TO_POINTER(i));
+            gtk_container_add(GTK_CONTAINER(item), label);
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+            g_signal_connect(item, "activate", G_CALLBACK(shift_cb), buttons);
+
+            gtk_widget_show(label);
+            gtk_widget_show(item);
+            g_free(text);
+        }
+    }
+
+    popup_button_menu(widget, GTK_MENU(buttons->priv->shift_left_menu));
+}
+
+void shift_right_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+shift_right_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    if (!buttons->priv->shift_right_menu) {
+        gint i;
+        GtkWidget *menu;
+
+        menu = buttons->priv->shift_right_menu = gtk_menu_new();
+        gtk_menu_set_reserve_toggle_size(GTK_MENU(menu), FALSE);
+
+        for (i = 1; i < 16; i++) {
+            GtkWidget *item, *label;
+            gchar *text;
+
+            if (i < 10) {
+                /* Right Shift Popup: Menu item to shift right by n places (n < 10) */
+                text = g_strdup_printf(ngettext("_%d place", "_%d places", i), i);
+            }
+            else {
+                /* Right Shift Popup: Menu item to shift right by n places (n >= 10) */
+                text = g_strdup_printf(ngettext("%d place", "%d places", i), i);
+            }
+            label = gtk_label_new_with_mnemonic(text);
+
+            item = gtk_menu_item_new();
+            g_object_set_data(G_OBJECT(item), "shiftcount", GINT_TO_POINTER(-i));
+            gtk_container_add(GTK_CONTAINER(item), label);
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+            g_signal_connect(item, "activate", G_CALLBACK(shift_cb), buttons);
+
+            gtk_widget_show(label);
+            gtk_widget_show(item);
+            g_free(text);
+        }
+    }
+
+    popup_button_menu(widget, GTK_MENU(buttons->priv->shift_right_menu));
+}
+
+static void
+insert_function_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget), "function"));
+}
+
+void function_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+function_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    if (!buttons->priv->function_menu) {
+        gint i;
+        GtkWidget *menu;
+        struct
+        {
+            gchar *name, *function;
+        } functions[] =
+        {
+            { /* Tooltip for the integer component button */
+              N_("Integer Component"), "int " },
+            { /* Tooltip for the fractional component button */
+              N_("Fractional Component"), "frac " },
+            { /* Tooltip for the round button */
+              N_("Round"), "round " },
+            { /* Tooltip for the floor button */
+              N_("Floor"), "floor " },
+            { /* Tooltip for the ceiling button */
+              N_("Ceiling"), "ceil " },
+            { /* Tooltip for the ceiling button */
+              N_("Sign"), "sgn " },
+            { NULL, NULL }
+        };
+
+        menu = buttons->priv->function_menu = gtk_menu_new();
+        gtk_menu_set_reserve_toggle_size(GTK_MENU(menu), FALSE);
+
+        for (i = 0; functions[i].name != NULL; i++) {
+            GtkWidget *item;
+
+            item = gtk_menu_item_new_with_label(_(functions[i].name));
+            g_object_set_data(G_OBJECT(item), "function", g_strdup(functions[i].function));
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+            g_signal_connect(item, "activate", G_CALLBACK(insert_function_cb), buttons);
+            gtk_widget_show(item);
+        }
+    }
+
+    popup_button_menu(widget, GTK_MENU(buttons->priv->function_menu));
+}
+
+static void
+insert_const_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget), "const"));
+}
+
+void const_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+const_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    if (!buttons->priv->const_menu) {
+        gint i;
+        GtkWidget *menu;
+        struct
+        {
+            gchar *name, *constant, *tooltip;
+        } constants[] =
+        {
+            { /* Tooltip for the c₀ component button */
+              N_("Velocity of Light"), "c₀", N_("299,792,458 m/s") },
+            { /* Tooltip for the μ₀ component button */
+              N_("Magnetic constant"), "μ₀", N_("1.2566370614×10⁻⁶ N/A²") },
+            { /* Tooltip for the ε₀ button */
+              N_("Electric constant"), "ε₀", N_("8.85418782×10⁻¹² s⁴A²/m³kg") },
+            { /* Tooltip for the G button */
+              N_("Newtonian constant of gravitation"), "G",  N_("6.67408×10⁻¹¹ m³/(s²kg)") },
+            { /* Tooltip for the h button */
+              N_("Planck constant"), "h", N_("6.62607004×10⁻³⁴ m²kg/s") },
+            { /* Tooltip for the e button */
+              N_("Elementary charge"), "e", N_("1.6021766208(98)×10⁻¹⁹ C") },
+            { /* Tooltip for the mₑ button */
+              N_("Electron mass"), "mₑ", N_("9.10938356×10⁻³¹ kg") },
+            { /* Tooltip for the mₚ button */
+              N_("Proton mass"), "mₚ", N_("1.672621898(21)×10⁻²⁷ kg") },
+            { /* Tooltip for the Nₐ button */
+              N_("Avogadro constant"), "Nₐ", N_("6.02214086×10²³ mol⁻¹") },
+            { NULL, NULL, NULL }
+        };
+
+        menu = buttons->priv->const_menu = gtk_menu_new();
+        gtk_menu_set_reserve_toggle_size(GTK_MENU(menu), FALSE);
+
+        for (i = 0; constants[i].name != NULL; i++) {
+            GtkWidget *item;
+
+            item = gtk_menu_item_new_with_label(_(constants[i].name));
+            gtk_widget_set_tooltip_text(item, _(constants[i].tooltip));
+            g_object_set_data(G_OBJECT(item), "const", g_strdup(constants[i].constant));
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+            g_signal_connect(item, "activate", G_CALLBACK(insert_const_cb), buttons);
+            gtk_widget_show(item);
+        }
+    }
+
+    popup_button_menu(widget, GTK_MENU(buttons->priv->const_menu));
+}
+
+void factorize_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+factorize_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_factorize(buttons->priv->equation);
+}
+
+void digit_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+digit_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert_digit(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "calc_digit")));
+}
+
+void numeric_point_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+numeric_point_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    math_equation_insert_numeric_point(buttons->priv->equation);
+}
+
+void finc_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+finc_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    gchar *name;
+
+    name = g_object_get_data(G_OBJECT(widget), "finc_dialog");
+    gtk_dialog_run(GTK_DIALOG(GET_WIDGET(buttons->priv->financial_ui, name)));
+    gtk_widget_hide(GTK_WIDGET(GET_WIDGET(buttons->priv->financial_ui, name)));
+}
+
+void insert_character_code_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+insert_character_code_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    gtk_window_present(GTK_WINDOW(buttons->priv->character_code_dialog));
+}
+
+void finc_activate_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+finc_activate_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    gint dialog, field;
+
+    dialog = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "finc_dialog"));
+    field = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "finc_field"));
+
+    if (finc_dialog_fields[dialog][field+1] == NULL) {
+        GtkWidget *dialog_widget;
+        dialog_widget = gtk_widget_get_toplevel(widget);
+        if (gtk_widget_is_toplevel(dialog_widget)) {
+            gtk_dialog_response(GTK_DIALOG(dialog_widget),
+                                GTK_RESPONSE_OK);
+            return;
+        }
+    }
+    else {
+        GtkWidget *next_widget;
+        next_widget = GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][field+1]);
+        gtk_widget_grab_focus(next_widget);
+    }
+}
+
+void finc_response_cb(GtkWidget *widget, gint response_id, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+finc_response_cb(GtkWidget *widget, gint response_id, MathButtons *buttons)
+{
+    int dialog;
+    int i;
+    MPNumber arg[4];
+    GtkWidget *entry;
+
+    if (response_id != GTK_RESPONSE_OK)
+        return;
+
+    dialog = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "finc_dialog"));
+
+    for (i = 0; i < 4; i++) {
+        arg[i] = mp_new();
+        if (finc_dialog_fields[dialog][i] == NULL) {
+            continue;
+        }
+        entry = GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][i]);
+        mp_set_from_string(gtk_entry_get_text(GTK_ENTRY(entry)), 10, &arg[i]);
+        gtk_entry_set_text(GTK_ENTRY(entry), "0");
+    }
+    gtk_widget_grab_focus(GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][0]));
+
+    do_finc_expression(buttons->priv->equation, dialog, &arg[0], &arg[1], &arg[2], &arg[3]);
+
+    for (i = 0; i < 4; i++) {
+        mp_clear(&arg[i]);
+    }
+}
+
+void character_code_dialog_response_cb(GtkWidget *dialog, gint response_id, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+character_code_dialog_response_cb(GtkWidget *dialog, gint response_id, MathButtons *buttons)
+{
+    const gchar *text;
+
+    text = gtk_entry_get_text(GTK_ENTRY(buttons->priv->character_code_entry));
+
+    if (response_id == GTK_RESPONSE_OK) {
+        MPNumber x = mp_new();
+        int i = 0;
+
+        mp_set_from_integer(0, &x);
+        while (TRUE) {
+            mp_add_integer(&x, text[i], &x);
+            if (text[i+1]) {
+                 mp_shift(&x, 8, &x);
+                 i++;
+            }
+            else
+                break;
+        }
+        math_equation_insert_number(buttons->priv->equation, &x);
+        mp_clear(&x);
+    }
+    gtk_widget_hide(dialog);
+}
+
+void character_code_dialog_activate_cb(GtkWidget *entry, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+character_code_dialog_activate_cb(GtkWidget *entry, MathButtons *buttons)
+{
+    character_code_dialog_response_cb(buttons->priv->character_code_dialog, GTK_RESPONSE_OK, buttons);
+}
+
+gboolean character_code_dialog_delete_cb(GtkWidget *dialog, GdkEvent *event, MathButtons *buttons);
+G_MODULE_EXPORT
+gboolean
+character_code_dialog_delete_cb(GtkWidget *dialog, GdkEvent *event, MathButtons *buttons)
+{
+    character_code_dialog_response_cb(dialog, GTK_RESPONSE_CANCEL, buttons);
+    return TRUE;
+}
+
+gboolean bit_toggle_cb(GtkWidget *event_box, GdkEventButton *event, MathButtons *buttons);
+G_MODULE_EXPORT
+gboolean
+bit_toggle_cb(GtkWidget *event_box, GdkEventButton *event, MathButtons *buttons)
+{
+    math_equation_toggle_bit(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box), "bit_index")));
+    return TRUE;
+}
+
+static void
+remove_trailing_spaces(MathButtons *buttons)
+{
+    GtkTextMark *insert_mark;
+    GtkTextIter start, end;
+    insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER(buttons->priv->equation));
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buttons->priv->equation), &end, insert_mark);
+    start = end;
+    while (gtk_text_iter_backward_char(&start)) {
+        if (!g_unichar_isspace(gtk_text_iter_get_char(&start)))
+            break;
+        gtk_text_buffer_delete(GTK_TEXT_BUFFER(buttons->priv->equation), &start, &end);
+    }
+}
+
+void set_superscript_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+set_superscript_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+        math_equation_set_number_mode(buttons->priv->equation, SUPERSCRIPT);
+        if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(buttons->priv->equation))) {
+            remove_trailing_spaces(buttons);
+        }
+    }
+    else if (math_equation_get_number_mode(buttons->priv->equation) == SUPERSCRIPT)
+        math_equation_set_number_mode(buttons->priv->equation, NORMAL);
+}
+
+void set_subscript_cb(GtkWidget *widget, MathButtons *buttons);
+G_MODULE_EXPORT
+void
+set_subscript_cb(GtkWidget *widget, MathButtons *buttons)
+{
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
+        math_equation_set_number_mode(buttons->priv->equation, SUBSCRIPT);
+        if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(buttons->priv->equation))) {
+            remove_trailing_spaces(buttons);
+        }
+    }
+    else if (math_equation_get_number_mode(buttons->priv->equation) == SUBSCRIPT)
+        math_equation_set_number_mode(buttons->priv->equation, NORMAL);
+}
+
+static void
+number_mode_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
+{
+    GList *i;
+    NumberMode mode;
+
+    mode = math_equation_get_number_mode(equation);
+
+    for (i = buttons->priv->superscript_toggles; i; i = i->next) {
+        GtkWidget *widget = i->data;
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), mode == SUPERSCRIPT);
+    }
+    for (i = buttons->priv->subscript_toggles; i; i = i->next) {
+        GtkWidget *widget = i->data;
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), mode == SUBSCRIPT);
+    }
+}
+
+static void
+math_buttons_set_property(GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+    MathButtons *self;
+
+    self = MATH_BUTTONS(object);
+
+    switch (prop_id) {
+    case PROP_EQUATION:
+        self->priv->equation = g_value_get_object(value);
+        math_buttons_set_mode(self, self->priv->mode);
+        g_signal_connect(self->priv->equation, "notify::display", G_CALLBACK(display_changed_cb), self);
+        g_signal_connect(self->priv->equation, "notify::number-mode", G_CALLBACK(number_mode_changed_cb), self);
+        g_signal_connect(self->priv->equation, "notify::angle-units", G_CALLBACK(display_changed_cb), self);
+        g_signal_connect(self->priv->equation, "notify::number-format", G_CALLBACK(display_changed_cb), self);
+        number_mode_changed_cb(self->priv->equation, NULL, self);
+        display_changed_cb(self->priv->equation, NULL, self);
+        break;
+    case PROP_MODE:
+        math_buttons_set_mode(self, g_value_get_int(value));
+        break;
+    case PROP_PROGRAMMING_BASE:
+        math_buttons_set_programming_base(self, g_value_get_int(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+math_buttons_get_property(GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+    MathButtons *self;
+
+    self = MATH_BUTTONS(object);
+
+    switch (prop_id) {
+    case PROP_EQUATION:
+        g_value_set_object(value, self->priv->equation);
+        break;
+    case PROP_MODE:
+        g_value_set_int(value, self->priv->mode);
+        break;
+    case PROP_PROGRAMMING_BASE:
+        g_value_set_int(value, math_buttons_get_programming_base(self));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+math_buttons_class_init(MathButtonsClass *klass)
+{
+    static GEnumValue button_mode_values[] =
+    {
+      {BASIC,       "basic",       "basic"},
+      {ADVANCED,    "advanced",    "advanced"},
+      {FINANCIAL,   "financial",   "financial"},
+      {PROGRAMMING, "programming", "programming"},
+      {0, NULL, NULL}
+    };
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    object_class->get_property = math_buttons_get_property;
+    object_class->set_property = math_buttons_set_property;
+
+    button_mode_type = g_enum_register_static("ButtonMode", button_mode_values);
+
+    g_object_class_install_property(object_class,
+                                    PROP_EQUATION,
+                                    g_param_spec_object("equation",
+                                                        "equation",
+                                                        "Equation being controlled",
+                                                        math_equation_get_type(),
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+    g_object_class_install_property(object_class,
+                                    PROP_MODE,
+                                    g_param_spec_enum("mode",
+                                                      "mode",
+                                                      "Button mode",
+                                                      button_mode_type,
+                                                      BASIC,
+                                                      G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_PROGRAMMING_BASE,
+                                    g_param_spec_int("programming-base",
+                                                     "programming-base",
+                                                     "Base to use in programming mode",
+                                                     2, 16, 10,
+                                                     G_PARAM_READWRITE));
+}
+
+static void
+math_buttons_init(MathButtons *buttons)
+{
+    buttons->priv = math_buttons_get_instance_private (buttons);
+    gtk_box_set_spacing(GTK_BOX(buttons), 6);
+    gtk_orientable_set_orientation (GTK_ORIENTABLE (buttons),
+                                    GTK_ORIENTATION_VERTICAL);
+    buttons->priv->programming_base = 10;
+    g_signal_connect(G_OBJECT(buttons), "show", G_CALLBACK(load_buttons), NULL);
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/5.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/5.html new file mode 100644 index 0000000..2d58909 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/5.html @@ -0,0 +1,4161 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+1435
+1436
+1437
+1438
+1439
+1440
+1441
+1442
+1443
+1444
+1445
+1446
+1447
+1448
+1449
+1450
+1451
+1452
+1453
+1454
+1455
+1456
+1457
+1458
+1459
+1460
+1461
+1462
+1463
+1464
+1465
+1466
+1467
+1468
+1469
+1470
+1471
+1472
+1473
+1474
+1475
+1476
+1477
+1478
+1479
+1480
+1481
+1482
+1483
+1484
+1485
+1486
+1487
+1488
+1489
+1490
+1491
+1492
+1493
+1494
+1495
+1496
+1497
+1498
+1499
+1500
+1501
+1502
+1503
+1504
+1505
+1506
+1507
+1508
+1509
+1510
+1511
+1512
+1513
+1514
+1515
+1516
+1517
+1518
+1519
+1520
+1521
+1522
+1523
+1524
+1525
+1526
+1527
+1528
+1529
+1530
+1531
+1532
+1533
+1534
+1535
+1536
+1537
+1538
+1539
+1540
+1541
+1542
+1543
+1544
+1545
+1546
+1547
+1548
+1549
+1550
+1551
+1552
+1553
+1554
+1555
+1556
+1557
+1558
+1559
+1560
+1561
+1562
+1563
+1564
+1565
+1566
+1567
+1568
+1569
+1570
+1571
+1572
+1573
+1574
+1575
+1576
+1577
+1578
+1579
+1580
+1581
+1582
+1583
+1584
+1585
+1586
+1587
+1588
+1589
+1590
+1591
+1592
+1593
+1594
+1595
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+1801
+1802
+1803
+1804
+1805
+1806
+1807
+1808
+1809
+1810
+1811
+1812
+1813
+1814
+1815
+1816
+1817
+1818
+1819
+1820
+1821
+1822
+1823
+1824
+1825
+1826
+1827
+1828
+1829
+1830
+1831
+1832
+1833
+1834
+1835
+1836
+1837
+1838
+1839
+1840
+1841
+1842
+1843
+1844
+1845
+1846
+1847
+1848
+1849
+1850
+1851
+1852
+1853
+1854
+1855
+1856
+1857
+1858
+1859
+1860
+1861
+1862
+1863
+1864
+1865
+1866
+1867
+1868
+1869
+1870
+1871
+1872
+1873
+1874
+1875
+1876
+1877
+1878
+1879
+1880
+1881
+1882
+1883
+1884
+1885
+1886
+1887
+1888
+1889
+1890
+1891
+1892
+1893
+1894
+1895
+1896
+1897
+1898
+1899
+1900
+1901
+1902
+1903
+1904
+1905
+1906
+1907
+1908
+1909
+1910
+1911
+1912
+1913
+1914
+1915
+1916
+1917
+1918
+1919
+1920
+1921
+1922
+1923
+1924
+1925
+1926
+1927
+1928
+1929
+1930
+1931
+1932
+1933
+1934
+1935
+1936
+1937
+1938
+1939
+1940
+1941
+1942
+1943
+1944
+1945
+1946
+1947
+1948
+1949
+1950
/*
+ * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2011 Robert Ancell
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <errno.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "math-equation.h"
+
+#include "mp.h"
+#include "mp-equation.h"
+#include "mp-serializer.h"
+#include "mp-enums.h"
+#include "unit-manager.h"
+#include "utility.h"
+
+enum {
+    PROP_0,
+    PROP_STATUS,
+    PROP_DISPLAY,
+    PROP_EQUATION,
+    PROP_NUMBER_MODE,
+    PROP_ACCURACY,
+    PROP_SHOW_THOUSANDS_SEPARATORS,
+    PROP_SHOW_TRAILING_ZEROES,
+    PROP_NUMBER_FORMAT,
+    PROP_BASE,
+    PROP_WORD_SIZE,
+    PROP_ANGLE_UNITS,
+    PROP_SOURCE_CURRENCY,
+    PROP_TARGET_CURRENCY,
+    PROP_SOURCE_UNITS,
+    PROP_TARGET_UNITS,
+    PROP_SERIALIZER
+};
+
+static GType number_mode_type, number_format_type, angle_unit_type;
+
+/* Expression mode state */
+typedef struct {
+    MPNumber ans;              /* Previously calculated answer */
+    gchar *expression;         /* Expression entered by user */
+    gint ans_start, ans_end;   /* Start and end characters for ans variable in expression */
+    gint cursor;               /* ??? */
+    NumberMode number_mode;    /* ??? */
+    gboolean can_super_minus;  /* TRUE if entering minus can generate a superscript minus */
+    gboolean entered_multiply; /* Last insert was a multiply character */
+    gchar *status;             /* Equation status */
+} MathEquationState;
+
+struct MathEquationPrivate
+{
+    GtkTextTag *ans_tag;
+
+    gint word_size;           /* Word size in bits */
+    MPAngleUnit angle_units;  /* Units for trigonometric functions */
+    char *source_currency;
+    char *target_currency;
+    char *source_units;
+    char *target_units;
+    NumberMode number_mode;   /* ??? */
+    gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
+
+    gunichar digits[16];      /* Localized digits */
+
+    GtkTextMark *ans_start, *ans_end;
+
+    MathEquationState state;  /* Equation state */
+    GList *undo_stack;        /* History of expression mode states */
+    GList *redo_stack;
+    gboolean in_undo_operation;
+
+    gboolean in_reformat;
+
+    gboolean in_delete;
+
+    gboolean in_solve;
+
+    MathVariables *variables;
+    MpSerializer *serializer;
+
+    GAsyncQueue *queue;
+};
+
+typedef struct {
+    MPNumber *number_result;
+    gchar *text_result;
+    gchar *error;
+} SolveData;
+
+G_DEFINE_TYPE_WITH_PRIVATE (MathEquation, math_equation, GTK_TYPE_TEXT_BUFFER);
+
+MathEquation *
+math_equation_new()
+{
+    return g_object_new(math_equation_get_type(), NULL);
+}
+
+MathVariables *
+math_equation_get_variables(MathEquation *equation)
+{
+    return equation->priv->variables;
+}
+
+static void
+get_ans_offsets(MathEquation *equation, gint *start, gint *end)
+{
+    GtkTextIter iter;
+
+    if (!equation->priv->ans_start) {
+        *start = *end = -1;
+        return;
+    }
+
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, equation->priv->ans_start);
+    *start = gtk_text_iter_get_offset(&iter);
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, equation->priv->ans_end);
+    *end = gtk_text_iter_get_offset(&iter);
+}
+
+static void
+reformat_ans(MathEquation *equation)
+{
+    if (!equation->priv->ans_start)
+        return;
+
+    gchar *orig_ans_text;
+    gchar *ans_text;
+    GtkTextIter ans_start, ans_end;
+
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_start, equation->priv->ans_start);
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_end, equation->priv->ans_end);
+    orig_ans_text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &ans_start, &ans_end, FALSE);
+    ans_text = mp_serializer_to_string(equation->priv->serializer, &equation->priv->state.ans);
+    if (strcmp(orig_ans_text, ans_text) != 0) {
+        gint start;
+
+        equation->priv->in_undo_operation = TRUE;
+        equation->priv->in_reformat = TRUE;
+
+        start = gtk_text_iter_get_offset(&ans_start);
+        gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation), &ans_start, &ans_end);
+        gtk_text_buffer_insert_with_tags(GTK_TEXT_BUFFER(equation), &ans_end, ans_text, -1, equation->priv->ans_tag, NULL);
+
+        /* There seems to be a bug in the marks as they alternate being the correct and incorrect ways.  Reset them */
+        gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &ans_start, start);
+        gtk_text_buffer_move_mark(GTK_TEXT_BUFFER(equation), equation->priv->ans_start, &ans_start);
+        gtk_text_buffer_move_mark(GTK_TEXT_BUFFER(equation), equation->priv->ans_end, &ans_end);
+
+        equation->priv->in_reformat = FALSE;
+        equation->priv->in_undo_operation = FALSE;
+    }
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_start, equation->priv->ans_start);
+    gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &ans_end, equation->priv->ans_end);
+    g_free(orig_ans_text);
+    g_free(ans_text);
+}
+
+static gint
+count_digits(MathEquation *equation, const gchar *text)
+{
+    const gchar *read_iter;
+    gint count = 0;
+
+    read_iter = text;
+    while (*read_iter != '\0') {
+        if (!g_unichar_isdigit(g_utf8_get_char(read_iter)))
+            return count;
+
+        read_iter = g_utf8_next_char(read_iter);
+
+        /* Allow a thousands separator between digits follow a digit */
+        if (g_utf8_get_char(read_iter) == mp_serializer_get_thousands_separator(equation->priv->serializer)) {
+            read_iter = g_utf8_next_char(read_iter);
+            if (!g_unichar_isdigit(g_utf8_get_char(read_iter)))
+                return count;
+        }
+
+        count++;
+    }
+
+    return count;
+}
+
+static void
+reformat_separators(MathEquation *equation)
+{
+    gchar *text, *read_iter;
+    gint ans_start, ans_end;
+    gint offset, digit_offset = 0;
+    gboolean in_number = FALSE, in_radix = FALSE, last_is_tsep = FALSE;
+
+    equation->priv->in_undo_operation = TRUE;
+    equation->priv->in_reformat = TRUE;
+
+    text = math_equation_get_display(equation);
+    get_ans_offsets(equation, &ans_start, &ans_end);
+    for (read_iter = text, offset = 0; *read_iter != '\0'; read_iter = g_utf8_next_char(read_iter), offset++) {
+        gunichar c;
+        gboolean expect_tsep;
+
+        /* See what digit this character is */
+        c = g_utf8_get_char(read_iter);
+
+        expect_tsep = math_equation_get_base(equation) == 10 &&
+                      mp_serializer_get_show_thousands_separators(equation->priv->serializer) &&
+                      in_number && !in_radix && !last_is_tsep &&
+                      digit_offset > 0 && digit_offset % mp_serializer_get_thousands_separator_count(equation->priv->serializer) == 0;
+        last_is_tsep = FALSE;
+
+        /* Don't mess with ans */
+        if (offset >= ans_start && offset <= ans_end) {
+            in_number = in_radix = FALSE;
+            continue;
+        }
+        if (g_unichar_isdigit(c)) {
+            if (!in_number)
+                digit_offset = count_digits(equation, read_iter);
+            in_number = TRUE;
+
+            /* Expected a thousands separator between these digits - insert it */
+            if (expect_tsep) {
+                GtkTextIter iter;
+                gchar buffer[7];
+                gint len;
+
+                gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &iter, offset);
+                len = g_unichar_to_utf8(mp_serializer_get_thousands_separator(equation->priv->serializer), buffer);
+                buffer[len] = '\0';
+                gtk_text_buffer_insert(GTK_TEXT_BUFFER(equation), &iter, buffer, -1);
+                offset++;
+                last_is_tsep = TRUE;
+            }
+
+            digit_offset--;
+        }
+        else if (c == mp_serializer_get_radix(equation->priv->serializer)) {
+            in_number = in_radix = TRUE;
+        }
+        else if (c == mp_serializer_get_thousands_separator(equation->priv->serializer)) {
+            /* Didn't expect thousands separator - delete it */
+            if (!expect_tsep && in_number) {
+                GtkTextIter start, end;
+                gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &start, offset);
+                gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &end, offset + 1);
+                gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation), &start, &end);
+                offset--;
+            }
+            else
+                last_is_tsep = TRUE;
+        }
+        else {
+            in_number = in_radix = FALSE;
+        }
+    }
+
+    g_free(text);
+
+    equation->priv->in_reformat = FALSE;
+    equation->priv->in_undo_operation = FALSE;
+}
+
+static void
+reformat_display(MathEquation *equation)
+{
+    /* Change ans */
+    reformat_ans(equation);
+
+    /* Add/remove thousands separators */
+    reformat_separators(equation);
+
+    g_signal_emit_by_name(equation, "display-changed");
+}
+
+static MathEquationState *
+get_current_state(MathEquation *equation)
+{
+    MathEquationState *state;
+    gint ans_start = -1, ans_end = -1;
+
+    state = g_malloc0(sizeof(MathEquationState));
+    state->ans = mp_new();
+
+    if (equation->priv->ans_start)
+    {
+        GtkTextIter iter;
+        gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, equation->priv->ans_start);
+        ans_start = gtk_text_iter_get_offset(&iter);
+        gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, equation->priv->ans_end);
+        ans_end = gtk_text_iter_get_offset(&iter);
+    }
+
+    mp_set_from_mp(&equation->priv->state.ans, &state->ans);
+    state->expression = math_equation_get_display(equation);
+    state->ans_start = ans_start;
+    state->ans_end = ans_end;
+    g_object_get(G_OBJECT(equation), "cursor-position", &state->cursor, NULL);
+    state->number_mode = equation->priv->number_mode;
+    state->can_super_minus = equation->priv->can_super_minus;
+    state->entered_multiply = equation->priv->state.entered_multiply;
+    state->status = g_strdup(equation->priv->state.status);
+
+    return state;
+}
+
+static void
+free_state(MathEquationState *state)
+{
+    g_free(state->expression);
+    g_free(state->status);
+    g_free(state);
+}
+
+static void
+math_equation_push_undo_stack(MathEquation *equation)
+{
+    GList *link;
+    MathEquationState *state;
+
+    if (equation->priv->in_undo_operation)
+        return;
+
+    math_equation_set_status(equation, "");
+
+    /* Can't redo anymore */
+    for (link = equation->priv->redo_stack; link; link = link->next) {
+        state = link->data;
+        free_state(state);
+    }
+    g_list_free(equation->priv->redo_stack);
+    equation->priv->redo_stack = NULL;
+
+    state = get_current_state(equation);
+    equation->priv->undo_stack = g_list_prepend(equation->priv->undo_stack, state);
+}
+
+static void
+clear_ans(MathEquation *equation, gboolean remove_tag)
+{
+    if (!equation->priv->ans_start)
+        return;
+
+    if (remove_tag) {
+        GtkTextIter start, end;
+
+        gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &start, equation->priv->ans_start);
+        gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &end, equation->priv->ans_end);
+        gtk_text_buffer_remove_tag(GTK_TEXT_BUFFER(equation), equation->priv->ans_tag, &start, &end);
+    }
+
+    gtk_text_buffer_delete_mark(GTK_TEXT_BUFFER(equation), equation->priv->ans_start);
+    gtk_text_buffer_delete_mark(GTK_TEXT_BUFFER(equation), equation->priv->ans_end);
+    equation->priv->ans_start = NULL;
+    equation->priv->ans_end = NULL;
+}
+
+static void
+apply_state(MathEquation *equation, MathEquationState *state)
+{
+    GtkTextIter cursor;
+
+    /* Disable undo detection */
+    equation->priv->in_undo_operation = TRUE;
+
+    mp_set_from_mp(&state->ans, &equation->priv->state.ans);
+
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), state->expression, -1);
+    gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &cursor, state->cursor);
+    gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(equation), &cursor);
+    clear_ans(equation, FALSE);
+    if (state->ans_start >= 0) {
+        GtkTextIter start, end;
+
+        gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &start, state->ans_start);
+        equation->priv->ans_start = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation), NULL, &start, FALSE);
+        gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &end, state->ans_end);
+        equation->priv->ans_end = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation), NULL, &end, TRUE);
+        gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(equation), equation->priv->ans_tag, &start, &end);
+    }
+
+    math_equation_set_number_mode(equation, state->number_mode);
+    equation->priv->can_super_minus = state->can_super_minus;
+    equation->priv->state.entered_multiply = state->entered_multiply;
+    math_equation_set_status(equation, state->status);
+
+    equation->priv->in_undo_operation = FALSE;
+}
+
+void
+math_equation_copy(MathEquation *equation)
+{
+    GtkTextIter start, end;
+    gchar *text;
+
+    g_return_if_fail(equation != NULL);
+
+    if (!gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation), &start, &end))
+        gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation), &start, &end);
+
+    text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &start, &end, FALSE);
+    gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE), g_str_to_ascii (text, "C"), -1);
+    g_free(text);
+}
+
+static void
+on_paste(GtkClipboard *clipboard, const gchar *text, gpointer data)
+{
+    MathEquation *equation = data;
+    if (text != NULL)
+        math_equation_insert(equation, text);
+}
+
+void
+math_equation_paste(MathEquation *equation)
+{
+    g_return_if_fail(equation != NULL);
+    gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE), on_paste, equation);
+}
+
+void
+math_equation_undo(MathEquation *equation)
+{
+    GList *link;
+    MathEquationState *state;
+
+    g_return_if_fail(equation != NULL);
+
+    if (!equation->priv->undo_stack) {
+        math_equation_set_status(equation,
+                                 /* Error shown when trying to undo with no undo history */
+                                 _("No undo history"));
+        return;
+    }
+
+    link = equation->priv->undo_stack;
+    equation->priv->undo_stack = g_list_remove_link(equation->priv->undo_stack, link);
+    state = link->data;
+    g_list_free(link);
+
+    equation->priv->redo_stack = g_list_prepend(equation->priv->redo_stack, get_current_state(equation));
+
+    apply_state(equation, state);
+    free_state(state);
+}
+
+void
+math_equation_redo(MathEquation *equation)
+{
+    GList *link;
+    MathEquationState *state;
+
+    g_return_if_fail(equation != NULL);
+
+    if (!equation->priv->redo_stack) {
+        math_equation_set_status(equation,
+                                 /* Error shown when trying to redo with no redo history */
+                                 _("No redo history"));
+        return;
+    }
+
+    link = equation->priv->redo_stack;
+    equation->priv->redo_stack = g_list_remove_link(equation->priv->redo_stack, link);
+    state = link->data;
+    g_list_free(link);
+
+    equation->priv->undo_stack = g_list_prepend(equation->priv->undo_stack, get_current_state(equation));
+
+    apply_state(equation, state);
+    free_state(state);
+}
+
+gunichar
+math_equation_get_digit_text(MathEquation *equation, guint digit)
+{
+    g_return_val_if_fail(equation != NULL, '?');
+    g_return_val_if_fail(digit < 16, '?');
+
+    return equation->priv->digits[digit];
+}
+
+void
+math_equation_set_accuracy(MathEquation *equation, gint accuracy)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (mp_serializer_get_trailing_digits(equation->priv->serializer) == accuracy)
+        return;
+    mp_serializer_set_trailing_digits(equation->priv->serializer, accuracy);
+    reformat_display(equation);
+    g_object_notify(G_OBJECT(equation), "accuracy");
+}
+
+gint
+math_equation_get_accuracy(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, 0);
+
+    return mp_serializer_get_trailing_digits(equation->priv->serializer);
+}
+
+void
+math_equation_set_show_thousands_separators(MathEquation *equation, gboolean visible)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (mp_serializer_get_show_thousands_separators(equation->priv->serializer) == visible)
+        return;
+
+    mp_serializer_set_show_thousands_separators(equation->priv->serializer, visible);
+    reformat_display(equation);
+    g_object_notify(G_OBJECT(equation), "show-thousands-separators");
+}
+
+gboolean
+math_equation_get_show_thousands_separators(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, FALSE);
+    return mp_serializer_get_show_thousands_separators(equation->priv->serializer);
+}
+
+void
+math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (mp_serializer_get_show_trailing_zeroes(equation->priv->serializer) == visible)
+        return;
+
+    mp_serializer_set_show_trailing_zeroes(equation->priv->serializer, visible);
+    reformat_display(equation);
+    g_object_notify(G_OBJECT(equation), "show-trailing-zeroes");
+}
+
+gboolean
+math_equation_get_show_trailing_zeroes(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, FALSE);
+    return mp_serializer_get_show_trailing_zeroes(equation->priv->serializer);
+}
+
+void
+math_equation_set_number_format(MathEquation *equation, MpDisplayFormat format)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (mp_serializer_get_number_format(equation->priv->serializer) == format)
+        return;
+
+    mp_serializer_set_number_format(equation->priv->serializer, format);
+    reformat_display(equation);
+    g_object_notify(G_OBJECT(equation), "number-format");
+}
+
+MpDisplayFormat
+math_equation_get_number_format(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, MP_DISPLAY_FORMAT_AUTOMATIC);
+    return mp_serializer_get_number_format(equation->priv->serializer);
+}
+
+void
+math_equation_set_base(MathEquation *equation, gint base)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (mp_serializer_get_base(equation->priv->serializer) == base)
+        return;
+
+    mp_serializer_set_base(equation->priv->serializer, base);
+    reformat_display(equation);
+    g_object_notify(G_OBJECT(equation), "base");
+}
+
+gint
+math_equation_get_base(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, 10);
+    return mp_serializer_get_base(equation->priv->serializer);
+}
+
+void
+math_equation_set_word_size(MathEquation *equation, gint word_size)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (equation->priv->word_size == word_size)
+        return;
+
+    equation->priv->word_size = word_size;
+    g_object_notify(G_OBJECT(equation), "word-size");
+}
+
+gint
+math_equation_get_word_size(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, 64);
+    return equation->priv->word_size;
+}
+
+void
+math_equation_set_angle_units(MathEquation *equation, MPAngleUnit angle_units)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (equation->priv->angle_units == angle_units)
+        return;
+
+    equation->priv->angle_units = angle_units;
+    g_object_notify(G_OBJECT(equation), "angle-units");
+}
+
+MPAngleUnit
+math_equation_get_angle_units(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, MP_DEGREES);
+    return equation->priv->angle_units;
+}
+
+void
+math_equation_set_source_currency(MathEquation *equation, const gchar *currency)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(currency != NULL);
+
+    if (strcmp(equation->priv->source_currency, currency) == 0)
+        return;
+    g_free(equation->priv->source_currency);
+    equation->priv->source_currency = g_strdup(currency);
+    g_settings_set_string(g_settings_var, "source-currency",
+            math_equation_get_source_currency(equation));
+}
+
+const gchar *
+math_equation_get_source_currency(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NULL);
+    return equation->priv->source_currency;
+}
+
+void
+math_equation_set_target_currency(MathEquation *equation, const gchar *currency)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(currency != NULL);
+
+    if (strcmp(equation->priv->target_currency, currency) == 0)
+        return;
+    g_free(equation->priv->target_currency);
+    equation->priv->target_currency = g_strdup(currency);
+    g_settings_set_string(g_settings_var, "target-currency",
+            math_equation_get_target_currency(equation));
+}
+
+const gchar *
+math_equation_get_target_currency(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NULL);
+    return equation->priv->target_currency;
+}
+
+void
+math_equation_set_source_units(MathEquation *equation, const gchar *units)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(units != NULL);
+
+    if (strcmp(equation->priv->source_units, units) == 0)
+        return;
+
+    g_free(equation->priv->source_units);
+    equation->priv->source_units = g_strdup(units);
+    g_settings_set_string(g_settings_var, "source-units",
+            math_equation_get_source_units(equation));
+}
+
+const gchar *
+math_equation_get_source_units(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NULL);
+    return equation->priv->source_units;
+}
+
+void
+math_equation_set_target_units(MathEquation *equation, const gchar *units)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(units != NULL);
+
+    if (strcmp(equation->priv->target_units, units) == 0)
+        return;
+
+    g_free(equation->priv->target_units);
+    equation->priv->target_units = g_strdup(units);
+    g_settings_set_string(g_settings_var, "target-units",
+            math_equation_get_target_units(equation));
+}
+
+const gchar *
+math_equation_get_target_units(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NULL);
+    return equation->priv->target_units;
+}
+
+void
+math_equation_set_status(MathEquation *equation, const gchar *status)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(status != NULL);
+
+    if (strcmp(equation->priv->state.status, status) == 0)
+        return;
+
+    g_free(equation->priv->state.status);
+    equation->priv->state.status = g_strdup(status);
+    g_object_notify(G_OBJECT(equation), "status");
+}
+
+const gchar *
+math_equation_get_status(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NULL);
+    return equation->priv->state.status;
+}
+
+gboolean
+math_equation_is_empty(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, FALSE);
+    return gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)) == 0;
+}
+
+gboolean
+math_equation_is_result(MathEquation *equation)
+{
+    char *text;
+    gboolean result;
+
+    g_return_val_if_fail(equation != NULL, FALSE);
+
+    text = math_equation_get_equation(equation);
+    result = strcmp(text, "ans") == 0;
+    g_free(text);
+
+    return result;
+}
+
+gchar *
+math_equation_get_display(MathEquation *equation)
+{
+    GtkTextIter start, end;
+
+    g_return_val_if_fail(equation != NULL, NULL);
+
+    gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation), &start, &end);
+    return gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &start, &end, FALSE);
+}
+
+gchar *
+math_equation_get_equation(MathEquation *equation)
+{
+    gchar *text;
+    GString *eq_text;
+    gint ans_start = -1, ans_end = -1, offset;
+    const gchar *read_iter;
+    gboolean last_is_digit = FALSE;
+
+    g_return_val_if_fail(equation != NULL, NULL);
+
+    text = math_equation_get_display(equation);
+    eq_text = g_string_sized_new(strlen(text));
+
+    if (equation->priv->ans_start)
+        get_ans_offsets(equation, &ans_start, &ans_end);
+
+    for (read_iter = text, offset = 0; *read_iter != '\0'; read_iter = g_utf8_next_char(read_iter), offset++) {
+        gunichar c;
+        gboolean is_digit, next_is_digit;
+
+        c = g_utf8_get_char(read_iter);
+        is_digit = g_unichar_isdigit(c);
+        next_is_digit = g_unichar_isdigit(g_utf8_get_char(g_utf8_next_char(read_iter)));
+
+        /* Replace ans text with variable */
+        if (offset == ans_start) {
+             g_string_append(eq_text, "ans");
+             read_iter = g_utf8_offset_to_pointer(read_iter, ans_end - ans_start - 1);
+             offset += ans_end - ans_start - 1;
+             is_digit = FALSE;
+             continue;
+        }
+
+        /* Ignore thousands separators */
+        if (c == mp_serializer_get_thousands_separator(equation->priv->serializer) && last_is_digit && next_is_digit)
+            ;
+        /* Substitute radix character */
+        else if (c == mp_serializer_get_radix(equation->priv->serializer) && (last_is_digit || next_is_digit))
+            g_string_append_unichar(eq_text, '.');
+        else
+            g_string_append_unichar(eq_text, c);
+
+        last_is_digit = is_digit;
+    }
+    g_free(text);
+
+    text = eq_text->str;
+    g_string_free(eq_text, FALSE);
+
+    return text;
+}
+
+gboolean
+math_equation_get_number(MathEquation *equation, MPNumber *z)
+{
+    gchar *text;
+    gboolean result;
+
+    g_return_val_if_fail(equation != NULL, FALSE);
+    g_return_val_if_fail(z != NULL, FALSE);
+
+    if (math_equation_is_result(equation)) {
+        mp_set_from_mp(math_equation_get_answer(equation), z);
+        return TRUE;
+    }
+    else {
+        text = math_equation_get_equation(equation);
+        result = !mp_serializer_from_string(equation->priv->serializer, text, z);
+        g_free(text);
+        return result;
+    }
+}
+
+MpSerializer *
+math_equation_get_serializer(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NULL);
+    return equation->priv->serializer;
+}
+
+void
+math_equation_set_number_mode(MathEquation *equation, NumberMode mode)
+{
+    g_return_if_fail(equation != NULL);
+
+    if (equation->priv->number_mode == mode)
+        return;
+
+    equation->priv->can_super_minus = mode == SUPERSCRIPT;
+
+    equation->priv->number_mode = mode;
+    g_object_notify(G_OBJECT(equation), "number-mode");
+}
+
+NumberMode
+math_equation_get_number_mode(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, NORMAL);
+    return equation->priv->number_mode;
+}
+
+gboolean
+math_equation_in_solve(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, FALSE);
+    return equation->priv->in_solve;
+}
+
+const MPNumber *
+math_equation_get_answer(MathEquation *equation)
+{
+    g_return_val_if_fail(equation != NULL, FALSE);
+    return &equation->priv->state.ans;
+}
+
+void
+math_equation_store(MathEquation *equation, const gchar *name)
+{
+    MPNumber t = mp_new();
+
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(name != NULL);
+
+    if (!math_equation_get_number(equation, &t))
+        math_equation_set_status(equation, _("No sane value to store"));
+    else
+        math_variables_set(equation->priv->variables, name, &t);
+    mp_clear(&t);
+}
+
+void
+math_equation_recall(MathEquation *equation, const gchar *name)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(name != NULL);
+    math_equation_insert(equation, name);
+}
+
+void
+math_equation_set(MathEquation *equation, const gchar *text)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(text != NULL);
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), text, -1);
+    clear_ans(equation, FALSE);
+}
+
+static void
+math_equation_set_with_history(MathEquation *equation, const gchar *text)
+{
+    MathEquationState *state;
+    MPNumber x = mp_new();
+
+    math_equation_get_number(equation, &x);
+    math_equation_set(equation, text);
+
+    /* Notify history */
+    state = get_current_state(equation);
+    g_signal_emit_by_name(equation, "history", state->expression, &x);
+
+    free_state(state);
+    mp_clear(&x);
+}
+
+void
+math_equation_set_number(MathEquation *equation, const MPNumber *x)
+{
+    char *text;
+    GtkTextIter start, end;
+    MathEquationState *state;
+
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(x != NULL);
+
+    /* Notify history */
+    state = get_current_state(equation);
+    g_signal_emit_by_name(equation, "history", state->expression, x);
+
+    /* Show the number in the user chosen format */
+    text = mp_serializer_to_string(equation->priv->serializer, x);
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), text, -1);
+    mp_set_from_mp(x, &equation->priv->state.ans);
+
+    /* Mark this text as the answer variable */
+    gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation), &start, &end);
+    clear_ans(equation, FALSE);
+    equation->priv->ans_start = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation), NULL, &start, FALSE);
+    equation->priv->ans_end = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation), NULL, &end, TRUE);
+    gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(equation), equation->priv->ans_tag, &start, &end);
+
+    g_object_notify(G_OBJECT(equation), "display");
+
+    g_free(text);
+    free_state(state);
+}
+
+void
+math_equation_insert(MathEquation *equation, const gchar *text)
+{
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(text != NULL);
+
+    /* Replace ** with ^ (not on all keyboards) */
+    if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(equation)) &&
+        strcmp(text, "×") == 0 && equation->priv->state.entered_multiply) {
+        GtkTextIter iter;
+
+        gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(equation)));
+        gtk_text_buffer_backspace(GTK_TEXT_BUFFER(equation), &iter, TRUE, TRUE);
+        gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(equation), "^", -1);
+        return;
+    }
+
+    /* Can't enter superscript minus after entering digits */
+    if (strstr("⁰¹²³⁴⁵⁶⁷⁸⁹", text) != NULL || strcmp("⁻", text) == 0)
+        equation->priv->can_super_minus = FALSE;
+
+    /* Disable super/subscript mode when finished entering */
+    if (strstr("⁻⁰¹²³⁴⁵⁶⁷⁸⁹₀₁₂₃₄₅₆₇₈₉", text) == NULL)
+        math_equation_set_number_mode(equation, NORMAL);
+
+    gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(equation), FALSE, FALSE);
+    gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(equation), text, -1);
+}
+
+void
+math_equation_insert_digit(MathEquation *equation, guint digit)
+{
+    static const char *subscript_digits[] = {"₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉", NULL};
+    static const char *superscript_digits[] = {"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", NULL};
+
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(digit < 16);
+
+    if (equation->priv->number_mode == NORMAL || digit >= 10) {
+        gchar buffer[7];
+        gint len;
+        len = g_unichar_to_utf8(math_equation_get_digit_text(equation, digit), buffer);
+        buffer[len] = '\0';
+        math_equation_insert(equation, buffer);
+    }
+    else if (equation->priv->number_mode == SUPERSCRIPT)
+        math_equation_insert(equation, superscript_digits[digit]);
+    else if (equation->priv->number_mode == SUBSCRIPT)
+        math_equation_insert(equation, subscript_digits[digit]);
+}
+
+void
+math_equation_insert_numeric_point(MathEquation *equation)
+{
+    gchar buffer[7];
+    gint len;
+
+    g_return_if_fail(equation != NULL);
+
+    len = g_unichar_to_utf8(mp_serializer_get_radix(equation->priv->serializer), buffer);
+    buffer[len] = '\0';
+    math_equation_insert(equation, buffer);
+}
+
+void
+math_equation_insert_number(MathEquation *equation, const MPNumber *x)
+{
+    char *text;
+
+    g_return_if_fail(equation != NULL);
+    g_return_if_fail(x != NULL);
+
+    text = mp_serializer_to_string(equation->priv->serializer, x);
+    math_equation_insert(equation, text);
+    g_free(text);
+}
+
+void
+math_equation_insert_exponent(MathEquation *equation)
+{
+    g_return_if_fail(equation != NULL);
+    math_equation_insert(equation, "×10");
+    math_equation_set_number_mode(equation, SUPERSCRIPT);
+}
+
+void
+math_equation_insert_subtract(MathEquation *equation)
+{
+    g_return_if_fail(equation != NULL);
+    if (equation->priv->number_mode == SUPERSCRIPT && equation->priv->can_super_minus) {
+        math_equation_insert(equation, "⁻");
+        equation->priv->can_super_minus = FALSE;
+    }
+    else {
+        math_equation_insert(equation, "−");
+        math_equation_set_number_mode(equation, NORMAL);
+    }
+}
+
+static int
+variable_is_defined(const char *name, void *data)
+{
+    MathEquation *equation = data;
+    char *c, *lower_name;
+
+    lower_name = strdup(name);
+    for (c = lower_name; *c; c++)
+        *c = tolower(*c);
+
+    if (strcmp(lower_name, "rand") == 0 ||
+        strcmp(lower_name, "ans") == 0) {
+        g_free(lower_name);
+        return 1;
+    }
+    g_free(lower_name);
+
+    return math_variables_get(equation->priv->variables, name) != NULL;
+}
+
+static int
+get_variable(const char *name, MPNumber *z, void *data)
+{
+    char *c, *lower_name;
+    int result = 1;
+    MathEquation *equation = data;
+    MPNumber *t;
+
+    lower_name = strdup(name);
+    for (c = lower_name; *c; c++)
+        *c = tolower(*c);
+
+    if (strcmp(lower_name, "rand") == 0)
+        mp_set_from_random(z);
+    else if (strcmp(lower_name, "ans") == 0)
+        mp_set_from_mp(&equation->priv->state.ans, z);
+    else {
+        t = math_variables_get(equation->priv->variables, name);
+        if (t)
+            mp_set_from_mp(t, z);
+        else
+            result = 0;
+    }
+    free(lower_name);
+
+    return result;
+}
+
+static void
+set_variable(const char *name, const MPNumber *x, void *data)
+{
+    MathEquation *equation = data;
+    /* FIXME: Don't allow writing to built-in variables, e.g. ans, rand, sin, ... */
+    math_variables_set(equation->priv->variables, name, x);
+}
+
+static int
+convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z, void *data)
+{
+    return unit_manager_convert_by_symbol(unit_manager_get_default(), x, x_units, z_units, z);
+}
+
+static int
+parse(MathEquation *equation, const char *text, MPNumber *z, char **error_token)
+{
+    MPEquationOptions options;
+
+    memset(&options, 0, sizeof(options));
+    options.base = mp_serializer_get_base(equation->priv->serializer);
+    options.wordlen = equation->priv->word_size;
+    options.angle_units = equation->priv->angle_units;
+    options.variable_is_defined = variable_is_defined;
+    options.get_variable = get_variable;
+    options.set_variable = set_variable;
+    options.convert = convert;
+    options.callback_data = equation;
+
+    return mp_equation_parse(text, &options, z, error_token);
+}
+
+/*
+ * Executed in separate thread. It is thus not a good idea to write to anything
+ * in MathEquation but the async queue from here.
+ */
+static gpointer
+math_equation_solve_real(gpointer data)
+{
+    MathEquation *equation = MATH_EQUATION(data);
+    SolveData *solvedata = g_slice_new0(SolveData);
+
+    gint n_brackets = 0, result;
+    gchar *c, *text, *error_token;
+    GString *equation_text;
+    MPNumber z = mp_new();
+
+    text = math_equation_get_equation(equation);
+    equation_text = g_string_new(text);
+    g_free(text);
+    /* Count the number of brackets and automatically add missing closing brackets */
+    for (c = equation_text->str; *c; c++) {
+        if (*c == '(')
+            n_brackets++;
+        else if (*c == ')')
+            n_brackets--;
+    }
+    while (n_brackets > 0) {
+        g_string_append_c(equation_text, ')');
+        n_brackets--;
+    }
+
+    result = parse(equation, equation_text->str, &z, &error_token);
+    g_string_free(equation_text, TRUE);
+
+    switch (result) {
+        case PARSER_ERR_NONE:
+            solvedata->number_result = g_slice_new(MPNumber);
+            *solvedata->number_result = mp_new();
+            mp_set_from_mp(&z, solvedata->number_result);
+            break;
+
+        case PARSER_ERR_OVERFLOW:
+            solvedata->error = g_strdup(/* Error displayed to user when they perform a bitwise operation on numbers greater than the current word */
+                               _("Overflow. Try a bigger word size"));
+            break;
+
+        case PARSER_ERR_UNKNOWN_VARIABLE:
+            solvedata->error = g_strdup_printf(/* Error displayed to user when they an unknown variable is entered */
+                                      _("Unknown variable '%s'"), error_token);
+            break;
+
+        case PARSER_ERR_UNKNOWN_FUNCTION:
+            solvedata->error = g_strdup_printf(/* Error displayed to user when an unknown function is entered */
+                                      _("Function '%s' is not defined"), error_token);
+            break;
+
+        case PARSER_ERR_UNKNOWN_CONVERSION:
+            solvedata->error = g_strdup(/* Error displayed to user when an conversion with unknown units is attempted */
+                               _("Unknown conversion"));
+            break;
+
+        case PARSER_ERR_MP:
+            if (mp_get_error())
+                solvedata->error = g_strdup(mp_get_error());
+            else if (error_token)
+                solvedata->error = g_strdup_printf(/* Uncategorized error. Show error token to user*/
+                                    _("Malformed expression at token '%s'"), error_token);
+            else
+                solvedata->error = g_strdup (/* Unknown error. */
+                                    _("Malformed expression"));
+            break;
+
+        default:
+            solvedata->error = g_strdup(/* Error displayed to user when they enter an invalid calculation */
+                               _("Malformed expression"));
+            break;
+    }
+    g_async_queue_push(equation->priv->queue, solvedata);
+    mp_clear(&z);
+
+    return NULL;
+}
+
+static gboolean
+math_equation_show_in_progress(gpointer data)
+{
+    MathEquation *equation = MATH_EQUATION(data);
+    if (equation->priv->in_solve)
+        math_equation_set_status(equation, _("Calculating"));
+    return false;
+}
+
+static gboolean
+math_equation_look_for_answer(gpointer data)
+{
+    MathEquation *equation = MATH_EQUATION(data);
+    SolveData *result = g_async_queue_try_pop(equation->priv->queue);
+
+    if (result == NULL)
+        return true;
+
+    equation->priv->in_solve = false;
+
+    if (!result->error)
+        math_equation_set_status(equation, "");
+
+    if (result->error != NULL) {
+        math_equation_set_status(equation, result->error);
+        g_free(result->error);
+    }
+    else if (result->number_result != NULL) {
+        math_equation_set_number(equation, result->number_result);
+        mp_clear(result->number_result);
+        g_slice_free(MPNumber, result->number_result);
+    }
+    else if (result->text_result != NULL) {
+        math_equation_set_with_history(equation, result->text_result);
+        g_free(result->text_result);
+    }
+    g_slice_free(SolveData, result);
+
+    return false;
+}
+
+void
+math_equation_solve(MathEquation *equation)
+{
+    g_return_if_fail(equation != NULL);
+
+    // FIXME: should replace calculation or give error message
+    if (equation->priv->in_solve)
+        return;
+
+    if (math_equation_is_empty(equation))
+        return;
+
+    /* If showing a result return to the equation that caused it */
+    // FIXME: Result may not be here due to solve (i.e. the user may have entered "ans")
+    if (math_equation_is_result(equation)) {
+        math_equation_undo(equation);
+        return;
+    }
+
+    equation->priv->in_solve = true;
+
+    math_equation_set_number_mode(equation, NORMAL);
+    g_thread_new("", math_equation_solve_real, equation);
+
+    g_timeout_add(50, math_equation_look_for_answer, equation);
+    g_timeout_add(100, math_equation_show_in_progress, equation);
+}
+
+static gpointer
+math_equation_factorize_real(gpointer data)
+{
+    GString *text;
+    GList *factors, *factor, *next_factor;
+    MPNumber x = mp_new();
+    MathEquation *equation = MATH_EQUATION(data);
+    SolveData *result = g_slice_new0(SolveData);
+    MpDisplayFormat format = mp_serializer_get_number_format(equation->priv->serializer);
+
+    mp_serializer_set_number_format(equation->priv->serializer, MP_DISPLAY_FORMAT_FIXED);
+    math_equation_get_number(equation, &x);
+    factors = mp_factorize(&x);
+
+    text = g_string_new("");
+
+    int e = 1;
+    for (factor = factors; factor != NULL; factor = factor->next)
+    {
+        gchar *temp;
+        MPNumber *n;
+
+        n = factor->data;
+        next_factor = factor->next;
+        if (next_factor != NULL && mp_compare(n, next_factor->data) == 0)
+        {
+            e++;
+            continue;
+        }
+        temp = mp_serializer_to_string(equation->priv->serializer, n);
+        g_string_append(text, temp);
+
+        if (e > 1)
+        {
+            g_string_append(text, "^");
+            g_string_append_printf(text, "%d", e);
+        }
+        if (factor->next)
+            g_string_append(text, " × ");
+
+        e = 1;
+
+        mp_clear(n);
+        g_slice_free(MPNumber, n);
+        g_free(temp);
+    }
+    g_list_free(factors);
+
+    result->text_result = g_strndup(text->str, text->len);
+    g_async_queue_push(equation->priv->queue, result);
+    g_string_free(text, TRUE);
+    mp_clear(&x);
+
+    mp_serializer_set_number_format(equation->priv->serializer, format);
+
+    return NULL;
+}
+
+void
+math_equation_factorize(MathEquation *equation)
+{
+    MPNumber x = mp_new();
+
+    g_return_if_fail(equation != NULL);
+
+    // FIXME: should replace calculation or give error message
+    if (equation->priv->in_solve)
+        return;
+
+    if (!math_equation_get_number(equation, &x) || !mp_is_integer(&x)) {
+        /* Error displayed when trying to factorize a non-integer value */
+        math_equation_set_status(equation, _("Need an integer to factorize"));
+        mp_clear(&x);
+        return;
+    }
+    mp_clear(&x);
+    equation->priv->in_solve = true;
+
+    g_thread_new("", math_equation_factorize_real, equation);
+
+    g_timeout_add(50, math_equation_look_for_answer, equation);
+    g_timeout_add(100, math_equation_show_in_progress, equation);
+}
+
+void
+math_equation_delete(MathEquation *equation)
+{
+    gint cursor;
+    GtkTextIter start, end;
+
+    g_return_if_fail(equation != NULL);
+
+    g_object_get(G_OBJECT(equation), "cursor-position", &cursor, NULL);
+    if (cursor >= gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)))
+        return;
+
+    gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &start, cursor);
+    gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &end, cursor+1);
+    gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation), &start, &end);
+}
+
+void
+math_equation_backspace(MathEquation *equation)
+{
+    g_return_if_fail(equation != NULL);
+
+    /* Can't delete empty display */
+    if (math_equation_is_empty(equation))
+        return;
+
+    if (gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(equation)))
+        gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(equation), FALSE, FALSE);
+    else {
+        GtkTextIter iter;
+        gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation), &iter, gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(equation)));
+        gtk_text_buffer_backspace(GTK_TEXT_BUFFER(equation), &iter, TRUE, TRUE);
+    }
+}
+
+void
+math_equation_clear(MathEquation *equation)
+{
+    g_return_if_fail(equation != NULL);
+
+    math_equation_set_number_mode(equation, NORMAL);
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), "", -1);
+    clear_ans(equation, FALSE);
+}
+
+void
+math_equation_shift(MathEquation *equation, gint count)
+{
+    MPNumber z = mp_new();
+
+    g_return_if_fail(equation != NULL);
+
+    if (!math_equation_get_number(equation, &z)) {
+        math_equation_set_status(equation,
+                                 /* This message is displayed in the status bar when a bit
+                                  shift operation is performed and the display does not contain a number */
+                                 _("No sane value to bitwise shift"));
+        return;
+    }
+
+    mp_shift(&z, count, &z);
+    math_equation_set_number(equation, &z);
+    mp_clear(&z);
+}
+
+void
+math_equation_toggle_bit(MathEquation *equation, guint bit)
+{
+    MPNumber x = mp_new();
+    guint64 bits;
+    gboolean result;
+
+    g_return_if_fail(equation != NULL);
+
+    result = math_equation_get_number(equation, &x);
+    if (result) {
+        MPNumber max = mp_new();
+        mp_set_from_unsigned_integer(G_MAXUINT64, &max);
+        if (mp_is_negative(&x) || mp_is_greater_than(&x, &max))
+            result = FALSE;
+        else
+            bits = mp_to_unsigned_integer(&x);
+        mp_clear(&max);
+    }
+
+    if (!result) {
+        math_equation_set_status(equation,
+                                 /* Message displayed when cannot toggle bit in display*/
+                                 _("Displayed value not an integer"));
+        mp_clear(&x);
+        return;
+    }
+
+    bits ^= (1LL << (63 - bit));
+
+    mp_set_from_unsigned_integer(bits, &x);
+
+    // FIXME: Only do this if in ans format, otherwise set text in same format as previous number
+    math_equation_set_number(equation, &x);
+    mp_clear(&x);
+}
+
+static void
+math_equation_set_property(GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+    MathEquation *self;
+
+    self = MATH_EQUATION(object);
+
+    switch (prop_id) {
+    case PROP_STATUS:
+        math_equation_set_status(self, g_value_get_string(value));
+        break;
+    case PROP_DISPLAY:
+        math_equation_set(self, g_value_get_string(value));
+        break;
+    case PROP_NUMBER_MODE:
+        math_equation_set_number_mode(self, g_value_get_int(value));
+        break;
+    case PROP_ACCURACY:
+        math_equation_set_accuracy(self, g_value_get_int(value));
+        break;
+    case PROP_SHOW_THOUSANDS_SEPARATORS:
+        math_equation_set_show_thousands_separators(self, g_value_get_boolean(value));
+        break;
+    case PROP_SHOW_TRAILING_ZEROES:
+        math_equation_set_show_trailing_zeroes(self, g_value_get_boolean(value));
+        break;
+    case PROP_NUMBER_FORMAT:
+        math_equation_set_number_format(self, g_value_get_int(value));
+        break;
+    case PROP_BASE:
+        math_equation_set_base(self, g_value_get_int(value));
+        break;
+    case PROP_WORD_SIZE:
+        math_equation_set_word_size(self, g_value_get_int(value));
+        break;
+    case PROP_ANGLE_UNITS:
+        math_equation_set_angle_units(self, g_value_get_int(value));
+        break;
+    case PROP_SOURCE_CURRENCY:
+        math_equation_set_source_currency(self, g_value_get_string(value));
+        break;
+    case PROP_TARGET_CURRENCY:
+        math_equation_set_target_currency(self, g_value_get_string(value));
+        break;
+    case PROP_SOURCE_UNITS:
+        math_equation_set_source_units(self, g_value_get_string(value));
+        break;
+    case PROP_TARGET_UNITS:
+        math_equation_set_target_units(self, g_value_get_string(value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+math_equation_get_property(GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+    MathEquation *self;
+    gchar *text;
+
+    self = MATH_EQUATION(object);
+
+    switch (prop_id) {
+    case PROP_STATUS:
+        g_value_set_string(value, self->priv->state.status);
+        break;
+    case PROP_DISPLAY:
+        text = math_equation_get_display(self);
+        g_value_set_string(value, text);
+        g_free(text);
+        break;
+    case PROP_EQUATION:
+        text = math_equation_get_equation(self);
+        g_value_set_string(value, text);
+        g_free(text);
+        break;
+    case PROP_NUMBER_MODE:
+        g_value_set_enum(value, self->priv->number_mode);
+        break;
+    case PROP_ACCURACY:
+        g_value_set_int(value, mp_serializer_get_trailing_digits(self->priv->serializer));
+        break;
+    case PROP_SHOW_THOUSANDS_SEPARATORS:
+        g_value_set_boolean(value, mp_serializer_get_show_thousands_separators(self->priv->serializer));
+        break;
+    case PROP_SHOW_TRAILING_ZEROES:
+        g_value_set_boolean(value, mp_serializer_get_show_trailing_zeroes(self->priv->serializer));
+        break;
+    case PROP_NUMBER_FORMAT:
+        g_value_set_enum(value, mp_serializer_get_number_format(self->priv->serializer));
+        break;
+    case PROP_BASE:
+        g_value_set_int(value, math_equation_get_base(self));
+        break;
+    case PROP_WORD_SIZE:
+        g_value_set_int(value, self->priv->word_size);
+        break;
+    case PROP_ANGLE_UNITS:
+        g_value_set_enum(value, self->priv->angle_units);
+        break;
+    case PROP_SOURCE_CURRENCY:
+        g_value_set_string(value, self->priv->source_currency);
+        break;
+    case PROP_TARGET_CURRENCY:
+        g_value_set_string(value, self->priv->target_currency);
+        break;
+    case PROP_SOURCE_UNITS:
+        g_value_set_string(value, self->priv->source_units);
+        break;
+    case PROP_TARGET_UNITS:
+        g_value_set_string(value, self->priv->target_units);
+        break;
+    case PROP_SERIALIZER:
+        g_value_set_object(value, self->priv->serializer);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+math_equation_constructed(GObject *object)
+{
+    GtkTextBuffer *parent_class;
+    parent_class = g_type_class_peek_parent(MATH_EQUATION_GET_CLASS(object));
+    if (G_OBJECT_CLASS(parent_class)->constructed)
+        G_OBJECT_CLASS(parent_class)->constructed(object);
+
+    MATH_EQUATION(object)->priv->ans_tag = gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(object), NULL, "weight", PANGO_WEIGHT_BOLD, NULL);
+}
+
+static void
+math_equation_class_init(MathEquationClass *klass)
+{
+    static GEnumValue number_mode_values[] =
+    {
+      {NORMAL,      "normal",      "normal"},
+      {SUPERSCRIPT, "superscript", "superscript"},
+      {SUBSCRIPT,   "subscript",   "subscript"},
+      {0, NULL, NULL}
+    };
+    static GEnumValue angle_unit_values[] =
+    {
+      {MP_RADIANS,  "radians",  "radians"},
+      {MP_DEGREES,  "degrees",  "degrees"},
+      {MP_GRADIANS, "gradians", "gradians"},
+      {0, NULL, NULL}
+    };
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    object_class->get_property = math_equation_get_property;
+    object_class->set_property = math_equation_set_property;
+    object_class->constructed = math_equation_constructed;
+
+    number_mode_type = g_enum_register_static("NumberMode", number_mode_values);
+    number_format_type = math_mp_display_format_get_type();
+    angle_unit_type = g_enum_register_static("AngleUnit", angle_unit_values);
+
+    g_object_class_install_property(object_class,
+                                    PROP_STATUS,
+                                    g_param_spec_string("status",
+                                                        "status",
+                                                        "Equation status",
+                                                        "",
+                                                        G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_DISPLAY,
+                                    g_param_spec_string("display",
+                                                        "display",
+                                                        "Displayed equation text",
+                                                        "",
+                                                        G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_EQUATION,
+                                    g_param_spec_string("equation",
+                                                        "equation",
+                                                        "Equation text",
+                                                        "",
+                                                        G_PARAM_READABLE));
+    g_object_class_install_property(object_class,
+                                    PROP_NUMBER_MODE,
+                                    g_param_spec_enum("number-mode",
+                                                      "number-mode",
+                                                      "Input number mode",
+                                                      number_mode_type,
+                                                      NORMAL,
+                                                      G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_ACCURACY,
+                                    g_param_spec_int("accuracy",
+                                                     "accuracy",
+                                                     "Display accuracy",
+                                                     0, 20, 9,
+                                                     G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_SHOW_THOUSANDS_SEPARATORS,
+                                    g_param_spec_boolean("show-thousands-separators",
+                                                         "show-thousands-separators",
+                                                         "Show thousands separators",
+                                                         TRUE,
+                                                         G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_SHOW_TRAILING_ZEROES,
+                                    g_param_spec_boolean("show-trailing-zeroes",
+                                                         "show-trailing-zeroes",
+                                                         "Show trailing zeroes",
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_NUMBER_FORMAT,
+                                    g_param_spec_enum("number-format",
+                                                      "number-format",
+                                                      "Display format",
+                                                      number_format_type,
+                                                      MP_DISPLAY_FORMAT_FIXED,
+                                                      G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_BASE,
+                                    g_param_spec_int("base",
+                                                     "base",
+                                                     "Default number base (derived from number-format)",
+                                                     2, 16, 10,
+                                                     G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_WORD_SIZE,
+                                    g_param_spec_int("word-size",
+                                                     "word-size",
+                                                     "Word size in bits",
+                                                     8, 64, 64,
+                                                     G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_ANGLE_UNITS,
+                                    g_param_spec_enum("angle-units",
+                                                      "angle-units",
+                                                      "Angle units",
+                                                      angle_unit_type,
+                                                      MP_DEGREES,
+                                                      G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_SOURCE_CURRENCY,
+                                    g_param_spec_string("source-currency",
+                                                        "source-currency",
+                                                        "Source Currency",
+                                                        "",
+                                                        G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_TARGET_CURRENCY,
+                                    g_param_spec_string("target-currency",
+                                                        "target-currency",
+                                                        "target Currency",
+                                                        "",
+                                                        G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_SOURCE_UNITS,
+                                    g_param_spec_string("source-units",
+                                                        "source-units",
+                                                        "Source Units",
+                                                        "",
+                                                        G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_TARGET_UNITS,
+                                    g_param_spec_string("target-units",
+                                                        "target-units",
+                                                        "target Units",
+                                                        "",
+                                                        G_PARAM_READWRITE));
+    g_object_class_install_property(object_class,
+                                    PROP_SERIALIZER,
+                                    g_param_spec_object("serializer",
+                                                        "serializer",
+                                                        "Serializer",
+                                                        MP_TYPE_SERIALIZER,
+                                                        G_PARAM_READABLE));
+
+    GType param_types[2] = {G_TYPE_STRING, G_TYPE_POINTER};
+    g_signal_newv("history",
+                  G_TYPE_FROM_CLASS(klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL,
+                  NULL,
+                  NULL,
+                  G_TYPE_NONE,
+                  2,
+                  param_types);
+
+    g_signal_new ("display-changed",
+                  G_TYPE_FROM_CLASS(klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL,
+                  NULL,
+                  NULL,
+                  G_TYPE_NONE,
+                  0,
+                  NULL);
+}
+
+static void
+pre_insert_text_cb(MathEquation  *equation,
+                   GtkTextIter   *location,
+                   gchar         *text,
+                   gint           len,
+                   gpointer       user_data)
+{
+    gunichar c;
+    gint cursor;
+
+    if (equation->priv->in_reformat)
+        return;
+
+    /* If following a delete then have already pushed undo stack (GtkTextBuffer
+       doesn't indicate replace operations so we have to infer them) */
+    if (!equation->priv->in_delete)
+        math_equation_push_undo_stack(equation);
+
+    /* Clear result on next digit entered if cursor at end of line */
+    c = g_utf8_get_char(text);
+    g_object_get(G_OBJECT(equation), "cursor-position", &cursor, NULL);
+    if ((g_unichar_isdigit(c) || c == mp_serializer_get_radix(equation->priv->serializer)) &&
+         math_equation_is_result(equation) &&
+         cursor >= gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation))) {
+        gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), "", -1);
+        clear_ans(equation, FALSE);
+        gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(equation), location);
+    }
+
+    if (equation->priv->ans_start) {
+        gint ans_start, ans_end;
+        gint offset;
+
+        offset = gtk_text_iter_get_offset(location);
+        get_ans_offsets(equation, &ans_start, &ans_end);
+
+        /* Inserted inside or right before ans */
+        if (offset >= ans_start && offset < ans_end)
+            clear_ans(equation, TRUE);
+    }
+}
+
+static gboolean
+on_delete(MathEquation *equation)
+{
+    equation->priv->in_delete = FALSE;
+    return FALSE;
+}
+
+static void
+pre_delete_range_cb(MathEquation  *equation,
+                    GtkTextIter   *start,
+                    GtkTextIter   *end,
+                    gpointer       user_data)
+{
+    if (equation->priv->in_reformat)
+        return;
+
+    math_equation_push_undo_stack(equation);
+
+    equation->priv->in_delete = TRUE;
+    g_idle_add((GSourceFunc)on_delete, equation);
+
+    if (equation->priv->ans_start) {
+        gint ans_start, ans_end;
+        gint start_offset, end_offset;
+
+        start_offset = gtk_text_iter_get_offset(start);
+        end_offset = gtk_text_iter_get_offset(end);
+        get_ans_offsets(equation, &ans_start, &ans_end);
+
+        /* Deleted part of ans */
+        if (start_offset < ans_end && end_offset > ans_start)
+            clear_ans(equation, TRUE);
+    }
+}
+
+static void
+insert_text_cb(MathEquation  *equation,
+               GtkTextIter   *location,
+               gchar         *text,
+               gint           len,
+               gpointer       user_data)
+{
+    if (equation->priv->in_reformat)
+        return;
+
+    equation->priv->state.entered_multiply = strcmp(text, "×") == 0;
+
+    /* Update thousands separators */
+    reformat_separators(equation);
+
+    g_object_notify(G_OBJECT(equation), "display");
+}
+
+static void
+delete_range_cb(MathEquation  *equation,
+                GtkTextIter   *start,
+                GtkTextIter   *end,
+                gpointer       user_data)
+{
+    if (equation->priv->in_reformat)
+        return;
+
+    equation->priv->state.entered_multiply = FALSE;
+
+    /* Update thousands separators */
+    reformat_separators(equation);
+
+    // FIXME: A replace will emit this both for delete-range and insert-text, can it be avoided?
+    g_object_notify(G_OBJECT(equation), "display");
+}
+
+static void
+math_equation_init(MathEquation *equation)
+{
+    /* Digits localized for the given language */
+    const char *digit_values = _("0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F");
+    const char *default_digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
+    gchar **digits;
+    /* Default to using untranslated digits, this is because it doesn't make sense in most languages and we need to make this optional.
+     * See https://bugzilla.gnome.org/show_bug.cgi?id=632661 */
+    gboolean use_default_digits = TRUE;
+    int i;
+
+    equation->priv = math_equation_get_instance_private (equation);
+
+    g_signal_connect(equation, "insert-text", G_CALLBACK(pre_insert_text_cb), equation);
+    g_signal_connect(equation, "delete-range", G_CALLBACK(pre_delete_range_cb), equation);
+    g_signal_connect_after(equation, "insert-text", G_CALLBACK(insert_text_cb), equation);
+    g_signal_connect_after(equation, "delete-range", G_CALLBACK(delete_range_cb), equation);
+
+    digits = g_strsplit(digit_values, ",", -1);
+    for (i = 0; i < 16; i++) {
+        if (use_default_digits || digits[i] == NULL) {
+            use_default_digits = TRUE;
+            equation->priv->digits[i] = g_utf8_get_char(default_digits[i]);
+        }
+        else
+            equation->priv->digits[i] = g_utf8_get_char(digits[i]);
+    }
+    g_strfreev(digits);
+
+    equation->priv->variables = math_variables_new();
+
+    equation->priv->state.ans = mp_new();
+    equation->priv->state.status = g_strdup("");
+    equation->priv->word_size = 32;
+    equation->priv->angle_units = MP_DEGREES;
+    // FIXME: Pick based on locale
+    equation->priv->source_currency = g_strdup("");
+    equation->priv->target_currency = g_strdup("");
+    equation->priv->source_units = g_strdup("");
+    equation->priv->target_units = g_strdup("");
+    equation->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9);
+    equation->priv->queue = g_async_queue_new();
+
+    mp_set_from_integer(0, &equation->priv->state.ans);
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/6.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/6.html new file mode 100644 index 0000000..ed984d4 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/6.html @@ -0,0 +1,1001 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
/*
+ * Copyright (C) 2008-2011 Robert Ancell
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "math-preferences.h"
+#include "utility.h"
+
+enum {
+    PROP_0,
+    PROP_EQUATION
+};
+
+struct MathPreferencesDialogPrivate
+{
+    MathEquation *equation;
+    GtkBuilder *ui;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (MathPreferencesDialog, math_preferences, GTK_TYPE_DIALOG);
+
+#define UI_DIALOGS_RESOURCE_PATH "/org/mate/calculator/ui/preferences.ui"
+#define GET_WIDGET(ui, name) \
+          GTK_WIDGET(gtk_builder_get_object(ui, name))
+
+MathPreferencesDialog *
+math_preferences_dialog_new(MathEquation *equation)
+{
+    return g_object_new(math_preferences_get_type(), "equation", equation, NULL);
+}
+
+static void
+preferences_response_cb(GtkWidget *widget, gint id)
+{
+    gtk_widget_hide(widget);
+}
+
+static gboolean
+preferences_dialog_delete_cb(GtkWidget *widget, GdkEvent *event)
+{
+    preferences_response_cb(widget, 0);
+    return TRUE;
+}
+
+void number_format_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog);
+G_MODULE_EXPORT
+void
+number_format_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog)
+{
+    MpDisplayFormat value;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
+    gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
+    gtk_tree_model_get(model, &iter, 1, &value, -1);
+    math_equation_set_number_format(dialog->priv->equation, value);
+}
+
+void angle_unit_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog);
+G_MODULE_EXPORT
+void
+angle_unit_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog)
+{
+    MPAngleUnit value;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
+    gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
+    gtk_tree_model_get(model, &iter, 1, &value, -1);
+    math_equation_set_angle_units(dialog->priv->equation, value);
+}
+
+void word_size_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog);
+G_MODULE_EXPORT
+void
+word_size_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog)
+{
+    gint value;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
+    gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
+    gtk_tree_model_get(model, &iter, 1, &value, -1);
+    math_equation_set_word_size(dialog->priv->equation, value);
+}
+
+void decimal_places_spin_change_value_cb(GtkWidget *spin, MathPreferencesDialog *dialog);
+G_MODULE_EXPORT
+void
+decimal_places_spin_change_value_cb(GtkWidget *spin, MathPreferencesDialog *dialog)
+{
+    gint value = 0;
+
+    value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin));
+    math_equation_set_accuracy(dialog->priv->equation, value);
+}
+
+void thousands_separator_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog);
+G_MODULE_EXPORT
+void
+thousands_separator_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog)
+{
+    gboolean value;
+
+    value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
+    math_equation_set_show_thousands_separators(dialog->priv->equation, value);
+}
+
+void trailing_zeroes_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog);
+G_MODULE_EXPORT
+void
+trailing_zeroes_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog)
+{
+    gboolean value;
+
+    value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
+    math_equation_set_show_trailing_zeroes(dialog->priv->equation, value);
+}
+
+static void
+set_combo_box_from_int(GtkWidget *combo, int value)
+{
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    gboolean valid;
+
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
+    valid = gtk_tree_model_get_iter_first(model, &iter);
+
+    while (valid) {
+        gint v;
+
+        gtk_tree_model_get(model, &iter, 1, &v, -1);
+        if (v == value)
+            break;
+        valid = gtk_tree_model_iter_next(model, &iter);
+    }
+    if (!valid)
+        valid = gtk_tree_model_get_iter_first(model, &iter);<--- Variable 'valid' is assigned a value that is never used.
+
+    gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter);
+}
+
+static void
+accuracy_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
+{
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(dialog->priv->ui, "decimal_places_spin")),
+                              math_equation_get_accuracy(equation));
+    g_settings_set_int(g_settings_var, "accuracy", math_equation_get_accuracy(equation));
+}
+
+static void
+show_thousands_separators_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
+{
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(dialog->priv->ui, "thousands_separator_check")),
+                                 math_equation_get_show_thousands_separators(equation));
+    g_settings_set_boolean(g_settings_var, "show-thousands", math_equation_get_show_thousands_separators(equation));
+}
+
+static void
+show_trailing_zeroes_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
+{
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(dialog->priv->ui, "trailing_zeroes_check")),
+                                 math_equation_get_show_trailing_zeroes(equation));
+    g_settings_set_boolean(g_settings_var, "show-zeroes", math_equation_get_show_trailing_zeroes(equation));
+}
+
+static void
+number_format_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
+{
+    set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "number_format_combobox"), math_equation_get_number_format(equation));
+    g_settings_set_enum(g_settings_var, "number-format", math_equation_get_number_format(equation));
+}
+
+static void
+word_size_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
+{
+    set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "word_size_combobox"), math_equation_get_word_size(equation));
+    g_settings_set_int(g_settings_var, "word-size", math_equation_get_word_size(equation));
+}
+
+static void
+angle_unit_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
+{
+    set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "angle_unit_combobox"), math_equation_get_angle_units(equation));
+    g_settings_set_enum(g_settings_var, "angle-units", math_equation_get_angle_units(equation));
+}
+
+static void
+create_gui(MathPreferencesDialog *dialog)
+{
+    GtkWidget *widget;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    GtkCellRenderer *renderer;
+    gchar *string, **tokens;
+    GError *error = NULL;
+    static gchar *objects[] = { "preferences_table", "angle_unit_model", "number_format_model",
+                                "word_size_model", "decimal_places_adjustment", "number_base_model", NULL };
+
+    // FIXME: Handle errors
+    dialog->priv->ui = gtk_builder_new();
+    gtk_builder_add_objects_from_resource(dialog->priv->ui, UI_DIALOGS_RESOURCE_PATH, objects, &error);
+    if (error)
+        g_warning("Error loading preferences UI: %s", error->message);
+    g_clear_error(&error);
+
+    gtk_window_set_title(GTK_WINDOW(dialog),
+                         /* Title of preferences dialog */
+                         _("Preferences"));
+    gtk_container_set_border_width(GTK_CONTAINER(dialog), 8);
+    gtk_dialog_add_button(GTK_DIALOG(dialog),
+                          /* Icon name on close button in preferences dialog */
+                          "gtk-close", GTK_RESPONSE_CLOSE);
+
+    gtk_window_set_icon_name (GTK_WINDOW(dialog), "accessories-calculator");
+
+    g_signal_connect(dialog, "response", G_CALLBACK(preferences_response_cb), NULL);
+    g_signal_connect(dialog, "delete-event", G_CALLBACK(preferences_dialog_delete_cb), NULL);
+    gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GET_WIDGET(dialog->priv->ui, "preferences_table"), TRUE, TRUE, 0);
+
+    widget = GET_WIDGET(dialog->priv->ui, "angle_unit_combobox");
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Preferences dialog: Angle unit combo box: Use degrees for trigonometric calculations */
+                       _("Degrees"), 1, MP_DEGREES, -1);
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Preferences dialog: Angle unit combo box: Use radians for trigonometric calculations */
+                       _("Radians"), 1, MP_RADIANS, -1);
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Preferences dialog: Angle unit combo box: Use gradians for trigonometric calculations */
+                       _("Gradians"), 1, MP_GRADIANS, -1);
+    renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0);
+
+    widget = GET_WIDGET(dialog->priv->ui, "number_format_combobox");
+    model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Number display mode combo: Automatic, e.g. 1234 (or scientific for large number 1.234×10^99) */
+                       _("Automatic"), 1, MP_DISPLAY_FORMAT_AUTOMATIC, -1);
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Number display mode combo: Fixed, e.g. 1234 */
+                       _("Fixed"), 1, MP_DISPLAY_FORMAT_FIXED, -1);
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Number display mode combo: Scientific, e.g. 1.234×10^3 */
+                       _("Scientific"), 1, MP_DISPLAY_FORMAT_SCIENTIFIC, -1);
+    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+    gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0,
+                       /* Number display mode combo: Engineering, e.g. 1.234k */
+                       _("Engineering"), 1, MP_DISPLAY_FORMAT_ENGINEERING, -1);
+    renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0);
+
+    widget = GET_WIDGET(dialog->priv->ui, "word_size_combobox");
+    renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+    gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0);
+
+    /* Label used in preferences dialog.  The %d is replaced by a spinbutton */
+    string = _("Show %d decimal _places");
+    tokens = g_strsplit(string, "%d", 2);
+    widget = GET_WIDGET(dialog->priv->ui, "decimal_places_label1");
+    if (tokens[0])
+        string = g_strstrip(tokens[0]);
+    else
+        string = "";
+    if (string[0] != '\0')
+        gtk_label_set_text_with_mnemonic(GTK_LABEL(widget), string);
+    else
+        gtk_widget_hide(widget);
+
+    widget = GET_WIDGET(dialog->priv->ui, "decimal_places_label2");
+    if (tokens[0] && tokens[1])
+        string = g_strstrip(tokens[1]);
+    else
+        string = "";
+    if (string[0] != '\0')
+        gtk_label_set_text_with_mnemonic(GTK_LABEL(widget), string);
+    else
+        gtk_widget_hide(widget);
+
+    g_strfreev(tokens);
+
+    gtk_builder_connect_signals(dialog->priv->ui, dialog);
+
+    g_signal_connect(dialog->priv->equation, "notify::accuracy", G_CALLBACK(accuracy_cb), dialog);
+    g_signal_connect(dialog->priv->equation, "notify::show-thousands-separators", G_CALLBACK(show_thousands_separators_cb), dialog);
+    g_signal_connect(dialog->priv->equation, "notify::show-trailing_zeroes", G_CALLBACK(show_trailing_zeroes_cb), dialog);
+    g_signal_connect(dialog->priv->equation, "notify::number-format", G_CALLBACK(number_format_cb), dialog);
+    g_signal_connect(dialog->priv->equation, "notify::word-size", G_CALLBACK(word_size_cb), dialog);
+    g_signal_connect(dialog->priv->equation, "notify::angle-units", G_CALLBACK(angle_unit_cb), dialog);
+
+    accuracy_cb(dialog->priv->equation, NULL, dialog);
+    show_thousands_separators_cb(dialog->priv->equation, NULL, dialog);
+    show_trailing_zeroes_cb(dialog->priv->equation, NULL, dialog);
+    number_format_cb(dialog->priv->equation, NULL, dialog);
+    word_size_cb(dialog->priv->equation, NULL, dialog);
+    angle_unit_cb(dialog->priv->equation, NULL, dialog);
+}
+
+static void
+math_preferences_set_property(GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+    MathPreferencesDialog *self;
+
+    self = MATH_PREFERENCES(object);
+
+    switch (prop_id) {
+    case PROP_EQUATION:
+        self->priv->equation = g_value_get_object(value);
+        create_gui(self);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+math_preferences_get_property(GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+    MathPreferencesDialog *self;
+
+    self = MATH_PREFERENCES(object);
+
+    switch (prop_id) {
+    case PROP_EQUATION:
+        g_value_set_object(value, self->priv->equation);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+math_preferences_class_init(MathPreferencesDialogClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+    object_class->get_property = math_preferences_get_property;
+    object_class->set_property = math_preferences_set_property;
+
+    g_object_class_install_property(object_class,
+                                    PROP_EQUATION,
+                                    g_param_spec_object("equation",
+                                                        "equation",
+                                                        "Equation being configured",
+                                                        math_equation_get_type(),
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+math_preferences_init(MathPreferencesDialog *dialog)
+{
+    dialog->priv = math_preferences_get_instance_private (dialog);
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/7.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/7.html new file mode 100644 index 0000000..0663ac3 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/7.html @@ -0,0 +1,933 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
/*
+ * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (C) 2008-2011 Robert Ancell
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <langinfo.h>
+
+#include "mp.h"
+
+void
+mp_set_from_mp(const MPNumber *x, MPNumber *z)
+{
+    mpc_set(z->num, x->num, MPC_RNDNN);
+}
+
+void
+mp_set_from_double(double dx, MPNumber *z)
+{
+    mpc_set_d(z->num, dx, MPC_RNDNN);
+}
+
+void
+mp_set_from_integer(long x, MPNumber *z)
+{
+    mpc_set_si(z->num, x, MPC_RNDNN);
+}
+
+void
+mp_set_from_unsigned_integer(ulong x, MPNumber *z)
+{
+    mpc_set_ui(z->num, x, MPC_RNDNN);
+}
+
+void
+mp_set_from_fraction(long numerator, long denominator, MPNumber *z)
+{
+    if (denominator < 0) {
+        numerator = -numerator;
+        denominator = -denominator;
+    }
+
+    mp_set_from_integer(numerator, z);
+    if (denominator != 1)
+        mp_divide_integer(z, denominator, z);
+}
+
+void
+mp_set_from_polar(const MPNumber *r, MPAngleUnit unit, const MPNumber *theta, MPNumber *z)
+{
+    MPNumber x = mp_new();
+    MPNumber y = mp_new();
+
+    mp_cos(theta, unit, &x);
+    mp_multiply(&x, r, &x);
+    mp_sin(theta, unit, &y);
+    mp_multiply(&y, r, &y);
+    mp_set_from_complex(&x, &y, z);
+
+    mp_clear(&x);
+    mp_clear(&y);
+}
+
+void
+mp_set_from_complex(const MPNumber *x, const MPNumber *y, MPNumber *z)
+{
+    mpc_set_fr_fr(z->num, mpc_realref(x->num), mpc_realref(y->num), MPC_RNDNN);
+}
+
+void
+mp_set_from_random(MPNumber *z)
+{
+    mp_set_from_double(drand48(), z);
+}
+
+long
+mp_to_integer(const MPNumber *x)
+{
+    return mpfr_get_si(mpc_realref(x->num), MPFR_RNDN);
+}
+
+ulong
+mp_to_unsigned_integer(const MPNumber *x)
+{
+    return mpfr_get_ui(mpc_realref(x->num), MPFR_RNDN);
+}
+
+float
+mp_to_float(const MPNumber *x)
+{
+    return mpfr_get_flt(mpc_realref(x->num), MPFR_RNDN);
+}
+
+double
+mp_to_double(const MPNumber *x)
+{
+    return mpfr_get_d(mpc_realref(x->num), MPFR_RNDN);
+}
+
+static int
+char_val(char **c, int base)
+{
+    int i, j, value;
+    size_t offset;
+    const char *digits[][10] = {{"٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"},
+                                {"〇", "〡", "〢", "〣", "〤", "〥", "〦", "〧", "〨", "〩"},
+                                {"۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"},
+                                {"߀", "߁", "߂", "߃", "߄", "߅", "߆", "߇", "߈", "߉"},
+                                {"०", "१", "२", "३", "४", "५", "६", "७", "८", "९"},
+                                {"০", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯"},
+                                {"੦", "੧", "੨", "੩", "੪", "੫", "੬", "੭", "੮", "੯"},
+                                {"૦", "૧", "૨", "૩", "૪", "૫", "૬", "૭", "૮", "૯"},
+                                {"୦", "୧", "୨", "୩", "୪", "୫", "୬", "୭", "୮", "୯"},
+                                {"௦", "௧", "௨", "௩", "௪", "௫", "௬", "௭", "௮", "௯"},
+                                {"౦", "౧", "౨", "౩", "౪", "౫", "౬", "౭", "౮", "౯"},
+                                {"೦", "೧", "೨", "೩", "೪", "೫", "೬", "೭", "೮", "೯"},
+                                {"൦", "൧", "൨", "൩", "൪", "൫", "൬", "൭", "൮", "൯"},
+                                {"๐", "๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙"},
+                                {"໐", "໑", "໒", "໓", "໔", "໕", "໖", "໗", "໘", "໙"},
+                                {"༠", "༡", "༢", "༣", "༤", "༥", "༦", "༧", "༨", "༩"},
+                                {"၀", "၁", "၂", "၃", "၄", "၅", "၆", "၇", "၈", "၉"},
+                                {"႐", "႑", "႒", "႓", "႔", "႕", "႖", "႗", "႘", "႙"},
+                                {"០", "១", "២", "៣", "៤", "៥", "៦", "៧", "៨", "៩"},
+                                {"᠐", "᠑", "᠒", "᠓", "᠔", "᠕", "᠖", "᠗", "᠘", "᠙"},
+                                {"᥆", "᥇", "᥈", "᥉", "᥊", "᥋", "᥌", "᥍", "᥎", "᥏"},
+                                {"᧐", "᧑", "᧒", "᧓", "᧔", "᧕", "᧖", "᧗", "᧘", "᧙"},
+                                {"᭐", "᭑", "᭒", "᭓", "᭔", "᭕", "᭖", "᭗", "᭘", "᭙"},
+                                {"᮰", "᮱", "᮲", "᮳", "᮴", "᮵", "᮶", "᮷", "᮸", "᮹"},
+                                {"᱀", "᱁", "᱂", "᱃", "᱄", "᱅", "᱆", "᱇", "᱈", "᱉"},
+                                {"᱐", "᱑", "᱒", "᱓", "᱔", "᱕", "᱖", "᱗", "᱘", "᱙"},
+                                {"꘠", "꘡", "꘢", "꘣", "꘤", "꘥", "꘦", "꘧", "꘨", "꘩"},
+                                {"꣐", "꣑", "꣒", "꣓", "꣔", "꣕", "꣖", "꣗", "꣘", "꣙"},
+                                {"꤀", "꤁", "꤂", "꤃", "꤄", "꤅", "꤆", "꤇", "꤈", "꤉"},
+                                {"꩐", "꩑", "꩒", "꩓", "꩔", "꩕", "꩖", "꩗", "꩘", "꩙"},
+                                {"𐒠", "𐒡", "𐒢", "𐒣", "𐒤", "𐒥", "𐒦", "𐒧", "𐒨", "𐒩"},
+                                {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
+
+    if (**c >= '0' && **c <= '9') {
+        value = **c - '0';
+        offset = 1;
+    } else if (**c >= 'a' && **c <= 'f') {
+        value = **c - 'a' + 10;
+        offset = 1;
+    } else if (**c >= 'A' && **c <= 'F') {
+        value = **c - 'A' + 10;
+        offset = 1;
+    } else {
+        for (i = 0; digits[i][0]; i++) {
+            for (j = 0; j < 10; j++) {
+                if (strncmp(*c, digits[i][j], strlen(digits[i][j])) == 0)
+                    break;
+            }
+            if (j != 10)
+                break;
+        }
+        if (digits[i][0] == NULL)
+            return -1;
+        value = j;
+        offset = strlen(digits[i][j]);
+    }
+    if (value >= base)
+       return -1;
+
+    *c += offset;
+
+    return value;
+}
+
+static int
+ends_with(const char *start, const char *end, const char *word)
+{
+    size_t word_len = strlen(word);
+
+    if (word_len > end - start)
+        return 0;
+
+    return strncmp(end - word_len, word, word_len) == 0;
+}
+
+// FIXME: Doesn't handle errors well (e.g. trailing space)
+static bool
+set_from_sexagesimal(const char *str, int length, MPNumber *z)
+{
+    int degrees = 0, minutes = 0;
+    char seconds[length+1];
+    int n_matched;
+
+    seconds[0] = '\0';
+    n_matched = sscanf(str, "%d°%d'%s\"", &degrees, &minutes, seconds);
+
+    if (n_matched < 1)
+        return true;
+    MPNumber t = mp_new();
+    mp_set_from_integer(degrees, z);
+    if (n_matched > 1) {
+        mp_set_from_integer(minutes, &t);
+        mp_divide_integer(&t, 60, &t);
+        mp_add(z, &t, z);
+    }
+    if (n_matched > 2) {
+        mp_set_from_string(seconds, 10, &t);
+        mp_divide_integer(&t, 3600, &t);
+        mp_add(z, &t, z);
+    }
+    mp_clear(&t);
+
+    return false;
+}
+
+bool
+mp_set_from_string(const char *str, int default_base, MPNumber *z)
+{
+    int i, base, negate = 0, multiplier = 0, base_multiplier = 1;<--- 'multiplier' is assigned value '0' here.
+    const char *c, *end;
+    gboolean has_fraction = FALSE;
+
+    const char *base_digits[]   = {"₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉", NULL};
+    const char *fractions[]     = {"½", "⅓", "⅔", "¼", "¾", "⅕", "⅖", "⅗", "⅘", "⅙", "⅚", "⅛", "⅜", "⅝", "⅞", NULL};
+    int numerators[]            = { 1,   1,   2,   1,   3,   1,   2,   3,   4,   1,   5,   1,   3,   5,   7};
+    int denominators[]          = { 2,   3,   3,   4,   4,   5,   5,   5,   5,   6,   6,   8,   8,   8,   8};
+
+    if (strstr(str, "°"))
+        return set_from_sexagesimal(str, strlen(str), z);
+
+    /* Find the base */
+    end = str;
+    while (*end != '\0')
+        end++;
+    base = 0;
+    while (1) {
+        for (i = 0; base_digits[i] != NULL; i++) {
+            if (ends_with(str, end, base_digits[i])) {
+                base += i * base_multiplier;
+                end -= strlen(base_digits[i]);
+                base_multiplier *= 10;
+                break;
+            }
+        }
+        if (base_digits[i] == NULL)
+            break;
+    }
+    if (base_multiplier == 1)
+        base = default_base;
+
+    /* Check if this has a sign */
+    c = str;
+    if (*c == '+') {
+        c++;
+    } else if (*c == '-') {
+        negate = 1;
+        c++;
+    } else if (strncmp(c, "−", strlen("−")) == 0) {
+        negate = 1;
+        c += strlen("−");
+    }
+
+    /* Convert integer part */
+    mp_set_from_integer(0, z);
+    while ((i = char_val((char **)&c, base)) >= 0) {
+        if (i > base)
+            return true;
+        mp_multiply_integer(z, base, z);
+        mp_add_integer(z, i, z);
+    }
+
+    /* Look for fraction characters, e.g. ⅚ */
+    for (i = 0; fractions[i] != NULL; i++) {
+        if (ends_with(str, end, fractions[i])) {
+            end -= strlen(fractions[i]);
+            break;
+        }
+    }
+    if (fractions[i] != NULL) {
+        MPNumber fraction = mp_new();
+        mp_set_from_fraction(numerators[i], denominators[i], &fraction);
+        mp_add(z, &fraction, z);
+        mp_clear(&fraction);
+    }
+
+    if (*c == '.') {
+        has_fraction = TRUE;
+        c++;
+    }
+
+    /* Convert fractional part */
+    if (has_fraction) {
+        MPNumber numerator = mp_new();
+        MPNumber denominator = mp_new();
+
+        mp_set_from_integer(0, &numerator);
+        mp_set_from_integer(1, &denominator);
+        while ((i = char_val((char **)&c, base)) >= 0) {
+            mp_multiply_integer(&denominator, base, &denominator);
+            mp_multiply_integer(&numerator, base, &numerator);
+            mp_add_integer(&numerator, i, &numerator);
+        }
+        mp_divide(&numerator, &denominator, &numerator);
+        mp_add(z, &numerator, z);
+        mp_clear(&numerator);
+        mp_clear(&denominator);
+    }
+
+    if (c != end) {
+        return true;
+    }
+
+    if (multiplier != 0) {
+        MPNumber t = mp_new();
+        mp_set_from_integer(10, &t);
+        mp_xpowy_integer(&t, multiplier, &t);
+        mp_multiply(z, &t, z);
+        mp_clear(&t);
+    }
+
+    if (negate == 1)
+        mp_invert_sign(z, z);
+
+    return false;
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/8.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/8.html new file mode 100644 index 0000000..dc0c535 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/8.html @@ -0,0 +1,959 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
/*
+ * Copyright (C) 2004-2008 Sami Pietila
+ * Copyright (C) 2008-2011 Robert Ancell.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "parser.h"
+
+static int
+variable_is_defined(ParserState *state, const char *name)
+{
+    /* FIXME: Make more generic */
+    if (strcmp(name, "e") == 0 ||
+        strcmp(name, "i") == 0 ||
+        strcmp(name, "π") == 0 ||
+        strcmp(name, "pi") == 0 ||
+        strcmp(name, "c₀") == 0 ||
+        strcmp(name, "μ₀") == 0 ||
+        strcmp(name, "ε₀") == 0 ||
+        strcmp(name, "G") == 0 ||
+        strcmp(name, "h") == 0 ||
+        strcmp(name, "e") == 0 ||
+        strcmp(name, "mₑ") == 0 ||
+        strcmp(name, "mₚ") == 0 ||
+        strcmp(name, "Nₐ") == 0)
+        return 1;
+    if (state->options->variable_is_defined)
+        return state->options->variable_is_defined(name, state->options->callback_data);
+    return 0;
+}
+
+static int
+get_variable(ParserState *state, const char *name, MPNumber *z)
+{
+    int result = 1;
+
+    if (strcmp(name, "e") == 0)
+        mp_get_eulers(z);
+    else if (strcmp(name, "i") == 0)
+        mp_get_i(z);
+    else if (strcmp(name, "π") == 0 || strcmp(name, "pi") == 0)
+        mp_get_pi(z);
+    else if (strcmp(name, "c₀") == 0)
+        mp_set_from_string("299792458", 10, z); /* velocity of light */
+    else if (strcmp(name, "μ₀") == 0)
+        mp_set_from_string("0.0000012566370614", 10, z); /* magnetic constant */
+    else if (strcmp(name, "ε₀") == 0)
+        mp_set_from_string("0.00000000000885418782", 10, z); /* electric constant */
+    else if (strcmp(name, "G") == 0)
+        mp_set_from_string("0.0000000000667408", 10, z); /* Newtonian constant of gravitation */
+    else if (strcmp(name, "h") == 0)
+        mp_set_from_string("0.000000000000000000000000000000000662607004", 10, z); /* Planck constant */
+    else if (strcmp(name, "e") == 0)
+        mp_set_from_string("0.00000000000000000016021766208", 10, z); /* elementary charge */
+    else if (strcmp(name, "mₑ") == 0)
+        mp_set_from_string("0.000000000000000000000000000000910938356", 10, z); /* electron mass */
+    else if (strcmp(name, "mₚ") == 0)
+        mp_set_from_string("0.000000000000000000000000001672621898", 10, z); /* proton mass */
+    else if (strcmp(name, "Nₐ") == 0)
+        mp_set_from_string("602214086000000000000000", 10, z); /* Avogadro constant */
+    else if (state->options->get_variable)
+        result = state->options->get_variable(name, z, state->options->callback_data);
+    else
+        result = 0;
+
+    return result;
+}
+
+static void
+set_variable(ParserState *state, const char *name, const MPNumber *x)
+{
+    // Reserved words, e, π, mod, and, or, xor, not, abs, log, ln, sqrt, int, frac, sin, cos, ...
+    if (strcmp(name, "e") == 0 ||
+        strcmp(name, "i") == 0 ||
+        strcmp(name, "π") == 0 ||
+        strcmp(name, "pi") == 0 ||
+        strcmp(name, "c₀") == 0 ||
+        strcmp(name, "μ₀") == 0 ||
+        strcmp(name, "ε₀") == 0 ||
+        strcmp(name, "G") == 0 ||
+        strcmp(name, "h") == 0 ||
+        strcmp(name, "e") == 0 ||
+        strcmp(name, "mₑ") == 0 ||
+        strcmp(name, "mₚ") == 0 ||
+        strcmp(name, "Nₐ") == 0)
+        return; // FALSE
+
+    if (state->options->set_variable)
+        state->options->set_variable(name, x, state->options->callback_data);
+}
+
+// FIXME: Accept "2sin" not "2 sin", i.e. let the tokenizer collect the multiple
+// Parser then distinguishes between "sin"="s*i*n" or "sin5" = "sin 5" = "sin(5)"
+// i.e. numbers+letters = variable or function depending on following arg
+// letters+numbers = numbers+letters+numbers = function
+
+int
+sub_atoi(const char *data)
+{
+    int i, value = 0;
+    const char *digits[] = {"₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉", NULL};
+
+    do {
+        for(i = 0; digits[i] != NULL && strncmp(data, digits[i], strlen(digits[i])) != 0; i++);
+        if(digits[i] == NULL)
+            return -1;
+        data += strlen(digits[i]);
+        value = value * 10 + i;
+    } while(*data != '\0');
+
+    return value;
+}
+
+int
+super_atoi(const char *data)
+{
+   int i, sign = 1, value = 0;
+   const char *digits[11] = {"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", NULL};
+
+   if(strncmp(data, "⁻", strlen("⁻")) == 0) {
+      sign = -1;
+      data += strlen("⁻");
+   }
+
+   do {
+      for(i = 0; digits[i] != NULL && strncmp(data, digits[i], strlen(digits[i])) != 0; i++);
+      if(digits[i] == NULL)
+         return 0;
+      value = value * 10 + i;
+      data += strlen(digits[i]);
+   } while(*data != '\0');
+
+   return sign * value;
+}
+
+static int
+function_is_defined(ParserState *state, const char *name)
+{
+    char *c, *lower_name;
+
+    lower_name = strdup(name);
+    for (c = lower_name; *c; c++)
+        *c = tolower(*c);
+
+    /* FIXME: Make more generic */
+    if (strcmp(lower_name, "log") == 0 ||
+        (strncmp(lower_name, "log", 3) == 0 && sub_atoi(lower_name + 3) >= 0) ||
+        strcmp(lower_name, "ln") == 0 ||
+        strcmp(lower_name, "sqrt") == 0 ||
+        strcmp(lower_name, "abs") == 0 ||
+        strcmp(lower_name, "sgn") == 0 ||
+        strcmp(lower_name, "arg") == 0 ||
+        strcmp(lower_name, "conj") == 0 ||
+        strcmp(lower_name, "int") == 0 ||
+        strcmp(lower_name, "frac") == 0 ||
+        strcmp(lower_name, "floor") == 0 ||
+        strcmp(lower_name, "ceil") == 0 ||
+        strcmp(lower_name, "round") == 0 ||
+        strcmp(lower_name, "re") == 0 ||
+        strcmp(lower_name, "im") == 0 ||
+        strcmp(lower_name, "sin") == 0 || strcmp(lower_name, "cos") == 0 || strcmp(lower_name, "tan") == 0 ||
+        strcmp(lower_name, "asin") == 0 || strcmp(lower_name, "acos") == 0 || strcmp(lower_name, "atan") == 0 ||
+        strcmp(lower_name, "sin⁻¹") == 0 || strcmp(lower_name, "cos⁻¹") == 0 || strcmp(lower_name, "tan⁻¹") == 0 ||
+        strcmp(lower_name, "sinh") == 0 || strcmp(lower_name, "cosh") == 0 || strcmp(lower_name, "tanh") == 0 ||
+        strcmp(lower_name, "sinh⁻¹") == 0 || strcmp(lower_name, "cosh⁻¹") == 0 || strcmp(lower_name, "tanh⁻¹") == 0 ||
+        strcmp(lower_name, "erf") == 0 || strcmp(lower_name, "zeta") == 0 ||
+        strcmp(lower_name, "asinh") == 0 || strcmp(lower_name, "acosh") == 0 || strcmp(lower_name, "atanh") == 0 ||
+        strcmp(lower_name, "ones") == 0 ||
+        strcmp(lower_name, "twos") == 0) {
+        g_free (lower_name);
+        return 1;
+    }
+    g_free (lower_name);
+
+    if (state->options->function_is_defined)
+        return state->options->function_is_defined(name, state->options->callback_data);
+    return 0;
+}
+
+static int
+get_function(ParserState *state, const char *name, const MPNumber *x, MPNumber *z)
+{
+    char *c, *lower_name;
+    int result = 1;
+
+    lower_name = strdup(name);
+    for (c = lower_name; *c; c++)
+        *c = tolower(*c);
+
+    // FIXME: Re Im ?
+
+    if (strcmp(lower_name, "log") == 0)
+        mp_logarithm(10, x, z); // FIXME: Default to ln
+    else if (strncmp(lower_name, "log", 3) == 0) {
+        int base;
+
+        base = sub_atoi(lower_name + 3);
+        if (base < 0)
+            result = 0;
+        else
+            mp_logarithm(base, x, z);
+    }
+    else if (strcmp(lower_name, "ln") == 0)
+        mp_ln(x, z);
+    else if (strcmp(lower_name, "sqrt") == 0) // √x
+        mp_sqrt(x, z);
+    else if (strcmp(lower_name, "abs") == 0) // |x|
+        mp_abs(x, z);
+    else if (strcmp(lower_name, "sgn") == 0)
+        mp_sgn(x, z);
+    else if (strcmp(lower_name, "arg") == 0)
+        mp_arg(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "conj") == 0)
+        mp_conjugate(x, z);
+    else if (strcmp(lower_name, "int") == 0)
+        mp_integer_component(x, z);
+    else if (strcmp(lower_name, "frac") == 0)
+        mp_fractional_component(x, z);
+    else if (strcmp(lower_name, "floor") == 0)
+        mp_floor(x, z);
+    else if (strcmp(lower_name, "ceil") == 0)
+        mp_ceiling(x, z);
+    else if (strcmp(lower_name, "round") == 0)
+        mp_round(x, z);
+    else if (strcmp(lower_name, "re") == 0)
+        mp_real_component(x, z);
+    else if (strcmp(lower_name, "im") == 0)
+        mp_imaginary_component(x, z);
+    else if (strcmp(lower_name, "sin") == 0)
+        mp_sin(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "cos") == 0)
+        mp_cos(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "tan") == 0)
+        mp_tan(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "sin⁻¹") == 0 || strcmp(lower_name, "asin") == 0)
+        mp_asin(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "cos⁻¹") == 0 || strcmp(lower_name, "acos") == 0)
+        mp_acos(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "tan⁻¹") == 0 || strcmp(lower_name, "atan") == 0)
+        mp_atan(x, state->options->angle_units, z);
+    else if (strcmp(lower_name, "sinh") == 0)
+        mp_sinh(x, z);
+    else if (strcmp(lower_name, "cosh") == 0)
+        mp_cosh(x, z);
+    else if (strcmp(lower_name, "tanh") == 0)
+        mp_tanh(x, z);
+    else if (strcmp(lower_name, "sinh⁻¹") == 0 || strcmp(lower_name, "asinh") == 0)
+        mp_asinh(x, z);
+    else if (strcmp(lower_name, "cosh⁻¹") == 0 || strcmp(lower_name, "acosh") == 0)
+        mp_acosh(x, z);
+    else if (strcmp(lower_name, "tanh⁻¹") == 0 || strcmp(lower_name, "atanh") == 0)
+        mp_atanh(x, z);
+    else if (strcmp(lower_name, "erf") == 0)
+        mp_erf(x, z);
+    else if (strcmp(lower_name, "zeta") == 0)
+        mp_zeta(x, z);
+    else if (strcmp(lower_name, "ones") == 0)
+        mp_ones_complement(x, state->options->wordlen, z);
+    else if (strcmp(lower_name, "twos") == 0)
+        mp_twos_complement(x, state->options->wordlen, z);
+    else if (state->options->get_function)
+        result = state->options->get_function(name, x, z, state->options->callback_data);
+    else
+        result = 0;
+
+    free(lower_name);
+
+    return result;
+}
+
+static int
+convert(ParserState *state, const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z)
+{
+    if (state->options->convert)
+        return state->options->convert(x, x_units, z_units, z, state->options->callback_data);
+    else
+        return 0;
+}
+
+MPErrorCode
+mp_equation_parse(const char *expression, MPEquationOptions *options, MPNumber *result, char **error_token)
+{
+    int ret;
+    int err;
+    ParserState* state;
+    state = p_create_parser (expression, options);
+
+    if (!(expression && result) || strlen(expression) == 0)
+        return PARSER_ERR_INVALID;
+
+    state->variable_is_defined = variable_is_defined;
+    state->get_variable = get_variable;
+    state->set_variable = set_variable;
+    state->function_is_defined = function_is_defined;
+    state->get_function = get_function;
+    state->convert = convert;
+    state->error = 0;
+    mp_clear_error();
+    ret = p_parse (state);
+    if (state->error_token != NULL && error_token != NULL) {
+        *error_token = state->error_token;
+    }
+    /* Error during parsing */
+    if (state->error) {
+	err = state->error;
+        p_destroy_parser (state);
+        return err;
+    }
+
+    if (mp_get_error()) {
+        p_destroy_parser (state);
+        return PARSER_ERR_MP;
+    }
+
+    /* Failed to parse */
+    if (ret) {
+        p_destroy_parser (state);
+        return PARSER_ERR_INVALID;
+    }
+    mp_set_from_mp(&state->ret, result);
+    p_destroy_parser (state);
+    return PARSER_ERR_NONE;
+}
+
+const char *
+mp_error_code_to_string(MPErrorCode error_code)
+{
+    switch(error_code)
+    {
+    case PARSER_ERR_NONE:
+        return "PARSER_ERR_NONE";
+    case PARSER_ERR_INVALID:
+        return "PARSER_ERR_INVALID";
+    case PARSER_ERR_OVERFLOW:
+        return "PARSER_ERR_OVERFLOW";
+    case PARSER_ERR_UNKNOWN_VARIABLE:
+        return "PARSER_ERR_UNKNOWN_VARIABLE";
+    case PARSER_ERR_UNKNOWN_FUNCTION:
+        return "PARSER_ERR_UNKNOWN_FUNCTION";
+    case PARSER_ERR_UNKNOWN_CONVERSION:
+        return "PARSER_ERR_UNKNOWN_CONVERSION";
+    case PARSER_ERR_MP:
+        return "PARSER_ERR_MP";
+    default:
+        return "Unknown parser error";
+    }
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/9.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/9.html new file mode 100644 index 0000000..c7a1aa3 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/9.html @@ -0,0 +1,2785 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+
   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+  10
+  11
+  12
+  13
+  14
+  15
+  16
+  17
+  18
+  19
+  20
+  21
+  22
+  23
+  24
+  25
+  26
+  27
+  28
+  29
+  30
+  31
+  32
+  33
+  34
+  35
+  36
+  37
+  38
+  39
+  40
+  41
+  42
+  43
+  44
+  45
+  46
+  47
+  48
+  49
+  50
+  51
+  52
+  53
+  54
+  55
+  56
+  57
+  58
+  59
+  60
+  61
+  62
+  63
+  64
+  65
+  66
+  67
+  68
+  69
+  70
+  71
+  72
+  73
+  74
+  75
+  76
+  77
+  78
+  79
+  80
+  81
+  82
+  83
+  84
+  85
+  86
+  87
+  88
+  89
+  90
+  91
+  92
+  93
+  94
+  95
+  96
+  97
+  98
+  99
+ 100
+ 101
+ 102
+ 103
+ 104
+ 105
+ 106
+ 107
+ 108
+ 109
+ 110
+ 111
+ 112
+ 113
+ 114
+ 115
+ 116
+ 117
+ 118
+ 119
+ 120
+ 121
+ 122
+ 123
+ 124
+ 125
+ 126
+ 127
+ 128
+ 129
+ 130
+ 131
+ 132
+ 133
+ 134
+ 135
+ 136
+ 137
+ 138
+ 139
+ 140
+ 141
+ 142
+ 143
+ 144
+ 145
+ 146
+ 147
+ 148
+ 149
+ 150
+ 151
+ 152
+ 153
+ 154
+ 155
+ 156
+ 157
+ 158
+ 159
+ 160
+ 161
+ 162
+ 163
+ 164
+ 165
+ 166
+ 167
+ 168
+ 169
+ 170
+ 171
+ 172
+ 173
+ 174
+ 175
+ 176
+ 177
+ 178
+ 179
+ 180
+ 181
+ 182
+ 183
+ 184
+ 185
+ 186
+ 187
+ 188
+ 189
+ 190
+ 191
+ 192
+ 193
+ 194
+ 195
+ 196
+ 197
+ 198
+ 199
+ 200
+ 201
+ 202
+ 203
+ 204
+ 205
+ 206
+ 207
+ 208
+ 209
+ 210
+ 211
+ 212
+ 213
+ 214
+ 215
+ 216
+ 217
+ 218
+ 219
+ 220
+ 221
+ 222
+ 223
+ 224
+ 225
+ 226
+ 227
+ 228
+ 229
+ 230
+ 231
+ 232
+ 233
+ 234
+ 235
+ 236
+ 237
+ 238
+ 239
+ 240
+ 241
+ 242
+ 243
+ 244
+ 245
+ 246
+ 247
+ 248
+ 249
+ 250
+ 251
+ 252
+ 253
+ 254
+ 255
+ 256
+ 257
+ 258
+ 259
+ 260
+ 261
+ 262
+ 263
+ 264
+ 265
+ 266
+ 267
+ 268
+ 269
+ 270
+ 271
+ 272
+ 273
+ 274
+ 275
+ 276
+ 277
+ 278
+ 279
+ 280
+ 281
+ 282
+ 283
+ 284
+ 285
+ 286
+ 287
+ 288
+ 289
+ 290
+ 291
+ 292
+ 293
+ 294
+ 295
+ 296
+ 297
+ 298
+ 299
+ 300
+ 301
+ 302
+ 303
+ 304
+ 305
+ 306
+ 307
+ 308
+ 309
+ 310
+ 311
+ 312
+ 313
+ 314
+ 315
+ 316
+ 317
+ 318
+ 319
+ 320
+ 321
+ 322
+ 323
+ 324
+ 325
+ 326
+ 327
+ 328
+ 329
+ 330
+ 331
+ 332
+ 333
+ 334
+ 335
+ 336
+ 337
+ 338
+ 339
+ 340
+ 341
+ 342
+ 343
+ 344
+ 345
+ 346
+ 347
+ 348
+ 349
+ 350
+ 351
+ 352
+ 353
+ 354
+ 355
+ 356
+ 357
+ 358
+ 359
+ 360
+ 361
+ 362
+ 363
+ 364
+ 365
+ 366
+ 367
+ 368
+ 369
+ 370
+ 371
+ 372
+ 373
+ 374
+ 375
+ 376
+ 377
+ 378
+ 379
+ 380
+ 381
+ 382
+ 383
+ 384
+ 385
+ 386
+ 387
+ 388
+ 389
+ 390
+ 391
+ 392
+ 393
+ 394
+ 395
+ 396
+ 397
+ 398
+ 399
+ 400
+ 401
+ 402
+ 403
+ 404
+ 405
+ 406
+ 407
+ 408
+ 409
+ 410
+ 411
+ 412
+ 413
+ 414
+ 415
+ 416
+ 417
+ 418
+ 419
+ 420
+ 421
+ 422
+ 423
+ 424
+ 425
+ 426
+ 427
+ 428
+ 429
+ 430
+ 431
+ 432
+ 433
+ 434
+ 435
+ 436
+ 437
+ 438
+ 439
+ 440
+ 441
+ 442
+ 443
+ 444
+ 445
+ 446
+ 447
+ 448
+ 449
+ 450
+ 451
+ 452
+ 453
+ 454
+ 455
+ 456
+ 457
+ 458
+ 459
+ 460
+ 461
+ 462
+ 463
+ 464
+ 465
+ 466
+ 467
+ 468
+ 469
+ 470
+ 471
+ 472
+ 473
+ 474
+ 475
+ 476
+ 477
+ 478
+ 479
+ 480
+ 481
+ 482
+ 483
+ 484
+ 485
+ 486
+ 487
+ 488
+ 489
+ 490
+ 491
+ 492
+ 493
+ 494
+ 495
+ 496
+ 497
+ 498
+ 499
+ 500
+ 501
+ 502
+ 503
+ 504
+ 505
+ 506
+ 507
+ 508
+ 509
+ 510
+ 511
+ 512
+ 513
+ 514
+ 515
+ 516
+ 517
+ 518
+ 519
+ 520
+ 521
+ 522
+ 523
+ 524
+ 525
+ 526
+ 527
+ 528
+ 529
+ 530
+ 531
+ 532
+ 533
+ 534
+ 535
+ 536
+ 537
+ 538
+ 539
+ 540
+ 541
+ 542
+ 543
+ 544
+ 545
+ 546
+ 547
+ 548
+ 549
+ 550
+ 551
+ 552
+ 553
+ 554
+ 555
+ 556
+ 557
+ 558
+ 559
+ 560
+ 561
+ 562
+ 563
+ 564
+ 565
+ 566
+ 567
+ 568
+ 569
+ 570
+ 571
+ 572
+ 573
+ 574
+ 575
+ 576
+ 577
+ 578
+ 579
+ 580
+ 581
+ 582
+ 583
+ 584
+ 585
+ 586
+ 587
+ 588
+ 589
+ 590
+ 591
+ 592
+ 593
+ 594
+ 595
+ 596
+ 597
+ 598
+ 599
+ 600
+ 601
+ 602
+ 603
+ 604
+ 605
+ 606
+ 607
+ 608
+ 609
+ 610
+ 611
+ 612
+ 613
+ 614
+ 615
+ 616
+ 617
+ 618
+ 619
+ 620
+ 621
+ 622
+ 623
+ 624
+ 625
+ 626
+ 627
+ 628
+ 629
+ 630
+ 631
+ 632
+ 633
+ 634
+ 635
+ 636
+ 637
+ 638
+ 639
+ 640
+ 641
+ 642
+ 643
+ 644
+ 645
+ 646
+ 647
+ 648
+ 649
+ 650
+ 651
+ 652
+ 653
+ 654
+ 655
+ 656
+ 657
+ 658
+ 659
+ 660
+ 661
+ 662
+ 663
+ 664
+ 665
+ 666
+ 667
+ 668
+ 669
+ 670
+ 671
+ 672
+ 673
+ 674
+ 675
+ 676
+ 677
+ 678
+ 679
+ 680
+ 681
+ 682
+ 683
+ 684
+ 685
+ 686
+ 687
+ 688
+ 689
+ 690
+ 691
+ 692
+ 693
+ 694
+ 695
+ 696
+ 697
+ 698
+ 699
+ 700
+ 701
+ 702
+ 703
+ 704
+ 705
+ 706
+ 707
+ 708
+ 709
+ 710
+ 711
+ 712
+ 713
+ 714
+ 715
+ 716
+ 717
+ 718
+ 719
+ 720
+ 721
+ 722
+ 723
+ 724
+ 725
+ 726
+ 727
+ 728
+ 729
+ 730
+ 731
+ 732
+ 733
+ 734
+ 735
+ 736
+ 737
+ 738
+ 739
+ 740
+ 741
+ 742
+ 743
+ 744
+ 745
+ 746
+ 747
+ 748
+ 749
+ 750
+ 751
+ 752
+ 753
+ 754
+ 755
+ 756
+ 757
+ 758
+ 759
+ 760
+ 761
+ 762
+ 763
+ 764
+ 765
+ 766
+ 767
+ 768
+ 769
+ 770
+ 771
+ 772
+ 773
+ 774
+ 775
+ 776
+ 777
+ 778
+ 779
+ 780
+ 781
+ 782
+ 783
+ 784
+ 785
+ 786
+ 787
+ 788
+ 789
+ 790
+ 791
+ 792
+ 793
+ 794
+ 795
+ 796
+ 797
+ 798
+ 799
+ 800
+ 801
+ 802
+ 803
+ 804
+ 805
+ 806
+ 807
+ 808
+ 809
+ 810
+ 811
+ 812
+ 813
+ 814
+ 815
+ 816
+ 817
+ 818
+ 819
+ 820
+ 821
+ 822
+ 823
+ 824
+ 825
+ 826
+ 827
+ 828
+ 829
+ 830
+ 831
+ 832
+ 833
+ 834
+ 835
+ 836
+ 837
+ 838
+ 839
+ 840
+ 841
+ 842
+ 843
+ 844
+ 845
+ 846
+ 847
+ 848
+ 849
+ 850
+ 851
+ 852
+ 853
+ 854
+ 855
+ 856
+ 857
+ 858
+ 859
+ 860
+ 861
+ 862
+ 863
+ 864
+ 865
+ 866
+ 867
+ 868
+ 869
+ 870
+ 871
+ 872
+ 873
+ 874
+ 875
+ 876
+ 877
+ 878
+ 879
+ 880
+ 881
+ 882
+ 883
+ 884
+ 885
+ 886
+ 887
+ 888
+ 889
+ 890
+ 891
+ 892
+ 893
+ 894
+ 895
+ 896
+ 897
+ 898
+ 899
+ 900
+ 901
+ 902
+ 903
+ 904
+ 905
+ 906
+ 907
+ 908
+ 909
+ 910
+ 911
+ 912
+ 913
+ 914
+ 915
+ 916
+ 917
+ 918
+ 919
+ 920
+ 921
+ 922
+ 923
+ 924
+ 925
+ 926
+ 927
+ 928
+ 929
+ 930
+ 931
+ 932
+ 933
+ 934
+ 935
+ 936
+ 937
+ 938
+ 939
+ 940
+ 941
+ 942
+ 943
+ 944
+ 945
+ 946
+ 947
+ 948
+ 949
+ 950
+ 951
+ 952
+ 953
+ 954
+ 955
+ 956
+ 957
+ 958
+ 959
+ 960
+ 961
+ 962
+ 963
+ 964
+ 965
+ 966
+ 967
+ 968
+ 969
+ 970
+ 971
+ 972
+ 973
+ 974
+ 975
+ 976
+ 977
+ 978
+ 979
+ 980
+ 981
+ 982
+ 983
+ 984
+ 985
+ 986
+ 987
+ 988
+ 989
+ 990
+ 991
+ 992
+ 993
+ 994
+ 995
+ 996
+ 997
+ 998
+ 999
+1000
+1001
+1002
+1003
+1004
+1005
+1006
+1007
+1008
+1009
+1010
+1011
+1012
+1013
+1014
+1015
+1016
+1017
+1018
+1019
+1020
+1021
+1022
+1023
+1024
+1025
+1026
+1027
+1028
+1029
+1030
+1031
+1032
+1033
+1034
+1035
+1036
+1037
+1038
+1039
+1040
+1041
+1042
+1043
+1044
+1045
+1046
+1047
+1048
+1049
+1050
+1051
+1052
+1053
+1054
+1055
+1056
+1057
+1058
+1059
+1060
+1061
+1062
+1063
+1064
+1065
+1066
+1067
+1068
+1069
+1070
+1071
+1072
+1073
+1074
+1075
+1076
+1077
+1078
+1079
+1080
+1081
+1082
+1083
+1084
+1085
+1086
+1087
+1088
+1089
+1090
+1091
+1092
+1093
+1094
+1095
+1096
+1097
+1098
+1099
+1100
+1101
+1102
+1103
+1104
+1105
+1106
+1107
+1108
+1109
+1110
+1111
+1112
+1113
+1114
+1115
+1116
+1117
+1118
+1119
+1120
+1121
+1122
+1123
+1124
+1125
+1126
+1127
+1128
+1129
+1130
+1131
+1132
+1133
+1134
+1135
+1136
+1137
+1138
+1139
+1140
+1141
+1142
+1143
+1144
+1145
+1146
+1147
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#include "parser.h"
+#include "parserfunc.h"
+#include "mp-equation.h"
+
+/* Converts LexerTokenType to Precedence value. */
+static guint
+p_get_precedence(LexerTokenType type)
+{
+    /* WARNING: This function doesn't work for Unary Plus and Unary Minus. Use their precedence directly while inserting them in tree. */
+    if(type == T_ADD
+     ||type == T_SUBTRACT)
+        return P_AddSubtract;
+    if(type == T_MULTIPLY)
+        return P_Multiply;
+    if(type == T_MOD)
+        return P_Mod;
+    if(type == T_DIV)
+        return P_Divide;
+    if(type == T_NOT)
+        return P_Not;
+    if(type == T_ROOT
+     ||type == T_ROOT_3
+     ||type == T_ROOT_4)
+        return P_Root;
+    if(type == T_FUNCTION)
+        return P_Function;
+    if(type == T_AND
+     ||type == T_OR
+     ||type == T_XOR)
+        return P_Boolean;
+    if(type == T_PERCENTAGE)
+        return P_Percentage;
+    if(type == T_POWER)
+        return P_Power;
+    if(type == T_FACTORIAL)
+        return P_Factorial;
+    if(type == T_NUMBER
+     ||type == T_VARIABLE)
+        return P_NumberVariable;
+    return P_Unknown;
+}
+
+/* Return associativity of specific token type from precedence. */
+static Associativity
+p_get_associativity_p(Precedence type)
+{
+    if(type == P_Boolean
+     ||type == P_Divide
+     ||type == P_Mod
+     ||type == P_Multiply
+     ||type == P_AddSubtract)
+        return LEFT_ASSOCIATIVE;
+    if(type == P_Power)
+        return RIGHT_ASSOCIATIVE;
+    /* For all remaining / non-associative operators, return Left Associativity. */
+    return LEFT_ASSOCIATIVE;
+}
+
+/* Return associativity of specific token by converting it to precedence first. */
+static Associativity
+p_get_associativity(LexerToken* token)
+{
+    return p_get_associativity_p(p_get_precedence(token->token_type));
+}
+
+/* Generate precedence for a node from precedence value. Includes depth_level. */
+static guint
+p_make_precedence_p(ParserState* state, Precedence p)
+{
+    return (p + (state->depth_level * P_Depth));
+}
+
+/* Generate precedence for a node from lexer token type. Includes depth_level. */
+static guint
+p_make_precedence_t(ParserState* state, LexerTokenType type)
+{
+    return (p_get_precedence(type) + (state->depth_level * P_Depth));
+}
+
+/* Allocate and create a new node. */
+static ParseNode*
+p_create_node(ParserState* state, LexerToken* token, guint precedence, Associativity associativity, void* value, void* (*function)(ParseNode*))
+{
+    ParseNode* new;
+    new = (ParseNode*) malloc(sizeof(ParseNode));
+    assert(new != NULL);
+    new->parent = NULL;
+    new->left = NULL;
+    new->right = NULL;
+    new->token = token;
+    new->precedence = precedence;
+    new->associativity = associativity;
+    new->value = value;
+    new->state = state;
+    new->evaluate = function;
+    return new;
+}
+
+/* Compares two nodes to decide, which will be parent and which willbe child. */
+static gint
+p_cmp_nodes(ParseNode* left, ParseNode* right)
+{
+    /* Return values.
+       1 = right goes up (near root) in parse tree.
+       0 = left  goes up (near root) in parse tree.
+    */
+    if(left == NULL)
+        return 0;
+    if(left->precedence > right->precedence)
+    {
+        return 1;
+    }
+    else if(left->precedence < right->precedence)
+    {
+        return 0;
+    }
+    else
+    {
+        if(right->associativity == RIGHT_ASSOCIATIVE)
+        {
+            return 0;
+        }
+        else
+        {
+            return 1;
+        }
+    }
+}
+
+/* Unified interface (unary and binary nodes) to insert node into parse tree. */
+static void
+p_insert_into_tree_all(ParserState* state, ParseNode* node, guint unary_function)
+{
+    if(state->root == NULL)
+    {
+        state->root = node;
+        state->right_most = state->root;
+        return;
+    }
+    ParseNode* tmp = state->right_most;
+    while(p_cmp_nodes(tmp, node))
+        tmp = tmp->parent;
+    if(unary_function)
+    {
+        /* If tmp is null, that means, we have to insert new node at root. */
+        if(tmp == NULL)
+        {
+            node->right = state->root;
+            node->right->parent = node;
+
+            state->root = node;
+        }
+        else
+        {
+            node->right = tmp->right;
+            if(node->right)
+                node->right->parent = node;
+
+            tmp->right = node;
+            if(tmp->right)
+                tmp->right->parent = tmp;
+
+        }
+        state->right_most = node;
+        while(state->right_most->right != NULL)
+            state->right_most = state->right_most->right;
+    }
+    else
+    {
+        /* If tmp is null, that means, we have to insert new node at root. */
+        if(tmp == NULL)
+        {
+            node->left = state->root;
+            node->left->parent = node;
+
+            state->root = node;
+        }
+        else
+        {
+            node->left = tmp->right;
+            if(node->left)
+                node->left->parent = node;
+
+            tmp->right = node;
+            if(tmp->right)
+                tmp->right->parent = tmp;
+
+        }
+        state->right_most = node;
+    }
+}
+
+/* Insert binary node into the parse tree. */
+static void
+p_insert_into_tree(ParserState* state, ParseNode* node)
+{
+    p_insert_into_tree_all(state, node, 0);
+}
+
+/* Insert unary node into the parse tree. */
+static void
+p_insert_into_tree_unary(ParserState* state, ParseNode* node)
+{
+    p_insert_into_tree_all(state, node, 1);
+}
+
+/* Recursive call to free every node of parse-tree. */
+static void
+p_destroy_all_nodes(ParseNode* node)
+{
+    if(node == NULL)
+        return;
+    p_destroy_all_nodes(node->left);
+    p_destroy_all_nodes(node->right);
+    /* Don't call free for tokens, as they are allocated and freed in lexer. */
+    /* WARNING: If node->value is freed elsewhere, please assign it NULL before calling p_destroy_all_nodes(). */
+    if(node->value)
+        free(node->value);
+    free(node);
+}
+
+/* Create parser state. */
+ParserState*
+p_create_parser(const gchar* input, MPEquationOptions* options)
+{
+    ParserState* state;
+    state = (ParserState*) malloc(sizeof(ParserState));
+    assert(state != NULL);
+    state->lexer = l_create_lexer(input, state);
+    state->root = NULL;
+    state->depth_level = 0;
+    state->right_most = NULL;
+    state->options = options;
+    state->error = 0;
+    state->error_token = NULL;
+    return state;
+}
+
+static guint statement (ParserState*);
+/* Start parsing input string. And call evaluate on success. */
+guint
+p_parse(ParserState* state)
+{
+    guint ret;
+    LexerToken* token;
+    MPNumber* ans;
+    l_insert_all_tokens(state->lexer);
+    ret = statement(state);
+    token = l_get_next_token(state->lexer);
+    if(token->token_type == T_ASSIGN)
+    {
+        token = l_get_next_token(state->lexer);
+        if(token->token_type != PL_EOS)
+        {
+        /* Full string is not parsed. */
+            if(!state->error)
+                set_error(state, PARSER_ERR_INVALID, token->string);
+            return PARSER_ERR_INVALID;
+        }
+    }
+    if(token->token_type != PL_EOS)
+    {
+        /* Full string is not parsed. */
+        if(!state->error)
+            set_error(state, PARSER_ERR_INVALID, token->string);
+        return PARSER_ERR_INVALID;
+    }
+    if(ret == 0)
+        /* Input can't be parsed with grammar. */
+        return PARSER_ERR_INVALID;
+    ans = (MPNumber *) (*(state->root->evaluate))(state->root);
+    if(ans)
+    {
+        state->ret = mp_new();
+        mp_set_from_mp(ans, &state->ret);
+        mp_free(ans);
+        return PARSER_ERR_NONE;
+    }
+    return PARSER_ERR_INVALID;
+}
+
+/* Destroy parser state. */
+void
+p_destroy_parser(ParserState* state)
+{
+    /* If state has a parse tree, destroy it first. */
+    if(state->root)
+    {
+        p_destroy_all_nodes(state->root);
+    }
+    l_destroy_lexer(state->lexer);
+    free(state);
+}
+
+/* LL (*) parser. Lookahead count depends on tokens. Handle with care. :P */
+
+static guint expression(ParserState* state);
+static guint expression_1(ParserState* state);
+static guint expression_2(ParserState* state);
+static guint unit(ParserState* state);
+static guint variable(ParserState* state);
+static guint term(ParserState* state);
+static guint term_2(ParserState* state);
+
+/* Helping function to p_check_variable. */
+static gchar*
+utf8_next_char(const gchar* c)
+{
+    c++;
+    while((*c & 0xC0) == 0x80)
+        c++;
+    return (gchar *)c;
+}
+
+/* Check if string "name" is a valid variable for given ParserState. It is the same code, used to get the value of variable in parserfunc.c. */
+static gboolean
+p_check_variable(ParserState* state, gchar* name)
+{
+    gint result = 0;
+
+    const gchar *c, *next;
+    gchar *buffer;
+    MPNumber temp;
+
+    if(!(state->get_variable))
+    {
+        return FALSE;
+    }
+    temp = mp_new();
+    /* If defined, then get the variable */
+    if((*(state->get_variable))(state, name, &temp))
+    {
+        mp_clear(&temp);
+        return TRUE;
+    }
+
+    /* If has more than one character then assume a multiplication of variables */
+    if(utf8_next_char(name)[0] != '\0')
+    {
+        result = 1;
+        buffer = (gchar*) malloc(sizeof(gchar) * strlen(name));
+        for(c = name; *c != '\0'; c = next)
+        {
+            next = utf8_next_char(c);
+            snprintf(buffer, (size_t) (next - c + 1), "%s", c);
+            if(!(*(state->get_variable))(state, buffer, &temp))
+            {
+                result = 0;
+                break;
+            }
+        }
+        free(buffer);
+    }
+    mp_clear(&temp);
+    if(!result)
+    {
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static guint
+statement(ParserState* state)
+{
+    LexerToken* token;
+    LexerToken* token_old;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+    if(token->token_type == T_VARIABLE)
+    {
+        token_old = token;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_ASSIGN)
+        {
+            /* VARIABLE = expression. */
+
+            node = p_create_node(state, token_old, p_make_precedence_p(state, P_NumberVariable), p_get_associativity(token_old), NULL, pf_none);
+            p_insert_into_tree(state, node);
+
+            node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_set_var);
+            p_insert_into_tree(state, node);
+
+            if(!expression(state))
+                return 0;
+            return 1;
+        }
+        else if(token->token_type == T_IN)
+        {
+            /* UNIT in UNIT. */
+            l_roll_back(state->lexer);
+            l_roll_back(state->lexer);
+            if(!unit(state))
+                return 0;
+            l_get_next_token(state->lexer);
+
+            node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_1);
+            p_insert_into_tree(state, node);
+
+            if(!unit(state))
+                return 0;
+            return 1;
+        }
+        else if(token->token_type == T_SUP_NUMBER)
+        {
+            token = l_get_next_token(state->lexer);
+            if(token->token_type == T_IN)
+            {
+                /* UNIT in UNIT */
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+                if(!unit(state))
+                    return 0;
+                l_get_next_token(state->lexer);
+
+                node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_1);
+                p_insert_into_tree(state, node);
+
+                if(!unit(state))
+                    return 0;
+                return 1;
+            }
+            else
+            {
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+                if(!expression(state))
+                    return 0;
+                return 1;
+            }
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+            l_roll_back(state->lexer);
+            if(!expression(state))
+                return 0;
+            return 1;
+        }
+    }
+    else if(token->token_type == T_NUMBER)
+    {
+        token_old = token;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_VARIABLE)
+        {
+            token = l_get_next_token(state->lexer);
+            if(token->token_type == T_IN)
+            {
+                /* NUMBER UNIT in UNIT */
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+
+                node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token), NULL, pf_constant);
+                p_insert_into_tree(state, node);
+
+                if(!unit(state))
+                    return 0;
+                token = l_get_next_token(state->lexer);
+
+                node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_number);
+                p_insert_into_tree(state, node);
+
+                if(!unit(state))
+                    return 0;
+                return 1;
+            }
+            else if(token->token_type == T_SUP_NUMBER)
+            {
+                token = l_get_next_token(state->lexer);
+                if(token->token_type == T_IN)
+                {
+                    /* NUMBER UNIT in UNIT */
+                    l_roll_back(state->lexer);
+                    l_roll_back(state->lexer);
+                    l_roll_back(state->lexer);
+
+                    node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token), NULL, pf_constant);
+                    p_insert_into_tree(state, node);
+
+                    if(!unit(state))
+                        return 0;
+                    token = l_get_next_token(state->lexer);
+
+                    node = p_create_node(state, token, 0, p_get_associativity(token), NULL, pf_convert_number);
+                    p_insert_into_tree(state, node);
+
+                    if(!unit(state))
+                        return 0;
+                    return 1;
+                }
+                else
+                {
+                    l_roll_back(state->lexer);
+                    l_roll_back(state->lexer);
+                    l_roll_back(state->lexer);
+                    l_roll_back(state->lexer);
+                    if(!expression(state))
+                        return 0;
+                    return 1;
+                }
+            }
+            else
+            {
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+                l_roll_back(state->lexer);
+                if(!expression(state))
+                    return 0;
+                return 1;
+            }
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+            l_roll_back(state->lexer);
+            if(!expression(state))
+                return 0;
+            return 1;
+        }
+    }
+    else
+    {
+        l_roll_back(state->lexer);
+        if(!expression(state))
+            return 0;
+        return 1;
+    }
+}
+
+static guint
+unit(ParserState* state)
+{
+    LexerToken* token;
+    LexerToken* token_old;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+    if(token->token_type == T_VARIABLE)
+    {
+        token_old = token;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_SUP_NUMBER)
+        {
+            /* VARIABLE POWER */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), pf_make_unit(token_old->string, token->string), pf_none);
+            p_insert_into_tree(state, node);
+
+            return 1;
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+            /* VARIABLE */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), NULL, pf_none);
+            p_insert_into_tree(state, node);
+
+            return 1;
+        }
+    }
+    else
+    {
+        l_roll_back(state->lexer);
+        return 0;
+    }
+}
+
+static guint
+expression(ParserState* state)
+{
+    if(!expression_1(state))
+        return 0;
+    if(!expression_2(state))
+        return 0;
+    return 1;
+}
+
+static guint
+expression_1(ParserState* state)
+{
+    LexerToken* token;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+    if(token->token_type == PL_EOS
+     ||token->token_type == T_ASSIGN)
+    {
+        l_roll_back(state->lexer);
+        return 0;
+    }
+    if(token->token_type == T_L_R_BRACKET)
+    {
+        state->depth_level++;
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_R_R_BRACKET)
+        {
+            state->depth_level--;
+            return 1;
+        }
+        else
+        //Expected ")" here...
+            return 0;
+    }
+    else if(token->token_type == T_L_S_BRACKET)
+    {
+        state->depth_level++;
+
+        /* Give round, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_Unknown), p_get_associativity(token), NULL, pf_do_round);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_R_S_BRACKET)
+        {
+            state->depth_level--;
+            return 1;
+        }
+        else
+        //Expected "]" here...
+            return 0;
+    }
+    else if(token->token_type == T_L_C_BRACKET)
+    {
+        state->depth_level++;
+
+        /* Give fraction, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_Unknown), p_get_associativity(token), NULL, pf_do_fraction);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_R_C_BRACKET)
+        {
+            state->depth_level--;
+            return 1;
+        }
+        else
+        //Expected "}" here...
+            return 0;
+    }
+    else if(token->token_type == T_ABS)
+    {
+        state->depth_level++;
+
+        /* Give abs, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_Unknown), p_get_associativity(token), NULL, pf_do_abs);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_ABS)
+        {
+            state->depth_level--;
+            return 1;
+        }
+        else
+        //Expected "|" here...
+            return 0;
+    }
+    else if(token->token_type == T_NOT)
+    {
+        /* NOT expression */
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_Not), p_get_associativity(token), NULL, pf_do_not);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_NUMBER)
+    {
+        /* NUMBER */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_constant);
+        p_insert_into_tree(state, node);
+
+        token = l_get_next_token(state->lexer);
+        l_roll_back(state->lexer);
+
+        if(token->token_type == T_FUNCTION
+         ||token->token_type == T_VARIABLE
+         ||token->token_type == T_SUB_NUMBER
+         ||token->token_type == T_ROOT
+         ||token->token_type == T_ROOT_3
+         ||token->token_type == T_ROOT_4)
+        {
+            /* NUMBER variable. */
+
+            node = p_create_node(state, NULL, p_make_precedence_p(state, P_Multiply), p_get_associativity_p(P_Multiply), NULL, pf_do_multiply);
+            p_insert_into_tree(state, node);
+
+            if(!variable(state))
+                return 0;
+            else
+                return 1;
+        }
+        else
+        {
+            return 1;
+        }
+    }
+    else if(token->token_type == T_L_FLOOR)
+    {
+        state->depth_level++;
+        /* Give floor, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+        node = p_create_node(state, NULL, p_make_precedence_p(state, P_Unknown), p_get_associativity_p(P_Unknown), NULL, pf_do_floor);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_R_FLOOR)
+        {
+            state->depth_level--;
+            return 1;
+        }
+        else
+        //Expected ⌋ here...
+            return 0;
+    }
+    else if(token->token_type == T_L_CEILING)
+    {
+        state->depth_level++;
+        /* Give ceiling, preference of P_Unknown aka 0, to keep it on the top of expression. */
+
+        node = p_create_node(state, NULL, p_make_precedence_p(state, P_Unknown), p_get_associativity_p(P_Unknown), NULL, pf_do_ceiling);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_R_CEILING)
+        {
+            state->depth_level--;
+            return 1;
+        }
+        else
+        //Expected ⌉ here...
+            return 0;
+    }
+    else if(token->token_type == T_SUBTRACT)
+    {
+        /* UnaryMinus expression */
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_UnaryMinus), p_get_associativity_p(P_UnaryMinus), NULL, pf_unary_minus);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_ADD)
+    {
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_NUMBER)
+        {
+            /* UnaryPlus expression */
+            /* Ignore T_ADD. It is not required. */
+
+            node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_constant);
+            p_insert_into_tree(state, node);
+            return 1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+    else
+    {
+        l_roll_back(state->lexer);
+        if(!variable(state))
+            return 0;
+        else
+            return 1;
+    }
+}
+
+static guint
+expression_2(ParserState* state)
+{
+    LexerToken* token;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+    if(token->token_type == T_L_R_BRACKET)
+    {
+        /* expression "(" expression ")" */
+
+        node = p_create_node(state, NULL, p_make_precedence_p(state, P_Multiply), p_get_associativity_p(P_Multiply), NULL, pf_do_multiply);
+        p_insert_into_tree(state, node);
+
+        state->depth_level++;
+        if(!expression(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_R_R_BRACKET)
+        {
+            state->depth_level--;
+            if(!expression_2(state))
+                return 0;
+            return 1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+    else if(token->token_type == T_POWER)
+    {
+        /* expression "^" expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_x_pow_y);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_SUP_NUMBER)
+    {
+        /* expression T_SUP_NUMBER */
+
+        node = p_create_node(state, NULL, p_make_precedence_p(state, P_Power), p_get_associativity_p(P_Power), NULL, pf_do_x_pow_y_int);
+        p_insert_into_tree(state, node);
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_NumberVariable), p_get_associativity_p(P_NumberVariable), NULL, pf_none);
+        p_insert_into_tree(state, node);
+
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_NSUP_NUMBER)
+    {
+        /* expression T_NSUP_NUMBER */
+
+        node = p_create_node(state, NULL, p_make_precedence_p(state, P_Power), p_get_associativity_p(P_Power), NULL, pf_do_x_pow_y_int);
+        p_insert_into_tree(state, node);
+
+        node = p_create_node(state, token, p_make_precedence_p(state, P_NumberVariable), p_get_associativity_p(P_NumberVariable), NULL, pf_none);
+        p_insert_into_tree(state, node);
+
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_FACTORIAL)
+    {
+        /* expression T_FACTORIAL */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_factorial);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_MULTIPLY)
+    {
+        /* expression T_MULTIPLY expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_multiply);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_PERCENTAGE)
+    {
+        /* expression % */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_percent);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_AND)
+    {
+        /* expression T_AND expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_and);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_OR)
+    {
+        /* expression T_OR expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_or);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_XOR)
+    {
+        /* expression T_XOR expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_xor);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_DIV)
+    {
+        /* expression T_DIV expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_divide);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_MOD)
+    {
+        /* expression T_MOD expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_mod);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_ADD)
+    {
+        /* expression T_ADD expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_add);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_PERCENTAGE)
+        {
+            //FIXME: This condition needs to be verified for all cases.. :(
+            if(node->right->precedence > P_Percentage)
+            {
+                node->precedence = P_Percentage;
+                node->evaluate = pf_do_add_percent;
+                return 1;
+            }
+            else
+            {
+                /* Assume '%' to be part of 'expression T_PERCENTAGE' statement. */
+                l_roll_back(state->lexer);
+                if(!expression_2(state))
+                    return 1;
+            }
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+        }
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_SUBTRACT)
+    {
+        /* expression T_SUBTRACT expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_subtract);
+        p_insert_into_tree(state, node);
+
+        if(!expression_1(state))
+            return 0;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_PERCENTAGE)
+        {
+            //FIXME: This condition needs to be verified for all cases.. :(
+            if(node->right->precedence > P_Percentage)
+            {
+                node->precedence = P_Percentage;
+                node->evaluate = pf_do_subtract_percent;
+                return 1;
+            }
+            else
+            {
+                /* Assume '%' to be part of 'expression T_PERCENTAGE' statement. */
+                l_roll_back(state->lexer);
+                if(!expression_2 (state))
+                    return 1;
+            }
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+        }
+        if(!expression_2(state))
+            return 0;
+        return 1;
+    }
+    else
+    {
+        l_roll_back(state->lexer);
+        return 1;
+    }
+}
+
+static guint
+variable(ParserState* state)
+{
+    LexerToken* token;
+    LexerToken* token_old;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+
+    if(token->token_type == T_FUNCTION)
+    {
+        token_old = token;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_SUP_NUMBER)
+        {
+            /* FUNCTION SUP_NUMBER expression */
+            /* Pass power as void * value. That will be taken care in pf_apply_func_with_powre. */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), token, pf_apply_func_with_power);
+            p_insert_into_tree_unary(state, node);
+
+            if(!expression(state))
+                return 0;
+            return 1;
+        }
+        else if(token->token_type == T_NSUP_NUMBER)
+        {
+            /* FUNCTION NSUP_NUMBER expression */
+            /* Pass power as void * value. That will be taken care in pf_apply_func_with_npowre. */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), token, pf_apply_func_with_npower);
+            p_insert_into_tree_unary(state, node);
+
+            if(!expression(state))
+                return 0;
+            return 1;
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+            /* FUNCTION expression */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), NULL, pf_apply_func);
+            p_insert_into_tree_unary(state, node);
+
+            if(!expression(state))
+                return 0;
+            return 1;
+        }
+    }
+    else if(token->token_type == T_SUB_NUMBER)
+    {
+        token_old = token;
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_ROOT)
+        {
+            /* SUB_NUM ROOT expression */
+            /* Pass SUB_NUM as void* value in node. pf_do_nth_root will take care of it. */
+
+            node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), token_old, pf_do_nth_root);
+            p_insert_into_tree_unary(state, node);
+
+            if(!expression (state))
+                return 0;
+            return 1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+    else if(token->token_type == T_ROOT)
+    {
+        /* ROOT expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_sqrt);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_ROOT_3)
+    {
+        /* ROOT_3 expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_root_3);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_ROOT_4)
+    {
+        /* ROOT_4 expression */
+
+        node = p_create_node(state, token, p_make_precedence_t(state, token->token_type), p_get_associativity(token), NULL, pf_do_root_4);
+        p_insert_into_tree_unary(state, node);
+
+        if(!expression(state))
+            return 0;
+        return 1;
+    }
+    else if(token->token_type == T_VARIABLE)
+    {
+        l_roll_back(state->lexer);
+        //TODO: unknown function ERROR for (T_VARIABLE T_SUP_NUMBER expression).
+        if(!term(state))
+            return 0;
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static guint
+term(ParserState* state)
+{
+    LexerToken* token;
+    LexerToken* token_old;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+    if(token->token_type == T_VARIABLE)
+    {
+        token_old = token;
+        /* Check if the token is a valid variable or not. */
+        if(!p_check_variable(state, token->string))
+        {
+            set_error(state, PARSER_ERR_UNKNOWN_VARIABLE, token->string);
+            return 0;
+        }
+        token = l_get_next_token(state->lexer);
+        if(token->token_type == T_SUP_NUMBER)
+        {
+            /* VARIABLE SUP_NUMBER */
+            /* Pass power as void* value. pf_get_variable_with_power will take care of it. */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), token, pf_get_variable_with_power);
+            p_insert_into_tree(state, node);
+
+        }
+        else
+        {
+            l_roll_back(state->lexer);
+            /* VARIABLE */
+
+            node = p_create_node(state, token_old, p_make_precedence_t(state, token_old->token_type), p_get_associativity(token_old), NULL, pf_get_variable);
+            p_insert_into_tree(state, node);
+
+        }
+        if(!term_2(state))
+            return 0;
+        return 1;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+static guint
+term_2(ParserState* state)
+{
+    LexerToken* token;
+    ParseNode* node;
+    token = l_get_next_token(state->lexer);
+    l_roll_back(state->lexer);
+    if(token->token_type == PL_EOS
+     ||token->token_type == T_ASSIGN)
+    {
+        return 1;
+    }
+    if(token->token_type == T_VARIABLE)
+    {
+        /* Insert multiply in between two distinct (variable). */
+
+        node = p_create_node(state, NULL, p_make_precedence_p(state, P_Multiply), p_get_associativity_p(P_Multiply), NULL, pf_do_multiply);
+        p_insert_into_tree(state, node);
+
+        if(!term(state))
+            return 0;
+        return 1;
+    }
+    else
+    {
+        return 1;
+    }
+}
+
+
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/index.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/index.html new file mode 100644 index 0000000..29cd26c --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/index.html @@ -0,0 +1,251 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeinformationCppcheck cannot find all the include files (use --check-config for details)
src/lexer.c
34variableScope398styleThe scope of the variable 'count' can be reduced.
125unreadVariable563styleVariable 'type' is assigned a value that is never used.
533variableScope398styleThe scope of the variable 'token' can be reduced.
src/mate-calc-cmd.c
71variableScope398styleThe scope of the variable 'line' can be reduced.
src/mate-calc-resources.c
9unusedStructMember563styleunion member 'Anonymous0::alignment' is never used.
9unusedStructMember563styleunion member 'Anonymous0::ptr' is never used.
src/mate-calc.c
127variableScope398styleThe scope of the variable 'arg' can be reduced.
src/math-buttons.c
472unreadVariable563styleVariable 'valid' is assigned a value that is never used.
src/math-equation.c
828variableScope398styleThe scope of the variable 'text' can be reduced.
1303variableScope398styleThe scope of the variable 'next_factor' can be reduced.
src/math-preferences.c
150unreadVariable563styleVariable 'valid' is assigned a value that is never used.
src/mp-convert.c
199invalidscanf119warningsscanf() without field width limits can crash with huge input data.
229variableScope398styleThe scope of the variable 'numerators' can be reduced.
230variableScope398styleThe scope of the variable 'denominators' can be reduced.
317knownConditionTrueFalse398styleThe comparison 'multiplier != 0' is always false.
src/mp-equation.c
292variableScope398styleThe scope of the variable 'err' can be reduced.
src/parser.c
326variableScope398styleThe scope of the variable 'c' can be reduced.
327variableScope398styleThe scope of the variable 'buffer' can be reduced.
541variableScope398styleThe scope of the variable 'token_old' can be reduced.
542variableScope398styleThe scope of the variable 'node' can be reduced.
1164variableScope398styleThe scope of the variable 'token_old' can be reduced.
1165variableScope398styleThe scope of the variable 'node' can be reduced.
1209variableScope398styleThe scope of the variable 'node' can be reduced.
src/parserfunc.c
171variableScope398styleThe scope of the variable 'c' can be reduced.
172variableScope398styleThe scope of the variable 'buffer' can be reduced.
227variableScope398styleThe scope of the variable 'c' can be reduced.
228variableScope398styleThe scope of the variable 'buffer' can be reduced.
src/unit-manager.c
189variableScope398styleThe scope of the variable 'u' can be reduced.
208variableScope398styleThe scope of the variable 'u' can be reduced.
+
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/stats.html b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/stats.html new file mode 100644 index 0000000..65bc607 --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/stats.html @@ -0,0 +1,179 @@ + + + + + + Cppcheck - HTML report - mate-calc + + + + + +
+ + + +
+

Top 10 files for warning severity, total findings: 1
+   1  src/mp-convert.c
+

+

Top 10 files for style severity, total findings: 28
+   7  src/parser.c
+   4  src/parserfunc.c
+   3  src/mp-convert.c
+   3  src/lexer.c
+   2  src/unit-manager.c
+   2  src/math-equation.c
+   2  src/mate-calc-resources.c
+   1  src/mp-equation.c
+   1  src/math-preferences.c
+   1  src/math-buttons.c
+

+ +
+ +
+ + diff --git a/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/style.css b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2022-10-30-114002-2295-cppcheck@9f60058d4b7d_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} -- cgit v1.2.1