Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

trans_c.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: trans_c.c,v 1.29 2006/04/22 13:14:46 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <limits.h>
00015 #include <string.h>
00016 #include <u/libu.h>
00017 #include <klone/klone.h>
00018 #include <klone/translat.h>
00019 #include <klone/parser.h>
00020 #include <klone/utils.h>
00021 #include <klone/codecs.h>
00022 
00023 struct code_block_s;
00024 
00025 TAILQ_HEAD(code_block_list_s, code_block_s);
00026 struct code_block_s
00027 {
00028     TAILQ_ENTRY(code_block_s) np; /* next & prev pointers                   */
00029     char *buf;
00030     size_t sz;
00031     size_t code_line;
00032     const char *file_in;
00033 };
00034 
00035 typedef struct code_block_s code_block_t;
00036 typedef struct code_block_list_s code_block_list_t;
00037 
00038 struct lang_c_ctx_s
00039 {
00040     code_block_list_t code_blocks;
00041     trans_info_t *ti;
00042     size_t html_block_cnt;
00043 };
00044 
00045 typedef struct lang_c_ctx_s lang_c_ctx_t;
00046 
00047 static const char copyright_hdr[] =
00048     "/*\n"
00049     " * Copyright (c) 2005, 2006, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>\n"
00050     " * All rights reserved.\n"
00051     " *\n"
00052     " * This file is part of KLone, and as such it is subject to the license\n"
00053     " * stated in the LICENSE file which you have received as part of this\n"
00054     " * distribution\n"
00055     " *\n"
00056     " */\n";
00057 
00058 static void free_code_block(code_block_t *node)
00059 {
00060     if(node)
00061     {
00062         U_FREE(node->buf);
00063         U_FREE(node);
00064     }
00065 }
00066 
00067 static void free_code_blocks(lang_c_ctx_t *ctx)
00068 {
00069     code_block_t *node;
00070     code_block_list_t *head;
00071 
00072     dbg_ifb (ctx == NULL) return;
00073 
00074     head = &ctx->code_blocks;
00075     
00076     while((node = head->tqh_first) != NULL)
00077     {
00078         TAILQ_REMOVE(head, node, np);
00079         free_code_block(node);
00080     }
00081 }
00082 
00083 static int push_code_block(lang_c_ctx_t *ctx, parser_t *p, 
00084     const char *buf, size_t sz)
00085 {
00086     code_block_t *node;
00087     
00088     dbg_return_if (p == NULL, ~0);
00089     dbg_return_if (ctx == NULL, ~0);
00090  
00091     node = (code_block_t*)u_zalloc(sizeof(code_block_t));
00092     dbg_err_if(node == NULL);
00093 
00094     node->sz = sz;
00095     node->buf = (char*)u_malloc(sz);
00096     dbg_err_if(node->buf == NULL);
00097 
00098     node->code_line = p->code_line;
00099     node->file_in = ctx->ti->file_in;
00100 
00101     memcpy(node->buf, buf, sz);
00102 
00103     TAILQ_INSERT_TAIL(&ctx->code_blocks, node, np);
00104 
00105     return 0;
00106 err:
00107     if(node)
00108         free_code_block(node);
00109     return ~0;
00110 }
00111 
00112 static void print_header(parser_t *p, lang_c_ctx_t *ctx)
00113 {
00114     const char *file;
00115 
00116     dbg_ifb (p == NULL) return;
00117     dbg_ifb (ctx == NULL) return;
00118 
00119     (void)ctx;
00120 
00121     io_printf(p->out, "%s", copyright_hdr);
00122     io_printf(p->out, "#include <klone/emb.h>\n");
00123 
00124     file = ctx->ti->uri + strlen(ctx->ti->uri) - 1;
00125 
00126     for(; *file != '/' && file >= ctx->ti->uri; --file)
00127             ;
00128     io_printf(p->out, "static const char *SCRIPT_NAME = \"%s\";\n", 
00129                 ++file);
00130 }
00131 
00132 static int print_var_definition(parser_t *p, int comp, const char *varname, 
00133         const char *buf, size_t bufsz)
00134 {
00135     codec_t *zip = NULL;
00136     io_t *ios = NULL;
00137     int rc, i;
00138     unsigned char c;
00139 
00140     dbg_err_if(p == NULL);
00141     dbg_err_if(varname == NULL);
00142     dbg_err_if(buf == NULL);
00143 
00144     /* create an io_t around the HTML block */
00145     dbg_err_if(io_mem_create((char*)buf, bufsz, 0, &ios));
00146 
00147 #ifdef HAVE_LIBZ
00148     /* if compression is enabled zip the data block */
00149     if(comp)
00150     {
00151         /* apply a gzip codec */
00152         dbg_err_if(codec_gzip_create(GZIP_COMPRESS, &zip));
00153         dbg_err_if(io_codec_add_tail(ios, zip));
00154         zip = NULL; /* io_free() will free the codec */
00155     }
00156 #endif
00157 
00158     io_printf(p->out, "static unsigned char %s[] = {\n", varname);
00159 
00160     for(i = 1; (rc = io_getc(ios, (char*)&c)) > 0; ++i)
00161     {
00162         io_printf(p->out, "0x%02X, ", c);
00163         if(i % 12 == 0)
00164             io_printf(p->out, "\n");
00165     }
00166     dbg_err_if(rc < 0); /* input stream error */
00167 
00168     io_printf(p->out, "};\n");
00169 
00170     io_free(ios);
00171 
00172     return 0;
00173 err:
00174     if(zip)
00175         codec_free(zip);
00176     if(ios)
00177         io_free(ios);
00178     return ~0;
00179 }
00180 
00181 static void print_code_blocks(parser_t *p, lang_c_ctx_t *ctx)
00182 {
00183     code_block_t *node;
00184     code_block_list_t *head;
00185 
00186     dbg_ifb (p == NULL) return;
00187     dbg_ifb (ctx == NULL) return;
00188 
00189     io_printf(p->out, 
00190         "\n\n"
00191         "static void exec_page(request_t *request, response_t *response,    \n"
00192         "   session_t *session) {                                           \n"
00193         "    io_t *out = response_io(response);                             \n"
00194         );
00195 
00196     head = &ctx->code_blocks;
00197     for(node = head->tqh_first; node != NULL; node = node->np.tqe_next)
00198         io_write(p->out, node->buf, node->sz);
00199 
00200     io_printf(p->out, 
00201             "klone_script_exit:     \n"
00202             "   return;             \n"
00203             "}                      \n"
00204             );
00205 }
00206 
00207 static void print_static_page_block(io_t *out, lang_c_ctx_t *ctx)
00208 {
00209     dbg_ifb (out == NULL) return;
00210     dbg_ifb (ctx == NULL) return;
00211     dbg_ifb (ctx->ti == NULL) return;
00212  
00213     io_printf(out, 
00214         "static embfile_t e;                \n"
00215         "static void res_ctor(void)         \n"
00216         "{                                  \n"
00217         "   e.res.type = ET_FILE;           \n"
00218         "   e.res.filename = \"%s\";        \n"
00219         "   e.data = data;                  \n"
00220         "   e.size = sizeof(data);          \n"
00221         "   e.file_size = %u;               \n"
00222         "   e.mime_type = \"%s\";           \n"
00223         "   e.mtime = %lu;                  \n"
00224         "   e.comp = %d;                    \n"
00225         "   e.encrypted = %d;               \n"
00226         "}                                  \n",
00227         ctx->ti->uri, 
00228          /* file_size will be == to size if the file is not compressed */
00229         ctx->ti->file_size, 
00230         u_guess_mime_type(ctx->ti->uri), 
00231         ctx->ti->mtime, 
00232         ctx->ti->comp,
00233         ctx->ti->encrypt);
00234 }
00235 
00236 static void print_dynamic_page_block(io_t *out, lang_c_ctx_t *ctx)
00237 {
00238     dbg_ifb (out == NULL) return;
00239     dbg_ifb (ctx == NULL) return;
00240     dbg_ifb (ctx->ti == NULL) return;
00241 
00242     io_printf(out, 
00243         "static embpage_t e;                \n"
00244         "static void res_ctor(void)         \n"
00245         "{                                  \n"
00246         "   e.res.type = ET_PAGE;           \n"
00247         "   e.res.filename = \"%s\";        \n"
00248         "   e.run = exec_page;              \n"
00249         "}                                  \n",
00250         ctx->ti->uri);
00251 }
00252 
00253 static void print_register_block(io_t *out, lang_c_ctx_t *ctx)
00254 {
00255     char md5[MD5_DIGEST_BUFSZ];
00256 
00257     dbg_ifb (out == NULL) return;
00258     dbg_ifb (ctx == NULL) return;
00259     dbg_ifb (ctx->ti == NULL) return;
00260 
00261     u_md5(ctx->ti->uri, strlen(ctx->ti->uri), md5);
00262 
00263     io_printf(out, 
00264         "#ifdef __cplusplus                 \n"
00265         "extern \"C\" {                     \n"
00266         "#endif                             \n"
00267         "void module_init_%s(void)          \n"
00268         "{                                  \n"
00269         "    res_ctor();                    \n"
00270         "    emb_register((embres_t*)&e);   \n"
00271         "}                                  \n"
00272         "void module_term_%s(void)          \n"
00273         "{                                  \n"
00274         "    emb_unregister((embres_t*)&e); \n"
00275         "}                                  \n"
00276         "#ifdef __cplusplus                 \n"
00277         "}                                  \n"
00278         "#endif                             \n",
00279         md5, md5);
00280 }
00281 
00282 static int print_c_line(parser_t *p, lang_c_ctx_t *ctx)
00283 {
00284     dbg_err_if (p == NULL);
00285     dbg_err_if (ctx == NULL);
00286     dbg_err_if (ctx->ti == NULL);
00287 
00288     dbg_err_if(io_printf(p->out, "#line %d \"%s\"\n", p->code_line, 
00289         ctx->ti->file_in) < 0);
00290 
00291     return 0;
00292 err:
00293     return ~0;
00294 }
00295 
00296 static int process_declaration(parser_t *p, void *arg, const char *buf, 
00297         size_t sz)
00298 {
00299     u_unused_args(arg);
00300 
00301     dbg_err_if (p == NULL);
00302 
00303     dbg_err_if(io_write(p->out, buf, sz) < 0);
00304 
00305     return 0;
00306 err:
00307     return ~0;
00308 }
00309 
00310 static int process_expression(parser_t *p, void *arg, const char *buf, 
00311         size_t sz)
00312 {
00313     lang_c_ctx_t *ctx;
00314     const char before[] = "io_printf(out, \"%s\",";
00315     const char after[] = ");";
00316 
00317     dbg_err_if (p == NULL);
00318     dbg_err_if (arg == NULL);
00319 
00320     ctx = (lang_c_ctx_t*)arg;
00321     
00322     dbg_err_if(push_code_block(ctx, p, before, strlen(before)));
00323     dbg_err_if(push_code_block(ctx, p, buf, sz));
00324     dbg_err_if(push_code_block(ctx, p, after, strlen(after)));
00325 
00326     return 0;
00327 err:
00328     return ~0;
00329 }
00330 
00331 static int process_code(parser_t *p, void *arg, const char *buf, size_t sz)
00332 {
00333     lang_c_ctx_t *ctx;
00334 
00335     dbg_err_if (p == NULL);
00336     dbg_err_if (arg == NULL);
00337 
00338     ctx = (lang_c_ctx_t*)arg;
00339  
00340     dbg_err_if(push_code_block(ctx, p, buf, sz));
00341 
00342     return 0;
00343 err:
00344     return ~0;
00345 }
00346 
00347 static int translate_set_error(trans_info_t *ti, parser_t *p, const char *msg)
00348 {
00349     char file[U_FILENAME_MAX];
00350 
00351     dbg_err_if (ti == NULL);
00352     dbg_err_if (p == NULL || p->in == NULL);
00353  
00354     dbg_err_if(io_name_get(p->in, file, U_FILENAME_MAX));
00355 
00356     dbg_err_if(u_snprintf(ti->emsg, EMSG_BUFSZ, "[%s:%d] %s", 
00357         file, p->line, msg));
00358 
00359     return 0;
00360 err:
00361     return ~0;
00362 }
00363 
00364 static int cb_html_block(parser_t *p, void *arg, const char *buf, size_t sz)
00365 {
00366     enum { CODESZ = 128, VARNSZ = 32 };
00367     lang_c_ctx_t *ctx;
00368     char code[CODESZ];
00369     char varname[VARNSZ];
00370 
00371     dbg_err_if (p == NULL);
00372     dbg_err_if (arg == NULL);
00373 
00374     ctx = (lang_c_ctx_t*)arg;
00375 
00376     if(ctx->ti->comp)
00377     {   /* zip embedded HTML blocks */
00378         dbg_err_if(u_snprintf(varname, VARNSZ, "klone_html_zblock_%lu", 
00379             ctx->html_block_cnt));
00380 
00381         dbg_err_if(print_var_definition(p, 1 /* zip it */, varname, buf, sz));
00382 
00383         dbg_err_if(u_snprintf(code, CODESZ, 
00384             "\ndbg_if(u_io_unzip_copy(out, klone_html_zblock_%lu, "
00385             "   sizeof(klone_html_zblock_%lu)));\n", 
00386             ctx->html_block_cnt, ctx->html_block_cnt));
00387 
00388     } else {
00389         /* embedded HTML blocks will not be zipped */
00390         dbg_err_if(u_snprintf(varname, VARNSZ, "klone_html_%lu", 
00391             ctx->html_block_cnt));
00392 
00393         dbg_err_if(print_var_definition(p, 0, varname, buf, sz));
00394 
00395         dbg_err_if(u_snprintf(code, CODESZ, 
00396             "\ndbg_if(io_write(out, klone_html_%lu, "
00397             "   sizeof(klone_html_%lu)) < 0);\n", 
00398             ctx->html_block_cnt, ctx->html_block_cnt));
00399     }
00400 
00401     dbg_err_if(push_code_block(ctx, p, code, strlen(code)));
00402 
00403     ctx->html_block_cnt++;
00404 
00405     return 0;
00406 err:
00407     return ~0;
00408 }
00409 
00410 static int cb_code_block(parser_t *p, int cmd, void *arg, const char *buf, 
00411         size_t sz)
00412 {
00413     lang_c_ctx_t *ctx;
00414 
00415     dbg_err_if (p == NULL);
00416     dbg_err_if (arg == NULL);
00417 
00418     ctx = (lang_c_ctx_t *)arg;
00419 
00420     switch(cmd)
00421     {
00422     case 0: /* plain code block <% ... %> */
00423         process_code(p, arg, buf, sz);
00424         break;
00425     case '@': /* <%@ ... %> */
00426         dbg_err_if("the file should have already been preprocessed");
00427         break;
00428     case '!': /* <%! ... %> */
00429         process_declaration(p, arg, buf, sz);
00430         break;
00431     case '=': /* <%= ... %> */
00432         process_expression(p, arg, buf, sz);
00433         break;
00434     default:
00435         translate_set_error(ctx->ti, p, "bad command char after <%");
00436         warn_err("unknown code type");
00437     }
00438     return 0;
00439 err:
00440     return ~0;
00441 }
00442 
00443 /* translate a opaque file to a C unsigned char array */
00444 int translate_opaque_to_c(io_t *in, io_t *out, trans_info_t *ti)
00445 {
00446     lang_c_ctx_t ctx;
00447     int i = 0;
00448     ssize_t rc;
00449     unsigned char c;
00450 
00451     dbg_err_if (in == NULL);
00452     dbg_err_if (out == NULL);
00453     dbg_err_if (ti == NULL);
00454     
00455     memset(&ctx, 0, sizeof(lang_c_ctx_t));
00456     TAILQ_INIT(&ctx.code_blocks);
00457     ctx.ti = ti;
00458 
00459     io_printf(out, "%s", copyright_hdr);
00460     io_printf(out, "#include <klone/emb.h>\n");
00461 
00462     io_printf(out, "static unsigned char data[] = {\n");
00463 
00464     for(i = 1; (rc = io_getc(in, (char*)&c)) > 0; ++i)
00465     {
00466         io_printf(out, "0x%02X, ", c);
00467         if(i % 12 == 0)
00468             io_printf(out, "\n");
00469     }
00470     dbg_err_if(rc < 0); /* input stream error */
00471 
00472     io_printf(out, "};\n");
00473 
00474     print_static_page_block(out, &ctx);
00475     print_register_block(out, &ctx);
00476 
00477     return 0;
00478 err:
00479     return ~0;
00480 }
00481 
00482 int translate_script_to_c(io_t *in, io_t *out, trans_info_t *ti)
00483 {
00484     parser_t *p = NULL;
00485     lang_c_ctx_t ctx;
00486 
00487     dbg_return_if (in == NULL, ~0);
00488     dbg_return_if (out == NULL, ~0);
00489     dbg_return_if (ti == NULL, ~0);
00490     
00491     /* init the context obj */
00492     memset(&ctx, 0, sizeof(lang_c_ctx_t));
00493     TAILQ_INIT(&ctx.code_blocks);
00494     ctx.ti = ti;
00495 
00496     /* create a parse that reads from in and writes to out */
00497     dbg_err_if(parser_create(&p));
00498 
00499     parser_set_io(p, in, out);
00500 
00501     parser_set_cb_arg(p, &ctx);
00502     parser_set_cb_code(p, cb_code_block);
00503     parser_set_cb_html(p, cb_html_block);
00504 
00505     print_header(p, &ctx);
00506 
00507     dbg_err_if(parser_run(p));
00508 
00509     print_code_blocks(p, &ctx);
00510 
00511     print_dynamic_page_block(p->out, &ctx);
00512 
00513     print_register_block(p->out, &ctx);
00514 
00515     free_code_blocks(&ctx);
00516 
00517     parser_free(p);
00518 
00519     return 0;
00520 err:
00521     free_code_blocks(&ctx);
00522     if(p)
00523         parser_free(p);
00524     return ~0;
00525 }

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved