├── .gitignore ├── CHANGES ├── LICENSE ├── Makefile.am ├── Makefile.in ├── README.md ├── TODO ├── aclocal.m4 ├── config.guess ├── config.h.in ├── config.sub ├── configure ├── configure.ac ├── depcomp ├── install-sh ├── missing ├── nginx ├── Makefile.am ├── Makefile.in ├── config ├── ngx_protobuf.c └── ngx_protobuf.h └── protongx ├── Makefile.am ├── Makefile.in ├── ngx_add.cc ├── ngx_descriptor.cc ├── ngx_descriptor_util.cc ├── ngx_extension.cc ├── ngx_field_util.cc ├── ngx_flags.cc ├── ngx_flags.h ├── ngx_generate.cc ├── ngx_generator.h ├── ngx_is_initialized.cc ├── ngx_main.cc ├── ngx_methods.cc ├── ngx_module.cc ├── ngx_name.cc ├── ngx_pack.cc ├── ngx_print.cc ├── ngx_size.cc ├── ngx_typedef.cc └── ngx_unpack.cc /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *~ 3 | .deps 4 | autom4te.cache 5 | Makefile 6 | config.h 7 | config.log 8 | config.status 9 | stamp-h1 10 | protongx/protongx 11 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | Changes with protobuf-nginx 1.1 24 Apr 2013 2 | 3 | *) Added support for unknown fields. Unknown fields are parsed into 4 | an array of ngx_protobuf_unknown_field_t. Generation of this code 5 | can be suppressed by setting the following file-level option: 6 | 7 | options optimize_for = LITE_RUNTIME; 8 | 9 | *) Added __is_initialized methods for messages. For messages with 10 | required fields, methods return 1 if all required fields are 11 | defined and 0 otherwise. Otherwise (i.e. for messages with no 12 | required fields), methods always return a value of 1. 13 | 14 | Changes with protobuf-nginx 1.0 19 Apr 2013 15 | 16 | *) Initial release 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Dave Bailey 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | 3 | SUBDIRS = nginx protongx 4 | 5 | EXTRA_DIST = README.md LICENSE CHANGES TODO 6 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.11.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, 6 | # Inc. 7 | # This Makefile.in is free software; the Free Software Foundation 8 | # gives unlimited permission to copy and/or distribute it, 9 | # with or without modifications, as long as this notice is preserved. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | # PARTICULAR PURPOSE. 15 | 16 | @SET_MAKE@ 17 | VPATH = @srcdir@ 18 | pkgdatadir = $(datadir)/@PACKAGE@ 19 | pkgincludedir = $(includedir)/@PACKAGE@ 20 | pkglibdir = $(libdir)/@PACKAGE@ 21 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 22 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 23 | install_sh_DATA = $(install_sh) -c -m 644 24 | install_sh_PROGRAM = $(install_sh) -c 25 | install_sh_SCRIPT = $(install_sh) -c 26 | INSTALL_HEADER = $(INSTALL_DATA) 27 | transform = $(program_transform_name) 28 | NORMAL_INSTALL = : 29 | PRE_INSTALL = : 30 | POST_INSTALL = : 31 | NORMAL_UNINSTALL = : 32 | PRE_UNINSTALL = : 33 | POST_UNINSTALL = : 34 | build_triplet = @build@ 35 | host_triplet = @host@ 36 | target_triplet = @target@ 37 | subdir = . 38 | DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ 39 | $(srcdir)/Makefile.in $(srcdir)/config.h.in \ 40 | $(top_srcdir)/configure TODO config.guess config.sub depcomp \ 41 | install-sh missing 42 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 43 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 44 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 45 | $(ACLOCAL_M4) 46 | am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ 47 | configure.lineno config.status.lineno 48 | mkinstalldirs = $(install_sh) -d 49 | CONFIG_HEADER = config.h 50 | CONFIG_CLEAN_FILES = 51 | CONFIG_CLEAN_VPATH_FILES = 52 | SOURCES = 53 | DIST_SOURCES = 54 | RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ 55 | html-recursive info-recursive install-data-recursive \ 56 | install-dvi-recursive install-exec-recursive \ 57 | install-html-recursive install-info-recursive \ 58 | install-pdf-recursive install-ps-recursive install-recursive \ 59 | installcheck-recursive installdirs-recursive pdf-recursive \ 60 | ps-recursive uninstall-recursive 61 | RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ 62 | distclean-recursive maintainer-clean-recursive 63 | AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ 64 | $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ 65 | distdir dist dist-all distcheck 66 | ETAGS = etags 67 | CTAGS = ctags 68 | DIST_SUBDIRS = $(SUBDIRS) 69 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 70 | distdir = $(PACKAGE)-$(VERSION) 71 | top_distdir = $(distdir) 72 | am__remove_distdir = \ 73 | { test ! -d "$(distdir)" \ 74 | || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ 75 | && rm -fr "$(distdir)"; }; } 76 | am__relativize = \ 77 | dir0=`pwd`; \ 78 | sed_first='s,^\([^/]*\)/.*$$,\1,'; \ 79 | sed_rest='s,^[^/]*/*,,'; \ 80 | sed_last='s,^.*/\([^/]*\)$$,\1,'; \ 81 | sed_butlast='s,/*[^/]*$$,,'; \ 82 | while test -n "$$dir1"; do \ 83 | first=`echo "$$dir1" | sed -e "$$sed_first"`; \ 84 | if test "$$first" != "."; then \ 85 | if test "$$first" = ".."; then \ 86 | dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ 87 | dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ 88 | else \ 89 | first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ 90 | if test "$$first2" = "$$first"; then \ 91 | dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ 92 | else \ 93 | dir2="../$$dir2"; \ 94 | fi; \ 95 | dir0="$$dir0"/"$$first"; \ 96 | fi; \ 97 | fi; \ 98 | dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ 99 | done; \ 100 | reldir="$$dir2" 101 | DIST_ARCHIVES = $(distdir).tar.gz 102 | GZIP_ENV = --best 103 | distuninstallcheck_listfiles = find . -type f -print 104 | distcleancheck_listfiles = find . -type f -print 105 | ACLOCAL = @ACLOCAL@ 106 | AMTAR = @AMTAR@ 107 | AUTOCONF = @AUTOCONF@ 108 | AUTOHEADER = @AUTOHEADER@ 109 | AUTOMAKE = @AUTOMAKE@ 110 | AWK = @AWK@ 111 | CC = @CC@ 112 | CCDEPMODE = @CCDEPMODE@ 113 | CFLAGS = @CFLAGS@ 114 | CPP = @CPP@ 115 | CPPFLAGS = @CPPFLAGS@ 116 | CXX = @CXX@ 117 | CXXCPP = @CXXCPP@ 118 | CXXDEPMODE = @CXXDEPMODE@ 119 | CXXFLAGS = @CXXFLAGS@ 120 | CYGPATH_W = @CYGPATH_W@ 121 | DEFS = @DEFS@ 122 | DEPDIR = @DEPDIR@ 123 | ECHO_C = @ECHO_C@ 124 | ECHO_N = @ECHO_N@ 125 | ECHO_T = @ECHO_T@ 126 | EGREP = @EGREP@ 127 | EXEEXT = @EXEEXT@ 128 | GREP = @GREP@ 129 | INSTALL = @INSTALL@ 130 | INSTALL_DATA = @INSTALL_DATA@ 131 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 132 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 133 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 134 | LDFLAGS = @LDFLAGS@ 135 | LIBOBJS = @LIBOBJS@ 136 | LIBS = @LIBS@ 137 | LTLIBOBJS = @LTLIBOBJS@ 138 | MAKEINFO = @MAKEINFO@ 139 | MKDIR_P = @MKDIR_P@ 140 | OBJEXT = @OBJEXT@ 141 | PACKAGE = @PACKAGE@ 142 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 143 | PACKAGE_NAME = @PACKAGE_NAME@ 144 | PACKAGE_STRING = @PACKAGE_STRING@ 145 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 146 | PACKAGE_VERSION = @PACKAGE_VERSION@ 147 | PATH_SEPARATOR = @PATH_SEPARATOR@ 148 | SET_MAKE = @SET_MAKE@ 149 | SHELL = @SHELL@ 150 | STRIP = @STRIP@ 151 | VERSION = @VERSION@ 152 | abs_builddir = @abs_builddir@ 153 | abs_srcdir = @abs_srcdir@ 154 | abs_top_builddir = @abs_top_builddir@ 155 | abs_top_srcdir = @abs_top_srcdir@ 156 | ac_ct_CC = @ac_ct_CC@ 157 | ac_ct_CXX = @ac_ct_CXX@ 158 | am__include = @am__include@ 159 | am__leading_dot = @am__leading_dot@ 160 | am__quote = @am__quote@ 161 | am__tar = @am__tar@ 162 | am__untar = @am__untar@ 163 | bindir = @bindir@ 164 | build = @build@ 165 | build_alias = @build_alias@ 166 | build_cpu = @build_cpu@ 167 | build_os = @build_os@ 168 | build_vendor = @build_vendor@ 169 | builddir = @builddir@ 170 | datadir = @datadir@ 171 | datarootdir = @datarootdir@ 172 | docdir = @docdir@ 173 | dvidir = @dvidir@ 174 | exec_prefix = @exec_prefix@ 175 | host = @host@ 176 | host_alias = @host_alias@ 177 | host_cpu = @host_cpu@ 178 | host_os = @host_os@ 179 | host_vendor = @host_vendor@ 180 | htmldir = @htmldir@ 181 | includedir = @includedir@ 182 | infodir = @infodir@ 183 | install_sh = @install_sh@ 184 | libdir = @libdir@ 185 | libexecdir = @libexecdir@ 186 | localedir = @localedir@ 187 | localstatedir = @localstatedir@ 188 | mandir = @mandir@ 189 | mkdir_p = @mkdir_p@ 190 | oldincludedir = @oldincludedir@ 191 | pdfdir = @pdfdir@ 192 | prefix = @prefix@ 193 | program_transform_name = @program_transform_name@ 194 | psdir = @psdir@ 195 | sbindir = @sbindir@ 196 | sharedstatedir = @sharedstatedir@ 197 | srcdir = @srcdir@ 198 | sysconfdir = @sysconfdir@ 199 | target = @target@ 200 | target_alias = @target_alias@ 201 | target_cpu = @target_cpu@ 202 | target_os = @target_os@ 203 | target_vendor = @target_vendor@ 204 | top_build_prefix = @top_build_prefix@ 205 | top_builddir = @top_builddir@ 206 | top_srcdir = @top_srcdir@ 207 | AUTOMAKE_OPTIONS = foreign 208 | SUBDIRS = nginx protongx 209 | EXTRA_DIST = README.md LICENSE CHANGES TODO 210 | all: config.h 211 | $(MAKE) $(AM_MAKEFLAGS) all-recursive 212 | 213 | .SUFFIXES: 214 | am--refresh: 215 | @: 216 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 217 | @for dep in $?; do \ 218 | case '$(am__configure_deps)' in \ 219 | *$$dep*) \ 220 | echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ 221 | $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ 222 | && exit 0; \ 223 | exit 1;; \ 224 | esac; \ 225 | done; \ 226 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ 227 | $(am__cd) $(top_srcdir) && \ 228 | $(AUTOMAKE) --foreign Makefile 229 | .PRECIOUS: Makefile 230 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 231 | @case '$?' in \ 232 | *config.status*) \ 233 | echo ' $(SHELL) ./config.status'; \ 234 | $(SHELL) ./config.status;; \ 235 | *) \ 236 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ 237 | cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ 238 | esac; 239 | 240 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 241 | $(SHELL) ./config.status --recheck 242 | 243 | $(top_srcdir)/configure: $(am__configure_deps) 244 | $(am__cd) $(srcdir) && $(AUTOCONF) 245 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 246 | $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) 247 | $(am__aclocal_m4_deps): 248 | 249 | config.h: stamp-h1 250 | @if test ! -f $@; then \ 251 | rm -f stamp-h1; \ 252 | $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ 253 | else :; fi 254 | 255 | stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status 256 | @rm -f stamp-h1 257 | cd $(top_builddir) && $(SHELL) ./config.status config.h 258 | $(srcdir)/config.h.in: $(am__configure_deps) 259 | ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) 260 | rm -f stamp-h1 261 | touch $@ 262 | 263 | distclean-hdr: 264 | -rm -f config.h stamp-h1 265 | 266 | # This directory's subdirectories are mostly independent; you can cd 267 | # into them and run `make' without going through this Makefile. 268 | # To change the values of `make' variables: instead of editing Makefiles, 269 | # (1) if the variable is set in `config.status', edit `config.status' 270 | # (which will cause the Makefiles to be regenerated when you run `make'); 271 | # (2) otherwise, pass the desired values on the `make' command line. 272 | $(RECURSIVE_TARGETS): 273 | @fail= failcom='exit 1'; \ 274 | for f in x $$MAKEFLAGS; do \ 275 | case $$f in \ 276 | *=* | --[!k]*);; \ 277 | *k*) failcom='fail=yes';; \ 278 | esac; \ 279 | done; \ 280 | dot_seen=no; \ 281 | target=`echo $@ | sed s/-recursive//`; \ 282 | list='$(SUBDIRS)'; for subdir in $$list; do \ 283 | echo "Making $$target in $$subdir"; \ 284 | if test "$$subdir" = "."; then \ 285 | dot_seen=yes; \ 286 | local_target="$$target-am"; \ 287 | else \ 288 | local_target="$$target"; \ 289 | fi; \ 290 | ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ 291 | || eval $$failcom; \ 292 | done; \ 293 | if test "$$dot_seen" = "no"; then \ 294 | $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ 295 | fi; test -z "$$fail" 296 | 297 | $(RECURSIVE_CLEAN_TARGETS): 298 | @fail= failcom='exit 1'; \ 299 | for f in x $$MAKEFLAGS; do \ 300 | case $$f in \ 301 | *=* | --[!k]*);; \ 302 | *k*) failcom='fail=yes';; \ 303 | esac; \ 304 | done; \ 305 | dot_seen=no; \ 306 | case "$@" in \ 307 | distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ 308 | *) list='$(SUBDIRS)' ;; \ 309 | esac; \ 310 | rev=''; for subdir in $$list; do \ 311 | if test "$$subdir" = "."; then :; else \ 312 | rev="$$subdir $$rev"; \ 313 | fi; \ 314 | done; \ 315 | rev="$$rev ."; \ 316 | target=`echo $@ | sed s/-recursive//`; \ 317 | for subdir in $$rev; do \ 318 | echo "Making $$target in $$subdir"; \ 319 | if test "$$subdir" = "."; then \ 320 | local_target="$$target-am"; \ 321 | else \ 322 | local_target="$$target"; \ 323 | fi; \ 324 | ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ 325 | || eval $$failcom; \ 326 | done && test -z "$$fail" 327 | tags-recursive: 328 | list='$(SUBDIRS)'; for subdir in $$list; do \ 329 | test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ 330 | done 331 | ctags-recursive: 332 | list='$(SUBDIRS)'; for subdir in $$list; do \ 333 | test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ 334 | done 335 | 336 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) 337 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 338 | unique=`for i in $$list; do \ 339 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 340 | done | \ 341 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 342 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 343 | mkid -fID $$unique 344 | tags: TAGS 345 | 346 | TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ 347 | $(TAGS_FILES) $(LISP) 348 | set x; \ 349 | here=`pwd`; \ 350 | if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ 351 | include_option=--etags-include; \ 352 | empty_fix=.; \ 353 | else \ 354 | include_option=--include; \ 355 | empty_fix=; \ 356 | fi; \ 357 | list='$(SUBDIRS)'; for subdir in $$list; do \ 358 | if test "$$subdir" = .; then :; else \ 359 | test ! -f $$subdir/TAGS || \ 360 | set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ 361 | fi; \ 362 | done; \ 363 | list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ 364 | unique=`for i in $$list; do \ 365 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 366 | done | \ 367 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 368 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 369 | shift; \ 370 | if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ 371 | test -n "$$unique" || unique=$$empty_fix; \ 372 | if test $$# -gt 0; then \ 373 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 374 | "$$@" $$unique; \ 375 | else \ 376 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 377 | $$unique; \ 378 | fi; \ 379 | fi 380 | ctags: CTAGS 381 | CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ 382 | $(TAGS_FILES) $(LISP) 383 | list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ 384 | unique=`for i in $$list; do \ 385 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 386 | done | \ 387 | $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ 388 | END { if (nonempty) { for (i in files) print i; }; }'`; \ 389 | test -z "$(CTAGS_ARGS)$$unique" \ 390 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 391 | $$unique 392 | 393 | GTAGS: 394 | here=`$(am__cd) $(top_builddir) && pwd` \ 395 | && $(am__cd) $(top_srcdir) \ 396 | && gtags -i $(GTAGS_ARGS) "$$here" 397 | 398 | distclean-tags: 399 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 400 | 401 | distdir: $(DISTFILES) 402 | $(am__remove_distdir) 403 | test -d "$(distdir)" || mkdir "$(distdir)" 404 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 405 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 406 | list='$(DISTFILES)'; \ 407 | dist_files=`for file in $$list; do echo $$file; done | \ 408 | sed -e "s|^$$srcdirstrip/||;t" \ 409 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 410 | case $$dist_files in \ 411 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 412 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 413 | sort -u` ;; \ 414 | esac; \ 415 | for file in $$dist_files; do \ 416 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 417 | if test -d $$d/$$file; then \ 418 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 419 | if test -d "$(distdir)/$$file"; then \ 420 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 421 | fi; \ 422 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 423 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 424 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 425 | fi; \ 426 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 427 | else \ 428 | test -f "$(distdir)/$$file" \ 429 | || cp -p $$d/$$file "$(distdir)/$$file" \ 430 | || exit 1; \ 431 | fi; \ 432 | done 433 | @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ 434 | if test "$$subdir" = .; then :; else \ 435 | test -d "$(distdir)/$$subdir" \ 436 | || $(MKDIR_P) "$(distdir)/$$subdir" \ 437 | || exit 1; \ 438 | fi; \ 439 | done 440 | @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ 441 | if test "$$subdir" = .; then :; else \ 442 | dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ 443 | $(am__relativize); \ 444 | new_distdir=$$reldir; \ 445 | dir1=$$subdir; dir2="$(top_distdir)"; \ 446 | $(am__relativize); \ 447 | new_top_distdir=$$reldir; \ 448 | echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ 449 | echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ 450 | ($(am__cd) $$subdir && \ 451 | $(MAKE) $(AM_MAKEFLAGS) \ 452 | top_distdir="$$new_top_distdir" \ 453 | distdir="$$new_distdir" \ 454 | am__remove_distdir=: \ 455 | am__skip_length_check=: \ 456 | am__skip_mode_fix=: \ 457 | distdir) \ 458 | || exit 1; \ 459 | fi; \ 460 | done 461 | -test -n "$(am__skip_mode_fix)" \ 462 | || find "$(distdir)" -type d ! -perm -755 \ 463 | -exec chmod u+rwx,go+rx {} \; -o \ 464 | ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ 465 | ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ 466 | ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ 467 | || chmod -R a+r "$(distdir)" 468 | dist-gzip: distdir 469 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 470 | $(am__remove_distdir) 471 | 472 | dist-bzip2: distdir 473 | tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 474 | $(am__remove_distdir) 475 | 476 | dist-lzma: distdir 477 | tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma 478 | $(am__remove_distdir) 479 | 480 | dist-xz: distdir 481 | tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz 482 | $(am__remove_distdir) 483 | 484 | dist-tarZ: distdir 485 | tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z 486 | $(am__remove_distdir) 487 | 488 | dist-shar: distdir 489 | shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz 490 | $(am__remove_distdir) 491 | 492 | dist-zip: distdir 493 | -rm -f $(distdir).zip 494 | zip -rq $(distdir).zip $(distdir) 495 | $(am__remove_distdir) 496 | 497 | dist dist-all: distdir 498 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 499 | $(am__remove_distdir) 500 | 501 | # This target untars the dist file and tries a VPATH configuration. Then 502 | # it guarantees that the distribution is self-contained by making another 503 | # tarfile. 504 | distcheck: dist 505 | case '$(DIST_ARCHIVES)' in \ 506 | *.tar.gz*) \ 507 | GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ 508 | *.tar.bz2*) \ 509 | bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ 510 | *.tar.lzma*) \ 511 | lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ 512 | *.tar.xz*) \ 513 | xz -dc $(distdir).tar.xz | $(am__untar) ;;\ 514 | *.tar.Z*) \ 515 | uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ 516 | *.shar.gz*) \ 517 | GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ 518 | *.zip*) \ 519 | unzip $(distdir).zip ;;\ 520 | esac 521 | chmod -R a-w $(distdir); chmod u+w $(distdir) 522 | mkdir $(distdir)/_build 523 | mkdir $(distdir)/_inst 524 | chmod a-w $(distdir) 525 | test -d $(distdir)/_build || exit 0; \ 526 | dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ 527 | && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ 528 | && am__cwd=`pwd` \ 529 | && $(am__cd) $(distdir)/_build \ 530 | && ../configure --srcdir=.. --prefix="$$dc_install_base" \ 531 | $(DISTCHECK_CONFIGURE_FLAGS) \ 532 | && $(MAKE) $(AM_MAKEFLAGS) \ 533 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 534 | && $(MAKE) $(AM_MAKEFLAGS) check \ 535 | && $(MAKE) $(AM_MAKEFLAGS) install \ 536 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 537 | && $(MAKE) $(AM_MAKEFLAGS) uninstall \ 538 | && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ 539 | distuninstallcheck \ 540 | && chmod -R a-w "$$dc_install_base" \ 541 | && ({ \ 542 | (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ 543 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ 544 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ 545 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ 546 | distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ 547 | } || { rm -rf "$$dc_destdir"; exit 1; }) \ 548 | && rm -rf "$$dc_destdir" \ 549 | && $(MAKE) $(AM_MAKEFLAGS) dist \ 550 | && rm -rf $(DIST_ARCHIVES) \ 551 | && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ 552 | && cd "$$am__cwd" \ 553 | || exit 1 554 | $(am__remove_distdir) 555 | @(echo "$(distdir) archives ready for distribution: "; \ 556 | list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ 557 | sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' 558 | distuninstallcheck: 559 | @$(am__cd) '$(distuninstallcheck_dir)' \ 560 | && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ 561 | || { echo "ERROR: files left after uninstall:" ; \ 562 | if test -n "$(DESTDIR)"; then \ 563 | echo " (check DESTDIR support)"; \ 564 | fi ; \ 565 | $(distuninstallcheck_listfiles) ; \ 566 | exit 1; } >&2 567 | distcleancheck: distclean 568 | @if test '$(srcdir)' = . ; then \ 569 | echo "ERROR: distcleancheck can only run from a VPATH build" ; \ 570 | exit 1 ; \ 571 | fi 572 | @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ 573 | || { echo "ERROR: files left in build directory after distclean:" ; \ 574 | $(distcleancheck_listfiles) ; \ 575 | exit 1; } >&2 576 | check-am: all-am 577 | check: check-recursive 578 | all-am: Makefile config.h 579 | installdirs: installdirs-recursive 580 | installdirs-am: 581 | install: install-recursive 582 | install-exec: install-exec-recursive 583 | install-data: install-data-recursive 584 | uninstall: uninstall-recursive 585 | 586 | install-am: all-am 587 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 588 | 589 | installcheck: installcheck-recursive 590 | install-strip: 591 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 592 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 593 | `test -z '$(STRIP)' || \ 594 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 595 | mostlyclean-generic: 596 | 597 | clean-generic: 598 | 599 | distclean-generic: 600 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 601 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 602 | 603 | maintainer-clean-generic: 604 | @echo "This command is intended for maintainers to use" 605 | @echo "it deletes files that may require special tools to rebuild." 606 | clean: clean-recursive 607 | 608 | clean-am: clean-generic mostlyclean-am 609 | 610 | distclean: distclean-recursive 611 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 612 | -rm -f Makefile 613 | distclean-am: clean-am distclean-generic distclean-hdr distclean-tags 614 | 615 | dvi: dvi-recursive 616 | 617 | dvi-am: 618 | 619 | html: html-recursive 620 | 621 | html-am: 622 | 623 | info: info-recursive 624 | 625 | info-am: 626 | 627 | install-data-am: 628 | 629 | install-dvi: install-dvi-recursive 630 | 631 | install-dvi-am: 632 | 633 | install-exec-am: 634 | 635 | install-html: install-html-recursive 636 | 637 | install-html-am: 638 | 639 | install-info: install-info-recursive 640 | 641 | install-info-am: 642 | 643 | install-man: 644 | 645 | install-pdf: install-pdf-recursive 646 | 647 | install-pdf-am: 648 | 649 | install-ps: install-ps-recursive 650 | 651 | install-ps-am: 652 | 653 | installcheck-am: 654 | 655 | maintainer-clean: maintainer-clean-recursive 656 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 657 | -rm -rf $(top_srcdir)/autom4te.cache 658 | -rm -f Makefile 659 | maintainer-clean-am: distclean-am maintainer-clean-generic 660 | 661 | mostlyclean: mostlyclean-recursive 662 | 663 | mostlyclean-am: mostlyclean-generic 664 | 665 | pdf: pdf-recursive 666 | 667 | pdf-am: 668 | 669 | ps: ps-recursive 670 | 671 | ps-am: 672 | 673 | uninstall-am: 674 | 675 | .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ 676 | ctags-recursive install-am install-strip tags-recursive 677 | 678 | .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ 679 | all all-am am--refresh check check-am clean clean-generic \ 680 | ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ 681 | dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ 682 | distclean distclean-generic distclean-hdr distclean-tags \ 683 | distcleancheck distdir distuninstallcheck dvi dvi-am html \ 684 | html-am info info-am install install-am install-data \ 685 | install-data-am install-dvi install-dvi-am install-exec \ 686 | install-exec-am install-html install-html-am install-info \ 687 | install-info-am install-man install-pdf install-pdf-am \ 688 | install-ps install-ps-am install-strip installcheck \ 689 | installcheck-am installdirs installdirs-am maintainer-clean \ 690 | maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ 691 | pdf-am ps ps-am tags tags-recursive uninstall uninstall-am 692 | 693 | 694 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 695 | # Otherwise a system limit (for SysV at least) may be exceeded. 696 | .NOEXPORT: 697 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | protobuf-nginx - Google Protocol Buffers for nginx 2 | ================================================== 3 | 4 | This is protobuf-nginx, a code generator and supporting library that 5 | aim to help [nginx](http://nginx.com) module developers work with 6 | [Google Protocol Buffers](http://code.google.com/p/protobuf) messages. 7 | 8 | Background and motivation 9 | ------------------------- 10 | 11 | The Google Protocol Buffers (protobuf for short) serialization 12 | framework, with its many language implementations, is a practical and 13 | efficient way to transfer structured data between applications using 14 | language-neutral *message definitions* that can be translated into 15 | native code in a variety of programming languages. Google 16 | open-sourced protobuf in 2008. Meanwhile, the nginx HTTP server 17 | (which was originally released to the public in 2004) has become one 18 | of the most popular HTTP servers in use today, thanks to its 19 | exceptional performance and stability. In a single-threaded 20 | event-driven program such as nginx, efficiency is a key concern, and 21 | nginx module developers are encouraged to make use of the nginx 22 | framework (data structures such as arrays and rbtrees, memory pools, 23 | etc) in order to do things the *nginx way*: not one byte of memory nor 24 | one CPU cycle shall be wasted. Embrace the nginx way, and you embrace 25 | all that is good and right in the world. 26 | 27 | The protobuf-nginx project aims to bring protobuf to nginx, the nginx 28 | way: with generated code that uses nginx types, memory pools, and 29 | modules in order to give nginx C module developers the power of 30 | Google's serialization framework within the nginx environment. The 31 | generated code (along with a core protobuf module that is distributed 32 | as part of protobuf-nginx) can be compiled directly into the nginx 33 | binary without any other dependencies. 34 | 35 | Supported and unsupported features 36 | ---------------------------------- 37 | 38 | protobuf-nginx should be able to generate code for any protobuf 39 | message definition, including enums, nested messages, and extensions. 40 | The list of currently unsupported features is as follows: 41 | 42 | * [RPC services](https://developers.google.com/protocol-buffers/docs/proto#services). 43 | * Retention of unknown fields. Unknown fields are currently dropped, although they do not break the parsing. 44 | * [Default values](https://developers.google.com/protocol-buffers/docs/proto#optional) for missing optional fields. 45 | 46 | Support for all of these features, in at least some form, is planned. 47 | See the 48 | [TODO](https://github.com/dbcode/protobuf-nginx/blob/master/TODO) file 49 | for more details on these and other planned improvements to 50 | protobuf-nginx. 51 | 52 | A simple example 53 | ---------------- 54 | 55 | We can write a header filter module (similar to the [User ID 56 | module](http://wiki.nginx.org/HttpUseridModule)) that creates, reads, 57 | and updates a cookie, the value of which is a base64 encoded 58 | serialized protobuf message. Let's start with a simple message 59 | definition: 60 | 61 | package cookie; 62 | 63 | message User { 64 | message Channel { 65 | required bytes name = 1; 66 | required uint64 timestamp = 2; 67 | optional bytes metadata = 3; 68 | } 69 | required uint64 created = 1; 70 | required uint64 updated = 2; 71 | required uint64 counter = 3; 72 | optional uint64 timegap = 4; 73 | repeated Channel channels = 5; 74 | } 75 | 76 | This message includes a creation timestamp, an update timestamp, a 77 | counter, a numeric value that gives the elapsed time between the 78 | previous update timestamp and the most recent update, and a list of 79 | Channel submessages, each of which contains a string name, a 80 | timestamp, and optional string metadata. 81 | 82 | If this file is saved as cookie.proto, the nginx code generator can be 83 | invoked like so: 84 | 85 | protongx --out=. cookie.proto 86 | 87 | The --out option allows you to specify an output directory for the 88 | generated code. The generated code will be a complete nginx module 89 | that lives in a subdirectory of the --out directory. In this example, 90 | the nginx module generated from cookie.proto is created in the 91 | ngx_cookie_proto subdirectory of the --out directory, and includes the 92 | following files: 93 | 94 | config 95 | ngx_cookie_proto.c 96 | ngx_cookie_proto.h 97 | 98 | To build your nginx with this module, you will need to add the core 99 | ngx_protobuf module and this generated module to your configure 100 | arguments for nginx: 101 | 102 | ./configure \ 103 | --add-module=/usr/local/share/protobuf-nginx \ 104 | --add-module=/path/to/ngx_cookie_proto 105 | 106 | The core ngx_protobuf module is installed in /usr/local/share (or 107 | $PREFIX/share) in the protobuf-nginx subdirectory, and consists of the 108 | following files: 109 | 110 | config 111 | ngx_protobuf.c 112 | ngx_protobuf.h 113 | 114 | The generated module calls some functions from the core module, so 115 | it's important that both the core and the generated module be included 116 | in your nginx build. 117 | 118 | The struct typedefs in ngx_cookie_proto.h show the nginx 119 | representation of the cookie.User message and its nested message 120 | (cookie.User.Channel): 121 | 122 | ````c 123 | /* cookie.User.Channel */ 124 | 125 | typedef struct { 126 | ngx_str_t name; 127 | uint64_t timestamp; 128 | ngx_str_t metadata; 129 | uint32_t __has_name : 1; 130 | uint32_t __has_timestamp : 1; 131 | uint32_t __has_metadata : 1; 132 | } ngx_cookie_user_channel_t; 133 | 134 | /* cookie.User */ 135 | 136 | typedef struct { 137 | uint64_t created; 138 | uint64_t updated; 139 | uint64_t counter; 140 | uint64_t timegap; 141 | /* ngx_cookie_user_channel_t */ 142 | ngx_array_t *channels; 143 | uint32_t __has_created : 1; 144 | uint32_t __has_updated : 1; 145 | uint32_t __has_counter : 1; 146 | uint32_t __has_timegap : 1; 147 | uint32_t __has_channels : 1; 148 | } ngx_cookie_user_t; 149 | ```` 150 | 151 | Now let's say you want to write a filter module that reads and sets 152 | cookies with these (base64 encoded) messages in them. Ignoring the 153 | base64 encoding/decoding part, you'll unpack your cookie using a 154 | *protobuf context* that includes pointers to the start and end of your 155 | serialized data, and optional flags to control some aspects of the 156 | parsing. Your parsing code will look something like this: 157 | 158 | ````c 159 | ngx_cookie_user_t * 160 | unpack_user(ngx_str_t *val, ngx_pool_t *pool) 161 | { 162 | ngx_protobuf_context_t ctx; 163 | ngx_cookie_user_t *user; 164 | 165 | user = ngx_cookie_user__alloc(pool); 166 | if (user == NULL) { 167 | return NULL; 168 | } 169 | 170 | ctx.pool = pool; 171 | ctx.buffer.start = val->data; 172 | ctx.buffer.pos = ctx.buffer.start; 173 | ctx.buffer.last = val->data + val->len; 174 | ctx.reuse_strings = 1; 175 | 176 | if (ngx_cookie_user__unpack(user, &ctx) != NGX_OK) { 177 | return NULL; 178 | } 179 | 180 | return user; 181 | } 182 | ```` 183 | 184 | The protobuf context needs a memory pool in order to unpack the 185 | message contents, including possible string fields, repeated fields, 186 | and nested message fields. All of these fields require allocation of 187 | memory (with the possible exception of string fields - see the 188 | information on the **reuse_strings** flag below), so a pool is often 189 | required. Note that if you are unpacking a message that consists 190 | solely of non-repeated primitive fields such as integer types, a pool 191 | is not necessary. 192 | 193 | The protobuf context also contains a simple memory buffer: 194 | 195 | ````c 196 | typedef struct { 197 | u_char *start; 198 | u_char *pos; 199 | u_char *last; 200 | } ngx_protobuf_buffer_t; 201 | ```` 202 | 203 | When unpacking a serialized object, the *start* and *pos* pointers 204 | should point to the beginning of the serialized data, and the *last* 205 | pointer should point to the end. When packing an object, the *start* 206 | and *pos* pointers should point to the beginning of the output buffer, 207 | and the *last* pointer should point to the end of that buffer's 208 | available space. Once an object has been packed, the buffer's *pos* 209 | pointer will point to the end of the serialized output. You can then 210 | use the *pos* pointer's offset from the *start* pointer to calculate 211 | the length of your output (which should be the same as its size): 212 | 213 | size_t size = ngx_cookie_user__size(user); 214 | 215 | The **reuse_strings** flag lets you specify whether string fields 216 | should be allocated into their own separate memory from the protobuf 217 | context's pool, or can reuse (point to) memory in the underlying 218 | input. If you want extra efficiency and can guarantee that your 219 | object will not outlive the raw data from which it was unpacked, the 220 | **reuse_strings** flag lets you avoid unnecessary allocation of memory 221 | from the context pool. 222 | 223 | Now you can modify the object in whatever way you like: 224 | 225 | ````c 226 | void 227 | update_user(ngx_cookie_user_t *user) 228 | { 229 | ngx_time_t *tp; 230 | uint64_t now; 231 | 232 | tp = ngx_timeofday(); 233 | now = tp->sec * 1000 + tp->msec; 234 | 235 | user->counter += 1; 236 | user->timegap = now - user->updated; 237 | user->updated = now; 238 | } 239 | ```` 240 | 241 | Now it's time to repack the modified object: 242 | 243 | ````c 244 | ngx_int_t 245 | pack_user(ngx_cookie_user_t *user, ngx_str_t *output, ngx_pool_t *pool) 246 | { 247 | ngx_protobuf_context_t ctx; 248 | size_t size; 249 | ngx_int_t rc; 250 | 251 | size = ngx_cookie_user__size(user); 252 | if (size == 0) { 253 | return NGX_DECLINED; 254 | } 255 | 256 | output->data = ngx_palloc(pool, size); 257 | if (output->data == NULL) { 258 | return NGX_ERROR; 259 | } 260 | 261 | ctx.pool = pool; 262 | ctx.buffer.start = output->data; 263 | ctx.buffer.pos = ctx.buffer.start; 264 | ctx.buffer.last = ctx.buffer.start + size; 265 | 266 | rc = ngx_cookie_user__pack(user, &ctx); 267 | output->len = ctx.buffer.pos - ctx.buffer.start; 268 | 269 | return rc; 270 | } 271 | ```` 272 | 273 | How it all works 274 | ---------------- 275 | 276 | At nginx startup time, the core ngx_protobuf module scans the list of 277 | nginx modules for any that match the NGX_PROTOBUF_MODULE (0x50425546, 278 | or "PBUF") tag. Each of these modules corresponds to a .proto file 279 | that may contain any number of enums, messages, and extensions to 280 | other messages. In most cases, nothing special needs to be done in 281 | order to for these modules to function. However, a .proto file that 282 | includes extensions must register its extensions with the extendee 283 | (the type that is being extended). This is done by calling a 284 | "register_extensions" method that is defined in any protobuf module 285 | that has extensions defined: 286 | 287 | ````c 288 | /* register extensions */ 289 | for (i = 0; ngx_modules[i]; i++) { 290 | if (ngx_modules[i]->type == NGX_PROTOBUF_MODULE) { 291 | module = ngx_modules[i]->ctx; 292 | if (module != NULL && module->register_extensions != NULL) { 293 | module->register_extensions(cycle); 294 | } 295 | } 296 | } 297 | ```` 298 | 299 | At the present time, the registration of extensions is the only thing 300 | that needs to be done explicitly at nginx startup. Translating .proto 301 | files into nginx modules lets us do this in a natural way. 302 | 303 | As was mentioned earlier, each .proto file is translated to a complete 304 | nginx module in its own subdirectory. You can define messages in as 305 | many .proto files as you like, and invoke protongx on all of them at 306 | once: 307 | 308 | protongx --out=/path/to/protobuf/modules /path/to/protos/*.proto 309 | 310 | The end result will be that /path/to/protobuf/modules contains a 311 | subdirectory for each input .proto file. Each of these subdirectories 312 | can then be added to the configure arguments to nginx, as shown above 313 | for the simple case of the cookie.proto file. 314 | 315 | 19 April 2013 316 | Dave Bailey 317 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Add working examples of nginx modules that use protobuf messages. 2 | 3 | - working version of user cookie filter module described in the 4 | README.md. 5 | - protobuf RPC module (reads input message from request body of 6 | a POST, responds with serialized output message). Can be used 7 | as an example of what code generation of services would look like. 8 | - logging module (access logs in protobuf format). Can write 9 | compressed logs of {length, message} pairs. Should include a 10 | simple utility to parse the gzipped protobuf logs. 11 | 12 | * Extend pack/unpack methods to handle incremental pack and unpack. 13 | 14 | - on pack, methods should return NGX_AGAIN if they need more space 15 | to pack the entire message. 16 | - on unpack, return NGX_AGAIN if we need more data to finish a field. 17 | note that it's possible to return NGX_OK even not all of the input 18 | has been parsed (e.g. if we finish a repeated field exactly at the 19 | boundary, we will return NGX_OK, but additional input can add more 20 | fields). 21 | - state should be saved to / restored from the protobuf context. 22 | for nested messages, this may include a stack of some kind. 23 | - caller should check the context to see if the pack or unpack was 24 | complete when expected to be. 25 | 26 | * Add support for default values. 27 | 28 | - when a message is fully unpacked, any missing fields with default 29 | values will be initialized to those values. 30 | 31 | * Consider how / whether to handle services in the .proto files. from 32 | the protobuf documentation: 33 | 34 | service SearchService { 35 | rpc Search (SearchRequest) returns (SearchResponse); 36 | } 37 | 38 | this is supposed to define an RPC interface that takes a SearchRequest 39 | and responds with a SearchResponse. in nginx, we could generate a 40 | SearchService (ngx_search_service) module that has a handler in it 41 | that expects a POST of a serialized ngx_search_request_t object, and 42 | responds with a serialized ngx_search_response_t object. the module 43 | can take care of everything except filling in the actual body of this 44 | function: 45 | 46 | ngx_search_response_t * 47 | ngx_search_service_handler(ngx_search_request_t *req); 48 | 49 | in the nginx config, the handler would be invoked as: 50 | 51 | location = /searchService { 52 | ngx_search_service; 53 | } 54 | 55 | or something along those lines. -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_INTTYPES_H 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_MEMORY_H 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_STDINT_H 11 | 12 | /* Define to 1 if you have the header file. */ 13 | #undef HAVE_STDLIB_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_STRINGS_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_STRING_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_SYS_STAT_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_SYS_TYPES_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_UNISTD_H 29 | 30 | /* Name of package */ 31 | #undef PACKAGE 32 | 33 | /* Define to the address where bug reports for this package should be sent. */ 34 | #undef PACKAGE_BUGREPORT 35 | 36 | /* Define to the full name of this package. */ 37 | #undef PACKAGE_NAME 38 | 39 | /* Define to the full name and version of this package. */ 40 | #undef PACKAGE_STRING 41 | 42 | /* Define to the one symbol short name of this package. */ 43 | #undef PACKAGE_TARNAME 44 | 45 | /* Define to the version of this package. */ 46 | #undef PACKAGE_VERSION 47 | 48 | /* Define to 1 if you have the ANSI C header files. */ 49 | #undef STDC_HEADERS 50 | 51 | /* Enable extensions on AIX 3, Interix. */ 52 | #ifndef _ALL_SOURCE 53 | # undef _ALL_SOURCE 54 | #endif 55 | /* Enable GNU extensions on systems that have them. */ 56 | #ifndef _GNU_SOURCE 57 | # undef _GNU_SOURCE 58 | #endif 59 | /* Enable threading extensions on Solaris. */ 60 | #ifndef _POSIX_PTHREAD_SEMANTICS 61 | # undef _POSIX_PTHREAD_SEMANTICS 62 | #endif 63 | /* Enable extensions on HP NonStop. */ 64 | #ifndef _TANDEM_SOURCE 65 | # undef _TANDEM_SOURCE 66 | #endif 67 | /* Enable general extensions on Solaris. */ 68 | #ifndef __EXTENSIONS__ 69 | # undef __EXTENSIONS__ 70 | #endif 71 | 72 | 73 | /* Version number of package */ 74 | #undef VERSION 75 | 76 | /* Define to 1 if on MINIX. */ 77 | #undef _MINIX 78 | 79 | /* Define to 2 if the system does not provide POSIX.1 features except with 80 | this defined. */ 81 | #undef _POSIX_1_SOURCE 82 | 83 | /* Define to 1 if you need to in order for `stat' and other things to work. */ 84 | #undef _POSIX_SOURCE 85 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to produce a configure script. 2 | AC_INIT 3 | AC_CONFIG_SRCDIR([configure.ac]) 4 | AC_CANONICAL_TARGET([]) 5 | AC_GNU_SOURCE 6 | 7 | dnl For Automake 8 | PACKAGE=protobuf-nginx 9 | VERSION=1.1 10 | 11 | dnl Initialize automake stuff 12 | AM_INIT_AUTOMAKE($PACKAGE, $VERSION) 13 | AC_CONFIG_HEADERS([config.h]) 14 | 15 | AC_PROG_CXX 16 | AC_PROG_CC 17 | AC_PROG_CPP 18 | AC_PROG_INSTALL 19 | AC_LANG([C++]) 20 | 21 | dnl Look for protobuf headers and libs 22 | 23 | AC_ARG_WITH(protobuf, 24 | [ --with-protobuf[=DIR] where to find Google's Protocol Buffers],, 25 | with_protobuf=yes) 26 | 27 | if test "$with_protobuf" != no; then 28 | if test -d "$with_protobuf"; then 29 | CPPFLAGS="$CPPFLAGS -I$with_protobuf/include" 30 | LDFLAGS="$LDFLAGS -L$with_protobuf/lib" 31 | else 32 | AC_CHECK_HEADER([google/protobuf/stubs/common.h],, 33 | [AC_MSG_ERROR([protobuf headers are required. Try using the --with-protobuf 34 | option.])]) 35 | fi 36 | fi 37 | 38 | AC_CONFIG_FILES([Makefile nginx/Makefile protongx/Makefile]) 39 | AC_OUTPUT 40 | 41 | echo "" 42 | echo "Configure finished!" 43 | echo "" 44 | -------------------------------------------------------------------------------- /depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2007-03-29.01 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software 7 | # Foundation, Inc. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program; if not, write to the Free Software 21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 | # 02110-1301, USA. 23 | 24 | # As a special exception to the GNU General Public License, if you 25 | # distribute this file as part of a program that contains a 26 | # configuration script generated by Autoconf, you may include it under 27 | # the same distribution terms that you use for the rest of that program. 28 | 29 | # Originally written by Alexandre Oliva . 30 | 31 | case $1 in 32 | '') 33 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 34 | exit 1; 35 | ;; 36 | -h | --h*) 37 | cat <<\EOF 38 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 39 | 40 | Run PROGRAMS ARGS to compile a file, generating dependencies 41 | as side-effects. 42 | 43 | Environment variables: 44 | depmode Dependency tracking mode. 45 | source Source file read by `PROGRAMS ARGS'. 46 | object Object file output by `PROGRAMS ARGS'. 47 | DEPDIR directory where to store dependencies. 48 | depfile Dependency file to output. 49 | tmpdepfile Temporary file to use when outputing dependencies. 50 | libtool Whether libtool is used (yes/no). 51 | 52 | Report bugs to . 53 | EOF 54 | exit $? 55 | ;; 56 | -v | --v*) 57 | echo "depcomp $scriptversion" 58 | exit $? 59 | ;; 60 | esac 61 | 62 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 63 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 64 | exit 1 65 | fi 66 | 67 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 68 | depfile=${depfile-`echo "$object" | 69 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 70 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 71 | 72 | rm -f "$tmpdepfile" 73 | 74 | # Some modes work just like other modes, but use different flags. We 75 | # parameterize here, but still list the modes in the big case below, 76 | # to make depend.m4 easier to write. Note that we *cannot* use a case 77 | # here, because this file can only contain one case statement. 78 | if test "$depmode" = hp; then 79 | # HP compiler uses -M and no extra arg. 80 | gccflag=-M 81 | depmode=gcc 82 | fi 83 | 84 | if test "$depmode" = dashXmstdout; then 85 | # This is just like dashmstdout with a different argument. 86 | dashmflag=-xM 87 | depmode=dashmstdout 88 | fi 89 | 90 | case "$depmode" in 91 | gcc3) 92 | ## gcc 3 implements dependency tracking that does exactly what 93 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 94 | ## it if -MD -MP comes after the -MF stuff. Hmm. 95 | ## Unfortunately, FreeBSD c89 acceptance of flags depends upon 96 | ## the command line argument order; so add the flags where they 97 | ## appear in depend2.am. Note that the slowdown incurred here 98 | ## affects only configure: in makefiles, %FASTDEP% shortcuts this. 99 | for arg 100 | do 101 | case $arg in 102 | -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; 103 | *) set fnord "$@" "$arg" ;; 104 | esac 105 | shift # fnord 106 | shift # $arg 107 | done 108 | "$@" 109 | stat=$? 110 | if test $stat -eq 0; then : 111 | else 112 | rm -f "$tmpdepfile" 113 | exit $stat 114 | fi 115 | mv "$tmpdepfile" "$depfile" 116 | ;; 117 | 118 | gcc) 119 | ## There are various ways to get dependency output from gcc. Here's 120 | ## why we pick this rather obscure method: 121 | ## - Don't want to use -MD because we'd like the dependencies to end 122 | ## up in a subdir. Having to rename by hand is ugly. 123 | ## (We might end up doing this anyway to support other compilers.) 124 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 125 | ## -MM, not -M (despite what the docs say). 126 | ## - Using -M directly means running the compiler twice (even worse 127 | ## than renaming). 128 | if test -z "$gccflag"; then 129 | gccflag=-MD, 130 | fi 131 | "$@" -Wp,"$gccflag$tmpdepfile" 132 | stat=$? 133 | if test $stat -eq 0; then : 134 | else 135 | rm -f "$tmpdepfile" 136 | exit $stat 137 | fi 138 | rm -f "$depfile" 139 | echo "$object : \\" > "$depfile" 140 | alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 141 | ## The second -e expression handles DOS-style file names with drive letters. 142 | sed -e 's/^[^:]*: / /' \ 143 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 144 | ## This next piece of magic avoids the `deleted header file' problem. 145 | ## The problem is that when a header file which appears in a .P file 146 | ## is deleted, the dependency causes make to die (because there is 147 | ## typically no way to rebuild the header). We avoid this by adding 148 | ## dummy dependencies for each header file. Too bad gcc doesn't do 149 | ## this for us directly. 150 | tr ' ' ' 151 | ' < "$tmpdepfile" | 152 | ## Some versions of gcc put a space before the `:'. On the theory 153 | ## that the space means something, we add a space to the output as 154 | ## well. 155 | ## Some versions of the HPUX 10.20 sed can't process this invocation 156 | ## correctly. Breaking it into two sed invocations is a workaround. 157 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 158 | rm -f "$tmpdepfile" 159 | ;; 160 | 161 | hp) 162 | # This case exists only to let depend.m4 do its work. It works by 163 | # looking at the text of this script. This case will never be run, 164 | # since it is checked for above. 165 | exit 1 166 | ;; 167 | 168 | sgi) 169 | if test "$libtool" = yes; then 170 | "$@" "-Wp,-MDupdate,$tmpdepfile" 171 | else 172 | "$@" -MDupdate "$tmpdepfile" 173 | fi 174 | stat=$? 175 | if test $stat -eq 0; then : 176 | else 177 | rm -f "$tmpdepfile" 178 | exit $stat 179 | fi 180 | rm -f "$depfile" 181 | 182 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 183 | echo "$object : \\" > "$depfile" 184 | 185 | # Clip off the initial element (the dependent). Don't try to be 186 | # clever and replace this with sed code, as IRIX sed won't handle 187 | # lines with more than a fixed number of characters (4096 in 188 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 189 | # the IRIX cc adds comments like `#:fec' to the end of the 190 | # dependency line. 191 | tr ' ' ' 192 | ' < "$tmpdepfile" \ 193 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ 194 | tr ' 195 | ' ' ' >> $depfile 196 | echo >> $depfile 197 | 198 | # The second pass generates a dummy entry for each header file. 199 | tr ' ' ' 200 | ' < "$tmpdepfile" \ 201 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 202 | >> $depfile 203 | else 204 | # The sourcefile does not contain any dependencies, so just 205 | # store a dummy comment line, to avoid errors with the Makefile 206 | # "include basename.Plo" scheme. 207 | echo "#dummy" > "$depfile" 208 | fi 209 | rm -f "$tmpdepfile" 210 | ;; 211 | 212 | aix) 213 | # The C for AIX Compiler uses -M and outputs the dependencies 214 | # in a .u file. In older versions, this file always lives in the 215 | # current directory. Also, the AIX compiler puts `$object:' at the 216 | # start of each line; $object doesn't have directory information. 217 | # Version 6 uses the directory in both cases. 218 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 219 | test "x$dir" = "x$object" && dir= 220 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 221 | if test "$libtool" = yes; then 222 | tmpdepfile1=$dir$base.u 223 | tmpdepfile2=$base.u 224 | tmpdepfile3=$dir.libs/$base.u 225 | "$@" -Wc,-M 226 | else 227 | tmpdepfile1=$dir$base.u 228 | tmpdepfile2=$dir$base.u 229 | tmpdepfile3=$dir$base.u 230 | "$@" -M 231 | fi 232 | stat=$? 233 | 234 | if test $stat -eq 0; then : 235 | else 236 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 237 | exit $stat 238 | fi 239 | 240 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" 241 | do 242 | test -f "$tmpdepfile" && break 243 | done 244 | if test -f "$tmpdepfile"; then 245 | # Each line is of the form `foo.o: dependent.h'. 246 | # Do two passes, one to just change these to 247 | # `$object: dependent.h' and one to simply `dependent.h:'. 248 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 249 | # That's a tab and a space in the []. 250 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 251 | else 252 | # The sourcefile does not contain any dependencies, so just 253 | # store a dummy comment line, to avoid errors with the Makefile 254 | # "include basename.Plo" scheme. 255 | echo "#dummy" > "$depfile" 256 | fi 257 | rm -f "$tmpdepfile" 258 | ;; 259 | 260 | icc) 261 | # Intel's C compiler understands `-MD -MF file'. However on 262 | # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c 263 | # ICC 7.0 will fill foo.d with something like 264 | # foo.o: sub/foo.c 265 | # foo.o: sub/foo.h 266 | # which is wrong. We want: 267 | # sub/foo.o: sub/foo.c 268 | # sub/foo.o: sub/foo.h 269 | # sub/foo.c: 270 | # sub/foo.h: 271 | # ICC 7.1 will output 272 | # foo.o: sub/foo.c sub/foo.h 273 | # and will wrap long lines using \ : 274 | # foo.o: sub/foo.c ... \ 275 | # sub/foo.h ... \ 276 | # ... 277 | 278 | "$@" -MD -MF "$tmpdepfile" 279 | stat=$? 280 | if test $stat -eq 0; then : 281 | else 282 | rm -f "$tmpdepfile" 283 | exit $stat 284 | fi 285 | rm -f "$depfile" 286 | # Each line is of the form `foo.o: dependent.h', 287 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 288 | # Do two passes, one to just change these to 289 | # `$object: dependent.h' and one to simply `dependent.h:'. 290 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 291 | # Some versions of the HPUX 10.20 sed can't process this invocation 292 | # correctly. Breaking it into two sed invocations is a workaround. 293 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | 294 | sed -e 's/$/ :/' >> "$depfile" 295 | rm -f "$tmpdepfile" 296 | ;; 297 | 298 | hp2) 299 | # The "hp" stanza above does not work with aCC (C++) and HP's ia64 300 | # compilers, which have integrated preprocessors. The correct option 301 | # to use with these is +Maked; it writes dependencies to a file named 302 | # 'foo.d', which lands next to the object file, wherever that 303 | # happens to be. 304 | # Much of this is similar to the tru64 case; see comments there. 305 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 306 | test "x$dir" = "x$object" && dir= 307 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 308 | if test "$libtool" = yes; then 309 | tmpdepfile1=$dir$base.d 310 | tmpdepfile2=$dir.libs/$base.d 311 | "$@" -Wc,+Maked 312 | else 313 | tmpdepfile1=$dir$base.d 314 | tmpdepfile2=$dir$base.d 315 | "$@" +Maked 316 | fi 317 | stat=$? 318 | if test $stat -eq 0; then : 319 | else 320 | rm -f "$tmpdepfile1" "$tmpdepfile2" 321 | exit $stat 322 | fi 323 | 324 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" 325 | do 326 | test -f "$tmpdepfile" && break 327 | done 328 | if test -f "$tmpdepfile"; then 329 | sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" 330 | # Add `dependent.h:' lines. 331 | sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" 332 | else 333 | echo "#dummy" > "$depfile" 334 | fi 335 | rm -f "$tmpdepfile" "$tmpdepfile2" 336 | ;; 337 | 338 | tru64) 339 | # The Tru64 compiler uses -MD to generate dependencies as a side 340 | # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. 341 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 342 | # dependencies in `foo.d' instead, so we check for that too. 343 | # Subdirectories are respected. 344 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 345 | test "x$dir" = "x$object" && dir= 346 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 347 | 348 | if test "$libtool" = yes; then 349 | # With Tru64 cc, shared objects can also be used to make a 350 | # static library. This mechanism is used in libtool 1.4 series to 351 | # handle both shared and static libraries in a single compilation. 352 | # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. 353 | # 354 | # With libtool 1.5 this exception was removed, and libtool now 355 | # generates 2 separate objects for the 2 libraries. These two 356 | # compilations output dependencies in $dir.libs/$base.o.d and 357 | # in $dir$base.o.d. We have to check for both files, because 358 | # one of the two compilations can be disabled. We should prefer 359 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 360 | # automatically cleaned when .libs/ is deleted, while ignoring 361 | # the former would cause a distcleancheck panic. 362 | tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 363 | tmpdepfile2=$dir$base.o.d # libtool 1.5 364 | tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 365 | tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 366 | "$@" -Wc,-MD 367 | else 368 | tmpdepfile1=$dir$base.o.d 369 | tmpdepfile2=$dir$base.d 370 | tmpdepfile3=$dir$base.d 371 | tmpdepfile4=$dir$base.d 372 | "$@" -MD 373 | fi 374 | 375 | stat=$? 376 | if test $stat -eq 0; then : 377 | else 378 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 379 | exit $stat 380 | fi 381 | 382 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 383 | do 384 | test -f "$tmpdepfile" && break 385 | done 386 | if test -f "$tmpdepfile"; then 387 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 388 | # That's a tab and a space in the []. 389 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 390 | else 391 | echo "#dummy" > "$depfile" 392 | fi 393 | rm -f "$tmpdepfile" 394 | ;; 395 | 396 | #nosideeffect) 397 | # This comment above is used by automake to tell side-effect 398 | # dependency tracking mechanisms from slower ones. 399 | 400 | dashmstdout) 401 | # Important note: in order to support this mode, a compiler *must* 402 | # always write the preprocessed file to stdout, regardless of -o. 403 | "$@" || exit $? 404 | 405 | # Remove the call to Libtool. 406 | if test "$libtool" = yes; then 407 | while test $1 != '--mode=compile'; do 408 | shift 409 | done 410 | shift 411 | fi 412 | 413 | # Remove `-o $object'. 414 | IFS=" " 415 | for arg 416 | do 417 | case $arg in 418 | -o) 419 | shift 420 | ;; 421 | $object) 422 | shift 423 | ;; 424 | *) 425 | set fnord "$@" "$arg" 426 | shift # fnord 427 | shift # $arg 428 | ;; 429 | esac 430 | done 431 | 432 | test -z "$dashmflag" && dashmflag=-M 433 | # Require at least two characters before searching for `:' 434 | # in the target name. This is to cope with DOS-style filenames: 435 | # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. 436 | "$@" $dashmflag | 437 | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" 438 | rm -f "$depfile" 439 | cat < "$tmpdepfile" > "$depfile" 440 | tr ' ' ' 441 | ' < "$tmpdepfile" | \ 442 | ## Some versions of the HPUX 10.20 sed can't process this invocation 443 | ## correctly. Breaking it into two sed invocations is a workaround. 444 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 445 | rm -f "$tmpdepfile" 446 | ;; 447 | 448 | dashXmstdout) 449 | # This case only exists to satisfy depend.m4. It is never actually 450 | # run, as this mode is specially recognized in the preamble. 451 | exit 1 452 | ;; 453 | 454 | makedepend) 455 | "$@" || exit $? 456 | # Remove any Libtool call 457 | if test "$libtool" = yes; then 458 | while test $1 != '--mode=compile'; do 459 | shift 460 | done 461 | shift 462 | fi 463 | # X makedepend 464 | shift 465 | cleared=no 466 | for arg in "$@"; do 467 | case $cleared in 468 | no) 469 | set ""; shift 470 | cleared=yes ;; 471 | esac 472 | case "$arg" in 473 | -D*|-I*) 474 | set fnord "$@" "$arg"; shift ;; 475 | # Strip any option that makedepend may not understand. Remove 476 | # the object too, otherwise makedepend will parse it as a source file. 477 | -*|$object) 478 | ;; 479 | *) 480 | set fnord "$@" "$arg"; shift ;; 481 | esac 482 | done 483 | obj_suffix="`echo $object | sed 's/^.*\././'`" 484 | touch "$tmpdepfile" 485 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 486 | rm -f "$depfile" 487 | cat < "$tmpdepfile" > "$depfile" 488 | sed '1,2d' "$tmpdepfile" | tr ' ' ' 489 | ' | \ 490 | ## Some versions of the HPUX 10.20 sed can't process this invocation 491 | ## correctly. Breaking it into two sed invocations is a workaround. 492 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 493 | rm -f "$tmpdepfile" "$tmpdepfile".bak 494 | ;; 495 | 496 | cpp) 497 | # Important note: in order to support this mode, a compiler *must* 498 | # always write the preprocessed file to stdout. 499 | "$@" || exit $? 500 | 501 | # Remove the call to Libtool. 502 | if test "$libtool" = yes; then 503 | while test $1 != '--mode=compile'; do 504 | shift 505 | done 506 | shift 507 | fi 508 | 509 | # Remove `-o $object'. 510 | IFS=" " 511 | for arg 512 | do 513 | case $arg in 514 | -o) 515 | shift 516 | ;; 517 | $object) 518 | shift 519 | ;; 520 | *) 521 | set fnord "$@" "$arg" 522 | shift # fnord 523 | shift # $arg 524 | ;; 525 | esac 526 | done 527 | 528 | "$@" -E | 529 | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 530 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | 531 | sed '$ s: \\$::' > "$tmpdepfile" 532 | rm -f "$depfile" 533 | echo "$object : \\" > "$depfile" 534 | cat < "$tmpdepfile" >> "$depfile" 535 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 536 | rm -f "$tmpdepfile" 537 | ;; 538 | 539 | msvisualcpp) 540 | # Important note: in order to support this mode, a compiler *must* 541 | # always write the preprocessed file to stdout, regardless of -o, 542 | # because we must use -o when running libtool. 543 | "$@" || exit $? 544 | IFS=" " 545 | for arg 546 | do 547 | case "$arg" in 548 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 549 | set fnord "$@" 550 | shift 551 | shift 552 | ;; 553 | *) 554 | set fnord "$@" "$arg" 555 | shift 556 | shift 557 | ;; 558 | esac 559 | done 560 | "$@" -E | 561 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" 562 | rm -f "$depfile" 563 | echo "$object : \\" > "$depfile" 564 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" 565 | echo " " >> "$depfile" 566 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" 567 | rm -f "$tmpdepfile" 568 | ;; 569 | 570 | none) 571 | exec "$@" 572 | ;; 573 | 574 | *) 575 | echo "Unknown depmode $depmode" 1>&2 576 | exit 1 577 | ;; 578 | esac 579 | 580 | exit 0 581 | 582 | # Local Variables: 583 | # mode: shell-script 584 | # sh-indentation: 2 585 | # eval: (add-hook 'write-file-hooks 'time-stamp) 586 | # time-stamp-start: "scriptversion=" 587 | # time-stamp-format: "%:y-%02m-%02d.%02H" 588 | # time-stamp-end: "$" 589 | # End: 590 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2006-12-25.00 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # `make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | nl=' 45 | ' 46 | IFS=" "" $nl" 47 | 48 | # set DOITPROG to echo to test this script 49 | 50 | # Don't use :- since 4.3BSD and earlier shells don't like it. 51 | doit=${DOITPROG-} 52 | if test -z "$doit"; then 53 | doit_exec=exec 54 | else 55 | doit_exec=$doit 56 | fi 57 | 58 | # Put in absolute file names if you don't have them in your path; 59 | # or use environment vars. 60 | 61 | chgrpprog=${CHGRPPROG-chgrp} 62 | chmodprog=${CHMODPROG-chmod} 63 | chownprog=${CHOWNPROG-chown} 64 | cmpprog=${CMPPROG-cmp} 65 | cpprog=${CPPROG-cp} 66 | mkdirprog=${MKDIRPROG-mkdir} 67 | mvprog=${MVPROG-mv} 68 | rmprog=${RMPROG-rm} 69 | stripprog=${STRIPPROG-strip} 70 | 71 | posix_glob='?' 72 | initialize_posix_glob=' 73 | test "$posix_glob" != "?" || { 74 | if (set -f) 2>/dev/null; then 75 | posix_glob= 76 | else 77 | posix_glob=: 78 | fi 79 | } 80 | ' 81 | 82 | posix_mkdir= 83 | 84 | # Desired mode of installed file. 85 | mode=0755 86 | 87 | chgrpcmd= 88 | chmodcmd=$chmodprog 89 | chowncmd= 90 | mvcmd=$mvprog 91 | rmcmd="$rmprog -f" 92 | stripcmd= 93 | 94 | src= 95 | dst= 96 | dir_arg= 97 | dst_arg= 98 | 99 | copy_on_change=false 100 | no_target_directory= 101 | 102 | usage="\ 103 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104 | or: $0 [OPTION]... SRCFILES... DIRECTORY 105 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106 | or: $0 [OPTION]... -d DIRECTORIES... 107 | 108 | In the 1st form, copy SRCFILE to DSTFILE. 109 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110 | In the 4th, create DIRECTORIES. 111 | 112 | Options: 113 | --help display this help and exit. 114 | --version display version info and exit. 115 | 116 | -c (ignored) 117 | -C install only if different (preserve the last data modification time) 118 | -d create directories instead of installing files. 119 | -g GROUP $chgrpprog installed files to GROUP. 120 | -m MODE $chmodprog installed files to MODE. 121 | -o USER $chownprog installed files to USER. 122 | -s $stripprog installed files. 123 | -t DIRECTORY install into DIRECTORY. 124 | -T report an error if DSTFILE is a directory. 125 | 126 | Environment variables override the default commands: 127 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128 | RMPROG STRIPPROG 129 | " 130 | 131 | while test $# -ne 0; do 132 | case $1 in 133 | -c) ;; 134 | 135 | -C) copy_on_change=true;; 136 | 137 | -d) dir_arg=true;; 138 | 139 | -g) chgrpcmd="$chgrpprog $2" 140 | shift;; 141 | 142 | --help) echo "$usage"; exit $?;; 143 | 144 | -m) mode=$2 145 | case $mode in 146 | *' '* | *' '* | *' 147 | '* | *'*'* | *'?'* | *'['*) 148 | echo "$0: invalid mode: $mode" >&2 149 | exit 1;; 150 | esac 151 | shift;; 152 | 153 | -o) chowncmd="$chownprog $2" 154 | shift;; 155 | 156 | -s) stripcmd=$stripprog;; 157 | 158 | -t) dst_arg=$2 159 | shift;; 160 | 161 | -T) no_target_directory=true;; 162 | 163 | --version) echo "$0 $scriptversion"; exit $?;; 164 | 165 | --) shift 166 | break;; 167 | 168 | -*) echo "$0: invalid option: $1" >&2 169 | exit 1;; 170 | 171 | *) break;; 172 | esac 173 | shift 174 | done 175 | 176 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177 | # When -d is used, all remaining arguments are directories to create. 178 | # When -t is used, the destination is already specified. 179 | # Otherwise, the last argument is the destination. Remove it from $@. 180 | for arg 181 | do 182 | if test -n "$dst_arg"; then 183 | # $@ is not empty: it contains at least $arg. 184 | set fnord "$@" "$dst_arg" 185 | shift # fnord 186 | fi 187 | shift # arg 188 | dst_arg=$arg 189 | done 190 | fi 191 | 192 | if test $# -eq 0; then 193 | if test -z "$dir_arg"; then 194 | echo "$0: no input file specified." >&2 195 | exit 1 196 | fi 197 | # It's OK to call `install-sh -d' without argument. 198 | # This can happen when creating conditional directories. 199 | exit 0 200 | fi 201 | 202 | if test -z "$dir_arg"; then 203 | trap '(exit $?); exit' 1 2 13 15 204 | 205 | # Set umask so as not to create temps with too-generous modes. 206 | # However, 'strip' requires both read and write access to temps. 207 | case $mode in 208 | # Optimize common cases. 209 | *644) cp_umask=133;; 210 | *755) cp_umask=22;; 211 | 212 | *[0-7]) 213 | if test -z "$stripcmd"; then 214 | u_plus_rw= 215 | else 216 | u_plus_rw='% 200' 217 | fi 218 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 219 | *) 220 | if test -z "$stripcmd"; then 221 | u_plus_rw= 222 | else 223 | u_plus_rw=,u+rw 224 | fi 225 | cp_umask=$mode$u_plus_rw;; 226 | esac 227 | fi 228 | 229 | for src 230 | do 231 | # Protect names starting with `-'. 232 | case $src in 233 | -*) src=./$src;; 234 | esac 235 | 236 | if test -n "$dir_arg"; then 237 | dst=$src 238 | dstdir=$dst 239 | test -d "$dstdir" 240 | dstdir_status=$? 241 | else 242 | 243 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 244 | # might cause directories to be created, which would be especially bad 245 | # if $src (and thus $dsttmp) contains '*'. 246 | if test ! -f "$src" && test ! -d "$src"; then 247 | echo "$0: $src does not exist." >&2 248 | exit 1 249 | fi 250 | 251 | if test -z "$dst_arg"; then 252 | echo "$0: no destination specified." >&2 253 | exit 1 254 | fi 255 | 256 | dst=$dst_arg 257 | # Protect names starting with `-'. 258 | case $dst in 259 | -*) dst=./$dst;; 260 | esac 261 | 262 | # If destination is a directory, append the input filename; won't work 263 | # if double slashes aren't ignored. 264 | if test -d "$dst"; then 265 | if test -n "$no_target_directory"; then 266 | echo "$0: $dst_arg: Is a directory" >&2 267 | exit 1 268 | fi 269 | dstdir=$dst 270 | dst=$dstdir/`basename "$src"` 271 | dstdir_status=0 272 | else 273 | # Prefer dirname, but fall back on a substitute if dirname fails. 274 | dstdir=` 275 | (dirname "$dst") 2>/dev/null || 276 | expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 277 | X"$dst" : 'X\(//\)[^/]' \| \ 278 | X"$dst" : 'X\(//\)$' \| \ 279 | X"$dst" : 'X\(/\)' \| . 2>/dev/null || 280 | echo X"$dst" | 281 | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 282 | s//\1/ 283 | q 284 | } 285 | /^X\(\/\/\)[^/].*/{ 286 | s//\1/ 287 | q 288 | } 289 | /^X\(\/\/\)$/{ 290 | s//\1/ 291 | q 292 | } 293 | /^X\(\/\).*/{ 294 | s//\1/ 295 | q 296 | } 297 | s/.*/./; q' 298 | ` 299 | 300 | test -d "$dstdir" 301 | dstdir_status=$? 302 | fi 303 | fi 304 | 305 | obsolete_mkdir_used=false 306 | 307 | if test $dstdir_status != 0; then 308 | case $posix_mkdir in 309 | '') 310 | # Create intermediate dirs using mode 755 as modified by the umask. 311 | # This is like FreeBSD 'install' as of 1997-10-28. 312 | umask=`umask` 313 | case $stripcmd.$umask in 314 | # Optimize common cases. 315 | *[2367][2367]) mkdir_umask=$umask;; 316 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 317 | 318 | *[0-7]) 319 | mkdir_umask=`expr $umask + 22 \ 320 | - $umask % 100 % 40 + $umask % 20 \ 321 | - $umask % 10 % 4 + $umask % 2 322 | `;; 323 | *) mkdir_umask=$umask,go-w;; 324 | esac 325 | 326 | # With -d, create the new directory with the user-specified mode. 327 | # Otherwise, rely on $mkdir_umask. 328 | if test -n "$dir_arg"; then 329 | mkdir_mode=-m$mode 330 | else 331 | mkdir_mode= 332 | fi 333 | 334 | posix_mkdir=false 335 | case $umask in 336 | *[123567][0-7][0-7]) 337 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 338 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 339 | ;; 340 | *) 341 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 342 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 343 | 344 | if (umask $mkdir_umask && 345 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 346 | then 347 | if test -z "$dir_arg" || { 348 | # Check for POSIX incompatibilities with -m. 349 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 350 | # other-writeable bit of parent directory when it shouldn't. 351 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 352 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 353 | case $ls_ld_tmpdir in 354 | d????-?r-*) different_mode=700;; 355 | d????-?--*) different_mode=755;; 356 | *) false;; 357 | esac && 358 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 359 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 360 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 361 | } 362 | } 363 | then posix_mkdir=: 364 | fi 365 | rmdir "$tmpdir/d" "$tmpdir" 366 | else 367 | # Remove any dirs left behind by ancient mkdir implementations. 368 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 369 | fi 370 | trap '' 0;; 371 | esac;; 372 | esac 373 | 374 | if 375 | $posix_mkdir && ( 376 | umask $mkdir_umask && 377 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 378 | ) 379 | then : 380 | else 381 | 382 | # The umask is ridiculous, or mkdir does not conform to POSIX, 383 | # or it failed possibly due to a race condition. Create the 384 | # directory the slow way, step by step, checking for races as we go. 385 | 386 | case $dstdir in 387 | /*) prefix='/';; 388 | -*) prefix='./';; 389 | *) prefix='';; 390 | esac 391 | 392 | eval "$initialize_posix_glob" 393 | 394 | oIFS=$IFS 395 | IFS=/ 396 | $posix_glob set -f 397 | set fnord $dstdir 398 | shift 399 | $posix_glob set +f 400 | IFS=$oIFS 401 | 402 | prefixes= 403 | 404 | for d 405 | do 406 | test -z "$d" && continue 407 | 408 | prefix=$prefix$d 409 | if test -d "$prefix"; then 410 | prefixes= 411 | else 412 | if $posix_mkdir; then 413 | (umask=$mkdir_umask && 414 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 415 | # Don't fail if two instances are running concurrently. 416 | test -d "$prefix" || exit 1 417 | else 418 | case $prefix in 419 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 420 | *) qprefix=$prefix;; 421 | esac 422 | prefixes="$prefixes '$qprefix'" 423 | fi 424 | fi 425 | prefix=$prefix/ 426 | done 427 | 428 | if test -n "$prefixes"; then 429 | # Don't fail if two instances are running concurrently. 430 | (umask $mkdir_umask && 431 | eval "\$doit_exec \$mkdirprog $prefixes") || 432 | test -d "$dstdir" || exit 1 433 | obsolete_mkdir_used=true 434 | fi 435 | fi 436 | fi 437 | 438 | if test -n "$dir_arg"; then 439 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 440 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 441 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 442 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 443 | else 444 | 445 | # Make a couple of temp file names in the proper directory. 446 | dsttmp=$dstdir/_inst.$$_ 447 | rmtmp=$dstdir/_rm.$$_ 448 | 449 | # Trap to clean up those temp files at exit. 450 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 451 | 452 | # Copy the file name to the temp name. 453 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 454 | 455 | # and set any options; do chmod last to preserve setuid bits. 456 | # 457 | # If any of these fail, we abort the whole thing. If we want to 458 | # ignore errors from any of these, just make sure not to ignore 459 | # errors from the above "$doit $cpprog $src $dsttmp" command. 460 | # 461 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 462 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 463 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 464 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 465 | 466 | # If -C, don't bother to copy if it wouldn't change the file. 467 | if $copy_on_change && 468 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 469 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 470 | 471 | eval "$initialize_posix_glob" && 472 | $posix_glob set -f && 473 | set X $old && old=:$2:$4:$5:$6 && 474 | set X $new && new=:$2:$4:$5:$6 && 475 | $posix_glob set +f && 476 | 477 | test "$old" = "$new" && 478 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 479 | then 480 | rm -f "$dsttmp" 481 | else 482 | # Rename the file to the real destination. 483 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 484 | 485 | # The rename failed, perhaps because mv can't rename something else 486 | # to itself, or perhaps because mv is so ancient that it does not 487 | # support -f. 488 | { 489 | # Now remove or move aside any old file at destination location. 490 | # We try this two ways since rm can't unlink itself on some 491 | # systems and the destination file might be busy for other 492 | # reasons. In this case, the final cleanup might fail but the new 493 | # file should still install successfully. 494 | { 495 | test ! -f "$dst" || 496 | $doit $rmcmd -f "$dst" 2>/dev/null || 497 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 498 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 499 | } || 500 | { echo "$0: cannot unlink or rename $dst" >&2 501 | (exit 1); exit 1 502 | } 503 | } && 504 | 505 | # Now rename the file to the real destination. 506 | $doit $mvcmd "$dsttmp" "$dst" 507 | } 508 | fi || exit 1 509 | 510 | trap '' 0 511 | fi 512 | done 513 | 514 | # Local variables: 515 | # eval: (add-hook 'write-file-hooks 'time-stamp) 516 | # time-stamp-start: "scriptversion=" 517 | # time-stamp-format: "%:y-%02m-%02d.%02H" 518 | # time-stamp-end: "$" 519 | # End: 520 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | 4 | scriptversion=2006-05-10.23 5 | 6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 7 | # Free Software Foundation, Inc. 8 | # Originally by Fran,cois Pinard , 1996. 9 | 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program; if not, write to the Free Software 22 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23 | # 02110-1301, USA. 24 | 25 | # As a special exception to the GNU General Public License, if you 26 | # distribute this file as part of a program that contains a 27 | # configuration script generated by Autoconf, you may include it under 28 | # the same distribution terms that you use for the rest of that program. 29 | 30 | if test $# -eq 0; then 31 | echo 1>&2 "Try \`$0 --help' for more information" 32 | exit 1 33 | fi 34 | 35 | run=: 36 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' 37 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p' 38 | 39 | # In the cases where this matters, `missing' is being run in the 40 | # srcdir already. 41 | if test -f configure.ac; then 42 | configure_ac=configure.ac 43 | else 44 | configure_ac=configure.in 45 | fi 46 | 47 | msg="missing on your system" 48 | 49 | case $1 in 50 | --run) 51 | # Try to run requested program, and just exit if it succeeds. 52 | run= 53 | shift 54 | "$@" && exit 0 55 | # Exit code 63 means version mismatch. This often happens 56 | # when the user try to use an ancient version of a tool on 57 | # a file that requires a minimum version. In this case we 58 | # we should proceed has if the program had been absent, or 59 | # if --run hadn't been passed. 60 | if test $? = 63; then 61 | run=: 62 | msg="probably too old" 63 | fi 64 | ;; 65 | 66 | -h|--h|--he|--hel|--help) 67 | echo "\ 68 | $0 [OPTION]... PROGRAM [ARGUMENT]... 69 | 70 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 71 | error status if there is no known handling for PROGRAM. 72 | 73 | Options: 74 | -h, --help display this help and exit 75 | -v, --version output version information and exit 76 | --run try to run the given command, and emulate it if it fails 77 | 78 | Supported PROGRAM values: 79 | aclocal touch file \`aclocal.m4' 80 | autoconf touch file \`configure' 81 | autoheader touch file \`config.h.in' 82 | autom4te touch the output file, or create a stub one 83 | automake touch all \`Makefile.in' files 84 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 85 | flex create \`lex.yy.c', if possible, from existing .c 86 | help2man touch the output file 87 | lex create \`lex.yy.c', if possible, from existing .c 88 | makeinfo touch the output file 89 | tar try tar, gnutar, gtar, then tar without non-portable flags 90 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 91 | 92 | Send bug reports to ." 93 | exit $? 94 | ;; 95 | 96 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 97 | echo "missing $scriptversion (GNU Automake)" 98 | exit $? 99 | ;; 100 | 101 | -*) 102 | echo 1>&2 "$0: Unknown \`$1' option" 103 | echo 1>&2 "Try \`$0 --help' for more information" 104 | exit 1 105 | ;; 106 | 107 | esac 108 | 109 | # Now exit if we have it, but it failed. Also exit now if we 110 | # don't have it and --version was passed (most likely to detect 111 | # the program). 112 | case $1 in 113 | lex|yacc) 114 | # Not GNU programs, they don't have --version. 115 | ;; 116 | 117 | tar) 118 | if test -n "$run"; then 119 | echo 1>&2 "ERROR: \`tar' requires --run" 120 | exit 1 121 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 122 | exit 1 123 | fi 124 | ;; 125 | 126 | *) 127 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 128 | # We have it, but it failed. 129 | exit 1 130 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 131 | # Could not run --version or --help. This is probably someone 132 | # running `$TOOL --version' or `$TOOL --help' to check whether 133 | # $TOOL exists and not knowing $TOOL uses missing. 134 | exit 1 135 | fi 136 | ;; 137 | esac 138 | 139 | # If it does not exist, or fails to run (possibly an outdated version), 140 | # try to emulate it. 141 | case $1 in 142 | aclocal*) 143 | echo 1>&2 "\ 144 | WARNING: \`$1' is $msg. You should only need it if 145 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 146 | to install the \`Automake' and \`Perl' packages. Grab them from 147 | any GNU archive site." 148 | touch aclocal.m4 149 | ;; 150 | 151 | autoconf) 152 | echo 1>&2 "\ 153 | WARNING: \`$1' is $msg. You should only need it if 154 | you modified \`${configure_ac}'. You might want to install the 155 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 156 | archive site." 157 | touch configure 158 | ;; 159 | 160 | autoheader) 161 | echo 1>&2 "\ 162 | WARNING: \`$1' is $msg. You should only need it if 163 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 164 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 165 | from any GNU archive site." 166 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 167 | test -z "$files" && files="config.h" 168 | touch_files= 169 | for f in $files; do 170 | case $f in 171 | *:*) touch_files="$touch_files "`echo "$f" | 172 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 173 | *) touch_files="$touch_files $f.in";; 174 | esac 175 | done 176 | touch $touch_files 177 | ;; 178 | 179 | automake*) 180 | echo 1>&2 "\ 181 | WARNING: \`$1' is $msg. You should only need it if 182 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 183 | You might want to install the \`Automake' and \`Perl' packages. 184 | Grab them from any GNU archive site." 185 | find . -type f -name Makefile.am -print | 186 | sed 's/\.am$/.in/' | 187 | while read f; do touch "$f"; done 188 | ;; 189 | 190 | autom4te) 191 | echo 1>&2 "\ 192 | WARNING: \`$1' is needed, but is $msg. 193 | You might have modified some files without having the 194 | proper tools for further handling them. 195 | You can get \`$1' as part of \`Autoconf' from any GNU 196 | archive site." 197 | 198 | file=`echo "$*" | sed -n "$sed_output"` 199 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 200 | if test -f "$file"; then 201 | touch $file 202 | else 203 | test -z "$file" || exec >$file 204 | echo "#! /bin/sh" 205 | echo "# Created by GNU Automake missing as a replacement of" 206 | echo "# $ $@" 207 | echo "exit 0" 208 | chmod +x $file 209 | exit 1 210 | fi 211 | ;; 212 | 213 | bison|yacc) 214 | echo 1>&2 "\ 215 | WARNING: \`$1' $msg. You should only need it if 216 | you modified a \`.y' file. You may need the \`Bison' package 217 | in order for those modifications to take effect. You can get 218 | \`Bison' from any GNU archive site." 219 | rm -f y.tab.c y.tab.h 220 | if test $# -ne 1; then 221 | eval LASTARG="\${$#}" 222 | case $LASTARG in 223 | *.y) 224 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 225 | if test -f "$SRCFILE"; then 226 | cp "$SRCFILE" y.tab.c 227 | fi 228 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 229 | if test -f "$SRCFILE"; then 230 | cp "$SRCFILE" y.tab.h 231 | fi 232 | ;; 233 | esac 234 | fi 235 | if test ! -f y.tab.h; then 236 | echo >y.tab.h 237 | fi 238 | if test ! -f y.tab.c; then 239 | echo 'main() { return 0; }' >y.tab.c 240 | fi 241 | ;; 242 | 243 | lex|flex) 244 | echo 1>&2 "\ 245 | WARNING: \`$1' is $msg. You should only need it if 246 | you modified a \`.l' file. You may need the \`Flex' package 247 | in order for those modifications to take effect. You can get 248 | \`Flex' from any GNU archive site." 249 | rm -f lex.yy.c 250 | if test $# -ne 1; then 251 | eval LASTARG="\${$#}" 252 | case $LASTARG in 253 | *.l) 254 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 255 | if test -f "$SRCFILE"; then 256 | cp "$SRCFILE" lex.yy.c 257 | fi 258 | ;; 259 | esac 260 | fi 261 | if test ! -f lex.yy.c; then 262 | echo 'main() { return 0; }' >lex.yy.c 263 | fi 264 | ;; 265 | 266 | help2man) 267 | echo 1>&2 "\ 268 | WARNING: \`$1' is $msg. You should only need it if 269 | you modified a dependency of a manual page. You may need the 270 | \`Help2man' package in order for those modifications to take 271 | effect. You can get \`Help2man' from any GNU archive site." 272 | 273 | file=`echo "$*" | sed -n "$sed_output"` 274 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 275 | if test -f "$file"; then 276 | touch $file 277 | else 278 | test -z "$file" || exec >$file 279 | echo ".ab help2man is required to generate this page" 280 | exit 1 281 | fi 282 | ;; 283 | 284 | makeinfo) 285 | echo 1>&2 "\ 286 | WARNING: \`$1' is $msg. You should only need it if 287 | you modified a \`.texi' or \`.texinfo' file, or any other file 288 | indirectly affecting the aspect of the manual. The spurious 289 | call might also be the consequence of using a buggy \`make' (AIX, 290 | DU, IRIX). You might want to install the \`Texinfo' package or 291 | the \`GNU make' package. Grab either from any GNU archive site." 292 | # The file to touch is that specified with -o ... 293 | file=`echo "$*" | sed -n "$sed_output"` 294 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 295 | if test -z "$file"; then 296 | # ... or it is the one specified with @setfilename ... 297 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 298 | file=`sed -n ' 299 | /^@setfilename/{ 300 | s/.* \([^ ]*\) *$/\1/ 301 | p 302 | q 303 | }' $infile` 304 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 305 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 306 | fi 307 | # If the file does not exist, the user really needs makeinfo; 308 | # let's fail without touching anything. 309 | test -f $file || exit 1 310 | touch $file 311 | ;; 312 | 313 | tar) 314 | shift 315 | 316 | # We have already tried tar in the generic part. 317 | # Look for gnutar/gtar before invocation to avoid ugly error 318 | # messages. 319 | if (gnutar --version > /dev/null 2>&1); then 320 | gnutar "$@" && exit 0 321 | fi 322 | if (gtar --version > /dev/null 2>&1); then 323 | gtar "$@" && exit 0 324 | fi 325 | firstarg="$1" 326 | if shift; then 327 | case $firstarg in 328 | *o*) 329 | firstarg=`echo "$firstarg" | sed s/o//` 330 | tar "$firstarg" "$@" && exit 0 331 | ;; 332 | esac 333 | case $firstarg in 334 | *h*) 335 | firstarg=`echo "$firstarg" | sed s/h//` 336 | tar "$firstarg" "$@" && exit 0 337 | ;; 338 | esac 339 | fi 340 | 341 | echo 1>&2 "\ 342 | WARNING: I can't seem to be able to run \`tar' with the given arguments. 343 | You may want to install GNU tar or Free paxutils, or check the 344 | command line arguments." 345 | exit 1 346 | ;; 347 | 348 | *) 349 | echo 1>&2 "\ 350 | WARNING: \`$1' is needed, and is $msg. 351 | You might have modified some files without having the 352 | proper tools for further handling them. Check the \`README' file, 353 | it often tells you about the needed prerequisites for installing 354 | this package. You may also peek at any GNU archive site, in case 355 | some other package would contain this missing \`$1' program." 356 | exit 1 357 | ;; 358 | esac 359 | 360 | exit 0 361 | 362 | # Local variables: 363 | # eval: (add-hook 'write-file-hooks 'time-stamp) 364 | # time-stamp-start: "scriptversion=" 365 | # time-stamp-format: "%:y-%02m-%02d.%02H" 366 | # time-stamp-end: "$" 367 | # End: 368 | -------------------------------------------------------------------------------- /nginx/Makefile.am: -------------------------------------------------------------------------------- 1 | dist_pkgdata_DATA = config ngx_protobuf.h ngx_protobuf.c 2 | -------------------------------------------------------------------------------- /nginx/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.11.1 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, 6 | # Inc. 7 | # This Makefile.in is free software; the Free Software Foundation 8 | # gives unlimited permission to copy and/or distribute it, 9 | # with or without modifications, as long as this notice is preserved. 10 | 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 13 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | # PARTICULAR PURPOSE. 15 | 16 | @SET_MAKE@ 17 | 18 | VPATH = @srcdir@ 19 | pkgdatadir = $(datadir)/@PACKAGE@ 20 | pkgincludedir = $(includedir)/@PACKAGE@ 21 | pkglibdir = $(libdir)/@PACKAGE@ 22 | pkglibexecdir = $(libexecdir)/@PACKAGE@ 23 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 24 | install_sh_DATA = $(install_sh) -c -m 644 25 | install_sh_PROGRAM = $(install_sh) -c 26 | install_sh_SCRIPT = $(install_sh) -c 27 | INSTALL_HEADER = $(INSTALL_DATA) 28 | transform = $(program_transform_name) 29 | NORMAL_INSTALL = : 30 | PRE_INSTALL = : 31 | POST_INSTALL = : 32 | NORMAL_UNINSTALL = : 33 | PRE_UNINSTALL = : 34 | POST_UNINSTALL = : 35 | build_triplet = @build@ 36 | host_triplet = @host@ 37 | target_triplet = @target@ 38 | subdir = nginx 39 | DIST_COMMON = $(dist_pkgdata_DATA) $(srcdir)/Makefile.am \ 40 | $(srcdir)/Makefile.in 41 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 42 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 43 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 44 | $(ACLOCAL_M4) 45 | mkinstalldirs = $(install_sh) -d 46 | CONFIG_HEADER = $(top_builddir)/config.h 47 | CONFIG_CLEAN_FILES = 48 | CONFIG_CLEAN_VPATH_FILES = 49 | SOURCES = 50 | DIST_SOURCES = 51 | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; 52 | am__vpath_adj = case $$p in \ 53 | $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ 54 | *) f=$$p;; \ 55 | esac; 56 | am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; 57 | am__install_max = 40 58 | am__nobase_strip_setup = \ 59 | srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` 60 | am__nobase_strip = \ 61 | for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" 62 | am__nobase_list = $(am__nobase_strip_setup); \ 63 | for p in $$list; do echo "$$p $$p"; done | \ 64 | sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ 65 | $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ 66 | if (++n[$$2] == $(am__install_max)) \ 67 | { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ 68 | END { for (dir in files) print dir, files[dir] }' 69 | am__base_list = \ 70 | sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ 71 | sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' 72 | am__installdirs = "$(DESTDIR)$(pkgdatadir)" 73 | DATA = $(dist_pkgdata_DATA) 74 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 75 | ACLOCAL = @ACLOCAL@ 76 | AMTAR = @AMTAR@ 77 | AUTOCONF = @AUTOCONF@ 78 | AUTOHEADER = @AUTOHEADER@ 79 | AUTOMAKE = @AUTOMAKE@ 80 | AWK = @AWK@ 81 | CC = @CC@ 82 | CCDEPMODE = @CCDEPMODE@ 83 | CFLAGS = @CFLAGS@ 84 | CPP = @CPP@ 85 | CPPFLAGS = @CPPFLAGS@ 86 | CXX = @CXX@ 87 | CXXCPP = @CXXCPP@ 88 | CXXDEPMODE = @CXXDEPMODE@ 89 | CXXFLAGS = @CXXFLAGS@ 90 | CYGPATH_W = @CYGPATH_W@ 91 | DEFS = @DEFS@ 92 | DEPDIR = @DEPDIR@ 93 | ECHO_C = @ECHO_C@ 94 | ECHO_N = @ECHO_N@ 95 | ECHO_T = @ECHO_T@ 96 | EGREP = @EGREP@ 97 | EXEEXT = @EXEEXT@ 98 | GREP = @GREP@ 99 | INSTALL = @INSTALL@ 100 | INSTALL_DATA = @INSTALL_DATA@ 101 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 102 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 103 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 104 | LDFLAGS = @LDFLAGS@ 105 | LIBOBJS = @LIBOBJS@ 106 | LIBS = @LIBS@ 107 | LTLIBOBJS = @LTLIBOBJS@ 108 | MAKEINFO = @MAKEINFO@ 109 | MKDIR_P = @MKDIR_P@ 110 | OBJEXT = @OBJEXT@ 111 | PACKAGE = @PACKAGE@ 112 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 113 | PACKAGE_NAME = @PACKAGE_NAME@ 114 | PACKAGE_STRING = @PACKAGE_STRING@ 115 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 116 | PACKAGE_VERSION = @PACKAGE_VERSION@ 117 | PATH_SEPARATOR = @PATH_SEPARATOR@ 118 | SET_MAKE = @SET_MAKE@ 119 | SHELL = @SHELL@ 120 | STRIP = @STRIP@ 121 | VERSION = @VERSION@ 122 | abs_builddir = @abs_builddir@ 123 | abs_srcdir = @abs_srcdir@ 124 | abs_top_builddir = @abs_top_builddir@ 125 | abs_top_srcdir = @abs_top_srcdir@ 126 | ac_ct_CC = @ac_ct_CC@ 127 | ac_ct_CXX = @ac_ct_CXX@ 128 | am__include = @am__include@ 129 | am__leading_dot = @am__leading_dot@ 130 | am__quote = @am__quote@ 131 | am__tar = @am__tar@ 132 | am__untar = @am__untar@ 133 | bindir = @bindir@ 134 | build = @build@ 135 | build_alias = @build_alias@ 136 | build_cpu = @build_cpu@ 137 | build_os = @build_os@ 138 | build_vendor = @build_vendor@ 139 | builddir = @builddir@ 140 | datadir = @datadir@ 141 | datarootdir = @datarootdir@ 142 | docdir = @docdir@ 143 | dvidir = @dvidir@ 144 | exec_prefix = @exec_prefix@ 145 | host = @host@ 146 | host_alias = @host_alias@ 147 | host_cpu = @host_cpu@ 148 | host_os = @host_os@ 149 | host_vendor = @host_vendor@ 150 | htmldir = @htmldir@ 151 | includedir = @includedir@ 152 | infodir = @infodir@ 153 | install_sh = @install_sh@ 154 | libdir = @libdir@ 155 | libexecdir = @libexecdir@ 156 | localedir = @localedir@ 157 | localstatedir = @localstatedir@ 158 | mandir = @mandir@ 159 | mkdir_p = @mkdir_p@ 160 | oldincludedir = @oldincludedir@ 161 | pdfdir = @pdfdir@ 162 | prefix = @prefix@ 163 | program_transform_name = @program_transform_name@ 164 | psdir = @psdir@ 165 | sbindir = @sbindir@ 166 | sharedstatedir = @sharedstatedir@ 167 | srcdir = @srcdir@ 168 | sysconfdir = @sysconfdir@ 169 | target = @target@ 170 | target_alias = @target_alias@ 171 | target_cpu = @target_cpu@ 172 | target_os = @target_os@ 173 | target_vendor = @target_vendor@ 174 | top_build_prefix = @top_build_prefix@ 175 | top_builddir = @top_builddir@ 176 | top_srcdir = @top_srcdir@ 177 | dist_pkgdata_DATA = config ngx_protobuf.h ngx_protobuf.c 178 | all: all-am 179 | 180 | .SUFFIXES: 181 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 182 | @for dep in $?; do \ 183 | case '$(am__configure_deps)' in \ 184 | *$$dep*) \ 185 | ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ 186 | && { if test -f $@; then exit 0; else break; fi; }; \ 187 | exit 1;; \ 188 | esac; \ 189 | done; \ 190 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign nginx/Makefile'; \ 191 | $(am__cd) $(top_srcdir) && \ 192 | $(AUTOMAKE) --foreign nginx/Makefile 193 | .PRECIOUS: Makefile 194 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 195 | @case '$?' in \ 196 | *config.status*) \ 197 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 198 | *) \ 199 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ 200 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ 201 | esac; 202 | 203 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 204 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 205 | 206 | $(top_srcdir)/configure: $(am__configure_deps) 207 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 208 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 209 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 210 | $(am__aclocal_m4_deps): 211 | install-dist_pkgdataDATA: $(dist_pkgdata_DATA) 212 | @$(NORMAL_INSTALL) 213 | test -z "$(pkgdatadir)" || $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" 214 | @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ 215 | for p in $$list; do \ 216 | if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ 217 | echo "$$d$$p"; \ 218 | done | $(am__base_list) | \ 219 | while read files; do \ 220 | echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ 221 | $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ 222 | done 223 | 224 | uninstall-dist_pkgdataDATA: 225 | @$(NORMAL_UNINSTALL) 226 | @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ 227 | files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ 228 | test -n "$$files" || exit 0; \ 229 | echo " ( cd '$(DESTDIR)$(pkgdatadir)' && rm -f" $$files ")"; \ 230 | cd "$(DESTDIR)$(pkgdatadir)" && rm -f $$files 231 | tags: TAGS 232 | TAGS: 233 | 234 | ctags: CTAGS 235 | CTAGS: 236 | 237 | 238 | distdir: $(DISTFILES) 239 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 240 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 241 | list='$(DISTFILES)'; \ 242 | dist_files=`for file in $$list; do echo $$file; done | \ 243 | sed -e "s|^$$srcdirstrip/||;t" \ 244 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 245 | case $$dist_files in \ 246 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 247 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 248 | sort -u` ;; \ 249 | esac; \ 250 | for file in $$dist_files; do \ 251 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 252 | if test -d $$d/$$file; then \ 253 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 254 | if test -d "$(distdir)/$$file"; then \ 255 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 256 | fi; \ 257 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 258 | cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ 259 | find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ 260 | fi; \ 261 | cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ 262 | else \ 263 | test -f "$(distdir)/$$file" \ 264 | || cp -p $$d/$$file "$(distdir)/$$file" \ 265 | || exit 1; \ 266 | fi; \ 267 | done 268 | check-am: all-am 269 | check: check-am 270 | all-am: Makefile $(DATA) 271 | installdirs: 272 | for dir in "$(DESTDIR)$(pkgdatadir)"; do \ 273 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ 274 | done 275 | install: install-am 276 | install-exec: install-exec-am 277 | install-data: install-data-am 278 | uninstall: uninstall-am 279 | 280 | install-am: all-am 281 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 282 | 283 | installcheck: installcheck-am 284 | install-strip: 285 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 286 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 287 | `test -z '$(STRIP)' || \ 288 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 289 | mostlyclean-generic: 290 | 291 | clean-generic: 292 | 293 | distclean-generic: 294 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 295 | -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) 296 | 297 | maintainer-clean-generic: 298 | @echo "This command is intended for maintainers to use" 299 | @echo "it deletes files that may require special tools to rebuild." 300 | clean: clean-am 301 | 302 | clean-am: clean-generic mostlyclean-am 303 | 304 | distclean: distclean-am 305 | -rm -f Makefile 306 | distclean-am: clean-am distclean-generic 307 | 308 | dvi: dvi-am 309 | 310 | dvi-am: 311 | 312 | html: html-am 313 | 314 | html-am: 315 | 316 | info: info-am 317 | 318 | info-am: 319 | 320 | install-data-am: install-dist_pkgdataDATA 321 | 322 | install-dvi: install-dvi-am 323 | 324 | install-dvi-am: 325 | 326 | install-exec-am: 327 | 328 | install-html: install-html-am 329 | 330 | install-html-am: 331 | 332 | install-info: install-info-am 333 | 334 | install-info-am: 335 | 336 | install-man: 337 | 338 | install-pdf: install-pdf-am 339 | 340 | install-pdf-am: 341 | 342 | install-ps: install-ps-am 343 | 344 | install-ps-am: 345 | 346 | installcheck-am: 347 | 348 | maintainer-clean: maintainer-clean-am 349 | -rm -f Makefile 350 | maintainer-clean-am: distclean-am maintainer-clean-generic 351 | 352 | mostlyclean: mostlyclean-am 353 | 354 | mostlyclean-am: mostlyclean-generic 355 | 356 | pdf: pdf-am 357 | 358 | pdf-am: 359 | 360 | ps: ps-am 361 | 362 | ps-am: 363 | 364 | uninstall-am: uninstall-dist_pkgdataDATA 365 | 366 | .MAKE: install-am install-strip 367 | 368 | .PHONY: all all-am check check-am clean clean-generic distclean \ 369 | distclean-generic distdir dvi dvi-am html html-am info info-am \ 370 | install install-am install-data install-data-am \ 371 | install-dist_pkgdataDATA install-dvi install-dvi-am \ 372 | install-exec install-exec-am install-html install-html-am \ 373 | install-info install-info-am install-man install-pdf \ 374 | install-pdf-am install-ps install-ps-am install-strip \ 375 | installcheck installcheck-am installdirs maintainer-clean \ 376 | maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ 377 | pdf-am ps ps-am uninstall uninstall-am \ 378 | uninstall-dist_pkgdataDATA 379 | 380 | 381 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 382 | # Otherwise a system limit (for SysV at least) may be exceeded. 383 | .NOEXPORT: 384 | -------------------------------------------------------------------------------- /nginx/config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_protobuf_module 2 | 3 | CORE_MODULES="$CORE_MODULES ngx_protobuf_module" 4 | NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/ngx_protobuf.h" 5 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_protobuf.c" 6 | -------------------------------------------------------------------------------- /nginx/ngx_protobuf.h: -------------------------------------------------------------------------------- 1 | #ifndef _NGX_PROTOBUF_H_INCLUDED_ 2 | #define _NGX_PROTOBUF_H_INCLUDED_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* wire types */ 9 | 10 | typedef enum { 11 | NGX_PROTOBUF_WIRETYPE_VARINT = 0, 12 | NGX_PROTOBUF_WIRETYPE_FIXED64 = 1, 13 | NGX_PROTOBUF_WIRETYPE_LENGTH_DELIMITED = 2, 14 | NGX_PROTOBUF_WIRETYPE_START_GROUP = 3, 15 | NGX_PROTOBUF_WIRETYPE_END_GROUP = 4, 16 | NGX_PROTOBUF_WIRETYPE_FIXED32 = 5 17 | } ngx_protobuf_wiretype_e; 18 | 19 | /* labels for fields */ 20 | 21 | typedef enum { 22 | NGX_PROTOBUF_LABEL_OPTIONAL = 1, 23 | NGX_PROTOBUF_LABEL_REQUIRED = 2, 24 | NGX_PROTOBUF_LABEL_REPEATED = 3 25 | } ngx_protobuf_label_e; 26 | 27 | /* data types */ 28 | 29 | typedef enum { 30 | NGX_PROTOBUF_TYPE_DOUBLE = 1, 31 | NGX_PROTOBUF_TYPE_FLOAT = 2, 32 | NGX_PROTOBUF_TYPE_INT64 = 3, 33 | NGX_PROTOBUF_TYPE_UINT64 = 4, 34 | NGX_PROTOBUF_TYPE_INT32 = 5, 35 | NGX_PROTOBUF_TYPE_FIXED64 = 6, 36 | NGX_PROTOBUF_TYPE_FIXED32 = 7, 37 | NGX_PROTOBUF_TYPE_BOOL = 8, 38 | NGX_PROTOBUF_TYPE_STRING = 9, 39 | NGX_PROTOBUF_TYPE_GROUP = 10, 40 | NGX_PROTOBUF_TYPE_MESSAGE = 11, 41 | NGX_PROTOBUF_TYPE_BYTES = 12, 42 | NGX_PROTOBUF_TYPE_UINT32 = 13, 43 | NGX_PROTOBUF_TYPE_ENUM = 14, 44 | NGX_PROTOBUF_TYPE_SFIXED32 = 15, 45 | NGX_PROTOBUF_TYPE_SFIXED64 = 16, 46 | NGX_PROTOBUF_TYPE_SINT32 = 17, 47 | NGX_PROTOBUF_TYPE_SINT64 = 18, 48 | } ngx_protobuf_type_e; 49 | 50 | /* hook for protobuf modules to register extensions. */ 51 | 52 | typedef struct { 53 | ngx_int_t (*register_extensions)(ngx_cycle_t *cycle); 54 | } ngx_protobuf_module_t; 55 | 56 | /* protobuf module identifier */ 57 | 58 | #define NGX_PROTOBUF_MODULE 0x50425546 /* "PBUF" */ 59 | 60 | /* forward declaration of context object */ 61 | 62 | typedef struct ngx_protobuf_context_s ngx_protobuf_context_t; 63 | 64 | /* method signatures for pack, unpack, and size calculation. */ 65 | 66 | typedef ngx_int_t (*ngx_protobuf_pack_pt) 67 | (void *obj, ngx_protobuf_context_t *ctx); 68 | typedef ngx_int_t (*ngx_protobuf_unpack_pt) 69 | (void *obj, ngx_protobuf_context_t *ctx); 70 | typedef size_t (*ngx_protobuf_size_pt)(void *obj); 71 | 72 | /* protobuf pack/unpack buffer. when packing a protobuf message into 73 | * a buffer, it is the caller's responsibility to ensure that there is 74 | * enough space in the buffer to fit the message. when unpacking, the 75 | * caller must initialize the start and last pointers so the unpack 76 | * routines know where the input data begin and end. the routines 77 | * will use the pos pointer internally. 78 | */ 79 | 80 | typedef struct { 81 | u_char *start; 82 | u_char *pos; 83 | u_char *last; 84 | } ngx_protobuf_buffer_t; 85 | 86 | #if 0 87 | /* protobuf context state object. this object contains the internal 88 | * state of the pack or unpack routines as they execute, such that a 89 | * protobuf message can be packed or unpacked incrementally (reusing 90 | * the context from one call to the next). so, for example, objects 91 | * that need to be unpacked from several non-contiguous input buffers 92 | * can be unpacked by calling the top-level unpack routine on each of 93 | * the input buffers in succession. the same is true for objects that 94 | * need to be packed into multiple output buffers. 95 | */ 96 | 97 | typedef struct { 98 | ngx_int_t status; 99 | uint32_t field; 100 | ngx_protobuf_wiretype_e wire; 101 | uint64_t varint; 102 | u_char fixed[8]; 103 | ngx_protobuf_buffer_t buffer; 104 | ngx_array_t opstack; /* ngx_protobuf_op_pt */ 105 | } ngx_protobuf_state_t; 106 | #endif 107 | 108 | /* protobuf pack/unpack context. the context contains a buffer for the 109 | * input or output binary data, a state object to support incremental 110 | * serialization and deserialization, a set of flags to control certain 111 | * aspects of the data processing, a memory pool for any memory that 112 | * needs to be allocated along the way, and a log for error messages. 113 | */ 114 | 115 | struct ngx_protobuf_context_s { 116 | ngx_protobuf_buffer_t buffer; 117 | // ngx_protobuf_state_t state; 118 | uint32_t reuse_strings : 1; 119 | ngx_pool_t *pool; 120 | ngx_log_t *log; 121 | }; 122 | 123 | /* field descriptor */ 124 | 125 | typedef struct { 126 | ngx_str_t name; 127 | uint32_t number; 128 | ngx_protobuf_wiretype_e wire_type; 129 | ngx_protobuf_label_e label; 130 | ngx_protobuf_type_e type; 131 | size_t width; 132 | ngx_flag_t packed; 133 | ngx_protobuf_pack_pt pack; 134 | ngx_protobuf_unpack_pt unpack; 135 | ngx_protobuf_size_pt size; 136 | } ngx_protobuf_field_descriptor_t; 137 | 138 | /* generic container for an unpacked value. */ 139 | 140 | typedef struct { 141 | ngx_protobuf_type_e type; 142 | ngx_flag_t exists; 143 | union { 144 | uint32_t v_uint32; 145 | int32_t v_int32; 146 | uint64_t v_uint64; 147 | int64_t v_int64; 148 | float v_float; 149 | double v_double; 150 | ngx_str_t v_bytes; 151 | void *v_message; 152 | ngx_array_t *v_repeated; 153 | } u; 154 | } ngx_protobuf_value_t; 155 | 156 | /* container for an unknown field. */ 157 | 158 | typedef struct { 159 | uint32_t number; 160 | ngx_protobuf_wiretype_e wire_type; 161 | ngx_protobuf_value_t value; 162 | } ngx_protobuf_unknown_field_t; 163 | 164 | /* rbtree node for an extension descriptor */ 165 | 166 | typedef struct { 167 | ngx_rbtree_node_t node; 168 | ngx_protobuf_field_descriptor_t *descriptor; 169 | } ngx_protobuf_extension_descriptor_t; 170 | 171 | /* rbtree node for an extension field. */ 172 | 173 | typedef struct { 174 | ngx_rbtree_node_t node; 175 | ngx_protobuf_field_descriptor_t *descriptor; 176 | ngx_protobuf_value_t value; 177 | } ngx_protobuf_extension_field_t; 178 | 179 | /* field prefix macros */ 180 | 181 | #define NGX_PROTOBUF_HEADER(field, wire) \ 182 | (((field) << 3) | NGX_PROTOBUF_WIRETYPE_##wire) 183 | 184 | #define NGX_PROTOBUF_VARINT(field) \ 185 | NGX_PROTOBUF_HEADER(field, VARINT) 186 | 187 | #define NGX_PROTOBUF_FIXED64(field) \ 188 | NGX_PROTOBUF_HEADER(field, FIXED64) 189 | 190 | #define NGX_PROTOBUF_LENGTH_DELIMITED(field) \ 191 | NGX_PROTOBUF_HEADER(field, LENGTH_DELIMITED) 192 | 193 | #define NGX_PROTOBUF_START_GROUP(field) \ 194 | NGX_PROTOBUF_HEADER(field, START_GROUP) 195 | 196 | #define NGX_PROTOBUF_END_GROUP(field) \ 197 | NGX_PROTOBUF_HEADER(field, END_GROUP) 198 | 199 | #define NGX_PROTOBUF_FIXED32(field) \ 200 | NGX_PROTOBUF_HEADER(field, FIXED32) 201 | 202 | /* zigzag encoding and decoding */ 203 | 204 | #define NGX_PROTOBUF_Z32_ENCODE(val) \ 205 | ((val << 1) ^ (val >> 31)) 206 | 207 | #define NGX_PROTOBUF_Z32_DECODE(val) \ 208 | (int32_t)((val >> 1) ^ -(int32_t)(val & 1)) 209 | 210 | #define NGX_PROTOBUF_Z64_ENCODE(val) \ 211 | ((val << 1) ^ (val >> 63)) 212 | 213 | #define NGX_PROTOBUF_Z64_DECODE(val) \ 214 | (int64_t)((val >> 1) ^ -(int64_t)(val & 1)) 215 | 216 | /* accessor macros */ 217 | 218 | #define NGX_PROTOBUF_CLEAR_MEMBER(obj, field) \ 219 | do { \ 220 | (obj)->field = NULL; \ 221 | (obj)->__has_##field = 0; \ 222 | } while (0) 223 | 224 | #define NGX_PROTOBUF_CLEAR_STRING(obj, field) \ 225 | do { \ 226 | (obj)->field.data = NULL; \ 227 | (obj)->field.len = 0; \ 228 | (obj)->__has_##field = 0; \ 229 | } while (0) 230 | 231 | #define NGX_PROTOBUF_CLEAR_NUMBER(obj, field) \ 232 | do { \ 233 | (obj)->field = 0; \ 234 | (obj)->__has_##field = 0; \ 235 | } while (0) 236 | 237 | #define NGX_PROTOBUF_SET_MEMBER(obj, field, val) \ 238 | do { \ 239 | (obj)->field = val; \ 240 | if (val != NULL) { \ 241 | (obj)->__has_##field = 1 ; \ 242 | } \ 243 | } while (0) 244 | 245 | #define NGX_PROTOBUF_SET_STRING(obj, field, str) \ 246 | do { \ 247 | (obj)->field.data = str->data; \ 248 | (obj)->field.len = str->len; \ 249 | (obj)->__has_##field = 1; \ 250 | } while (0) 251 | 252 | #define NGX_PROTOBUF_SET_NUMBER(obj, field, val) \ 253 | do { \ 254 | (obj)->field = val; \ 255 | (obj)->__has_##field = 1; \ 256 | } while (0) 257 | 258 | #define NGX_PROTOBUF_SET_ARRAY(obj, field, val) \ 259 | do { \ 260 | (obj)->field = val; \ 261 | if (val != NULL && val->nelts > 0) { \ 262 | (obj)->__has_##field = 1; \ 263 | } \ 264 | } while (0) 265 | 266 | #define NGX_PROTOBUF_HAS_FIELD(obj, field) \ 267 | (obj)->__has_##field 268 | 269 | /* datatype size calculations */ 270 | 271 | #define NGX_PROTOBUF_SIZE_UINT \ 272 | size_t s = 0; \ 273 | \ 274 | do { ++s; } while ((val >>= 7)); \ 275 | \ 276 | return s 277 | 278 | static ngx_inline size_t 279 | ngx_protobuf_size_uint32(uint32_t val) 280 | { 281 | NGX_PROTOBUF_SIZE_UINT; 282 | } 283 | 284 | static ngx_inline size_t 285 | ngx_protobuf_size_uint64(uint64_t val) 286 | { 287 | NGX_PROTOBUF_SIZE_UINT; 288 | } 289 | 290 | static ngx_inline size_t 291 | ngx_protobuf_size_int32(int32_t val) 292 | { 293 | return (val < 0) ? 10 : ngx_protobuf_size_uint32((uint32_t)val); 294 | } 295 | 296 | static ngx_inline size_t 297 | ngx_protobuf_size_int64(int64_t val) 298 | { 299 | return (val < 0) ? 10 : ngx_protobuf_size_uint64((uint64_t)val); 300 | } 301 | 302 | static ngx_inline size_t 303 | ngx_protobuf_size_sint32(int32_t val) 304 | { 305 | return ngx_protobuf_size_uint32(NGX_PROTOBUF_Z32_ENCODE(val)); 306 | } 307 | 308 | static ngx_inline size_t 309 | ngx_protobuf_size_sint64(int64_t val) 310 | { 311 | return ngx_protobuf_size_uint64(NGX_PROTOBUF_Z64_ENCODE(val)); 312 | } 313 | 314 | static ngx_inline size_t 315 | ngx_protobuf_size_binary(size_t val) 316 | { 317 | return ngx_protobuf_size_uint32(val) + val; 318 | } 319 | 320 | static ngx_inline size_t 321 | ngx_protobuf_size_string(ngx_str_t *val) 322 | { 323 | return ngx_protobuf_size_binary(val->len); 324 | } 325 | 326 | /* field size calculations */ 327 | 328 | #define ngx_protobuf_size_uint32_field(val, field) \ 329 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_VARINT(field)) + \ 330 | ngx_protobuf_size_uint32(val)) 331 | 332 | #define ngx_protobuf_size_uint64_field(val, field) \ 333 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_VARINT(field)) + \ 334 | ngx_protobuf_size_uint64(val)) 335 | 336 | #define ngx_protobuf_size_fixed32_field(field) \ 337 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_FIXED32(field)) + 4) 338 | 339 | #define ngx_protobuf_size_fixed64_field(field) \ 340 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_FIXED64(field)) + 8) 341 | 342 | #define ngx_protobuf_size_sint32_field(val, field) \ 343 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_VARINT(field)) + \ 344 | ngx_protobuf_size_uint32(NGX_PROTOBUF_Z32_ENCODE(val))) 345 | 346 | #define ngx_protobuf_size_sint64_field(val, field) \ 347 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_VARINT(field)) + \ 348 | ngx_protobuf_size_uint64(NGX_PROTOBUF_Z64_ENCODE(val))) 349 | 350 | #define ngx_protobuf_size_string_field(val, field) \ 351 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_LENGTH_DELIMITED(field)) + \ 352 | ngx_protobuf_size_string(val)) 353 | 354 | #define ngx_protobuf_size_message_field(len, field) \ 355 | (ngx_protobuf_size_uint32(NGX_PROTOBUF_LENGTH_DELIMITED(field)) + \ 356 | ngx_protobuf_size_binary(len)) 357 | 358 | /* using fixed sizes for memcpy helps with optimization */ 359 | 360 | #define NGX_PROTOBUF_BIGENDIAN_COPY4(dst, src) \ 361 | dst += 3; \ 362 | *dst-- = *src++; *dst-- = *src++; *dst-- = *src++; *dst = *src 363 | 364 | #define NGX_PROTOBUF_BIGENDIAN_COPY8(dst, src) \ 365 | dst += 7; \ 366 | *dst-- = *src++; *dst-- = *src++; *dst-- = *src++; *dst-- = *src++; \ 367 | *dst-- = *src++; *dst-- = *src++; *dst-- = *src++; *dst = *src; 368 | 369 | static ngx_inline void 370 | ngx_protobuf_copy_endian4(u_char *dst, u_char *src) 371 | { 372 | #if __BYTE_ORDER == __LITTLE_ENDIAN 373 | memcpy(dst, src, 4); 374 | #else /* __BYTE_ORDER != __LITTLE_ENDIAN */ 375 | NGX_PROTOBUF_BIGENDIAN_COPY4(dst, src); 376 | #endif /* __BYTE_ORDER */ 377 | } 378 | 379 | static ngx_inline void 380 | ngx_protobuf_copy_endian8(u_char *dst, u_char *src) 381 | { 382 | #if __BYTE_ORDER == __LITTLE_ENDIAN 383 | memcpy(dst, src, 8); 384 | #else /* __BYTE_ORDER != __LITTLE_ENDIAN */ 385 | NGX_PROTOBUF_BIGENDIAN_COPY8(dst, src); 386 | #endif /* __BYTE_ORDER */ 387 | } 388 | 389 | static ngx_inline void 390 | ngx_protobuf_copy_float4(u_char *dst, u_char *src) 391 | { 392 | #if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN 393 | memcpy(dst, src, 4); 394 | #else /* __FLOAT_WORD_ORDER != __LITTLE_ENDIAN */ 395 | NGX_PROTOBUF_BIGENDIAN_COPY4(dst, src); 396 | #endif /* __FLOAT_WORD_ORDER */ 397 | } 398 | 399 | static ngx_inline void 400 | ngx_protobuf_copy_float8(u_char *dst, u_char *src) 401 | { 402 | #if __FLOAT_WORD_ORDER == __LITTLE_ENDIAN 403 | memcpy(dst, src, 8); 404 | #else /* __FLOAT_WORD_ORDER != __LITTLE_ENDIAN */ 405 | NGX_PROTOBUF_BIGENDIAN_COPY8(dst, src); 406 | #endif /* __FLOAT_WORD_ORDER */ 407 | } 408 | 409 | /* reading values */ 410 | 411 | static ngx_inline ngx_int_t 412 | ngx_protobuf_read_uint64(u_char **buf, u_char *end, uint64_t *val) 413 | { 414 | uint32_t s = 0; 415 | uint64_t v = 0; 416 | u_char *p = *buf; 417 | 418 | if (p >= end) { 419 | return NGX_ABORT; 420 | } 421 | 422 | do { 423 | v |= (uint64_t)(*p & 0x7f) << s; 424 | s += 7; 425 | } while ((*p++ & 0x80) && (p <= end) && (s < 64)); 426 | 427 | *buf = p; 428 | 429 | if (*(p-1) & 0x80) { 430 | return NGX_ABORT; 431 | } 432 | 433 | *val = v; 434 | 435 | return NGX_OK; 436 | } 437 | 438 | static ngx_inline ngx_int_t 439 | ngx_protobuf_read_uint32(u_char **buf, u_char *end, uint32_t *val) 440 | { 441 | uint64_t v64; 442 | 443 | if (ngx_protobuf_read_uint64(buf, end, &v64) != NGX_OK) { 444 | return NGX_ABORT; 445 | } 446 | 447 | *val = (uint32_t)v64; 448 | 449 | return NGX_OK; 450 | } 451 | 452 | ngx_int_t ngx_protobuf_read_string(u_char **buf, 453 | u_char *end, 454 | ngx_str_t *val, 455 | ngx_pool_t *pool); 456 | 457 | static ngx_inline ngx_int_t 458 | ngx_protobuf_read_bool(u_char **buf, u_char *end, uint32_t *val) 459 | { 460 | ngx_int_t rc; 461 | uint32_t uval; 462 | 463 | rc = ngx_protobuf_read_uint32(buf, end, &uval); 464 | if (rc == NGX_OK) { 465 | *val = (uval != 0); 466 | } 467 | 468 | return rc; 469 | } 470 | 471 | #define NGX_PROTOBUF_READ_COPY(method, dst, size) \ 472 | if (*buf + size > end) { \ 473 | return NGX_ABORT; \ 474 | } \ 475 | \ 476 | ngx_protobuf_copy_##method##size(*buf, (u_char *)dst); \ 477 | *buf += size 478 | 479 | static ngx_inline ngx_int_t 480 | ngx_protobuf_read_fixed32(u_char **buf, u_char *end, uint32_t *val) 481 | { 482 | NGX_PROTOBUF_READ_COPY(endian, val, 4); 483 | 484 | return NGX_OK; 485 | } 486 | 487 | static ngx_inline ngx_int_t 488 | ngx_protobuf_read_sfixed32(u_char **buf, u_char *end, int32_t *val) 489 | { 490 | uint32_t uval; 491 | 492 | NGX_PROTOBUF_READ_COPY(endian, &uval, 4); 493 | *val = NGX_PROTOBUF_Z32_DECODE(uval); 494 | 495 | return NGX_OK; 496 | } 497 | 498 | static ngx_inline ngx_int_t 499 | ngx_protobuf_read_fixed64(u_char **buf, u_char *end, uint64_t *val) 500 | { 501 | NGX_PROTOBUF_READ_COPY(endian, val, 8); 502 | 503 | return NGX_OK; 504 | } 505 | 506 | static ngx_inline ngx_int_t 507 | ngx_protobuf_read_sfixed64(u_char **buf, u_char *end, int64_t *val) 508 | { 509 | uint64_t uval; 510 | 511 | NGX_PROTOBUF_READ_COPY(endian, &uval, 8); 512 | *val = NGX_PROTOBUF_Z64_DECODE(uval); 513 | 514 | return NGX_OK; 515 | } 516 | 517 | static ngx_inline ngx_int_t 518 | ngx_protobuf_read_sint32(u_char **buf, u_char *end, int32_t *val) 519 | { 520 | ngx_int_t rc; 521 | uint32_t uval; 522 | 523 | rc = ngx_protobuf_read_uint32(buf, end, &uval); 524 | if (rc == NGX_OK) { 525 | *val = NGX_PROTOBUF_Z32_DECODE(uval); 526 | } 527 | 528 | return rc; 529 | } 530 | 531 | static ngx_inline ngx_int_t 532 | ngx_protobuf_read_sint64(u_char **buf, u_char *end, int64_t *val) 533 | { 534 | ngx_int_t rc; 535 | uint64_t uval; 536 | 537 | rc = ngx_protobuf_read_uint64(buf, end, &uval); 538 | if (rc == NGX_OK) { 539 | *val = NGX_PROTOBUF_Z64_DECODE(uval); 540 | } 541 | 542 | return rc; 543 | } 544 | 545 | static ngx_inline ngx_int_t 546 | ngx_protobuf_read_float(u_char **buf, u_char *end, float *val) 547 | { 548 | NGX_PROTOBUF_READ_COPY(float, val, 4); 549 | 550 | return NGX_OK; 551 | } 552 | 553 | static ngx_inline ngx_int_t 554 | ngx_protobuf_read_double(u_char **buf, u_char *end, double *val) 555 | { 556 | NGX_PROTOBUF_READ_COPY(endian, val, 8); 557 | 558 | return NGX_OK; 559 | } 560 | 561 | /* writing values */ 562 | 563 | #define NGX_PROTOBUF_WRITE_UINT \ 564 | do { *buf++ = (uint8_t)(val | 0x80); } while ((val >>= 7)); \ 565 | *(buf-1) &= 0x7f; \ 566 | \ 567 | return buf 568 | 569 | static ngx_inline u_char * 570 | ngx_protobuf_write_uint32(u_char *buf, uint32_t val) 571 | { 572 | NGX_PROTOBUF_WRITE_UINT; 573 | } 574 | 575 | static ngx_inline u_char * 576 | ngx_protobuf_write_uint64(u_char *buf, uint64_t val) 577 | { 578 | NGX_PROTOBUF_WRITE_UINT; 579 | } 580 | 581 | static ngx_inline u_char * 582 | ngx_protobuf_write_string(u_char *buf, ngx_str_t *val) 583 | { 584 | buf = ngx_protobuf_write_uint32(buf, val->len); 585 | buf = ngx_cpymem(buf, val->data, val->len); 586 | 587 | return buf; 588 | } 589 | 590 | #define NGX_PROTOBUF_WRITE_COPY(method, size) \ 591 | ngx_protobuf_copy_##method##size(buf, (uint8_t *)&val); \ 592 | \ 593 | return buf + size 594 | 595 | static ngx_inline u_char * 596 | ngx_protobuf_write_fixed32(u_char *buf, uint32_t val) 597 | { 598 | NGX_PROTOBUF_WRITE_COPY(endian, 4); 599 | } 600 | 601 | static ngx_inline u_char * 602 | ngx_protobuf_write_fixed64(u_char *buf, uint64_t val) 603 | { 604 | NGX_PROTOBUF_WRITE_COPY(endian, 8); 605 | } 606 | 607 | #define ngx_protobuf_write_sfixed32(buf, val) \ 608 | ngx_protobuf_write_fixed32(buf, NGX_PROTOBUF_Z32_ENCODE(val)) 609 | 610 | #define ngx_protobuf_write_sfixed64(buf, val) \ 611 | ngx_protobuf_write_fixed64(buf, NGX_PROTOBUF_Z64_ENCODE(val)) 612 | 613 | #define ngx_protobuf_write_sint32(buf, val) \ 614 | ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_Z32_ENCODE(val)) 615 | 616 | #define ngx_protobuf_write_sint64(buf, val) \ 617 | ngx_protobuf_write_uint64(buf, NGX_PROTOBUF_Z64_ENCODE(val)) 618 | 619 | static ngx_inline u_char * 620 | ngx_protobuf_write_float(u_char *buf, float val) 621 | { 622 | NGX_PROTOBUF_WRITE_COPY(float, 4); 623 | } 624 | 625 | static ngx_inline u_char * 626 | ngx_protobuf_write_double(u_char *buf, double val) 627 | { 628 | NGX_PROTOBUF_WRITE_COPY(float, 8); 629 | } 630 | 631 | /* writing fields */ 632 | 633 | static ngx_inline u_char * 634 | ngx_protobuf_write_uint32_field(u_char *buf, uint32_t val, uint32_t field) 635 | { 636 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_VARINT(field)); 637 | buf = ngx_protobuf_write_uint32(buf, val); 638 | 639 | return buf; 640 | } 641 | 642 | static ngx_inline u_char * 643 | ngx_protobuf_write_uint64_field(u_char *buf, uint64_t val, uint32_t field) 644 | { 645 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_VARINT(field)); 646 | buf = ngx_protobuf_write_uint64(buf, val); 647 | 648 | return buf; 649 | } 650 | 651 | static ngx_inline u_char * 652 | ngx_protobuf_write_string_field(u_char *buf, ngx_str_t *val, uint32_t field) 653 | { 654 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_LENGTH_DELIMITED(field)); 655 | buf = ngx_protobuf_write_string(buf, val); 656 | 657 | return buf; 658 | } 659 | 660 | static ngx_inline u_char * 661 | ngx_protobuf_write_fixed32_field(u_char *buf, uint32_t val, uint32_t field) 662 | { 663 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_FIXED32(field)); 664 | buf = ngx_protobuf_write_fixed32(buf, val); 665 | 666 | return buf; 667 | } 668 | 669 | static ngx_inline u_char * 670 | ngx_protobuf_write_fixed64_field(u_char *buf, uint64_t val, uint32_t field) 671 | { 672 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_FIXED64(field)); 673 | buf = ngx_protobuf_write_fixed64(buf, val); 674 | 675 | return buf; 676 | } 677 | 678 | #define ngx_protobuf_write_sfixed32_field(buf, val, field) \ 679 | ngx_protobuf_write_fixed32_field(buf, NGX_PROTOBUF_Z32_ENCODE(val), field) 680 | 681 | #define ngx_protobuf_write_sfixed64_field(buf, val, field) \ 682 | ngx_protobuf_write_fixed64_field(buf, NGX_PROTOBUF_Z64_ENCODE(val), field) 683 | 684 | #define ngx_protobuf_write_sint32_field(buf, val, field) \ 685 | ngx_protobuf_write_uint32_field(buf, NGX_PROTOBUF_Z32_ENCODE(val), field) 686 | 687 | #define ngx_protobuf_write_sint64_field(buf, val, field) \ 688 | ngx_protobuf_write_uint64_field(buf, NGX_PROTOBUF_Z64_ENCODE(val), field) 689 | 690 | static ngx_inline u_char * 691 | ngx_protobuf_write_float_field(u_char *buf, float val, uint32_t field) 692 | { 693 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_FIXED32(field)); 694 | buf = ngx_protobuf_write_float(buf, val); 695 | 696 | return buf; 697 | } 698 | 699 | static ngx_inline u_char * 700 | ngx_protobuf_write_double_field(u_char *buf, float val, uint32_t field) 701 | { 702 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_FIXED32(field)); 703 | buf = ngx_protobuf_write_double(buf, val); 704 | 705 | return buf; 706 | } 707 | 708 | static ngx_inline u_char * 709 | ngx_protobuf_write_message_header(u_char *buf, size_t len, uint32_t field) 710 | { 711 | buf = ngx_protobuf_write_uint32(buf, NGX_PROTOBUF_LENGTH_DELIMITED(field)); 712 | buf = ngx_protobuf_write_uint32(buf, len); 713 | 714 | return buf; 715 | } 716 | 717 | /* other non-inlined methods */ 718 | 719 | ngx_int_t ngx_protobuf_skip(u_char **buf, u_char *end, uint32_t wire); 720 | 721 | void *ngx_protobuf_push_array(ngx_array_t **a, ngx_pool_t *p, size_t n); 722 | 723 | ngx_int_t ngx_protobuf_import_extension(ngx_rbtree_t **registry, 724 | ngx_protobuf_field_descriptor_t *desc, 725 | ngx_cycle_t *cycle); 726 | 727 | ngx_protobuf_value_t *ngx_protobuf_get_extension(ngx_rbtree_t *extensions, 728 | uint32_t field); 729 | 730 | ngx_int_t ngx_protobuf_set_extension(ngx_rbtree_t **extensions, 731 | ngx_rbtree_t *registry, 732 | uint32_t field, 733 | ngx_protobuf_value_t *value, 734 | ngx_pool_t *pool); 735 | 736 | ngx_int_t ngx_protobuf_add_extension(ngx_rbtree_t **extensions, 737 | ngx_rbtree_t *registry, 738 | uint32_t field, 739 | void **ptr, 740 | ngx_pool_t *pool); 741 | 742 | void ngx_protobuf_clear_extension(ngx_rbtree_t *extensions, 743 | uint32_t field); 744 | 745 | ngx_int_t ngx_protobuf_unpack_extension(uint32_t field, 746 | ngx_protobuf_wiretype_e wire, 747 | ngx_protobuf_context_t *ctx, 748 | ngx_rbtree_t *registry, 749 | ngx_rbtree_t **extensions); 750 | 751 | size_t ngx_protobuf_size_extensions(ngx_rbtree_t *extensions); 752 | 753 | ngx_int_t ngx_protobuf_pack_extensions(ngx_rbtree_t *extensions, 754 | uint32_t lower, 755 | uint32_t upper, 756 | ngx_protobuf_context_t *ctx); 757 | 758 | ngx_int_t ngx_protobuf_unpack_unknown_field(uint32_t field, 759 | ngx_protobuf_wiretype_e wire, 760 | ngx_protobuf_context_t *ctx, 761 | ngx_array_t **unknown); 762 | 763 | size_t ngx_protobuf_size_unknown_field(ngx_protobuf_unknown_field_t *field); 764 | 765 | ngx_int_t ngx_protobuf_pack_unknown_field(ngx_protobuf_unknown_field_t *field, 766 | ngx_protobuf_context_t *ctx); 767 | 768 | #endif /* _NGX_PROTOBUF_H_INCLUDED_ */ 769 | -------------------------------------------------------------------------------- /protongx/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = protongx 2 | 3 | noinst_HEADERS = \ 4 | ngx_flags.h \ 5 | ngx_generator.h 6 | 7 | protongx_SOURCES = \ 8 | ngx_add.cc \ 9 | ngx_descriptor.cc \ 10 | ngx_descriptor_util.cc \ 11 | ngx_extension.cc \ 12 | ngx_field_util.cc \ 13 | ngx_flags.cc \ 14 | ngx_generate.cc \ 15 | ngx_is_initialized.cc \ 16 | ngx_main.cc \ 17 | ngx_methods.cc \ 18 | ngx_module.cc \ 19 | ngx_name.cc \ 20 | ngx_pack.cc \ 21 | ngx_print.cc \ 22 | ngx_size.cc \ 23 | ngx_typedef.cc \ 24 | ngx_unpack.cc 25 | 26 | protongx_CXXFLAGS = -Wall 27 | protongx_LDADD = -lprotobuf -lprotoc -lpthread 28 | -------------------------------------------------------------------------------- /protongx/ngx_add.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | void 10 | Generator::GenerateAdd(const Descriptor* desc, io::Printer& printer) 11 | { 12 | Flags flags(desc); 13 | 14 | if (!flags.has_array()) { 15 | return; 16 | } 17 | 18 | std::map vars; 19 | 20 | vars["name"] = desc->full_name(); 21 | vars["root"] = TypedefRoot(desc->full_name()); 22 | vars["type"] = StructType(desc->full_name()); 23 | 24 | printer.Print(vars, 25 | "/* $name$ field methods */\n" 26 | "\n"); 27 | 28 | for (int i = 0; i < desc->field_count(); ++i) { 29 | const FieldDescriptor *field = desc->field(i); 30 | 31 | if (field->is_repeated()) { 32 | vars["field"] = FieldRealType(field); 33 | vars["fname"] = field->name(); 34 | 35 | printer.Print(vars, 36 | "$field$ *\n" 37 | "$root$__add__$fname$(\n" 38 | " $type$ *obj,\n" 39 | " ngx_pool_t *pool)\n" 40 | "{\n"); 41 | Indent(printer); 42 | 43 | printer.Print(vars, 44 | "$field$ *ret;\n" 45 | "\n" 46 | "ret = ngx_protobuf_push_array(&obj->$fname$, pool,\n" 47 | " sizeof($field$));\n" 48 | "if (ret != NULL) {\n"); 49 | Indent(printer); 50 | printer.Print(vars, 51 | "obj->__has_$fname$ = 1;\n"); 52 | Outdent(printer); 53 | printer.Print("}\n" 54 | "\n" 55 | "return ret;\n"); 56 | 57 | Outdent(printer); 58 | printer.Print("}\n" 59 | "\n"); 60 | } 61 | } 62 | } 63 | 64 | } // namespace nginx 65 | } // namespace compiler 66 | } // namespace protobuf 67 | } // namespace google 68 | -------------------------------------------------------------------------------- /protongx/ngx_descriptor.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | void 10 | Generator::GenerateFieldDescriptor(const FieldDescriptor *field, 11 | io::Printer& printer) 12 | { 13 | std::string type(TypedefRoot(field->containing_type()->full_name())); 14 | std::string name; 15 | 16 | if (field->is_extension()) { 17 | name = ExtensionFieldName(field); 18 | } else { 19 | name = field->name(); 20 | } 21 | 22 | std::map vars; 23 | 24 | vars["type"] = type; 25 | vars["name"] = name; 26 | vars["fname"] = field->full_name(); 27 | vars["fnum"] = Number(field->number()); 28 | vars["ftype"] = FieldRealType(field); 29 | vars["wire"] = WireType(field); 30 | vars["label"] = Label(field); 31 | vars["tname"] = Type(field); 32 | 33 | if (field->is_packable() && field->options().packed()) { 34 | vars["packed"] = "1"; 35 | } else { 36 | vars["packed"] = "0"; 37 | } 38 | 39 | if (field->type() == FieldDescriptor::TYPE_MESSAGE) { 40 | std::string froot(TypedefRoot(field->message_type()->full_name())); 41 | 42 | vars["pack"] = froot + "__pack"; 43 | vars["unpack"] = froot + "__unpack"; 44 | vars["size"] = froot + "__size"; 45 | } else { 46 | vars["pack"] = "NULL"; 47 | vars["unpack"] = "NULL"; 48 | vars["size"] = "NULL"; 49 | } 50 | 51 | printer.Print(vars, 52 | "ngx_protobuf_field_descriptor_t\n" 53 | "$type$_$name$ = {\n"); 54 | Indent(printer); 55 | printer.Print(vars, 56 | "ngx_string(\"$name$\"),\n" 57 | "$fnum$,\n" 58 | "$wire$,\n" 59 | "$label$,\n" 60 | "$tname$,\n" 61 | "sizeof($ftype$),\n" 62 | "$packed$,\n" 63 | "(ngx_protobuf_pack_pt)\n" 64 | "$pack$,\n" 65 | "(ngx_protobuf_unpack_pt)\n" 66 | "$unpack$,\n" 67 | "(ngx_protobuf_size_pt)\n" 68 | "$size$\n"); 69 | Outdent(printer); 70 | printer.Print("};\n" 71 | "\n"); 72 | } 73 | 74 | void 75 | Generator::GenerateDescriptors(const Descriptor *desc, 76 | io::Printer& printer) 77 | { 78 | for (int i = 0; i < desc->nested_type_count(); ++i) { 79 | GenerateDescriptors(desc->nested_type(i), printer); 80 | } 81 | 82 | printer.Print("/* $type$ field descriptors */\n" 83 | "\n", 84 | "type", desc->full_name()); 85 | 86 | for (int i = 0; i < desc->field_count(); ++i) { 87 | GenerateFieldDescriptor(desc->field(i), printer); 88 | } 89 | 90 | if (desc->extension_count() > 0) { 91 | printer.Print("/* $type$ extension field descriptors */\n" 92 | "\n", 93 | "type", desc->full_name()); 94 | 95 | for (int i = 0; i < desc->extension_count(); ++i) { 96 | GenerateFieldDescriptor(desc->extension(i), printer); 97 | } 98 | } 99 | 100 | // TODO: generate message descriptor 101 | } 102 | 103 | } // namespace nginx 104 | } // namespace compiler 105 | } // namespace protobuf 106 | } // namespace google 107 | -------------------------------------------------------------------------------- /protongx/ngx_descriptor_util.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | bool 10 | Generator::HasUnknownFields(const Descriptor *desc) 11 | { 12 | return (desc->file()->options().optimize_for() != FileOptions::LITE_RUNTIME); 13 | } 14 | 15 | bool 16 | Generator::HasExtensionFields(const Descriptor *desc) 17 | { 18 | for (int i = 0; i < desc->field_count(); ++i) { 19 | if (desc->field(i)->is_extension()) { 20 | return true; 21 | } 22 | } 23 | 24 | return false; 25 | } 26 | 27 | } // namespace nginx 28 | } // namespace compiler 29 | } // namespace protobuf 30 | } // namespace google 31 | -------------------------------------------------------------------------------- /protongx/ngx_extension.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace google { 4 | namespace protobuf { 5 | namespace compiler { 6 | namespace nginx { 7 | 8 | void 9 | Generator::GenerateExtendeeDecls(const Descriptor *desc, 10 | io::Printer& printer) 11 | { 12 | if (desc->extension_range_count() == 0) { 13 | return; 14 | } 15 | 16 | std::string root(TypedefRoot(desc->full_name())); 17 | 18 | printer.Print("/* $name$ extendee methods */\n" 19 | "\n", "name", desc->full_name()); 20 | 21 | // import, set, add extension 22 | 23 | printer.Print("ngx_int_t $root$__import_extension(\n" 24 | " ngx_protobuf_field_descriptor_t *desc,\n" 25 | " ngx_cycle_t *cycle);\n" 26 | "\n" 27 | "ngx_int_t $root$__set_extension(\n" 28 | " ngx_rbtree_t **extensions,\n" 29 | " uint32_t field,\n" 30 | " ngx_protobuf_value_t *val,\n" 31 | " ngx_pool_t *pool);\n" 32 | "\n" 33 | "void *$root$__add_extension(\n" 34 | " ngx_rbtree_t **extensions,\n" 35 | " uint32_t field,\n" 36 | " ngx_pool_t *pool);\n" 37 | "\n", 38 | "root", root); 39 | } 40 | 41 | void 42 | Generator::GenerateExtendeeMethods(const Descriptor *desc, 43 | io::Printer& printer) 44 | { 45 | if (desc->extension_range_count() == 0) { 46 | return; 47 | } 48 | 49 | std::string root(TypedefRoot(desc->full_name())); 50 | 51 | // import 52 | 53 | printer.Print("ngx_int_t\n" 54 | "$root$__import_extension(\n" 55 | " ngx_protobuf_field_descriptor_t *desc,\n" 56 | " ngx_cycle_t *cycle)\n" 57 | "{\n", 58 | "root", root); 59 | Indent(printer); 60 | printer.Print("return ngx_protobuf_import_extension(\n"); 61 | Indent(printer); 62 | printer.Print("&$root$__extensions, desc, cycle);\n", 63 | "root", root); 64 | Outdent(printer); 65 | CloseBrace(printer); 66 | 67 | printer.Print("\n"); 68 | 69 | // set_extension 70 | 71 | printer.Print("ngx_int_t\n" 72 | "$root$__set_extension(\n" 73 | " ngx_rbtree_t **extensions,\n" 74 | " uint32_t field,\n" 75 | " ngx_protobuf_value_t *val,\n" 76 | " ngx_pool_t *pool)\n", 77 | "root", root); 78 | OpenBrace(printer); 79 | printer.Print("return ngx_protobuf_set_extension(extensions,\n" 80 | " $root$__extensions,\n" 81 | " field, val, pool);\n", 82 | "root", root); 83 | CloseBrace(printer); 84 | printer.Print("\n"); 85 | 86 | // add_extension 87 | 88 | printer.Print("void *\n" 89 | "$root$__add_extension(\n" 90 | " ngx_rbtree_t **extensions,\n" 91 | " uint32_t field,\n" 92 | " ngx_pool_t *pool)\n", 93 | "root", root); 94 | OpenBrace(printer); 95 | printer.Print("void *val = NULL;\n" 96 | "\n" 97 | "ngx_protobuf_add_extension(extensions,\n" 98 | " $root$__extensions,\n" 99 | " field, &val, pool);\n" 100 | "\n" 101 | "return val;\n", 102 | "root", root); 103 | CloseBrace(printer); 104 | printer.Print("\n"); 105 | } 106 | 107 | void 108 | Generator::GenerateExtensionFieldDecls(const FieldDescriptor *field, 109 | io::Printer& printer) 110 | { 111 | std::string mtype(TypedefRoot(field->containing_type()->full_name())); 112 | std::string ftype(FieldRealType(field)); 113 | std::string name(ExtensionFieldName(field)); 114 | 115 | std::map vars; 116 | 117 | int primitive = 0; 118 | 119 | vars["mtype"] = mtype; 120 | vars["name"] = name; 121 | vars["fnum"] = Number(field->number()); 122 | vars["ftype"] = ftype; 123 | vars["dtype"] = Type(field); 124 | vars["gtype"] = FieldTypeName(field); 125 | vars["stype"] = ExtensionSetterType(field, &primitive); 126 | vars["space"] = Spaces(primitive); 127 | 128 | printer.Print(vars, 129 | "#define $mtype$__has_$name$(obj) \\\n" 130 | " (ngx_protobuf_get_extension(obj->__extensions, $fnum$) " 131 | "!= NULL)\n" 132 | "\n" 133 | "#define $mtype$__clear_$name$(obj) \\\n" 134 | " ngx_protobuf_clear_extension(obj->__extensions, " 135 | "$fnum$);\n" 136 | "\n" 137 | "$stype$$space$$mtype$__get_$name$(\n" 138 | " $mtype$_t *obj);\n" 139 | "\n" 140 | "ngx_int_t $mtype$__set_$name$(\n" 141 | " $mtype$_t *obj,\n" 142 | " $stype$$space$ext,\n" 143 | " ngx_pool_t *pool);\n" 144 | "\n"); 145 | 146 | if (primitive) { 147 | printer.Print(vars, 148 | "$gtype$ *$mtype$__mutable_$name$(\n" 149 | " $mtype$_t *obj);\n" 150 | "\n"); 151 | } 152 | 153 | if (field->is_repeated()) { 154 | printer.Print(vars, 155 | "$ftype$ *\n" 156 | "$mtype$__add_$name$(\n" 157 | " $mtype$_t *obj,\n" 158 | " ngx_pool_t *pool);\n" 159 | "\n"); 160 | } 161 | } 162 | 163 | void 164 | Generator::GenerateExtensionFieldMethods(const FieldDescriptor *field, 165 | io::Printer& printer) 166 | { 167 | std::string mtype(TypedefRoot(field->containing_type()->full_name())); 168 | std::string ftype(FieldRealType(field)); 169 | std::string name(ExtensionFieldName(field)); 170 | 171 | std::map vars; 172 | int primitive = 0; 173 | 174 | vars["mtype"] = mtype; 175 | vars["name"] = name; 176 | vars["fnum"] = Number(field->number()); 177 | vars["ftype"] = ftype; 178 | vars["dtype"] = Type(field); 179 | vars["gtype"] = FieldTypeName(field); 180 | vars["stype"] = ExtensionSetterType(field, &primitive); 181 | vars["space"] = Spaces(primitive); 182 | 183 | // get extension 184 | 185 | printer.Print(vars, 186 | "$stype$\n" 187 | "$mtype$__get_$name$(\n" 188 | " $mtype$_t *obj)\n"); 189 | OpenBrace(printer); 190 | printer.Print(vars, 191 | "ngx_protobuf_value_t *val;\n" 192 | "\n" 193 | "val = ngx_protobuf_get_extension(obj->__extensions, " 194 | "$fnum$);\n"); 195 | FullSimpleIf(printer, vars, 196 | "val == NULL || !val->exists", 197 | "return NULL;"); 198 | 199 | printer.Print("\n"); 200 | 201 | if (primitive) { 202 | FullSimpleIf(printer, vars, 203 | "val->type != $dtype$", 204 | "return 0;"); 205 | } else { 206 | FullSimpleIf(printer, vars, 207 | "val->type != $dtype$", 208 | "return NULL;"); 209 | } 210 | 211 | std::string rval; 212 | 213 | if (field->is_repeated()) { 214 | rval = "val->u.v_repeated"; 215 | } else { 216 | switch (field->type()) { 217 | case FieldDescriptor::TYPE_MESSAGE: rval = "val->u.v_message"; break; 218 | case FieldDescriptor::TYPE_BYTES: 219 | case FieldDescriptor::TYPE_STRING: rval = "&val->u.v_bytes"; break; 220 | case FieldDescriptor::TYPE_BOOL: 221 | case FieldDescriptor::TYPE_ENUM: 222 | case FieldDescriptor::TYPE_UINT32: 223 | case FieldDescriptor::TYPE_FIXED32: rval = "val->u.v_uint32"; break; 224 | case FieldDescriptor::TYPE_INT32: 225 | case FieldDescriptor::TYPE_SINT32: 226 | case FieldDescriptor::TYPE_SFIXED32: rval = "val->u.v_int32"; break; 227 | case FieldDescriptor::TYPE_UINT64: 228 | case FieldDescriptor::TYPE_FIXED64: rval = "val->u.v_uint64"; break; 229 | case FieldDescriptor::TYPE_INT64: 230 | case FieldDescriptor::TYPE_SINT64: 231 | case FieldDescriptor::TYPE_SFIXED64: rval = "val->u.v_int64"; break; 232 | case FieldDescriptor::TYPE_FLOAT: rval = "val->u.v_float"; break; 233 | case FieldDescriptor::TYPE_DOUBLE: rval = "val->u.v_double"; break; 234 | default: rval = "FIXME"; break; 235 | } 236 | } 237 | 238 | printer.Print("\n" 239 | "return $rval$;\n", 240 | "rval", rval); 241 | 242 | CloseBrace(printer); 243 | printer.Print("\n"); 244 | 245 | // set extension 246 | 247 | printer.Print(vars, 248 | "ngx_int_t\n" 249 | "$mtype$__set_$name$(\n" 250 | " $mtype$_t *obj,\n" 251 | " $stype$$space$ext,\n" 252 | " ngx_pool_t *pool)\n"); 253 | OpenBrace(printer); 254 | printer.Print(vars, 255 | "ngx_protobuf_value_t val;\n" 256 | "\n" 257 | "val.type = $dtype$;\n"); 258 | 259 | if (field->is_repeated()) { 260 | printer.Print("val.u.v_repeated = ext;\n" 261 | "val.exists = (ext != NULL);\n"); 262 | } else if (field->type() == FieldDescriptor::TYPE_MESSAGE) { 263 | printer.Print("val.u.v_message = ext;\n" 264 | "val.exists = (ext != NULL);\n"); 265 | } else if (field->type() == FieldDescriptor::TYPE_BYTES || 266 | field->type() == FieldDescriptor::TYPE_STRING) { 267 | SimpleIf(printer, vars, "ext != NULL"); 268 | printer.Print("val.u.v_bytes.len = ext->len;\n" 269 | "val.u.v_bytes.data = ext->data;\n" 270 | "val.exists = 1;\n"); 271 | Else(printer); 272 | printer.Print("val.exists = 0;\n"); 273 | CloseBrace(printer); 274 | } else { 275 | printer.Print("val.exists = 1;\n"); 276 | } 277 | 278 | printer.Print(vars, 279 | "\n" 280 | "return $mtype$__set_extension(\n" 281 | " &obj->__extensions, $fnum$, &val, pool);\n"); 282 | 283 | CloseBrace(printer); 284 | printer.Print("\n"); 285 | 286 | // add extension (for repeated extension fields) 287 | 288 | if (field->is_repeated()) { 289 | printer.Print(vars, 290 | "$ftype$ *\n" 291 | "$mtype$__add_$name$(\n" 292 | " $mtype$_t *obj,\n" 293 | " ngx_pool_t *pool)\n"); 294 | OpenBrace(printer); 295 | printer.Print(vars, 296 | "return $mtype$__add_extension(\n" 297 | " &obj->__extensions, $fnum$, pool);\n"); 298 | CloseBrace(printer); 299 | printer.Print("\n"); 300 | } 301 | 302 | 303 | } 304 | 305 | void 306 | Generator::GenerateExtensionMethods(const Descriptor *desc, 307 | io::Printer& printer) 308 | { 309 | for (int i = 0; i < desc->field_count(); ++i) { 310 | const FieldDescriptor *field = desc->field(i); 311 | 312 | if (field->is_extension()) { 313 | GenerateExtensionFieldMethods(field, printer); 314 | } 315 | } 316 | } 317 | 318 | } // namespace nginx 319 | } // namespace compiler 320 | } // namespace protobuf 321 | } // namespace google 322 | -------------------------------------------------------------------------------- /protongx/ngx_field_util.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace google { 4 | namespace protobuf { 5 | namespace compiler { 6 | namespace nginx { 7 | 8 | std::string 9 | Generator::ExtensionSetterType(const FieldDescriptor *field, int *primitive) 10 | { 11 | std::string type; 12 | 13 | if (field->is_repeated()) { 14 | // repeated fields can be set from an array of the right type. 15 | // it is the caller's responsibility to ensure that the contents 16 | // of the array are legal for the type. 17 | type = "ngx_array_t *"; 18 | *primitive = 0; 19 | } else if (field->type() == FieldDescriptor::TYPE_MESSAGE || 20 | field->type() == FieldDescriptor::TYPE_BYTES || 21 | field->type() == FieldDescriptor::TYPE_STRING) { 22 | type = FieldRealType(field) + " *"; 23 | *primitive = 0; 24 | } else { 25 | type = FieldRealType(field); 26 | *primitive = 1; 27 | } 28 | 29 | return type; 30 | } 31 | 32 | std::string 33 | Generator::ExtensionFieldName(const FieldDescriptor *field) 34 | { 35 | std::string name; 36 | 37 | if (field->extension_scope() != NULL) { 38 | std::string package(field->containing_type()->file()->package()); 39 | 40 | name = BareRoot(field->extension_scope()->full_name()); 41 | if (!package.empty() && 42 | package == field->extension_scope()->file()->package()) { 43 | // strip the package from the name 44 | std::string prefix(BareRoot(package) + "_"); 45 | 46 | if (prefix.compare(0, prefix.length(), name) == 0) { 47 | name = name.substr(prefix.length()); 48 | } 49 | } 50 | name += "_"; 51 | } 52 | name += field->name(); 53 | 54 | return name; 55 | } 56 | 57 | std::string 58 | Generator::FieldTypeName(const FieldDescriptor *field) 59 | { 60 | std::string type; 61 | 62 | if (field->is_repeated()) { 63 | type = "ngx_array_t"; 64 | } else { 65 | type = FieldRealType(field); 66 | } 67 | 68 | return type; 69 | } 70 | 71 | std::string 72 | Generator::FieldRealType(const FieldDescriptor *field) 73 | { 74 | std::string type; 75 | 76 | switch (field->type()) { 77 | case FieldDescriptor::TYPE_BOOL: type = "ngx_flag_t"; break; 78 | case FieldDescriptor::TYPE_UINT32: 79 | case FieldDescriptor::TYPE_FIXED32: type = "uint32_t"; break; 80 | case FieldDescriptor::TYPE_INT32: 81 | case FieldDescriptor::TYPE_SINT32: 82 | case FieldDescriptor::TYPE_SFIXED32: type = "int32_t"; break; 83 | case FieldDescriptor::TYPE_UINT64: 84 | case FieldDescriptor::TYPE_FIXED64: type = "uint64_t"; break; 85 | case FieldDescriptor::TYPE_INT64: 86 | case FieldDescriptor::TYPE_SINT64: 87 | case FieldDescriptor::TYPE_SFIXED64: type = "int64_t"; break; 88 | case FieldDescriptor::TYPE_FLOAT: type = "float"; break; 89 | case FieldDescriptor::TYPE_DOUBLE: type = "double"; break; 90 | case FieldDescriptor::TYPE_STRING: 91 | case FieldDescriptor::TYPE_BYTES: type = "ngx_str_t"; break; 92 | case FieldDescriptor::TYPE_ENUM: 93 | type = EnumType(field->enum_type()->full_name()); 94 | break; 95 | case FieldDescriptor::TYPE_MESSAGE: 96 | type = StructType(field->message_type()->full_name()); 97 | break; 98 | default: 99 | type = "FIXME"; 100 | break; 101 | } 102 | 103 | return type; 104 | } 105 | 106 | std::string 107 | Generator::WireType(const FieldDescriptor *field) 108 | { 109 | std::string type("NGX_PROTOBUF_WIRETYPE_"); 110 | 111 | switch (field->type()) { 112 | case FieldDescriptor::TYPE_INT64: 113 | case FieldDescriptor::TYPE_UINT64: 114 | case FieldDescriptor::TYPE_INT32: 115 | case FieldDescriptor::TYPE_BOOL: 116 | case FieldDescriptor::TYPE_UINT32: 117 | case FieldDescriptor::TYPE_ENUM: 118 | case FieldDescriptor::TYPE_SINT32: 119 | case FieldDescriptor::TYPE_SINT64: type += "VARINT"; break; 120 | case FieldDescriptor::TYPE_DOUBLE: 121 | case FieldDescriptor::TYPE_FIXED64: 122 | case FieldDescriptor::TYPE_SFIXED64: type += "FIXED64"; break; 123 | case FieldDescriptor::TYPE_STRING: 124 | case FieldDescriptor::TYPE_MESSAGE: 125 | case FieldDescriptor::TYPE_BYTES: type += "LENGTH_DELIMITED"; break; 126 | case FieldDescriptor::TYPE_FLOAT: 127 | case FieldDescriptor::TYPE_FIXED32: 128 | case FieldDescriptor::TYPE_SFIXED32: type += "FIXED32"; break; 129 | default: type += "FIXME"; break; 130 | } 131 | 132 | return type; 133 | } 134 | 135 | std::string 136 | Generator::Label(const FieldDescriptor *field) 137 | { 138 | std::string label("NGX_PROTOBUF_LABEL_"); 139 | 140 | switch (field->label()) { 141 | case FieldDescriptor::LABEL_REQUIRED: label += "REQUIRED"; break; 142 | case FieldDescriptor::LABEL_OPTIONAL: label += "OPTIONAL"; break; 143 | case FieldDescriptor::LABEL_REPEATED: label += "REPEATED"; break; 144 | default: label += "FIXME"; break; 145 | } 146 | 147 | return label; 148 | } 149 | 150 | std::string 151 | Generator::Type(const FieldDescriptor *field) 152 | { 153 | std::string type("NGX_PROTOBUF_TYPE_"); 154 | 155 | switch (field->type()) { 156 | case FieldDescriptor::TYPE_DOUBLE: type += "DOUBLE"; break; 157 | case FieldDescriptor::TYPE_FLOAT: type += "FLOAT"; break; 158 | case FieldDescriptor::TYPE_INT64: type += "INT64"; break; 159 | case FieldDescriptor::TYPE_UINT64: type += "UINT64"; break; 160 | case FieldDescriptor::TYPE_INT32: type += "INT32"; break; 161 | case FieldDescriptor::TYPE_FIXED64: type += "FIXED64"; break; 162 | case FieldDescriptor::TYPE_FIXED32: type += "FIXED32"; break; 163 | case FieldDescriptor::TYPE_BOOL: type += "BOOL"; break; 164 | case FieldDescriptor::TYPE_STRING: type += "STRING"; break; 165 | case FieldDescriptor::TYPE_MESSAGE: type += "MESSAGE"; break; 166 | case FieldDescriptor::TYPE_BYTES: type += "BYTES"; break; 167 | case FieldDescriptor::TYPE_UINT32: type += "UINT32"; break; 168 | case FieldDescriptor::TYPE_ENUM: type += "ENUM"; break; 169 | case FieldDescriptor::TYPE_SFIXED32: type += "SFIXED32"; break; 170 | case FieldDescriptor::TYPE_SFIXED64: type += "SFIXED64"; break; 171 | case FieldDescriptor::TYPE_SINT32: type += "SINT32"; break; 172 | case FieldDescriptor::TYPE_SINT64: type += "SINT64"; break; 173 | default: type += "FIXME"; break; 174 | } 175 | 176 | return type; 177 | } 178 | 179 | bool 180 | Generator::IsFixedWidth(const FieldDescriptor *field) 181 | { 182 | bool fixed = false; 183 | 184 | switch (field->type()) { 185 | case FieldDescriptor::TYPE_FIXED32: 186 | case FieldDescriptor::TYPE_SFIXED32: 187 | case FieldDescriptor::TYPE_FLOAT: 188 | case FieldDescriptor::TYPE_FIXED64: 189 | case FieldDescriptor::TYPE_SFIXED64: 190 | case FieldDescriptor::TYPE_DOUBLE: 191 | fixed = true; 192 | break; 193 | default: 194 | break; 195 | } 196 | 197 | return fixed; 198 | } 199 | 200 | bool 201 | Generator::FieldIsPointer(const FieldDescriptor *field) 202 | { 203 | if (field->is_repeated()) { 204 | return true; 205 | } else if (field->type() == FieldDescriptor::TYPE_MESSAGE) { 206 | return true; 207 | } 208 | 209 | return false; 210 | } 211 | 212 | } // namespace nginx 213 | } // namespace compiler 214 | } // namespace protobuf 215 | } // namespace google 216 | -------------------------------------------------------------------------------- /protongx/ngx_flags.cc: -------------------------------------------------------------------------------- 1 | // -*-c++-*- 2 | 3 | #include 4 | #include 5 | 6 | namespace google { 7 | namespace protobuf { 8 | namespace compiler { 9 | namespace nginx { 10 | 11 | Flags::Flags(const Descriptor *desc) : 12 | has_required_(false), 13 | has_array_(false), 14 | has_message_(false), 15 | has_packed_(false), 16 | has_string_(false), 17 | has_bool_(false), 18 | has_float_(false), 19 | has_double_(false), 20 | has_int32_(false), 21 | has_int64_(false), 22 | has_repnm_(false) 23 | { 24 | for (int i = 0; i < desc->field_count(); ++i) { 25 | const FieldDescriptor *field = desc->field(i); 26 | 27 | if (field->is_repeated()) { 28 | has_array_ = true; 29 | if (field->type() != FieldDescriptor::TYPE_MESSAGE) { 30 | has_repnm_ = true; 31 | } 32 | } else if (field->is_required()) { 33 | has_required_ = true; 34 | } 35 | if (field->is_packable() && field->options().packed()) { 36 | has_packed_ = true; 37 | } 38 | switch (field->type()) { 39 | case FieldDescriptor::TYPE_MESSAGE: has_message_ = true; break; 40 | case FieldDescriptor::TYPE_BYTES: 41 | case FieldDescriptor::TYPE_STRING: has_string_ = true; break; 42 | case FieldDescriptor::TYPE_BOOL: has_bool_ = true; break; 43 | case FieldDescriptor::TYPE_FLOAT: has_float_ = true; break; 44 | case FieldDescriptor::TYPE_DOUBLE: has_double_ = true; break; 45 | case FieldDescriptor::TYPE_INT32: 46 | case FieldDescriptor::TYPE_SINT32: 47 | case FieldDescriptor::TYPE_SFIXED32: has_int32_ = true; break; 48 | case FieldDescriptor::TYPE_INT64: 49 | case FieldDescriptor::TYPE_SINT64: 50 | case FieldDescriptor::TYPE_SFIXED64: has_int64_ = true; break; 51 | default: 52 | break; 53 | } 54 | } 55 | } 56 | 57 | } // namespace nginx 58 | } // namespace compiler 59 | } // namespace protobuf 60 | } // namespace google 61 | -------------------------------------------------------------------------------- /protongx/ngx_flags.h: -------------------------------------------------------------------------------- 1 | // -*-c++-*- 2 | 3 | #ifndef NGX_FLAGS_H_ 4 | #define NGX_FLAGS_H_ 5 | 6 | #include 7 | 8 | namespace google { 9 | namespace protobuf { 10 | namespace compiler { 11 | namespace nginx { 12 | 13 | class Flags { 14 | public: 15 | explicit Flags(const Descriptor *desc); 16 | ~Flags() {} 17 | 18 | public: 19 | bool has_required() const { return has_required_; } 20 | bool has_array() const { return has_array_; } 21 | bool has_message() const { return has_message_; } 22 | bool has_packed() const { return has_packed_; } 23 | bool has_string() const { return has_string_; } 24 | bool has_bool() const { return has_bool_; } 25 | bool has_float() const { return has_float_; } 26 | bool has_double() const { return has_double_; } 27 | bool has_int32() const { return has_int32_; } 28 | bool has_int64() const { return has_int64_; } 29 | bool has_repnm() const { return has_repnm_; } 30 | 31 | private: 32 | bool has_required_; 33 | bool has_array_; 34 | bool has_message_; 35 | bool has_packed_; 36 | bool has_string_; 37 | bool has_bool_; 38 | bool has_float_; 39 | bool has_double_; 40 | bool has_int32_; 41 | bool has_int64_; 42 | bool has_repnm_; 43 | }; 44 | 45 | } // namespace nginx 46 | } // namespace compiler 47 | } // namespace protobuf 48 | } // namespace google 49 | 50 | #endif // NGX_FLAGS_H_ 51 | -------------------------------------------------------------------------------- /protongx/ngx_generate.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include 3 | #include 4 | 5 | namespace google { 6 | namespace protobuf { 7 | namespace compiler { 8 | namespace nginx { 9 | 10 | bool 11 | Generator::Generate(const FileDescriptor* file, 12 | const std::string& parameter, 13 | OutputDirectory* outdir, 14 | std::string* error) const 15 | { 16 | std::string root(FileRoot(file->name())); 17 | std::string dotc(root + ".c"); 18 | std::string doth(root + ".h"); 19 | std::string conf("config"); 20 | 21 | scoped_ptr source(outdir->Open(root + "/" + dotc)); 22 | scoped_ptr header(outdir->Open(root + "/" + doth)); 23 | scoped_ptr config(outdir->Open(root + "/" + conf)); 24 | 25 | io::Printer sprint(source.get(), '$'); 26 | io::Printer hprint(header.get(), '$'); 27 | io::Printer cprint(config.get(), '*'); 28 | 29 | std::map vars; 30 | 31 | vars["p"] = PACKAGE; 32 | vars["v"] = VERSION; 33 | vars["g"] = IncludeGuard(doth); 34 | vars["h"] = doth; 35 | vars["r"] = root; 36 | 37 | // the module config file 38 | 39 | cprint.Print("ngx_addon_name=*root*_module\n" 40 | "\n" 41 | "HTTP_MODULES=\"$HTTP_MODULES *root*_module\"\n" 42 | "NGX_ADDON_DEPS=\"$NGX_ADDON_DEPS $ngx_addon_dir/*root*.h\"\n" 43 | "NGX_ADDON_SRCS=\"$NGX_ADDON_SRCS $ngx_addon_dir/*root*.c\"\n", 44 | "root", root); 45 | 46 | // the header file 47 | 48 | hprint.Print(vars, 49 | "/* Generated by $p$ $v$ - DO NOT EDIT */\n" 50 | "\n" 51 | "#ifndef $g$\n" 52 | "#define $g$\n" 53 | "\n" 54 | "#include \n" 55 | "#include \n" 56 | "#include \n" 57 | "#include \n" 58 | "#include \n" 59 | "#include \n" 60 | "#include \n"); 61 | 62 | for (int i = 0; i < file->dependency_count(); ++i) { 63 | hprint.Print("#include <$droot$/$droot$.h>\n", 64 | "droot", FileRoot(file->dependency(i)->name())); 65 | } 66 | 67 | hprint.Print("\n"); 68 | 69 | for (int i = 0; i < file->enum_type_count(); ++i) { 70 | GenerateEnumDecl(file->enum_type(i), hprint); 71 | } 72 | 73 | for (int i = 0; i < file->message_type_count(); ++i) { 74 | GenerateTypedef(file->message_type(i), hprint); 75 | } 76 | 77 | for (int i = 0; i < file->message_type_count(); ++i) { 78 | GenerateMethodDecls(file->message_type(i), hprint); 79 | } 80 | 81 | if (file->extension_count() > 0) { 82 | hprint.Print("/* file-level extensions */\n"); 83 | 84 | for (int i = 0; i < file->extension_count(); ++i) { 85 | GenerateExtensionFieldDecls(file->extension(i), hprint); 86 | } 87 | hprint.Print("void $root$__export_extensions(void);\n" 88 | "\n", 89 | "root", root); 90 | } 91 | 92 | hprint.Print(vars, 93 | "#endif /* $g$ */\n"); 94 | 95 | // the module source file 96 | 97 | sprint.Print(vars, 98 | "/* Generated by $p$ $v$ - DO NOT EDIT */\n" 99 | "\n" 100 | "#include \n" 101 | "#include <$r$/$h$>\n" 102 | "\n"); 103 | 104 | for (int i = 0; i < file->message_type_count(); ++i) { 105 | GenerateDescriptors(file->message_type(i), sprint); 106 | } 107 | 108 | if (file->extension_count() > 0) { 109 | sprint.Print("/* extension field descriptors */\n" 110 | "\n"); 111 | 112 | for (int i = 0; i < file->extension_count(); ++i) { 113 | GenerateFieldDescriptor(file->extension(i), sprint); 114 | } 115 | } 116 | 117 | GenerateModule(file, sprint); 118 | 119 | for (int i = 0; i < file->message_type_count(); ++i) { 120 | GenerateMethods(file->message_type(i), sprint); 121 | } 122 | 123 | if (file->extension_count() > 0) { 124 | sprint.Print("/* file-level extensions */\n" 125 | "\n"); 126 | 127 | for (int i = 0; i < file->extension_count(); ++i) { 128 | GenerateExtensionFieldMethods(file->extension(i), sprint); 129 | } 130 | } 131 | 132 | return true; 133 | } 134 | 135 | } // namespace nginx 136 | } // namespace compiler 137 | } // namespace protobuf 138 | } // namespace google 139 | -------------------------------------------------------------------------------- /protongx/ngx_generator.h: -------------------------------------------------------------------------------- 1 | // -*-c++-*- 2 | 3 | #ifndef NGX_GENERATOR_H_ 4 | #define NGX_GENERATOR_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace google { 12 | namespace protobuf { 13 | namespace compiler { 14 | namespace nginx { 15 | 16 | class Generator : public CodeGenerator { 17 | public: 18 | Generator() {} 19 | virtual ~Generator() {} 20 | 21 | private: 22 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); 23 | 24 | public: 25 | // ngx_generate.cc 26 | virtual bool Generate(const FileDescriptor* file, 27 | const std::string& parameter, 28 | OutputDirectory* output_directory, 29 | std::string* error) const; 30 | 31 | private: 32 | // ngx_add.cc 33 | static void GenerateAdd(const Descriptor* desc, 34 | io::Printer& printer); 35 | 36 | // ngx_descriptor.cc 37 | static void GenerateFieldDescriptor(const FieldDescriptor *field, 38 | io::Printer& printer); 39 | static void GenerateDescriptors(const Descriptor *desc, 40 | io::Printer& printer); 41 | 42 | // ngx_descriptor_util.cc 43 | static bool HasUnknownFields(const Descriptor *desc); 44 | static bool HasExtensionFields(const Descriptor *desc); 45 | 46 | // ngx_extension.cc 47 | static void GenerateExtendeeDecls(const Descriptor *desc, 48 | io::Printer& printer); 49 | static void GenerateExtendeeMethods(const Descriptor *desc, 50 | io::Printer& printer); 51 | static void GenerateExtensionFieldDecls(const FieldDescriptor *field, 52 | io::Printer& printer); 53 | static void GenerateExtensionFieldMethods(const FieldDescriptor *field, 54 | io::Printer& printer); 55 | static void GenerateExtensionMethods(const Descriptor *desc, 56 | io::Printer& printer); 57 | 58 | // ngx_field_util.cc 59 | static std::string ExtensionSetterType(const FieldDescriptor *field, 60 | int *primitive); 61 | static std::string ExtensionFieldName(const FieldDescriptor *field); 62 | static std::string FieldTypeName(const FieldDescriptor *field); 63 | static std::string FieldRealType(const FieldDescriptor *field); 64 | static std::string WireType(const FieldDescriptor *field); 65 | static std::string Label(const FieldDescriptor *field); 66 | static std::string Type(const FieldDescriptor *field); 67 | static bool IsFixedWidth(const FieldDescriptor *field); 68 | static bool FieldIsPointer(const FieldDescriptor *field); 69 | 70 | // ngx_is_initialized.cc 71 | static void GenerateIsInitialized(const Descriptor *desc, 72 | io::Printer& printer); 73 | 74 | // ngx_methods.cc 75 | static void GenerateMethodDecls(const Descriptor* desc, 76 | io::Printer& printer); 77 | static void GenerateMethods(const Descriptor* desc, 78 | io::Printer& printer); 79 | 80 | // ngx_module.cc 81 | static void GenerateRegisterExtension(const FieldDescriptor *extension, 82 | io::Printer& printer); 83 | static void GenerateRegisterMessageExtensions(const Descriptor* desc, 84 | io::Printer& printer); 85 | static int CountMessageExtensions(const Descriptor *desc); 86 | static int CountExtensions(const FileDescriptor *file); 87 | static void GenerateModule(const FileDescriptor *file, 88 | io::Printer& printer); 89 | 90 | // ngx_name.cc 91 | static std::string FileRoot(const std::string& input); 92 | static std::string IncludeGuard(const std::string& input); 93 | static std::string BareRoot(const std::string& input); 94 | static std::string TypedefRoot(const std::string& input); 95 | static std::string EnumType(const std::string& input); 96 | static std::string EnumValue(const std::string& input); 97 | static std::string StructType(const std::string& input); 98 | 99 | // ngx_pack.cc 100 | static void GeneratePackField(const FieldDescriptor *field, 101 | io::Printer& printer); 102 | static void GeneratePackRange(const Descriptor::ExtensionRange *range, 103 | io::Printer& printer); 104 | static void GeneratePackUnknown(const Descriptor *desc, 105 | io::Printer& printer); 106 | static void GeneratePack(const Descriptor* desc, io::Printer& printer); 107 | 108 | // ngx_print.cc 109 | static void Indented(io::Printer& printer, 110 | const std::map& vars, 111 | const char *body); 112 | static void OpenBrace(io::Printer& printer); 113 | static void CloseBrace(io::Printer& printer); 114 | static void SimpleIf(io::Printer& printer, 115 | const std::map& vars, 116 | const char *cond); 117 | static void CuddledIf(io::Printer& printer, 118 | const std::map& vars, 119 | const char *cond1, 120 | const char *cond2); 121 | static void FullSimpleIf(io::Printer& printer, 122 | const std::map& vars, 123 | const char *cond, 124 | const char *body); 125 | static void FullCuddledIf(io::Printer& printer, 126 | const std::map& vars, 127 | const char *cond1, 128 | const char *cond2, 129 | const char *body); 130 | 131 | static void Else(io::Printer& printer); 132 | static void SkipUnknown(io::Printer& printer); 133 | static void BracedReturn(io::Printer& printer, 134 | const char *value); 135 | static std::string Spaces(int count); 136 | static std::string Number(int number); 137 | static void Indent(io::Printer& printer); 138 | static void Outdent(io::Printer& printer); 139 | 140 | // ngx_size.cc 141 | static void GenerateSize(const Descriptor* desc, 142 | io::Printer& printer); 143 | 144 | // ngx_typedef.cc 145 | static void GenerateEnumDecl(const EnumDescriptor* desc, 146 | io::Printer& printer); 147 | static void GenerateTypedef(const Descriptor* desc, 148 | io::Printer& printer); 149 | 150 | // ngx_unpack.cc 151 | static void GenerateUnpackUnknown(const Descriptor *desc, 152 | io::Printer& printer); 153 | static void GenerateUnpack(const Descriptor* desc, 154 | io::Printer& printer); 155 | }; 156 | 157 | } // namespace nginx 158 | } // namespace compiler 159 | } // namespace protobuf 160 | } // namespace google 161 | 162 | #endif // NGX_GENERATOR_H_ 163 | -------------------------------------------------------------------------------- /protongx/ngx_is_initialized.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | void 10 | Generator::GenerateIsInitialized(const Descriptor *desc, io::Printer& printer) 11 | { 12 | Flags flags(desc); 13 | 14 | std::map vars; 15 | 16 | vars["name"] = desc->full_name(); 17 | vars["root"] = TypedefRoot(desc->full_name()); 18 | vars["type"] = StructType(desc->full_name()); 19 | 20 | printer.Print(vars, 21 | "ngx_int_t\n" 22 | "$root$__is_initialized(\n" 23 | " $type$ *obj)\n"); 24 | OpenBrace(printer); 25 | 26 | if (flags.has_required()) { 27 | int rcnt = 0; 28 | 29 | printer.Print("return ("); 30 | for (int i = 0; i < desc->field_count(); ++i) { 31 | const FieldDescriptor *field = desc->field(i); 32 | 33 | if (field->is_required()) { 34 | vars["fname"] = field->name(); 35 | 36 | if (rcnt++ > 0) { 37 | printer.Print("\n && "); 38 | } 39 | printer.Print(vars, "$root$__has_$fname$(obj)"); 40 | } 41 | } 42 | printer.Print(");\n"); 43 | } else { 44 | printer.Print("return 1; /* no required fields */\n"); 45 | } 46 | 47 | CloseBrace(printer); 48 | printer.Print("\n"); 49 | } 50 | 51 | 52 | } // namespace nginx 53 | } // namespace compiler 54 | } // namespace protobuf 55 | } // namespace google 56 | -------------------------------------------------------------------------------- /protongx/ngx_main.cc: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int 7 | main (int argc, char **argv) 8 | { 9 | google::protobuf::compiler::CommandLineInterface cli; 10 | google::protobuf::compiler::nginx::Generator gen; 11 | 12 | cli.RegisterGenerator("--out", &gen, "Generate nginx source files."); 13 | cli.SetVersionInfo(PACKAGE " " VERSION); 14 | 15 | return cli.Run(argc, argv); 16 | } 17 | -------------------------------------------------------------------------------- /protongx/ngx_methods.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | void 10 | Generator::GenerateMethodDecls(const Descriptor *desc, io::Printer& printer) 11 | { 12 | for (int i = 0; i < desc->nested_type_count(); ++i) { 13 | GenerateMethodDecls(desc->nested_type(i), printer); 14 | } 15 | 16 | std::map vars; 17 | 18 | vars["name"] = desc->full_name(); 19 | vars["root"] = TypedefRoot(desc->full_name()); 20 | vars["type"] = StructType(desc->full_name()); 21 | 22 | printer.Print(vars, 23 | "/* $name$ field methods */\n" 24 | "\n"); 25 | 26 | for (int i = 0; i < desc->field_count(); ++i) { 27 | const FieldDescriptor *field = desc->field(i); 28 | 29 | vars["field"] = FieldRealType(field); 30 | vars["fname"] = field->name(); 31 | 32 | // set 33 | 34 | if (field->is_repeated() || 35 | field->type() == FieldDescriptor::TYPE_MESSAGE) { 36 | printer.Print(vars, 37 | "#define $root$__set_$fname$(obj, val) \\\n" 38 | " NGX_PROTOBUF_SET_MEMBER(obj, $fname$, val)\n" 39 | "\n"); 40 | } else if (field->type() == FieldDescriptor::TYPE_BYTES || 41 | field->type() == FieldDescriptor::TYPE_STRING) { 42 | printer.Print(vars, 43 | "#define $root$__set_$fname$(obj, val) \\\n" 44 | " NGX_PROTOBUF_SET_STRING(obj, $fname$, val)\n" 45 | "\n"); 46 | } else { 47 | printer.Print(vars, 48 | "#define $root$__set_$fname$(obj, val) \\\n" 49 | " NGX_PROTOBUF_SET_NUMBER(obj, $fname$, val)\n" 50 | "\n"); 51 | } 52 | 53 | // add (if repeated) 54 | 55 | if (field->is_repeated()) { 56 | printer.Print(vars, 57 | "$field$ *\n" 58 | "$root$__add__$fname$(\n" 59 | " $type$ *obj,\n" 60 | " ngx_pool_t *pool);\n" 61 | "\n"); 62 | } 63 | 64 | // clear 65 | 66 | if (field->is_repeated() || 67 | field->type() == FieldDescriptor::TYPE_MESSAGE) { 68 | printer.Print(vars, 69 | "#define $root$__clear_$fname$(obj) \\\n" 70 | " NGX_PROTOBUF_CLEAR_MEMBER(obj, $fname$)\n" 71 | "\n"); 72 | } else if (field->type() == FieldDescriptor::TYPE_BYTES || 73 | field->type() == FieldDescriptor::TYPE_STRING) { 74 | printer.Print(vars, 75 | "#define $root$__clear_$fname$(obj) \\\n" 76 | " NGX_PROTOBUF_CLEAR_STRING(obj, $fname$)\n" 77 | "\n"); 78 | } else { 79 | printer.Print(vars, 80 | "#define $root$__clear_$fname$(obj) \\\n" 81 | " NGX_PROTOBUF_CLEAR_NUMBER(obj, $fname$)\n" 82 | "\n"); 83 | } 84 | 85 | // has 86 | 87 | if (field->is_repeated()) { 88 | printer.Print(vars, 89 | "#define $root$__has_$fname$(obj) \\\n" 90 | " (NGX_PROTOBUF_HAS_FIELD(obj, $fname$) && \\\n" 91 | " (obj)->$fname$->nelts > 0)\n" 92 | "\n"); 93 | } else { 94 | printer.Print(vars, 95 | "#define $root$__has_$fname$(obj) \\\n" 96 | " (NGX_PROTOBUF_HAS_FIELD(obj, $fname$))\n" 97 | "\n"); 98 | } 99 | } 100 | 101 | printer.Print(vars, 102 | "/* $name$ message methods */\n" 103 | "\n" 104 | "#define $root$__alloc(pool) \\\n" 105 | " ngx_pcalloc(pool, \\\n" 106 | " sizeof($type$))\n" 107 | "\n" 108 | "#define $root$__clear(obj) \\\n" 109 | " ngx_memzero(obj, sizeof($type$))\n" 110 | "\n" 111 | "ngx_int_t $root$__is_initialized(\n" 112 | " $type$ *obj);\n" 113 | "\n" 114 | "ngx_int_t $root$__unpack(\n" 115 | " $type$ *obj,\n" 116 | " ngx_protobuf_context_t *ctx);\n" 117 | "\n" 118 | "size_t $root$__size(\n" 119 | " $type$ *obj);\n" 120 | "\n" 121 | "ngx_int_t $root$__pack(\n" 122 | " $type$ *obj,\n" 123 | " ngx_protobuf_context_t *ctx);\n" 124 | "\n"); 125 | 126 | if (desc->extension_range_count() > 0) { 127 | GenerateExtendeeDecls(desc, printer); 128 | } 129 | } 130 | 131 | void 132 | Generator::GenerateMethods(const Descriptor* desc, io::Printer& printer) 133 | { 134 | for (int i = 0; i < desc->nested_type_count(); ++i) { 135 | GenerateMethods(desc->nested_type(i), printer); 136 | } 137 | 138 | // field-level methods for the message 139 | 140 | GenerateAdd(desc, printer); 141 | 142 | if (desc->extension_range_count() > 0) { 143 | std::string root(TypedefRoot(desc->full_name())); 144 | 145 | printer.Print("/* extension registry for $name$ */\n" 146 | "\n" 147 | "static ngx_rbtree_t *$root$__extensions = NULL;\n" 148 | "\n", "name", desc->full_name(), "root", root); 149 | } 150 | 151 | // message-level methods 152 | 153 | printer.Print("/* $name$ message methods */\n" 154 | "\n", "name", desc->full_name()); 155 | 156 | GenerateIsInitialized(desc, printer); 157 | GenerateUnpack(desc, printer); 158 | GenerateSize(desc, printer); 159 | GeneratePack(desc, printer); 160 | 161 | if (desc->extension_range_count() > 0) { 162 | printer.Print("/* $name$ extendee methods */\n" 163 | "\n", "name", desc->full_name()); 164 | 165 | GenerateExtendeeMethods(desc, printer); 166 | } 167 | 168 | if (HasExtensionFields(desc)) { 169 | printer.Print("/* $name$ extension field methods */\n" 170 | "\n", "name", desc->full_name()); 171 | 172 | GenerateExtensionMethods(desc, printer); 173 | } 174 | } 175 | 176 | } // namespace nginx 177 | } // namespace compiler 178 | } // namespace protobuf 179 | } // namespace google 180 | -------------------------------------------------------------------------------- /protongx/ngx_module.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace google { 4 | namespace protobuf { 5 | namespace compiler { 6 | namespace nginx { 7 | 8 | void 9 | Generator::GenerateRegisterExtension(const FieldDescriptor *extension, 10 | io::Printer& printer) 11 | { 12 | std::string type(TypedefRoot(extension->containing_type()->full_name())); 13 | std::string name(ExtensionFieldName(extension)); 14 | 15 | printer.Print("if ($type$__import_extension(\n", "type", type); 16 | Indent(printer); 17 | printer.Print("&$type$_$name$, cycle) != NGX_OK) {\n", 18 | "type", type, "name", name); 19 | printer.Print("return NGX_ERROR;\n"); 20 | CloseBrace(printer); 21 | } 22 | 23 | void 24 | Generator::GenerateRegisterMessageExtensions(const Descriptor* desc, 25 | io::Printer& printer) 26 | { 27 | for (int i = 0; i < desc->nested_type_count(); ++i) { 28 | GenerateRegisterMessageExtensions(desc->nested_type(i), printer); 29 | } 30 | 31 | for (int i = 0; i < desc->extension_count(); ++i) { 32 | GenerateRegisterExtension(desc->extension(i), printer); 33 | } 34 | } 35 | 36 | int 37 | Generator::CountMessageExtensions(const Descriptor *desc) 38 | { 39 | int count = 0; 40 | 41 | for (int i = 0; i < desc->nested_type_count(); ++i) { 42 | count += CountMessageExtensions(desc->nested_type(i)); 43 | } 44 | 45 | return count + desc->extension_count(); 46 | } 47 | 48 | int 49 | Generator::CountExtensions(const FileDescriptor *file) 50 | { 51 | int count = 0; 52 | 53 | for (int i = 0; i < file->message_type_count(); ++i) { 54 | count += CountMessageExtensions(file->message_type(i)); 55 | } 56 | 57 | return count + file->extension_count(); 58 | } 59 | 60 | void 61 | Generator::GenerateModule(const FileDescriptor *file, io::Printer& printer) 62 | { 63 | std::string root(FileRoot(file->name())); 64 | int ecount = CountExtensions(file); 65 | 66 | if (ecount > 0) { 67 | printer.Print("static ngx_int_t\n" 68 | "$root$__register_extensions(ngx_cycle_t *cycle)\n" 69 | "{\n", 70 | "root", root); 71 | Indent(printer); 72 | 73 | for (int i = 0; i < file->message_type_count(); ++i) { 74 | GenerateRegisterMessageExtensions(file->message_type(i), printer); 75 | } 76 | 77 | for (int i = 0; i < file->extension_count(); ++i) { 78 | GenerateRegisterExtension(file->extension(i), printer); 79 | } 80 | 81 | printer.Print("\n" 82 | "return NGX_OK;\n"); 83 | Outdent(printer); 84 | printer.Print("}\n" 85 | "\n"); 86 | 87 | printer.Print("static ngx_protobuf_module_t\n" 88 | "$root$_module_ctx = {\n", 89 | "root", root); 90 | Indent(printer); 91 | printer.Print("$root$__register_extensions\n", 92 | "root", root); 93 | Outdent(printer); 94 | printer.Print("};\n" 95 | "\n"); 96 | } else { 97 | printer.Print("static ngx_protobuf_module_t\n" 98 | "$root$_module_ctx = {\n", 99 | "root", root); 100 | Indent(printer); 101 | printer.Print("NULL\n"); 102 | Outdent(printer); 103 | printer.Print("};\n" 104 | "\n"); 105 | } 106 | 107 | printer.Print("ngx_module_t $root$_module = {\n", 108 | "root", root); 109 | Indent(printer); 110 | printer.Print("NGX_MODULE_V1,\n" 111 | "&$root$_module_ctx,\n" 112 | "NULL,\n" 113 | "NGX_PROTOBUF_MODULE,\n" 114 | "NULL,\n" 115 | "NULL,\n" 116 | "NULL,\n" 117 | "NULL,\n" 118 | "NULL,\n" 119 | "NULL,\n" 120 | "NULL,\n" 121 | "NGX_MODULE_V1_PADDING\n", 122 | "root", root); 123 | Outdent(printer); 124 | printer.Print("};\n" 125 | "\n"); 126 | } 127 | 128 | } // namespace nginx 129 | } // namespace compiler 130 | } // namespace protobuf 131 | } // namespace google 132 | -------------------------------------------------------------------------------- /protongx/ngx_name.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace google { 4 | namespace protobuf { 5 | namespace compiler { 6 | namespace nginx { 7 | 8 | std::string 9 | Generator::FileRoot(const std::string& input) 10 | { 11 | std::string output; 12 | std::string::const_iterator i; 13 | 14 | output = "ngx_"; 15 | for (i = input.begin(); i != input.end(); ++i) { 16 | char c = *i; 17 | 18 | if (isalnum(c)) { 19 | output += c; 20 | } else { 21 | output += '_'; 22 | } 23 | } 24 | 25 | return output; 26 | } 27 | 28 | std::string 29 | Generator::IncludeGuard(const std::string& input) 30 | { 31 | std::string output; 32 | std::string::const_iterator i; 33 | 34 | output = "_"; 35 | for (i = input.begin(); i != input.end(); ++i) { 36 | char c = *i; 37 | 38 | if (isalnum(c)) { 39 | output += toupper(c); 40 | } else { 41 | output += '_'; 42 | } 43 | } 44 | output += "_INCLUDED_"; 45 | 46 | return output; 47 | } 48 | 49 | std::string 50 | Generator::BareRoot(const std::string& input) 51 | { 52 | std::string output; 53 | std::string::const_iterator i; 54 | bool lower = false; 55 | 56 | for (i = input.begin(); i != input.end(); ++i) { 57 | char c = *i; 58 | 59 | if (islower(c)) { 60 | lower = true; 61 | } else { 62 | if (lower && c != '.') { 63 | output += '_'; 64 | } 65 | lower = false; 66 | } 67 | if (isalnum(c)) { 68 | output += tolower(c); 69 | } else { 70 | output += '_'; 71 | } 72 | } 73 | 74 | return output; 75 | } 76 | 77 | std::string 78 | Generator::TypedefRoot(const std::string& input) 79 | { 80 | return "ngx_" + BareRoot(input); 81 | } 82 | 83 | std::string 84 | Generator::EnumType(const std::string& input) 85 | { 86 | return TypedefRoot(input) + "_e"; 87 | } 88 | 89 | std::string 90 | Generator::EnumValue(const std::string& input) 91 | { 92 | std::string output; 93 | std::string::const_iterator i; 94 | 95 | output = "NGX_"; 96 | for (i = input.begin(); i != input.end(); ++i) { 97 | char c = *i; 98 | 99 | if (isalnum(c)) { 100 | output += toupper(c); 101 | } else { 102 | output += '_'; 103 | } 104 | } 105 | 106 | return output; 107 | } 108 | 109 | std::string 110 | Generator::StructType(const std::string& input) 111 | { 112 | return TypedefRoot(input) + "_t"; 113 | } 114 | 115 | } // namespace nginx 116 | } // namespace compiler 117 | } // namespace protobuf 118 | } // namespace google 119 | -------------------------------------------------------------------------------- /protongx/ngx_pack.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace google { 8 | namespace protobuf { 9 | namespace compiler { 10 | namespace nginx { 11 | 12 | struct ExtensionRangeSorter { 13 | bool operator()(const Descriptor::ExtensionRange *left, 14 | const Descriptor::ExtensionRange *right) const 15 | { 16 | return (left->start < right->start); 17 | } 18 | }; 19 | 20 | struct FieldDescriptorSorter { 21 | bool operator()(const FieldDescriptor *left, 22 | const FieldDescriptor *right) const 23 | { 24 | return (left->number() < right->number()); 25 | } 26 | }; 27 | 28 | void 29 | Generator::GeneratePackField(const FieldDescriptor *field, 30 | io::Printer& printer) 31 | { 32 | std::map vars; 33 | 34 | vars["fname"] = field->name(); 35 | vars["ftype"] = FieldRealType(field); 36 | vars["fnum"] = Number(field->number()); 37 | 38 | if (field->is_repeated()) { 39 | CuddledIf(printer, vars, 40 | "obj->__has_$fname$", 41 | "&& obj->$fname$ != NULL\n" 42 | "&& obj->$fname$->nelts > 0"); 43 | } else if (field->type() == FieldDescriptor::TYPE_MESSAGE) { 44 | CuddledIf(printer, vars, 45 | "obj->__has_$fname$", 46 | "&& obj->$fname$ != NULL"); 47 | } else { 48 | SimpleIf(printer, vars, "obj->__has_$fname$"); 49 | } 50 | 51 | if (field->is_repeated()) { 52 | printer.Print(vars, 53 | "$ftype$ *vals = obj->$fname$->elts;\n" 54 | "ngx_uint_t i;\n" 55 | "\n"); 56 | 57 | if (field->is_packable() && field->options().packed()) { 58 | vars["root"] = TypedefRoot(field->containing_type()->full_name()); 59 | printer.Print(vars, 60 | "n = $root$_$fname$__packed_size(obj->$fname$);\n" 61 | "ctx->buffer.pos = ngx_protobuf_write_message_header(\n" 62 | " ctx->buffer.pos, n, $fnum$);\n" 63 | "\n"); 64 | } 65 | 66 | printer.Print(vars, 67 | "for (i = 0; i < obj->$fname$->nelts; ++i) {\n"); 68 | Indent(printer); 69 | switch (field->type()) { 70 | case FieldDescriptor::TYPE_MESSAGE: 71 | vars["froot"] = TypedefRoot(field->message_type()->full_name()); 72 | printer.Print(vars, 73 | "n = $froot$__size(vals + i);\n" 74 | "ctx->buffer.pos = ngx_protobuf_write_message_header(\n" 75 | " ctx->buffer.pos, n, $fnum$);\n" 76 | "$froot$__pack(vals + i, ctx);\n"); 77 | break; 78 | case FieldDescriptor::TYPE_BYTES: 79 | case FieldDescriptor::TYPE_STRING: 80 | printer.Print(vars, 81 | "ctx->buffer.pos = ngx_protobuf_write_string_field(\n" 82 | " ctx->buffer.pos, vals + i, $fnum$);\n"); 83 | break; 84 | case FieldDescriptor::TYPE_BOOL: 85 | printer.Print(vars, 86 | "ctx->buffer.pos = ngx_protobuf_write_uint32_field(\n" 87 | " ctx->buffer.pos, (vals[i] != 0), $fnum$);\n"); 88 | break; 89 | case FieldDescriptor::TYPE_ENUM: 90 | case FieldDescriptor::TYPE_UINT32: 91 | case FieldDescriptor::TYPE_INT32: 92 | printer.Print(vars, 93 | "ctx->buffer.pos = ngx_protobuf_write_uint32_field(\n" 94 | " ctx->buffer.pos, vals[i], $fnum$);\n"); 95 | break; 96 | case FieldDescriptor::TYPE_SINT32: 97 | printer.Print(vars, 98 | "ctx->buffer.pos = ngx_protobuf_write_uint32_field(\n" 99 | " ctx->buffer.pos, " 100 | "NGX_PROTOBUF_Z32_ENCODE(vals[i]), $fnum$);\n"); 101 | break; 102 | case FieldDescriptor::TYPE_UINT64: 103 | case FieldDescriptor::TYPE_INT64: 104 | printer.Print(vars, 105 | "ctx->buffer.pos = ngx_protobuf_write_uint64_field(\n" 106 | " ctx->buffer.pos, vals[i], $fnum$);\n"); 107 | break; 108 | case FieldDescriptor::TYPE_SINT64: 109 | printer.Print(vars, 110 | "ctx->buffer.pos = ngx_protobuf_write_uint64_field(\n" 111 | " ctx->buffer.pos, " 112 | "NGX_PROTOBUF_Z64_ENCODE(vals[i]), $fnum$);\n"); 113 | break; 114 | case FieldDescriptor::TYPE_FIXED32: 115 | case FieldDescriptor::TYPE_SFIXED32: 116 | printer.Print(vars, 117 | "ctx->buffer.pos = ngx_protobuf_write_fixed32_field(\n" 118 | " ctx->buffer.pos, vals[i], $fnum$);\n"); 119 | break; 120 | case FieldDescriptor::TYPE_FLOAT: 121 | printer.Print(vars, 122 | "ctx->buffer.pos = ngx_protobuf_write_float_field(\n" 123 | " ctx->buffer.pos, vals[i], $fnum$);\n"); 124 | break; 125 | case FieldDescriptor::TYPE_FIXED64: 126 | case FieldDescriptor::TYPE_SFIXED64: 127 | printer.Print(vars, 128 | "ctx->buffer.pos = ngx_protobuf_write_fixed64_field(\n" 129 | " ctx->buffer.pos, vals[i], $fnum$);\n"); 130 | break; 131 | case FieldDescriptor::TYPE_DOUBLE: 132 | printer.Print(vars, 133 | "ctx->buffer.pos = ngx_protobuf_write_double_field(\n" 134 | " ctx->buffer.pos, vals[i], $fnum$);\n"); 135 | break; 136 | default: 137 | printer.Print(vars, 138 | "/* pack repeated $ftype$ */\n" 139 | "ctx->buffer.pos = FIXME;\n"); 140 | break; 141 | } 142 | Outdent(printer); 143 | printer.Print("}\n"); 144 | } else { 145 | switch (field->type()) { 146 | case FieldDescriptor::TYPE_MESSAGE: 147 | vars["froot"] = TypedefRoot(field->message_type()->full_name()); 148 | printer.Print(vars, 149 | "n = $froot$__size(obj->$fname$);\n" 150 | "ctx->buffer.pos = ngx_protobuf_write_message_header(\n" 151 | " ctx->buffer.pos, n, $fnum$);\n" 152 | "$froot$__pack(obj->$fname$, ctx);\n"); 153 | break; 154 | case FieldDescriptor::TYPE_BYTES: 155 | case FieldDescriptor::TYPE_STRING: 156 | printer.Print(vars, 157 | "ctx->buffer.pos = ngx_protobuf_write_string_field(\n" 158 | " ctx->buffer.pos,\n" 159 | " &obj->$fname$,\n" 160 | " $fnum$);\n"); 161 | break; 162 | case FieldDescriptor::TYPE_BOOL: 163 | printer.Print(vars, 164 | "ctx->buffer.pos = ngx_protobuf_write_uint32_field(\n" 165 | " ctx->buffer.pos,\n" 166 | " (obj->$fname$ != 0),\n" 167 | " $fnum$);\n"); 168 | break; 169 | case FieldDescriptor::TYPE_ENUM: 170 | case FieldDescriptor::TYPE_UINT32: 171 | case FieldDescriptor::TYPE_INT32: 172 | printer.Print(vars, 173 | "ctx->buffer.pos = ngx_protobuf_write_uint32_field(\n" 174 | " ctx->buffer.pos,\n" 175 | " obj->$fname$,\n" 176 | " $fnum$);\n"); 177 | break; 178 | case FieldDescriptor::TYPE_SINT32: 179 | printer.Print(vars, 180 | "ctx->buffer.pos = ngx_protobuf_write_uint32_field(\n" 181 | " ctx->buffer.pos,\n" 182 | " NGX_PROTOBUF_Z32_ENCODE(obj->$fname$),\n" 183 | " $fnum$);\n"); 184 | break; 185 | case FieldDescriptor::TYPE_UINT64: 186 | case FieldDescriptor::TYPE_INT64: 187 | printer.Print(vars, 188 | "ctx->buffer.pos = ngx_protobuf_write_uint64_field(\n" 189 | " ctx->buffer.pos,\n" 190 | " obj->$fname$,\n" 191 | " $fnum$);\n"); 192 | break; 193 | case FieldDescriptor::TYPE_SINT64: 194 | printer.Print(vars, 195 | "ctx->buffer.pos = ngx_protobuf_write_uint64_field(\n" 196 | " ctx->buffer.pos,\n" 197 | " NGX_PROTOBUF_Z64_ENCODE(obj->$fname$),\n" 198 | " $fnum$);\n"); 199 | break; 200 | case FieldDescriptor::TYPE_FIXED32: 201 | case FieldDescriptor::TYPE_SFIXED32: 202 | printer.Print(vars, 203 | "ctx->buffer.pos = ngx_protobuf_write_fixed32_field(\n" 204 | " ctx->buffer.pos,\n" 205 | " obj->$fname$,\n" 206 | " $fnum$);\n"); 207 | break; 208 | case FieldDescriptor::TYPE_FLOAT: 209 | printer.Print(vars, 210 | "ctx->buffer.pos = ngx_protobuf_write_float_field(\n" 211 | " ctx->buffer.pos,\n" 212 | " obj->$fname$,\n" 213 | " $fnum$);\n"); 214 | break; 215 | case FieldDescriptor::TYPE_FIXED64: 216 | case FieldDescriptor::TYPE_SFIXED64: 217 | printer.Print(vars, 218 | "ctx->buffer.pos = ngx_protobuf_write_fixed64_field(\n" 219 | " ctx->buffer.pos,\n" 220 | " obj->$fname$,\n" 221 | " $fnum$);\n"); 222 | break; 223 | case FieldDescriptor::TYPE_DOUBLE: 224 | printer.Print(vars, 225 | "ctx->buffer.pos = ngx_protobuf_write_double_field(\n" 226 | " ctx->buffer.pos,\n" 227 | " obj->$fname$,\n" 228 | " $fnum$);\n"); 229 | break; 230 | default: 231 | printer.Print(vars, 232 | "ctx->buffer.pos = FIXME; /* pack $ftype$ */\n"); 233 | break; 234 | } 235 | } 236 | 237 | Outdent(printer); 238 | printer.Print("}\n"); 239 | } 240 | 241 | void 242 | Generator::GeneratePackRange(const Descriptor::ExtensionRange *range, 243 | io::Printer& printer) 244 | { 245 | std::map vars; 246 | 247 | vars["lower"] = Number(range->start); 248 | vars["upper"] = Number(range->end); 249 | 250 | SimpleIf(printer, vars, "obj->__extensions != NULL"); 251 | printer.Print(vars, 252 | "rc = ngx_protobuf_pack_extensions(obj->__extensions,\n" 253 | " $lower$, $upper$, ctx);\n"); 254 | FullSimpleIf(printer, vars, "rc != NGX_OK", "return rc;"); 255 | CloseBrace(printer); 256 | } 257 | 258 | void 259 | Generator::GeneratePackUnknown(const Descriptor *desc, io::Printer& printer) 260 | { 261 | printer.Print("\n" 262 | "if (obj->__unknown != NULL\n" 263 | " && obj->__unknown->elts != NULL\n" 264 | " && obj->__unknown->nelts > 0)\n"); 265 | OpenBrace(printer); 266 | printer.Print("ngx_protobuf_unknown_field_t *unk = obj->__unknown->elts;\n" 267 | "ngx_uint_t i;\n" 268 | "\n" 269 | "for (i = 0; i < obj->__unknown->nelts; ++i) "); 270 | OpenBrace(printer); 271 | printer.Print("rc = ngx_protobuf_pack_unknown_field(unk + i, ctx);\n" 272 | "if (rc != NGX_OK) "); 273 | OpenBrace(printer); 274 | printer.Print("return rc;\n"); 275 | CloseBrace(printer); 276 | CloseBrace(printer); 277 | CloseBrace(printer); 278 | } 279 | 280 | void 281 | Generator::GeneratePack(const Descriptor* desc, io::Printer& printer) 282 | { 283 | std::map vars; 284 | 285 | vars["name"] = desc->full_name(); 286 | vars["root"] = TypedefRoot(desc->full_name()); 287 | vars["type"] = StructType(desc->full_name()); 288 | 289 | printer.Print(vars, 290 | "ngx_int_t\n" 291 | "$root$__pack(\n" 292 | " $type$ *obj,\n" 293 | " ngx_protobuf_context_t *ctx)\n" 294 | "{\n"); 295 | Indent(printer); 296 | 297 | printer.Print(vars, 298 | "size_t size = $root$__size(obj);\n"); 299 | 300 | Flags flags(desc); 301 | 302 | if (flags.has_message() || flags.has_packed()) { 303 | printer.Print("size_t n;\n"); 304 | } 305 | 306 | if (desc->extension_range_count() > 0 || HasUnknownFields(desc)) { 307 | printer.Print("ngx_int_t rc;\n"); 308 | } 309 | 310 | printer.Print("\n"); 311 | FullSimpleIf(printer, vars, "size == 0", "return NGX_OK;"); 312 | printer.Print("\n"); 313 | FullSimpleIf(printer, vars, 314 | "ctx->buffer.pos + size > ctx->buffer.last", 315 | "return NGX_ABORT;"); 316 | printer.Print("\n"); 317 | 318 | // fields and extension ranges may be declared in any order, 319 | // but we should serialize in canonical order 320 | 321 | std::vector extensions; 322 | std::vector fields; 323 | 324 | for (int i = 0; i < desc->field_count(); ++i) { 325 | fields.push_back(desc->field(i)); 326 | } 327 | 328 | for (int i = 0; i < desc->extension_range_count(); ++i) { 329 | extensions.push_back(desc->extension_range(i)); 330 | } 331 | 332 | std::sort(extensions.begin(), extensions.end(), ExtensionRangeSorter()); 333 | std::sort(fields.begin(), fields.end(), FieldDescriptorSorter()); 334 | 335 | std::vector::const_iterator ei; 336 | std::vector::const_iterator fi; 337 | 338 | ei = extensions.begin(); 339 | fi = fields.begin(); 340 | 341 | while (ei != extensions.end() || fi != fields.end()) { 342 | if (ei == extensions.end()) { 343 | GeneratePackField(*fi++, printer); 344 | } else if (fi == fields.end()) { 345 | GeneratePackRange(*ei++, printer); 346 | } else if ((*fi)->number() < (*ei)->start) { 347 | GeneratePackField(*fi++, printer); 348 | } else { 349 | GeneratePackRange(*ei++, printer); 350 | } 351 | } 352 | 353 | if (HasUnknownFields(desc)) { 354 | GeneratePackUnknown(desc, printer); 355 | } 356 | 357 | printer.Print("\n" 358 | "return NGX_OK;\n"); 359 | 360 | CloseBrace(printer); 361 | 362 | printer.Print("\n"); 363 | } 364 | 365 | } // namespace nginx 366 | } // namespace compiler 367 | } // namespace protobuf 368 | } // namespace google 369 | -------------------------------------------------------------------------------- /protongx/ngx_print.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | void 10 | Generator::Indented(io::Printer& printer, 11 | const std::map& vars, 12 | const char *body) 13 | { 14 | Indent(printer); 15 | printer.Print(vars, body); 16 | Outdent(printer); 17 | } 18 | 19 | void 20 | Generator::OpenBrace(io::Printer& printer) 21 | { 22 | printer.Print("{\n"); 23 | Indent(printer); 24 | } 25 | 26 | void 27 | Generator::CloseBrace(io::Printer& printer) 28 | { 29 | Outdent(printer); 30 | printer.Print("}\n"); 31 | } 32 | 33 | void 34 | Generator::SimpleIf(io::Printer& printer, 35 | const std::map& vars, 36 | const char *cond) 37 | { 38 | printer.Print("if ("); 39 | printer.Print(vars, cond); 40 | printer.Print(") "); 41 | OpenBrace(printer); 42 | } 43 | 44 | void 45 | Generator::CuddledIf(io::Printer& printer, 46 | const std::map& vars, 47 | const char *cond1, 48 | const char *cond2) 49 | { 50 | printer.Print("if ("); 51 | printer.Print(vars, cond1); 52 | printer.Print("\n"); 53 | Indent(printer); 54 | printer.Print(vars, cond2); 55 | printer.Print(")\n"); 56 | Outdent(printer); 57 | OpenBrace(printer); 58 | } 59 | 60 | void 61 | Generator::FullSimpleIf(io::Printer& printer, 62 | const std::map& vars, 63 | const char *cond, 64 | const char *body) 65 | { 66 | SimpleIf(printer, vars, cond); 67 | printer.Print(vars, body); 68 | printer.Print("\n"); 69 | CloseBrace(printer); 70 | } 71 | 72 | void 73 | Generator::FullCuddledIf(io::Printer& printer, 74 | const std::map& vars, 75 | const char *cond1, 76 | const char *cond2, 77 | const char *body) 78 | { 79 | CuddledIf(printer, vars, cond1, cond2); 80 | printer.Print(vars, body); 81 | printer.Print("\n"); 82 | CloseBrace(printer); 83 | } 84 | 85 | void 86 | Generator::Else(io::Printer& printer) 87 | { 88 | Outdent(printer); 89 | printer.Print("} else {\n"); 90 | Indent(printer); 91 | } 92 | 93 | void 94 | Generator::SkipUnknown(io::Printer& printer) 95 | { 96 | printer.Print("if (ngx_protobuf_skip(pos, end, wire) != NGX_OK) "); 97 | BracedReturn(printer, "NGX_ABORT"); 98 | } 99 | 100 | void 101 | Generator::BracedReturn(io::Printer& printer, const char *value) 102 | { 103 | OpenBrace(printer); 104 | printer.Print("return "); 105 | printer.Print(value); 106 | printer.Print(";\n"); 107 | CloseBrace(printer); 108 | } 109 | 110 | std::string 111 | Generator::Spaces(int count) 112 | { 113 | std::string output; 114 | 115 | while (count-- > 0) { 116 | output += ' '; 117 | } 118 | 119 | return output; 120 | } 121 | 122 | std::string 123 | Generator::Number(int number) 124 | { 125 | std::ostringstream os; 126 | 127 | os << number; 128 | 129 | return os.str(); 130 | } 131 | 132 | void 133 | Generator::Indent(io::Printer& printer) 134 | { 135 | printer.Indent(); 136 | printer.Indent(); 137 | } 138 | 139 | void 140 | Generator::Outdent(io::Printer& printer) 141 | { 142 | printer.Outdent(); 143 | printer.Outdent(); 144 | } 145 | 146 | } // namespace nginx 147 | } // namespace compiler 148 | } // namespace protobuf 149 | } // namespace google 150 | -------------------------------------------------------------------------------- /protongx/ngx_size.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace google { 6 | namespace protobuf { 7 | namespace compiler { 8 | namespace nginx { 9 | 10 | void 11 | Generator::GenerateSize(const Descriptor* desc, io::Printer& printer) 12 | { 13 | std::map vars; 14 | 15 | vars["name"] = desc->full_name(); 16 | vars["root"] = TypedefRoot(desc->full_name()); 17 | vars["type"] = StructType(desc->full_name()); 18 | 19 | // statics for packed field size calcs. this is independent of field 20 | // number and just calculates the payload size (of the actual data). 21 | 22 | for (int i = 0; i < desc->field_count(); ++i) { 23 | const FieldDescriptor *field = desc->field(i); 24 | 25 | if (field->is_packable() && field->options().packed()) { 26 | bool fixed = false; 27 | 28 | vars["ffull"] = field->full_name(); 29 | vars["fname"] = field->name(); 30 | vars["ftype"] = FieldRealType(field); 31 | 32 | printer.Print(vars, 33 | "static size_t\n" 34 | "$root$_$fname$__packed_size(ngx_array_t *a)\n" 35 | "{\n"); 36 | Indent(printer); 37 | 38 | switch (field->type()) { 39 | case FieldDescriptor::TYPE_FIXED32: 40 | case FieldDescriptor::TYPE_SFIXED32: 41 | case FieldDescriptor::TYPE_FLOAT: 42 | printer.Print("return (a && a->nelts > 0) ? a->nelts * 4 : 0;\n"); 43 | fixed = true; 44 | break; 45 | case FieldDescriptor::TYPE_FIXED64: 46 | case FieldDescriptor::TYPE_SFIXED64: 47 | case FieldDescriptor::TYPE_DOUBLE: 48 | printer.Print("return (a && a->nelts > 0) ? a->nelts * 8 : 0;\n"); 49 | fixed = true; 50 | break; 51 | default: 52 | // continue with the codegen 53 | break; 54 | } 55 | 56 | if (!fixed) { 57 | printer.Print(vars, 58 | "size_t size = 0;\n" 59 | "ngx_uint_t i;\n" 60 | "$ftype$ *fptr;\n" 61 | "\n"); 62 | 63 | SimpleIf(printer, vars, 64 | "a != NULL && a->nelts > 0"); 65 | printer.Print(vars, 66 | "fptr = a->elts;\n" 67 | "for (i = 0; i < a->nelts; ++i) {\n"); 68 | Indent(printer); 69 | 70 | switch (field->type()) { 71 | case FieldDescriptor::TYPE_BOOL: 72 | case FieldDescriptor::TYPE_ENUM: 73 | case FieldDescriptor::TYPE_UINT32: 74 | case FieldDescriptor::TYPE_INT32: 75 | printer.Print("size += ngx_protobuf_size_uint32(fptr[i]);\n"); 76 | break; 77 | case FieldDescriptor::TYPE_SINT32: 78 | printer.Print("size += ngx_protobuf_size_sint32(fptr[i]);\n"); 79 | break; 80 | case FieldDescriptor::TYPE_UINT64: 81 | case FieldDescriptor::TYPE_INT64: 82 | printer.Print("size += ngx_protobuf_size_uint32(fptr[i]);\n"); 83 | break; 84 | case FieldDescriptor::TYPE_SINT64: 85 | printer.Print("size += ngx_protobuf_size_sint64(fptr[i]);\n"); 86 | break; 87 | default: 88 | printer.Print(vars, 89 | "#error $ffull$ cannot be a packed field"); 90 | break; 91 | } 92 | 93 | CloseBrace(printer); 94 | CloseBrace(printer); 95 | printer.Print("\n" 96 | "return size;\n"); 97 | } 98 | CloseBrace(printer); 99 | printer.Print("\n"); 100 | } 101 | } 102 | 103 | printer.Print(vars, 104 | "size_t\n" 105 | "$root$__size(\n" 106 | " $type$ *obj)\n" 107 | "{\n"); 108 | Indent(printer); 109 | 110 | Flags flags(desc); 111 | bool iterates = false; 112 | 113 | for (int i = 0; i < desc->field_count(); ++i) { 114 | const FieldDescriptor *field = desc->field(i); 115 | 116 | if (field->is_repeated() && !IsFixedWidth(field) && 117 | !(field->is_packable() && field->options().packed())) { 118 | iterates = true; 119 | break; 120 | } 121 | } 122 | 123 | printer.Print("size_t size = 0;\n"); 124 | if (flags.has_packed() || flags.has_message()) { 125 | printer.Print("size_t n;\n"); 126 | } 127 | if (iterates || HasUnknownFields(desc)) { 128 | // we need to iterate any repeated non-fixed field or unknown fields 129 | printer.Print("ngx_uint_t i;\n"); 130 | } 131 | printer.Print("\n"); 132 | 133 | for (int i = 0; i < desc->field_count(); ++i) { 134 | const FieldDescriptor *field = desc->field(i); 135 | 136 | vars["fname"] = field->name(); 137 | vars["ftype"] = FieldRealType(field); 138 | vars["fnum"] = Number(field->number()); 139 | 140 | if (field->is_repeated()) { 141 | 142 | CuddledIf(printer, vars, 143 | "obj->__has_$fname$", 144 | "&& obj->$fname$ != NULL\n" 145 | "&& obj->$fname$->nelts > 0"); 146 | 147 | if (field->is_packable() && field->options().packed()) { 148 | printer.Print(vars, 149 | "n = $root$_$fname$__packed_size(\n"); 150 | Indented(printer, vars, "obj->$fname$);\n"); 151 | 152 | printer.Print("\n"); 153 | 154 | printer.Print(vars, 155 | "size += ngx_protobuf_size_message_field(n, $fnum$);\n"); 156 | 157 | } else if (IsFixedWidth(field)) { 158 | 159 | // size calculation of a non-packed repeated fixed-width field 160 | 161 | switch (field->type()) { 162 | case FieldDescriptor::TYPE_FIXED32: 163 | case FieldDescriptor::TYPE_SFIXED32: 164 | case FieldDescriptor::TYPE_FLOAT: 165 | printer.Print(vars, 166 | "size += obj->$fname$->nelts *\n" 167 | " ngx_protobuf_size_fixed32_field($fnum$);\n"); 168 | break; 169 | case FieldDescriptor::TYPE_FIXED64: 170 | case FieldDescriptor::TYPE_SFIXED64: 171 | case FieldDescriptor::TYPE_DOUBLE: 172 | printer.Print(vars, 173 | "size += obj->$fname$->nelts *\n" 174 | " ngx_protobuf_size_fixed64_field($fnum$);\n"); 175 | break; 176 | default: 177 | break; 178 | } 179 | } else { 180 | 181 | // size calculation of a non-packed repeated non-fixed width field 182 | 183 | printer.Print(vars, 184 | "$ftype$ *vals = obj->$fname$->elts;\n" 185 | "\n" 186 | "for (i = 0; i < obj->$fname$->nelts; ++i) {\n"); 187 | Indent(printer); 188 | 189 | switch (field->type()) { 190 | case FieldDescriptor::TYPE_MESSAGE: 191 | vars["froot"] = TypedefRoot(field->message_type()->full_name()); 192 | printer.Print(vars, 193 | "n = $froot$__size(vals + i);\n" 194 | "size += ngx_protobuf_size_message_field(" 195 | "n, $fnum$);\n"); 196 | break; 197 | case FieldDescriptor::TYPE_BYTES: 198 | case FieldDescriptor::TYPE_STRING: 199 | printer.Print(vars, 200 | "size += ngx_protobuf_size_string_field(" 201 | "vals + i, $fnum$);\n"); 202 | break; 203 | case FieldDescriptor::TYPE_BOOL: 204 | printer.Print(vars, 205 | "size += ngx_protobuf_size_uint32_field(" 206 | "(vals[i] != 0), $fnum$);\n"); 207 | break; 208 | case FieldDescriptor::TYPE_ENUM: 209 | case FieldDescriptor::TYPE_UINT32: 210 | case FieldDescriptor::TYPE_INT32: 211 | printer.Print(vars, 212 | "size += ngx_protobuf_size_uint32_field(" 213 | "vals[i], $fnum$);\n"); 214 | break; 215 | case FieldDescriptor::TYPE_SINT32: 216 | printer.Print(vars, 217 | "size += ngx_protobuf_size_sint32_field(" 218 | "vals[i], $fnum$);\n"); 219 | break; 220 | case FieldDescriptor::TYPE_UINT64: 221 | case FieldDescriptor::TYPE_INT64: 222 | printer.Print(vars, 223 | "size += ngx_protobuf_size_uint64_field(" 224 | "vals[i], $fnum$);\n"); 225 | break; 226 | case FieldDescriptor::TYPE_SINT64: 227 | printer.Print(vars, 228 | "size += ngx_protobuf_size_sint64_field(" 229 | "vals[i], $fnum$);\n"); 230 | break; 231 | case FieldDescriptor::TYPE_FIXED32: 232 | case FieldDescriptor::TYPE_SFIXED32: 233 | case FieldDescriptor::TYPE_FLOAT: 234 | printer.Print(vars, 235 | "size += ngx_protobuf_size_fixed32_field($fnum$);\n"); 236 | break; 237 | case FieldDescriptor::TYPE_FIXED64: 238 | case FieldDescriptor::TYPE_SFIXED64: 239 | case FieldDescriptor::TYPE_DOUBLE: 240 | printer.Print(vars, 241 | "size += ngx_protobuf_size_fixed64_field($fnum$);\n"); 242 | break; 243 | default: 244 | printer.Print(vars, 245 | "size += FIXME; /* size $ftype$ */\n"); 246 | break; 247 | } 248 | 249 | Outdent(printer); 250 | printer.Print("}\n"); 251 | } 252 | Outdent(printer); 253 | printer.Print("}\n"); 254 | } else { 255 | switch (field->type()) { 256 | case FieldDescriptor::TYPE_MESSAGE: 257 | vars["froot"] = TypedefRoot(field->message_type()->full_name()); 258 | FullCuddledIf(printer, vars, 259 | "obj->__has_$fname$", 260 | "&& obj->$fname$ != NULL", 261 | "n = $froot$__size(obj->$fname$);\n" 262 | "size += ngx_protobuf_size_message_field(n, $fnum$);"); 263 | break; 264 | case FieldDescriptor::TYPE_BYTES: 265 | case FieldDescriptor::TYPE_STRING: 266 | FullSimpleIf(printer, vars, 267 | "obj->__has_$fname$", 268 | "size += ngx_protobuf_size_string_field(" 269 | "&obj->$fname$, $fnum$);"); 270 | break; 271 | case FieldDescriptor::TYPE_BOOL: 272 | FullSimpleIf(printer, vars, 273 | "obj->__has_$fname$", 274 | "size += ngx_protobuf_size_uint32_field(" 275 | "(obj->$fname$ != 0), $fnum$);"); 276 | break; 277 | case FieldDescriptor::TYPE_ENUM: 278 | case FieldDescriptor::TYPE_UINT32: 279 | case FieldDescriptor::TYPE_INT32: 280 | FullSimpleIf(printer, vars, 281 | "obj->__has_$fname$", 282 | "size += ngx_protobuf_size_uint32_field(" 283 | "obj->$fname$, $fnum$);"); 284 | break; 285 | case FieldDescriptor::TYPE_SINT32: 286 | FullSimpleIf(printer, vars, 287 | "obj->__has_$fname$", 288 | "size += ngx_protobuf_size_sint32_field(" 289 | "obj->$fname$, $fnum$);"); 290 | break; 291 | case FieldDescriptor::TYPE_UINT64: 292 | case FieldDescriptor::TYPE_INT64: 293 | FullSimpleIf(printer, vars, 294 | "obj->__has_$fname$", 295 | "size += ngx_protobuf_size_uint64_field(" 296 | "obj->$fname$, $fnum$);"); 297 | break; 298 | case FieldDescriptor::TYPE_SINT64: 299 | FullSimpleIf(printer, vars, 300 | "obj->__has_$fname$", 301 | "size += ngx_protobuf_size_sint64_field(" 302 | "obj->$fname$, $fnum$);"); 303 | break; 304 | case FieldDescriptor::TYPE_FIXED32: 305 | case FieldDescriptor::TYPE_SFIXED32: 306 | case FieldDescriptor::TYPE_FLOAT: 307 | FullSimpleIf(printer, vars, 308 | "obj->__has_$fname$", 309 | "size += ngx_protobuf_size_fixed32_field($fnum$);"); 310 | break; 311 | case FieldDescriptor::TYPE_FIXED64: 312 | case FieldDescriptor::TYPE_SFIXED64: 313 | case FieldDescriptor::TYPE_DOUBLE: 314 | FullSimpleIf(printer, vars, 315 | "obj->__has_$fname$", 316 | "size += ngx_protobuf_size_fixed64_field($fnum$);"); 317 | break; 318 | default: 319 | printer.Print(vars, 320 | "size += FIXME; /* size $ftype$ */\n"); 321 | break; 322 | } 323 | } 324 | } 325 | 326 | if (desc->extension_range_count() > 0) { 327 | FullSimpleIf(printer, vars, 328 | "obj->__extensions != NULL", 329 | "size += ngx_protobuf_size_extensions(obj->__extensions);"); 330 | } 331 | 332 | if (HasUnknownFields(desc)) { 333 | printer.Print("\n"); 334 | CuddledIf(printer, vars, 335 | "obj->__unknown != NULL", 336 | "&& obj->__unknown->elts != NULL\n" 337 | "&& obj->__unknown->nelts > 0"); 338 | printer.Print("ngx_protobuf_unknown_field_t *unk = " 339 | "obj->__unknown->elts;\n" 340 | "\n" 341 | "for (i = 0; i < obj->__unknown->nelts; ++i) "); 342 | OpenBrace(printer); 343 | printer.Print("size += ngx_protobuf_size_unknown_field(unk + i);\n"); 344 | CloseBrace(printer); 345 | CloseBrace(printer); 346 | } 347 | 348 | printer.Print("\n" 349 | "return size;\n"); 350 | 351 | CloseBrace(printer); 352 | printer.Print("\n"); 353 | } 354 | 355 | } // namespace nginx 356 | } // namespace compiler 357 | } // namespace protobuf 358 | } // namespace google 359 | -------------------------------------------------------------------------------- /protongx/ngx_typedef.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace google { 5 | namespace protobuf { 6 | namespace compiler { 7 | namespace nginx { 8 | 9 | void 10 | Generator::GenerateEnumDecl(const EnumDescriptor* desc, io::Printer& printer) 11 | { 12 | std::string type(EnumType(desc->full_name())); 13 | unsigned int maxname = 0; 14 | unsigned int maxnumb = 0; 15 | 16 | // if we don't align the '=', what good are we? 17 | for (int i = 0; i < desc->value_count(); ++i) { 18 | const EnumValueDescriptor *value = desc->value(i); 19 | std::string name = EnumValue(value->full_name()); 20 | std::string numb = Number(value->number()); 21 | 22 | if (name.length() > maxname) { 23 | maxname = name.length(); 24 | } 25 | if (numb.length() > maxnumb) { 26 | maxnumb = numb.length(); 27 | } 28 | } 29 | 30 | printer.Print("/* $type$ */\n" 31 | "\n" 32 | "typedef enum {\n", 33 | "type", desc->full_name()); 34 | Indent(printer); 35 | 36 | for (int i = 0; i < desc->value_count(); ++i) { 37 | const EnumValueDescriptor *value = desc->value(i); 38 | std::string name = EnumValue(value->full_name()); 39 | std::string numb = Number(value->number()); 40 | std::map vars; 41 | 42 | vars["name"] = name; 43 | vars["nspace"] = Spaces(maxname - name.length()); 44 | vars["vspace"] = Spaces(maxnumb - numb.length()); 45 | vars["value"] = Number(value->number()); 46 | printer.Print(vars, "$name$$nspace$ = $vspace$$value$"); 47 | if (i < desc->value_count() - 1) { 48 | printer.Print(","); 49 | } 50 | printer.Print("\n"); 51 | } 52 | 53 | Outdent(printer); 54 | printer.Print("} $type$;\n" 55 | "\n", 56 | "type", type); 57 | } 58 | 59 | void 60 | Generator::GenerateTypedef(const Descriptor* desc, io::Printer& printer) 61 | { 62 | for (int i = 0; i < desc->enum_type_count(); ++i) { 63 | GenerateEnumDecl(desc->enum_type(i), printer); 64 | } 65 | 66 | for (int i = 0; i < desc->nested_type_count(); ++i) { 67 | GenerateTypedef(desc->nested_type(i), printer); 68 | } 69 | 70 | // now we can generate this typedef 71 | 72 | std::string type(StructType(desc->full_name())); 73 | std::string root(TypedefRoot(desc->full_name())); 74 | 75 | unsigned int maxtype = 0; 76 | unsigned int maxname = 0; 77 | bool hasptr = false; 78 | bool hasself = false; 79 | bool unknown = HasUnknownFields(desc); 80 | 81 | if (desc->extension_range_count() > 0) { 82 | maxtype = sizeof("ngx_rbtree_t") - 1; 83 | hasptr = true; 84 | } else if (unknown) { 85 | maxtype = sizeof("ngx_array_t") - 1; 86 | hasptr = true; 87 | } else { 88 | maxtype = sizeof("uint32_t") - 1; 89 | } 90 | 91 | for (int i = 0; i < desc->field_count(); ++i) { 92 | const FieldDescriptor *field = desc->field(i); 93 | std::string ftype = FieldTypeName(field); 94 | 95 | if (field->is_optional() && FieldRealType(field) == type) { 96 | // type contains a pointer to itself 97 | hasself = true; 98 | } 99 | 100 | if (ftype.length() > maxtype) { 101 | maxtype = ftype.length(); 102 | } 103 | if (field->name().length() > maxname) { 104 | maxname = field->name().length(); 105 | } 106 | if (hasptr == false && FieldIsPointer(field)) { 107 | hasptr = true; 108 | } 109 | } 110 | 111 | printer.Print("/* $type$ */\n" 112 | "\n", 113 | "type", desc->full_name()); 114 | 115 | if (hasself) { 116 | printer.Print("typedef struct $root$_s $type$;\n" 117 | "\n" 118 | "struct $root$_s {\n", 119 | "root", root, "type", type); 120 | } else { 121 | printer.Print("typedef struct {\n"); 122 | } 123 | Indent(printer); 124 | 125 | for (int i = 0; i < desc->field_count(); ++i) { 126 | const FieldDescriptor *field = desc->field(i); 127 | std::string ftype = FieldTypeName(field); 128 | std::string fname = field->name(); 129 | std::string star; 130 | std::map vars; 131 | 132 | if (hasptr) { 133 | if (FieldIsPointer(field)) { 134 | star = "*"; 135 | } else { 136 | star = " "; 137 | } 138 | } else { 139 | star = ""; 140 | } 141 | 142 | vars["type"] = ftype; 143 | vars["tspace"] = Spaces(maxtype - ftype.length()); 144 | vars["fname"] = fname; 145 | vars["star"] = star; 146 | 147 | if (field->is_repeated()) { 148 | printer.Print("/* $rtype$ */\n", "rtype", FieldRealType(field)); 149 | } 150 | printer.Print(vars, "$type$$tspace$ $star$$fname$;\n"); 151 | } 152 | 153 | // extension tree 154 | 155 | if (desc->extension_range_count() > 0) { 156 | std::map vars; 157 | std::string ftype = "ngx_rbtree_t"; 158 | 159 | vars["type"] = ftype; 160 | vars["tspace"] = Spaces(maxtype - ftype.length()); 161 | printer.Print(vars, "$type$$tspace$ *__extensions;\n"); 162 | } 163 | 164 | // unknown fields (if applicable) 165 | 166 | if (unknown) { 167 | std::map vars; 168 | std::string ftype = "ngx_array_t"; 169 | 170 | vars["type"] = ftype; 171 | vars["tspace"] = Spaces(maxtype - ftype.length()); 172 | printer.Print(vars, 173 | "/* ngx_protobuf_unknown_field_t */\n" 174 | "$type$$tspace$ *__unknown;\n"); 175 | } 176 | 177 | // the "has" bits are last 178 | 179 | for (int i = 0; i < desc->field_count(); ++i) { 180 | const FieldDescriptor *field = desc->field(i); 181 | std::string ftype = "uint32_t"; 182 | std::string fname = field->name(); 183 | std::map vars; 184 | 185 | vars["type"] = ftype; 186 | vars["tspace"] = Spaces(maxtype - ftype.length()); 187 | vars["fname"] = "__has_" + field->name(); 188 | vars["nspace"] = Spaces(maxname - field->name().length()); 189 | vars["star"] = (hasptr) ? " " : ""; 190 | 191 | printer.Print(vars, "$type$$tspace$ $star$$fname$$nspace$ : 1;\n"); 192 | } 193 | 194 | Outdent(printer); 195 | 196 | if (hasself) { 197 | printer.Print("};\n" 198 | "\n"); 199 | } else { 200 | printer.Print("} $type$;\n" 201 | "\n", 202 | "type", type); 203 | } 204 | } 205 | 206 | } // namespace nginx 207 | } // namespace compiler 208 | } // namespace protobuf 209 | } // namespace google 210 | --------------------------------------------------------------------------------