1 #! /usr/bin/env node
2
3 /*
4 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
5 */
6
7 var util = require('util');
8 var fs = require('fs');
9 var mod_getopt = require('posix-getopt');
10
11 var prologue =
12 '/*\n' +
13 ' * STOP!\n' +
14 ' *\n' +
15 ' * Do not edit this file. It is automatically generated by generrno.\n' +
16 ' */\n\n';
17
18 var guard_prologue =
19 '#ifndef\t_V8PLUS_ERRNO_H\n' +
20 '#define\t_V8PLUS_ERRNO_H\n\n' +
21 '#ifdef\t__cplusplus\n' +
22 'extern "C" {\n' +
23 '#endif\t/* __cplusplus */\n';
24
25 var decl_prologue =
26 '#define\tV8PLUS_ERRNO_BASE\t%s\n\n' +
27 'typedef enum _v8plus_errno {\n' +
28 '\tV8PLUSERR_NOERROR = 0,\n' +
29 '\tV8PLUSERR_%s = V8PLUS_ERRNO_BASE + 1,\n';
30
31 var decl_one =
32 '\tV8PLUSERR_%s,\n';
33
34 var decl_epilogue =
35 '} v8plus_errno_t;\n';
36
37 var guard_epilogue =
38 '#ifdef\t__cplusplus\n' +
39 '}\n' +
40 '#endif\t/* __cplusplus */\n\n' +
41 '#endif\t/* _V8PLUS_ERRNO_H */\n';
42
43 var include =
44 '#include "v8plus_errno.h"\n\n';
45
46 var func_prologue =
47 'const char *\n' +
48 'v8plus_%s(v8plus_errno_t e)\n' +
49 '{\n' +
50 '\tswitch (e) {\n';
51
52 var generic_case =
53 '\tcase V8PLUSERR_%s:\n' +
54 '\t\treturn ("%s");\n';
55
56 var errname_case =
57 '\tcase V8PLUSERR_%s:\n' +
58 '\t\treturn ("V8PLUSERR_%s");\n';
59
60 var func_epilogue =
61 '\tdefault:\n' +
62 '\t\treturn ("%s");\n' +
63 '\t}\n' +
64 '}\n';
65
66 var BUILTIN_ERRORS = [
67 {
68 code: 'NOMEM',
69 msg: 'out of memory',
70 exception: 'Error'
71 },
72 {
73 code: 'YOUSUCK',
74 msg: 'programmer error',
75 exception: 'Error'
76 },
77 {
78 code: 'UNKNOWN',
79 msg: 'unknown error',
80 exception: 'Error'
81 },
82 {
83 code: 'MISSINGARG',
84 msg: 'missing argument is required',
85 exception: 'TypeError'
86 },
87 {
88 code: 'BADARG',
89 msg: 'argument is of incorrect type',
90 exception: 'TypeError'
91 },
92 {
93 code: 'EXTRAARG',
94 msg: 'superfluous argument(s) detected',
95 exception: 'TypeError'
96 },
97 {
98 code: 'BADF',
99 msg: 'bad file descriptor',
100 exception: 'Error'
101 }
102 ];
103
104 function
105 usage()
106 {
107 console.log(process.argv[0] + ' ' + process.argv[1] +
108 ' {-c|-h} [-o <output>] <input>\n');
109 process.exit(1);
110 }
111
112 function
113 parse_arguments(argv)
114 {
115 var opt_c = 0;
116 var opt_h = 0;
117 var option;
118 var obj = {};
119 var parser = new mod_getopt.BasicParser('cho:', argv);
120 var defs;
121
122 while ((option = parser.getopt()) !== undefined && !option.error) {
123 switch (option.option) {
124 case 'c':
125 opt_c++;
126 obj.action = 'c';
127 break;
128 case 'h':
129 opt_h++;
130 obj.action = 'h';
131 break;
132 case 'o':
133 obj.output = option.optarg;
134 break;
135 default:
136 usage();
137 break;
138 }
139 }
140
141 obj.input = argv[parser.optind()];
142
143 if (opt_c + opt_h != 1)
144 usage();
145
146 if (!obj.input)
147 usage();
148
149 defs = fs.readFileSync(obj.input);
150 obj.defs = JSON.parse(defs);
151
152 BUILTIN_ERRORS.forEach(function _prepend_err(e) {
153 obj.defs.errors.unshift(e);
154 });
155
156 return (obj);
157 }
158
159 function
160 write(output, str)
161 {
162 if (!output)
163 process.stdout.write(str);
164 else
165 fs.writeFileSync(output, str)
166 }
167
168 function
169 write_c(defs, output)
170 {
171 var out = '';
172
173 out += prologue;
174 out += include;
175
176 out += util.format(func_prologue, 'strerror');
177 defs.errors.forEach(function _append_str(e) {
178 out += util.format(generic_case, e.code, e.msg);
179 });
180 out += util.format(func_epilogue, 'unknown v8+ error code');
181 out += '\n';
182
183 out += util.format(func_prologue, 'errname');
184 defs.errors.forEach(function _append_name(e) {
185 out += util.format(errname_case, e.code, e.code);
186 });
187 out += util.format(func_epilogue, 'unknown v8+ error code');
188 out += '\n';
189
190 out += util.format(func_prologue, 'excptype');
191 defs.errors.forEach(function _append_excp(e) {
192 out += util.format(generic_case, e.code, e.exception);
193 });
194 out += util.format(func_epilogue, 'Error');
195
196 write(output, out);
197 }
198
199 function
200 write_header(defs, output)
201 {
202 var out = '';
203
204 out += prologue;
205 out += guard_prologue;
206 out += util.format(decl_prologue, defs.error_base, defs.errors[0].code);
207 defs.errors.forEach(function _spew_decl(e, i) {
208 if (i > 0)
209 out += util.format(decl_one, e.code);
210 });
211 out += decl_epilogue;
212 out += guard_epilogue;
213
214 write(output, out);
215 }
216
217 var action = parse_arguments(process.argv);
218
219 switch (action.action) {
220 case 'c':
221 write_c(action.defs, action.output);
222 break;
223 case 'h':
224 write_header(action.defs, action.output);
225 break;
226 default:
227 usage();
228 break;
229 }