adamc@117
|
1 #include <stdlib.h>
|
adamc@102
|
2 #include <stdio.h>
|
adamc@117
|
3 #include <string.h>
|
adamc@106
|
4 #include <ctype.h>
|
adamc@167
|
5 #include <setjmp.h>
|
adamc@167
|
6 #include <stdarg.h>
|
adamc@102
|
7
|
adamc@102
|
8 #include "types.h"
|
adamc@102
|
9
|
adamc@102
|
10 lw_unit lw_unit_v = {};
|
adamc@102
|
11
|
adamc@167
|
12 #define ERROR_BUF_LEN 1024
|
adamc@167
|
13
|
adamc@117
|
14 struct lw_context {
|
adamc@117
|
15 char *page, *page_front, *page_back;
|
adamc@136
|
16 char *heap, *heap_front, *heap_back;
|
adamc@144
|
17 char **inputs;
|
adamc@167
|
18
|
adamc@272
|
19 void *db;
|
adamc@272
|
20
|
adamc@167
|
21 jmp_buf jmp_buf;
|
adamc@167
|
22
|
adamc@167
|
23 char error_message[ERROR_BUF_LEN];
|
adamc@117
|
24 };
|
adamc@117
|
25
|
adamc@144
|
26 extern int lw_inputs_len;
|
adamc@144
|
27
|
adamc@136
|
28 lw_context lw_init(size_t page_len, size_t heap_len) {
|
adamc@117
|
29 lw_context ctx = malloc(sizeof(struct lw_context));
|
adamc@136
|
30
|
adamc@117
|
31 ctx->page_front = ctx->page = malloc(page_len);
|
adamc@117
|
32 ctx->page_back = ctx->page_front + page_len;
|
adamc@136
|
33
|
adamc@136
|
34 ctx->heap_front = ctx->heap = malloc(heap_len);
|
adamc@136
|
35 ctx->heap_back = ctx->heap_front + heap_len;
|
adamc@136
|
36
|
adamc@144
|
37 ctx->inputs = calloc(lw_inputs_len, sizeof(char *));
|
adamc@144
|
38
|
adamc@272
|
39 ctx->db = NULL;
|
adamc@272
|
40
|
adamc@167
|
41 ctx->error_message[0] = 0;
|
adamc@167
|
42
|
adamc@117
|
43 return ctx;
|
adamc@106
|
44 }
|
adamc@106
|
45
|
adamc@272
|
46 void lw_set_db(lw_context ctx, void *db) {
|
adamc@272
|
47 ctx->db = db;
|
adamc@272
|
48 }
|
adamc@272
|
49
|
adamc@272
|
50 void *lw_get_db(lw_context ctx) {
|
adamc@272
|
51 return ctx->db;
|
adamc@272
|
52 }
|
adamc@272
|
53
|
adamc@117
|
54 void lw_free(lw_context ctx) {
|
adamc@117
|
55 free(ctx->page);
|
adamc@136
|
56 free(ctx->heap);
|
adamc@144
|
57 free(ctx->inputs);
|
adamc@136
|
58 free(ctx);
|
adamc@136
|
59 }
|
adamc@136
|
60
|
adamc@167
|
61 void lw_reset_keep_request(lw_context ctx) {
|
adamc@138
|
62 ctx->page_front = ctx->page;
|
adamc@138
|
63 ctx->heap_front = ctx->heap;
|
adamc@167
|
64
|
adamc@167
|
65 ctx->error_message[0] = 0;
|
adamc@167
|
66 }
|
adamc@167
|
67
|
adamc@167
|
68 void lw_reset_keep_error_message(lw_context ctx) {
|
adamc@167
|
69 ctx->page_front = ctx->page;
|
adamc@167
|
70 ctx->heap_front = ctx->heap;
|
adamc@167
|
71 }
|
adamc@167
|
72
|
adamc@167
|
73 void lw_reset(lw_context ctx) {
|
adamc@167
|
74 lw_reset_keep_request(ctx);
|
adamc@144
|
75 memset(ctx->inputs, 0, lw_inputs_len * sizeof(char *));
|
adamc@144
|
76 }
|
adamc@144
|
77
|
adamc@272
|
78 void lw_db_init(lw_context);
|
adamc@167
|
79 void lw_handle(lw_context, char *);
|
adamc@167
|
80
|
adamc@272
|
81 failure_kind lw_begin_init(lw_context ctx) {
|
adamc@272
|
82 int r = setjmp(ctx->jmp_buf);
|
adamc@272
|
83
|
adamc@272
|
84 if (r == 0)
|
adamc@272
|
85 lw_db_init(ctx);
|
adamc@272
|
86
|
adamc@272
|
87 return r;
|
adamc@272
|
88 }
|
adamc@272
|
89
|
adamc@167
|
90 failure_kind lw_begin(lw_context ctx, char *path) {
|
adamc@190
|
91 int r = setjmp(ctx->jmp_buf);
|
adamc@190
|
92
|
adamc@190
|
93 if (r == 0)
|
adamc@167
|
94 lw_handle(ctx, path);
|
adamc@167
|
95
|
adamc@190
|
96 return r;
|
adamc@167
|
97 }
|
adamc@167
|
98
|
adamc@167
|
99 void lw_error(lw_context ctx, failure_kind fk, const char *fmt, ...) {
|
adamc@167
|
100 va_list ap;
|
adamc@167
|
101 va_start(ap, fmt);
|
adamc@167
|
102
|
adamc@167
|
103 vsnprintf(ctx->error_message, ERROR_BUF_LEN, fmt, ap);
|
adamc@167
|
104
|
adamc@190
|
105 longjmp(ctx->jmp_buf, fk);
|
adamc@167
|
106 }
|
adamc@167
|
107
|
adamc@167
|
108 char *lw_error_message(lw_context ctx) {
|
adamc@167
|
109 return ctx->error_message;
|
adamc@167
|
110 }
|
adamc@167
|
111
|
adamc@144
|
112 int lw_input_num(char*);
|
adamc@144
|
113
|
adamc@144
|
114 void lw_set_input(lw_context ctx, char *name, char *value) {
|
adamc@144
|
115 int n = lw_input_num(name);
|
adamc@144
|
116
|
adamc@169
|
117 if (n < 0)
|
adamc@169
|
118 lw_error(ctx, FATAL, "Bad input name %s", name);
|
adamc@144
|
119
|
adamc@169
|
120 if (n >= lw_inputs_len)
|
adamc@169
|
121 lw_error(ctx, FATAL, "For input name %s, index %d is out of range", name, n);
|
adamc@169
|
122
|
adamc@144
|
123 ctx->inputs[n] = value;
|
adamc@144
|
124
|
adamc@144
|
125 printf("[%d] %s = %s\n", n, name, value);
|
adamc@144
|
126 }
|
adamc@144
|
127
|
adamc@144
|
128 char *lw_get_input(lw_context ctx, int n) {
|
adamc@169
|
129 if (n < 0)
|
adamc@169
|
130 lw_error(ctx, FATAL, "Negative input index %d", n);
|
adamc@169
|
131 if (n >= lw_inputs_len)
|
adamc@169
|
132 lw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
|
adamc@144
|
133 printf("[%d] = %s\n", n, ctx->inputs[n]);
|
adamc@144
|
134 return ctx->inputs[n];
|
adamc@138
|
135 }
|
adamc@138
|
136
|
adamc@190
|
137 char *lw_get_optional_input(lw_context ctx, int n) {
|
adamc@190
|
138 if (n < 0)
|
adamc@190
|
139 lw_error(ctx, FATAL, "Negative input index %d", n);
|
adamc@190
|
140 if (n >= lw_inputs_len)
|
adamc@190
|
141 lw_error(ctx, FATAL, "Out-of-bounds input index %d", n);
|
adamc@190
|
142 printf("[%d] = %s\n", n, ctx->inputs[n]);
|
adamc@190
|
143 return (ctx->inputs[n] == NULL ? "" : ctx->inputs[n]);
|
adamc@190
|
144 }
|
adamc@190
|
145
|
adamc@136
|
146 static void lw_check_heap(lw_context ctx, size_t extra) {
|
adamc@136
|
147 if (ctx->heap_back - ctx->heap_front < extra) {
|
adamc@136
|
148 size_t desired = ctx->heap_back - ctx->heap_front + extra, next;
|
adamc@136
|
149 char *new_heap;
|
adamc@136
|
150
|
adamc@136
|
151 for (next = ctx->heap_back - ctx->heap_front; next < desired; next *= 2);
|
adamc@136
|
152
|
adamc@136
|
153 new_heap = realloc(ctx->heap, next);
|
adamc@169
|
154 ctx->heap_front = new_heap;
|
adamc@169
|
155 ctx->heap_back = new_heap + next;
|
adamc@136
|
156
|
adamc@136
|
157 if (new_heap != ctx->heap) {
|
adamc@136
|
158 ctx->heap = new_heap;
|
adamc@169
|
159 lw_error(ctx, UNLIMITED_RETRY, "Couldn't allocate new heap chunk contiguously");
|
adamc@136
|
160 }
|
adamc@136
|
161
|
adamc@169
|
162 ctx->heap = new_heap;
|
adamc@136
|
163 }
|
adamc@136
|
164 }
|
adamc@136
|
165
|
adamc@136
|
166 void *lw_malloc(lw_context ctx, size_t len) {
|
adamc@136
|
167 void *result;
|
adamc@136
|
168
|
adamc@136
|
169 lw_check_heap(ctx, len);
|
adamc@136
|
170
|
adamc@136
|
171 result = ctx->heap_front;
|
adamc@136
|
172 ctx->heap_front += len;
|
adamc@136
|
173 return result;
|
adamc@117
|
174 }
|
adamc@117
|
175
|
adamc@117
|
176 int lw_really_send(int sock, const void *buf, ssize_t len) {
|
adamc@117
|
177 while (len > 0) {
|
adamc@117
|
178 ssize_t n = send(sock, buf, len, 0);
|
adamc@117
|
179
|
adamc@117
|
180 if (n < 0)
|
adamc@117
|
181 return n;
|
adamc@117
|
182
|
adamc@117
|
183 buf += n;
|
adamc@117
|
184 len -= n;
|
adamc@117
|
185 }
|
adamc@117
|
186
|
adamc@117
|
187 return 0;
|
adamc@117
|
188 }
|
adamc@117
|
189
|
adamc@117
|
190 int lw_send(lw_context ctx, int sock) {
|
adamc@117
|
191 return lw_really_send(sock, ctx->page, ctx->page_front - ctx->page);
|
adamc@117
|
192 }
|
adamc@117
|
193
|
adamc@117
|
194 static void lw_check(lw_context ctx, size_t extra) {
|
adamc@117
|
195 size_t desired = ctx->page_back - ctx->page_front + extra, next;
|
adamc@117
|
196 char *new_page;
|
adamc@117
|
197
|
adamc@117
|
198 for (next = ctx->page_back - ctx->page_front; next < desired; next *= 2);
|
adamc@117
|
199
|
adamc@117
|
200 new_page = realloc(ctx->page, next);
|
adamc@117
|
201 ctx->page_front = new_page + (ctx->page_front - ctx->page);
|
adamc@117
|
202 ctx->page_back = new_page + (ctx->page_back - ctx->page);
|
adamc@117
|
203 ctx->page = new_page;
|
adamc@117
|
204 }
|
adamc@117
|
205
|
adamc@117
|
206 static void lw_writec_unsafe(lw_context ctx, char c) {
|
adamc@117
|
207 *(ctx->page_front)++ = c;
|
adamc@117
|
208 }
|
adamc@117
|
209
|
adamc@117
|
210 void lw_writec(lw_context ctx, char c) {
|
adamc@117
|
211 lw_check(ctx, 1);
|
adamc@117
|
212 lw_writec_unsafe(ctx, c);
|
adamc@117
|
213 }
|
adamc@117
|
214
|
adamc@117
|
215 static void lw_write_unsafe(lw_context ctx, const char* s) {
|
adamc@117
|
216 int len = strlen(s);
|
adamc@117
|
217 memcpy(ctx->page_front, s, len);
|
adamc@117
|
218 ctx->page_front += len;
|
adamc@117
|
219 }
|
adamc@117
|
220
|
adamc@117
|
221 void lw_write(lw_context ctx, const char* s) {
|
adamc@183
|
222 lw_check(ctx, strlen(s) + 1);
|
adamc@117
|
223 lw_write_unsafe(ctx, s);
|
adamc@183
|
224 *ctx->page_front = 0;
|
adamc@102
|
225 }
|
adamc@106
|
226
|
adamc@135
|
227
|
adamc@136
|
228 #define INTS_MAX 50
|
adamc@136
|
229 #define FLOATS_MAX 100
|
adamc@136
|
230
|
adamc@136
|
231 char *lw_Basis_attrifyInt(lw_context ctx, lw_Basis_int n) {
|
adamc@136
|
232 char *result;
|
adamc@136
|
233 int len;
|
adamc@136
|
234 lw_check_heap(ctx, INTS_MAX);
|
adamc@136
|
235 result = ctx->heap_front;
|
adamc@276
|
236 sprintf(result, "%lld%n", n, &len);
|
adamc@137
|
237 ctx->heap_front += len+1;
|
adamc@136
|
238 return result;
|
adamc@106
|
239 }
|
adamc@106
|
240
|
adamc@136
|
241 char *lw_Basis_attrifyFloat(lw_context ctx, lw_Basis_float n) {
|
adamc@136
|
242 char *result;
|
adamc@136
|
243 int len;
|
adamc@137
|
244 lw_check_heap(ctx, FLOATS_MAX);
|
adamc@136
|
245 result = ctx->heap_front;
|
adamc@136
|
246 sprintf(result, "%g%n", n, &len);
|
adamc@137
|
247 ctx->heap_front += len+1;
|
adamc@136
|
248 return result;
|
adamc@106
|
249 }
|
adamc@106
|
250
|
adamc@136
|
251 char *lw_Basis_attrifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@136
|
252 int len = strlen(s);
|
adamc@136
|
253 char *result, *p;
|
adamc@137
|
254 lw_check_heap(ctx, len * 6 + 1);
|
adamc@136
|
255
|
adamc@136
|
256 result = p = ctx->heap_front;
|
adamc@136
|
257
|
adamc@136
|
258 for (; *s; s++) {
|
adamc@136
|
259 char c = *s;
|
adamc@136
|
260
|
adamc@136
|
261 if (c == '"') {
|
adamc@136
|
262 strcpy(p, """);
|
adamc@136
|
263 p += 6;
|
adamc@136
|
264 } else if (c == '&') {
|
adamc@136
|
265 strcpy(p, "&");
|
adamc@136
|
266 p += 5;
|
adamc@136
|
267 }
|
adamc@136
|
268 else if (isprint(c))
|
adamc@136
|
269 *p++ = c;
|
adamc@136
|
270 else {
|
adamc@136
|
271 int len2;
|
adamc@136
|
272 sprintf(p, "&#%d;%n", c, &len2);
|
adamc@136
|
273 p += len2;
|
adamc@136
|
274 }
|
adamc@136
|
275 }
|
adamc@136
|
276
|
adamc@137
|
277 *p++ = 0;
|
adamc@136
|
278 ctx->heap_front = p;
|
adamc@136
|
279 return result;
|
adamc@106
|
280 }
|
adamc@106
|
281
|
adamc@117
|
282 static void lw_Basis_attrifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
|
adamc@117
|
283 int len;
|
adamc@117
|
284
|
adamc@276
|
285 sprintf(ctx->page_front, "%lld%n", n, &len);
|
adamc@117
|
286 ctx->page_front += len;
|
adamc@106
|
287 }
|
adamc@106
|
288
|
adamc@117
|
289 void lw_Basis_attrifyInt_w(lw_context ctx, lw_Basis_int n) {
|
adamc@117
|
290 lw_check(ctx, INTS_MAX);
|
adamc@117
|
291 lw_Basis_attrifyInt_w_unsafe(ctx, n);
|
adamc@106
|
292 }
|
adamc@106
|
293
|
adamc@117
|
294 void lw_Basis_attrifyFloat_w(lw_context ctx, lw_Basis_float n) {
|
adamc@117
|
295 int len;
|
adamc@117
|
296
|
adamc@117
|
297 lw_check(ctx, FLOATS_MAX);
|
adamc@117
|
298 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@117
|
299 ctx->page_front += len;
|
adamc@117
|
300 }
|
adamc@117
|
301
|
adamc@117
|
302 void lw_Basis_attrifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@117
|
303 lw_check(ctx, strlen(s) * 6);
|
adamc@117
|
304
|
adamc@106
|
305 for (; *s; s++) {
|
adamc@106
|
306 char c = *s;
|
adamc@106
|
307
|
adamc@106
|
308 if (c == '"')
|
adamc@117
|
309 lw_write_unsafe(ctx, """);
|
adamc@136
|
310 else if (c == '&')
|
adamc@136
|
311 lw_write_unsafe(ctx, "&");
|
adamc@106
|
312 else if (isprint(c))
|
adamc@117
|
313 lw_writec_unsafe(ctx, c);
|
adamc@106
|
314 else {
|
adamc@117
|
315 lw_write_unsafe(ctx, "&#");
|
adamc@117
|
316 lw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@117
|
317 lw_writec_unsafe(ctx, ';');
|
adamc@106
|
318 }
|
adamc@106
|
319 }
|
adamc@106
|
320 }
|
adamc@120
|
321
|
adamc@120
|
322
|
adamc@137
|
323 char *lw_Basis_urlifyInt(lw_context ctx, lw_Basis_int n) {
|
adamc@137
|
324 int len;
|
adamc@137
|
325 char *r;
|
adamc@137
|
326
|
adamc@137
|
327 lw_check_heap(ctx, INTS_MAX);
|
adamc@137
|
328 r = ctx->heap_front;
|
adamc@276
|
329 sprintf(r, "%lld%n", n, &len);
|
adamc@137
|
330 ctx->heap_front += len+1;
|
adamc@137
|
331 return r;
|
adamc@120
|
332 }
|
adamc@120
|
333
|
adamc@137
|
334 char *lw_Basis_urlifyFloat(lw_context ctx, lw_Basis_float n) {
|
adamc@137
|
335 int len;
|
adamc@137
|
336 char *r;
|
adamc@137
|
337
|
adamc@137
|
338 lw_check_heap(ctx, FLOATS_MAX);
|
adamc@137
|
339 r = ctx->heap_front;
|
adamc@137
|
340 sprintf(r, "%g%n", n, &len);
|
adamc@137
|
341 ctx->heap_front += len+1;
|
adamc@137
|
342 return r;
|
adamc@120
|
343 }
|
adamc@120
|
344
|
adamc@137
|
345 char *lw_Basis_urlifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@137
|
346 char *r, *p;
|
adamc@137
|
347
|
adamc@137
|
348 lw_check_heap(ctx, strlen(s) * 3 + 1);
|
adamc@137
|
349
|
adamc@137
|
350 for (r = p = ctx->heap_front; *s; s++) {
|
adamc@137
|
351 char c = *s;
|
adamc@137
|
352
|
adamc@137
|
353 if (c == ' ')
|
adamc@137
|
354 *p++ = '+';
|
adamc@137
|
355 else if (isalnum(c))
|
adamc@137
|
356 *p++ = c;
|
adamc@137
|
357 else {
|
adamc@137
|
358 sprintf(p, "%%%02X", c);
|
adamc@137
|
359 p += 3;
|
adamc@137
|
360 }
|
adamc@137
|
361 }
|
adamc@137
|
362
|
adamc@137
|
363 *p++ = 0;
|
adamc@137
|
364 ctx->heap_front = p;
|
adamc@137
|
365 return r;
|
adamc@120
|
366 }
|
adamc@120
|
367
|
adamc@186
|
368 char *lw_Basis_urlifyBool(lw_context ctx, lw_Basis_bool b) {
|
adamc@189
|
369 if (b == lw_Basis_False)
|
adamc@186
|
370 return "0";
|
adamc@186
|
371 else
|
adamc@186
|
372 return "1";
|
adamc@186
|
373 }
|
adamc@186
|
374
|
adamc@120
|
375 static void lw_Basis_urlifyInt_w_unsafe(lw_context ctx, lw_Basis_int n) {
|
adamc@120
|
376 int len;
|
adamc@120
|
377
|
adamc@276
|
378 sprintf(ctx->page_front, "%lld%n", n, &len);
|
adamc@120
|
379 ctx->page_front += len;
|
adamc@120
|
380 }
|
adamc@120
|
381
|
adamc@120
|
382 void lw_Basis_urlifyInt_w(lw_context ctx, lw_Basis_int n) {
|
adamc@120
|
383 lw_check(ctx, INTS_MAX);
|
adamc@120
|
384 lw_Basis_urlifyInt_w_unsafe(ctx, n);
|
adamc@120
|
385 }
|
adamc@120
|
386
|
adamc@120
|
387 void lw_Basis_urlifyFloat_w(lw_context ctx, lw_Basis_float n) {
|
adamc@120
|
388 int len;
|
adamc@120
|
389
|
adamc@120
|
390 lw_check(ctx, FLOATS_MAX);
|
adamc@120
|
391 sprintf(ctx->page_front, "%g%n", n, &len);
|
adamc@120
|
392 ctx->page_front += len;
|
adamc@120
|
393 }
|
adamc@120
|
394
|
adamc@120
|
395 void lw_Basis_urlifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@120
|
396 lw_check(ctx, strlen(s) * 3);
|
adamc@120
|
397
|
adamc@120
|
398 for (; *s; s++) {
|
adamc@120
|
399 char c = *s;
|
adamc@120
|
400
|
adamc@120
|
401 if (c == ' ')
|
adamc@120
|
402 lw_writec_unsafe(ctx, '+');
|
adamc@120
|
403 else if (isalnum(c))
|
adamc@120
|
404 lw_writec_unsafe(ctx, c);
|
adamc@120
|
405 else {
|
adamc@120
|
406 sprintf(ctx->page_front, "%%%02X", c);
|
adamc@120
|
407 ctx->page_front += 3;
|
adamc@120
|
408 }
|
adamc@120
|
409 }
|
adamc@120
|
410 }
|
adamc@120
|
411
|
adamc@186
|
412 void lw_Basis_urlifyBool_w(lw_context ctx, lw_Basis_bool b) {
|
adamc@189
|
413 if (b == lw_Basis_False)
|
adamc@186
|
414 lw_writec(ctx, '0');
|
adamc@186
|
415 else
|
adamc@186
|
416 lw_writec(ctx, '1');
|
adamc@186
|
417 }
|
adamc@186
|
418
|
adamc@120
|
419
|
adamc@144
|
420 static char *lw_unurlify_advance(char *s) {
|
adamc@144
|
421 char *new_s = strchr(s, '/');
|
adamc@120
|
422
|
adamc@120
|
423 if (new_s)
|
adamc@120
|
424 *new_s++ = 0;
|
adamc@120
|
425 else
|
adamc@144
|
426 new_s = strchr(s, 0);
|
adamc@144
|
427
|
adamc@144
|
428 return new_s;
|
adamc@144
|
429 }
|
adamc@144
|
430
|
adamc@186
|
431 lw_Basis_int lw_Basis_unurlifyInt(lw_context ctx, char **s) {
|
adamc@144
|
432 char *new_s = lw_unurlify_advance(*s);
|
adamc@276
|
433 lw_Basis_int r;
|
adamc@120
|
434
|
adamc@276
|
435 r = atoll(*s);
|
adamc@120
|
436 *s = new_s;
|
adamc@120
|
437 return r;
|
adamc@120
|
438 }
|
adamc@120
|
439
|
adamc@186
|
440 lw_Basis_float lw_Basis_unurlifyFloat(lw_context ctx, char **s) {
|
adamc@144
|
441 char *new_s = lw_unurlify_advance(*s);
|
adamc@276
|
442 lw_Basis_float r;
|
adamc@120
|
443
|
adamc@120
|
444 r = atof(*s);
|
adamc@120
|
445 *s = new_s;
|
adamc@120
|
446 return r;
|
adamc@120
|
447 }
|
adamc@120
|
448
|
adamc@169
|
449 static lw_Basis_string lw_unurlifyString_to(lw_context ctx, char *r, char *s) {
|
adamc@144
|
450 char *s1, *s2;
|
adamc@144
|
451 int n;
|
adamc@136
|
452
|
adamc@144
|
453 for (s1 = r, s2 = s; *s2; ++s1, ++s2) {
|
adamc@136
|
454 char c = *s2;
|
adamc@136
|
455
|
adamc@136
|
456 switch (c) {
|
adamc@136
|
457 case '+':
|
adamc@136
|
458 *s1 = ' ';
|
adamc@136
|
459 break;
|
adamc@136
|
460 case '%':
|
adamc@169
|
461 if (s2[1] == 0)
|
adamc@169
|
462 lw_error(ctx, FATAL, "Missing first character of escaped URL byte");
|
adamc@169
|
463 if (s2[2] == 0)
|
adamc@169
|
464 lw_error(ctx, FATAL, "Missing second character of escaped URL byte");
|
adamc@169
|
465 if (sscanf(s2+1, "%02X", &n) != 1)
|
adamc@169
|
466 lw_error(ctx, FATAL, "Invalid escaped URL byte starting at: %s", s2);
|
adamc@136
|
467 *s1 = n;
|
adamc@136
|
468 s2 += 2;
|
adamc@136
|
469 break;
|
adamc@136
|
470 default:
|
adamc@136
|
471 *s1 = c;
|
adamc@136
|
472 }
|
adamc@136
|
473 }
|
adamc@136
|
474 *s1++ = 0;
|
adamc@144
|
475 return s1;
|
adamc@144
|
476 }
|
adamc@144
|
477
|
adamc@186
|
478 lw_Basis_bool lw_Basis_unurlifyBool(lw_context ctx, char **s) {
|
adamc@186
|
479 char *new_s = lw_unurlify_advance(*s);
|
adamc@186
|
480 lw_Basis_bool r;
|
adamc@186
|
481
|
adamc@186
|
482 if (*s[0] == 0 || !strcmp(*s, "0") || !strcmp(*s, "off"))
|
adamc@189
|
483 r = lw_Basis_False;
|
adamc@186
|
484 else
|
adamc@189
|
485 r = lw_Basis_True;
|
adamc@186
|
486
|
adamc@186
|
487 *s = new_s;
|
adamc@186
|
488 return r;
|
adamc@186
|
489 }
|
adamc@186
|
490
|
adamc@186
|
491 lw_Basis_string lw_Basis_unurlifyString(lw_context ctx, char **s) {
|
adamc@144
|
492 char *new_s = lw_unurlify_advance(*s);
|
adamc@144
|
493 char *r, *s1, *s2;
|
adamc@144
|
494 int len, n;
|
adamc@144
|
495
|
adamc@200
|
496 len = strlen(*s);
|
adamc@144
|
497 lw_check_heap(ctx, len + 1);
|
adamc@144
|
498
|
adamc@144
|
499 r = ctx->heap_front;
|
adamc@200
|
500 ctx->heap_front = lw_unurlifyString_to(ctx, ctx->heap_front, *s);
|
adamc@136
|
501 *s = new_s;
|
adamc@136
|
502 return r;
|
adamc@120
|
503 }
|
adamc@135
|
504
|
adamc@135
|
505
|
adamc@136
|
506 char *lw_Basis_htmlifyString(lw_context ctx, lw_Basis_string s) {
|
adamc@137
|
507 char *r, *s2;
|
adamc@137
|
508
|
adamc@137
|
509 lw_check_heap(ctx, strlen(s) * 5 + 1);
|
adamc@137
|
510
|
adamc@137
|
511 for (r = s2 = ctx->heap_front; *s; s++) {
|
adamc@137
|
512 char c = *s;
|
adamc@137
|
513
|
adamc@137
|
514 switch (c) {
|
adamc@137
|
515 case '<':
|
adamc@137
|
516 strcpy(s2, "<");
|
adamc@137
|
517 s2 += 4;
|
adamc@137
|
518 break;
|
adamc@137
|
519 case '&':
|
adamc@137
|
520 strcpy(s2, "&");
|
adamc@137
|
521 s2 += 5;
|
adamc@137
|
522 break;
|
adamc@137
|
523 default:
|
adamc@137
|
524 if (isprint(c))
|
adamc@137
|
525 *s2++ = c;
|
adamc@137
|
526 else {
|
adamc@137
|
527 int len2;
|
adamc@137
|
528 sprintf(s2, "&#%d;%n", c, &len2);
|
adamc@137
|
529 s2 += len2;
|
adamc@137
|
530 }
|
adamc@137
|
531 }
|
adamc@137
|
532 }
|
adamc@137
|
533
|
adamc@137
|
534 *s2++ = 0;
|
adamc@137
|
535 ctx->heap_front = s2;
|
adamc@137
|
536 return r;
|
adamc@135
|
537 }
|
adamc@135
|
538
|
adamc@135
|
539 void lw_Basis_htmlifyString_w(lw_context ctx, lw_Basis_string s) {
|
adamc@135
|
540 lw_check(ctx, strlen(s) * 5);
|
adamc@135
|
541
|
adamc@135
|
542 for (; *s; s++) {
|
adamc@135
|
543 char c = *s;
|
adamc@135
|
544
|
adamc@135
|
545 switch (c) {
|
adamc@135
|
546 case '<':
|
adamc@135
|
547 lw_write_unsafe(ctx, "<");
|
adamc@135
|
548 break;
|
adamc@135
|
549 case '&':
|
adamc@135
|
550 lw_write_unsafe(ctx, "&");
|
adamc@135
|
551 break;
|
adamc@135
|
552 default:
|
adamc@135
|
553 if (isprint(c))
|
adamc@135
|
554 lw_writec_unsafe(ctx, c);
|
adamc@135
|
555 else {
|
adamc@135
|
556 lw_write_unsafe(ctx, "&#");
|
adamc@135
|
557 lw_Basis_attrifyInt_w_unsafe(ctx, c);
|
adamc@135
|
558 lw_writec_unsafe(ctx, ';');
|
adamc@135
|
559 }
|
adamc@135
|
560 }
|
adamc@135
|
561 }
|
adamc@135
|
562 }
|
adamc@180
|
563
|
adamc@180
|
564 lw_Basis_string lw_Basis_strcat(lw_context ctx, lw_Basis_string s1, lw_Basis_string s2) {
|
adamc@180
|
565 int len = strlen(s1) + strlen(s2) + 1;
|
adamc@180
|
566 char *s;
|
adamc@180
|
567
|
adamc@183
|
568 lw_check_heap(ctx, len);
|
adamc@180
|
569
|
adamc@180
|
570 s = ctx->heap_front;
|
adamc@180
|
571
|
adamc@180
|
572 strcpy(s, s1);
|
adamc@180
|
573 strcat(s, s2);
|
adamc@180
|
574 ctx->heap_front += len;
|
adamc@180
|
575
|
adamc@180
|
576 return s;
|
adamc@180
|
577 }
|
adamc@278
|
578
|
adamc@278
|
579 lw_Basis_string lw_Basis_strdup(lw_context ctx, lw_Basis_string s1) {
|
adamc@278
|
580 int len = strlen(s1) + 1;
|
adamc@278
|
581 char *s;
|
adamc@278
|
582
|
adamc@278
|
583 lw_check_heap(ctx, len);
|
adamc@278
|
584
|
adamc@278
|
585 s = ctx->heap_front;
|
adamc@278
|
586
|
adamc@278
|
587 strcpy(s, s1);
|
adamc@278
|
588 ctx->heap_front += len;
|
adamc@278
|
589
|
adamc@278
|
590 return s;
|
adamc@278
|
591 }
|