~mshinke/nvdajp/MiscellaneousDependencies

« back to all changes in this revision

Viewing changes to include/liblouis/liblouis/transcommon.ci

  • Committer: Masataka Shinke
  • Date: 2012-01-12 20:01:32 UTC
  • mfrom: (26.1.42 miscdep)
  • Revision ID: mshinke@users.sourceforge.jp-20120112200132-fvksmjulcjdzu5mk
mergedĀ lp:~nishimotz/nvdajp/MiscellaneousDependenciesĀ 68

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file contains code common to the translator and back-translator. 
 
2
* It is included immediately after the headr files. */
 
3
 
 
4
/* liblouis Braille Translation and Back-Translation 
 
5
Library
 
6
 
 
7
   Based on the Linux screenreader BRLTTY, copyright (C) 1999-2006 by
 
8
   The BRLTTY Team
 
9
 
 
10
   Copyright (C) 2004, 2005, 2006
 
11
   ViewPlus Technologies, Inc. www.viewplus.com
 
12
   and
 
13
   JJB Software, Inc. www.jjb-software.com
 
14
   All rights reserved
 
15
 
 
16
   This file is free software; you can redistribute it and/or modify it
 
17
   under the terms of the Lesser or Library GNU General Public License 
 
18
   as published by the
 
19
   Free Software Foundation; either version 3, or (at your option) any
 
20
   later version.
 
21
 
 
22
   This file is distributed in the hope that it will be useful, but
 
23
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
24
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 
25
   Library GNU General Public License for more details.
 
26
 
 
27
   You should have received a copy of the Library GNU General Public 
 
28
   License along with this program; see the file COPYING.  If not, write to
 
29
   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 
30
   Boston, MA 02110-1301, USA.
 
31
 
 
32
   Maintained by John J. Boyer john.boyer@jjb-software.com
 
33
   */
 
34
 
 
35
/*additional bits in typebuf*/
 
36
#define capsemph 0x8000
 
37
#define EMPHASIS 0x0f
 
38
#define STARTWORD 0x4000
 
39
#define FIRSTWORD 0x2000
 
40
#define SYLLABLEMARKS 0x00c0
 
41
#define INTERNALMARKS 0xff00
 
42
 
 
43
static const TranslationTableHeader *table;
 
44
static int src, srcmax;
 
45
static int dest, destmax;
 
46
static int mode;
 
47
static int currentPass = 1;
 
48
static const widechar *currentInput;
 
49
static widechar *passbuf1 = NULL;
 
50
static widechar *passbuf2 = NULL;
 
51
static widechar *currentOutput;
 
52
static int *srcMapping = NULL;
 
53
static unsigned short *typebuf = NULL;
 
54
static unsigned char *srcSpacing = NULL;
 
55
static unsigned char *destSpacing = NULL;
 
56
static int haveEmphasis = 0;
 
57
static TranslationTableOpcode transOpcode;
 
58
static TranslationTableOpcode prevTransOpcode;
 
59
static const TranslationTableRule *transRule;
 
60
static int transCharslen;
 
61
static int checkAttr (const widechar c,
 
62
                      const TranslationTableCharacterAttributes a, int nm);
 
63
static int putCharacter (widechar c);
 
64
static int makeCorrections (void);
 
65
static int passDoTest (void);
 
66
static int passDoAction (void);
 
67
static int passVariables[NUMVAR];
 
68
static int passCharDots;
 
69
static int passSrc;
 
70
static widechar const *passInstructions;
 
71
static int passIC;              /*Instruction counter */
 
72
static int startMatch;
 
73
static int endMatch;
 
74
static int startReplace;
 
75
static int endReplace;
 
76
static int realInlen;
 
77
static int srcIncremented;
 
78
static int *outputPositions;
 
79
static int *inputPositions;
 
80
static int cursorPosition;
 
81
static int cursorStatus;
 
82
 
 
83
static TranslationTableCharacter *
 
84
findCharOrDots (widechar c, int m)
 
85
{
 
86
/*Look up character or dot pattern in the appropriate  
 
87
* table. */
 
88
  static TranslationTableCharacter noChar =
 
89
    { 0, 0, 0, CTC_Space, 32, 32, 32 };
 
90
  static TranslationTableCharacter noDots =
 
91
    { 0, 0, 0, CTC_Space, B16, B16, B16 };
 
92
  TranslationTableCharacter *notFound;
 
93
  TranslationTableCharacter *character;
 
94
  TranslationTableOffset bucket;
 
95
  unsigned long int makeHash = (unsigned long int) c % HASHNUM;
 
96
  if (m == 0)
 
97
    {
 
98
      bucket = table->characters[makeHash];
 
99
      notFound = &noChar;
 
100
    }
 
101
  else
 
102
    {
 
103
      bucket = table->dots[makeHash];
 
104
      notFound = &noDots;
 
105
    }
 
106
  while (bucket)
 
107
    {
 
108
      character = (TranslationTableCharacter *) & table->ruleArea[bucket];
 
109
      if (character->realchar == c)
 
110
        return character;
 
111
      bucket = character->next;
 
112
    }
 
113
  notFound->realchar = notFound->uppercase = notFound->lowercase = c;
 
114
  return notFound;
 
115
}
 
