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 }