w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Resource.c
Go to the documentation of this file.
1 /*
2  * ChkTeX, resource file reader.
3  * Copyright (C) 1995-96 Jens T. Berger Thielemann
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * Contact the author at:
20  * Jens Berger
21  * Spektrumvn. 4
22  * N-0666 Oslo
23  * Norway
24  * E-mail: <jensthi@ifi.uio.no>
25  *
26  *
27  */
28 
29 #include "ChkTeX.h"
30 #include "OpSys.h"
31 #include "Utility.h"
32 #include "Resource.h"
33 
34 #define LNEMPTY(a) struct WordList a = {0, 1, {0}, {0}};
35 #define LIST(a) struct WordList a = {0, 0, {0}, {0}};
36 #define LCASE(a) LIST(a) LIST(a ## Case)
37 #define KEY(a,def) const char *a = def;
38 
40 #undef KEY
41 #undef LCASE
42 #undef LNEMPTY
43 #undef LIST
44 struct KeyWord
45 {
46  const char *Name;
47  const char **String; /* Keyword = item */
48  struct WordList *List, /* Case-sensitive strings */
49  *CaseList; /* Case-insensitive strings */
50 };
51 
52 #define LNEMPTY LIST
53 #define LIST(name) {#name, NULL, &name, NULL},
54 #define LCASE(name) {#name, NULL, &name, &name ## Case},
55 #define KEY(name,def) {#name, &name, NULL, NULL},
56 
57 struct KeyWord Keys[] = {
59 };
60 
61 #undef KEY
62 #undef LCASE
63 #undef LNEMPTY
64 #undef LIST
65 
66 
67 /***************************** RESOURCE HANDLING **************************/
68 
69 /* We don't include a trailing semicolon here, so that we can add it
70  * at the calling site, thereby preserving proper indentation. Double
71  * semicolons are undesirable since they have been known to break some
72  * compilers. */
73 #define TOKENBITS(name) enum name { \
74  BIT(Eof), /* End-of-file */ \
75  BIT(Open), /* { */ \
76  BIT(Close), /* } */ \
77  BIT(BrOpen), /* [ */ \
78  BIT(BrClose), /* ] */ \
79  BIT(Equal), /* = */ \
80  BIT(Word), /* Keyword */ \
81  BIT(Item) /* List item */ \
82 }
83 
84 #undef BIT
85 #define BIT BITDEF1
87 #undef BIT
88 #define BIT BITDEF2
90 static enum Token Expect;
91 static unsigned long RsrcLine;
92 
93 static enum Token ReadWord(char *, FILE *);
94 static char MapChars(char **String);
95 
96 
97 
98 /*
99  * Parses the contents of a resource file.
100  *
101  * Format:
102  * Keyword { item1 item2 ... } [ item1 item2 ... ]
103  * Keyword [ item1 item2 ... ] { item1 item2 ... }
104  * Keyword = { item1 item2 ... }
105  * Keyword = [ item1 item2 ... ]
106  * Keyword = item
107  *
108  * Returns whether the attempt was a successful one.
109  */
110 
111 int ReadRC(const char *Filename)
112 {
113  const char *String = NULL;
114  int Success = FALSE;
115  FILE *fh;
116  enum Token Token;
117  unsigned long Counter;
118 
119  struct KeyWord *CurWord = NULL;
120 
121  /* Interpret incoming words as ... */
122  enum
123  {
124  whList, /* List elements */
125  whCaseList, /* Case insensitive list elements */
126  whEqual, /* Solo elements */
127  whNone /* List items not accepted */
128  } What = whNone;
129 
130 
131  RsrcLine = 0;
132  Expect = FLG_Word | FLG_Eof;
133 
134  if ((fh = fopen(Filename, "r")))
135  {
136  Success = TRUE;
137  do
138  {
139  Token = ReadWord(ReadBuffer, fh);
140  if (!(Expect & Token))
141  {
142  switch (Token)
143  {
144  case FLG_Item:
145  String = "item";
146  break;
147  case FLG_Word:
148  String = "word";
149  break;
150  case FLG_Equal:
151  String = "`='";
152  break;
153  case FLG_Open:
154  String = "`{'";
155  break;
156  case FLG_Close:
157  String = "`}'";
158  break;
159  case FLG_BrOpen:
160  String = "`['";
161  break;
162  case FLG_BrClose:
163  String = "`]'";
164  break;
165  case FLG_Eof:
166  String = "EOF";
167  break;
168  }
170  Success = FALSE;
171  Token = FLG_Eof;
172  }
173 
174  switch (Token)
175  {
176  case FLG_Word:
177  for (Counter = 0; Keys[Counter].Name; Counter++)
178  {
179  if (!strcasecmp(ReadBuffer, Keys[Counter].Name))
180  {
181  CurWord = &Keys[Counter];
182  Expect = (CurWord->List ? FLG_Open : 0) |
183  (CurWord->CaseList ? FLG_BrOpen : 0) | FLG_Equal;
184  break;
185  }
186  }
187  if (!Keys[Counter].Name)
188  {
190  Success = FALSE;
191  Token = FLG_Eof;
192  }
193  break;
194  case FLG_Item:
195  switch (What)
196  {
197  case whEqual:
198  if (!(*(CurWord->String) = strdup(ReadBuffer)))
199  {
201  Token = FLG_Eof;
202  Success = FALSE;
203  }
204 
205  What = whNone;
206  Expect = FLG_Word | FLG_Eof;
207  break;
208  case whCaseList:
209  if (!InsertWord(ReadBuffer, CurWord->CaseList))
210  {
211  Token = FLG_Eof;
212  Success = FALSE;
213  }
214  break;
215  case whList:
216  if (!InsertWord(ReadBuffer, CurWord->List))
217  {
218  Token = FLG_Eof;
219  Success = FALSE;
220  }
221  break;
222  case whNone:
224  }
225  break;
226  case FLG_Equal:
227  What = whEqual;
228  Expect = (CurWord->List ? FLG_Open : 0) |
229  (CurWord->CaseList ? FLG_BrOpen : 0) |
230  (CurWord->String ? FLG_Item : 0);
231  break;
232  case FLG_BrOpen:
233  if (What == whEqual)
234  ClearWord(CurWord->CaseList);
235  What = whCaseList;
237  break;
238  case FLG_Open:
239  if (What == whEqual)
240  ClearWord(CurWord->List);
241  What = whList;
243  break;
244  case FLG_BrClose:
245  case FLG_Close:
246  Expect = (CurWord->List ? FLG_Open : 0) |
247  (CurWord->CaseList ? FLG_BrOpen : 0) |
249  What = whNone;
250  break;
251  case FLG_Eof:
252  break;
253  }
254  }
255  while (Token != FLG_Eof);
256 
257  fclose(fh);
258  }
259  else
261 
262  return (Success);
263 }
264 
265 /*
266  * Reads a token from the `.chktexrc' file; if the token is
267  * FLG_Item or FLG_Word, Buffer will contain the plaintext of the
268  * token. If not, the contents are undefined.
269  */
270 
271 static enum Token ReadWord(char *Buffer, FILE * fh)
272 {
273  static char *String = NULL;
274  static char StatBuf[BUFSIZ];
275  enum Token Retval = FLG_Eof;
276 
277  unsigned short Chr;
278 
279  char *Ptr;
280  int OnceMore = TRUE, Cont = TRUE;
281 
282  if (Buffer)
283  {
284  do
285  {
286  if (!(String && *String))
287  {
288  if (fgets(StatBuf, BUFSIZ - 1, fh))
289  String = strip(StatBuf, STRP_RGT);
290  RsrcLine++;
291  }
292 
293  Ptr = Buffer;
294  if (String && (String = strip(String, STRP_LFT)))
295  {
296  switch (Chr = *String)
297  {
298  case 0:
299  case CMNT:
300  String = NULL;
301  break;
302  case QUOTE: /* Quoted argument */
303  Cont = TRUE;
304  String++;
305 
306  while (Cont)
307  {
308  switch (Chr = *String++)
309  {
310  case 0:
311  case QUOTE:
312  Cont = FALSE;
313  break;
314  case ESCAPE:
315  if (!(Chr = MapChars(&String)))
316  break;
317 
318  /* FALLTHRU */
319  default:
320  *Ptr++ = Chr;
321  }
322  }
323  *Ptr = 0;
324  Retval = FLG_Item;
325  OnceMore = FALSE;
326  break;
327 
328 #define DONEKEY (FLG_Open | FLG_Equal | FLG_BrOpen)
329 #define DONELIST (FLG_Close | FLG_BrClose)
330 #define TOKEN(c, ctxt, tk) case c: if(Expect & (ctxt)) Retval = tk; LAST(token)
331 
332  LOOP(token,
333  TOKEN('{', DONEKEY, FLG_Open);
334  TOKEN('[', DONEKEY, FLG_BrOpen);
335  TOKEN('=', DONEKEY, FLG_Equal);
336  TOKEN(']', DONELIST, FLG_BrClose);
337  TOKEN('}', DONELIST, FLG_Close);
338  )
339  if (Retval != FLG_Eof)
340  {
341  OnceMore = FALSE;
342  String++;
343  break;
344  }
345 
346  /* FALLTHRU */
347 
348  default: /* Non-quoted argument */
349  OnceMore = FALSE;
350  if (Expect & FLG_Word)
351  {
352  while (Cont)
353  {
354  Chr = *String++;
355  if (isalpha((unsigned char)Chr))
356  *Ptr++ = Chr;
357  else
358  Cont = FALSE;
359  }
360  String--;
361  Retval = FLG_Word;
362  }
363  else /* Expect & FLG_Item */
364  {
365  while (Cont)
366  {
367  switch (Chr = *String++)
368  {
369  case CMNT:
370  case 0:
371  String = NULL;
372  Cont = FALSE;
373  break;
374  case ESCAPE:
375  if (!(Chr = MapChars(&String)))
376  break;
377 
378  *Ptr++ = Chr;
379  break;
380  default:
381  if (!isspace((unsigned char)Chr))
382  *Ptr++ = Chr;
383  else
384  Cont = FALSE;
385  }
386  }
387  Retval = FLG_Item;
388  }
389 
390  if (!(Buffer[0]))
391  {
393  if (*String)
394  String++;
395  }
396  *Ptr = 0;
397  break;
398  }
399  }
400  else
401  OnceMore = FALSE;
402  }
403  while (OnceMore);
404  }
405  return (Retval);
406 }
407 
408 
409 
410 /*
411  * Translates escape codes. Give it a pointer to the char after the
412  * escape char, and we'll return what it maps to.
413  */
414 
415 #define MAP(a,b) case a: Tmp = b; break;
416 
417 static char MapChars(char **String)
418 {
419  int Chr, Tmp = 0;
420  unsigned short Cnt;
421 
422  Chr = *((char *) (*String)++);
423 
424  switch (tolower((unsigned char)Chr))
425  {
426  MAP(QUOTE, QUOTE);
427  MAP(ESCAPE, ESCAPE);
428  MAP(CMNT, CMNT);
429  MAP('n', '\n');
430  MAP('r', '\r');
431  MAP('b', '\b');
432  MAP('t', '\t');
433  MAP('f', '\f');
434  MAP('{', '{');
435  MAP('}', '}');
436  MAP('[', '[');
437  MAP(']', ']');
438  MAP('=', '=');
439  MAP(' ', ' ');
440  case 'x':
441  Tmp = 0;
442 
443  for (Cnt = 0; Cnt < 2; Cnt++)
444  {
445  Chr = *((*String)++);
446  if (isxdigit((unsigned char)Chr))
447  {
448  Chr = toupper((unsigned char)Chr);
449  Tmp = (Tmp << 4) + Chr;
450 
451  if (isdigit((unsigned char)Chr))
452  Tmp -= '0';
453  else
454  Tmp -= 'A' - 10;
455  }
456  else
457  {
458  if (Chr)
459  {
460  PrintPrgErr(pmNotPSDigit, Chr, "hex");
461  Tmp = 0;
462  }
463  break;
464  }
465  }
466  break;
467  case '0':
468  case '1':
469  case '2':
470  case '3':
471  case '4':
472  case '5':
473  case '6':
474  case '7':
475 
476  Tmp = Chr - '0';
477 
478  for (Cnt = 0; Cnt < 2; Cnt++)
479  {
480  Chr = *((*String)++);
481  if (within('0', Chr, '7'))
482  Tmp = (Tmp * 8) + Chr - '0';
483  else
484  {
485  if (Chr)
486  {
487  PrintPrgErr(pmNotPSDigit, Chr, "octal");
488  Tmp = 0;
489  }
490  break;
491  }
492  }
493  break;
494  case 'd':
495  for (Cnt = 0; Cnt < 3; Cnt++)
496  {
497  if (isdigit((unsigned char)(Chr = *((*String)++))))
498  Tmp = (Tmp * 10) + Chr - '0';
499  else
500  {
501  if (Chr)
502  {
503  PrintPrgErr(pmNotPSDigit, Chr, "");
504  Tmp = 0;
505  }
506  break;
507  }
508  }
509  break;
510  default:
512  }
513  return (Tmp);
514 }
char * ReadBuffer
Definition: ChkTeX.c:75
void PrintPrgErr(enum PrgErrNum Error,...)
Definition: ChkTeX.c:1048
@ pmKeyWord
Definition: ChkTeX.h:270
@ pmRsrcOpen
Definition: ChkTeX.h:270
@ pmEscCode
Definition: ChkTeX.h:270
@ pmNotPSDigit
Definition: ChkTeX.h:270
@ pmAssert
Definition: ChkTeX.h:270
@ pmStrDupErr
Definition: ChkTeX.h:270
@ pmFaultFmt
Definition: ChkTeX.h:270
@ pmEmptyToken
Definition: ChkTeX.h:270
#define LOOP(name, body)
Definition: ChkTeX.h:154
int ReadRC(const char *Filename)
Definition: Resource.c:111
static char MapChars(char **String)
Definition: Resource.c:417
#define TOKENBITS(name)
Definition: Resource.c:73
#define DONEKEY
struct KeyWord Keys[]
Definition: Resource.c:57
#define MAP(a, b)
Definition: Resource.c:415
Token
Definition: Resource.c:89
@ FLG_BrOpen
Definition: Resource.c:89
@ FLG_Eof
Definition: Resource.c:89
@ FLG_Word
Definition: Resource.c:89
@ FLG_Close
Definition: Resource.c:89
@ FLG_BrClose
Definition: Resource.c:89
@ FLG_Open
Definition: Resource.c:89
@ FLG_Item
Definition: Resource.c:89
@ FLG_Equal
Definition: Resource.c:89
#define TOKEN(c, ctxt, tk)
#define DONELIST
static enum Token Expect
Definition: Resource.c:90
static unsigned long RsrcLine
Definition: Resource.c:91
Token_BIT
Definition: Resource.c:86
static enum Token ReadWord(char *, FILE *)
Definition: Resource.c:271
#define RESOURCE_INFO
Definition: Resource.h:43
#define CMNT
Definition: Resource.h:36
#define QUOTE
Definition: Resource.h:34
#define ESCAPE
Definition: Resource.h:35
void ClearWord(struct WordList *WL)
Definition: Utility.c:539
char * strip(char *str, const enum Strip flags)
Definition: Utility.c:168
int InsertWord(const char *Word, struct WordList *WL)
Definition: Utility.c:512
@ STRP_LFT
Definition: Utility.h:54
@ STRP_RGT
Definition: Utility.h:55
#define strdup
Definition: Utility.h:167
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
char * within
Definition: definitions.c:59
#define fopen
Definition: xxstdio.h:21
#define fgets
Definition: xxstdio.h:29
SimBuffer::B Buffer
Definition: gensi.hpp:669
#define NULL
Definition: ftobjs.h:61
#define strcasecmp
Definition: c-auto.h:150
#define fclose
Definition: debug.h:100
#define isdigit(c)
Definition: snprintf.c:177
#define Ptr
type_C toupper(type_C)
#define tolower(ch)
Definition: utype.h:137
#define isspace(ch)
Definition: utype.h:87
#define isalpha(ch)
Definition: utype.h:82
char * Ptr
Definition: TECkit_Common.h:41
const char * Name
Definition: Resource.c:46
struct WordList * CaseList
Definition: Resource.c:49
const char ** String
Definition: Resource.c:47
struct WordList * List
Definition: Resource.c:48
A string of characters.
Definition: t1part.c:49
Definition: llex.h:50
Definition: parser.c:43
#define FILE
Definition: t1stdio.h:34
#define BUFSIZ
Definition: ps.c:61