tabgen.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /*
  6. chtabgen - character table generator
  7. Author: Erik Baalbergen (..tjalk!erikb)
  8. Many mods by Ceriel Jacobs
  9. */
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #define MAXBUF 256
  14. #define MAXTAB 10000
  15. #define COMCOM '-'
  16. #define FILECOM '%'
  17. int InputForm = 'c'; /* default input format (and, currently, only one) */
  18. char OutputForm[MAXBUF] = "%s,\n";
  19. /* format for spitting out a string */
  20. char *Table[MAXTAB];
  21. char *ProgCall; /* callname of this program */
  22. int TabSize = 128; /* default size of generated table */
  23. char *InitialValue; /* initial value of all table entries */
  24. /* Some protypes */
  25. void option(char *str);
  26. void InitTable(char *ival);
  27. void PrintTable();
  28. int process(char *str, int format);
  29. int c_proc(char *str, char *Name);
  30. int setval(int ch, char *nm);
  31. int quoted(char **pstr);
  32. void DoFile(char *name);
  33. char *getln(char *s, int n, FILE *fp);
  34. int main(int argc, char *argv[])
  35. {
  36. ProgCall = *argv++;
  37. argc--;
  38. while (argc-- > 0) {
  39. if (**argv == COMCOM) {
  40. option(*argv++);
  41. }
  42. else {
  43. if (! process(*argv++, InputForm)) {
  44. exit(1);
  45. }
  46. }
  47. }
  48. exit(0);
  49. /*NOTREACHED*/
  50. return 0;
  51. }
  52. char *Salloc(char *s)
  53. {
  54. char *ns = malloc((unsigned)strlen(s) + 1);
  55. if (ns) {
  56. strcpy(ns, s);
  57. }
  58. else {
  59. fprintf(stderr, "%s: out of memory\n", ProgCall);
  60. exit(1);
  61. }
  62. return ns;
  63. }
  64. void option(char *str)
  65. {
  66. /* note that *str indicates the source of the option:
  67. either COMCOM (from command line) or FILECOM (from a file).
  68. */
  69. switch (*++str) {
  70. case ' ': /* command */
  71. case '\t':
  72. case '\0':
  73. break;
  74. case 'I': /* for future extension */
  75. InputForm = *++str;
  76. break;
  77. case 'f': /* input from file ... */
  78. if (*++str == '\0') {
  79. fprintf(stderr, "%s: -f: name expected\n", ProgCall);
  80. exit(1);
  81. }
  82. DoFile(str);
  83. break;
  84. case 'F': /* new output format string */
  85. sprintf(OutputForm, "%s\n", ++str);
  86. break;
  87. case 'T': /* insert text literally */
  88. printf("%s\n", ++str);
  89. break;
  90. case 'p': /* print table */
  91. PrintTable();
  92. break;
  93. case 'C': /* clear table */
  94. InitTable((char *)0);
  95. break;
  96. case 'i': /* initialize table with given value */
  97. if (*++str == '\0') {
  98. InitTable((char *)0);
  99. }
  100. else InitTable(str);
  101. break;
  102. case 'S':
  103. {
  104. int i = atoi(++str);
  105. if (i <= 0 || i > MAXTAB) {
  106. fprintf(stderr, "%s: size would exceed maximum\n",
  107. ProgCall);
  108. }
  109. else {
  110. TabSize = i;
  111. }
  112. break;
  113. }
  114. default:
  115. fprintf(stderr, "%s: bad option -%s\n", ProgCall, str);
  116. }
  117. }
  118. void InitTable(char *ival)
  119. {
  120. int i;
  121. for (i = 0; i < TabSize; i++) {
  122. Table[i] = 0;
  123. }
  124. InitialValue = 0;
  125. if (ival) {
  126. InitialValue = Salloc(ival);
  127. }
  128. }
  129. void PrintTable()
  130. {
  131. int i;
  132. for (i = 0; i < TabSize; i++) {
  133. if (Table[i]) {
  134. printf(OutputForm, Table[i]);
  135. }
  136. else if (InitialValue) {
  137. printf(OutputForm, InitialValue);
  138. }
  139. else {
  140. printf(OutputForm, "0");
  141. }
  142. }
  143. }
  144. int process(char *str, int format)
  145. {
  146. char *cstr = str;
  147. char *Name = cstr; /* overwrite original string! */
  148. /* strip of the entry name
  149. */
  150. while (*str && *str != ':') {
  151. if (*str == '\\') {
  152. ++str;
  153. }
  154. *cstr++ = *str++;
  155. }
  156. if (*str != ':') {
  157. fprintf(stderr, "%s: bad specification: \"%s\", ignored\n",
  158. ProgCall, Name);
  159. return 0;
  160. }
  161. *cstr = '\0';
  162. str++;
  163. switch (format) {
  164. case 'c':
  165. return c_proc(str, Name);
  166. default:
  167. fprintf(stderr, "%s: bad input format\n", ProgCall);
  168. }
  169. return 0;
  170. }
  171. int c_proc(char *str, char *Name)
  172. {
  173. int ch, ch2;
  174. int quoted();
  175. char *name = Salloc(Name);
  176. while (*str) {
  177. if (*str == '\\') {
  178. ch = quoted(&str);
  179. }
  180. else {
  181. ch = *str++ & 0377;
  182. }
  183. if (*str == '-') {
  184. if (*++str == '\\') {
  185. ch2 = quoted(&str);
  186. }
  187. else {
  188. if (!(ch2 = (*str++ & 0377)))
  189. str--;
  190. }
  191. if (ch > ch2) {
  192. fprintf(stderr, "%s: bad range\n", ProgCall);
  193. return 0;
  194. }
  195. while (ch <= ch2) {
  196. if (! setval(ch, name)) return 0;
  197. ch++;
  198. }
  199. }
  200. else {
  201. if (! setval(ch, name)) return 0;
  202. }
  203. }
  204. return 1;
  205. }
  206. int setval(int ch, char *nm)
  207. {
  208. char **p = &Table[ch];
  209. if (ch < 0 || ch >= TabSize) {
  210. fprintf(stderr, "Illegal index: %d\n", ch);
  211. return 0;
  212. }
  213. if (*(p = &Table[ch])) {
  214. fprintf(stderr, "Warning: redefinition of index %d\n", ch);
  215. }
  216. *p = nm;
  217. return 1;
  218. }
  219. int quoted(char **pstr)
  220. {
  221. int ch;
  222. int i;
  223. char *str = *pstr;
  224. if ((*++str >= '0') && (*str <= '9')) {
  225. ch = 0;
  226. for (i = 0; i < 3; i++) {
  227. ch = 8 * ch + (*str - '0');
  228. if (*++str < '0' || *str > '9')
  229. break;
  230. }
  231. }
  232. else {
  233. switch (*str++) {
  234. case 'n':
  235. ch = '\n';
  236. break;
  237. case 't':
  238. ch = '\t';
  239. break;
  240. case 'b':
  241. ch = '\b';
  242. break;
  243. case 'r':
  244. ch = '\r';
  245. break;
  246. case 'f':
  247. ch = '\f';
  248. break;
  249. case 'v':
  250. ch = 013;
  251. break;
  252. default :
  253. ch = *(str - 1);
  254. break;
  255. }
  256. }
  257. *pstr = str;
  258. return ch & 0377;
  259. }
  260. char *getln(char *s, int n, FILE *fp)
  261. {
  262. int c = getc(fp);
  263. char *str = s;
  264. while (n--) {
  265. if (c == EOF) {
  266. return NULL;
  267. }
  268. else
  269. if (c == '\n') {
  270. *str++ = '\0';
  271. return s;
  272. }
  273. *str++ = c;
  274. c = getc(fp);
  275. }
  276. s[n - 1] = '\0';
  277. return s;
  278. }
  279. #define BUFSIZE 1024
  280. void DoFile(char *name)
  281. {
  282. char text[BUFSIZE];
  283. FILE *fp;
  284. if ((fp = fopen(name, "r")) == NULL) {
  285. fprintf(stderr, "%s: cannot read file %s\n", ProgCall, name);
  286. exit(1);
  287. }
  288. while (getln(text, BUFSIZE, fp) != NULL) {
  289. if (text[0] == FILECOM) {
  290. option(text);
  291. }
  292. else {
  293. if (! process(text, InputForm)) {
  294. exit(1);
  295. }
  296. }
  297. }
  298. }