]>
git.cameronkatri.com Git - mandoc.git/blob - mlg.c
17ef1efd9a8217e8c3e7081a6d2c21c46e544dda
1 /* $Id: mlg.c,v 1.3 2008/12/03 21:27:56 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 *);
67 static int mlg_rofftail(void *);
68 static int mlg_roffin(void *, int, int *, char **);
69 static int mlg_roffdata(void *, int, char *);
70 static int mlg_roffout(void *, int);
71 static int mlg_roffblkin(void *, int, int *, char **);
72 static int mlg_roffblkout(void *, int);
73 static int mlg_roffspecial(void *, int, int *,
75 static int mlg_roffblkheadin(void *, int, int *, char **);
76 static int mlg_roffblkheadout(void *, int);
77 static int mlg_roffblkbodyin(void *, int, int *, char **);
78 static int mlg_roffblkbodyout(void *, int);
80 static int mlg_beginblk(struct md_mlg
*, enum md_ns
, int,
82 static int mlg_endblk(struct md_mlg
*, enum md_ns
, int);
83 static int mlg_begintag(struct md_mlg
*, enum md_ns
,
85 static int mlg_endtag(struct md_mlg
*, enum md_ns
, int);
86 static int mlg_indent(struct md_mlg
*);
87 static int mlg_newline(struct md_mlg
*);
88 static void mlg_mode(struct md_mlg
*, enum md_tok
);
89 static int mlg_data(struct md_mlg
*, int, char *);
92 extern size_t strlcat(char *, const char *, size_t);
93 extern size_t strlcpy(char *, const char *, size_t);
98 mlg_beginblk(struct md_mlg
*p
, enum md_ns ns
, int tok
,
99 int *argc
, char **argv
)
102 if ( ! mlg_newline(p
))
104 if ( ! mlg_indent(p
))
106 } else if ( ! mlg_indent(p
))
110 mlg_mode(p
, MD_BLK_IN
);
112 if ( ! mlg_begintag(p
, ns
, tok
, argc
, argv
))
114 return(mlg_newline(p
));
119 mlg_endblk(struct md_mlg
*p
, enum md_ns ns
, int tok
)
125 if ( ! mlg_newline(p
))
127 if ( ! mlg_indent(p
))
129 } else if ( ! mlg_indent(p
))
132 mlg_mode(p
, MD_BLK_OUT
);
133 if ( ! mlg_endtag(p
, ns
, tok
))
135 return(mlg_newline(p
));
140 mlg_begintag(struct md_mlg
*p
, enum md_ns ns
, int tok
,
141 int *argc
, char **argv
)
145 /* TODO: extra rules for block/inline. */
147 if ( ! ml_nputs(p
->mbuf
, "<", 1, &p
->pos
))
150 res
= (*p
->begintag
)(p
->mbuf
, p
->args
, ns
, tok
,
151 argc
, (const char **)argv
);
156 p
->pos
+= (size_t)res
;
158 /* TODO: extra rules for block/inline. */
160 return(ml_nputs(p
->mbuf
, ">", 1, &p
->pos
));
165 mlg_endtag(struct md_mlg
*p
, enum md_ns ns
, int tok
)
169 /* TODO: extra rules for block/inline. */
171 if ( ! ml_nputs(p
->mbuf
, "</", 2, &p
->pos
))
174 res
= (*p
->endtag
)(p
->mbuf
, p
->args
, ns
, tok
);
179 p
->pos
+= (size_t)res
;
181 /* TODO: extra rules for block/inline. */
183 return(ml_nputs(p
->mbuf
, ">", 1, &p
->pos
));
188 mlg_indent(struct md_mlg
*p
)
192 count
= p
->indent
> MAXINDENT
? (size_t)MAXINDENT
: p
->indent
;
196 return(ml_putchars(p
->mbuf
, ' ', count
, &p
->pos
));
201 mlg_newline(struct md_mlg
*p
)
205 if ( ! ml_nputs(p
->mbuf
, "\n", 1, &dummy
))
213 mlg_mode(struct md_mlg
*p
, enum md_tok ns
)
216 p
->flags
&= ~ML_OVERRIDE_ONE
;
222 mlg_data(struct md_mlg
*p
, int space
, char *buf
)
228 assert(0 != p
->indent
);
230 if (ML_OVERRIDE_ONE
& p
->flags
||
231 ML_OVERRIDE_ALL
& p
->flags
)
235 while (*buf
&& isspace(*buf
))
242 while (*buf
&& ! isspace(*buf
))
251 if ( ! mlg_indent(p
))
253 if ( ! ml_nputstring(p
->mbuf
, bufp
,
256 if (p
->indent
* INDENT
+ sz
>= COLUMNS
)
257 if ( ! mlg_newline(p
))
259 if ( ! (ML_OVERRIDE_ALL
& p
->flags
))
264 if (space
&& sz
+ p
->pos
>= COLUMNS
) {
265 if ( ! mlg_newline(p
))
267 if ( ! mlg_indent(p
))
270 if ( ! ml_nputs(p
->mbuf
, " ", 1, &p
->pos
))
274 if ( ! ml_nputstring(p
->mbuf
, bufp
, sz
, &p
->pos
))
277 if ( ! (ML_OVERRIDE_ALL
& p
->flags
))
286 mlg_line(struct md_mlg
*p
, char *buf
)
289 return(roff_engine(p
->tree
, buf
));
294 mlg_exit(struct md_mlg
*p
, int flush
)
298 c
= roff_free(p
->tree
, flush
);
305 mlg_alloc(const struct md_args
*args
,
306 const struct md_rbuf
*rbuf
,
307 struct md_mbuf
*mbuf
,
308 ml_begintag begintag
, ml_endtag endtag
,
309 ml_begin begin
, ml_end end
)
314 cb
.roffhead
= mlg_roffhead
;
315 cb
.rofftail
= mlg_rofftail
;
316 cb
.roffin
= mlg_roffin
;
317 cb
.roffout
= mlg_roffout
;
318 cb
.roffblkin
= mlg_roffblkin
;
319 cb
.roffblkheadin
= mlg_roffblkheadin
;
320 cb
.roffblkheadout
= mlg_roffblkheadout
;
321 cb
.roffblkbodyin
= mlg_roffblkbodyin
;
322 cb
.roffblkbodyout
= mlg_roffblkbodyout
;
323 cb
.roffblkout
= mlg_roffblkout
;
324 cb
.roffspecial
= mlg_roffspecial
;
325 cb
.roffmsg
= mlg_roffmsg
;
326 cb
.roffdata
= mlg_roffdata
;
328 if (NULL
== (p
= calloc(1, sizeof(struct md_mlg
))))
334 p
->begintag
= begintag
;
339 if (NULL
== (p
->tree
= roff_alloc(&cb
, p
))) {
349 mlg_roffhead(void *arg
)
354 p
= (struct md_mlg
*)arg
;
356 mlg_mode(p
, MD_BLK_IN
);
357 if ( ! (*p
->begin
)(p
->mbuf
, p
->args
))
361 return(mlg_newline(p
));
366 mlg_rofftail(void *arg
)
371 p
= (struct md_mlg
*)arg
;
373 if (0 != p
->pos
&& ! mlg_newline(p
))
376 mlg_mode(p
, MD_BLK_OUT
);
377 if ( ! (*p
->end
)(p
->mbuf
, p
->args
))
380 return(mlg_newline(p
));
386 mlg_roffspecial(void *arg
, int tok
, int *argc
, char **argv
, char **more
)
391 p
= (struct md_mlg
*)arg
;
395 p
->flags
|= ML_OVERRIDE_ONE
;
399 if (0 == strcmp(*more
, "on"))
400 p
->flags
|= ML_OVERRIDE_ALL
;
402 p
->flags
&= ~ML_OVERRIDE_ALL
;
413 mlg_roffblkin(void *arg
, int tok
, int *argc
, char **argv
)
416 return(mlg_beginblk((struct md_mlg
*)arg
,
417 MD_NS_BLOCK
, tok
, argc
, argv
));
422 mlg_roffblkout(void *arg
, int tok
)
425 return(mlg_endblk((struct md_mlg
*)arg
, MD_NS_BLOCK
, tok
));
430 mlg_roffblkbodyin(void *arg
, int tok
, int *argc
, char **argv
)
433 return(mlg_beginblk((struct md_mlg
*)arg
,
434 MD_NS_BODY
, tok
, argc
, argv
));
439 mlg_roffblkbodyout(void *arg
, int tok
)
442 return(mlg_endblk((struct md_mlg
*)arg
, MD_NS_BODY
, tok
));
447 mlg_roffblkheadin(void *arg
, int tok
, int *argc
, char **argv
)
450 return(mlg_beginblk((struct md_mlg
*)arg
,
451 MD_NS_HEAD
, tok
, argc
, argv
));
456 mlg_roffblkheadout(void *arg
, int tok
)
459 return(mlg_endblk((struct md_mlg
*)arg
, MD_NS_HEAD
, tok
));
464 mlg_roffin(void *arg
, int tok
, int *argc
, char **argv
)
469 p
= (struct md_mlg
*)arg
;
471 /* FIXME: this part. */
473 if ( ! (ML_OVERRIDE_ONE
& p
->flags
) &&
474 ! (ML_OVERRIDE_ALL
& p
->flags
) &&
475 p
->pos
+ 11 > COLUMNS
)
476 if ( ! mlg_newline(p
))
479 if (0 != p
->pos
&& (MD_TEXT
== p
->last
||
480 MD_INLINE_OUT
== p
->last
)
481 && ! (ML_OVERRIDE_ONE
& p
->flags
)
482 && ! (ML_OVERRIDE_ALL
& p
->flags
))
483 if ( ! ml_nputs(p
->mbuf
, " ", 1, &p
->pos
))
486 if (0 == p
->pos
&& ! mlg_indent(p
))
489 mlg_mode(p
, MD_INLINE_IN
);
490 return(mlg_begintag(p
, MD_NS_INLINE
, tok
, argc
, argv
));
495 mlg_roffout(void *arg
, int tok
)
500 p
= (struct md_mlg
*)arg
;
502 if (0 == p
->pos
&& ! mlg_indent(p
))
505 mlg_mode(p
, MD_INLINE_OUT
);
506 return(mlg_endtag(p
, MD_NS_INLINE
, tok
));
511 mlg_roffmsg(void *arg
, enum roffmsg lvl
,
512 const char *buf
, const char *pos
, char *msg
)
518 p
= (struct md_mlg
*)arg
;
522 if ( ! (MD_WARN_ALL
& p
->args
->warnings
))
534 (void)fprintf(stderr
, "%s:%zu: %s: %s (column %zu)\n",
535 p
->rbuf
->name
, p
->rbuf
->line
, level
,
538 (void)fprintf(stderr
, "%s: %s: %s\n",
539 p
->rbuf
->name
, level
, msg
);
545 mlg_roffdata(void *arg
, int space
, char *buf
)
550 p
= (struct md_mlg
*)arg
;
552 if ( ! mlg_data(p
, space
, buf
))
555 mlg_mode(p
, MD_TEXT
);