Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Initial commit |
---|---|
Timelines: | family | ancestors | trunk |
Files: | files | file ages | folders |
SHA1: | b7de7b4c7cfeddda59e818fae16ee0b3cb2e5f39 |
User & Date: | mh 2014-08-29 00:08:12 |
2014-08-29
| ||
00:08 | Initial commit Leaf check-in: b7de7b4c7c user: mh tags: trunk | |
2014-08-28
| ||
15:08 | initial empty check-in check-in: e2f156395e user: machel tags: trunk | |
Added BuildRecipes/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
# ### === Machel's MAKEFILE ### === # :: File: # .. project/file: Makefile <GNU Make> # . # .. info: # . Created: 2014-01-12 by "Machel" # . Last modified: 2014-07-12 by "Machel" # . License: GNU Public License # . (c) Copyright: "Machel" 2014 # . # .. dependencies: # -- GNU Make - many specific features used # -- GCC - dependency creation feature used # # :: Description: # . Makefile for Machel's C/C++ projects. # . May be used in all Machel's C/C++ projects adhering to certain project # layout # # :: Functionality: # -- sources: auto hunting up source files # - inside all src* and lib* directories one level deep # - for files with 'c/cxx' suffix (.c/.cxx) # # -- headers: auto determine directories with header files # - header files are assumed to exist in source dirs ONLY thus header dirs # are the same as source dirs # # -- shell scripts: files with .sh extension auto copied from sh_scripts # directory to .bin (extension is removed) # # -- documentation: auto created from files resisting in doc directory and # having proper suffix (see targets for docs) # # -- dependencies: auto generates dependency files # - depfile is created for each object file, and object file is assumed for # each source file # - object files depends on corresponding source file and all header files # included by this source file # - depfile depends on same files to ensure it is recreated each time one # of that files is changed (in case included files changed) # - depfile lists all dependencies being header files as targets themselves # to suppress errors if they do not exist (programmer could remove them # from includes in source file and from file system or rename) # # -- separate dirs: files generated by compiler and auxillary files # (like depfiles) are placed in separate dirs to not mix them up # with source and header files # - executables go to '.bin' # - object files go to '.build' # - depfiles go to '.deps' # - GENERAL: temporary files go to dirs begining with dots, except packages # which goes to .packages directory # # -- static checks: splint, flawfinder, rats, clang analyzer # # -- debug builds: several levels with different warning flags # # -- cleanup: cleanup project directories # - shallow cleans - remove specific files # - deep cleans - remove all created dirs and leave project in original state # - see clean targets for details # # :: Limitations: # --- header files are assumed to be only in same dirs as source files # --- can't use compiler other then GCC for reason of dependency creation SHELL := /bin/sh REQUIRED_FILES := NAME VERSION BuildRecipes/ProjSettings.mk BuildRecipes/mk_hllibs.sh RES := $(wildcard $(REQUIRED_FILES)) ifneq ($(RES),$(REQUIRED_FILES)) $(error "One of following files does not exist: $(REQUIRED_FILES)")) endif # === USER SETTINGS === include BuildRecipes/ProjSettings.mk # --- BASE SETTINGS --- PRNAME := $(shell cat NAME) VERSION := $(patsubst VER%,,$(shell cat VERSION)) VERSION := $(subst \#define ,,$(VERSION)) SPACE_ := SPACE_ += VERSION := $(subst $(SPACE_),.,$(VERSION)) PACK_NAME := $(PRNAME)-$(VERSION) ifeq ($(PR_LANG),C) PROJS_MAIN_DIR := /home/Magazyn/Projects/c else ifeq ($(PR_LANG),CXX) PROJS_MAIN_DIR := /home/Magazyn/Projects/cxx else $(error "Invalid PR_LANG value") endif # --- INSTALL SETTINGS --- DESTDIR ?= prefix ?= /usr confdir ?= /etc bindir := $(prefix)/bin libdir := $(prefix)/lib mandir ?= /usr/share/man appdatadir ?= /usr/share/$(PRNAME) vimdatadir := $(appdatadir)/vim/vimfiles vimdir ?= /usr/share/vim/vimfiles # --- BUILD LAYOUT SETTINGS --- # SOURCE FILES ARCH_BUNDLE := BuildRecipes/arch DIR_DOCS_SRCS := doc DIR_SCRIPTS_SRCS := sh_scripts SOURCES_TESTS_C := $(wildcard src*/*_test.c src*/**/*_test.c) SOURCES_EXECS_C := $(wildcard src*/*_exec.c src*/**/*_exec.c) SOURCES_ALL_C := $(wildcard src*/*.c src*/**/*.c lib_*/*.c lib_*/**/*.c) SOURCES_C := $(filter-out $(SOURCES_TESTS_C),$(SOURCES_ALL_C)) SOURCES_C := $(filter-out $(SOURCES_EXECS_C),$(SOURCES_C)) SOURCES_TESTS_C += $(wildcard tests*/*.c tests*/**/*.c) SOURCES_EXECS_C += $(wildcard execs*/*.c execs*/**/*.c) ifeq ($(PR_LANG),CXX) SOURCES_TESTS_CXX := $(wildcard src*/*_test.cxx src*/**/*_test.cxx) SOURCES_EXECS_CXX := $(wildcard src*/*_exec.cxx src*/**/*_exec.cxx) SOURCES_ALL_CXX := $(wildcard src*/*.cxx src*/**/*.cxx lib_*/*.cxx lib_*/**/*.cxx) SOURCES_CXX := $(filter-out $(SOURCES_TESTS_CXX),$(SOURCES_ALL_CXX)) SOURCES_CXX := $(filter-out $(SOURCES_EXECS_CXX),$(SOURCES_CXX)) SOURCES_TESTS_CXX += $(wildcard tests*/*.cxx tests*/**/*.cxx) SOURCES_EXECS_CXX += $(wildcard execs*/*.cxx execs*/**/*.cxx) endif SOURCES_TESTS := $(SOURCES_TESTS_C) $(SOURCES_TESTS_CXX) SOURCES_EXECS := $(SOURCES_EXECS_C) $(SOURCES_EXECS_CXX) SOURCES_ALL := $(SOURCES_ALL_C) $(SOURCES_ALL_CXX) SOURCES := $(SOURCES_C) $(SOURCES_CXX) #$(info $(SOURCES_TESTS)) #$(info $(SOURCES_EXECS)) #$(info $(SOURCES_ALL)) #$(info $(SOURCES)) SOURCES_SCRIPTS ?= SOURCES_SCRIPTS += $(wildcard $(DIR_SCRIPTS_SRCS)/*.sh) SOURCES_VIM ?= SOURCES_VIM += $(wildcard vim_*/**/*.vim) # ex. 'manpage.1.man.t2t' where '1' is section number SOURCES_DOCS_MANS ?= SOURCES_DOCS_MANS += $(wildcard $(DIR_DOCS_SRCS)/*.man.t2t) SOURCES_DOCS_HTMLS ?= SOURCES_DOCS_HTMLS += $(wildcard $(DIR_DOCS_SRCS)/*.html.t2t) SOURCES_DOCS_MAINS ?= SOURCES_DOCS_MAINS += $(wildcard $(DIR_DOCS_SRCS)/*.main.t2t) SOURCES_DOCS_MDS ?= SOURCES_DOCS_MDS += $(wildcard $(DIR_DOCS_SRCS)/*.md) # TARGET FILES DIR_DOCS := doc DIR_BIN := .bin DIR_VIM := .vim DIR_PACK := .packages DIR_ANALYSE := .analyse ANALYZE_OUTPUT_FILE := static_analysis.txt TAR_TESTS := $(DIR_BIN)/$(PRNAME)_test TAR_LIBS := $(DIR_BIN)/$(PRNAME).a TAR_EXECS := $(DIR_BIN)/$(PRNAME) TAR_SCRIPTS := $(patsubst %.sh,$(DIR_BIN)/%,$(notdir $(SOURCES_SCRIPTS))) TAR_VIM_FILES := $(notdir $(SOURCES_VIM)) TAR_VIM_DIRS := $(notdir $(patsubst %/,%,$(dir $(SOURCES_VIM)))) TAR_VIM := $(addprefix $(DIR_VIM)/,$(SOURCES_VIM)) DOC_MANS := $(patsubst %.man.t2t,$(DIR_DOCS)/man/%.gz,$(notdir $(SOURCES_DOCS_MANS))) DOC_HTMLS := $(patsubst %.html.t2t,$(DIR_DOCS)/html/%.html,$(notdir $(SOURCES_DOCS_HTMLS))) DOC_MAINS := $(patsubst %.main.t2t,$(DIR_DOCS)/mains/%,$(notdir $(SOURCES_DOCS_MAINS))) DOC_MDS := $(patsubst %.md,$(DIR_DOCS)/md/%.md,$(notdir $(SOURCES_DOCS_MDS))) DOCS := $(DOC_MANS) $(DOC_HTMLS) $(DOC_MAINS) $(DOC_MDS) # --- BUILD OPTIONS --- ifeq ($(PR_LANG),C) CC = gcc STD_FLAGS := -std=c99 -pedantic else ifeq ($(PR_LANG),CXX) CC = /usr/bin/g++ STD_FLAGS := -std=c++11 -pedantic endif COMPILER := $(CC) -pipe #-fdiagnostics-color CPP_FLAGS := ARCH_FLAGS := -march=native -mtune=native OPTIMIZE_FLAGS := -fstrict-aliasing -Wdisabled-optimization -minline-all-stringops \ -funroll-loops -momit-leaf-frame-pointer #<C++>: -fstrict-enums WARN_FLAGS := -Wall -Wextra -Wshadow -Wwrite-strings -Wpointer-arith -Wcast-qual \ -Wcast-align -Wswitch-default -Wswitch-enum \ -Wstrict-overflow=2 -Wredundant-decls \ -Wlogical-op -Wfloat-equal -Wmissing-include-dirs #ev. -Wno-unused-parameter #ev. -Wno-unused-value WARN2_FLAGS := -Wundef -Wstrict-overflow=5 -Wconversion -Wunsuffixed-float-constants \ -Wdouble-promotion -Wunused -Wuninitialized -Winit-self -Wfloat-equal \ -Wbad-function-cast -Wjump-misses-init -Wpadded -Winline -Wformat=2 \ -Werror-implicit-function-declaration -Wunused-parameter -Wunused NOWARN_DEPL := -Wno-cast-qual -Wno-pedantic -Wno-unused-parameter ifeq ($(PR_LANG),C) WARN_FLAGS += -Wstrict-prototypes -Wnested-externs else ifeq ($(PR_LANG),CXX) WARN_FLAGS += -Wctor-dtor-privacy -Wnon-virtual-dtor -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Weffc++ endif TOOLS_FLAGS := -ggdb3 -pg DIAGNOSE_FLAGS := -fmem-report -fprofile-report -fstack-usage -ftest-coverage -Q \ -fdump-translation-unit -fdump-class-hierarchy -save-temps DBG_COMMON_FLAGS := -DDEBUG -fno-eliminate-unused-debug-types -ftrapv -fstack-check DBG_FLAGS := -O0 $(DBG_COMMON_FLAGS) $(TOOLS_FLAGS) $(WARN_FLAGS) DBG2_FLAGS := -O2 $(DBG_COMMON_FLAGS) $(TOOLS_FLAGS) $(WARN2_FLAGS) -DDEBUG2 DBG3_FLAGS := -O3 $(DBG_COMMON_FLAGS) $(TOOLS_FLAGS) $(WARN2_FLAGS) \ -fmudflap -Wno-nested-externs -fstack-protector-all -lmudflap # -fmudflap - check arrays/heap bounds ;needs special lib # -fmudflapth - check arrays/heap bounds for multi-th pr DEPL_FLAGS := -O3 -DNDEBUG $(WARN_FLAGS) $(NOWARN_DEPL) -fomit-frame-pointer -g TEST_FLAGS := -O3 -DDEBUG2 $(WARN_FLAGS) $(TOOLS_FLAGS) #-finline-functions - try inline all simple enough funs MSGS_FLAGS := -fmessage-length=0 -fmax-errors=10 #<C++>: -fno-pretty-templates # === TRANSITIONAL FILES === DIR_OBJS := .build DIR_DEPS := .deps DEPS := $(SOURCES:%.c=$(DIR_DEPS)/%.dep) DEPS_TESTS := $(SOURCES_TESTS:%.c=$(DIR_DEPS)/%.dep) DEPS_EXECS := $(SOURCES_EXECS:%.c=$(DIR_DEPS)/%.dep) OBJECTS := $(patsubst %.c,$(DIR_OBJS)/%.o,$(SOURCES)) OBJECTS_TESTS := $(patsubst %.c,$(DIR_OBJS)/%.o,$(SOURCES_TESTS)) OBJECTS_EXEC := $(patsubst %.c,$(DIR_OBJS)/%.o,$(SOURCES_EXECS)) ifeq ($(PR_LANG),CXX) DEPS := $(DEPS:%.cxx=$(DIR_DEPS)/%.dep) DEPS_TESTS := $(DEPS_TESTS:%.cxx=$(DIR_DEPS)/%.dep) DEPS_EXECS := $(DEPS_EXECS:%.cxx=$(DIR_DEPS)/%.dep) OBJECTS := $(patsubst %.cxx,$(DIR_OBJS)/%.o,$(OBJECTS)) OBJECTS_TESTS := $(patsubst %.cxx,$(DIR_OBJS)/%.o,$(OBJECTS_TESTS)) OBJECTS_EXEC := $(patsubst %.cxx,$(DIR_OBJS)/%.o,$(OBJECTS_EXECS)) endif #$(info $(OBJECTS)) #$(info $(OBJECTS_TESTS)) #$(error ABORT) SOURCES_DOCS := $(wildcard doc*/*.t2t) DIRS_INCLUDES := . $(wildcard src*) $(filter %/, $(wildcard src*/**/)) DIRS_INCLUDES += $(wildcard include*) $(filter %/, $(wildcard include*/**/)) DIRS_INCLUDES += $(wildcard lib_*) $(filter %/, $(wildcard lib_*/**/)) INCLUDES_OPTS := $(patsubst %,-I%,$(DIRS_INCLUDES)) LIBRARIES := $(wildcard lib/*.a) LIBRARIES := $(patsubst lib/lib%.a,-l%,$(LIBRARIES)) CPPFLAGS := $(CPP_FLAGS) $(INCLUDES_OPTS) CFLAGS := $(STD_FLAGS) $(ARCH_FLAGS) $(MSGS_FLAGS) $(OPTIMIZE_FLAGS) LFLAGS := -L./lib $(LIBRARIES) DIRS_CONCAT := $(DIR_BIN) $(DIR_OBJS) $(DIR_DEPS) $(DIR_DOCS) $(DIR_PACK) $(DIR_VIM) $(DIR_ANALYSE) # === TARGETS === # --- General targets --- all: depl docs # print help .PHONY: help help: @echo "make DESTDIR=/dir install - install to /dir (def. is /usr)" # createllibs hllibs: @BuildRecipes/mk_hllibs.sh "$(PR_LANG)" "$(PROJS_MAIN_DIR)" # --- Main targets --- debug: CFLAGS+=$(DBG_FLAGS) debug: OUT_REDIRECT := >diagnose.txt 2>&1 debug: prepare $(TAR_TESTS) debug2: CFLAGS+=$(DBG2_FLAGS) debug2: prepare $(TAR_TESTS) debug3: CFLAGS+=$(DBG3_FLAGS) debug3: prepare $(TAR_TESTS) diagnose: CFLAGS+=$(DBG_FLAGS) $(DIAGNOSE_FLAGS) diagnose: prepare $(TAR_TESTS) depl: CFLAGS+=$(DEPL_FLAGS) ifeq ($(TYPE),pr) depl: prepare $(TAR_EXECS) docs scripts vimscripts else depl: prepare $(TAR_LIBS) endif depl_test: CFLAGS+=$(TEST_FLAGS) ifeq ($(TYPE),pr) depl_test: prepare $(TAR_EXECS) docs scripts vimscripts else depl_test: prepare $(TAR_LIBS) endif docs: prepare $(DOCS) scripts: prepare $(TAR_SCRIPTS) vimscripts: prepare $(TAR_VIM) # --- Build targets --- .PHONY: prepare prepare: @mkdir -vp $(DIRS_CONCAT) $(DIR_OBJS)/%.o : %.c @echo doing $@ @mkdir -vp $(@D) @mkdir -vp $(@D:$(DIR_OBJS)/%=$(DIR_DEPS)/%) $(COMPILER) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) @echo -e "...> COMPILED $@\n\n\n" @$(COMPILER) -MM -MP -MT'$(@) $(DIR_DEPS)/$*.dep' $(CPPFLAGS) -o $(DIR_DEPS)/$*.dep $< $(DIR_OBJS)/%.o : %.cxx @echo doing $@ @mkdir -vp $(@D) @mkdir -vp $(@D:$(DIR_OBJS)/%=$(DIR_DEPS)/%) $(COMPILER) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) @echo -e "...> COMPILED $@\n\n\n" @$(COMPILER) -MM -MP -MT'$(@) $(DIR_DEPS)/$*.dep' $(CPPFLAGS) -o $(DIR_DEPS)/$*.dep $< # create object file together with depfile if *.c file changed: # . create directories: dirs chain for object file # $(@D) - directory part of target object file # . create directories: dirs chain for dependency file # $(@D:...) - substitute objects dir for deps dir # . compile source file that triggered recipe # @< - dependency source file that triggered recipe (:right) # $@ - target object file (left:) # . generate depfiles for created object file # $* - part of target that matches pattern (%) ;only in implicit rules # -M:generate dep rule for target (*.o) -MM:same but skip system headers in deps # -MP:create phony targets for *.h - prevents errors when headers missing and # it is still in old depfile (file will be overriden now with valid deps) # -MT:target pattern in rule - current target + current depfile (to make sure # its recreation when sources changed - it can mean that #incs changed) # Other special vars: # $^ - all dependencies -include $(DEPS) -include $(DEPS_TESTS) -include $(DEPS_EXECS) # include depfiles # evaluate each depfile and if contains rule to build itself and deps are #ne newer it would rebuild itself if we provide implicit rule for thie # (and we do not provide as recipe for building .o contains command to # generate depfile - .o and .dep have same dependencies) # succ: rerun this Makefile # + no rebuilding depfiles (timestamp changed) # + include redone depfile literally $(TAR_TESTS): $(OBJECTS) $(OBJECTS_TESTS) $(COMPILER) $^ -o $@ $(CFLAGS) $(LFLAGS) @echo -e ":::-> LINKED $@\n\n\n" # /\ create executable with tests: # . link object files into target # $(TAR_LIBS): $(OBJECTS) ar cr $@ $^ @echo -e ":::-> LIBRARY CREATED $@\n\n\n" # /\ create library: # . archive object files into library # $^ - all dependencies # $(TAR_EXECS): $(OBJECTS) $(OBJECTS_EXEC) $(COMPILER) $^ -o $@ $(CFLAGS) $(LFLAGS) @echo -e ":::-> LINKED $@\n\n\n" # /\ create executable: # . link object files into target # $(TAR_SCRIPTS): $(DIR_BIN)/% : $(DIR_SCRIPTS_SRCS)/%.sh \cp -va $< $@ && \chmod -v a+x $@ # $(TAR_VIM): $(DIR_VIM)/% : % @tar=$@; \ tar=$(DIR_VIM)/$${tar#$(DIR_VIM)/*/}; \ mkdir -vp $$(dirname $${tar}); \ cp -va $< $${tar} # create DOC_MANS + additional docs not destined for installation in system # $(DOC_MANS): $(DIR_DOCS)/man/%.gz : $(DIR_DOCS_SRCS)/%.man.t2t @mkdir -vp $(@D) && \ txt2tags -t man -o $(basename $@) $< && \ gzip -vf $(basename $@) T2T_HTML_OPTS := --toc $(DOC_HTMLS): $(DIR_DOCS)/html/%.html : $(DIR_DOCS_SRCS)/%.html.t2t @mkdir -vp $(@D) && \ txt2tags -t html $(T2T_HTML_OPTS) -o $@ $< $(DOC_MAINS): $(DIR_DOCS)/mains/% : $(DIR_DOCS_SRCS)/%.main.t2t @txt2tags -t txt -o $(notdir $@) $< $(DOC_MDS): $(SOURCES_DOCS_MDS) @mkdir -vp $(@D) && \ cp -va $< $@ # --- Packaging and Installing targets --- # create package .PHONY: pack pack: $(DOCS) @BuildRecipes/pack.sh $(VERSION) $(PACK_NAME) $(DIR_PACK) $(ARCH_BUNDLE) "$(FILES_TO_PACK)" # install/uninstall package .PHONY: install install: depl @[[ ! -z "$(DESTDIR)" ]] && mkdir -vp $(DESTDIR) || echo "" @mkdir -vp $(DESTDIR)$(bindir) @mkdir -vp $(DESTDIR)$(mandir)/man{1,2,3,4,5,6,7,8,9} @mkdir -vp $(DESTDIR)$(vimdatadir)/{plugin,syntax} @install -vm 0755 $(DIR_BIN)/* $(DESTDIR)$(bindir) @for f in $(DOC_MANS); do \ section=$${f%.gz}; \ section=$${section##*.}; \ install -vm 0644 $${f} $(DESTDIR)$(mandir)/man$${section}/; \ done; @for subdir in plugin syntax; do \ install -vm 0644 $(DIR_VIM)/$${subdir}/*.vim $(DESTDIR)$(vimdatadir)/$${subdir}/; \ done; @if [[ -d $(DESTDIR)$(vimdir) ]]; then \ for subdir in plugin syntax; do \ install -vm 0644 $(DIR_VIM)/$${subdir}/*.vim $(DESTDIR)$(vimdir)/$${subdir}/; \ done; \ else \ echo "Unable to find Vim system directory, for Vim support copy following files by hand:"; \ echo " $(DESTDIR)$(vimdatadir)/*/*.vim to Vim's plugin directory"; \ fi; .PHONY: uninstall uninstall: @for f in $(TAR_EXECS); do \ rm -vf $(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ done; @for f in $(TAR_SCRIPTS); do \ rm -vf $(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ done; @for f in $(DOC_MANS); do \ section=$${f%.gz}; \ section=$${section##*.}; \ rm -vf $(DESTDIR)$(mandir)/man$${section}/$$(basename $${f}); \ done; @for f in $(SOURCES_VIM); do \ rm -vf $(DESTDIR)$(vimdatadir)/$${f#*/}; \ done; @if [[ -d $(DESTDIR)$(vimdir) ]]; then \ rm -vf $(DESTDIR)$(vimdir)/$${f#*/}; \ fi; .PHONY: isinstalled isinstalled: @for f in $(TAR_EXECS); do \ fname=$(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @for f in $(TAR_SCRIPTS); do \ fname=$(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @for f in $(DOC_MANS); do \ section=$${f%.gz}; \ section=$${section##*.}; \ fname=$(DESTDIR)$(mandir)/man$${section}/$$(basename $${f}); \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @for f in $(SOURCES_VIM); do \ fname=$(DESTDIR)$(vimdatadir)/$${f#*/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @if [[ -d $(DESTDIR)$(vimdir) ]]; then \ fname=$(DESTDIR)$(vimdir)/$${f#*/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ fi; # --- Auxillary targets --- # + Run tests + .PHONY: runt runt: @$(TAR_TESTS) .PHONY: runt debugr: debug @echo -e ":: Make: running tests now\n\n" @$(TAR_TESTS) .PHONY: vrunt vrunt: @f=$(DIR_ANALYSE)/val_$$(date +%T).txt; \ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --num-callers=40 --track-fds=yes --error-limit=yes --log-file=$${f} $(TAR_TESTS); \ cat $${f}; .PHONY: vrunts vrunts: @f=$(DIR_ANALYSE)/val_$$(date +%T).txt; \ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --num-callers=40 --track-fds=yes --error-limit=yes --log-file=$${f} $(TAR_TESTS) s; \ cat $${f}; # + Fossil info + .PHONY: fosinf fosinf: @fossil status && \ echo -e "\n:: TIMELINE:" && fossil timeline && \ echo -e "\n:: INFO:" && fossil info && \ echo -en "\n:: BRANCH: " && fossil branch # + Gcc info + # see what settings GCC uses .PHONY: gcc-test gcc-test: @gcc $(CPPFLAGS) $(CFLAGS) -E -v - </dev/null 2>&1 # see options only .PHONY: gcc-opts gcc-opts: @gcc $(CPPFLAGS) $(CFLAGS) -E -v - </dev/null 2>&1 | grep cc1 # see arch options .PHONY: gcc-arch gcc-arch: @gcc $(ARCH_FLAGS) -E -v - </dev/null 2>&1 | grep cc1 # --- Code analysis --- # create cpp files from sources .PHONY: cpp cpp: @for file in $(SOURCES); do \ $(COMPILER) -E -C $${file} -o $${file}.cpp $(CPPFLAGS) $(CFLAGS);\ done .PHONY: analyze analyze: @date >> $(ANALYZE_OUTPUT_FILE) @echo -e "==============\n\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @make dist-clean > /dev/null @make debug CC="scan-build gcc" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @flawfinder $(SOURCES) >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "RATS ::" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @rats $(SOURCES) >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @splint $(DIRS_INCLUDES) $(SOURCES) >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n\n\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 .PHONY: compile_headers compile_headers: @for dir in $(DIRS_INCLUDES); do \ for file in $${dir}/*.h; do \ if [ $${file} == "./*.h" ]; then continue; fi; \ filec=$${file}.c; \ echo "compiling header: $${file}"; \ echo "#include \"$${file}\"" > $${filec}; \ $(COMPILER) -c $${filec} -o /dev/null $(CPPFLAGS) $(CFLAGS); \ \rm -v $${filec}; \ done \ done .PHONY: headers_tree headers_tree: @for file in $(SOURCES); do \ echo -e "\ntree for file: $${file}"; \ $(COMPILER) -c -H $${file} $(CPPFLAGS) $(CFLAGS); \ done # --- Cleanup targets --- # remove all not-project files and dirs .PHONY: dist-clean dist-clean: clean-objs clean-tool clean-deps clean-bins clean-dirs @\rm -vrf $(ANALYZE_OUTPUT_FILE) # remove all not-project files .PHONY: clean clean: clean-objs clean-tool clean-deps # remove object files .PHONY: clean-objs clean-objs: @\rm -vrf $(TAR_TESTS) $(TAR_LIBS) $(TAR_EXECS) $(TAR_SCRIPTS) $(DOCS) $(DIR_OBJS)/*.o $(DIR_OBJS)/**/*.o # remove tool files .PHONY: clean-tool clean-tool: @\rm -vrf $(TAR_TESTS) $(TAR_LIBS) $(TAR_EXECS) $(TAR_SCRIPTS) $(DOCS) $(DIR_OBJS)/{*.gcno,*.su,*.tu} \ $(DIR_OBJS)/**/{*.gcno,*.su,*.tu} \ src*/*.cpp src*/**/*.cpp \ *.i *.s gmon.out # remove depfiles .PHONY: clean-deps clean-deps: @\rm -vrf $(DIR_DEPS)/*.dep $(DIR_DEPS)/**/*.dep # remove executables .PHONY: clean-bins clean-bins: @\rm -vrf $(DIR_BIN)/* # remove all not-project dirs with contents .PHONY: clean-dirs clean-dirs: @\rm -vrf $(DIRS_CONCAT) ### REMAINDERS: # create implicit rule for creating depfiles #%.dep : %.c #$(MAKEDEPEND) |
Added BuildRecipes/ProjSettings.mk.
> > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 |
.SUFFIXES: .c .cxx #PR_LANG := C PR_LANG := CXX TYPE := pr #TYPE := lib FILES_TO_PACK="src* sh_scripts lib* doc tests vim_* BuildRecipes Makefile ChangeLog INSTALL LICENSE README VERSION NAME" |
Added BuildRecipes/mk_hllibs.sh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#! /usr/bin/env bash # $1 - project's language (C or CXX) # $2 - project's main dir libs=(lib*) [[ "${libs[0]}" == 'lib*' ]] && exit 0 #echo $1 #echo $2 olddir=$PWD for l in ${libs[@]}; do cd ${l} lib_dir="$2/a${l:3}" srcs=(src*) [[ "${srcs[0]}" == 'src*' ]] && { cd -; continue; } for s in ${srcs[@]}; do cd ${s} \ln -v -L ${lib_dir}/${s}/* . \rm -vf *_test.c *_test.cxx cd - done cd ${olddir} done |
Added BuildRecipes/pack.sh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
#!/usr/bin/env bash # $1 - current program version # $2 - package name (prname-version) # $3 - dir where store package # $4 - directory with AUR files (PKGBUILD. *.install etc.) # $5 - files to pack ex. "file file2 file3" PKGBUILD_FILE="${4}/PKGBUILD" # get package version and release VER=$(\sed -n 's/^pkgver=\(.*\)$/\1/p' ${PKGBUILD_FILE}) REL=$(\sed -n 's/^pkgrel=\(.*\)$/\1/p' ${PKGBUILD_FILE}) if [[ "$VER" != "$1" ]]; then # version in PKGBUILD and current pr version are different # - reset package release REL=1 else # are same # - increment package release ((REL++)) fi PACK_NAME=${2} # pr-ver PACK_DIR=${3} # .package TARBALL=${PACK_NAME}-${REL}.tar.gz AUR_DIR=${4} # MakeRecipes/arch AURBALL=${PACK_NAME}-${REL}.src.tar.gz FILES_TO_PACK=${5} # create pack-directory tree with files intended to pack # and tarball pack-directory and create 'current' link \mkdir -vp ${PACK_DIR}/${PACK_NAME} \cp -vaf ${FILES_TO_PACK} ${PACK_DIR}/${PACK_NAME} \cd ${PACK_DIR} \tar -cvzf ${TARBALL} ${PACK_NAME} \ln -sf ${TARBALL} current.tar.gz \cd - \rm -rf ${PACK_DIR}/${PACK_NAME} # NOW HAVE: .package / pr-ver.tar.gz, current.tar.gz # Alter PKGBUID file: checksums, pkg-release pack_md5sum=$(md5sum ${PACK_DIR}/current.tar.gz) pack_sha256sum=$(sha256sum ${PACK_DIR}/current.tar.gz) pack_md5sum="md5sums=('${pack_md5sum%% *}')" pack_sha256sum="sha256sums=('${pack_sha256sum%% *}')"; \ \sed -i "s/md5sums=(.*)/${pack_md5sum}/" ${PKGBUILD_FILE}; \ \sed -i "s/sha256sums=(.*)/${pack_sha256sum}/" ${PKGBUILD_FILE}; \sed -i "s/^pkgrel=.*$/pkgrel=${REL}/" ${PKGBUILD_FILE} # NOW HAVE: same + PKGBUILD altered # make AurBall and create 'current_aur' link \cp -vaf ${PACK_DIR}/${TARBALL} ${AUR_DIR}; # now PKGBUILD will find tarball in own directory and will not download old version \cd ${AUR_DIR} && mkaurball -f \rm ${TARBALL} \ln -sf ${AURBALL} current_aur.tar.gz \cd - \mv -vf ${AUR_DIR}/*.tar.gz ${PACK_DIR} # NOW HAVE: same + .package / aurball.src.tar.gz , current_aur.tar.gz fossil rm ${PACK_DIR}/tfman*.tar.gz fossil add ${PACK_DIR}/${TARBALL} fossil add ${PACK_DIR}/${AURBALL} # Note to user echo "Aurball created, checksums substituted in PKGBUILD" echo -e "You can now, in this order:\n" \ "\t1.push to repository (to upload new tarball with new sources)\n" \ "\t2.place aurball in AUR (to upload new aurball with new PKGBUILD checksums)" exit 0 |
Added Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 |
# ### === Machel's MAKEFILE ### === # :: File: # .. project/file: Makefile <GNU Make> # . # .. info: # . Created: 2014-01-12 by "Machel" # . Last modified: 2014-07-12 by "Machel" # . License: GNU Public License # . (c) Copyright: "Machel" 2014 # . # .. dependencies: # -- GNU Make - many specific features used # -- GCC - dependency creation feature used # # :: Description: # . Makefile for Machel's C/C++ projects. # . May be used in all Machel's C/C++ projects adhering to certain project # layout # # :: Functionality: # -- sources: auto hunting up source files # - inside all src* and lib* directories one level deep # - for files with 'c/cxx' suffix (.c/.cxx) # # -- headers: auto determine directories with header files # - header files are assumed to exist in source dirs ONLY thus header dirs # are the same as source dirs # # -- shell scripts: files with .sh extension auto copied from sh_scripts # directory to .bin (extension is removed) # # -- documentation: auto created from files resisting in doc directory and # having proper suffix (see targets for docs) # # -- dependencies: auto generates dependency files # - depfile is created for each object file, and object file is assumed for # each source file # - object files depends on corresponding source file and all header files # included by this source file # - depfile depends on same files to ensure it is recreated each time one # of that files is changed (in case included files changed) # - depfile lists all dependencies being header files as targets themselves # to suppress errors if they do not exist (programmer could remove them # from includes in source file and from file system or rename) # # -- separate dirs: files generated by compiler and auxillary files # (like depfiles) are placed in separate dirs to not mix them up # with source and header files # - executables go to '.bin' # - object files go to '.build' # - depfiles go to '.deps' # - GENERAL: temporary files go to dirs begining with dots, except packages # which goes to .packages directory # # -- static checks: splint, flawfinder, rats, clang analyzer # # -- debug builds: several levels with different warning flags # # -- cleanup: cleanup project directories # - shallow cleans - remove specific files # - deep cleans - remove all created dirs and leave project in original state # - see clean targets for details # # :: Limitations: # --- header files are assumed to be only in same dirs as source files # --- can't use compiler other then GCC for reason of dependency creation SHELL := /bin/sh REQUIRED_FILES := NAME VERSION BuildRecipes/ProjSettings.mk BuildRecipes/mk_hllibs.sh RES := $(wildcard $(REQUIRED_FILES)) ifneq ($(RES),$(REQUIRED_FILES)) $(error "One of following files does not exist: $(REQUIRED_FILES)")) endif # === USER SETTINGS === include BuildRecipes/ProjSettings.mk # --- BASE SETTINGS --- PRNAME := $(shell cat NAME) VERSION := $(patsubst VER%,,$(shell cat VERSION)) VERSION := $(subst \#define ,,$(VERSION)) SPACE_ := SPACE_ += VERSION := $(subst $(SPACE_),.,$(VERSION)) PACK_NAME := $(PRNAME)-$(VERSION) ifeq ($(PR_LANG),C) PROJS_MAIN_DIR := /home/Magazyn/Projects/c else ifeq ($(PR_LANG),CXX) PROJS_MAIN_DIR := /home/Magazyn/Projects/cxx else $(error "Invalid PR_LANG value") endif # --- INSTALL SETTINGS --- DESTDIR ?= prefix ?= /usr confdir ?= /etc bindir := $(prefix)/bin libdir := $(prefix)/lib mandir ?= /usr/share/man appdatadir ?= /usr/share/$(PRNAME) vimdatadir := $(appdatadir)/vim/vimfiles vimdir ?= /usr/share/vim/vimfiles # --- BUILD LAYOUT SETTINGS --- # SOURCE FILES ARCH_BUNDLE := BuildRecipes/arch DIR_DOCS_SRCS := doc DIR_SCRIPTS_SRCS := sh_scripts SOURCES_TESTS_C := $(wildcard src*/*_test.c src*/**/*_test.c) SOURCES_EXECS_C := $(wildcard src*/*_exec.c src*/**/*_exec.c) SOURCES_ALL_C := $(wildcard src*/*.c src*/**/*.c lib_*/*.c lib_*/**/*.c) SOURCES_C := $(filter-out $(SOURCES_TESTS_C),$(SOURCES_ALL_C)) SOURCES_C := $(filter-out $(SOURCES_EXECS_C),$(SOURCES_C)) SOURCES_TESTS_C += $(wildcard tests*/*.c tests*/**/*.c) SOURCES_EXECS_C += $(wildcard execs*/*.c execs*/**/*.c) ifeq ($(PR_LANG),CXX) SOURCES_TESTS_CXX := $(wildcard src*/*_test.cxx src*/**/*_test.cxx) SOURCES_EXECS_CXX := $(wildcard src*/*_exec.cxx src*/**/*_exec.cxx) SOURCES_ALL_CXX := $(wildcard src*/*.cxx src*/**/*.cxx lib_*/*.cxx lib_*/**/*.cxx) SOURCES_CXX := $(filter-out $(SOURCES_TESTS_CXX),$(SOURCES_ALL_CXX)) SOURCES_CXX := $(filter-out $(SOURCES_EXECS_CXX),$(SOURCES_CXX)) SOURCES_TESTS_CXX += $(wildcard tests*/*.cxx tests*/**/*.cxx) SOURCES_EXECS_CXX += $(wildcard execs*/*.cxx execs*/**/*.cxx) endif SOURCES_TESTS := $(SOURCES_TESTS_C) $(SOURCES_TESTS_CXX) SOURCES_EXECS := $(SOURCES_EXECS_C) $(SOURCES_EXECS_CXX) SOURCES_ALL := $(SOURCES_ALL_C) $(SOURCES_ALL_CXX) SOURCES := $(SOURCES_C) $(SOURCES_CXX) #$(info $(SOURCES_TESTS)) #$(info $(SOURCES_EXECS)) #$(info $(SOURCES_ALL)) #$(info $(SOURCES)) SOURCES_SCRIPTS ?= SOURCES_SCRIPTS += $(wildcard $(DIR_SCRIPTS_SRCS)/*.sh) SOURCES_VIM ?= SOURCES_VIM += $(wildcard vim_*/**/*.vim) # ex. 'manpage.1.man.t2t' where '1' is section number SOURCES_DOCS_MANS ?= SOURCES_DOCS_MANS += $(wildcard $(DIR_DOCS_SRCS)/*.man.t2t) SOURCES_DOCS_HTMLS ?= SOURCES_DOCS_HTMLS += $(wildcard $(DIR_DOCS_SRCS)/*.html.t2t) SOURCES_DOCS_MAINS ?= SOURCES_DOCS_MAINS += $(wildcard $(DIR_DOCS_SRCS)/*.main.t2t) SOURCES_DOCS_MDS ?= SOURCES_DOCS_MDS += $(wildcard $(DIR_DOCS_SRCS)/*.md) # TARGET FILES DIR_DOCS := doc DIR_BIN := .bin DIR_VIM := .vim DIR_PACK := .packages DIR_ANALYSE := .analyse ANALYZE_OUTPUT_FILE := static_analysis.txt TAR_TESTS := $(DIR_BIN)/$(PRNAME)_test TAR_LIBS := $(DIR_BIN)/$(PRNAME).a TAR_EXECS := $(DIR_BIN)/$(PRNAME) TAR_SCRIPTS := $(patsubst %.sh,$(DIR_BIN)/%,$(notdir $(SOURCES_SCRIPTS))) TAR_VIM_FILES := $(notdir $(SOURCES_VIM)) TAR_VIM_DIRS := $(notdir $(patsubst %/,%,$(dir $(SOURCES_VIM)))) TAR_VIM := $(addprefix $(DIR_VIM)/,$(SOURCES_VIM)) DOC_MANS := $(patsubst %.man.t2t,$(DIR_DOCS)/man/%.gz,$(notdir $(SOURCES_DOCS_MANS))) DOC_HTMLS := $(patsubst %.html.t2t,$(DIR_DOCS)/html/%.html,$(notdir $(SOURCES_DOCS_HTMLS))) DOC_MAINS := $(patsubst %.main.t2t,$(DIR_DOCS)/mains/%,$(notdir $(SOURCES_DOCS_MAINS))) DOC_MDS := $(patsubst %.md,$(DIR_DOCS)/md/%.md,$(notdir $(SOURCES_DOCS_MDS))) DOCS := $(DOC_MANS) $(DOC_HTMLS) $(DOC_MAINS) $(DOC_MDS) # --- BUILD OPTIONS --- ifeq ($(PR_LANG),C) CC = gcc STD_FLAGS := -std=c99 -pedantic else ifeq ($(PR_LANG),CXX) CC = /usr/bin/g++ STD_FLAGS := -std=c++11 -pedantic endif COMPILER := $(CC) -pipe #-fdiagnostics-color CPP_FLAGS := ARCH_FLAGS := -march=native -mtune=native OPTIMIZE_FLAGS := -fstrict-aliasing -Wdisabled-optimization -minline-all-stringops \ -funroll-loops -momit-leaf-frame-pointer #<C++>: -fstrict-enums WARN_FLAGS := -Wall -Wextra -Wshadow -Wwrite-strings -Wpointer-arith -Wcast-qual \ -Wcast-align -Wswitch-default -Wswitch-enum \ -Wstrict-overflow=2 -Wredundant-decls \ -Wlogical-op -Wfloat-equal -Wmissing-include-dirs #ev. -Wno-unused-parameter #ev. -Wno-unused-value WARN2_FLAGS := -Wundef -Wstrict-overflow=5 -Wconversion -Wunsuffixed-float-constants \ -Wdouble-promotion -Wunused -Wuninitialized -Winit-self -Wfloat-equal \ -Wbad-function-cast -Wjump-misses-init -Wpadded -Winline -Wformat=2 \ -Werror-implicit-function-declaration -Wunused-parameter -Wunused NOWARN_DEPL := -Wno-cast-qual -Wno-pedantic -Wno-unused-parameter ifeq ($(PR_LANG),C) WARN_FLAGS += -Wstrict-prototypes -Wnested-externs else ifeq ($(PR_LANG),CXX) WARN_FLAGS += -Wctor-dtor-privacy -Wnon-virtual-dtor -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Weffc++ endif TOOLS_FLAGS := -ggdb3 -pg DIAGNOSE_FLAGS := -fmem-report -fprofile-report -fstack-usage -ftest-coverage -Q \ -fdump-translation-unit -fdump-class-hierarchy -save-temps DBG_COMMON_FLAGS := -DDEBUG -fno-eliminate-unused-debug-types -ftrapv -fstack-check DBG_FLAGS := -O0 $(DBG_COMMON_FLAGS) $(TOOLS_FLAGS) $(WARN_FLAGS) DBG2_FLAGS := -O2 $(DBG_COMMON_FLAGS) $(TOOLS_FLAGS) $(WARN2_FLAGS) -DDEBUG2 DBG3_FLAGS := -O3 $(DBG_COMMON_FLAGS) $(TOOLS_FLAGS) $(WARN2_FLAGS) \ -fmudflap -Wno-nested-externs -fstack-protector-all -lmudflap # -fmudflap - check arrays/heap bounds ;needs special lib # -fmudflapth - check arrays/heap bounds for multi-th pr DEPL_FLAGS := -O3 -DNDEBUG $(WARN_FLAGS) $(NOWARN_DEPL) -fomit-frame-pointer -g TEST_FLAGS := -O3 -DDEBUG2 $(WARN_FLAGS) $(TOOLS_FLAGS) #-finline-functions - try inline all simple enough funs MSGS_FLAGS := -fmessage-length=0 -fmax-errors=10 #<C++>: -fno-pretty-templates # === TRANSITIONAL FILES === DIR_OBJS := .build DIR_DEPS := .deps DEPS := $(SOURCES:%.c=$(DIR_DEPS)/%.dep) DEPS_TESTS := $(SOURCES_TESTS:%.c=$(DIR_DEPS)/%.dep) DEPS_EXECS := $(SOURCES_EXECS:%.c=$(DIR_DEPS)/%.dep) OBJECTS := $(patsubst %.c,$(DIR_OBJS)/%.o,$(SOURCES)) OBJECTS_TESTS := $(patsubst %.c,$(DIR_OBJS)/%.o,$(SOURCES_TESTS)) OBJECTS_EXEC := $(patsubst %.c,$(DIR_OBJS)/%.o,$(SOURCES_EXECS)) ifeq ($(PR_LANG),CXX) DEPS := $(DEPS:%.cxx=$(DIR_DEPS)/%.dep) DEPS_TESTS := $(DEPS_TESTS:%.cxx=$(DIR_DEPS)/%.dep) DEPS_EXECS := $(DEPS_EXECS:%.cxx=$(DIR_DEPS)/%.dep) OBJECTS := $(patsubst %.cxx,$(DIR_OBJS)/%.o,$(OBJECTS)) OBJECTS_TESTS := $(patsubst %.cxx,$(DIR_OBJS)/%.o,$(OBJECTS_TESTS)) OBJECTS_EXEC := $(patsubst %.cxx,$(DIR_OBJS)/%.o,$(OBJECTS_EXECS)) endif #$(info $(OBJECTS)) #$(info $(OBJECTS_TESTS)) #$(error ABORT) SOURCES_DOCS := $(wildcard doc*/*.t2t) DIRS_INCLUDES := . $(wildcard src*) $(filter %/, $(wildcard src*/**/)) DIRS_INCLUDES += $(wildcard include*) $(filter %/, $(wildcard include*/**/)) DIRS_INCLUDES += $(wildcard lib_*) $(filter %/, $(wildcard lib_*/**/)) INCLUDES_OPTS := $(patsubst %,-I%,$(DIRS_INCLUDES)) LIBRARIES := $(wildcard lib/*.a) LIBRARIES := $(patsubst lib/lib%.a,-l%,$(LIBRARIES)) CPPFLAGS := $(CPP_FLAGS) $(INCLUDES_OPTS) CFLAGS := $(STD_FLAGS) $(ARCH_FLAGS) $(MSGS_FLAGS) $(OPTIMIZE_FLAGS) LFLAGS := -L./lib $(LIBRARIES) DIRS_CONCAT := $(DIR_BIN) $(DIR_OBJS) $(DIR_DEPS) $(DIR_DOCS) $(DIR_PACK) $(DIR_VIM) $(DIR_ANALYSE) # === TARGETS === # --- General targets --- all: depl docs # print help .PHONY: help help: @echo "make DESTDIR=/dir install - install to /dir (def. is /usr)" # createllibs hllibs: @BuildRecipes/mk_hllibs.sh "$(PR_LANG)" "$(PROJS_MAIN_DIR)" # --- Main targets --- debug: CFLAGS+=$(DBG_FLAGS) debug: OUT_REDIRECT := >diagnose.txt 2>&1 debug: prepare $(TAR_TESTS) debug2: CFLAGS+=$(DBG2_FLAGS) debug2: prepare $(TAR_TESTS) debug3: CFLAGS+=$(DBG3_FLAGS) debug3: prepare $(TAR_TESTS) diagnose: CFLAGS+=$(DBG_FLAGS) $(DIAGNOSE_FLAGS) diagnose: prepare $(TAR_TESTS) depl: CFLAGS+=$(DEPL_FLAGS) ifeq ($(TYPE),pr) depl: prepare $(TAR_EXECS) docs scripts vimscripts else depl: prepare $(TAR_LIBS) endif depl_test: CFLAGS+=$(TEST_FLAGS) ifeq ($(TYPE),pr) depl_test: prepare $(TAR_EXECS) docs scripts vimscripts else depl_test: prepare $(TAR_LIBS) endif docs: prepare $(DOCS) scripts: prepare $(TAR_SCRIPTS) vimscripts: prepare $(TAR_VIM) # --- Build targets --- .PHONY: prepare prepare: @mkdir -vp $(DIRS_CONCAT) $(DIR_OBJS)/%.o : %.c @echo doing $@ @mkdir -vp $(@D) @mkdir -vp $(@D:$(DIR_OBJS)/%=$(DIR_DEPS)/%) $(COMPILER) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) @echo -e "...> COMPILED $@\n\n\n" @$(COMPILER) -MM -MP -MT'$(@) $(DIR_DEPS)/$*.dep' $(CPPFLAGS) -o $(DIR_DEPS)/$*.dep $< $(DIR_OBJS)/%.o : %.cxx @echo doing $@ @mkdir -vp $(@D) @mkdir -vp $(@D:$(DIR_OBJS)/%=$(DIR_DEPS)/%) $(COMPILER) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) @echo -e "...> COMPILED $@\n\n\n" @$(COMPILER) -MM -MP -MT'$(@) $(DIR_DEPS)/$*.dep' $(CPPFLAGS) -o $(DIR_DEPS)/$*.dep $< # create object file together with depfile if *.c file changed: # . create directories: dirs chain for object file # $(@D) - directory part of target object file # . create directories: dirs chain for dependency file # $(@D:...) - substitute objects dir for deps dir # . compile source file that triggered recipe # @< - dependency source file that triggered recipe (:right) # $@ - target object file (left:) # . generate depfiles for created object file # $* - part of target that matches pattern (%) ;only in implicit rules # -M:generate dep rule for target (*.o) -MM:same but skip system headers in deps # -MP:create phony targets for *.h - prevents errors when headers missing and # it is still in old depfile (file will be overriden now with valid deps) # -MT:target pattern in rule - current target + current depfile (to make sure # its recreation when sources changed - it can mean that #incs changed) # Other special vars: # $^ - all dependencies -include $(DEPS) -include $(DEPS_TESTS) -include $(DEPS_EXECS) # include depfiles # evaluate each depfile and if contains rule to build itself and deps are #ne newer it would rebuild itself if we provide implicit rule for thie # (and we do not provide as recipe for building .o contains command to # generate depfile - .o and .dep have same dependencies) # succ: rerun this Makefile # + no rebuilding depfiles (timestamp changed) # + include redone depfile literally $(TAR_TESTS): $(OBJECTS) $(OBJECTS_TESTS) $(COMPILER) $^ -o $@ $(CFLAGS) $(LFLAGS) @echo -e ":::-> LINKED $@\n\n\n" # /\ create executable with tests: # . link object files into target # $(TAR_LIBS): $(OBJECTS) ar cr $@ $^ @echo -e ":::-> LIBRARY CREATED $@\n\n\n" # /\ create library: # . archive object files into library # $^ - all dependencies # $(TAR_EXECS): $(OBJECTS) $(OBJECTS_EXEC) $(COMPILER) $^ -o $@ $(CFLAGS) $(LFLAGS) @echo -e ":::-> LINKED $@\n\n\n" # /\ create executable: # . link object files into target # $(TAR_SCRIPTS): $(DIR_BIN)/% : $(DIR_SCRIPTS_SRCS)/%.sh \cp -va $< $@ && \chmod -v a+x $@ # $(TAR_VIM): $(DIR_VIM)/% : % @tar=$@; \ tar=$(DIR_VIM)/$${tar#$(DIR_VIM)/*/}; \ mkdir -vp $$(dirname $${tar}); \ cp -va $< $${tar} # create DOC_MANS + additional docs not destined for installation in system # $(DOC_MANS): $(DIR_DOCS)/man/%.gz : $(DIR_DOCS_SRCS)/%.man.t2t @mkdir -vp $(@D) && \ txt2tags -t man -o $(basename $@) $< && \ gzip -vf $(basename $@) T2T_HTML_OPTS := --toc $(DOC_HTMLS): $(DIR_DOCS)/html/%.html : $(DIR_DOCS_SRCS)/%.html.t2t @mkdir -vp $(@D) && \ txt2tags -t html $(T2T_HTML_OPTS) -o $@ $< $(DOC_MAINS): $(DIR_DOCS)/mains/% : $(DIR_DOCS_SRCS)/%.main.t2t @txt2tags -t txt -o $(notdir $@) $< $(DOC_MDS): $(SOURCES_DOCS_MDS) @mkdir -vp $(@D) && \ cp -va $< $@ # --- Packaging and Installing targets --- # create package .PHONY: pack pack: $(DOCS) @BuildRecipes/pack.sh $(VERSION) $(PACK_NAME) $(DIR_PACK) $(ARCH_BUNDLE) "$(FILES_TO_PACK)" # install/uninstall package .PHONY: install install: depl @[[ ! -z "$(DESTDIR)" ]] && mkdir -vp $(DESTDIR) || echo "" @mkdir -vp $(DESTDIR)$(bindir) @mkdir -vp $(DESTDIR)$(mandir)/man{1,2,3,4,5,6,7,8,9} @mkdir -vp $(DESTDIR)$(vimdatadir)/{plugin,syntax} @install -vm 0755 $(DIR_BIN)/* $(DESTDIR)$(bindir) @for f in $(DOC_MANS); do \ section=$${f%.gz}; \ section=$${section##*.}; \ install -vm 0644 $${f} $(DESTDIR)$(mandir)/man$${section}/; \ done; @for subdir in plugin syntax; do \ install -vm 0644 $(DIR_VIM)/$${subdir}/*.vim $(DESTDIR)$(vimdatadir)/$${subdir}/; \ done; @if [[ -d $(DESTDIR)$(vimdir) ]]; then \ for subdir in plugin syntax; do \ install -vm 0644 $(DIR_VIM)/$${subdir}/*.vim $(DESTDIR)$(vimdir)/$${subdir}/; \ done; \ else \ echo "Unable to find Vim system directory, for Vim support copy following files by hand:"; \ echo " $(DESTDIR)$(vimdatadir)/*/*.vim to Vim's plugin directory"; \ fi; .PHONY: uninstall uninstall: @for f in $(TAR_EXECS); do \ rm -vf $(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ done; @for f in $(TAR_SCRIPTS); do \ rm -vf $(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ done; @for f in $(DOC_MANS); do \ section=$${f%.gz}; \ section=$${section##*.}; \ rm -vf $(DESTDIR)$(mandir)/man$${section}/$$(basename $${f}); \ done; @for f in $(SOURCES_VIM); do \ rm -vf $(DESTDIR)$(vimdatadir)/$${f#*/}; \ done; @if [[ -d $(DESTDIR)$(vimdir) ]]; then \ rm -vf $(DESTDIR)$(vimdir)/$${f#*/}; \ fi; .PHONY: isinstalled isinstalled: @for f in $(TAR_EXECS); do \ fname=$(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @for f in $(TAR_SCRIPTS); do \ fname=$(DESTDIR)$(bindir)/$${f#$(DIR_BIN)/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @for f in $(DOC_MANS); do \ section=$${f%.gz}; \ section=$${section##*.}; \ fname=$(DESTDIR)$(mandir)/man$${section}/$$(basename $${f}); \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @for f in $(SOURCES_VIM); do \ fname=$(DESTDIR)$(vimdatadir)/$${f#*/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ done; @if [[ -d $(DESTDIR)$(vimdir) ]]; then \ fname=$(DESTDIR)$(vimdir)/$${f#*/}; \ [[ -f $${fname} ]] && echo "$${fname} OK" || echo "$${fname} not present"; \ fi; # --- Auxillary targets --- # + Run tests + .PHONY: runt runt: @$(TAR_TESTS) .PHONY: runt debugr: debug @echo -e ":: Make: running tests now\n\n" @$(TAR_TESTS) .PHONY: vrunt vrunt: @f=$(DIR_ANALYSE)/val_$$(date +%T).txt; \ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --num-callers=40 --track-fds=yes --error-limit=yes --log-file=$${f} $(TAR_TESTS); \ cat $${f}; .PHONY: vrunts vrunts: @f=$(DIR_ANALYSE)/val_$$(date +%T).txt; \ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --num-callers=40 --track-fds=yes --error-limit=yes --log-file=$${f} $(TAR_TESTS) s; \ cat $${f}; # + Fossil info + .PHONY: fosinf fosinf: @fossil status && \ echo -e "\n:: TIMELINE:" && fossil timeline && \ echo -e "\n:: INFO:" && fossil info && \ echo -en "\n:: BRANCH: " && fossil branch # + Gcc info + # see what settings GCC uses .PHONY: gcc-test gcc-test: @gcc $(CPPFLAGS) $(CFLAGS) -E -v - </dev/null 2>&1 # see options only .PHONY: gcc-opts gcc-opts: @gcc $(CPPFLAGS) $(CFLAGS) -E -v - </dev/null 2>&1 | grep cc1 # see arch options .PHONY: gcc-arch gcc-arch: @gcc $(ARCH_FLAGS) -E -v - </dev/null 2>&1 | grep cc1 # --- Code analysis --- # create cpp files from sources .PHONY: cpp cpp: @for file in $(SOURCES); do \ $(COMPILER) -E -C $${file} -o $${file}.cpp $(CPPFLAGS) $(CFLAGS);\ done .PHONY: analyze analyze: @date >> $(ANALYZE_OUTPUT_FILE) @echo -e "==============\n\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @make dist-clean > /dev/null @make debug CC="scan-build gcc" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @flawfinder $(SOURCES) >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "RATS ::" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @rats $(SOURCES) >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 @splint $(DIRS_INCLUDES) $(SOURCES) >> $(ANALYZE_OUTPUT_FILE) 2>&1 @echo -e "\n\t--------------\n\n\n" >> $(ANALYZE_OUTPUT_FILE) 2>&1 .PHONY: compile_headers compile_headers: @for dir in $(DIRS_INCLUDES); do \ for file in $${dir}/*.h; do \ if [ $${file} == "./*.h" ]; then continue; fi; \ filec=$${file}.c; \ echo "compiling header: $${file}"; \ echo "#include \"$${file}\"" > $${filec}; \ $(COMPILER) -c $${filec} -o /dev/null $(CPPFLAGS) $(CFLAGS); \ \rm -v $${filec}; \ done \ done .PHONY: headers_tree headers_tree: @for file in $(SOURCES); do \ echo -e "\ntree for file: $${file}"; \ $(COMPILER) -c -H $${file} $(CPPFLAGS) $(CFLAGS); \ done # --- Cleanup targets --- # remove all not-project files and dirs .PHONY: dist-clean dist-clean: clean-objs clean-tool clean-deps clean-bins clean-dirs @\rm -vrf $(ANALYZE_OUTPUT_FILE) # remove all not-project files .PHONY: clean clean: clean-objs clean-tool clean-deps # remove object files .PHONY: clean-objs clean-objs: @\rm -vrf $(TAR_TESTS) $(TAR_LIBS) $(TAR_EXECS) $(TAR_SCRIPTS) $(DOCS) $(DIR_OBJS)/*.o $(DIR_OBJS)/**/*.o # remove tool files .PHONY: clean-tool clean-tool: @\rm -vrf $(TAR_TESTS) $(TAR_LIBS) $(TAR_EXECS) $(TAR_SCRIPTS) $(DOCS) $(DIR_OBJS)/{*.gcno,*.su,*.tu} \ $(DIR_OBJS)/**/{*.gcno,*.su,*.tu} \ src*/*.cpp src*/**/*.cpp \ *.i *.s gmon.out # remove depfiles .PHONY: clean-deps clean-deps: @\rm -vrf $(DIR_DEPS)/*.dep $(DIR_DEPS)/**/*.dep # remove executables .PHONY: clean-bins clean-bins: @\rm -vrf $(DIR_BIN)/* # remove all not-project dirs with contents .PHONY: clean-dirs clean-dirs: @\rm -vrf $(DIRS_CONCAT) ### REMAINDERS: # create implicit rule for creating depfiles #%.dep : %.c #$(MAKEDEPEND) |
Added NAME.
> |
1 |
manex
|
Added VERSION.
> > > |
1 2 3 |
#define VER_MAJOR 0 #define VER_MINOR 1 #define VER_PATCH 0 |
Added lib_base/Debug.cxx.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
/*!F::Debugging facilities - main implementation file. * * ::Purpose: * Detect and inform about bugs in code. Bugs are considered distinct from * standard errors - they are programmer mistakes, mainly in program logic. * To deal with other errors (system, user etc.) see other facilities. * * ::Goals: * - thread-safe, reentrant, portable (POSIX systems) * - buffer/integer overflow safe * * ::Properties: * compiler options: -std=c++11 * thread safe * * ::Limitations: * - should have type indicating what is the cause: assert, parameter, * sentinel etc. * * ::Other: * File: This file is part of program distributed under GNU General Public License. * For terms of distribution, warranty and licensing see README file. * Created: 2014-08-12 * (c) Copyright: Maciej Helminiak 2014 * License: GNU General Public License, version 3 * Copy of the license is distributed along with this program * or can be seen at <http://www.gnu.org/licenses/> */ /* snprintf(), vsnprintf(): _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L; or cc -std=c99 asctime_r(), ctime_r(), gmtime_r(), localtime_r(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE */ #define _POSIX_C_SOURCE 200809L /* current project */ /* mh library */ #include "core.hh" /* libc */ #include <cstdarg> // vsnprintf() #include <ctime> // time(), localtime() etc. /* libc++ */ /* current module */ #include "Debug.hh" /* implementation for classes declared in this namespace: */ using namespace ERRORS_HANDLING; using namespace ERRORS_HANDLING::__impl__; /* --------------------------------------------------- st_abort ---- */ /*!:: Construct aborter with given attributes. * Takes information describing place and reason of abort request. */ st_abort::st_abort ( const char* file, //! file name where abort has been created const char* func, //! function name int line, //! line number const char* fmt, //! reason ;printf-like format ... //! reason ;printf-like data list ) : _file{file}, _func{func}, _line{line}, _reason{'\0'}, _time{'\0'} { ___Dassert(file != NULL && file[0] != '\0'); ___Dassert(func != NULL && func[0] != '\0'); ___Dassert(line > 0); ___Dassert(fmt != NULL); /*: Compose reason cstring: */ va_list ap; va_start(ap, fmt); vsnprintf(_reason, REASON_MAX_BYTES, fmt, ap); va_end(ap); /*: Create time cstring: */ time_t t = time(NULL); // simple time - since epoch struct tm stT; // broken-down time localtime_r(&t, &stT); strftime(_time, TIME_MAX_BYTES, "%Y-%m-%d %a %H:%M:%S", &stT); } /*!:: Write information about abort request to given file stream. Information * is formatted in consistent and concise manner. */ void st_abort::report_info ( FILE* fs ){ ___Dassert(fs != NULL); fprintf(fs, ":: ABORT REQUESTED:\n %s\n %s : %s() :%d:\n %s\n", _time, _file, _func, _line, _reason); } /* --------------------------------------------------- st_abort ---- */ |
Added lib_base/Debug.hh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
#ifndef MHLIB_BASE_SRCCORE_DEBUG_HH #define MHLIB_BASE_SRCCORE_DEBUG_HH /*!F::Debugging facilities - external interface file. * * ::Provides class definitions, routines declarations and macro definitions. */ #include "core.hh" namespace ERRORS_HANDLING { namespace __impl__ { /* =================================================================== */ /* ----------------------------------------------------- st_abort ---- */ /*!:: Object of this type (called aborter) is intended to be thrown as exception * when program is making abort request (issued by error checking routine or * assertion or in other situations). * * ::Usage: * . Throw instance as exception, catch it where appropriate * . Outer code is responsible for catching and performing appropriate action. * . Intended to be used by assertion routines. * . see Assertion routines below. * * ::Note: * All members are public intentionally, subject to change in the future */ struct st_abort { /*- ...... FUNDAMENTALS ...... -*/ st_abort (const char* file, const char* func, int line, const char* fmt, ...); /*- deleted -*/ st_abort () = delete; /*- ...... INTERFACE ...... -*/ void report_info (FILE* fs); /*- ...... DATA ...... -*/ static constexpr const uint REASON_MAX_BYTES = 1024; static constexpr const uint TIME_MAX_BYTES = 128; const char* _file; //! file name of abort request origin const char* _func; //! function name int _line; //! line number char _reason[REASON_MAX_BYTES]; //! reason char _time[TIME_MAX_BYTES]; //! time of request }; /* ----------------------------------------------------- st_abort ---- */ /* =================================================================== */ } /*- STUFF TO BE USED BY OUTSIDE PARTIES -*/ using __impl__::st_abort; } /*!:: Assertion routines. * * ::1 Assert condition. * ::2 Indicate execution of code that should not be reached. * ::3 Assert function parameter. * ::4 Assert internal function state. * ::5 Assert function return expression. */ /* =================================================================== */ #ifdef DEBUG #define ___Dassert(Cond) do { if(!(Cond)) { throw ERRORS_HANDLING::st_abort(__FILE__, __func__, __LINE__, "assertion failed: '"#Cond"'"); } } while(0) #define ___Dsentinel(...) do { throw ERRORS_HANDLING::st_abort(__FILE__, __func__, __LINE__, __VA_ARGS__); } while(0) #define ___Dparam(Cond) do { if(!(Cond)) { throw ERRORS_HANDLING::st_abort(__FILE__, __func__, __LINE__, "'"#Cond"' parameter invalid"); } } while(0) #define ___Dinter(Cond) do { if(!(Cond)) { throw ERRORS_HANDLING::st_abort(__FILE__, __func__, __LINE__, "'"#Cond"' internal check failed"); } } while(0) #define ___Dreturn(Cond) do { if(!(Cond)) { throw ERRORS_HANDLING::st_abort(__FILE__, __func__, __LINE__, "'"#Cond"' return expression invalid"); } } while(0) #else #define ___Dassert(...) #define ___Dsentinel(...) #define ___Dparam(...) #define ___Dinter(...) #define ___Dreturn(...) #endif /*- DEBUG -*/ /* =================================================================== */ #endif /*- MHLIB_BASE_SRCCORE_DEBUG_HH -*/ |
Added lib_base/Exception.cxx.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 |
#include "core.hh" #include "errors.h" #include "Debug.hh" #include "Exception.hh" #include <cstdio> #include <cstring> /*!:: Exception object instance. * :: Used by Exception throwing, catching and handling routines. * Created in thread local storage. */ __tls__ ERRORS_HANDLING::cl_exception __exc__; /* implementation for classes declared in this namespace: */ using namespace ERRORS_HANDLING; using namespace ERRORS_HANDLING::__impl__; /* ---------------------------------------------------- excnum_en ---- */ constexpr const char* const excnum_en::_Labels[count-ERR_START_NUMBER+1]; constexpr const char* const excnum_en::_Descrs[count-ERR_START_NUMBER+1]; /*- ...... FUNDAMENTALS ...... -*/ /*!:: Construct with enum constant value. */ excnum_en::excnum_en ( val_en val //! excnum_en constant ) : _val{val} { ___Dparam(val >= None && val < count); } /*!:: Construct with default value. */ excnum_en::excnum_en () { } /*!:: Construct with 'errno' constant value. */ excnum_en::excnum_en ( int val //! errno constant ) : _val{static_cast<val_en>(val)} { ___Dparam(val >= 0 && val < count); } /*!:: Allows cast to 'int' (excnum_en -> int). * Used to convert 'excnum_en' to 'errno' value. */ excnum_en::operator int() const { ___Dreturn(_val >= 0 && _val < count); return _val; } /*!:: Copy-constructor. */ excnum_en::excnum_en ( const excnum_en& obj //! copied object ) : _val{obj._val} { } /*!:: Assignment. */ excnum_en& excnum_en::operator= ( const excnum_en& robj //! assigned object ){ _val = robj._val; return *this; } /*- ...... INTERFACE ...... -*/ /*!:: Return label of enum constant currently hold. */ const char* excnum_en::label () const { return _label(); } /*!:: Return description of enum constant currently hold. */ const char* excnum_en::descr () const { return _descr(); } /*!:: Return label of enum constant given as parameter. */ const char* excnum_en::label ( const excnum_en& e //! excnum_en or errno constant ){ return e._label(); } /*!:: Return description of enum constant given as parameter. */ const char* excnum_en::descr ( const excnum_en& e //! excnum_en or errno constant ){ return e._descr(); } /*- ...... INTERNAL ROUTINES ...... -*/ const char* excnum_en::_label () const { /* error in range of errno values defined in libc */ if (_val < ERR_START_NUMBER) { ___Dinter(_val >= 0); return ""; } /* error type defined outside libc */ else { ___Dinter(_val >= None && _val < count); return _Labels[_val-ERR_START_NUMBER]; } } const char* excnum_en::_descr () const { /* error in range of errno values defined in libc */ if (_val < ERR_START_NUMBER) { ___Dinter(_val >= 0); return strerror(_val); } /* error type defined outside libc */ else { ___Dinter(_val >= None && _val < count); return _Descrs[_val-ERR_START_NUMBER]; } } /* ---------------------------------------------------- excnum_en ---- */ /* ------------------------------------------------- cl_exc_trace ---- */ /*- ...... INTERFACE ...... -*/ /*!:: Record location of exception origin. */ void cl_exc_trace::origin_stamp ( const char* file, //! file where exception occured const char* func, //! function name ulong line //! line number ){ ___Dparam(file != NULL); ___Dparam(func != NULL); _Origin._cs_file = file; _Origin._cs_func = func; _Origin._line = line; } /*!:: Record location of 'catch' block passed by exception. */ void cl_exc_trace::app_midway_stamp ( const char* file, //! file where exception occured const char* func, //! function name ulong line //! line number ){ ___Dparam(file != NULL); ___Dparam(func != NULL); ___Dinter(_used_stamps < STAMPS_MAX_NUM); _Stamps[_used_stamps]._cs_file = file; _Stamps[_used_stamps]._cs_func = func; _Stamps[_used_stamps]._line = line; ++_used_stamps; ___Dreturn(_used_stamps <= STAMPS_MAX_NUM); } /*!:: Record location of last 'catch' block. */ void cl_exc_trace::term_stamp ( const char* file, //! file where exception occured const char* func, //! function name ulong line //! line number ){ ___Dparam(file != NULL); ___Dparam(func != NULL); _Term._cs_file = file; _Term._cs_func = func; _Term._line = line; } const cl_exc_trace::st_stamp& cl_exc_trace::ret_origin_stamp () const { return _Origin; } const cl_exc_trace::st_stamp& cl_exc_trace::ret_midway_stamp ( uint idx //! index of record of location ) const { ___Dparam(idx < _used_stamps); return _Stamps[idx]; } const cl_exc_trace::st_stamp& cl_exc_trace::ret_term_stamp () const { return _Term; } uint cl_exc_trace::used_stamps () const { return _used_stamps; } /* ------------------------------------------------- cl_exc_trace ---- */ /* ------------------------------------------------- cl_exception ---- */ constexpr const char* const cl_exception::FILE_DEF; constexpr const char* const cl_exception::FUNC_DEF; constexpr const ulong cl_exception::LINE_DEF; constexpr const char* const cl_exception::DESCR_DEF; constexpr const int cl_exception::ARB_VAL_DEF; /*- ...... FUNDAMENTALS ...... -*/ /*!:: Construct with custom attributes. */ cl_exception::cl_exception ( const char* subj, //! subject excnum_en errnum, //! error number const char* descr, //! description of error const char* file, //! file where exception occured (location of origin) const char* func, //! function name ulong line, //! line number int arb_val //! arbitrary value for user use ) : _arb_val{arb_val}, _cs_subj{subj}, _errnum{errnum}, _cs_descr{descr}, _C_error{NULL} { ___Dparam(subj != NULL); ___Dparam(descr != NULL); ___Dparam(file != NULL); ___Dparam(func != NULL); _Trace.origin_stamp(file, func, line); } /*!:: Construct with given custom attributes, remaining attributes are default. */ cl_exception::cl_exception ( const char* subj, //! subject excnum_en errnum, //! error number const char* file, //! file where exception occured (location of origin) const char* func, //! function name ulong line, //! line number int arb_val //! arbitrary value for user use ) : cl_exception(subj, errnum, DESCR_DEF, file, func, line, arb_val) { ___Dparam(subj != NULL); ___Dparam(file != NULL); ___Dparam(func != NULL); } /*!:: Construct with given attributes custom, remaining attributes are default. */ cl_exception::cl_exception ( const char* subj, //! subject excnum_en errnum, //! error number const char* descr, //! description of error const char* file, //! file where exception occured (location of origin) const char* func, //! function name ulong line //! line number ) : cl_exception(subj, errnum, descr, file, func, line, ARB_VAL_DEF) { ___Dparam(subj != NULL); ___Dparam(descr != NULL); ___Dparam(file != NULL); ___Dparam(func != NULL); } /*!:: Construct with given attributes custom, remaining attributes are default. */ cl_exception::cl_exception ( const char* subj, //! subject excnum_en errnum, //! error number const char* file, //! file where exception occured (location of origin) const char* func, //! function name ulong line //! line number ) : cl_exception(subj, errnum, DESCR_DEF, file, func, line, ARB_VAL_DEF) { ___Dparam(subj != NULL); ___Dparam(file != NULL); ___Dparam(func != NULL); } /*!:: Construct with default attributes. */ cl_exception::cl_exception ( ) : cl_exception(SUBJ_DEF, excnum_en(), FILE_DEF, FUNC_DEF, LINE_DEF) { } /*!:: Construct with attributes figured from C error. */ cl_exception::cl_exception ( const st_mh_error& c_error ) : cl_exception() { setup(c_error); } cl_exception::~cl_exception() {} /*- ...... INTERFACE ...... -*/ /*!:: Set exception attributes. */ void cl_exception::setup ( const char* subj, //! subject excnum_en errnum, //! error number const char* descr, //! description of error const char* file, //! file where exception occured (location of origin) const char* func, //! function name ulong line, //! line number int arb_val //! arbitrary value for user use ){ ___Dparam(subj != NULL); ___Dparam(descr != NULL); ___Dparam(file != NULL); ___Dparam(func != NULL); first_stamp(file, func, line); _cs_subj = subj; _errnum = errnum; _cs_descr = descr; _arb_val = arb_val; } /*!:: Set exception attributes figured from C error. */ void cl_exception::setup ( const st_mh_error& c_error ){ setup("C routine", errno, c_error.msg, "", "", 0, static_cast<int>(c_error.aux)); _C_error = &c_error; } /*!:: Record location of origin. */ void cl_exception::first_stamp ( const char* file, //! file where exception occured const char* func, //! function name ulong line //! line number ){ ___Dparam(file != NULL); ___Dparam(func != NULL); _Trace.origin_stamp(file, func, line); } /*!:: Record location of 'catch' block on exception way. */ void cl_exception::app_stamp ( const char* file, //! file where exception occured const char* func, //! function name ulong line //! line number ){ ___Dparam(file != NULL); ___Dparam(func != NULL); /*: Silently ingore stamp if their max quantity reached: */ if (_Trace.used_stamps() >= cl_exc_trace::STAMPS_MAX_NUM) { return; } /*: Append stamp: */ _Trace.app_midway_stamp(file, func, line); return; } /*!:: Record location of last 'catch' block. */ void cl_exception::last_stamp ( const char* file, //! file where exception occured const char* func, //! function name ulong line //! line number ){ ___Dparam(file != NULL); ___Dparam(func != NULL); _Trace.term_stamp(file, func, line); } /*!:: Print information about exception in consistent and concise manner. */ void cl_exception::report_info ( FILE* fs //! destination ){ ___Dparam(fs != NULL); const char* sep = STAMPS_SEP; /*: Location of origin: */ if (_C_error == NULL) { const cl_exc_trace::st_stamp& StampO = _Trace.ret_origin_stamp(); fprintf(fs, "TRACE: %s:(%s):%lu", StampO._cs_file, StampO._cs_func, StampO._line); } else { //: Error originated from C routine: fprintf(fs, "TRACE: %s%s%s", _C_error->sig, sep, _C_error->trace); } /*: Visited 'catch' blocks: */ for (uint i = 0; i < _Trace.used_stamps(); ++i) { const cl_exc_trace::st_stamp& Stamp = _Trace.ret_midway_stamp(i); fprintf(fs, "%s%s:(%s):%lu", sep, Stamp._cs_file, Stamp._cs_func, Stamp._line); } /*: Last 'catch' block: */ const cl_exc_trace::st_stamp& Stamp = _Trace.ret_term_stamp(); if (Stamp._line != 0) { fprintf(fs, "%s%s:(%s):%lu", sep, Stamp._cs_file, Stamp._cs_func, Stamp._line); } /*: Other attributes: */ fprintf(fs, "\nSUBJ: %s\nERROR: %s [%d]\nDESCR: %s\n", _cs_subj, _errnum.descr(), static_cast<int>(_errnum), _cs_descr); } /*!:: Print information about exception in descriptive way. */ void cl_exception::present_info ( FILE* fs //! destination ){ ___Dparam(fs != NULL); const char* sep = STAMPS_SEP; /*: Type of error and subject: */ fprintf(fs, "%s [%d] in %s at ", _errnum.descr(), static_cast<int>(_errnum), _cs_subj); /*: Location of origin: */ if (_C_error == NULL) { const cl_exc_trace::st_stamp& StampO = _Trace.ret_origin_stamp(); fprintf(fs, "%s:(%s):%lu", StampO._cs_file, StampO._cs_func, StampO._line); } else { //: Error originated from C routine: fprintf(fs, "%s%s%s", _C_error->sig, sep, _C_error->trace); } /*: Visited 'catch' blocks: */ for (uint i = 0; i < _Trace.used_stamps(); ++i) { const cl_exc_trace::st_stamp& Stamp = _Trace.ret_midway_stamp(i); fprintf(fs, "%s%s:(%s):%lu", sep, Stamp._cs_file, Stamp._cs_func, Stamp._line); } /*: Last 'catch' block: */ const cl_exc_trace::st_stamp& Stamp = _Trace.ret_term_stamp(); if (Stamp._line != 0) { fprintf(fs, "%s%s:(%s):%lu", sep, Stamp._cs_file, Stamp._cs_func, Stamp._line); } /*: Error description: */ fprintf(fs, "\n%s\n", _cs_descr); } /* ------------------------------------------------- cl_exception ---- */ /* CONCEPTS --------------------------------------------------- EXCEPTIONS OVERHEAD: - modern policy: try-catch: NONE, throw: HIGH (separate table with handling routines) + MORE MEMORY - old policy: try-catch: HIGH (pushed onto stack), throw: LOW FAILURE ORIGIN: [System] [Pr-Developer] [Pr-Client] [User] Fatal, Error, Warn, Info, Debug FAILURE CATHEGORIES: Syntactic Error - compiler detects Semantic Error - prevents fun from succeeding by not: . meeting calees precondition (ex. param) . achieve own postcondition (ex. valid ret val) . reestablish shared maintained invariant => exception / assert fatal - external fatal circumstances ;nomem, thread abort can't prevent, can't cleanup => exception: fail fast external- external retriable circumstances ;file non-exist, unsufficient perms can't prevent, cleanup possible => normal flow: retry/inform, continue logic - code design fault ;wrong input format preventable, cleanup possible => exception: fail fast bug - programmer fault ;NULL param, bad cast, index overflow, div by 0, > instead of >= preventable, cleanup possible => assert: abort fast Other - expected outcome: fun succeeded but result means failure . no char in str found . obj is not type T => code/ret_Val/errno etc. HANDLE WAYS: internal - handled in fun other - report to caller abort, exit, retry, ignore GUARANTEES: GUARANT THAT none - bug basic - pr in valid state: no leaks, invariants preserved, state may be different strong - consistent state: original (operation rolled back) OR target (commited) nofail/nothrow - can't fail, Excepts handled internally ;destr, dealloc-funs, swap-funs + Provide strongest guarantee function can. + Guarantee can not penalize code that do not need it. + Guarantee can penalize code using fun only if code states that it needs this guarantee. SPECIAL CASES: constructor: cant create obj =>Except (obj's lifetime never began) destructor / deallocation funs: except-emmiting code on side and when succeeded modify pr state with non-throwing ops operators: no place for error-params or ret-error, only errno-like approach if no exceptions ASSURANCES: precondition - condition before fun call (param) postcondition - condition after call (ret val) invariant - state of pr/class/fun that must be true all the time SYNTAX --------------------------------------------------- unwinding stack: immediate catch / return+caller catch / propagate further / main() / ev. uncaught:terminate catch: execute catch code + continue execution after catch {} try { throw VALUE } catch (DERIVED&) { cerr << "Error"; } catch (BASE&) { cerr << "Error"; } catch (T& OBJ) { cerr << "Error: " << OBJ; throw; == throw OBJ; //rethrow exception } catch (...) { //empty block - ignore exception } catch (T& ) { } == catch(T& obj) { throw; } Fun() try //function-try-block : a(0) { BODY } catch(...) { HANDLE_EXC } exc specifiers: void Fun() throw(T1,T2) / throw(...) / throw() //may throw: types / unspecified exc / none std::exception : bad_alloc / bad_cast / runtime_error ... { what() }; PROPER USE --------------------------------------------------- throw obj catch ref& class Base { virtual void raise() { throw *this; } class Deriv { virtual void raise() { throw *this; } void f(Base& e) { e.raise(); } Deriv e; try { f(e); } catch (Base& e) { } //throw polymorphically try { AQUIRE_RES(var); RELEASE(var); } catch(...) { RELEASE(var); } //var needs to be in both scopes ptr = NULL; try { ptr = new K; delete ptr; } catch(...) { delete ptr; } //ptr needs to be in both scopes try { p = new K; auto_ptr<K> xp(p); } catch(...) { } //auto_ptr delete holded ptr when out of scope <memory> try { K obj; } catch(...) { } //destr called when out of scope K obj; obj.action(); obj.commit(); //commit makes destructor not to undo operation constr { NO if STATIC INSTANCES //standard says: cannot catch Exc from static obj destr { NEVER //exc during stack unwinding terminates program class OwnException { OwnException() OwnException(string) OwnException(string, OwnException) ALWAYS COPY-CONSTR ENHANCEMENTS --------------------------------------------------- <execinfo.h> <GNU> exc_constr { void* buf[25]; int size = backtrace(buf, 25); //series of return addresses of frames on stack (active function calls), newest first char** symbols = backtrace_symbols(buf, size); //array of strs describing frame addresses symbolically for (0 TO size) { cout << symbols[i]; } // fun_name + offset into fun + ret addr free(symbols); SCOPE GUARDS SGImplBase { protected: mutable bool _dismissed; public: void Dismiss() { _dismissed = true; } SGImplBase() : _dismissed(false) {} SGImplBase(const SGImplBase& obj) : _dismissed(obj._dismissed) { obj.Dismiss(); } ~SGImplBase() {} private: operator= }; template <typename FUN, typename PARM> class SGImpl1 : public SGImplBase { private: FUN _f; PARM _p; public: SGImpl1 (const FUN& f, const PARM& p) : _f(f), _p(p) {} ~SGImpl1() { if (!_dismissed) _f(_p); } template <typename FUN, typename PARM> SGImpl1<FUN, PARM> MakeGuard (const FUN& f, const PARM& p) { return SGImpl1<FUN, PARM>(f, p); } typedef const SGImplBase& ScopeGuard; { OPERATION1 ScopeGuard g1 = MakeObjGuard(obj, &Klasa::reverting_method); //auto call given meth in destructor on object OPERATION2 //throw => obj.reverting_method() ScopeGuard g2 = MakeGuard(fun, var); //auto call given fun in destructor with variable OPERATION3 //throw => fun(var) g1.Dismiss(); //disable above g2.Dismiss(); //disable above } */ |
Added lib_base/Exception.hh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
#ifndef MHLIB_BASE_SRCCORE_EXCEPTION_HH #define MHLIB_BASE_SRCCORE_EXCEPTION_HH #include "core.hh" #include "errors.h" #include <exception> namespace ERRORS_HANDLING { namespace __impl__ { /* =================================================================== */ /* ---------------------------------------------------- excnum_en ---- */ /*!:: Type of error (exception). * Defines error type labels and descriptions too. * * ::Note: * Auxillary for exception class. Not intended for stand-alone use. */ struct excnum_en { /*- ...... SPECIAL ...... -*/ /* Macros for compile-time creation of eumeration constants and their labels and descriptions. Everything in sync. */ #define MH_ERR_START_NUMBER 4096 #undef MH_ENUM_CREATE #undef MH_ENUM_CREATE_N #undef MH_ENUM_CONSTANTS #define MH_ENUM_CONSTANTS \ MH_ENUM_CREATE_N(None, "No error", MH_ERR_START_NUMBER), \ MH_ENUM_CREATE(OverflowInt, "Integer overflow"), \ MH_ENUM_CREATE(OverflowBuf, "Buffer overflow"), \ MH_ENUM_CREATE(StateWrong, "Wrong state"), \ MH_ENUM_CREATE(BadParam, "Bad parameter"), \ MH_ENUM_CREATE(LenExc, "Length exceeded"), \ MH_ENUM_CREATE(Custom, "Custom error"), \ MH_ENUM_CREATE(All, "All errors"), \ MH_ENUM_CREATE(Unknown, "Unknown error") \ /*- ...... TYPES ...... -*/ public: enum val_en : int { #undef MH_ENUM_CREATE #undef MH_ENUM_CREATE_N #define MH_ENUM_CREATE(CONST, DESCR) CONST #define MH_ENUM_CREATE_N(CONST, DESCR, VAL) CONST=VAL MH_ENUM_CONSTANTS, count }; /*- ...... FUNDAMENTALS ...... -*/ public: excnum_en (); excnum_en (val_en val); excnum_en (int val); operator int() const; excnum_en (const excnum_en& obj); excnum_en& operator= (const excnum_en& robj); /*- .. deleted.. -*/ template<typename T> operator T () const = delete; /*- ...... INTERFACE ...... -*/ public: const char* label () const; const char* descr () const; static const char* label (const excnum_en& e); static const char* descr (const excnum_en& e); /*- ...... DATA ...... -*/ private: static const int ERR_START_NUMBER = MH_ERR_START_NUMBER; //! first custom error number val_en _val = Unknown; //! enum value static constexpr const char* const _Labels[count-ERR_START_NUMBER+1] = { #undef MH_ENUM_CREATE #undef MH_ENUM_CREATE_N #define MH_ENUM_CREATE(CONST, DESCR) #CONST #define MH_ENUM_CREATE_N(CONST, DESCR, VAL) #CONST MH_ENUM_CONSTANTS }; //! array of labels of enum constants static constexpr const char* const _Descrs[count-ERR_START_NUMBER+1] = { #undef MH_ENUM_CREATE #undef MH_ENUM_CREATE_N #define MH_ENUM_CREATE(CONST, DESCR) DESCR #define MH_ENUM_CREATE_N(CONST, DESCR, VAL) DESCR MH_ENUM_CONSTANTS }; //! array of descriptions of enum constants /*- ...... INTERNAL ROUTINES ...... -*/ private: const char* _label () const; const char* _descr () const; friend class errnum_TEST_en; }; /* ---------------------------------------------------- excnum_en ---- */ /* ------------------------------------------------- cl_exc_trace ---- */ /*!:: Exception trace. * Allows tracking of exception throw location and way through 'catch()' * blocks. * * ::Note: * Auxillary for exception class. Not intended for stand-alone use. */ class cl_exc_trace { /*- ...... TYPES ...... -*/ protected: struct st_stamp { st_stamp () : _cs_file{NULL}, _cs_func{NULL}, _line{0} {} const char* _cs_file; //! file name const char* _cs_func; //! function name ulong _line; //! line number }; /*- ...... INTERFACE ...... -*/ protected: void origin_stamp (const char* file, const char* func, ulong line); void app_midway_stamp (const char* file, const char* func, ulong line); void term_stamp (const char* file, const char* func, ulong line); const st_stamp& ret_origin_stamp () const; const st_stamp& ret_midway_stamp (uint idx) const; const st_stamp& ret_term_stamp () const; uint used_stamps () const; /*- ...... DATA ...... -*/ protected: static const uint STAMPS_MAX_NUM = 128; private: st_stamp _Origin = {}; //! first stamp st_stamp _Stamps[STAMPS_MAX_NUM]; //! stamps between uint _used_stamps = 0; //! number of stamps used in '_Stamps' st_stamp _Term = {}; //! last stamp /*- ...... Friends ...... -*/ friend class cl_exception; friend class cl_exc_trace_TEST; }; /* ------------------------------------------------- cl_exc_trace ---- */ /* ------------------------------------------------- cl_exception ---- */ /*!:: Exception. * Create object with specified exception attributes. * Record location of origin and all places where it is caught. * Print exception information. */ class cl_exception : public std::exception { /*- ...... FUNDAMENTALS ...... -*/ public: /* `descr` and `arb_val` are not necessary. */ cl_exception (const char* subj, excnum_en errnum, const char* descr, const char* file, const char* func, ulong line, int arb_val); cl_exception (const char* subj, excnum_en errnum, const char* file, const char* func, ulong line, int arb_val); cl_exception (const char* subj, excnum_en errnum, const char* descr, const char* file, const char* func, ulong line); cl_exception (const char* subj, excnum_en errnum, const char* file, const char* func, ulong line); cl_exception (); cl_exception (const st_mh_error& c_error); virtual ~cl_exception(); /*- .. deleted.. -*/ cl_exception& operator= (const cl_exception&) = delete; /*- ...... INTERFACE ...... -*/ public: virtual void setup (const char* subj, excnum_en errnum, const char* descr, const char* file, const char* func, ulong line, int arb_val); virtual void setup (const st_mh_error& c_error); virtual void first_stamp (const char* file, const char* func, ulong line); virtual void app_stamp (const char* file, const char* func, ulong line); virtual void last_stamp (const char* file, const char* func, ulong line); void report_info (FILE* fs); void present_info (FILE* fs); /*- ...... PUBLIC DATA ...... -*/ public: int _arb_val; //! arbitrary value for custom use /*- ...... DATA ...... -*/ protected: /* Default values */ static constexpr const char* const SUBJ_DEF = ""; static constexpr const char* const FILE_DEF = ""; static constexpr const char* const FUNC_DEF = ""; static constexpr const ulong LINE_DEF = 0; static constexpr const char* const DESCR_DEF = ""; static constexpr const int ARB_VAL_DEF = 0; static constexpr const char* STAMPS_SEP = " --> "; //! separator for locations in trace /* Exception data */ const char* _cs_subj; //! subject of exception: filename, file system, object name, data etc. excnum_en _errnum; //! errno or excnum_en value denoting error type const char* _cs_descr; //! more elaborate description of error cl_exc_trace _Trace = {}; //! Way travelled by exception const st_mh_error* _C_error; //! error taken over from C routines friend class cl_exception_TEST; }; /* ------------------------------------------------- cl_exception ---- */ /* =================================================================== */ } /*- STUFF TO BE USED BY OUTSIDE PARTIES -*/ using __impl__::excnum_en; using __impl__::cl_exception; } extern __tls__ ERRORS_HANDLING::cl_exception __exc__; /*!:: Interface macros. * Use them on regular basis instead of raw classes, which should be used * only in special cases. It will make your code consistent. */ /* =================================================================== */ #define ExcThrowObject() do { \ throw __exc__; \ } while(0) #define ExcArbVal(Val) do { \ __exc__._arb_val = (Val); \ } while(0) #define ExcThrow(Subj, Errnum, Descr) do { \ __exc__.setup((Subj), (Errnum), (Descr), __FILE__, __func__, __LINE__, __exc__._arb_val); \ ExcThrowObject(); \ } while(0) #define ExcRethrow() do { \ ExcThrowObject(); \ } while(0) #define ExcMidStamp() do { \ __exc__.app_stamp(__FILE__, __func__, __LINE__); \ } while(0) #define ExcLastStamp() do { \ __exc__.last_stamp(__FILE__, __func__, __LINE__); \ } while(0) /*!:: Macro to handle C routines errors. Counterpart of HandleErr() in C. */ #define HandleCErr() do { \ if (errno != 0) { \ __exc__.setup(__err__); \ __exc__.first_stamp(__FILE__, __func__, __LINE__); \ ExcThrowObject(); \ } \ } while(0) /*!:: Macro to handle C routines errors. Counterpart of ErrorTrigIf() in C. */ #define ExcTrigIf(Cond, Subj, Errnum, Descr) do { \ if ((Cond)) { \ ExcThrow((Subj), (Errnum), (Descr)); \ } \ } while(0) #define ExcReportInfo(FS) do { \ __exc__.report_info((FS)); \ } while(0) #define ExcPresentInfo(FS) do { \ __exc__.present_info((FS)); \ } while(0) /* =================================================================== */ /*!:: Standard, common exceptions tracking. * Use them for consistent, standardized exceptions tracking in functions. * Will record location and rethrow exception. */ /* =================================================================== */ #define ExcTRACK_BEG try { #define ExcTRACK_END } \ catch (ERRORS_HANDLING::cl_exception&) { ExcMidStamp(); ExcRethrow(); } /* =================================================================== */ #endif /*- MHLIB_BASE_SRCCORE_EXCEPTION_HH -*/ |
Added lib_base/core.hh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
#ifndef MHLIBS_BASE_SRCCORE_CORE_HH #define MHLIBS_BASE_SRCCORE_CORE_HH /*!F::Core declarations and definitions for Machel's C++ projects. * * ::Purpose: * Common for every C++ project declarations and definitions: * - headers * - macros * - type definitions and aliases * - common functions nad macro functions * - GNU extensions: attributes * * ::Properties: * compiler options: -std=c++11 * thread safe * * ::Other: * Created: 2014-06-16 * (c) Copyright: "Machel" 2014 * License: GNU Public License */ /* 32/64b */ /* -------------------------------------------------------------------------- */ /* Functions that take 32b parameters (like lseek) wil now take 64b parameters. * Thus lseek on 32b system will be transparently replaced by lseek64. * Allows 32b systems to use 64b large files and large data. */ #define _FILE_OFFSET_BITS 64 /* Common headers */ /* -------------------------------------------------------------------------- */ #include <cerrno> // errno() #include <cassert> // assert() #include <cstddef> // NULL, size_t, ptrdiff_t, offsetof /* Pathname component separator */ #if defined(_WIN32) || defined(_MSC_VER) # define MH_PNCS '\\' #else # define MH_PNCS '/' #endif /* Thread local storage. */ /* -------------------------------------------------------------------------- */ /* Thread local storage. Different defines for different compilers. * Usage: * extern/static __tls__ int var; * * !!! C++: * GCC do not allow construct/destruct for '__thread' variables! * use C++'s 'thread_local' (but it is <C++11>) */ #ifndef __tls__ #if defined(__cplusplus) && (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER)) # define __tls__ thread_local #elif defined(__GNUC__) || defined(__GNUG__) \ || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ || defined(__ICC) || defined(__INTEL_COMPILER) # define __tls__ __thread #elif defined(_MSC_VER) && defined(__cplusplus) # define __tls__ __declspec(thread) #else # define __tls__ TLS_FOR_THIS_COMPILER_NOT_SUPPORTED #endif #endif /* Type definitions. */ /* -------------------------------------------------------------------------- */ #undef NULL #define NULL nullptr /* Signed size type. For Windows and for other systems. * ssize_t */ #if defined(_MSC_VER) # include <BaseTsd.h> typedef SSIZE_T ssize_t; #else # include <unistd.h> #endif /* SIZE_MAX */ #include <climits> // <C++/Solaris>SIZE_MAX #if HAVE_STDINT_H #include <cstdint> // <C99>SIZE_MAX #endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)(-1)) #endif /*!:: Special type that can take three values: * negative (less then 0), neutral (0), positive (greater then 0). */ #if !defined(TROOL_DEFINED) enum trool { tr_neg=-1, tr_less=-1, tr_neut=0, tr_equal=0, tr_pos=1, tr_great=1 }; typedef enum trool trool; #define TROOL_DEFINED #endif /* aliases for built-in types */ typedef unsigned short ushort; typedef signed short sshort; typedef unsigned int uint; typedef signed int sint; typedef unsigned long ulong; typedef signed long slong; typedef int FD; #include <string> typedef std::string str; /* Helper functions. */ /* -------------------------------------------------------------------------- */ /*!:: Stringize macro constant */ #define __STR__(x) #x #define _STR_(x) __STR__(x) /*!1-3 * :: Set arrays. */ #define ArrSet(ARR,NELS,VAL) for(size_t ii=0; ii<(NELS); ++ii) (ARR)[ii] = (VAL) #define ArrSetN(ARR,START,NELS,VAL) for(size_t ii=(START); ii<(NELS); ++ii) (ARR)[ii] = (VAL) #define Arr2DSet(ARR,RELS,CELS,VAL) for(size_t ii=0; ii<(RELS); ++ii) for(size_t jj=0; jj<(CELS); ++jj) (ARR)[ii][jj] = (VAL) #define SetArr2D(parr, I, J, val) do { \ for (size_t iii = 0; iii < (I); ++iii) { \ for (uint jjj = 0; jjj < (J); ++jjj) { \ (*(parr))[iii][jjj] = (val); \ } \ } \ } while(0) #ifndef ASK_YN_DEFINED #include <cstdio> #include <cstdarg> static inline bool ask_yn ( const char* yes_chars, //! any of this chars is 'yes' answer const char* fmt, //! format string conforming to printf specification ... //! data to print ){ int ch = '\0'; if (fmt != NULL) { va_list ap; va_start(ap, fmt); vfprintf(stdout, fmt, ap); fflush(stdout); va_end(ap); } ch = getchar(); //==getc(stdin) if (ch == '\n') { ch = getchar(); } //scanf() leaves \n in input buffer while (*yes_chars != '\0') { if (ch == *yes_chars) { return true; } ++yes_chars; } return false; } #define ASK_YN_DEFINED 1 #endif /* GCC extensions. */ /* -------------------------------------------------------------------------- */ /* Function attributes. * Define attribute macros only if compiler is GCC or compatible (particulary * Clang), otherwise define empty macros that do nothing. */ #if defined(__GNUC__) || defined(__GNUG__) // function has no effects, ONLY: ret val, may depend on outside var, // not on volatile mem etc. # define __attr_pure__ __attribute__((__pure__)) // function has no effects, ONLY: ret val, may NOT depend on outside var, // not on volatile mem etc. // examining data pointed by ptr args is depending on outside data! # define __attr_const__ __attribute__((__const__)) // list contains parameter numbers starting from 1 that can not be NULL. # define __attr_nonnull__(...) __attribute__((__nonnull__(__VA_ARGS__))) // return value can not be NULL # define __attr_ret_nonnull__ __attribute__((__returns_nonnull__)) // return value can not be ignored # define __attr_wures__ __attribute__((__warn_unused_result__)) // num of parameter that specifies size of memory that function will alloc # define __attr_alloc_size__(PARAM_NUM) __attribute__((__alloc_size__(PARAM_NUM))) // mallo-like function - see documentation # define __attr_malloc__ __attribute__((__malloc__)) // printf-like function - see documentation # define __attr_format__(FUN,FMT_NUM,VA_NUM) __attribute__((__format__(FUN,FMT_NUM,VA_NUM))) // num of parameter from back starting from 0 that is sentinel in va function # define __attr_sentinel__(PARAM_NUM_BACK) __attribute__((__sentinel__(PARAM_NUM_BACK))) // attribute can be unused, suppress warnings about it # define __attr_unused__ __attribute((__unused__)) #else /*- __GNUC__ -*/ # define __attribute__(x) /*-nothing-*/ # define __attr_pure__ /*-nothing-*/ # define __attr_const__ /*-nothing-*/ # define __attr_nonnull__(...) /*-nothing-*/ # define __attr_ret_nonnull__ /*-nothing-*/ # define __attr_wures__ /*-nothing-*/ # define __attr_alloc_size__(PARAM_NUM) /*-nothing-*/ # define __attr_malloc__ /*-nothing-*/ # define __attr_format__(FUN,FMT_NUM,VA_NUM) /*-nothing-*/ # define __attr_sentinel__(PARAM_NUM_BACK) /*-nothing-*/ # define __attr_unused__ /*-nothing-*/ #endif /*- __GNUC__ -*/ // for descriptions of attributes see documentation at: // http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html /* REAMINDERS */ /* macros indicating compilers */ #if defined(__GNUC__) || defined(__GNUG__) /* <C&C++> <C++> GNU GCC/G++, Clang/LLVM, IBM XL C/C++. ------------------- */ #elif (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER)) /* GNU GCC/G++. -----------------------------------only------ */ #elif defined(__clang__) /* <C&C++> Clang/LLVM. ---------------------------------------------- */ #elif defined(__IBMC__) || defined(__IBMCPP__) /* <C> <C++> IBM XL C/C++. -------------------------------------------- */ #elif defined(__ICC) || defined(__INTEL_COMPILER) /* <C&C++> <C&C++> Intel ICC/ICPC. ------------------------------------------ */ #elif defined(__HP_cc) || defined(__HP_aCC) /* <C> <C++> Hewlett-Packard C/aC++. ---------------------------------- */ #elif defined(_MSC_VER) && defined(__cplusplus) /* <C&C++> <C++> Microsoft Visual Studio. --------------------------------- */ #elif defined(__PGI) && defined(__cplusplus) /* <C&C++> <C++> Portland Group PGCC/PGCPP. ------------------------------- */ #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* <C> <C++> Oracle Solaris Studio. ----------------------------------- */ #endif /* macros indicating operating systems */ // __unix__ - any unix-like, NOT Apple-like // - HP-UX // __linux__ - linuxes // _POSIX* - linuxes // BSD - any BSD or specific: __DragonFly__, __Free/Net/OpenBSD__ // - OSX, iOS // __APPLE__ && __MACH__ - OSX, iOS + TARGET_OS_MAC (OSX), TARGET_OS_IPHONE etc. // __sun && __SVR4 // // __hpux - HP-UX // _AIX - Ibm AIX // // _WIN64, _WIN32 - WinXP,Vista,7,8 // __CYGWIN__ && !_WIN32 - Cygwin (only 32b version exist) // __MINGW32/64_ - MinGW #if defined(__unix__) #include <sys/param.h> #if defined(BSD) /* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD) ----------- */ #endif #endif #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include <sys/param.h> #if defined(BSD) /* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD) + OSX, iOS, Darwin ----------- */ #endif #endif #if defined(__APPLE__) && defined(__MACH__) /* Apple OSX and iOS (Darwin). ------------------------------ */ #include <TargetConditionals.h> #if TARGET_IPHONE_SIMULATOR == 1 /* iOS in Xcode simulator */ #elif TARGET_OS_IPHONE == 1 /* iOS on iPhone, iPad, etc. */ #elif TARGET_OS_MAC == 1 /* OSX */ #endif #endif /* UNIX line and POSIX compliant - currently BSD,linux,OSX,Solaris */ #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) /* UNIX-style OS. ------------------------------------------- */ #include <unistd.h> #if defined(_POSIX_VERSION) /* POSIX compliant */ #endif #endif #endif /*- MHLIBS_BASE_SRCCORE_CORE_HH -*/ |
Added lib_c_base/common_mhlbase.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#ifndef MHCL_BASE_SRCMAIN_COMMON_MHLBASE_H #define MHCL_BASE_SRCMAIN_COMMON_MHLBASE_H /*!F::Common items for this project source files. * * ::Purpose: * Provides items common for source files in current project, like its name, * version and the like. * * ::Properties: * compiler options: -std= * thread safe * * ::Other: * Created: 2013-12-16 * (c) Copyright: "Machel" 2013 * License: GNU Public License */ #define MHLC_BASE_PR_PACK "mhlibs" #define MHLC_BASE_PR_NAME "baselibs" #define MHLC_BASE_PR_LONGNAME "base tools" #define MHLC_BASE_VER_MAJOR 0 #define MHLC_BASE_VER_MINOR 4 #define MHLC_BASE_VER_PATCH 0 #define MHLC_BASE_PR_VER MHLC_BASE_VER_MAJOR.MHLC_BASE_VER_MINOR.MHLC_BASE_VER_PATCH #define MHLC_BASE_PR_FULLNAME MHLC_BASE_PR_NAME " (" MHLC_BASE_PR_PACK ") " _STR_(MHLC_BASE_PR_VER) #define LOG_DEF_STREAM stderr #endif /*- MHCL_BASE_SRCMAIN_COMMON_MHLBASE_H -*/ |
Added lib_c_base/core.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
#ifndef MHLIBS_BASE_SRCBASE_CORE_H #define MHLIBS_BASE_SRCBASE_CORE_H /*!F::Core declarations and definitions for Machel's C projects. * * ::Purpose: * Common for every C project declarations and definitions: * - headers * - macros * - type definitions and aliases * - common functions nad macro functions * - GNU extensions: attributes * * ::Properties: * compiler options: -std=c99 * thread safe * * ::Other: * Created: 2013-12-16 * (c) Copyright: "Machel" 2013 * License: GNU Public License */ /* 32/64b */ /* -------------------------------------------------------------------------- */ /* Functions that take 32b parameters (like lseek) wil now take 64b parameters. * Thus lseek on 32b system will be transparently replaced by lseek64. * Allows 32b systems to use 64b large files and large data. */ #define _FILE_OFFSET_BITS 64 /* Common headers */ /* -------------------------------------------------------------------------- */ #include <assert.h> // assert() #include <stddef.h> // NULL, size_t, ptrdiff_t, offsetof #include <stdbool.h> // bool, true, false /* Pathname component separator */ #define PNCS '/' /* Thread local storage. */ /* -------------------------------------------------------------------------- */ /* Thread local storage. Different defines for different compilers. * Usage: * extern/static __tls__ int var; * * !!! C++: * GCC do not allow construct/destruct for '__thread' variables! * use C++'s 'thread_local' (but it is <C++11>) */ #ifndef __tls__ #if defined(__cplusplus) && (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER)) # define __tls__ thread_local #elif defined(__GNUC__) || defined(__GNUG__) \ || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \ || defined(__ICC) || defined(__INTEL_COMPILER) # define __tls__ __thread #elif defined(_MSC_VER) && defined(__cplusplus) # define __tls__ __declspec(thread) #else # define __tls__ TLS_FOR_THIS_COMPILER_NOT_SUPPORTED #endif #endif /* Type definitions. */ /* -------------------------------------------------------------------------- */ #if defined(__cplusplus) #undef NULL #define NULL nullptr #endif /* Signed size type. For Windows and for other systems. * ssize_t */ #if defined(_MSC_VER) # include <BaseTsd.h> typedef SSIZE_T ssize_t; #else # include <unistd.h> #endif /* SIZE_MAX */ #include <limits.h> // <C++/Solaris>SIZE_MAX #if HAVE_STDINT_H #include <stdint.h> // <C99>SIZE_MAX #endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)(-1)) #endif /*!:: Special type that can take three values: * negative (less then 0), neutral (0), positive (greater then 0). */ #if !defined(TROOL_DEFINED) enum trool { tr_neg=-1, tr_less=-1, tr_neut=0, tr_equal=0, tr_pos=1, tr_great=1 }; typedef enum trool trool; #define TROOL_DEFINED #endif /* aliases for built-in types */ typedef unsigned short ushort; typedef signed short sshort; typedef unsigned int uint; typedef signed int sint; typedef unsigned long ulong; typedef signed long slong; typedef int FD; /* Helper functions. */ /* -------------------------------------------------------------------------- */ /*!:: Stringize macro constant */ #define __STR__(x) #x #define _STR_(x) __STR__(x) /*!1-3 * :: Set arrays. */ #define ArrSet(ARR,NELS,VAL) for(size_t ii=0; ii<(NELS); ++ii) (ARR)[ii] = (VAL) #define ArrSetN(ARR,START,NELS,VAL) for(size_t ii=(START); ii<(NELS); ++ii) (ARR)[ii] = (VAL) #define Arr2DSet(ARR,RELS,CELS,VAL) for(size_t ii=0; ii<(RELS); ++ii) for(size_t jj=0; jj<(CELS); ++jj) (ARR)[ii][jj] = (VAL) #define SetArr2D(parr, I, J, val) do { \ for (size_t iii = 0; iii < (I); ++iii) { \ for (uint jjj = 0; jjj < (J); ++jjj) { \ (*(parr))[iii][jjj] = (val); \ } \ } \ } while(0) #ifndef ASK_YN_DEFINED #include <stdio.h> #include <stdarg.h> static inline bool ask_yn ( const char* yes_chars, //! any of this chars is 'yes' answer const char* fmt, //! format string conforming to printf specification ... //! data to print ){ int ch = '\0'; if (fmt != NULL) { va_list ap; va_start(ap, fmt); vfprintf(stdout, fmt, ap); fflush(stdout); va_end(ap); } ch = getchar(); //==getc(stdin) if (ch == '\n') { ch = getchar(); } //scanf() leaves \n in input buffer while (*yes_chars != '\0') { if (ch == *yes_chars) { return true; } ++yes_chars; } return false; } #define ASK_YN_DEFINED 1 #endif /* GCC extensions. */ /* -------------------------------------------------------------------------- */ /* Function attributes. * Define attribute macros only if compiler is GCC or compatible (particulary * Clang), otherwise define empty macros that do nothing. */ #if defined(__GNUC__) || defined(__GNUG__) // function has no effects, ONLY: ret val, may depend on outside var, // not on volatile mem etc. # define __attr_pure__ __attribute__((__pure__)) // function has no effects, ONLY: ret val, may NOT depend on outside var, // not on volatile mem etc. // examining data pointed by ptr args is depending on outside data! # define __attr_const__ __attribute__((__const__)) // list contains parameter numbers starting from 1 that can not be NULL. # define __attr_nonnull__(...) __attribute__((__nonnull__(__VA_ARGS__))) // return value can not be NULL # define __attr_ret_nonnull__ __attribute__((__returns_nonnull__)) // return value can not be ignored # define __attr_wures__ __attribute__((__warn_unused_result__)) // num of parameter that specifies size of memory that function will alloc # define __attr_alloc_size__(PARAM_NUM) __attribute__((__alloc_size__(PARAM_NUM))) // mallo-like function - see documentation # define __attr_malloc__ __attribute__((__malloc__)) // printf-like function - see documentation # define __attr_format__(FUN,FMT_NUM,VA_NUM) __attribute__((__format__(FUN,FMT_NUM,VA_NUM))) // num of parameter from back starting from 0 that is sentinel in va function # define __attr_sentinel__(PARAM_NUM_BACK) __attribute__((__sentinel__(PARAM_NUM_BACK))) // attribute can be unused, suppress warnings about it # define __attr_unused__ __attribute((__unused__)) #else /*- __GNUC__ -*/ # define __attribute__(x) /*-nothing-*/ # define __attr_pure__ /*-nothing-*/ # define __attr_const__ /*-nothing-*/ # define __attr_nonnull__(...) /*-nothing-*/ # define __attr_ret_nonnull__ /*-nothing-*/ # define __attr_wures__ /*-nothing-*/ # define __attr_alloc_size__(PARAM_NUM) /*-nothing-*/ # define __attr_malloc__ /*-nothing-*/ # define __attr_format__(FUN,FMT_NUM,VA_NUM) /*-nothing-*/ # define __attr_sentinel__(PARAM_NUM_BACK) /*-nothing-*/ # define __attr_unused__ /*-nothing-*/ #endif /*- __GNUC__ -*/ // for descriptions of attributes see documentation at: // http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html /* REAMINDERS */ /* macros indicating compilers */ #if defined(__GNUC__) || defined(__GNUG__) /* <C&C++> <C++> GNU GCC/G++, Clang/LLVM, IBM XL C/C++. ------------------- */ #elif (defined(__GNUC__) || defined(__GNUG__)) && !(defined(__clang__) || defined(__INTEL_COMPILER)) /* GNU GCC/G++. -----------------------------------only------ */ #elif defined(__clang__) /* <C&C++> Clang/LLVM. ---------------------------------------------- */ #elif defined(__IBMC__) || defined(__IBMCPP__) /* <C> <C++> IBM XL C/C++. -------------------------------------------- */ #elif defined(__ICC) || defined(__INTEL_COMPILER) /* <C&C++> <C&C++> Intel ICC/ICPC. ------------------------------------------ */ #elif defined(__HP_cc) || defined(__HP_aCC) /* <C> <C++> Hewlett-Packard C/aC++. ---------------------------------- */ #elif defined(_MSC_VER) && defined(__cplusplus) /* <C&C++> <C++> Microsoft Visual Studio. --------------------------------- */ #elif defined(__PGI) && defined(__cplusplus) /* <C&C++> <C++> Portland Group PGCC/PGCPP. ------------------------------- */ #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* <C> <C++> Oracle Solaris Studio. ----------------------------------- */ #endif /* macros indicating operating systems */ // __unix__ - any unix-like, NOT Apple-like // - HP-UX // __linux__ - linuxes // _POSIX* - linuxes // BSD - any BSD or specific: __DragonFly__, __Free/Net/OpenBSD__ // - OSX, iOS // __APPLE__ && __MACH__ - OSX, iOS + TARGET_OS_MAC (OSX), TARGET_OS_IPHONE etc. // __sun && __SVR4 // // __hpux - HP-UX // _AIX - Ibm AIX // // _WIN64, _WIN32 - WinXP,Vista,7,8 // __CYGWIN__ && !_WIN32 - Cygwin (only 32b version exist) // __MINGW32/64_ - MinGW #if defined(__unix__) #include <sys/param.h> #if defined(BSD) /* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD) ----------- */ #endif #endif #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include <sys/param.h> #if defined(BSD) /* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD) + OSX, iOS, Darwin ----------- */ #endif #endif #if defined(__APPLE__) && defined(__MACH__) /* Apple OSX and iOS (Darwin). ------------------------------ */ #include <TargetConditionals.h> #if TARGET_IPHONE_SIMULATOR == 1 /* iOS in Xcode simulator */ #elif TARGET_OS_IPHONE == 1 /* iOS on iPhone, iPad, etc. */ #elif TARGET_OS_MAC == 1 /* OSX */ #endif #endif /* UNIX line and POSIX compliant - currently BSD,linux,OSX,Solaris */ #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) /* UNIX-style OS. ------------------------------------------- */ #include <unistd.h> #if defined(_POSIX_VERSION) /* POSIX compliant */ #endif #endif #endif /*- MHLIBS_BASE_SRCBASE_CORE_H -*/ |
Added lib_c_base/debug.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/*!F::Debug procedures - main implementation file. * * ::Purpose: * Detect bugs and inform programmer about them. * * It is part of error handling facilities which involve error.s, debug.c and * faults.c. * It covers programmers mistakes: bad argument passed, wrong code reached, * bad use of programming facility. * It doesn't cover OS errors (errors.c) and user's errors (faults.c). * * ::Goals: * - thread-safe, reentrant, portable (POSIX systems) * - buffer/integer overflow safe * - propagate or handle errors with routines from "errors.h" * * ::Functionality: * - log messages * - log messages if condition true * - log variable values * * ::Limitations: * - definitely more debug routines can be implemented * * ::Properties: * compiler options: -std=c99 * thread safe * * ::Other: * File: This file is part of program distributed under GNU General Public License. * For terms of distribution, warranty and licensing see README file. * Created: 2013-12-16 * (c) Copyright: Maciej Helminiak 2013 * License: GNU General Public License, version 3 * Copy of the license is distributed along with this program * or can be seen at <http://www.gnu.org/licenses/> */ /* current project */ #include "common_mhlbase.h" /* mh library */ #include "core.h" #include "logs.h" /* libc */ /* current module */ #include "debug.h" |
Added lib_c_base/debug.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
#ifndef MHCL_BASE_SRCBASE_DEBUG_H #define MHCL_BASE_SRCBASE_DEBUG_H /*!F::Debug procedures - external interface file. * * ::Provides function declarations for other modules. */ /* current project */ #include "common_mhlbase.h" /* mh library */ #include "core.h" #include "logs.h" /* libc */ #include <stdlib.h> // abort() #include <stdio.h> // printf(), fflush() #define LogAssert(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_ASSERT, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) #define ___Sentinel(...) do { LogAssert(__VA_ARGS__); } while(0) /* DEBUG */ /* ========================================================================== */ #ifdef DEBUG /*!1-6 * :: Log debug messages. * :: Print messages of certain type to 'LOG_DEF_STREAM'. Messages are * consistently formatted with use of adequate prefix, current file name, * line number, function name and additional printf-like string customized * by user. * :: Intended for printing various debug messages. * :: These macro functions are in effect only if 'DEBUG' macro is defined. */ #define DLog(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) #define DLogInfo(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) #define DLogWarn(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) #define DLogError(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) #define DLogTest(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_TEST, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) #define DLogAssert(...) do { log_string(LOG_DEF_STREAM, LOG_PREF_ASSERT, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0) /*!1-6 * :: Checks. * :: Check if condition is true and take actions if it is not. Log message or * eventually abort. * :: This macro functions are in effect only if 'DEBUG' macro is defined. */ #define ___Dcheck(Cond, ...) do { if(!(Cond)) { DLogError(__VA_ARGS__); } } while(0) #define ___Dassert(Cond, ...) do { if(!(Cond)) { DLogAssert(__VA_ARGS__); abort(); } } while(0) #define ___Dsentinel(...) do { DLogAssert(__VA_ARGS__); } while(0) #define ___DParam(Param, Cond) do { if(!((Param) Cond)) { DLogAssert("'"#Param"' parameter invalid"); abort(); } } while(0) #define ___DInter(Param, Cond) do { if(!((Param) Cond)) { DLogAssert("'"#Param"' internal check failed"); abort(); } } while(0) #define ___DReturn(Param, Cond) do { if(!((Param) Cond)) { DLogAssert("'"#Param"' return expression invalid"); abort(); } } while(0) #else #define DLog(...) ((void)0) #define DLogInfo(...) ((void)0) #define DLogWarn(...) ((void)0) #define DLogError(...) ((void)0) #define DLogTest(...) ((void)0) #define DLogAssert(...) ((void)0) #define ___Dcheck(Cond, ...) ((void)0) #define ___Dassert(Cond, ...) ((void)0) #define ___Dsentinel(...) ((void)0) #define ___DParam(Param, Cond) do { (void)sizeof(Param); } while(0) #define ___DInter(Param, Cond) do { (void)sizeof(Param); } while(0) #define ___DReturn(Param, Cond) do { (void)sizeof(Param); } while(0) #endif /*- DEBUG -*/ /* DEBUG2 */ /* ========================================================================== */ #ifdef DEBUG2 /*!1-4 * :: Log program state. * :: Simply print printf-like formatted message to 'stdout' preceded by * function name and line number, then flush stream. * :: Intended for printing state of program during debugging time, * ie. value of variables. */ #define ___DPr(...) do { \ fprintf(stdout, ">> %s:%d: ", __func__, __LINE__); \ fprintf(stdout, __VA_ARGS__); \ fflush(stdout); \ } while(0) #define ___DVs(VAR) do { \ fprintf(stdout, #VAR"=|%s|", (VAR)); \ fflush(stdout); \ } while(0) #define ___DVd(VAR) do { \ fprintf(stdout, #VAR"=%d", (VAR)); \ fflush(stdout); \ } while(0) #define ___DVz(VAR) do { \ fprintf(stdout, #VAR"=%zu", (VAR)); \ fflush(stdout); \ } while(0) #define ___DVp(VAR) do { \ fprintf(stdout, #VAR"=%p", (VAR)); \ fflush(stdout); \ } while(0) #else #define ___DPr(...) #define ___DVs(VAR) #define ___DVd(VAR) #define ___DVz(VAR) #define ___DVp(VAR) #endif /*- DEBUG2 -*/ #ifdef DEBUG bool debug_all_tests_run (void) __attr_wures__ ; #endif #endif /*- MHCL_BASE_SRCBASE_DEBUG_H -*/ |
Added lib_c_base/errors.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
/*!F::Errors management - main implementation file. * * ::Purpose: * Detecting, propagating and handling of errors in consistent and convenient * way. Thread-safe. * Test for specified conditions and take actions on failing, like jumping to * label. * * It is part of error handling facilities which involve error.s, debug.c and * faults.c. * It covers OS errors: access denied, bad permissions, operation not supported, * no memory, quota exceeded etc. * It doesn't cover: programmer's errors (covered by debug.c), user's errors * (covered by faults.c). * * ::Goals: * - thread-safe, reentrant, portable (POSIX systems) * - buffer/integer overflow safe * * ::Functionality: * - propagate error information from within a function * - set/cancel errors * - handle errors * * ::Limitations: * - information is limited to fixed size arrays * - error handling uses labels that must be placed within scope * * ::Properties: * compiler options: -std=c99 * thread safe * * ::Other: * File: This file is part of program distributed under GNU General Public License. * For terms of distribution, warranty and licensing see README file. * Created: 2013-12-16 * (c) Copyright: Maciej Helminiak 2013 * License: GNU General Public License, version 3 * Copy of the license is distributed along with this program * or can be seen at <http://www.gnu.org/licenses/> */ /* snprintf(), vsnprintf(): * _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE * || _POSIX_C_SOURCE >= 200112L; * or -std=c99 */ #define _POSIX_C_SOURCE 200112L /* current project */ #include "common_mhlbase.h" /* mh library */ #include "core.h" #include "debug.h" #include "logs.h" /* libc */ #include <errno.h> // errno #include <stdarg.h> // va_* #include <stdio.h> // printf(), fflush() #include <string.h> // strerror() /* current module */ #include "errors.h" /* Error structure */ /* -------------------------------------------------------------------------- */ /*!:: Error object instance. * :: Used by error setting and handling routines. * Created in thread local storage. */ __tls__ st_mh_error __err__; /* Error codes */ /* -------------------------------------------------------------------------- */ /*!:: Labels for enumeration constants in 'errt_en'. * :: Printable, unmodifiable string literals describing each enum constant. * Constant itself minus MH_ET_STARTING_NUMBER can be used as index in this * array. */ static const char* const errnum_Labels[errnum_count-MH_ET_STARTING_NUMBER] = { "Parameter out of range", "Data length exceeded", "Integer overflow", "Buffer overflow", "Output error", "Functionality not implemented", "State changed during operation", "Subject exist", "Format is wrong", "all types of errors", "unknown error" }; /* Error manipulating routines. */ /* -------------------------------------------------------------------------- */ /*!1-3 * :: Return cstring with current error's signature, trace, message. * ::Preconditions: NONE. * ::Errors: NONE. */ char* err_ret_sig ( void ){ return &__err__.sig[0]; } char* err_ret_trace ( void ){ return &__err__.trace[0]; } char* err_ret_msg ( void ){ return &__err__.msg[0]; } /*!1-3 * :: Place formatted in printf-like manner cstring in error's signature, trace, * message. * ::Preconditions: * ::Errors: * no Errors. * ..Note: vsnprintf() returns -1 on output error, but it is ignored as we are * here because of error condition anyway. * ::Parameters: * `fmt`: format cstring * `...`: arguments */ char* err_carve_sig ( const char* fmt, ... ){ va_list ap; va_start(ap, fmt); vsnprintf(&__err__.sig[0], ERROR_SIGNATURE_BYTES, fmt, ap); va_end(ap); return &__err__.sig[0]; } char* err_carve_trace ( const char* fmt, ... ){ va_list ap; va_start(ap, fmt); vsnprintf(&__err__.trace[0], ERROR_TRACE_BYTES, fmt, ap); va_end(ap); return &__err__.trace[0]; } char* err_carve_msg ( const char* fmt, ... ){ va_list ap; va_start(ap, fmt); vsnprintf(&__err__.msg[0], ERROR_MESSAGE_BYTES, fmt, ap); va_end(ap); return &__err__.msg[0]; } /*!1-2 * :: Append formatted in printf-like manner cstring to error's trace, message. * ::Preconditions: * ::Errors: * no Errors. * ..Note: vsnprintf() returns -1 on output error, but it is ignored as we are * here because of error condition anyway. * ::Parameters: * `fmt`: format cstring * `...`: arguments */ char* err_append_trace ( const char* fmt, ... ){ va_list ap; va_start(ap, fmt); const size_t nc = strlen(__err__.trace); vsnprintf(&__err__.trace[nc], ERROR_TRACE_BYTES-nc, fmt, ap); va_end(ap); return &__err__.trace[0]; } char* err_append_msg ( const char* fmt, ... ){ va_list ap; va_start(ap, fmt); const size_t nc = strlen(__err__.msg); vsnprintf(&__err__.msg[nc], ERROR_MESSAGE_BYTES-nc, fmt, ap); va_end(ap); return &__err__.msg[0]; } /*!:: Return pointer to string describing given error code. * ::Errors: */ const char* err_descr ( int err //! error code ){ /* error in range of errno values defined in libc */ if (err < MH_ET_STARTING_NUMBER) { return strerror(err); } /* error type defined outside libc */ else { return errnum_Labels[err - MH_ET_STARTING_NUMBER]; } } /* Error handling routines. */ /* -------------------------------------------------------------------------- */ /*!:: Error code must be different from 'NONE' and must be equal to current * code in error or to constant indicating ALL codes. * ::Errors: */ bool err_catch_cond_fulfiled ( errnum_en errnum //! error code ){ if (errno == 0) { return false; } if ( ((errnum) != E_NONE) && ((uint)errno == (errnum) || (errnum) == E_ALL_TYPES) ) { return true; } return false; } /*!:: Error information is printed accordingly to specified print action. * ::Errors: */ void err_catch_print_action ( errprint_en errpr ){ switch (errpr) { case EPR_NONE: /*- nothing -*/ break; case EPR_NOTICE: LogError("Error: %s\n", ErrDescr()); break; case EPR_MESSAGE: LogError("%s\n", ErrMessage()); break; case EPR_DEBUG_INFO: LogError("%s\n\ttype: %s\n\toriginated: %s\n\ttrace: %s\n\tmsg: %s", "Error encountered:", ErrDescr(), ErrSignat(), ErrTrace(), ErrMessage()); break; case EPR_UNKNOWN: case errprint_count: default: ___Sentinel("Wrong print error action"); abort(); }; } |
Added lib_c_base/errors.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
#ifndef MHCL_BASE_SRCBASE_ERRORS_H #define MHCL_BASE_SRCBASE_ERRORS_H /*!F::Errors management - external interface file. * * ::Provides function declarations for other modules. */ /* mh library */ #include "core.h" /* current project */ #include "common_mhlbase.h" /* libc */ #include <errno.h> // errno #include <stdlib.h> // abort() #include <stdio.h> // printf(), fflush() /* Error structure */ /* -------------------------------------------------------------------------- */ /* Number of bytes of cstrings representing error's signature, trace, message in error structure. */ #define ERROR_SIGNATURE_BYTES 128 #define ERROR_TRACE_BYTES 1024 #define ERROR_MESSAGE_BYTES 1024 typedef struct st_mh_error st_mh_error; /*!:: Error structure. * Data describing current error. In conjunction with 'errno' provided by * libc makes overall error description. */ struct st_mh_error { char sig[ERROR_SIGNATURE_BYTES]; //! signature - where error originated from char trace[ERROR_TRACE_BYTES]; //! subsequent places of error propagation char msg[ERROR_MESSAGE_BYTES]; //! message used if more elaborate description //! then provided by 'errno' needed bool aux; //! for use by error routines }; extern __tls__ st_mh_error __err__; /* Error codes and cathegory */ /* -------------------------------------------------------------------------- */ /* Number of first error in 'enum errnum'. It must be greater then highest 'errno' code.*/ #define MH_ET_STARTING_NUMBER 4096 /*!:: Error codes. * Error codes complementary to those used by 'errno'. */ enum errnum_en { E_NONE=0, E_PARAMOOR=MH_ET_STARTING_NUMBER, //! parameter has value out of range E_DATALENEXC, //! data is too long E_OVERFLOWINT, //! integer overflow E_OVERFLOWBUF, //! buffer overflow E_OUTPUTERR, //! output to file, screen, network error E_FUNC_NOTIMPL, E_STATE_CHANGE, //! state of subject changed during operation E_EXIST, //! file, object, entity exist E_FORMAT_WRONG, //! file, string, user input is in wrong format E_ALL_TYPES, //! all types E_UNKNOWN, errnum_count }; typedef enum errnum_en errnum_en; /*!:: Error print action. */ enum errprint_en { EPR_NONE=0, //! do not print EPR_NOTICE, //! short notice EPR_MESSAGE, //! informative message EPR_DEBUG_INFO, //! full debug info EPR_UNKNOWN, //! unknown cathegory errprint_count }; typedef enum errprint_en errprint_en; /* Error manipulating routines. */ /* -------------------------------------------------------------------------- */ /*!1-3 * :: Return error's signature, trace, message. */ extern char* err_ret_sig (void) __attr_wures__ ; extern char* err_ret_trace (void) __attr_wures__ ; extern char* err_ret_msg (void) __attr_wures__ ; /*!1-3 * :: Carve error's signature, trace, message. */ extern char* err_carve_sig (const char* format, ...) __attr_nonnull__(1) __attr_format__(__printf__,1,2) ; extern char* err_carve_trace (const char* format, ...) __attr_nonnull__(1) __attr_format__(__printf__,1,2) ; extern char* err_carve_msg (const char* format, ...) __attr_nonnull__(1) __attr_format__(__printf__,1,2) ; /*!1-3 * :: Append to error's signature, trace, message. */ extern char* err_append_trace (const char* format, ...) __attr_nonnull__(1) __attr_format__(__printf__,1,2) ; extern char* err_append_msg (const char* format, ...) __attr_nonnull__(1) __attr_format__(__printf__,1,2) ; /*!1:: Return description of error type. */ extern const char* err_descr (int errno_val) __attr_wures__ ; /*!1-5 * :: Error code. * :: Set, get, test, clear current error code. */ #define SetErr(errnum) do { \ errno = (errnum); \ } while(0) #define GetErr() errno #define IsErr() errno #define ClrErrCode() do { \ errno = 0; \ } while(0) #define ClrErr() do { \ __err__.sig[0] = '\0'; \ __err__.trace[0] = '\0'; \ __err__.msg[0] = '\0'; \ __err__.aux = false; \ errno = 0; \ } while(0) /*!1-5 * :: Get error parameters. * :: Return current error's code, code description, signature, trace, message, * error struct. */ #define ErrNum() errno #define ErrDescr() err_descr(errno) #define ErrSignat() err_ret_sig() #define ErrTrace() err_ret_trace() #define ErrMessage() err_ret_msg() #define ErrSt() __err__ /* Error triggering routines. */ /* -------------------------------------------------------------------------- */ /*!1-5 * :: Set error. * :: Set error parameters, ev. set custom message, ev. do it conditionally, * ev. do not assign code. Then goto label. */ //#define ErrorTrig(errnum, label) #define ErrorSet(errnum, label) do { \ if (errno == 0) SetErr(errnum); \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ goto label; \ } while(0) //#define ErrorTrig_msg(errnum, label, ...) #define ErrorSetm(errnum, label, ...) do { \ if (errno == 0) SetErr(errnum); \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ err_carve_msg(__VA_ARGS__); \ goto label; \ } while(0) /*err_carve_trace("%s:(%s):%d", __FILE__, __func__, __LINE__); \*/ //#define ErrorTrigIf(Cond, errnum, label) #define ErrorSetIf(Cond, errnum, label) do { \ if ((Cond)) { \ if (errno == 0) SetErr(errnum); \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ goto label; \ } \ } while(0) //#define ErrorIf(Cond, label) #define ErrorTrigIf(Cond, label) do { \ if ((Cond)) { \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ goto label; \ } \ } while(0) #define ErrorTrigIfm(Cond, label, ...) do { \ if ((Cond)) { \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ err_carve_msg(__VA_ARGS__); \ goto label; \ } \ } while(0) /*!1-2 * :: Overflows. * :: Set error if overflow occured. */ #define OverflowIntIf(Cond, label) do { \ if ((Cond)) { \ if (errno == 0) SetErr(E_OVERFLOWINT); \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ goto label; \ } \ } while(0) /*!:: If condition is true buffer overflow occured. * Set error approprietely and goto `label`. */ #define OverflowBufIf(Cond, label) do { \ if ((Cond)) { \ if (errno == 0) SetErr(E_OVERFLOWBUF); \ err_carve_sig("%s:(%s):%d", __FILE__, __func__, __LINE__); \ goto label; \ } \ } while(0) /* Error handling routines. */ /* -------------------------------------------------------------------------- */ /*!1-2 * :: Handle (propagate) errors. * :: If error is set append trace to parameters and goto label. Eventually * carve custom message. */ #define HandleErr(label) do { \ if (errno != 0) { \ const char* trace = ErrTrace(); \ if (trace[0] == '\0') { \ err_carve_trace("%s:(%s):%d", __FILE__, __func__, __LINE__); \ } else { \ err_append_trace(" --> %s:(%s):%d", __FILE__, __func__, __LINE__); \ } \ goto label; \ } \ } while(0) #define HandleErrm(label, ...) do { \ if (errno != 0) { \ const char* trace = ErrTrace(); \ if (trace[0] == '\0') { \ err_carve_trace("%s:(%s):%d", __FILE__, __func__, __LINE__); \ } else { \ err_append_trace(" --> %s:(%s):%d", __FILE__, __func__, __LINE__); \ } \ err_carve_msg(__VA_ARGS__); \ goto label; \ } \ } while(0) /*!:: True if error code in current error is as specified. */ extern bool err_catch_cond_fulfiled (errnum_en errnum) __attr_wures__ ; /*!:: Error information print. */ extern void err_catch_print_action (errprint_en errpr) ; /*!1-2 * :: Catch errors. * :: If error is set do any of following actions: print notice, message or * debug info, ignore, continue, retry, exit, abort. */ #define CatchError(err_num, err_pr) \ __err__.aux = err_catch_cond_fulfiled((err_num)); \ if (__err__.aux == true) { \ err_append_trace(" --> %s:(%s):%d", __FILE__, __func__, __LINE__); \ err_catch_print_action((err_pr)); } \ if (__err__.aux == true) #ifdef DEBUG /* Used only by tests in debug mode. */ bool errors_all_tests_run (void) __attr_wures__ ; #endif #endif /*- MHCL_BASE_SRCBASE_ERRORS_H -*/ |
Added lib_c_base/logs.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
/*!F::Messages logging - main implementation file. * * ::Purpose: * Log messages in consistent manner. * * ::Goals: * - thread-safe, reentrant, portable (POSIX systems) * - buffer/integer overflow safe * - propagate or handle errors with routines from "errors.h" * * ::Functionality: * - log messages * * ::Limitations: * * ::Properties: * compiler options: -std=c99 * thread safe * * ::Other: * Created: 2013-12-16 * (c) Copyright: "Machel" 2013 * License: GNU Public License */ /* current project */ #include "common_mhlbase.h" /* mh library */ #include "core.h" /* libc */ #include <stdarg.h> // va_* #include <stdio.h> // printf(), fflush(), FILE* /* current module */ #include "logs.h" /*!:: First, fixed part of message is composed from established elements: prefix, * program name, file name, line number and function name. Second part is * customized by user in printf-like manner. * Message is printed to `fs` stream, stream is flushed. * :: Intended for logging, debugging and errors printing, wenever message needs * to carry info about file, line and function where event occured. * * ::Preconditions: * - all parameters except variadic list are required and can't be NULL * * ::Special preconditions: * - 'MHLC_BASE_PR_NAME' macro should be defined or "UNKNOWN" string will be * used as program name * * ::Errors: NONE. * printf-like functions return -1 on output error, but it is ignored. */ void log_string ( FILE* fs, //! message goes to this stream const char* pref, //! prefix, begining of message const char* file, //! file where message originated from uint line, //! line in file const char* func, //! function where message originated from const char* fmt, //! format string conforming to printf specification ... //! data to print ){ assert(pref && "'pref' parameter invalid"); assert(file && "'file' parameter invalid"); assert(line > 0 && "'line' parameter invalid"); assert(func && "'func' parameter invalid"); assert(fmt && "'fmt' parameter invalid"); #ifndef MHLC_BASE_PR_NAME # define MHLC_BASE_PR_NAME "UNKNOWN" #endif va_list ap; va_start(ap, fmt); /*: print custom part */ vfprintf(fs, fmt, ap); /*: print fixed part */ fprintf(fs, "\nlogged %s at: <%s> %s(): %s:%d\n", pref, MHLC_BASE_PR_NAME, func, file, line); fflush(fs); va_end(ap); } |
Added lib_c_base/logs.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
#ifndef MHCL_BASE_SRCBASE_LOGS_H #define MHCL_BASE_SRCBASE_LOGS_H /*!F::Messages logging - external interface file. * * ::Provides function declarations for other modules. */ /* current project */ #include "common_mhlbase.h" /* mh library */ #include "core.h" /* libc */ #include <stdarg.h> // va_* #include <stdio.h> // printf(), fflush(), FILE* /*!1:: Print consistently formatted message to specified file stream. */ extern void log_string (FILE* filestream, const char* prefix, const char* filename, uint line, const char* funcname, const char* format, ...) __attr_nonnull__(1,2,3,5,6) __attr_format__(__printf__,6,7) ; /*!:: Stream where all debug messages go by default. */ #ifndef LOG_DEF_STREAM # define LOG_DEF_STREAM stderr #endif /* Prefixes for various types of log messages. */ #ifndef LOG_PREF_DEBUG #define LOG_PREF_DEBUG " DBG " #endif #ifndef LOG_PREF_INFO #define LOG_PREF_INFO " INFO " #endif #ifndef LOG_PREF_WARN #define LOG_PREF_WARN " -WARN-" #endif #ifndef LOG_PREF_ERROR #define LOG_PREF_ERROR "=ERROR=" #endif #ifndef LOG_PREF_TEST #define LOG_PREF_TEST "test__>" #endif #ifndef LOG_PREF_ASSERT #define LOG_PREF_ASSERT "Assert>" #endif /*!:: Print message with error prefix to 'LOG_DEF_STREAM'. */ #define LogError(...) do { \ log_string(LOG_DEF_STREAM, LOG_PREF_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__); \ } while(0) /*!:: Print message with test prefix to 'LOG_DEF_STREAM'. */ #define LogTest(...) do { \ log_string(LOG_DEF_STREAM, LOG_PREF_TEST, __FILE__, __LINE__, __func__, __VA_ARGS__); \ } while(0) #ifdef DEBUG /* Used only by tests in debug mode. */ bool logs_all_tests_run (void) __attr_wures__ ; #endif #endif /*- MHCL_BASE_SRCBASE_LOGS_H -*/ |
Added src_main/ManxController.cxx.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
/* current project */ //#include "PureConn.hh" /* mh library */ #include "core.hh" //#include "sock.h" #include "Debug.hh" #include "Exception.hh" /* libc */ #include <cstdio> // fgets(), fileno() #include <cstring> // strcpy() #include <unistd.h> // isatty(), write() /* current module */ #include "ManxController.hh" using namespace MANX::GOVERNING; using namespace MANX::GOVERNING::__impl__; /* -------------------------------------------------- cl_user_cmd ---- */ constexpr const cl_user_cmd::st_cmd_spec cl_user_cmd::_Cmd_specs[]; void cl_user_cmd::read_user_cmd (FILE* fs_input) { ___Dparam(fs_input != NULL); /*: Print prompt if input is from terminal: */ int fd_in = fileno(fs_input); if (isatty(fd_in)) { write(fd_in, PROMPT, strlen(PROMPT)); } else { errno = 0; //isatty() sets errno on fail } /*: Read input: */ char* ret = fgets(_buf_input, INBUF_BYTES, fs_input); if (ret == NULL) { _buf_input[0] = '\0'; ExcTrigIf(ferror(fs_input), "Input fs", EIO, "Cannot read user input"); } /*: Get command and arguments: */ const st_cmd_spec* Spec_curr = NULL; size_t ii = 1; do { Spec_curr = &_Cmd_specs[ii++]; if (strstr(_buf_input, Spec_curr->_cs_keyword) == _buf_input) { //: Keyword or its abbreviation matches begining of input retrieve_args(&_buf_input[0] + strlen(Spec_curr->_cs_keyword)); break; } else if (strstr(_buf_input, Spec_curr->_cs_abbr) == _buf_input) { //: Keyword abbreviation matches begining of input retrieve_args(&_buf_input[0] + strlen(Spec_curr->_cs_abbr)); break; } } while (Spec_curr->_e_kw != keyw_en::Unknown); _e_kw = Spec_curr->_e_kw; } void cl_user_cmd::retrieve_args ( char* input ){ ___Dparam(input != NULL); char* p_n = strrchr(input, '\n'); if (p_n != NULL) { *p_n = '\0'; } printf("|%s|\n", input); char* p_beg = input; size_t ii = 0; while (true) { while (*p_beg == ' ') { ++p_beg; } if (*p_beg == '\0') { break; } //: No more arguments char* p_end = p_beg + 1; while (*p_end != ' ' && *p_end != '\0') { ++p_end; } _cs_args[ii++] = p_beg; if (*p_end == ' ') { *p_end = '\0'; } else { break; } p_beg = p_end + 1; } _cs_args[ii] = NULL; } /* -------------------------------------------------- cl_user_cmd ---- */ /* ------------------------------------------------ cl_controller ---- */ /*- ...... FUNDAMENTALS ...... -*/ cl_controller::cl_controller ( FILE* fs_input, FILE* fs_output, FILE* fs_logs ) : _fs_input{fs_input}, _fs_output{fs_output}, _fs_logs{fs_logs} { ___Dparam(fs_input != NULL); ___Dparam(fs_output != NULL); ___Dparam(fs_logs != NULL); } /*- ...... INTERFACE ...... -*/ void cl_controller::run () { while (true) { _Command.read_user_cmd(_fs_input); switch (_Command._e_kw) { case cl_user_cmd::keyw_en::WorldCreate: { printf("Creating world, Args:\n"); size_t ii = 0; const char* arg = NULL; while ((arg = _Command._cs_args[ii++]) != NULL) { printf("\t%s\n", arg); } //spawn(dept_en::World); //spawn(dept_en::NetCommunication); } break; case cl_user_cmd::keyw_en::WorldDestroy: printf("Destroying world\n"); return; //stow(dept_en::World); //stow(dept_en::NetCommunication); break; case cl_user_cmd::keyw_en::Unknown: printf("Not recognized\n"); break; default: printf("ERR\n"); } } } /* ------------------------------------------------ cl_controller ---- */ |
Added src_main/ManxController.hh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
#ifndef MANEX_SRCMAIN_MANXCONTROLLER_HH #define MANEX_SRCMAIN_MANXCONTROLLER_HH #include "core.hh" namespace MANX { namespace GOVERNING { namespace __impl__ { /* =================================================================== */ class cl_user_cmd { /*- ...... TYPES ...... -*/ private: enum class keyw_en { None = 0, WorldCreate, WorldDestroy, Unknown, count }; struct st_cmd_spec { keyw_en _e_kw; const char* const _cs_keyword; const char* const _cs_abbr; }; /*- Commands specification -*/ static constexpr const st_cmd_spec _Cmd_specs[] = { { keyw_en::None, "", ""} ,{ keyw_en::WorldCreate, "create world", "wc"} ,{ keyw_en::WorldDestroy, "destroy world", "wd"} ,{ keyw_en::Unknown, "", ""} }; /*- ...... FUNDAMENTALS ...... -*/ private: /*- ...... INTERFACE ...... -*/ public: void read_user_cmd (FILE* fs_input); /*- ...... DATA ...... -*/ private: static constexpr const uint MAX_ARGS = 128; static constexpr const uint INBUF_BYTES = 4096; static constexpr const char* const PROMPT = "> "; char _buf_input[INBUF_BYTES]; //! buffer for user input keyw_en _e_kw; //! command keyword const char* _cs_args[MAX_ARGS]; //! each arg points to location in `_buf_input` /*- ...... INTERNAL ROUTINES ...... -*/ private: void retrieve_args (char* input); friend class cl_controller; }; class cl_controller { /*- ...... FUNDAMENTALS ...... -*/ public: cl_controller (FILE* fs_input, FILE* fs_output, FILE* fs_logs); /*- deleted -*/ cl_controller () = delete; public: /*- ...... INTERFACE ...... -*/ void run (); /*- ...... DATA ...... -*/ private: FILE* _fs_input = NULL; FILE* _fs_output = NULL; FILE* _fs_logs = NULL; cl_user_cmd _Command = {}; /*- ...... INTERNAL ROUTINES ...... -*/ private: }; /* =================================================================== */ } /*- STUFF TO BE USED BY OUTSIDE PARTIES -*/ using __impl__::cl_controller; } } #endif /*- MANEX_SRCMAIN_MANXCONTROLLER_HH */ |
Added src_network/src_server/ManxServer.cxx.
Added src_network/src_server/ManxServer.hh.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#ifndef MANX_NETWORK_SRCSERVER_MANXSERVER_HH #define MANX_NETWORK_SRCSERVER_MANXSERVER_HH namespace MANX { namespace NETWORKING { namespace __impl__ { /* =================================================================== */ class cl_server { /*- ...... FUNDAMENTALS ...... -*/ /*- ...... INTERFACE ...... -*/ /*- ...... DATA ...... -*/ /*- ...... INTERNAL ROUTINES ...... -*/ }; /* =================================================================== */ } } /*- STUFF TO BE USED BY OUTSIDE PARTIES -*/ using __impl__::cl_XXXXX; } #include "main_exec.hh" int main () { MANX::GOVERNING::cl_controller Ctrl{stdin, stdout, stdout}; int ret = Ctrl.run(); return ret; } #endif /*- MANX_NETWORK_SRCSERVER_MANXSERVER_HH -*/ |
Added tests/main_test.cxx.
> > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "ManxController.hh" int main () { MANX::GOVERNING::cl_controller Ctrl{stdin, stdout, stdout}; Ctrl.run(); return EXIT_SUCCESS; } |