#!/usr/bin/env perl
use feature 'say';
use strictures 1;
my $ua = LWP::UserAgent->new;
my @headers = (
);
my %const;
my %errconst;
my @posixonly = qw/
EAGAIN
EFAULT
EINTR
EINVAL
/;
# FIXME
# Pull in the POSIX consts not included in zmq.h, such as EAGAIN and EINTR
# FIXME
# Better define parser.
# We should be able to handle ( FOO | BAR ) etc,
# so we can get ZMQ_EVENT_ALL in particular.
sub parse_consts {
my ($lines) = @_;
die "No data?" unless $lines->has_any;
my $defs = $lines->grep(sub { /^#define ZMQ/ });
my $errordefs = $lines->grep(sub { /^#define E/ });
die "No defines?" unless $defs->has_any;
DEF: for my $thisdef ($defs->all) {
my (undef, $sym, $val) = split /\s+/, $thisdef, 3;
next DEF if $sym =~ /^ZMQ_VERSION|MAKE_VERSION/;
if ($val =~ /^\(/) {
warn "Skipping unhandled sym '$sym' ($val)";
next DEF
}
if ($val =~ /[A-Z]/i) {
if (exists $const{$val}) {
warn "Aliasing $sym to $val\n";
$const{$sym} = $const{$val}
}
} else {
$const{$sym} = $val
}
}
ERRORDEF: for my $thisdef ($errordefs->all) {
my (undef, $sym, $val) = split /\s+/, $thisdef, 3;
my ($orig, $add) = $val =~ /\((\w+) \+ (\d+)\)/;
warn "Adding $add to $orig for $sym";
$errconst{$sym} = $const{$orig} + $add;
# FIXME these need to be handled differently ..
# build a separate %errconst hash and handle it separately
# should probably be a compile-time constant def that checks if
# POSIX::$const is defined and uses the zmq.h const if not
}
}
for my $header (@headers) {
warn "--> fetching $header";
my $rs = $ua->get($header);
unless ($rs->is_success) {
die "Failed retrieval: $header: ".$rs->status_line
}
parse_consts( array(split /\n|\r\n/, $rs->decoded_content) )
}
my $output .= <<'HEADER';
package POEx::ZMQ::Constants;
# Automatically generated by tools/gen_zmq_constants
use strict; use warnings FATAL => 'all';
use POSIX ();
use parent 'Exporter::Tiny';
our @EXPORT = our @EXPORT_ALL = qw/
HEADER
for my $constant (keys %const, keys %errconst, @posixonly) {
$output .= " $constant\n"
}
$output .= "/;\n\n";
for my $constant (keys %const) {
my $val = $const{$constant};
$output .= "sub $constant () { $val }\n";
}
$output .= "\nno strict 'refs';\n";
for my $constant (keys %errconst) {
my $val = $errconst{$constant};
$output .= "eval( defined *{'POSIX::$constant'} ?\n";
$output .= " 'sub $constant () { &POSIX::$constant }'\n";
$output .=" : 'sub $constant () { $val }'\n);\n\n";
}
for my $constant (@posixonly) {
$output .= "sub $constant () { \n";
$output .= " &POSIX::$constant\n";
$output .= "}\n";
}
$output .= "\n1;\n";
$output .= " # Generated at " . localtime . "\n";
$output .= <<'PODMAIN';
=pod
=head1 NAME
POEx::ZMQ::Constants - ZeroMQ (3 + 4) constants for use with POEx::ZMQ
=head1 SYNOPSIS
# All ZeroMQ v3 + v4 constants:
use POEx::ZMQ::Constants -all;
# Specific constants:
use POEx::ZMQ::Constants qw/ZMQ_ROUTER ZMQ_DEALER EINTR/;
=head1 DESCRIPTION
ZeroMQ constant exporter for use with L<POEx::ZMQ> applications.
Automatically generated from ZeroMQ version 3 & 4 headers.
Uses L<Exporter::Tiny>; look there for detailed import-related documentation.
C<E>-prefixed error constants should generally do the right thing, using the
ZeroMQ C<zmq.h> values if the POSIX constants are not available.
The complete list of exported constants:
=over
PODMAIN
$output .= "=item $_\n\n" for (keys %const, keys %errconst, @posixonly);
$output .= <<'PODFOOTER';
=back
=head1 AUTHOR
Jon Portnoy <avenj@cobaltirc.org>
=cut
PODFOOTER
print $output;