2 * Copyright (c) 2012 ikh software, inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * 1) Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * 2) Redistributions of source code with modification must include a notice
10 * that the code was modified.
11 * 3) Neither the names of the authors nor the names of their contributors may
12 * be used to endorse or promote products derived from this software without
13 * specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
40 #define WRITE_BATCH 50
41 #define WRITE_BEG "[=====["
42 #define WRITE_END "]=====]"
49 #define doNewLine(c) fprintf(fo,"io.write('\\n') -- %d\n",lineno)
51 #define begText() fprintf(fo,"io.write(%s",WRITE_BEG)
52 #define doText(c) fputc(c,fo)
53 #define endText() fprintf(fo,"%s) -- %d\n",WRITE_END,lineno)
55 #define begStat() fputc(NL,fo)
56 #define doStat(c) fputc(c,fo)
57 #define endStat() fprintf(fo," -- %d\n",lineno)
59 #define begExpr() fprintf(fo,"io.write(tostring(")
60 #define doExpr(c) fputc(c,fo)
61 #define endExpr() fprintf(fo,")) -- %d\n", lineno)
63 // if (lineno % WRITE_BATCH == 0) {
65 void convert(FILE* fi
, FILE* fo
) {
77 case NL
: s
=1; doNewLine(); break;
78 default: s
=5; begText(); doText(c
); break;
84 case EOF
: s
=5; doText(EQ
); endText(); break;
85 case NL
: s
=1; doText(EQ
); endText(); break;
86 default: s
=5; doText(EQ
); doText(c
); break;
91 case EQ
: s
=4; begStat(); break;
92 case EOF
: s
=5; doText(EQ
); doText(EQ
); endText(); break;
93 case NL
: s
=1; doText(EQ
); doText(EQ
); endText(); break;
94 default: s
=5; doText(EQ
); doText(EQ
); doText(c
); break;
99 case EOF
: s
=1; endStat(); break;
100 case NL
: s
=1; endStat(); break;
101 default: s
=4; doStat(c
); break;
107 case NL
: s
=1; doText(c
); endText(); break;
108 case EOF
: s
=5; endText(); break;
109 default: s
=5; doText(c
); break;
115 case EOF
: s
=5; doText(LA
); endText(); break;
116 case NL
: s
=1; doText(LA
); endText(); break;
117 default: s
=5; doText(LA
); doText(c
); break;
122 case LA
: s
=8; endText(); begExpr(); break;
123 case EOF
: s
=5; doText(LA
); doText(LA
); endText(); break;
124 case NL
: s
=1; doText(LA
); doText(LA
); endText(); break;
125 default: s
=5; doText(LA
); doText(LA
); doText(c
); break;
131 case EOF
: s
=8; endExpr(); break;
132 default: s
=8; doExpr(c
); break;
137 case RA
: s
=10; break;
138 case EOF
: s
=8; doExpr(RA
); endExpr(); break;
139 default: s
=8; doExpr(RA
); doExpr(c
); break;
144 case RA
: s
=5; endExpr(); begText(); break;
145 case EOF
: s
=8; doExpr(RA
); doExpr(RA
); endExpr(); break;
146 default: s
=8; doExpr(RA
); doExpr(RA
); doExpr(c
); break;
157 fprintf(stderr
,"file read error (errno=%d: %s)\n", errno
, strerror(errno
));
162 void process_file(lua_State
*L
, const char* iname
, const char* oname
, int tflag
, int mflag
, int vflag
, const char* pattern
) {
165 fprintf(stderr
, "processing file '%s' -> '%s'\n", iname
, oname
);
172 int isStdin
= (strcmp(iname
,"-")==0);
173 int isStdout
= (strcmp(oname
,"-")==0);
175 mflag
= mflag
|| isStdin
|| isStdout
;
180 fi
= fopen(iname
,"r");
182 fprintf(stderr
,"can't open input file (file='%s', errno=%d: %s)\n", iname
, errno
, strerror(errno
));
188 stdout
= freopen(oname
, "w", stdout
);
190 fprintf(stderr
,"can't open output file (file='%s', errno=%d: %s)\n", oname
, errno
, strerror(errno
));
195 tname
= tmpnam(NULL
);
197 fprintf(stderr
,"can't obtain temporary file name (errno=%d: %s)\n", errno
, strerror(errno
));
200 ft
= fopen(tname
,"w");
202 fprintf(stderr
,"can't open temporary file (file='%s', errno=%d: %s)\n", tname
, errno
, strerror(errno
));
212 if (luaL_dofile(L
,tname
)!=0) {
213 fprintf(stderr
,"%s (file='%s')\n",lua_tostring(L
,-1),tname
);
219 // stdout = freopen("/dev/null", "w", stdout);
220 // if (stdout==NULL) {
221 // fprintf(stderr,"can't open /dev/null (errno=%d: %s)\n", errno, strerror(errno));
227 if (stat(iname
,&tstats
) != 0) {
228 fprintf(stderr
,"can't stat input file (file='%s', errno=%d: %s)\n", iname
, errno
, strerror(errno
));
231 if (chmod(oname
,tstats
.st_mode
)!=0) {
232 fprintf(stderr
,"can't chmod output file (file='%s', mode=%o, errno=%d: %s)\n", tname
, tstats
.st_mode
, errno
, strerror(errno
));
238 if (unlink(tname
)!=0) {
239 fprintf(stderr
,"can't remove temporary file (file='%s', errno=%d: %s)\n", tname
, errno
, strerror(errno
));
243 fprintf(stderr
,"temporary file '%s'\n",tname
);
247 void process_dir(lua_State
*L
, const char* dname
, int tflag
, int mflag
, int vflag
, const char* pattern
, int level
) {
250 fprintf(stderr
, "processing dir(%d) '%s'\n", level
, dname
);
253 DIR *dirp
= opendir(dname
);
255 fprintf(stderr
,"can't open directory (name='%s', errno=%d: %s)\n", dname
, errno
, strerror(errno
));
259 while ((dp
=readdir(dirp
)) != NULL
) {
262 lua_getglobal(L
,"miconf_fname_hook");
263 lua_pushinteger(L
,level
);
264 lua_pushstring(L
,pattern
);
265 lua_pushstring(L
,dname
);
266 lua_pushstring(L
,dp
->d_name
);
267 lua_pushinteger(L
,dp
->d_type
);
268 if (lua_pcall(L
, 5, 2, 0) != 0) {
269 fprintf(stderr
,"error running lua function 'miconf_fname_hook': %s\n", lua_tostring(L
,-1));
272 if (lua_isstring(L
,-1) && lua_isstring(L
,-1)) {
273 const char* iname
= lua_tostring(L
,-2);
274 const char* oname
= lua_tostring(L
,-1);
275 process_file(L
,iname
,oname
,tflag
,mflag
,vflag
,pattern
);
280 if (strcmp(dp
->d_name
,".")==0 || strcmp(dp
->d_name
,"..")==0)
282 lua_getglobal(L
,"miconf_dname_hook");
283 lua_pushinteger(L
,level
);
284 lua_pushstring(L
,dname
);
285 lua_pushstring(L
,dp
->d_name
);
286 if (lua_pcall(L
, 3, 1, 0) != 0) {
287 fprintf(stderr
,"error running lua function 'miconf_dname_hook': %s\n", lua_tostring(L
,-1));
290 if (lua_isstring(L
,-1)) {
291 process_dir(L
,lua_tostring(L
,-1),tflag
,mflag
,vflag
,pattern
,level
+1);
303 fprintf(stderr
,"Miconf: configuration utility\n\n");
304 fprintf(stderr
,"Miconf %s Copyright (c) 2012 ikh software, inc.\n", strchr(MICONF_RELEASE
,'-')+1);
305 fprintf(stderr
,"%s\n\n", LUA_COPYRIGHT
);
306 fprintf(stderr
,"Usage:\n");
307 fprintf(stderr
," miconf [options] template_file output_file\n");
308 fprintf(stderr
," miconf [options] -r directory\n\n");
309 fprintf(stderr
,"Options:\n");
310 fprintf(stderr
," -c file -- config file, for example: -c config.lua \n");
311 fprintf(stderr
," -e block -- config block, for example: -e 'host=\"foo\"; ip=\"127.0.0.1\"' \n");
312 fprintf(stderr
," -p pattern -- template file name pattern (default: '[.]template$')\n");
313 fprintf(stderr
," -t -- preserve temp files\n");
314 fprintf(stderr
," -m -- disable chmod\n");
315 fprintf(stderr
," -v -- verbose\n");
316 fprintf(stderr
," -h -- help\n\n");
320 int main(int argc
, char* argv
[]) {
326 const char* pattern
= "[.]template$";
327 lua_State
*L
= luaL_newstate();
332 "function miconf_dname_hook(level,path,file)\n"
333 " return path..(file and (\"/\"..file) or \"\")\n"
335 "function miconf_fname_hook(level,pattern,path,file,type)\n"
336 " ofile,cnt = file:gsub(pattern,\"\")\n"
337 " if ofile and cnt==1 and ofile:len()>0 then\n"
338 " return path..(file and (\"/\"..file) or \"\"), path..\"/\"..ofile\n"
345 if (luaL_dostring(L
,hooks
)!=0) {
346 fprintf(stderr
,"%s (string='%s')\n",lua_tostring(L
,-1),hooks
);
351 while ((ch
= getopt(argc
, argv
, "hrtmvp:e:c:")) != -1) {
355 fprintf(stderr
,"Default config:\n\n",hooks
);
356 fprintf(stderr
,"%s\n",hooks
);
357 fprintf(stderr
,"----\n\n");
359 case 'r': rflag
= 1; break;
360 case 't': tflag
= 1; break;
361 case 'm': mflag
= 1; break;
362 case 'v': vflag
= 1; break;
363 case 'p': pattern
= optarg
; break;
365 if (luaL_dofile(L
,optarg
)!=0) {
366 fprintf(stderr
,"%s (file='%s')\n",lua_tostring(L
,-1),optarg
);
372 if (luaL_dostring(L
,optarg
)!=0) {
373 fprintf(stderr
,"%s (block='%s')\n",lua_tostring(L
,-1),optarg
);
387 const char* iname
= argc
>0 ? argv
[0] : "-";
388 const char* oname
= argc
>1 ? argv
[1] : "-";
389 process_file(L
,iname
,oname
,tflag
,mflag
,vflag
,pattern
);
391 const char* dname
= argc
>0 ? argv
[0] : ".";
392 lua_getglobal(L
,"miconf_dname_hook");
393 lua_pushinteger(L
,0);
394 lua_pushstring(L
,dname
);
396 if (lua_pcall(L
, 3, 1, 0) != 0) {
397 fprintf(stderr
,"error running lua function 'miconf_dname_hook': %s\n", lua_tostring(L
,-1));
400 if (lua_isstring(L
,-1)) {
401 process_dir(L
,lua_tostring(L
,-1),tflag
,mflag
,vflag
,pattern
,1);