Add to git.
[monolith.git] / src / ml_smarttext.l
1 /* Monolith smart text. -*- C -*-
2  * - by Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: ml_smarttext.l,v 1.1 2002/12/08 17:29:17 rich Exp $
19  */
20
21 %{
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #endif
30
31 #include <pool.h>
32
33 #include "monolith.h"
34 #include "ml_smarttext.h"
35
36 /* This removes a warning message. */
37 #define YY_NO_UNPUT 1
38
39 static void emit_str (const char *s);
40 static void emit_strn (const char *str, const char *end);
41 static void emit_char (char c);
42 %}
43
44 %option noyywrap
45
46         /* Characters in URLs. */
47 URLCHAR [^ \t\)<>]
48
49         /* Characters in bold/italic/monospace text. */
50 ORDCHARS [[:alnum:] \t,\']
51
52 %%
53
54         /* URLs. */
55 [[:lower:]]+"://"{URLCHAR}+ {
56   emit_str ("<a href=\"");
57   emit_str (yytext);
58   emit_str ("\" target=\"_new\">");
59   emit_str (yytext);
60   emit_str ("</a>");
61 }
62
63         /* Special mailto: URLs. */
64         /* XXX Email addresses. */
65 mailto:{URLCHAR}+ {
66   emit_str ("<a href=\"");
67   emit_str (yytext);
68   emit_str ("\" target=\"_new\"><img src=\"/ml-icons/envelope.gif\">&nbsp;");
69   emit_str (yytext+7);
70   emit_str ("</a>");
71 }
72
73         /* Fractions - must appear before italics. */
74 "1/4"   emit_str ("&frac14;");
75 "1/2"   emit_str ("&frac12;");
76 "3/4"   emit_str ("&frac34;");
77
78         /* Special characters. */
79 "(C)"   emit_str ("&copy;");
80 "(R)"   emit_str ("&reg;");
81 "(TM)"  emit_str ("<sup>TM</sup>");
82
83         /* Bold, italic, monospace text. */
84 "*"{ORDCHARS}+"*" {
85   emit_str ("<b>");
86   emit_strn (yytext+1, &yytext[strlen (yytext)-1]);
87   emit_str ("</b>");
88 }
89 "/"{ORDCHARS}+"/" {
90   emit_str ("<i>");
91   emit_strn (yytext+1, &yytext[strlen (yytext)-1]);
92   emit_str ("</i>");
93 }
94 "="{ORDCHARS}+"=" {
95   emit_str ("<code>");
96   emit_strn (yytext+1, &yytext[strlen (yytext)-1]);
97   emit_str ("</code>");
98 }
99
100         /* Smileys. */
101 [:;][-oO][\)>] {
102   emit_str ("<img src=\"/ml-icons/smiley.gif\">");
103 }
104 [:;][-oO][\(<] {
105   emit_str ("<img src=\"/ml-icons/sad.gif\">");
106 }
107 [:;][-oO][pP] {
108   emit_str ("<img src=\"/ml-icons/tongue.gif\">");
109 }
110
111         /* HTML entities which need to be escaped. */
112 "&"     emit_str ("&amp;");
113 "<"     emit_str ("&lt;");
114 ">"     emit_str ("&gt;");
115 \"      emit_str ("&quot;");
116 \n      emit_str ("<br>");
117
118         /* Anything else just gets emitted as a normal character. */
119 .       emit_char (yytext[0]);
120
121 %%
122
123 /* These global variables control where the output gets sent.
124  * Note that because none of this code blocks, we don't need to
125  * worry about these globals getting corrupted.
126  */
127 static pool out_pool;           /* Pool for allocations. */
128 static char *out_str;           /* Output string. */
129 static int used, allocated;     /* Space used and allocated in the string. */
130
131 const char *
132 ml_smarttext_to_html (pool pool, const char *text)
133 {
134   YY_BUFFER_STATE buf;
135
136   /* Set up the global variables so that output goes to our string. */
137   out_pool = pool;
138   out_str = 0;
139   used = allocated = 0;
140
141   /* We're going to scan from this buffer (instead of stdin). */
142   buf = yy_scan_string (text);
143
144   /* Run the scanner. */
145   ml_smarttext_lex ();
146
147   /* Clean up. */
148   yy_delete_buffer (buf);
149
150   /* Tack an ASCII NUL on the end of the string to terminate it. */
151   emit_char ('\0');
152
153   return out_str;
154 }
155
156 static void
157 emit_str (const char *s)
158 {
159   while (*s) emit_char (*s++);
160 }
161
162 static void
163 emit_strn (const char *str, const char *end)
164 {
165   while (str < end) emit_char (*str++);
166 }
167
168 static void
169 emit_char (char c)
170 {
171   if (used >= allocated)
172     {
173       allocated += 32;
174       out_str = prealloc (out_pool, out_str, allocated);
175     }
176
177   out_str[used++] = c;
178 }