Add func doc creation program edit-sgml
This commit is contained in:
parent
c92abf78e1
commit
5e1f56b567
|
@ -0,0 +1,426 @@
|
|||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright © 2003 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef enum { False, True } Bool;
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
int size;
|
||||
int len;
|
||||
} String;
|
||||
|
||||
#define STRING_INIT 128
|
||||
|
||||
void *
|
||||
New (int size)
|
||||
{
|
||||
void *m = malloc (size);
|
||||
if (!m)
|
||||
abort ();
|
||||
return m;
|
||||
}
|
||||
|
||||
void *
|
||||
Reallocate (void *p, int size)
|
||||
{
|
||||
void *r = realloc (p, size);
|
||||
|
||||
if (!r)
|
||||
abort ();
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
Dispose (void *p)
|
||||
{
|
||||
free (p);
|
||||
}
|
||||
|
||||
String *
|
||||
StringNew (void)
|
||||
{
|
||||
String *s;
|
||||
|
||||
s = New (sizeof (String));
|
||||
s->buf = New (STRING_INIT);
|
||||
s->size = STRING_INIT - 1;
|
||||
s->buf[0] = '\0';
|
||||
s->len = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
StringAdd (String *s, char c)
|
||||
{
|
||||
if (s->len == s->size)
|
||||
s->buf = Reallocate (s->buf, (s->size *= 2) + 1);
|
||||
s->buf[s->len++] = c;
|
||||
s->buf[s->len] = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
StringAddString (String *s, char *buf)
|
||||
{
|
||||
while (*buf)
|
||||
StringAdd (s, *buf++);
|
||||
}
|
||||
|
||||
String *
|
||||
StringMake (char *buf)
|
||||
{
|
||||
String *s = StringNew ();
|
||||
StringAddString (s, buf);
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
StringDel (String *s)
|
||||
{
|
||||
if (s->len)
|
||||
s->buf[--s->len] = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
StringPut (FILE *f, String *s)
|
||||
{
|
||||
char *b = s->buf;
|
||||
|
||||
while (*b)
|
||||
putc (*b++, f);
|
||||
}
|
||||
|
||||
#define StringLast(s) ((s)->len ? (s)->buf[(s)->len - 1] : '\0')
|
||||
|
||||
void
|
||||
StringDispose (String *s)
|
||||
{
|
||||
Dispose (s->buf);
|
||||
Dispose (s);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
String *tag;
|
||||
String *text;
|
||||
} Replace;
|
||||
|
||||
Replace *
|
||||
ReplaceNew (void)
|
||||
{
|
||||
Replace *r = New (sizeof (Replace));
|
||||
r->tag = StringNew ();
|
||||
r->text = StringNew ();
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceDispose (Replace *r)
|
||||
{
|
||||
StringDispose (r->tag);
|
||||
StringDispose (r->text);
|
||||
Dispose (r);
|
||||
}
|
||||
|
||||
Replace *
|
||||
ReplaceRead (FILE *f)
|
||||
{
|
||||
int c;
|
||||
Replace *r;
|
||||
|
||||
while ((c = getc (f)) != '@')
|
||||
{
|
||||
if (c == EOF)
|
||||
return 0;
|
||||
}
|
||||
r = ReplaceNew();
|
||||
while ((c = getc (f)) != '@')
|
||||
{
|
||||
if (c == EOF)
|
||||
{
|
||||
ReplaceDispose (r);
|
||||
return 0;
|
||||
}
|
||||
StringAdd (r->tag, c);
|
||||
}
|
||||
if (r->tag->buf[0] == '\0')
|
||||
{
|
||||
ReplaceDispose (r);
|
||||
return 0;
|
||||
}
|
||||
while (isspace ((c = getc (f))))
|
||||
;
|
||||
ungetc (c, f);
|
||||
while ((c = getc (f)) != '@' && c != EOF)
|
||||
StringAdd (r->text, c);
|
||||
if (c == '@')
|
||||
ungetc (c, f);
|
||||
while (StringLast (r->text) == '\n')
|
||||
StringDel (r->text);
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef struct _replaceList {
|
||||
struct _replaceList *next;
|
||||
Replace *r;
|
||||
} ReplaceList;
|
||||
|
||||
ReplaceList *
|
||||
ReplaceListNew (Replace *r, ReplaceList *next)
|
||||
{
|
||||
ReplaceList *l = New (sizeof (ReplaceList));
|
||||
l->r = r;
|
||||
l->next = next;
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceListDispose (ReplaceList *l)
|
||||
{
|
||||
if (l)
|
||||
{
|
||||
ReplaceListDispose (l->next);
|
||||
ReplaceDispose (l->r);
|
||||
Dispose (l);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ReplaceList *head;
|
||||
} ReplaceSet;
|
||||
|
||||
ReplaceSet *
|
||||
ReplaceSetNew (void)
|
||||
{
|
||||
ReplaceSet *s = New (sizeof (ReplaceSet));
|
||||
s->head = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceSetDispose (ReplaceSet *s)
|
||||
{
|
||||
ReplaceListDispose (s->head);
|
||||
Dispose (s);
|
||||
}
|
||||
|
||||
void
|
||||
ReplaceSetAdd (ReplaceSet *s, Replace *r)
|
||||
{
|
||||
s->head = ReplaceListNew (r, s->head);
|
||||
}
|
||||
|
||||
Replace *
|
||||
ReplaceSetFind (ReplaceSet *s, char *tag)
|
||||
{
|
||||
ReplaceList *l;
|
||||
|
||||
for (l = s->head; l; l = l->next)
|
||||
if (!strcmp (tag, l->r->tag->buf))
|
||||
return l->r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReplaceSet *
|
||||
ReplaceSetRead (FILE *f)
|
||||
{
|
||||
ReplaceSet *s = ReplaceSetNew ();
|
||||
Replace *r;
|
||||
|
||||
while ((r = ReplaceRead (f)))
|
||||
{
|
||||
while (ReplaceSetFind (s, r->tag->buf))
|
||||
StringAdd (r->tag, '+');
|
||||
ReplaceSetAdd (s, r);
|
||||
}
|
||||
if (!s->head)
|
||||
{
|
||||
ReplaceSetDispose (s);
|
||||
s = 0;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
typedef struct _skipStack {
|
||||
struct _skipStack *prev;
|
||||
int skipping;
|
||||
} SkipStack;
|
||||
|
||||
SkipStack *
|
||||
SkipStackPush (SkipStack *prev, int skipping)
|
||||
{
|
||||
SkipStack *ss = New (sizeof (SkipStack));
|
||||
ss->prev = prev;
|
||||
ss->skipping = skipping;
|
||||
return ss;
|
||||
}
|
||||
|
||||
SkipStack *
|
||||
SkipStackPop (SkipStack *prev)
|
||||
{
|
||||
SkipStack *ss = prev->prev;
|
||||
Dispose (prev);
|
||||
return ss;
|
||||
}
|
||||
|
||||
typedef struct _loopStack {
|
||||
struct _loopStack *prev;
|
||||
String *tag;
|
||||
String *extra;
|
||||
long pos;
|
||||
} LoopStack;
|
||||
|
||||
LoopStack *
|
||||
LoopStackPush (LoopStack *prev, FILE *f, char *tag)
|
||||
{
|
||||
LoopStack *ls = New (sizeof (LoopStack));
|
||||
ls->prev = prev;
|
||||
ls->tag = StringMake (tag);
|
||||
ls->extra = StringNew ();
|
||||
ls->pos = ftell (f);
|
||||
return ls;
|
||||
}
|
||||
|
||||
LoopStack *
|
||||
LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f)
|
||||
{
|
||||
String *s = StringMake (ls->tag->buf);
|
||||
LoopStack *ret = ls;
|
||||
Bool loop;
|
||||
|
||||
StringAdd (ls->extra, '+');
|
||||
StringAddString (s, ls->extra->buf);
|
||||
loop = ReplaceSetFind (rs, s->buf) != 0;
|
||||
StringDispose (s);
|
||||
if (loop)
|
||||
fseek (f, ls->pos, SEEK_SET);
|
||||
else
|
||||
{
|
||||
ret = ls->prev;
|
||||
StringDispose (ls->tag);
|
||||
StringDispose (ls->extra);
|
||||
Dispose (ls);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
LineSkip (FILE *f)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getc (f)) == '\n')
|
||||
;
|
||||
ungetc (c, f);
|
||||
}
|
||||
|
||||
void
|
||||
DoReplace (FILE *f, ReplaceSet *s)
|
||||
{
|
||||
int c;
|
||||
String *tag;
|
||||
Replace *r;
|
||||
SkipStack *ss = 0;
|
||||
LoopStack *ls = 0;
|
||||
int skipping = 0;
|
||||
|
||||
while ((c = getc (f)) != EOF)
|
||||
{
|
||||
if (c == '@')
|
||||
{
|
||||
tag = StringNew ();
|
||||
while ((c = getc (f)) != '@')
|
||||
{
|
||||
if (c == EOF)
|
||||
abort ();
|
||||
StringAdd (tag, c);
|
||||
}
|
||||
if (ls)
|
||||
StringAddString (tag, ls->extra->buf);
|
||||
switch (tag->buf[0]) {
|
||||
case '?':
|
||||
ss = SkipStackPush (ss, skipping);
|
||||
if (!ReplaceSetFind (s, tag->buf + 1))
|
||||
skipping++;
|
||||
LineSkip (f);
|
||||
break;
|
||||
case ':':
|
||||
if (!ss)
|
||||
abort ();
|
||||
if (ss->skipping == skipping)
|
||||
++skipping;
|
||||
else
|
||||
--skipping;
|
||||
LineSkip (f);
|
||||
break;
|
||||
case ';':
|
||||
skipping = ss->skipping;
|
||||
ss = SkipStackPop (ss);
|
||||
LineSkip (f);
|
||||
break;
|
||||
case '{':
|
||||
ls = LoopStackPush (ls, f, tag->buf + 1);
|
||||
LineSkip (f);
|
||||
break;
|
||||
case '}':
|
||||
ls = LoopStackLoop (s, ls, f);
|
||||
LineSkip (f);
|
||||
break;
|
||||
default:
|
||||
r = ReplaceSetFind (s, tag->buf);
|
||||
if (r && !skipping)
|
||||
StringPut (stdout, r->text);
|
||||
break;
|
||||
}
|
||||
StringDispose (tag);
|
||||
}
|
||||
else if (!skipping)
|
||||
putchar (c);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
ReplaceSet *s;
|
||||
|
||||
f = fopen (argv[1], "r");
|
||||
if (!f)
|
||||
{
|
||||
perror (argv[1]);
|
||||
exit (1);
|
||||
}
|
||||
while ((s = ReplaceSetRead (stdin)))
|
||||
{
|
||||
DoReplace (f, s);
|
||||
ReplaceSetDispose (s);
|
||||
rewind (f);
|
||||
}
|
||||
if (ferror (stdout))
|
||||
exit (1);
|
||||
exit (0);
|
||||
}
|
Loading…
Reference in New Issue