Track line numbers in sgml edit tool input.
Errors in the documentation can be hard to find unless the tool outputs the line number where the problem exists.
This commit is contained in:
parent
088b582a26
commit
b868a14473
|
@ -77,10 +77,10 @@ static void
|
||||||
ReplaceDispose (Replace *r);
|
ReplaceDispose (Replace *r);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
Bail (const char *format, const char *arg);
|
Bail (const char *format, int line, const char *arg);
|
||||||
|
|
||||||
static Replace *
|
static Replace *
|
||||||
ReplaceRead (FILE *f);
|
ReplaceRead (FILE *f, int *linep);
|
||||||
|
|
||||||
typedef struct _replaceList {
|
typedef struct _replaceList {
|
||||||
struct _replaceList *next;
|
struct _replaceList *next;
|
||||||
|
@ -110,7 +110,7 @@ static Replace *
|
||||||
ReplaceSetFind (ReplaceSet *s, char *tag);
|
ReplaceSetFind (ReplaceSet *s, char *tag);
|
||||||
|
|
||||||
static ReplaceSet *
|
static ReplaceSet *
|
||||||
ReplaceSetRead (FILE *f);
|
ReplaceSetRead (FILE *f, int *linep);
|
||||||
|
|
||||||
typedef struct _skipStack {
|
typedef struct _skipStack {
|
||||||
struct _skipStack *prev;
|
struct _skipStack *prev;
|
||||||
|
@ -137,10 +137,10 @@ static LoopStack *
|
||||||
LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f);
|
LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
LineSkip (FILE *f);
|
LineSkip (FILE *f, int *linep);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DoReplace (FILE *f, ReplaceSet *s);
|
DoReplace (FILE *f, int *linep, ReplaceSet *s);
|
||||||
|
|
||||||
#define STRING_INIT 128
|
#define STRING_INIT 128
|
||||||
|
|
||||||
|
@ -249,27 +249,43 @@ ReplaceDispose (Replace *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
Bail (const char *format, const char *arg)
|
Bail (const char *format, int line, const char *arg)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "fatal: ");
|
fprintf (stderr, "fatal: ");
|
||||||
fprintf (stderr, format, arg);
|
fprintf (stderr, format, line, arg);
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
Getc (FILE *f, int *linep)
|
||||||
|
{
|
||||||
|
int c = getc (f);
|
||||||
|
if (c == '\n')
|
||||||
|
++(*linep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Ungetc (int c, FILE *f, int *linep)
|
||||||
|
{
|
||||||
|
if (c == '\n')
|
||||||
|
--(*linep);
|
||||||
|
ungetc (c, f);
|
||||||
|
}
|
||||||
|
|
||||||
static Replace *
|
static Replace *
|
||||||
ReplaceRead (FILE *f)
|
ReplaceRead (FILE *f, int *linep)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
Replace *r;
|
Replace *r;
|
||||||
|
|
||||||
while ((c = getc (f)) != '@')
|
while ((c = Getc (f, linep)) != '@')
|
||||||
{
|
{
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r = ReplaceNew();
|
r = ReplaceNew();
|
||||||
while ((c = getc (f)) != '@')
|
while ((c = Getc (f, linep)) != '@')
|
||||||
{
|
{
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
{
|
{
|
||||||
|
@ -277,7 +293,7 @@ ReplaceRead (FILE *f)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (isspace (c))
|
if (isspace (c))
|
||||||
Bail ("invalid character after tag %s", r->tag->buf);
|
Bail ("%d: invalid character after tag %s", *linep, r->tag->buf);
|
||||||
StringAdd (r->tag, c);
|
StringAdd (r->tag, c);
|
||||||
}
|
}
|
||||||
if (r->tag->buf[0] == '\0')
|
if (r->tag->buf[0] == '\0')
|
||||||
|
@ -285,13 +301,13 @@ ReplaceRead (FILE *f)
|
||||||
ReplaceDispose (r);
|
ReplaceDispose (r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (isspace ((c = getc (f))))
|
while (isspace ((c = Getc (f, linep))))
|
||||||
;
|
;
|
||||||
ungetc (c, f);
|
Ungetc (c, f, linep);
|
||||||
while ((c = getc (f)) != '@' && c != EOF)
|
while ((c = Getc (f, linep)) != '@' && c != EOF)
|
||||||
StringAdd (r->text, c);
|
StringAdd (r->text, c);
|
||||||
if (c == '@')
|
if (c == '@')
|
||||||
ungetc (c, f);
|
Ungetc (c, f, linep);
|
||||||
while (isspace (StringLast (r->text)))
|
while (isspace (StringLast (r->text)))
|
||||||
StringDel (r->text);
|
StringDel (r->text);
|
||||||
if (StringLast(r->text) == '%')
|
if (StringLast(r->text) == '%')
|
||||||
|
@ -355,12 +371,12 @@ ReplaceSetFind (ReplaceSet *s, char *tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ReplaceSet *
|
static ReplaceSet *
|
||||||
ReplaceSetRead (FILE *f)
|
ReplaceSetRead (FILE *f, int *linep)
|
||||||
{
|
{
|
||||||
ReplaceSet *s = ReplaceSetNew ();
|
ReplaceSet *s = ReplaceSetNew ();
|
||||||
Replace *r;
|
Replace *r;
|
||||||
|
|
||||||
while ((r = ReplaceRead (f)))
|
while ((r = ReplaceRead (f, linep)))
|
||||||
{
|
{
|
||||||
while (ReplaceSetFind (s, r->tag->buf))
|
while (ReplaceSetFind (s, r->tag->buf))
|
||||||
StringAdd (r->tag, '+');
|
StringAdd (r->tag, '+');
|
||||||
|
@ -426,17 +442,17 @@ LoopStackLoop (ReplaceSet *rs, LoopStack *ls, FILE *f)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
LineSkip (FILE *f)
|
LineSkip (FILE *f, int *linep)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while ((c = getc (f)) == '\n')
|
while ((c = Getc (f, linep)) == '\n')
|
||||||
;
|
;
|
||||||
ungetc (c, f);
|
Ungetc (c, f, linep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DoReplace (FILE *f, ReplaceSet *s)
|
DoReplace (FILE *f, int *linep, ReplaceSet *s)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
String *tag;
|
String *tag;
|
||||||
|
@ -445,12 +461,12 @@ DoReplace (FILE *f, ReplaceSet *s)
|
||||||
LoopStack *ls = 0;
|
LoopStack *ls = 0;
|
||||||
int skipping = 0;
|
int skipping = 0;
|
||||||
|
|
||||||
while ((c = getc (f)) != EOF)
|
while ((c = Getc (f, linep)) != EOF)
|
||||||
{
|
{
|
||||||
if (c == '@')
|
if (c == '@')
|
||||||
{
|
{
|
||||||
tag = StringNew ();
|
tag = StringNew ();
|
||||||
while ((c = getc (f)) != '@')
|
while ((c = Getc (f, linep)) != '@')
|
||||||
{
|
{
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
abort ();
|
abort ();
|
||||||
|
@ -463,7 +479,7 @@ DoReplace (FILE *f, ReplaceSet *s)
|
||||||
ss = SkipStackPush (ss, skipping);
|
ss = SkipStackPush (ss, skipping);
|
||||||
if (!ReplaceSetFind (s, tag->buf + 1))
|
if (!ReplaceSetFind (s, tag->buf + 1))
|
||||||
skipping++;
|
skipping++;
|
||||||
LineSkip (f);
|
LineSkip (f, linep);
|
||||||
break;
|
break;
|
||||||
case ':':
|
case ':':
|
||||||
if (!ss)
|
if (!ss)
|
||||||
|
@ -472,20 +488,20 @@ DoReplace (FILE *f, ReplaceSet *s)
|
||||||
++skipping;
|
++skipping;
|
||||||
else
|
else
|
||||||
--skipping;
|
--skipping;
|
||||||
LineSkip (f);
|
LineSkip (f, linep);
|
||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
skipping = ss->skipping;
|
skipping = ss->skipping;
|
||||||
ss = SkipStackPop (ss);
|
ss = SkipStackPop (ss);
|
||||||
LineSkip (f);
|
LineSkip (f, linep);
|
||||||
break;
|
break;
|
||||||
case '{':
|
case '{':
|
||||||
ls = LoopStackPush (ls, f, tag->buf + 1);
|
ls = LoopStackPush (ls, f, tag->buf + 1);
|
||||||
LineSkip (f);
|
LineSkip (f, linep);
|
||||||
break;
|
break;
|
||||||
case '}':
|
case '}':
|
||||||
ls = LoopStackLoop (s, ls, f);
|
ls = LoopStackLoop (s, ls, f);
|
||||||
LineSkip (f);
|
LineSkip (f, linep);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
r = ReplaceSetFind (s, tag->buf);
|
r = ReplaceSetFind (s, tag->buf);
|
||||||
|
@ -505,22 +521,25 @@ main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
ReplaceSet *s;
|
ReplaceSet *s;
|
||||||
|
int iline, oline;
|
||||||
|
|
||||||
if (!argv[1])
|
if (!argv[1])
|
||||||
Bail ("usage: %s <template.sgml>", argv[0]);
|
Bail ("usage: %s <template.sgml>", 0, argv[0]);
|
||||||
f = fopen (argv[1], "r");
|
f = fopen (argv[1], "r");
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
Bail ("can't open file %s", argv[1]);
|
Bail ("can't open file %s", 0, argv[1]);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
while ((s = ReplaceSetRead (stdin)))
|
iline = 1;
|
||||||
|
while ((s = ReplaceSetRead (stdin, &iline)))
|
||||||
{
|
{
|
||||||
DoReplace (f, s);
|
oline = 1;
|
||||||
|
DoReplace (f, &oline, s);
|
||||||
ReplaceSetDispose (s);
|
ReplaceSetDispose (s);
|
||||||
rewind (f);
|
rewind (f);
|
||||||
}
|
}
|
||||||
if (ferror (stdout))
|
if (ferror (stdout))
|
||||||
Bail ("%s", "error writing output");
|
Bail ("%s", 0, "error writing output");
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue