2 * fontconfig/doc/edit-sgml.c
4 * Copyright © 2003 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
34 Reallocate (void *p, int size);
39 typedef enum { False, True } Bool;
51 StringAdd (String *s, char c);
54 StringAddString (String *s, char *buf);
57 StringMake (char *buf);
60 StringDel (String *s);
63 StringPut (FILE *f, String *s);
66 StringDispose (String *s);
77 ReplaceDispose (Replace *r);
80 Bail (const char *format, int line, const char *arg);
83 ReplaceRead (FILE *f, int *linep);
85 typedef struct _replaceList {
86 struct _replaceList *next;
91 ReplaceListNew (Replace *r, ReplaceList *next);
94 ReplaceListDispose (ReplaceList *l);
101 ReplaceSetNew (void);
104 ReplaceSetDispose (ReplaceSet *s);
107 ReplaceSetAdd (ReplaceSet *s, Replace *r);
110 ReplaceSetFind (ReplaceSet *s, char *tag);
113 ReplaceSetRead (FILE *f, int *linep);
115 typedef struct _skipStack {
116 struct _skipStack *prev;
121 SkipStackPush (SkipStack *prev, int skipping);
124 SkipStackPop (SkipStack *prev);
126 typedef struct _loopStack {
127 struct _loopStack *prev;
134 LoopStackPush (LoopStack *prev, FILE *f, char *tag);
137 LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f);
140 LineSkip (FILE *f, int *linep);
143 DoReplace (FILE *f, int *linep, ReplaceSet *s);
145 #define STRING_INIT 128
150 void *m = malloc (size);
157 Reallocate (void *p, int size)
159 void *r = realloc (p, size);
177 s = New (sizeof (String));
178 s->buf = New (STRING_INIT);
179 s->size = STRING_INIT - 1;
186 StringAdd (String *s, char c)
188 if (s->len == s->size)
189 s->buf = Reallocate (s->buf, (s->size *= 2) + 1);
190 s->buf[s->len++] = c;
191 s->buf[s->len] = '\0';
195 StringAddString (String *s, char *buf)
198 StringAdd (s, *buf++);
202 StringMake (char *buf)
204 String *s = StringNew ();
205 StringAddString (s, buf);
210 StringDel (String *s)
213 s->buf[--s->len] = '\0';
217 StringPut (FILE *f, String *s)
225 #define StringLast(s) ((s)->len ? (s)->buf[(s)->len - 1] : '\0')
228 StringDispose (String *s)
237 Replace *r = New (sizeof (Replace));
238 r->tag = StringNew ();
239 r->text = StringNew ();
244 ReplaceDispose (Replace *r)
246 StringDispose (r->tag);
247 StringDispose (r->text);
252 Bail (const char *format, int line, const char *arg)
254 fprintf (stderr, "fatal: ");
255 fprintf (stderr, format, line, arg);
256 fprintf (stderr, "\n");
261 Getc (FILE *f, int *linep)
270 Ungetc (int c, FILE *f, int *linep)
278 ReplaceRead (FILE *f, int *linep)
283 while ((c = Getc (f, linep)) != '@')
289 while ((c = Getc (f, linep)) != '@')
297 Bail ("%d: invalid character after tag %s", *linep, r->tag->buf);
298 StringAdd (r->tag, c);
300 if (r->tag->buf[0] == '\0')
305 while (isspace ((c = Getc (f, linep))))
307 Ungetc (c, f, linep);
308 while ((c = Getc (f, linep)) != '@' && c != EOF)
309 StringAdd (r->text, c);
311 Ungetc (c, f, linep);
312 while (isspace (StringLast (r->text)))
314 if (StringLast(r->text) == '%')
317 StringAdd (r->text, ' ');
323 ReplaceListNew (Replace *r, ReplaceList *next)
325 ReplaceList *l = New (sizeof (ReplaceList));
332 ReplaceListDispose (ReplaceList *l)
336 ReplaceListDispose (l->next);
337 ReplaceDispose (l->r);
345 ReplaceSet *s = New (sizeof (ReplaceSet));
351 ReplaceSetDispose (ReplaceSet *s)
353 ReplaceListDispose (s->head);
358 ReplaceSetAdd (ReplaceSet *s, Replace *r)
360 s->head = ReplaceListNew (r, s->head);
364 ReplaceSetFind (ReplaceSet *s, char *tag)
368 for (l = s->head; l; l = l->next)
369 if (!strcmp (tag, l->r->tag->buf))
375 ReplaceSetRead (FILE *f, int *linep)
377 ReplaceSet *s = ReplaceSetNew ();
380 while ((r = ReplaceRead (f, linep)))
382 while (ReplaceSetFind (s, r->tag->buf))
383 StringAdd (r->tag, '+');
384 ReplaceSetAdd (s, r);
388 ReplaceSetDispose (s);
395 SkipStackPush (SkipStack *prev, int skipping)
397 SkipStack *ss = New (sizeof (SkipStack));
399 ss->skipping = skipping;
404 SkipStackPop (SkipStack *prev)
406 SkipStack *ss = prev->prev;
412 LoopStackPush (LoopStack *prev, FILE *f, char *tag)
414 LoopStack *ls = New (sizeof (LoopStack));
416 ls->tag = StringMake (tag);
417 ls->extra = StringNew ();
423 LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f)
425 String *s = StringMake (ls->tag->buf);
429 StringAdd (ls->extra, '+');
430 StringAddString (s, ls->extra->buf);
431 loop = ReplaceSetFind (rs, s->buf) != 0;
434 fseek (f, ls->pos, SEEK_SET);
438 StringDispose (ls->tag);
439 StringDispose (ls->extra);
446 LineSkip (FILE *f, int *linep)
450 while ((c = Getc (f, linep)) == '\n')
452 Ungetc (c, f, linep);
456 DoReplace (FILE *f, int *linep, ReplaceSet *s)
465 while ((c = Getc (f, linep)) != EOF)
470 while ((c = Getc (f, linep)) != '@')
477 StringAddString (tag, ls->extra->buf);
478 switch (tag->buf[0]) {
480 ss = SkipStackPush (ss, skipping);
481 if (!ReplaceSetFind (s, tag->buf + 1))
488 if (ss->skipping == skipping)
495 skipping = ss->skipping;
496 ss = SkipStackPop (ss);
500 ls = LoopStackPush (ls, f, tag->buf + 1);
504 ls = LoopStackLoop (s, ls, f);
508 r = ReplaceSetFind (s, tag->buf);
510 StringPut (stdout, r->text);
521 main (int argc, char **argv)
528 Bail ("usage: %*s <template.sgml>", 0, argv[0]);
529 f = fopen (argv[1], "r");
532 Bail ("can't open file %s", 0, argv[1]);
536 while ((s = ReplaceSetRead (stdin, &iline)))
539 DoReplace (f, &oline, s);
540 ReplaceSetDispose (s);
544 Bail ("%s", 0, "error writing output");