]>
git.cameronkatri.com Git - mandoc.git/blob - mandoc.c
1 /* $Id: mandoc.c,v 1.36 2011/01/03 22:42:37 schwarze Exp $ */
3 * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <sys/types.h>
32 #include "libmandoc.h"
34 static int a2time(time_t *, const char *, const char *);
38 mandoc_special(char *p
)
98 if ('+' == *p
|| '-' == *p
) {
122 if (ASCII_HYPH
== *p
)
124 if ('+' == *p
|| '-' == *p
) {
130 /* Handle embedded numerical subexp or escape. */
133 while (*p
&& ')' != *p
)
135 i
= mandoc_special(--p
);
145 } else if ('\\' == *p
) {
146 if (0 == (i
= mandoc_special(p
)))
195 if (0 == (i
= mandoc_special(p
)))
198 return(*p
? (int)(p
- sv
) : 0);
216 for ( ; *p
&& term
!= *p
; p
++)
217 if (ASCII_HYPH
== *p
)
219 return(*p
? (int)(p
- sv
) : 0);
222 for (i
= 0; *p
&& i
< len
; i
++, p
++)
223 if (ASCII_HYPH
== *p
)
225 return(i
== len
? (int)(p
- sv
) : 0);
230 mandoc_calloc(size_t num
, size_t size
)
234 ptr
= calloc(num
, size
);
237 exit((int)MANDOCLEVEL_SYSERR
);
245 mandoc_malloc(size_t size
)
252 exit((int)MANDOCLEVEL_SYSERR
);
260 mandoc_realloc(void *ptr
, size_t size
)
263 ptr
= realloc(ptr
, size
);
266 exit((int)MANDOCLEVEL_SYSERR
);
274 mandoc_strdup(const char *ptr
)
281 exit((int)MANDOCLEVEL_SYSERR
);
288 * Parse a quoted or unquoted roff-style request or macro argument.
289 * Return a pointer to the parsed argument, which is either the original
290 * pointer or advanced by one byte in case the argument is quoted.
291 * Null-terminate the argument in place.
292 * Collapse pairs of quotes inside quoted arguments.
293 * Advance the argument pointer to the next argument,
294 * or to the null byte terminating the argument line.
297 mandoc_getarg(char **cpp
, mandocmsg msg
, void *data
, int ln
, int *pos
)
300 int quoted
, pairs
, white
;
302 /* Quoting can only start with a new word. */
312 for (cp
= start
; '\0' != *cp
; cp
++) {
313 /* Move left after quoted quotes and escaped backslashes. */
318 /* Poor man's copy mode. */
321 } else if (0 == quoted
&& ' ' == cp
[1])
322 /* Skip escaped blanks. */
324 } else if (0 == quoted
) {
326 /* Unescaped blanks end unquoted args. */
330 } else if ('"' == cp
[0]) {
332 /* Quoted quotes collapse. */
336 /* Unquoted quotes end quoted args. */
343 /* Quoted argument without a closing quote. */
344 if (1 == quoted
&& msg
)
345 (*msg
)(MANDOCERR_BADQUOTE
, data
, ln
, *pos
, NULL
);
347 /* Null-terminate this argument and move to the next one. */
355 *pos
+= (cp
- start
) + (quoted
? 1 : 0);
358 if ('\0' == *cp
&& msg
&& (white
|| ' ' == cp
[-1]))
359 (*msg
)(MANDOCERR_EOLNSPACE
, data
, ln
, *pos
, NULL
);
366 a2time(time_t *t
, const char *fmt
, const char *p
)
371 memset(&tm
, 0, sizeof(struct tm
));
373 pp
= strptime(p
, fmt
, &tm
);
374 if (NULL
!= pp
&& '\0' == *pp
) {
384 * Convert from a manual date string (see mdoc(7) and man(7)) into a
385 * date according to the stipulated date type.
388 mandoc_a2time(int flags
, const char *p
)
392 if (MTIME_MDOCDATE
& flags
) {
393 if (0 == strcmp(p
, "$" "Mdocdate$"))
395 if (a2time(&t
, "$" "Mdocdate: %b %d %Y $", p
))
399 if (MTIME_CANONICAL
& flags
|| MTIME_REDUCED
& flags
)
400 if (a2time(&t
, "%b %d, %Y", p
))
403 if (MTIME_ISO_8601
& flags
)
404 if (a2time(&t
, "%Y-%m-%d", p
))
407 if (MTIME_REDUCED
& flags
) {
408 if (a2time(&t
, "%d, %Y", p
))
410 if (a2time(&t
, "%Y", p
))
419 mandoc_eos(const char *p
, size_t sz
, int enclosed
)
428 * End-of-sentence recognition must include situations where
429 * some symbols, such as `)', allow prior EOS punctuation to
434 for (q
= p
+ (int)sz
- 1; q
>= p
; q
--) {
454 return(found
&& (!enclosed
|| isalnum((unsigned char)*q
)));
458 return(found
&& !enclosed
);
463 mandoc_hyph(const char *start
, const char *c
)
467 * Choose whether to break at a hyphenated character. We only
468 * do this if it's free-standing within a word.
471 /* Skip first/last character of buffer. */
472 if (c
== start
|| '\0' == *(c
+ 1))
474 /* Skip first/last character of word. */
475 if ('\t' == *(c
+ 1) || '\t' == *(c
- 1))
477 if (' ' == *(c
+ 1) || ' ' == *(c
- 1))
479 /* Skip double invocations. */
480 if ('-' == *(c
+ 1) || '-' == *(c
- 1))
483 if ('\\' == *(c
- 1))