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

translat.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 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: translat.c,v 1.23 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 <ctype.h>
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 #include <limits.h>
00018 #ifdef HAVE_LIBOPENSSL
00019 #include <openssl/evp.h>
00020 #endif /* HAVE_LIBOPENSSL */
00021 #include <klone/klone.h>
00022 #include <klone/translat.h>
00023 #include <klone/parser.h>
00024 #include <klone/utils.h>
00025 #include <klone/os.h>
00026 #include <klone/io.h>
00027 #include <klone/codec.h>
00028 #include <klone/codecs.h>
00029 
00030 #define tr_err(...)             \
00031     do  { con_p_ctx(p); con_err(__VA_ARGS__); } while(0)
00032 #define tr_err_if(expr)          \
00033     do { if( (expr) ) { con_p_ctx(p); con("%s", #expr); goto err; } } while(0)
00034 #define tr_err_ifm(expr, ...)    \
00035     do { if( (expr) ) { con_p_ctx(p); con(__VA_ARGS__); goto err; } } while(0)
00036 
00037 static int preprocess(io_t *in, io_t *out);
00038 
00039 /* print parser context to the console */
00040 static void con_p_ctx(parser_t *p)
00041 {
00042     char fn[U_FILENAME_MAX];
00043 
00044     dbg_err_if(io_name_get(p->in, fn, U_FILENAME_MAX));
00045 
00046     /* con_ macro should be used here; we'd need a con_no_newline(...) */
00047     fprintf(stderr, "[%s:%d]: error:  ", fn, p->code_line);
00048 err:
00049     return;
00050 }
00051 
00052 static int is_a_script(const char *filename)
00053 {
00054     static const char *script_ext[] = { 
00055         ".klone", ".kl1", ".klc", 
00056         ".klx",  /* C++ page */
00057         NULL 
00058     };
00059     const char **ext;
00060 
00061     dbg_return_if(filename == NULL, 0);
00062 
00063     /* try to find an index page between default index uris */
00064     for(ext = script_ext; *ext; ++ext)
00065     {
00066         /* case insensitive matching */
00067         if(u_match_ext(filename, *ext))
00068             return 1;
00069     }
00070     return 0;
00071 }
00072 
00073 static int process_directive_include(parser_t *p, char *inc_file)
00074 {
00075     enum { BUFSZ = 4096 };
00076     char buf[U_FILENAME_MAX], *pc;
00077     char file[U_FILENAME_MAX];
00078     io_t *io = NULL;
00079 
00080     dbg_return_if (p == NULL, ~0);
00081     dbg_return_if (inc_file == NULL, ~0);
00082 
00083     dbg_err_if(io_name_get(p->in, file, U_FILENAME_MAX));
00084     dbg_err_if(io_name_get(p->in, buf, U_FILENAME_MAX));
00085 
00086     /* remove file name, just path is needed */
00087     dbg_err_if((pc = strrchr(buf, '/')) == NULL);
00088     ++pc; *pc = 0;
00089 
00090     dbg_err_if(strlen(buf) + strlen(inc_file) >= BUFSZ);
00091 
00092     strcat(buf, inc_file);
00093 
00094     /* copy include file to p->out */
00095     tr_err_ifm(u_file_open(buf, O_RDONLY, &io), 
00096         "unable to open included file %s", buf);
00097 
00098     dbg_err_if(io_printf(p->out, "<%% #line 1 \"%s\" \n %%>", buf));
00099 
00100     dbg_err_if(preprocess(io, p->out));
00101 
00102     dbg_err_if(io_printf(p->out, "<%% #line %d \"%s\" \n %%>", 
00103         p->code_line, file));
00104 
00105     io_free(io);
00106 
00107     return 0;
00108 err:
00109     if(io)
00110         io_free(io);
00111     return ~0;
00112 }
00113 
00114 static int process_directive(parser_t *p, char *buf)
00115 {
00116     char *tok, *pp;
00117 
00118     dbg_return_if (p == NULL, ~0);
00119     dbg_return_if (buf == NULL, ~0);
00120 
00121     /* get preprocessor command */
00122     tr_err_ifm((tok = strtok_r(buf, " \t", &pp)) == NULL,
00123         "bad or missing preprocessor command");
00124 
00125     if(strcasecmp(tok, "include") == 0)
00126     {
00127         /* get include file name */
00128         tr_err_ifm((tok = strtok_r(NULL, " \t\"", &pp)) == NULL,
00129             "bad or missing include filename");
00130 
00131         dbg_err_if(process_directive_include(p, tok));
00132     } else {
00133         tr_err("unknown preprocessor directive: %s", tok);
00134     }
00135 
00136     return 0;
00137 err:
00138     return ~0;
00139 }
00140 
00141 static int parse_directive(parser_t *p, void *arg, const char *buf, size_t sz)
00142 {
00143     enum { LINE_BUFSZ = 1024 };
00144     char line[LINE_BUFSZ];
00145     io_t *io = NULL;
00146 
00147     u_unused_args(arg);
00148 
00149     dbg_return_if (p == NULL, ~0);
00150     dbg_return_if (buf == NULL, ~0);
00151     
00152     dbg_err_if(io_mem_create((char*)buf, sz, 0, &io));
00153 
00154     while(io_gets(io, line, LINE_BUFSZ) > 0)
00155         dbg_err_if(process_directive(p, line));
00156 
00157     io_free(io);
00158 
00159     return 0;
00160 err:
00161     if(io)
00162         io_free(io);
00163     return ~0;
00164 }
00165 
00166 static int cb_pre_html_block(parser_t *p, void *arg, const char *buf, size_t sz)
00167 {
00168     u_unused_args(arg);
00169 
00170     dbg_err_if (p == NULL);
00171 
00172     dbg_err_if(io_write(p->out, buf, sz) < 0);
00173 
00174     return 0;
00175 err:
00176     return ~0;
00177 }
00178 
00179 static int cb_pre_code_block(parser_t *p, int cmd, void *arg, const char *buf, 
00180         size_t sz)
00181 {
00182     char file[U_FILENAME_MAX];
00183 
00184     dbg_err_if (p == NULL);
00185 
00186     if(cmd == '@')
00187     {   /* do preprocess */
00188         dbg_err_if(parse_directive(p, arg, buf, sz));
00189     } else {
00190         dbg_err_if(io_name_get(p->in, file, U_FILENAME_MAX));
00191         if(cmd != '=')
00192             dbg_err_if(io_printf(p->out, "<%%%c #line %d \"%s\" \n%%>", 
00193                 (cmd == 0 ? ' ' : cmd), p->code_line, file)); 
00194         else
00195             dbg_err_if(io_printf(p->out, "<%% #line %d \"%s\" \n%%>", 
00196                 p->code_line, file)); 
00197 
00198         dbg_err_if(io_printf(p->out, "<%%%c ", (cmd == 0 ? ' ' : cmd)) < 0);
00199         dbg_err_if(io_write(p->out, buf, sz) < 0);
00200         dbg_err_if(io_printf(p->out, "%%>") < 0);
00201     }
00202     return 0;
00203 err:
00204     return ~0;
00205 }
00206 
00207 static int preprocess(io_t *in, io_t *out)
00208 {
00209     parser_t *p = NULL;
00210 
00211     /* create a parse that reads from in and writes to out */
00212     dbg_err_if(parser_create(&p));
00213 
00214     parser_set_io(p, in, out);
00215 
00216     parser_set_cb_code(p, cb_pre_code_block);
00217     parser_set_cb_html(p, cb_pre_html_block);
00218 
00219     dbg_err_if(parser_run(p));
00220 
00221     parser_free(p);
00222 
00223     return 0;
00224 err:
00225     if(p)
00226         parser_free(p);
00227     return ~0;
00228 }
00229 
00230 int translate(trans_info_t *pti)
00231 {
00232     io_t *in = NULL, *out = NULL, *tmp = NULL;
00233     codec_t *gzip = NULL, *aes = NULL;
00234     char tname[U_FILENAME_MAX];
00235 
00236     dbg_return_if (pti == NULL, ~0);
00237     
00238     /* open the input file */
00239     con_err_ifm(u_file_open(pti->file_in, O_RDONLY, &in),
00240         "unable to open %s", pti->file_in);
00241 
00242     /* open the output file */
00243     con_err_ifm(u_file_open(pti->file_out, O_CREAT | O_TRUNC | O_WRONLY, &out),
00244         "unable to open %s", pti->file_out);
00245 
00246     /* should choose the right translator based on file extensions or config */
00247     if(is_a_script(pti->file_in))
00248     {
00249         /* get a temporary io_t */
00250         con_err_if(u_tmpfile_open(&tmp));
00251 
00252         /* save the preprocessed in file to tmp */
00253         dbg_err_if(preprocess(in, tmp));
00254 
00255         /* reset the tmp io */
00256         io_seek(tmp, 0);
00257 
00258         /* translate it */
00259         dbg_err_if(translate_script_to_c(tmp, out, pti));
00260 
00261         /* get the filename of the temporary io_t */
00262         dbg_err_if(io_name_get(tmp, tname, U_FILENAME_MAX));
00263 
00264         /* free the tmp io */
00265         io_free(tmp);
00266 
00267         /* remove the tmp file */
00268         unlink(tname);
00269     } else  {
00270         /* check if compression is requested */
00271 #ifdef HAVE_LIBZ
00272         if(pti->comp)
00273         {
00274             /* set a compression filter to the input stream */
00275             dbg_err_if(codec_gzip_create(GZIP_COMPRESS, &gzip));
00276             dbg_err_if(io_codec_add_tail(in, gzip));
00277             gzip = NULL;
00278         }
00279 #endif
00280 #ifdef HAVE_LIBOPENSSL
00281         /* check if encryption is requested */
00282         if(pti->encrypt)
00283         {
00284             /* set a cipher filter */
00285             dbg_err_if(codec_cipher_create(CIPHER_ENCRYPT, EVP_aes_256_cbc(),
00286                 pti->key, NULL, &aes));
00287             dbg_err_if(io_codec_add_tail(in, aes));
00288             aes = NULL;
00289         }
00290 #endif
00291         dbg_err_if(translate_opaque_to_c(in, out, pti));
00292     }
00293 
00294     io_free(in);
00295     io_free(out);
00296 
00297     return 0;
00298 err:
00299     if(pti && strlen(pti->emsg))
00300         con("%s", pti->emsg);
00301     if(gzip)
00302         codec_free(gzip);
00303     if(tmp)
00304         io_free(tmp);
00305     if(in)
00306         io_free(in);
00307     if(out)
00308         io_free(out);
00309     return ~0;
00310 }

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