conv_gbk.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #ifdef PLAN9
  10. #include <u.h>
  11. #include <libc.h>
  12. #include <bio.h>
  13. #else
  14. #include <stdio.h>
  15. #include <unistd.h>
  16. #include "plan9.h"
  17. #endif
  18. #include "hdr.h"
  19. #include "conv.h"
  20. #include "gbk.h"
  21. static void
  22. gbkproc(int c, Rune **r, long input_loc)
  23. {
  24. static enum { state0, state1 } state = state0;
  25. static int lastc;
  26. long ch, cold = c;
  27. switch(state)
  28. {
  29. case state0: /* idle state */
  30. if(c < 0)
  31. return;
  32. if(c >= 0x80){
  33. lastc = c;
  34. state = state1;
  35. return;
  36. }
  37. emit(c);
  38. return;
  39. case state1: /* seen a font spec */
  40. ch = -1;
  41. c = lastc<<8 | c;
  42. if(c >= GBKMIN && c < GBKMAX)
  43. ch = tabgbk[c - GBKMIN];
  44. if(ch < 0){
  45. nerrors++;
  46. if(squawk)
  47. EPR "%s: bad gbk glyph %d (from 0x%x,0x%lx) near byte %ld in %s\n", argv0, (c & 0xFF), lastc, cold, input_loc, file);
  48. if(!clean)
  49. emit(BADMAP);
  50. state = state0;
  51. return;
  52. }
  53. emit(ch);
  54. state = state0;
  55. }
  56. }
  57. void
  58. gbk_in(int fd, int32_t *notused, struct convert *out)
  59. {
  60. Rune ob[N];
  61. Rune *r, *re;
  62. uint8_t ibuf[N];
  63. int n, i;
  64. int32_t nin;
  65. USED(notused);
  66. r = ob;
  67. re = ob+N-3;
  68. nin = 0;
  69. while((n = read(fd, ibuf, sizeof ibuf)) > 0){
  70. for(i = 0; i < n; i++){
  71. gbkproc(ibuf[i], &r, nin++);
  72. if(r >= re){
  73. OUT(out, ob, r-ob);
  74. r = ob;
  75. }
  76. }
  77. if(r > ob){
  78. OUT(out, ob, r-ob);
  79. r = ob;
  80. }
  81. }
  82. gbkproc(-1, &r, nin);
  83. if(r > ob)
  84. OUT(out, ob, r-ob);
  85. OUT(out, ob, 0);
  86. }
  87. void
  88. gbk_out(Rune *base, int n, long *notused)
  89. {
  90. char *p;
  91. int i;
  92. Rune r;
  93. static int first = 1;
  94. USED(notused);
  95. if(first){
  96. first = 0;
  97. for(i = 0; i < NRUNE; i++)
  98. tab[i] = -1;
  99. for(i = GBKMIN; i < GBKMAX; i++)
  100. tab[tabgbk[i-GBKMIN]] = i;
  101. }
  102. nrunes += n;
  103. p = obuf;
  104. for(i = 0; i < n; i++){
  105. r = base[i];
  106. if(r < 0x80)
  107. *p++ = r;
  108. else {
  109. if(tab[r] != -1){
  110. r = tab[r];
  111. *p++ = (r>>8) & 0xFF;
  112. *p++ = r & 0xFF;
  113. continue;
  114. }
  115. if(squawk)
  116. EPR "%s: rune 0x%x not in output cs\n", argv0, r);
  117. nerrors++;
  118. if(clean)
  119. continue;
  120. *p++ = BYTEBADMAP;
  121. }
  122. }
  123. noutput += p-obuf;
  124. if(p > obuf)
  125. write(1, obuf, p-obuf);
  126. }