116
 
 
117
static int
 
118
checkAttr (const widechar c, const TranslationTableCharacterAttributes
 
119
           a, int m)
 
120
{
 
121
  static widechar prevc = 0;
 
122
  static TranslationTableCharacterAttributes preva = 0;
 
123
  if (c != prevc)
 
124
    {
 
125
      preva = (findCharOrDots (c, m))->attributes;
 
126
      prevc = c;
 
127
    }
 
128
  return ((preva & a) ? 1 : 0);
 
129
}
 
130
 
 
131
static int
 
132
findAttribOrSwapRules (void)
 
133
{
 
134
  int save_transCharslen = transCharslen;
 
135
  const TranslationTableRule *save_transRule = transRule;
 
136
  TranslationTableOpcode save_transOpcode = transOpcode;
 
137
  TranslationTableOffset ruleOffset;
 
138
  ruleOffset = table->attribOrSwapRules[currentPass];
 
139
  transCharslen = 0;
 
140
  while (ruleOffset)
 
141
    {
 
142
      transRule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
143
      transOpcode = transRule->opcode;
 
144
      if (passDoTest ())
 
145
        return 1;
 
146
      ruleOffset = transRule->charsnext;
 
147
    }
 
148
  transCharslen = save_transCharslen;
 
149
  transRule = save_transRule;
 
150
  transOpcode = save_transOpcode;
 
151
  return 0;
 
152
}
 
153
 
 
154
static int
 
155
compareChars (const widechar * address1, const widechar * address2, int
 
156
              count, int m)
 
157
{
 
158
  int k;
 
159
  if (!count)
 
160
    return 0;
 
161
  for (k = 0; k < count; k++)
 
162
    if ((findCharOrDots (address1[k], m))->lowercase !=
 
163
        (findCharOrDots (address2[k], m))->lowercase)
 
164
      return 0;
 
165
  return 1;
 
166
}
 
167
 
 
168
static int
 
169
makeCorrections (void)
 
