text: #!/usr/bin/env node
  
  /**
  * @license Apache-2.0
  *
  * Copyright (c) 2021 The Stdlib Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *    http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
  
  /* eslint-disable node/shebang */
  
  'use strict';
  
  // MODULES //
  
  var resolve = require( 'path' ).resolve;
  var writeFile = require( '@stdlib/fs-write-file' ).sync;
  var readFile = require( '@stdlib/fs-read-file' ).sync;
  var replace = require( '@stdlib/string-replace' );
  var resolveStr = require( '@stdlib/strided-base-dtype-resolve-str' );
  var dtypeChar = require( '@stdlib/ndarray-base-dtype-char' );
  var char2dtype = require( '@stdlib/ndarray-base-char2dtype' );
  var contains = require( '@stdlib/assert-contains' );
  var uppercase = require( '@stdlib/string-uppercase' );
  var types = require( './../lib/types.js' );
  
  
  // VARIABLES //
  
  var OPTS = {
  	'encoding': 'utf8'
  };
  var SRC_PATH = resolve( __dirname, '..', 'src', 'addon.c.txt' );
  var OUT_PATH = resolve( __dirname, '..', 'src', 'addon.c' );
  
  // Define a list of JavaScript types to exclude:
  var EXCLUDE = [
  	'generic',
  	'binary',
  	'uint8c'  // FIXME: remove once C support
  ];
  
  // Define regular expressions for extracting dtype signatures:
  var RE_IO_ARGS = /^stdlib_strided_([a-z])([a-z])_([a-z])/;
  var RE_CLBK_ARGS = /([a-z])([a-z])_([a-z])$/;
  
  // Resolve dtype characters for select dtypes:
  var FLOAT64_CHAR = dtypeChar( 'float64' );
  var FLOAT32_CHAR = dtypeChar( 'float32' );
  var COMPLEX64_CHAR = dtypeChar( 'complex64' );
  var COMPLEX128_CHAR = dtypeChar( 'complex128' );
  
  // Define the function "base" name:
  var FCN_BASENAME = 'add';
  var FCN_DESCRIPTION = 'Adds two numbers.';
  var FCN_BODY = 'return x + y;';
  
  // Define a note:
  var NOTE = 'NOTE: Do not edit this file directly. This file is auto-generated. See ./src/addon.c.txt.';
  
  var YEAR = ( new Date() ).getFullYear();
  var COPYRIGHT = 'The Stdlib Authors';
  
  
  // MAIN //
  
  /**
  * Main execution sequence.
  *
  * @private
  * @throws {Error} unexpected error
  */
  function main() {
  	var parts;
  	var file;
  	var fcns;
  	var data;
  	var err;
  	var tmp;
  	var t1;
  	var t2;
  	var t3;
  	var ch;
  	var dt;
  	var f;
  	var i;
  
  	file = readFile( SRC_PATH, OPTS );
  	if ( file instanceof Error ) {
  		throw file;
  	}
  	// Resolve the list of strided array functions...
  	fcns = [];
  	for ( i = 0; i < types.length; i += 3 ) {
  		t1 = types[ i ];
  		t2 = types[ i+1 ];
  		t3 = types[ i+2 ];
  		if (
  			contains( EXCLUDE, resolveStr( t1 ) ) ||
  			contains( EXCLUDE, resolveStr( t2 ) ) ||
  			contains( EXCLUDE, resolveStr( t3 ) )
  		) {
  			continue;
  		}
  		ch = dtypeChar( t3 );
  		f = 'stdlib_strided_'+dtypeChar( t1 )+dtypeChar( t2 )+'_'+ch;
  		if ( t1 !== t2 || t2 !== t3 ) {
  			f += '_as_'+ch+ch+'_'+ch;
  		}
  		fcns.push( f );
  	}
  	// Resolve the list of dtypes...
  	dt = [];
  	for ( i = 0; i < fcns.length; i++ ) {
  		parts = fcns[ i ].match( RE_IO_ARGS );
  		if ( parts === null ) {
  			throw new Error( 'unexpected error. Unable to resolve signature dtypes. Function: `' + fcns[ i ] + '`.' );
  		}
  		tmp = [];
  		t1 = parts[ 1 ];
  		tmp.push( 'STDLIB_STRIDED_'+uppercase( char2dtype( t1 ) ) );
  		t2 = parts[ 2 ];
  		tmp.push( 'STDLIB_STRIDED_'+uppercase( char2dtype( t2 ) ) );
  		t3 = parts[ 3 ];
  		tmp.push( 'STDLIB_STRIDED_'+uppercase( char2dtype( t3 ) ) );
  		dt.push( tmp.join( ', ' ) );
  	}
  	// Resolve the list of callbacks...
  	data = [];
  	for ( i = 0; i < fcns.length; i++ ) {
  		parts = fcns[ i ].match( RE_CLBK_ARGS );
  		if ( parts === null ) {
  			throw new Error( 'unexpected error. Unable to resolve signature dtypes. Function: `' + fcns[ i ] + '`.' );
  		}
  		t1 = parts[ 1 ];
  		t2 = parts[ 2 ];
  		t3 = parts[ 3 ];
  		if ( t1 !== t2 || t2 !== t3 ) {
  			throw new Error( 'unexpected error. Callback arguments must all be the same. Function: `' + fcns[ i ] + '`.' );
  		}
  		if ( t1 === FLOAT64_CHAR ) {
  			f = 'stdlib_base_'+FCN_BASENAME;
  		} else if ( t1 === FLOAT32_CHAR ) {
  			f = 'stdlib_base_'+FCN_BASENAME+t1;
  		} else if ( t1 === COMPLEX64_CHAR ) {
  			f = 'stdlib_base_c'+FCN_BASENAME+'f';
  		} else if ( t1 === COMPLEX128_CHAR ) {
  			f = 'stdlib_base_c'+FCN_BASENAME;
  		} else {
  			f = FCN_BASENAME+t1;
  		}
  		data.push( '(void *)'+f );
  	}
  	// Insert the resolved data into the template:
  	file = replace( file, '{{YEAR}}', YEAR.toString() );
  	file = replace( file, '{{COPYRIGHT}}', COPYRIGHT );
  	file = replace( file, '{{NOTE}}', NOTE );
  	file = replace( file, '{{FCN_BASENAME}}', FCN_BASENAME );
  	file = replace( file, '{{FCN_DESCRIPTION}}', FCN_DESCRIPTION );
  	file = replace( file, '{{FCN_BODY}}', FCN_BODY );
  	file = replace( file, '{{FUNCTIONS}}', fcns.join( ',\n\t' ) );
  	file = replace( file, '{{TYPES}}', dt.join( ',\n\t' ) );
  	file = replace( file, '{{DATA}}', data.join( ',\n\t' ) );
  	file = replace( file, '{{NUM_FUNCTIONS}}', fcns.length.toString() );
  
  	// Save the generated output to file:
  	err = writeFile( OUT_PATH, file, OPTS );
  	if ( err ) {
  		throw err;
  	}
  }
  
  main();
  