Bgetfield.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "../common/common.h"
  5. #include "tr2post.h"
  6. int
  7. isspace(Rune r)
  8. {
  9. return(r==' ' || r=='\t' || r=='\n' || r == '\r' || r=='\f');
  10. }
  11. int
  12. Bskipws(Biobufhdr *bp) {
  13. int r;
  14. char c[UTFmax];
  15. int sindex = 0;
  16. /* skip over initial white space */
  17. do {
  18. r = Bgetrune(bp);
  19. if (r == '\n') inputlineno++;
  20. sindex++;
  21. } while (r>=0 && isspace(r));
  22. if (r<0) {
  23. return(-1);
  24. } else if (!isspace(r)) {
  25. Bungetrune(bp);
  26. --sindex;
  27. }
  28. return(sindex);
  29. }
  30. int
  31. asc2dig(char c, int base) {
  32. if (c >= '0' && c <= '9')
  33. if (base == 8 && c > '7') return(-1);
  34. else return(c - '0');
  35. if (base == 16)
  36. if (c >= 'a' && c <= 'f') return(10 + c - 'a');
  37. else if (c >= 'A' && c <= 'F') return(10 + c - 'A');
  38. return(-1);
  39. }
  40. /* get a string of type: "d" for decimal integer, "u" for unsigned,
  41. * "s" for string", "c" for char,
  42. * return the number of characters gotten for the field. If nothing
  43. * was gotten and the end of file was reached, a negative value
  44. * from the Bgetrune is returned.
  45. */
  46. int
  47. Bgetfield(Biobufhdr *bp, int type, void *thing, int size) {
  48. int r;
  49. Rune R;
  50. char c[UTFmax];
  51. int sindex = 0, i, j, n = 0;
  52. int negate = 0;
  53. int base = 10;
  54. BOOLEAN bailout = FALSE;
  55. int dig;
  56. unsigned int u = 0;
  57. /* skip over initial white space */
  58. if (Bskipws(bp) < 0)
  59. return(-1);
  60. switch (type) {
  61. case 'd':
  62. while (!bailout && (r = Bgetrune(bp))>=0) {
  63. switch (sindex++) {
  64. case 0:
  65. switch (r) {
  66. case '-':
  67. negate = 1;
  68. continue;
  69. case '+':
  70. continue;
  71. case '0':
  72. base = 8;
  73. continue;
  74. default:
  75. break;
  76. }
  77. break;
  78. case 1:
  79. if ((r == 'x' || r == 'X') && base == 8) {
  80. base = 16;
  81. continue;
  82. }
  83. }
  84. if ((dig = asc2dig(r, base)) == -1) bailout = TRUE;
  85. else n = dig + (n * base);
  86. }
  87. if (r < 0) return(-1);
  88. *(int *)thing = (negate)?-n:n;
  89. Bungetrune(bp);
  90. break;
  91. case 'u':
  92. while (!bailout && (r = Bgetrune(bp))>=0) {
  93. switch (sindex++) {
  94. case 0:
  95. if (*c == '0') {
  96. base = 8;
  97. continue;
  98. }
  99. break;
  100. case 1:
  101. if ((r == 'x' || r == 'X') && base == 8) {
  102. base = 16;
  103. continue;
  104. }
  105. }
  106. if ((dig = asc2dig(r, base)) == -1) bailout = TRUE;
  107. else u = dig + (n * base);
  108. }
  109. *(int *)thing = u;
  110. if (r < 0) return(-1);
  111. Bungetrune(bp);
  112. break;
  113. case 's':
  114. j = 0;
  115. while ((size>j+UTFmax) && (r = Bgetrune(bp))>=0 && !isspace(r)) {
  116. R = r;
  117. i = runetochar(&(((char *)thing)[j]), &R);
  118. j += i;
  119. sindex++;
  120. }
  121. ((char *)thing)[j++] = '\0';
  122. if (r < 0) return(-1);
  123. Bungetrune(bp);
  124. break;
  125. case 'r':
  126. if ((r = Bgetrune(bp))>=0) {
  127. *(Rune *)thing = r;
  128. sindex++;
  129. return(sindex);
  130. }
  131. if (r <= 0) return(-1);
  132. Bungetrune(bp);
  133. break;
  134. default:
  135. return(-2);
  136. }
  137. if (r < 0 && sindex == 0)
  138. return(r);
  139. else if (bailout && sindex == 1) {
  140. return(0);
  141. } else
  142. return(sindex);
  143. }