170
{
 
171
  int k;
 
172
  if (!table->corrections)
 
173
    return 1;
 
174
  src = 0;
 
175
  dest = 0;
 
176
  srcIncremented = 1;
 
177
  for (k = 0; k < NUMVAR; k++)
 
178
    passVariables[k] = 0;
 
179
  while (src < srcmax)
 
180
    {
 
181
      int length = srcmax - src;
 
182
      const TranslationTableCharacter *character = findCharOrDots
 
183
        (currentInput[src], 0);
 
184
      const TranslationTableCharacter *character2;
 
185
      int tryThis = 0;
 
186
      if (!findAttribOrSwapRules ())
 
187
        while (tryThis < 3)
 
188
          {
 
189
            TranslationTableOffset ruleOffset = 0;
 
190
            unsigned long int makeHash = 0;
 
191
            switch (tryThis)
 
192
              {
 
193
              case 0:
 
194
                if (!(length >= 2))
 
195
                  break;
 
196
                makeHash = (unsigned long int) character->lowercase << 8;
 
197
                character2 = findCharOrDots (currentInput[src + 1], 0);
 
198
                makeHash += (unsigned long int) character2->lowercase;
 
199
                makeHash %= HASHNUM;
 
200
                ruleOffset = table->forRules[makeHash];
 
201
                break;
 
202
              case 1:
 
203
                if (!(length >= 1))
 
204
                  break;
 
205
                length = 1;
 
206
                ruleOffset = character->otherRules;
 
207
                break;
 
208
              case 2:           /*No rule found */
 
209
                transOpcode = CTO_Always;
 
210
                ruleOffset = 0;
 
211
                break;
 
212
              }
 
213
            while (ruleOffset)
 
214
              {
 
215
                transRule =
 
216
                  (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
217
                transOpcode = transRule->opcode;
 
218
                transCharslen = transRule->charslen;
 
219
                if (tryThis == 1 || (transCharslen <= length &&
 
220
                                     compareChars (&transRule->
 
221
                                                   charsdots[0],
 
222
                                                   &currentInput[src],
 
223
                                                   transCharslen, 0)))
 
224
                  {
 
225
                    if (srcIncremented && transOpcode == CTO_Correct &&
 
226
                        passDoTest ())
 
227
                      {
 
228
                        tryThis = 4;
 
229
                        break;
 
230
                      }
 
231
                  }
 
232
                ruleOffset = transRule->charsnext;
 
233
              }
 
234
            tryThis++;
 
235
          }
 
236
      srcIncremented = 1;
 
237
 
 
238
      switch (transOpcode)
 
239
        {
 
240
        case CTO_Always:
 
241
          if (dest >= destmax)
 
242
            goto failure;
 
243
          srcMapping[dest] = srcMapping[src];
 
244
          currentOutput[dest++] = currentInput[src++];
 
245
          break;
 
246
        case CTO_Correct:
 
247
          if (!passDoAction ())
 
248
            goto failure;
 
249
          if (endReplace == src)
 
250
            srcIncremented = 0;
 
251
          src = endReplace;
 
252
          break;
 
253
        default:
 
254
          break;
 
255
        }
 
256
    }
 
257
failure:
 
258
  realInlen = src;
 
259
  return 1;
 
260
}
 
261
 
 
262
static int
 
263
matchcurrentInput (void)
 
264
{
 
265
  int k;
 
266
  int kk = passSrc;
 
267
  for (k = passIC + 2; k < passIC + 2 + passInstructions[passIC + 1]; k++)
 
268
    if (passInstructions[k] != currentInput[kk++])
 
269
      return 0;
 
270
  return 1;
 
271
}
 
272
 
 
273
static int
 
274
swapTest (int swapIC, int *callSrc)
 
275
{
 
276
  int curLen;
 
277
  int curTest;
 
278
  int curSrc = *callSrc;
 
279
  TranslationTableOffset swapRuleOffset;
 
280
  TranslationTableRule *swapRule;
 
281
  swapRuleOffset =
 
282
    (passInstructions[swapIC + 1] << 16) | passInstructions[swapIC + 2];
 
283
  swapRule = (TranslationTableRule *) & table->ruleArea[swapRuleOffset];
 
284
  for (curLen = 0; curLen < passInstructions[swapIC + 3]; curLen++)
 
285
    {
 
286
      if (swapRule->opcode == CTO_SwapDd)
 
287
        {
 
288
          for (curTest = 1; curTest < swapRule->charslen; curTest += 2)
 
289
            {
 
290
              if (currentInput[curSrc] == swapRule->charsdots[curTest])
 
291
                break;
 
292
            }
 
293
        }
 
294
      else
 
295
        {
 
296
          for (curTest = 0; curTest < swapRule->charslen; curTest++)
 
297
            {
 
298
              if (currentInput[curSrc] == swapRule->charsdots[curTest])
 
299
                break;
 
300
            }
 
301
        }
 
302
      if (curTest >= swapRule->charslen)
 
303
        return 0;
 
304
      curSrc++;
 
305
    }
 
306
  if (passInstructions[swapIC + 3] == passInstructions[swapIC + 4])
 
307
    {
 
308
      *callSrc = curSrc;
 
309
      return 1;
 
310
    }
 
311
  while (curLen < passInstructions[swapIC + 4])
 
312
    {
 
313
      if (swapRule->opcode == CTO_SwapDd)
 
314
        {
 
315
          for (curTest = 1; curTest < swapRule->charslen; curTest += 2)
 
316
            {
 
317
              if (currentInput[curSrc] == swapRule->charsdots[curTest])
 
318
                break;
 
319
            }
 
320
        }
 
321
      else
 
322
        {
 
323
          for (curTest = 0; curTest < swapRule->charslen; curTest++)
 
324
            {
 
325
              if (currentInput[curSrc] == swapRule->charsdots[curTest])
 
326
                break;
 
327
            }
 
328
        }
 
329
      if (curTest >= swapRule->charslen)
 
330
        {
 
331
          *callSrc = curSrc;
 
332
          return 1;
 
333
        }
 
334
      curSrc++;
 
335
      curLen++;
 
336
    }
 
337
  *callSrc = curSrc;
 
338
  return 1;
 
339
}
 
340
 
 
341
static int
 
342
swapReplace (int start, int end)
 
343
{
 
344
  TranslationTableOffset swapRuleOffset;
 
345
  TranslationTableRule *swapRule;
 
346
  widechar *replacements;
 
347
  int curRep;
 
348
  int curPos;
 
349
  int curTest;
 
350
  int curSrc;
 
351
  swapRuleOffset =
 
352
    (passInstructions[passIC + 1] << 16) | passInstructions[passIC + 2];
 
353
  swapRule = (TranslationTableRule *) & table->ruleArea[swapRuleOffset];
 
354
  replacements = &swapRule->charsdots[swapRule->charslen];
 
355
  for (curSrc = start; curSrc < end; curSrc++)
 
356
    {
 
357
      for (curTest = 0; curTest < swapRule->charslen; curTest++)
 
358
        if (currentInput[curSrc] == swapRule->charsdots[curTest])
 
359
          break;
 
360
      if (curTest == swapRule->charslen)
 
361
        continue;
 
362
      curPos = 0;
 
363
      for (curRep = 0; curRep < curTest; curRep++)
 
364
        if (swapRule->opcode == CTO_SwapCc)
 
365
          curPos++;
 
366
        else
 
367
          curPos += replacements[curPos];
 
368
      if (swapRule->opcode == CTO_SwapCc)
 
369
        {
 
370
          if ((dest + 1) >= srcmax)
 
371
            return 0;
 
372
          srcMapping[dest] = srcMapping[curSrc];
 
373
          currentOutput[dest++] = replacements[curPos];
 
374
        }
 
375
      else
 
376
        {
 
377
          int k;
 
378
          if ((dest + replacements[curPos] - 1) >= destmax)
 
379
            return 0;
 
380
          for (k = dest + replacements[curPos] - 1; k >= dest; --k)
 
381
            srcMapping[k] = srcMapping[curSrc];
 
382
          memcpy (&currentOutput[dest], &replacements[curPos + 1],
 
383
                  (replacements[curPos]) * CHARSIZE);
 
384
          dest += replacements[curPos] - 1;
 
385
        }
 
386
    }
 
387
  return 1;
 
388
}
 
389
 
 
390
static TranslationTableRule *groupingRule;
 
391
static widechar groupingOp;
 
392
 
 
393
static int
 
394
replaceGrouping (void)
 
395
{
 
396
  widechar startCharDots = groupingRule->charsdots[2 * passCharDots];
 
397
  widechar endCharDots = groupingRule->charsdots[2 * passCharDots + 1];
 
398
  widechar *curin = (widechar *) currentInput;
 
399
  int curPos;
 
400
  int level = 0;
 
401
  TranslationTableOffset replaceOffset = passInstructions[passIC + 1] <<
 
402
    16 | (passInstructions[passIC + 2] & 0xff);
 
403
  TranslationTableRule *replaceRule = (TranslationTableRule *) &
 
404
    table->ruleArea[replaceOffset];
 
405
  widechar replaceStart = replaceRule->charsdots[2 * passCharDots];
 
406
  widechar replaceEnd = replaceRule->charsdots[2 * passCharDots + 1];
 
407
  if (groupingOp == pass_groupstart)
 
408
    {
 
409
      curin[startReplace] = replaceStart;
 
410
      for (curPos = startReplace + 1; curPos < srcmax; curPos++)
 
411
        {
 
412
          if (currentInput[curPos] == startCharDots)
 
413
            level--;
 
414
          if (currentInput[curPos] == endCharDots)
 
415
            level++;
 
416
          if (level == 1)
 
417
            break;
 
418
        }
 
419
      if (curPos == srcmax)
 
420
        return 0;
 
421
      curin[curPos] = replaceEnd;
 
422
    }
 
423
  else
 
424
    {
 
425
      if (transOpcode == CTO_Context)
 
426
        {
 
427
          startCharDots = groupingRule->charsdots[2];
 
428
          endCharDots = groupingRule->charsdots[3];
 
429
          replaceStart = replaceRule->charsdots[2];
 
430
          replaceEnd = replaceRule->charsdots[3];
 
431
        }
 
432
      currentOutput[dest] = replaceEnd;
 
433
      for (curPos = dest - 1; curPos >= 0; curPos--)
 
434
        {
 
435
          if (currentOutput[curPos] == endCharDots)
 
436
            level--;
 
437
          if (currentOutput[curPos] == startCharDots)
 
438
            level++;
 
439
          if (level == 1)
 
440
            break;
 
441
        }
 
442
      if (curPos < 0)
 
443
        return 0;
 
444
      currentOutput[curPos] = replaceStart;
 
445
      dest++;
 
446
    }
 
447
  return 1;
 
448
}
 
449
 
 
450
static int
 
451
removeGrouping (void)
 
452
{
 
453
  widechar startCharDots = groupingRule->charsdots[2 * passCharDots];
 
454
  widechar endCharDots = groupingRule->charsdots[2 * passCharDots + 1];
 
455
  widechar *curin = (widechar *) currentInput;
 
456
  int curPos;
 
457
  int level = 0;
 
458
  if (groupingOp == pass_groupstart)
 
459
    {
 
460
      for (curPos = startReplace + 1; curPos < srcmax; curPos++)
 
461
        {
 
462
          if (currentInput[curPos] == startCharDots)
 
463
            level--;
 
464
          if (currentInput[curPos] == endCharDots)
 
465
            level++;
 
466
          if (level == 1)
 
467
            break;
 
468
        }
 
469
      if (curPos == srcmax)
 
470
        return 0;
 
471
      curPos++;
 
472
      for (; curPos < srcmax; curPos++)
 
473
        curin[curPos - 1] = curin[curPos];
 
474
      srcmax--;
 
475
    }
 
476
  else
 
477
    {
 
478
      for (curPos = dest - 1; curPos >= 0; curPos--)
 
479
        {
 
480
          if (currentOutput[curPos] == endCharDots)
 
481
            level--;
 
482
          if (currentOutput[curPos] == startCharDots)
 
483
            level++;
 
484
          if (level == 1)
 
485
            break;
 
486
        }
 
487
      if (curPos < 0)
 
488
        return 0;
 
489
      curPos++;
 
490
      for (; curPos < dest; curPos++)
 
491
        currentOutput[curPos - 1] = currentOutput[curPos];
 
492
      dest--;
 
493
    }
 
494
  return 1;
 
495
}
 
496
 
 
497
static int searchIC;
 
498
static int searchSrc;
 
499
 
 
500
static int
 
501
doPassSearch (void)
 
502
{
 
503
  int level = 0;
 
504
  int k, kk;
 
505
  int not = 0;
 
506
  TranslationTableOffset ruleOffset;
 
507
  TranslationTableRule *rule;
 
508
  TranslationTableCharacterAttributes attributes;
 
509
  int stepper = passSrc;
 
510
  while (stepper < srcmax)
 
511
    {
 
512
      searchIC = passIC + 1;
 
513
      searchSrc = stepper;
 
514
      while (searchIC < transRule->dotslen)
 
515
        {
 
516
          int itsTrue = 1;
 
517
          if (searchSrc > srcmax)
 
518
            return 0;
 
519
          switch (passInstructions[searchIC])
 
520
            {
 
521
            case pass_lookback:
 
522
              searchSrc -= passInstructions[searchIC + 1];
 
523
              if (searchSrc < 0)
 
524
                searchSrc = 0;
 
525
              searchIC += 2;
 
526
              break;
 
527
            case pass_not:
 
528
              not = 1;
 
529
              searchIC++;
 
530
              continue;
 
531
            case pass_string:
 
532
            case pass_dots:
 
533
              kk = searchSrc;
 
534
              for (k = searchIC + 2;
 
535
                   k < searchIC + 2 + passInstructions[searchIC + 1]; k++)
 
536
                if (passInstructions[k] != currentInput[kk++])
 
537
                  {
 
538
                    itsTrue = 0;
 
539
                    break;
 
540
                  }
 
541
              searchSrc += passInstructions[searchIC + 1];
 
542
              searchIC += passInstructions[searchIC + 1] + 2;
 
543
              break;
 
544
            case pass_startReplace:
 
545
              searchIC++;
 
546
              break;
 
547
            case pass_endReplace:
 
548
              searchIC++;
 
549
              break;
 
550
            case pass_attributes:
 
551
              attributes =
 
552
                (passInstructions[searchIC + 1] << 16) |
 
553
                passInstructions[searchIC + 2];
 
554
              for (k = 0; k < passInstructions[searchIC + 3]; k++)
 
555
                {
 
556
                  itsTrue =
 
557
                    (((findCharOrDots (currentInput[searchSrc++],
 
558
                                       passCharDots)->
 
559
                       attributes & attributes)) ? 1 : 0);
 
560
                  if (!itsTrue)
 
561
                    break;
 
562
                }
 
563
              if (itsTrue)
 
564
                for (k = passInstructions[searchIC + 3]; k <
 
565
                     passInstructions[searchIC + 4]; k++)
 
566
                  {
 
567
                    if (!
 
568
                        (findCharOrDots (currentInput[searchSrc],
 
569
                                         passCharDots)->
 
570
                         attributes & attributes))
 
571
                      break;
 
572
                    searchSrc++;
 
573
                  }
 
574
              searchIC += 5;
 
575
              break;
 
576
            case pass_groupstart:
 
577
            case pass_groupend:
 
578
              ruleOffset = (passInstructions[searchIC + 1] << 16) |
 
579
                passInstructions[searchIC + 2];
 
580
              rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
581
              if (passInstructions[searchIC] == pass_groupstart)
 
582
                itsTrue =
 
583
                  (currentInput[searchSrc] == rule->charsdots[2 *
 
584
                                                              passCharDots]) ?
 
585
                  1 : 0;
 
586
              else
 
587
                itsTrue =
 
588
                  (currentInput[searchSrc] == rule->charsdots[2 *
 
589
                                                              passCharDots +
 
590
                                                              1]) ? 1 : 0;
 
591
              if (groupingRule != NULL && groupingOp == pass_groupstart
 
592
                  && rule == groupingRule)
 
593
                {
 
594
                  if (currentInput[searchSrc] == rule->charsdots[2 *
 
595
                                                                 passCharDots])
 
596
                    level--;
 
597
                  else if (currentInput[searchSrc] ==
 
598
                           rule->charsdots[2 * passCharDots + 1])
 
599
                    level++;
 
600
                }
 
601
              searchSrc++;
 
602
              searchIC += 3;
 
603
              break;
 
604
            case pass_swap:
 
605
              itsTrue = swapTest (searchIC, &searchSrc);
 
606
              searchIC += 5;
 
607
              break;
 
608
            case pass_eq:
 
609
              if (passVariables[passInstructions[searchIC + 1]] !=
 
610
                  passInstructions[searchIC + 2])
 
611
                itsTrue = 0;
 
612
              searchIC += 3;
 
613
              break;
 
614
            case pass_lt:
 
615
              if (passVariables[passInstructions[searchIC + 1]] >=
 
616
                  passInstructions[searchIC + 2])
 
617
                itsTrue = 0;
 
618
              searchIC += 3;
 
619
              break;
 
620
            case pass_gt:
 
621
              if (passVariables[passInstructions[searchIC + 1]] <=
 
622
                  passInstructions[searchIC + 2])
 
623
                itsTrue = 0;
 
624
              searchIC += 3;
 
625
              break;
 
626
            case pass_lteq:
 
627
              if (passVariables[passInstructions[searchIC + 1]] >
 
628
                  passInstructions[searchIC + 2])
 
629
                itsTrue = 0;
 
630
              searchIC += 3;
 
631
              break;
 
632
            case pass_gteq:
 
633
              if (passVariables[passInstructions[searchIC + 1]] <
 
634
                  passInstructions[searchIC + 2])
 
635
                itsTrue = 0;
 
636
              searchIC += 3;
 
637
              break;
 
638
            case pass_endTest:
 
639
              if (itsTrue)
 
640
                {
 
641
                  if ((groupingRule && level == 1) || !groupingRule)
 
642
                    return 1;
 
643
                }
 
644
              searchIC = transRule->dotslen;
 
645
              break;
 
646
            default:
 
647
              break;
 
648
            }
 
649
          if ((!not && !itsTrue) || (not && itsTrue))
 
650
            break;
 
651
          not = 0;
 
652
        }
 
653
      stepper++;
 
654
    }
 
655
  return 0;
 
656
}
 
657
 
 
658
static int
 
659
passDoTest (void)
 
660
{
 
661
  int k;
 
662
  int not = 0;
 
663
  TranslationTableOffset ruleOffset;
 
664
  TranslationTableRule *rule;
 
665
  TranslationTableCharacterAttributes attributes;
 
666
  groupingRule = NULL;
 
667
  passSrc = src;
 
668
  passInstructions = &transRule->charsdots[transCharslen];
 
669
  passIC = 0;
 
670
  startMatch = endMatch = passSrc;
 
671
  startReplace = endReplace = -1;
 
672
  if (transOpcode == CTO_Context || transOpcode == CTO_Correct)
 
673
    passCharDots = 0;
 
674
  else
 
675
    passCharDots = 1;
 
676
  while (passIC < transRule->dotslen)
 
677
    {
 
678
      int itsTrue = 1;
 
679
      if (passSrc > srcmax)
 
680
        return 0;
 
681
      switch (passInstructions[passIC])
 
682
        {
 
683
        case pass_first:
 
684
          if (passSrc != 0)
 
685
            itsTrue = 0;
 
686
          passIC++;
 
687
          break;
 
688
        case pass_last:
 
689
          if (passSrc != (srcmax - 1))
 
690
            itsTrue = 0;
 
691
          passIC++;
 
692
          break;
 
693
        case pass_lookback:
 
694
          passSrc -= passInstructions[passIC + 1];
 
695
          if (passSrc < 0)
 
696
            passSrc = 0;
 
697
          passIC += 2;
 
698
          break;
 
699
        case pass_not:
 
700
          not = 1;
 
701
          passIC++;
 
702
          continue;
 
703
        case pass_string:
 
704
        case pass_dots:
 
705
          itsTrue = matchcurrentInput ();
 
706
          passSrc += passInstructions[passIC + 1];
 
707
          passIC += passInstructions[passIC + 1] + 2;
 
708
          break;
 
709
        case pass_startReplace:
 
710
          startReplace = passSrc;
 
711
          passIC++;
 
712
          break;
 
713
        case pass_endReplace:
 
714
          endReplace = passSrc;
 
715
          passIC++;
 
716
          break;
 
717
        case pass_attributes:
 
718
          attributes =
 
719
            (passInstructions[passIC + 1] << 16) | passInstructions[passIC +
 
720
                                                                    2];
 
721
          for (k = 0; k < passInstructions[passIC + 3]; k++)
 
722
            {
 
723
              itsTrue =
 
724
                (((findCharOrDots (currentInput[passSrc++],
 
725
                                   passCharDots)->
 
726
                   attributes & attributes)) ? 1 : 0);
 
727
              if (!itsTrue)
 
728
                break;
 
729
            }
 
730
          if (itsTrue)
 
731
            for (k = passInstructions[passIC + 3]; k <
 
732
                 passInstructions[passIC + 4]; k++)
 
733
              {
 
734
                if (!
 
735
                    (findCharOrDots (currentInput[passSrc],
 
736
                                     passCharDots)->attributes & attributes))
 
737
                  break;
 
738
                passSrc++;
 
739
              }
 
740
          passIC += 5;
 
741
          break;
 
742
        case pass_groupstart:
 
743
        case pass_groupend:
 
744
          ruleOffset = (passInstructions[passIC + 1] << 16) |
 
745
            passInstructions[passIC + 2];
 
746
          rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
747
          if (passIC == 0 || (passIC > 0 && passInstructions[passIC - 1] ==
 
748
                              pass_startReplace))
 
749
            {
 
750
              groupingRule = rule;
 
751
              groupingOp = passInstructions[passIC];
 
752
            }
 
753
          if (passInstructions[passIC] == pass_groupstart)
 
754
            itsTrue = (currentInput[passSrc] == rule->charsdots[2 *
 
755
                                                                passCharDots])
 
756
              ? 1 : 0;
 
757
          else
 
758
            itsTrue = (currentInput[passSrc] == rule->charsdots[2 *
 
759
                                                                passCharDots +
 
760
                                                                1]) ? 1 : 0;
 
761
          passSrc++;
 
762
          passIC += 3;
 
763
          break;
 
764
        case pass_swap:
 
765
          itsTrue = swapTest (passIC, &passSrc);
 
766
          passIC += 5;
 
767
          break;
 
768
        case pass_eq:
 
769
          if (passVariables[passInstructions[passIC + 1]] !=
 
770
              passInstructions[passIC + 2])
 
771
            itsTrue = 0;
 
772
          passIC += 3;
 
773
          break;
 
774
        case pass_lt:
 
775
          if (passVariables[passInstructions[passIC + 1]] >=
 
776
              passInstructions[passIC + 2])
 
777
            itsTrue = 0;
 
778
          passIC += 3;
 
779
          break;
 
780
        case pass_gt:
 
781
          if (passVariables[passInstructions[passIC + 1]] <=
 
782
              passInstructions[passIC + 2])
 
783
            itsTrue = 0;
 
784
          passIC += 3;
 
785
          break;
 
786
        case pass_lteq:
 
787
          if (passVariables[passInstructions[passIC + 1]] >
 
788
              passInstructions[passIC + 2])
 
789
            itsTrue = 0;
 
790
          passIC += 3;
 
791
          break;
 
792
        case pass_gteq:
 
793
          if (passVariables[passInstructions[passIC + 1]] <
 
794
              passInstructions[passIC + 2])
 
795
            itsTrue = 0;
 
796
          passIC += 3;
 
797
          break;
 
798
        case pass_search:
 
799
          itsTrue = doPassSearch ();
 
800
          if ((!not && !itsTrue) || (not && itsTrue))
 
801
            return 0;
 
802
          passIC = searchIC;
 
803
          passSrc = searchSrc;
 
804
        case pass_endTest:
 
805
          passIC++;
 
806
          endMatch = passSrc;
 
807
          if (startReplace == -1)
 
808
            {
 
809
              startReplace = startMatch;
 
810
              endReplace = endMatch;
 
811
            }
 
812
          return 1;
 
813
          break;
 
814
        default:
 
815
          return 0;
 
816
        }
 
817
      if ((!not && !itsTrue) || (not && itsTrue))
 
818
        return 0;
 
819
      not = 0;
 
820
    }
 
821
  return 0;
 
822
}
 
823
 
 
824
static int
 
825
passDoAction (void)
 
826
{
 
827
  int k;
 
828
  TranslationTableOffset ruleOffset;
 
829
  TranslationTableRule *rule;
 
830
  if ((dest + startReplace - startMatch) > destmax)
 
831
    return 0;
 
832
  if (transOpcode != CTO_Context)
 
833
    memmove (&srcMapping[dest], &srcMapping[startMatch],
 
834
             (startReplace - startMatch) * sizeof (int));
 
835
  for (k = startMatch; k < startReplace; k++)
 
836
    if (transOpcode == CTO_Context)
 
837
      {
 
838
        if (!putCharacter (currentInput[k]))
 
839
          return 0;
 
840
      }
 
841
    else
 
842
      currentOutput[dest++] = currentInput[k];
 
843
  while (passIC < transRule->dotslen)
 
844
    switch (passInstructions[passIC])
 
845
      {
 
846
      case pass_string:
 
847
      case pass_dots:
 
848
        if ((dest + passInstructions[passIC + 1]) > destmax)
 
849
          return 0;
 
850
        for (k = 0; k < passInstructions[passIC + 1]; ++k)
 
851
          srcMapping[dest + k] = startMatch;
 
852
        memcpy (&currentOutput[dest], &passInstructions[passIC + 2],
 
853
                passInstructions[passIC + 1] * CHARSIZE);
 
854
        dest += passInstructions[passIC + 1];
 
855
        passIC += passInstructions[passIC + 1] + 2;
 
856
        break;
 
857
      case pass_eq:
 
858
        passVariables[passInstructions[passIC + 1]] =
 
859
          passInstructions[passIC + 2];
 
860
        passIC += 3;
 
861
        break;
 
862
      case pass_hyphen:
 
863
        passVariables[passInstructions[passIC + 1]]--;
 
864
        if (passVariables[passInstructions[passIC + 1]] < 0)
 
865
          passVariables[passInstructions[passIC + 1]] = 0;
 
866
        passIC += 2;
 
867
        break;
 
868
      case pass_plus:
 
869
        passVariables[passInstructions[passIC + 1]]++;
 
870
        passIC += 2;
 
871
        break;
 
872
      case pass_groupstart:
 
873
        ruleOffset = (passInstructions[passIC + 1] << 16) |
 
874
          passInstructions[passIC + 2];
 
875
        rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
876
        srcMapping[dest] = startMatch;
 
877
        currentOutput[dest++] = rule->charsdots[2 * passCharDots];
 
878
        passIC += 3;
 
879
        break;
 
880
      case pass_groupend:
 
881
        ruleOffset = (passInstructions[passIC + 1] << 16) |
 
882
          passInstructions[passIC + 2];
 
883
        rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
884
        srcMapping[dest] = startMatch;
 
885
        currentOutput[dest++] = rule->charsdots[2 * passCharDots + 1];
 
886
        passIC += 3;
 
887
        break;
 
888
      case pass_swap:
 
889
        if (!swapReplace (startReplace, endReplace))
 
890
          return 0;
 
891
        passIC += 3;
 
892
        break;
 
893
      case pass_groupreplace:
 
894
        if (!groupingRule || !replaceGrouping ())
 
895
          return 0;
 
896
        passIC += 3;
 
897
        break;
 
898
      case pass_omit:
 
899
        if (groupingRule)
 
900
          removeGrouping ();
 
901
        passIC++;
 
902
        break;
 
903
      case pass_copy:
 
904
        dest -= startReplace - startMatch;
 
905
        k = endReplace - startReplace;
 
906
        if ((dest + k) > destmax)
 
907
          return 0;
 
908
        memmove (&srcMapping[dest], &srcMapping[startReplace],
 
909
                 k * sizeof (int));
 
910
        memcpy (&currentOutput[dest], &currentInput[startReplace],
 
911
                k * CHARSIZE);
 
912
        dest += k;
 
913
        passIC++;
 
914
        endReplace = passSrc;
 
915
        break;
 
916
      default:
 
917
        return 0;
 
918
      }
 
919
  return 1;
 
920
}
 
921
 
 
922
static int
 
923
checkDots (void)
 
924
{
 
925
  int k;
 
926
  int kk = src;
 
927
  for (k = 0; k < transCharslen; k++)
 
928
    if (transRule->charsdots[k] != currentInput[kk++])
 
929
      return 0;
 
930
  return 1;
 
931
}
 
932
 
 
933
static void
 
934
passSelectRule (void)
 
935
{
 
936
  int length = srcmax - src;
 
937
  const TranslationTableCharacter *dots;
 
938
  const TranslationTableCharacter *dots2;
 
939
  int tryThis;
 
940
  TranslationTableOffset ruleOffset = 0;
 
941
  unsigned long int makeHash = 0;
 
942
  if (findAttribOrSwapRules ())
 
943
    return;
 
944
  dots = findCharOrDots (currentInput[src], 1);
 
945
  for (tryThis = 0; tryThis < 3; tryThis++)
 
946
    {
 
947
      switch (tryThis)
 
948
        {
 
949
        case 0:
 
950
          if (!(length >= 2))
 
951
            break;
 
952
/*Hash function optimized for forward translation */
 
953
          makeHash = (unsigned long int) dots->lowercase << 8;
 
954
          dots2 = findCharOrDots (currentInput[src + 1], 1);
 
955
          makeHash += (unsigned long int) dots2->lowercase;
 
956
          makeHash %= HASHNUM;
 
957
          ruleOffset = table->forRules[makeHash];
 
958
          break;
 
959
        case 1:
 
960
          if (!(length >= 1))
 
961
            break;
 
962
          length = 1;
 
963
          ruleOffset = dots->otherRules;
 
964
          break;
 
965
        case 2:         /*No rule found */
 
966
          transOpcode = CTO_Always;
 
967
          return;
 
968
          break;
 
969
        }
 
970
      while (ruleOffset)
 
971
        {
 
972
          transRule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 
973
          transOpcode = transRule->opcode;
 
974
          transCharslen = transRule->charslen;
 
975
          if (tryThis == 1 || ((transCharslen <= length) && checkDots ()))
 
976
            switch (transOpcode)
 
977
              {                 /*check validity of this Translation */
 
978
              case CTO_Pass2:
 
979
                if (currentPass != 2 || !srcIncremented)
 
980
                  break;
 
981
                if (!passDoTest ())
 
982
                  break;
 
983
                return;
 
984
              case CTO_Pass3:
 
985
                if (currentPass != 3 || !srcIncremented)
 
986
                  break;
 
987
                if (!passDoTest ())
 
988
                  break;
 
989
                return;
 
990
              case CTO_Pass4:
 
991
                if (currentPass != 4 || !srcIncremented)
 
992
                  break;
 
993
                if (!passDoTest ())
 
994
                  break;
 
995
                return;
 
996
              default:
 
997
                break;
 
998
              }
 
999
          ruleOffset = transRule->charsnext;
 
1000
        }
 
1001
    }
 
1002
  return;
 
1003
}
 
1004
 
 
1005
static int
 
1006
translatePass (void)
 
1007
{
 
1008
  int k;
 
1009
  prevTransOpcode = CTO_None;
 
1010
  src = dest = 0;
 
1011
  srcIncremented = 1;
 
1012
  for (k = 0; k < NUMVAR; k++)
 
1013
    passVariables[k] = 0;
 
1014
  while (src < srcmax)
 
1015
    {                           /*the main multipass translation loop */
 
1016
      passSelectRule ();
 
1017
      srcIncremented = 1;
 
1018
      switch (transOpcode)
 
1019
        {
 
1020
        case CTO_Context:
 
1021
        case CTO_Pass2:
 
1022
        case CTO_Pass3:
 
1023
        case CTO_Pass4:
 
1024
          if (!passDoAction ())
 
1025
            goto failure;
 
1026
          if (endReplace == src)
 
1027
            srcIncremented = 0;
 
1028
          src = endReplace;
 
1029
          break;
 
1030
        case CTO_Always:
 
1031
          if ((dest + 1) > destmax)
 
1032
            goto failure;
 
1033
          srcMapping[dest] = srcMapping[src];
 
1034
          currentOutput[dest++] = currentInput[src++];
 
1035
          break;
 
1036
        default:
 
1037
          goto failure;
 
1038
        }
 
1039
    }
 
1040
  srcMapping[dest] = srcMapping[src];
 
1041
failure:if (src < srcmax)
 
1042
    {
 
1043
      while (checkAttr (currentInput[src], CTC_Space, 1))
 
1044
        if (++src == srcmax)
 
1045
          break;
 
1046
    }
 
1047
  return 1;
 
1048
}