]>
git.cameronkatri.com Git - mandoc.git/blob - mlg.c
1 /* $Id: mlg.c,v 1.7 2008/12/04 19:31:57 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
26 #include "libmdocml.h"
30 /* TODO: literal tokens. */
45 const struct md_args
*args
;
46 const struct md_rbuf
*rbuf
;
49 struct rofftree
*tree
;
59 #define ML_OVERRIDE_ONE (1 << 0)
60 #define ML_OVERRIDE_ALL (1 << 1)
64 static void mlg_roffmsg(void *arg
, enum roffmsg
,
65 const char *, const char *, char *);
66 static int mlg_roffhead(void *, const struct tm
*,
67 const char *, const char *,
68 const char *, const char *);
69 static int mlg_rofftail(void *);
70 static int mlg_roffin(void *, int, int *, char **);
71 static int mlg_roffdata(void *, int,
72 const char *, char *);
73 static int mlg_roffout(void *, int);
74 static int mlg_roffblkin(void *, int, int *, char **);
75 static int mlg_roffblkout(void *, int);
76 static int mlg_roffspecial(void *, int, int *,
78 static int mlg_roffblkheadin(void *, int,
80 static int mlg_roffblkheadout(void *, int);
81 static int mlg_roffblkbodyin(void *, int,
83 static int mlg_roffblkbodyout(void *, int);
85 static int mlg_beginblk(struct md_mlg
*, enum md_ns
, int,
87 static int mlg_endblk(struct md_mlg
*, enum md_ns
, int);
88 static int mlg_begintag(struct md_mlg
*, enum md_ns
,
90 static int mlg_endtag(struct md_mlg
*, enum md_ns
, int);
91 static int mlg_indent(struct md_mlg
*);
92 static int mlg_newline(struct md_mlg
*);
93 static void mlg_mode(struct md_mlg
*, enum md_tok
);
94 static int mlg_data(struct md_mlg
*, int,
95 const char *, char *);
96 static void mlg_err(struct md_mlg
*, const char *,
97 const char *, char *);
98 static void mlg_warn(struct md_mlg
*, const char *,
99 const char *, char *);
100 static void mlg_msg(struct md_mlg
*, enum roffmsg
,
101 const char *, const char *, char *);
104 extern size_t strlcat(char *, const char *, size_t);
105 extern size_t strlcpy(char *, const char *, size_t);
110 mlg_beginblk(struct md_mlg
*p
, enum md_ns ns
, int tok
,
111 int *argc
, char **argv
)
114 if ( ! mlg_newline(p
))
116 if ( ! mlg_indent(p
))
118 } else if ( ! mlg_indent(p
))
122 mlg_mode(p
, MD_BLK_IN
);
124 if ( ! mlg_begintag(p
, ns
, tok
, argc
, argv
))
126 return(mlg_newline(p
));
131 mlg_endblk(struct md_mlg
*p
, enum md_ns ns
, int tok
)
137 if ( ! mlg_newline(p
))
139 if ( ! mlg_indent(p
))
141 } else if ( ! mlg_indent(p
))
144 mlg_mode(p
, MD_BLK_OUT
);
145 if ( ! mlg_endtag(p
, ns
, tok
))
147 return(mlg_newline(p
));
152 mlg_begintag(struct md_mlg
*p
, enum md_ns ns
, int tok
,
153 int *argc
, char **argv
)
157 /* TODO: extra rules for block/inline. */
159 if ( ! ml_nputs(p
->mbuf
, "<", 1, &p
->pos
))
162 res
= (*p
->begintag
)(p
->mbuf
, p
->args
, ns
, tok
,
163 argc
, (const char **)argv
);
168 p
->pos
+= (size_t)res
;
170 /* TODO: extra rules for block/inline. */
172 return(ml_nputs(p
->mbuf
, ">", 1, &p
->pos
));
177 mlg_endtag(struct md_mlg
*p
, enum md_ns ns
, int tok
)
181 /* TODO: extra rules for block/inline. */
183 if ( ! ml_nputs(p
->mbuf
, "</", 2, &p
->pos
))
186 res
= (*p
->endtag
)(p
->mbuf
, p
->args
, ns
, tok
);
191 p
->pos
+= (size_t)res
;
193 /* TODO: extra rules for block/inline. */
195 return(ml_nputs(p
->mbuf
, ">", 1, &p
->pos
));
200 mlg_indent(struct md_mlg
*p
)
204 count
= p
->indent
> MAXINDENT
? (size_t)MAXINDENT
: p
->indent
;
208 return(ml_putchars(p
->mbuf
, ' ', count
, &p
->pos
));
213 mlg_newline(struct md_mlg
*p
)
217 if ( ! ml_nputs(p
->mbuf
, "\n", 1, &dummy
))
225 mlg_mode(struct md_mlg
*p
, enum md_tok ns
)
228 p
->flags
&= ~ML_OVERRIDE_ONE
;
234 mlg_data(struct md_mlg
*p
, int space
, const char *start
, char *buf
)
241 assert(0 != p
->indent
);
243 if (ML_OVERRIDE_ONE
& p
->flags
||
244 ML_OVERRIDE_ALL
& p
->flags
)
248 while (*buf
&& isspace(*buf
))
255 while (*buf
&& ! isspace(*buf
))
264 if ( ! mlg_indent(p
))
267 c
= ml_nputstring(p
->mbuf
, bufp
, sz
, &p
->pos
);
269 mlg_err(p
, start
, bufp
, "invalid "
270 "character sequence");
273 mlg_warn(p
, start
, bufp
, "bogus "
274 "character sequence");
279 if (p
->indent
* INDENT
+ sz
>= COLUMNS
)
280 if ( ! mlg_newline(p
))
282 if ( ! (ML_OVERRIDE_ALL
& p
->flags
))
287 if (space
&& sz
+ p
->pos
>= COLUMNS
) {
288 if ( ! mlg_newline(p
))
290 if ( ! mlg_indent(p
))
293 if ( ! ml_nputs(p
->mbuf
, " ", 1, &p
->pos
))
297 c
= ml_nputstring(p
->mbuf
, bufp
, sz
, &p
->pos
);
299 mlg_err(p
, start
, bufp
, "invalid "
300 "character sequence");
303 mlg_warn(p
, start
, bufp
, "bogus "
304 "character sequence");
309 if ( ! (ML_OVERRIDE_ALL
& p
->flags
))
318 mlg_line(struct md_mlg
*p
, char *buf
)
321 return(roff_engine(p
->tree
, buf
));
326 mlg_exit(struct md_mlg
*p
, int flush
)
330 c
= roff_free(p
->tree
, flush
);
337 mlg_alloc(const struct md_args
*args
,
338 const struct md_rbuf
*rbuf
,
339 struct md_mbuf
*mbuf
,
340 ml_begintag begintag
, ml_endtag endtag
,
341 ml_begin begin
, ml_end end
)
346 cb
.roffhead
= mlg_roffhead
;
347 cb
.rofftail
= mlg_rofftail
;
348 cb
.roffin
= mlg_roffin
;
349 cb
.roffout
= mlg_roffout
;
350 cb
.roffblkin
= mlg_roffblkin
;
351 cb
.roffblkheadin
= mlg_roffblkheadin
;
352 cb
.roffblkheadout
= mlg_roffblkheadout
;
353 cb
.roffblkbodyin
= mlg_roffblkbodyin
;
354 cb
.roffblkbodyout
= mlg_roffblkbodyout
;
355 cb
.roffblkout
= mlg_roffblkout
;
356 cb
.roffspecial
= mlg_roffspecial
;
357 cb
.roffmsg
= mlg_roffmsg
;
358 cb
.roffdata
= mlg_roffdata
;
360 if (NULL
== (p
= calloc(1, sizeof(struct md_mlg
))))
366 p
->begintag
= begintag
;
371 if (NULL
== (p
->tree
= roff_alloc(&cb
, p
))) {
381 mlg_roffhead(void *arg
, const struct tm
*tm
, const char *os
,
382 const char *title
, const char *sec
, const char *vol
)
387 p
= (struct md_mlg
*)arg
;
389 mlg_mode(p
, MD_BLK_IN
);
390 if ( ! (*p
->begin
)(p
->mbuf
, p
->args
, tm
, os
, title
, sec
, vol
))
394 return(mlg_newline(p
));
399 mlg_rofftail(void *arg
)
404 p
= (struct md_mlg
*)arg
;
406 if (0 != p
->pos
&& ! mlg_newline(p
))
409 mlg_mode(p
, MD_BLK_OUT
);
410 if ( ! (*p
->end
)(p
->mbuf
, p
->args
))
413 return(mlg_newline(p
));
419 mlg_roffspecial(void *arg
, int tok
, int *argc
, char **argv
, char **more
)
424 p
= (struct md_mlg
*)arg
;
428 p
->flags
|= ML_OVERRIDE_ONE
;
432 if (0 == strcmp(*more
, "on"))
433 p
->flags
|= ML_OVERRIDE_ALL
;
435 p
->flags
&= ~ML_OVERRIDE_ALL
;
446 mlg_roffblkin(void *arg
, int tok
, int *argc
, char **argv
)
449 return(mlg_beginblk((struct md_mlg
*)arg
,
450 MD_NS_BLOCK
, tok
, argc
, argv
));
455 mlg_roffblkout(void *arg
, int tok
)
458 return(mlg_endblk((struct md_mlg
*)arg
, MD_NS_BLOCK
, tok
));
463 mlg_roffblkbodyin(void *arg
, int tok
, int *argc
, char **argv
)
466 return(mlg_beginblk((struct md_mlg
*)arg
,
467 MD_NS_BODY
, tok
, argc
, argv
));
472 mlg_roffblkbodyout(void *arg
, int tok
)
475 return(mlg_endblk((struct md_mlg
*)arg
, MD_NS_BODY
, tok
));
480 mlg_roffblkheadin(void *arg
, int tok
, int *argc
, char **argv
)
483 return(mlg_beginblk((struct md_mlg
*)arg
,
484 MD_NS_HEAD
, tok
, argc
, argv
));
489 mlg_roffblkheadout(void *arg
, int tok
)
492 return(mlg_endblk((struct md_mlg
*)arg
, MD_NS_HEAD
, tok
));
497 mlg_roffin(void *arg
, int tok
, int *argc
, char **argv
)
502 p
= (struct md_mlg
*)arg
;
504 /* FIXME: this part. */
506 if ( ! (ML_OVERRIDE_ONE
& p
->flags
) &&
507 ! (ML_OVERRIDE_ALL
& p
->flags
) &&
508 p
->pos
+ 11 > COLUMNS
)
509 if ( ! mlg_newline(p
))
512 if (0 != p
->pos
&& (MD_TEXT
== p
->last
||
513 MD_INLINE_OUT
== p
->last
)
514 && ! (ML_OVERRIDE_ONE
& p
->flags
)
515 && ! (ML_OVERRIDE_ALL
& p
->flags
))
516 if ( ! ml_nputs(p
->mbuf
, " ", 1, &p
->pos
))
519 if (0 == p
->pos
&& ! mlg_indent(p
))
522 mlg_mode(p
, MD_INLINE_IN
);
523 return(mlg_begintag(p
, MD_NS_INLINE
, tok
, argc
, argv
));
528 mlg_roffout(void *arg
, int tok
)
533 p
= (struct md_mlg
*)arg
;
535 if (0 == p
->pos
&& ! mlg_indent(p
))
538 mlg_mode(p
, MD_INLINE_OUT
);
539 return(mlg_endtag(p
, MD_NS_INLINE
, tok
));
544 mlg_roffmsg(void *arg
, enum roffmsg lvl
,
545 const char *buf
, const char *pos
, char *msg
)
548 mlg_msg((struct md_mlg
*)arg
, lvl
, buf
, pos
, msg
);
553 mlg_roffdata(void *arg
, int space
, const char *start
, char *buf
)
558 p
= (struct md_mlg
*)arg
;
560 if ( ! mlg_data(p
, space
, start
, buf
))
563 mlg_mode(p
, MD_TEXT
);
569 mlg_err(struct md_mlg
*p
, const char *buf
, const char *pos
, char *msg
)
572 mlg_msg(p
, ROFF_ERROR
, buf
, pos
, msg
);
577 mlg_warn(struct md_mlg
*p
, const char *buf
, const char *pos
, char *msg
)
580 mlg_msg(p
, ROFF_WARN
, buf
, pos
, msg
);
585 mlg_msg(struct md_mlg
*p
, enum roffmsg lvl
,
586 const char *buf
, const char *pos
, char *msg
)
592 if ( ! (MD_WARN_ALL
& p
->args
->warnings
))
604 (void)fprintf(stderr
, "%s:%zu: %s: %s (column %zu)\n",
605 p
->rbuf
->name
, p
->rbuf
->line
, level
,
608 (void)fprintf(stderr
, "%s: %s: %s\n",
609 p
->rbuf
->name
, level
, msg
);