ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
Travis CI ื”ื•ื ืฉื™ืจื•ืช ืื™ื ื˜ืจื ื˜ ืžื‘ื•ื–ืจ ืœื‘ื ื™ื™ืช ื•ื‘ื“ื™ืงืช ืชื•ื›ื ื•ืช ื”ืžืฉืชืžืฉ ื‘-GitHub ื›ืื—ืกื•ืŸ ืงื•ื“ ืžืงื•ืจ. ื‘ื ื•ืกืฃ ืœืชืจื—ื™ืฉื™ ื”ื”ืคืขืœื” ื”ื "ืœ, ืืชื” ื™ื›ื•ืœ ืœื”ื•ืกื™ืฃ ืžืฉืœืš ื”ื•ื“ื•ืช ืœืืคืฉืจื•ื™ื•ืช ื”ืชืฆื•ืจื” ื”ื ืจื—ื‘ื•ืช. ื‘ืžืืžืจ ื–ื” ื ื’ื“ื™ืจ ืืช Travis CI ืœืขื‘ื•ื“ ืขื PVS-Studio ื‘ืืžืฆืขื•ืช ื“ื•ื’ืžื” ืœืงื•ื“ PPSSPP.

ืžื‘ื•ื

ื˜ืจื•ื•ื™ืก CI ื”ื•ื ืฉื™ืจื•ืช ืื™ื ื˜ืจื ื˜ ืœื‘ื ื™ื™ืช ื•ื‘ื“ื™ืงืช ืชื•ื›ื ื•ืช. ื”ื•ื ืžืฉืžืฉ ื‘ื“ืจืš ื›ืœืœ ื‘ืฉื™ืœื•ื‘ ืขื ืฉื™ื˜ื•ืช ืื™ื ื˜ื’ืจืฆื™ื” ืžืชืžืฉื›ื•ืช.

PPSSPP - ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืงื™ื PSP. ื”ืชื•ื›ื ื™ืช ืžืกื•ื’ืœืช ืœื—ืงื•ืช ืืช ื”ื”ืฉืงื” ืฉืœ ื›ืœ ืžืฉื—ืง ืžืชื•ืš ืชืžื•ื ื•ืช ื“ื™ืกืง ื”ืžื™ื•ืขื“ื•ืช ืขื‘ื•ืจ Sony PSP. ื”ืชื•ื›ื ื™ืช ืฉื•ื—ืจืจื” ื‘-1 ื‘ื ื•ื‘ืžื‘ืจ 2012. PPSSPP ืžื•ืจืฉื” ืชื—ืช GPL v2. ื›ืœ ืื—ื“ ื™ื›ื•ืœ ืœืขืฉื•ืช ืฉื™ืคื•ืจื™ื ืงื•ื“ ื”ืžืงื•ืจ ืฉืœ ื”ืคืจื•ื™ืงื˜.

ืกื˜ื•ื“ื™ื• PVS - ืžื ืชื— ืงื•ื“ ืกื˜ื˜ื™ ืœื—ื™ืคื•ืฉ ืฉื’ื™ืื•ืช ื•ืคื’ื™ืขื•ื™ื•ืช ืคื•ื˜ื ืฆื™ืืœื™ื•ืช ื‘ืงื•ื“ ื”ืชื•ื›ื ื™ืช. ื‘ืžืืžืจ ื–ื”, ืœืฉื ืฉื™ื ื•ื™, ื ืฉื™ืง ืืช PVS-Studio ืœื ื‘ืื•ืคืŸ ืžืงื•ืžื™ ืขืœ ื”ืžื—ืฉื‘ ืฉืœ ื”ืžืคืชื—, ืืœื ื‘ืขื ืŸ, ื•ื ื—ืคืฉ ืฉื’ื™ืื•ืช ื‘-PPSSPP.

ื”ื’ื“ืจืช Travis CI

ื ืฆื˜ืจืš ืžืื’ืจ ื‘-GitHub, ืฉื‘ื• ื ืžืฆื ื”ืคืจื•ื™ืงื˜ ืฉืื ื• ืฆืจื™ื›ื™ื, ื›ืžื• ื’ื ืžืคืชื— ืขื‘ื•ืจ PVS-Studio (ืชื•ื›ืœ ืœืงื‘ืœ ืžืคืชื— ื ื™ืกื™ื•ืŸ ืื• ื—ื™ื ื ืขื‘ื•ืจ ืคืจื•ื™ืงื˜ื™ ืงื•ื“ ืคืชื•ื—).

ื‘ื•ื ื ืœืš ืœืืชืจ ื˜ืจื•ื•ื™ืก CI. ืœืื—ืจ ื”ืจืฉืื” ื‘ืืžืฆืขื•ืช ื—ืฉื‘ื•ืŸ GitHub ืฉืœืš, ื ืจืื” ืจืฉื™ืžื” ืฉืœ ืžืื’ืจื™ื:

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
ืœื‘ื“ื™ืงื”, ื—ื™ืœืคืชื™ PPSSPP.

ืื ื• ืžืคืขื™ืœื™ื ืืช ื”ืžืื’ืจ ืฉืื ื• ืจื•ืฆื™ื ืœืืกื•ืฃ:

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
ื›ืจื’ืข, Travis CI ืœื ื™ื›ื•ืœ ืœื‘ื ื•ืช ืืช ื”ืคืจื•ื™ืงื˜ ืฉืœื ื• ื›ื™ ืื™ืŸ ื”ื•ืจืื•ืช ืœื‘ื ื™ื™ื”. ืื– ื”ื’ื™ืข ื”ื–ืžืŸ ืœื”ื’ื“ืจื”.

ื‘ืžื”ืœืš ื”ื ื™ืชื•ื—, ื›ืžื” ืžืฉืชื ื™ื ื™ื”ื™ื• ืฉื™ืžื•ืฉื™ื™ื ืขื‘ื•ืจื ื•, ืœืžืฉืœ, ื”ืžืคืชื— ืขื‘ื•ืจ PVS-Studio, ืฉืœื ืจืฆื•ื™ ืœืฆื™ื™ืŸ ื‘ืงื•ื‘ืฅ ื”ืชืฆื•ืจื”. ืื– ื‘ื•ืื• ื ื•ืกื™ืฃ ืžืฉืชื ื™ ืกื‘ื™ื‘ื” ื‘ืืžืฆืขื•ืช ื”ื’ื“ืจื•ืช ื”ื‘ื ื™ื™ื” ื‘-Travis CI:

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
ืื ื—ื ื• ืฆืจื™ื›ื™ื:

  • PVS_USERNAME - ืฉื ืžืฉืชืžืฉ
  • PVS_KEY - ืžืคืชื—
  • MAIL_USER - ืื™ืžื™ื™ืœ ืฉื™ืฉืžืฉ ืœืฉืœื™ื—ืช ื”ื“ื•ื—
  • MAIL_PASSWORD - ืกื™ืกืžืช ื“ื•ื"ืœ

ืฉื ื™ ื”ืื—ืจื•ื ื™ื ื”ื ืื•ืคืฆื™ื•ื ืœื™ื™ื. ืืœื” ื™ืฉืžืฉื• ืœืฉืœื™ื—ืช ืชื•ืฆืื•ืช ื‘ื“ื•ืืจ. ืื ื‘ืจืฆื•ื ืš ืœื”ืคื™ืฅ ืืช ื”ื“ื•ื— ื‘ื“ืจืš ืื—ืจืช, ืื™ืŸ ืฆื•ืจืš ืœืฆื™ื™ืŸ ืื•ืชื.

ืื–, ื”ื•ืกืคื ื• ืืช ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ื”ื“ืจื•ืฉื™ื ืœื ื•:

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
ืขื›ืฉื™ื• ื‘ื•ืื• ื ื™ืฆื•ืจ ืงื•ื‘ืฅ .travis.yml ื•ืœืžืงื ืื•ืชื• ื‘ืฉื•ืจืฉ ื”ืคืจื•ื™ืงื˜. ืœ-PPSSPP ื›ื‘ืจ ื”ื™ื” ืงื•ื‘ืฅ ืชืฆื•ืจื” ืขื‘ื•ืจ Travis CI, ืขื ื–ืืช, ื”ื•ื ื”ื™ื” ื’ื“ื•ืœ ืžื“ื™ ื•ืœื’ืžืจื™ ืœื ืžืชืื™ื ืœื“ื•ื’ืžื, ืื– ื”ื™ื™ื ื• ืฆืจื™ื›ื™ื ืœืคืฉื˜ ืื•ืชื• ืžืื•ื“ ื•ืœื”ืฉืื™ืจ ืจืง ืืช ื”ืืœืžื ื˜ื™ื ื”ื‘ืกื™ืกื™ื™ื.

ืจืืฉื™ืช, ื ืฆื™ื™ืŸ ืืช ื”ืฉืคื”, ืืช ื”ื’ืจืกื” ืฉืœ ืื•ื‘ื•ื ื˜ื• ืœื™ื ื•ืงืก ื‘ื” ืื ื• ืจื•ืฆื™ื ืœื”ืฉืชืžืฉ ื‘ืžื›ื•ื ื” ื”ื•ื™ืจื˜ื•ืืœื™ืช, ื•ื”ื—ื‘ื™ืœื•ืช ื”ื“ืจื•ืฉื•ืช ืœื‘ื ื™ื™ื”:

language: cpp
dist: xenial

addons:
  apt:
    update: true
    packages:
      - ant
      - aria2
      - build-essential
      - cmake
      - libgl1-mesa-dev
      - libglu1-mesa-dev
      - libsdl2-dev
      - pv
      - sendemail
      - software-properties-common
    sources:
      - sourceline: 'ppa:ubuntu-toolchain-r/test'
      - sourceline: 'ppa:ubuntu-sdk-team/ppa'

ื›ืœ ื”ื—ื‘ื™ืœื•ืช ื”ืžืคื•ืจื˜ื•ืช ื ื—ื•ืฆื•ืช ืืš ื•ืจืง ืขื‘ื•ืจ PPSSPP.

ื›ืขืช ืื ื• ืžืฆื™ื™ื ื™ื ืืช ืžื˜ืจื™ืฆืช ื”ื”ืจื›ื‘ื”:

matrix:
  include:
    - os: linux
      compiler: "gcc"
      env: PPSSPP_BUILD_TYPE=Linux PVS_ANALYZE=Yes
    - os: linux
      compiler: "clang"
      env: PPSSPP_BUILD_TYPE=Linux

ืขื•ื“ ืงืฆืช ืขืœ ื”ืกืขื™ืฃ ืžึทื˜ืจึดื™ืฆึธื”. ื‘-Travis CI ื™ืฉื ืŸ ืฉืชื™ ื“ืจื›ื™ื ืœื™ืฆื•ืจ ืืคืฉืจื•ื™ื•ืช ื‘ื ื™ื™ื”: ื”ืจืืฉื•ื ื” ื”ื™ื ืœืฆื™ื™ืŸ ืจืฉื™ืžื” ืฉืœ ืžื”ื“ืจื™ื, ืกื•ื’ื™ ืžืขืจื›ื•ืช ื”ืคืขืœื”, ืžืฉืชื ื™ ืกื‘ื™ื‘ื” ื•ื›ื•', ื•ืœืื—ืจ ืžื›ืŸ ื ื•ืฆืจืช ืžื˜ืจื™ืฆื” โ€‹โ€‹ืฉืœ ื›ืœ ื”ืฉื™ืœื•ื‘ื™ื ื”ืืคืฉืจื™ื™ื; ื”ืฉื ื™ ื”ื•ื ืื™ื ื“ื™ืงืฆื™ื” ืžืคื•ืจืฉืช ืฉืœ ื”ืžื˜ืจื™ืฆื”. ื›ืžื•ื‘ืŸ, ื ื™ืชืŸ ืœืฉืœื‘ ืืช ืฉืชื™ ื”ื’ื™ืฉื•ืช ื”ืœืœื• ื•ืœื”ื•ืกื™ืฃ ืžืงืจื” ื™ื™ื—ื•ื“ื™, ืื• ืœื”ื™ืคืš, ืœื ืœื›ืœื•ืœ ืื•ืชื• ื‘ืืžืฆืขื•ืช ื”ืกืขื™ืฃ ืœื”ื•ืฆื™ื. ืืชื” ื™ื›ื•ืœ ืœืงืจื•ื ืขื•ื“ ืขืœ ื–ื” ื‘ ืชื™ืขื•ื“ Travis CI.

ื›ืœ ืžื” ืฉื ื•ืชืจ ื”ื•ื ืœืกืคืง ื”ื•ืจืื•ืช ื”ืจื›ื‘ื” ืกืคืฆื™ืคื™ื•ืช ืœืคืจื•ื™ืงื˜:

before_install:
  - travis_retry bash .travis.sh travis_before_install

install:
  - travis_retry bash .travis.sh travis_install

script:
  - bash .travis.sh travis_script

after_success:
  - bash .travis.sh travis_after_success

Travis CI ืžืืคืฉืจ ืœืš ืœื”ื•ืกื™ืฃ ืคืงื•ื“ื•ืช ืžืฉืœืš ืขื‘ื•ืจ ืฉืœื‘ื™ื ืฉื•ื ื™ื ื‘ื—ื™ื™ื” ืฉืœ ืžื›ื•ื ื” ื•ื™ืจื˜ื•ืืœื™ืช. ืกึธืขึดื™ืฃ ืœืคื ื™_ื”ืชืงื ื” ื‘ื•ืฆืข ืœืคื ื™ ื”ืชืงื ืช ื—ื‘ื™ืœื•ืช. ืœืื—ืจ ืžื›ืŸ ืœื”ืชืงื™ืŸ, ืืฉืจ ืขื•ืงื‘ ืื—ืจ ื”ืชืงื ืช ื”ื—ื‘ื™ืœื•ืช ืžื”ืจืฉื™ืžื” addons.aptืฉืฆื™ื™ื ื• ืœืžืขืœื”. ื”ื”ืจื›ื‘ื” ืขืฆืžื” ืžืชืงื™ื™ืžืช ื‘ ืชืกืจื™ื˜. ืื ื”ื›ืœ ื”ืœืš ื›ืฉื•ืจื”, ืื– ืื ื—ื ื• ืžื•ืฆืื™ื ืืช ืขืฆืžื ื• ืคื ื™ืžื” ืื—ืจื™_ื”ืฆืœื—ื” (ื‘ื—ืœืง ื–ื” ื ืคืขื™ืœ ื ื™ืชื•ื— ืกื˜ื˜ื™). ืืœื” ืœื ื›ืœ ื”ืฉืœื‘ื™ื ืฉื ื™ืชืŸ ืœืฉื ื•ืช, ืื ืืชื” ืฆืจื™ืš ื™ื•ืชืจ, ืื– ืืชื” ืฆืจื™ืš ืœื”ืกืชื›ืœ ืคื ื™ืžื” ืชื™ืขื•ื“ Travis CI.

ื›ื“ื™ ืœื”ืงืœ ืขืœ ื”ืงืจื™ืื”, ื”ืคืงื•ื“ื•ืช ื”ื•ืฆื‘ื• ื‘ืกืงืจื™ืคื˜ ื ืคืจื“ .travis.sh, ืืฉืจ ืžืžื•ืงื ื‘ืฉื•ืจืฉ ื”ืคืจื•ื™ืงื˜.

ืื– ื™ืฉ ืœื ื• ืืช ื”ืงื•ื‘ืฅ ื”ื‘ื .travis.yml:

language: cpp
dist: xenial

addons:
  apt:
    update: true
    packages:
      - ant
      - aria2
      - build-essential
      - cmake
      - libgl1-mesa-dev
      - libglu1-mesa-dev
      - libsdl2-dev
      - pv
      - sendemail
      - software-properties-common
    sources:
      - sourceline: 'ppa:ubuntu-toolchain-r/test'
      - sourceline: 'ppa:ubuntu-sdk-team/ppa'

matrix:
  include:
    - os: linux
      compiler: "gcc"
      env: PVS_ANALYZE=Yes
    - os: linux
      compiler: "clang"

before_install:
  - travis_retry bash .travis.sh travis_before_install

install:
  - travis_retry bash .travis.sh travis_install

script:
  - bash .travis.sh travis_script

after_success:
  - bash .travis.sh travis_after_success

ืœืคื ื™ ื”ืชืงื ืช ื”ื—ื‘ื™ืœื•ืช, ื ืขื“ื›ืŸ ืืช ืชืช-ื”ืžื•ื“ื•ืœื™ื. ื–ื” ื ื—ื•ืฅ ื›ื“ื™ ืœื‘ื ื•ืช PPSSPP. ื‘ื•ืื• ื ื•ืกื™ืฃ ืืช ื”ืคื•ื ืงืฆื™ื” ื”ืจืืฉื•ื ื” ืœ .travis.sh (ืฉื™ืžื• ืœื‘ ืœื”ืจื—ื‘ื”):

travis_before_install() {
  git submodule update --init --recursive
}

ื›ืขืช ืื ื• ืžื’ื™ืขื™ื ื™ืฉื™ืจื•ืช ืœื”ื’ื“ืจืช ื”ื”ืฉืงื” ื”ืื•ื˜ื•ืžื˜ื™ืช ืฉืœ PVS-Studio ื‘-Travis CI. ืจืืฉื™ืช ืขืœื™ื ื• ืœื”ืชืงื™ืŸ ืืช ื—ื‘ื™ืœืช PVS-Studio ืขืœ ื”ืžืขืจื›ืช:

travis_install() {
  if [ "$CXX" = "g++" ]; then
    sudo apt-get install -qq g++-4.8
  fi
  
  if [ "$PVS_ANALYZE" = "Yes" ]; then
    wget -q -O - https://files.viva64.com/etc/pubkey.txt 
      | sudo apt-key add -
    sudo wget -O /etc/apt/sources.list.d/viva64.list 
      https://files.viva64.com/etc/viva64.list  
    
    sudo apt-get update -qq
    sudo apt-get install -qq pvs-studio 
                             libio-socket-ssl-perl 
                             libnet-ssleay-perl
  fi
    
  download_extract 
    "https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz" 
    cmake-3.6.2-Linux-x86_64.tar.gz
}

ื‘ืชื—ื™ืœืช ื”ืคื•ื ืงืฆื™ื” travis_install ืื ื• ืžืชืงื™ื ื™ื ืืช ื”ืžื”ื“ืจื™ื ืฉืื ื• ืฆืจื™ื›ื™ื ื‘ืืžืฆืขื•ืช ืžืฉืชื ื™ ืกื‘ื™ื‘ื”. ื•ืื– ืื ื”ืžืฉืชื ื” $PVS_ANALYZE ืฉื•ืžืจืช ืขืจืš ื™ืฉ (ืฆื™ื™ื ื• ื–ืืช ื‘ืกืขื™ืฃ env ื‘ืžื”ืœืš ืชืฆื•ืจืช ื”ืžื˜ืจื™ืฆื” โ€‹โ€‹ืœื‘ื ื•ืช), ืื ื• ืžืชืงื™ื ื™ื ืืช ื”ื—ื‘ื™ืœื” pvs-studio. ื‘ื ื•ืกืฃ ืœื›ืš, ืžืฆื•ื™ื ื•ืช ื’ื ื—ื‘ื™ืœื•ืช libio-socket-ssl-perl ะธ libnet-ssleay-perl, ืขื ื–ืืช, ื”ื ื ื“ืจืฉื™ื ืขื‘ื•ืจ ืฉืœื™ื—ืช ืชื•ืฆืื•ืช ื‘ื“ื•ืืจ, ื•ืœื›ืŸ ื”ื ืื™ื ื ื ื—ื•ืฆื™ื ืื ื‘ื—ืจืช ื‘ืฉื™ื˜ื” ืื—ืจืช ืœื”ืขื‘ืจืช ื”ื“ื•ื— ืฉืœืš.

ืคื•ื ืงืฆื™ื” ื”ื•ืจื“ื”_ื—ืœืฅ ืžื•ืจื™ื“ ื•ืžืคืจืง ืืช ื”ืืจื›ื™ื•ืŸ ืฉืฆื•ื™ืŸ:

download_extract() {
  aria2c -x 16 $1 -o $2
  tar -xf $2
}

ื”ื’ื™ืข ื”ื–ืžืŸ ืœื”ืจื›ื™ื‘ ืืช ื”ืคืจื•ื™ืงื˜. ื–ื” ืงื•ืจื” ื‘ืกืขื™ืฃ ืชืกืจื™ื˜:

travis_script() {
  if [ -d cmake-3.6.2-Linux-x86_64 ]; then
    export PATH=$(pwd)/cmake-3.6.2-Linux-x86_64/bin:$PATH
  fi
  
  CMAKE_ARGS="-DHEADLESS=ON ${CMAKE_ARGS}"
  if [ "$PVS_ANALYZE" = "Yes" ]; then
    CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
  fi
  cmake $CMAKE_ARGS CMakeLists.txt
  make
}

ืœืžืขืฉื”, ื–ื•ื”ื™ ืชืฆื•ืจื” ืžืงื•ืจื™ืช ืคืฉื•ื˜ื”, ืœืžืขื˜ ืฉื•ืจื•ืช ืืœื”:

if [ "$PVS_ANALYZE" = "Yes" ]; then
  CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
fi

ื‘ื—ืœืง ื–ื” ืฉืœ ื”ืงื•ื“ ืฉืงื‘ืขื ื• ืขื‘ื•ืจ cmmake ื“ื’ืœ ืœื™ื™ืฆื•ื ืคืงื•ื“ื•ืช ืงื•ืžืคื™ืœืฆื™ื”. ื–ื” ื”ื›ืจื—ื™ ืขื‘ื•ืจ ืžื ืชื— ืงื•ื“ ืกื˜ื˜ื™. ืชื•ื›ืœ ืœืงืจื•ื ืขื•ื“ ืขืœ ื›ืš ื‘ืžืืžืจ "ื›ื™ืฆื“ ืœื”ืคืขื™ืœ PVS-Studio ืขืœ ืœื™ื ื•ืงืก ื•-macOS".

ืื ื”ื”ืจื›ื‘ื” ื”ื™ื™ืชื” ืžื•ืฆืœื—ืช, ืื– ื ื’ื™ืข ืื—ืจื™_ื”ืฆืœื—ื”, ืฉื‘ื• ืื ื• ืžื‘ืฆืขื™ื ื ื™ืชื•ื— ืกื˜ื˜ื™:

travis_after_success() {
  if [ "$PVS_ANALYZE" = "Yes" ]; then
    pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
    pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic 
                                    -o PVS-Studio-${CC}.log 
                                    --disableLicenseExpirationCheck
    
    plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html
    sendemail -t [email protected] 
              -u "PVS-Studio $CC report, commit:$TRAVIS_COMMIT" 
              -m "PVS-Studio $CC report, commit:$TRAVIS_COMMIT" 
              -s smtp.gmail.com:587 
              -xu $MAIL_USER 
              -xp $MAIL_PASSWORD 
              -o tls=yes 
              -f $MAIL_USER 
              -a PVS-Studio-${CC}.log PVS-Studio-${CC}.html
  fi
}

ื‘ื•ืื• ื ืกืชื›ืœ ืžืงืจื•ื‘ ืขืœ ื”ืฉื•ืจื•ืช ื”ื‘ืื•ืช:

pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic 
                                -o PVS-Studio-${CC}.log 
                                --disableLicenseExpirationCheck
plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html

ื”ืฉื•ืจื” ื”ืจืืฉื•ื ื” ื™ื•ืฆืจืช ืงื•ื‘ืฅ ืจื™ืฉื™ื•ืŸ ืžืชื•ืš ืฉื ื”ืžืฉืชืžืฉ ื•ื”ืžืคืชื— ืฉืฆื™ื™ื ื• ื›ื‘ืจ ื‘ื”ืชื—ืœื” ื‘ืขืช ื”ื’ื“ืจืช ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ืฉืœ Travis CI.

ื”ืฉื•ืจื” ื”ืฉื ื™ื™ื” ืžืชื—ื™ืœื” ืืช ื”ื ื™ืชื•ื— ื™ืฉื™ืจื•ืช. ื“ึถื’ึถืœ -ื™ ืžื’ื“ื™ืจ ืืช ืžืกืคืจ ื”ืฉืจืฉื•ืจื™ื ืœื ื™ืชื•ื—, ื“ื’ืœ -ืœ ืžืฆื™ื™ืŸ ืจื™ืฉื™ื•ืŸ, ื“ื’ืœ -ืื• ืžื’ื“ื™ืจ ืืช ื”ืงื•ื‘ืฅ ืœืคืœื˜ ื™ื•ืžื ื™ื, ื•ืืช ื”ื“ื’ืœ -disableLicenseExpirationCheck ื ื“ืจืฉ ืขื‘ื•ืจ ื’ืจืกืื•ืช ื ื™ืกื™ื•ืŸ, ืฉื›ืŸ ื›ื‘ืจื™ืจืช ืžื—ื“ืœ pvs-studio-analyzer ื™ื–ื”ื™ืจ ืืช ื”ืžืฉืชืžืฉ ืฉื”ืจื™ืฉื™ื•ืŸ ืขื•ืžื“ ืœืคื•ื’. ื›ื“ื™ ืœืžื ื•ืข ืืช ื–ื”, ืืชื” ื™ื›ื•ืœ ืœืฆื™ื™ืŸ ื“ื’ืœ ื–ื”.

ืงื•ื‘ืฅ ื”ื™ื•ืžืŸ ืžื›ื™ืœ ืคืœื˜ ื’ื•ืœืžื™ ืฉืœื ื ื™ืชืŸ ืœืงืจื•ื ืœืœื ื”ืžืจื”, ืื– ืชื—ื™ืœื” ืขืœื™ืš ืœื”ืคื•ืš ืืช ื”ืงื•ื‘ืฅ ืœืงืจื™ื. ื‘ื•ืื• ื ืขื‘ื™ืจ ืืช ื”ื™ื•ืžื ื™ื ืžืžื™ืจ-plog, ื•ื”ืคืœื˜ ื”ื•ื ืงื•ื‘ืฅ HTML.

ื‘ื“ื•ื’ืžื” ื–ื•, ื”ื—ืœื˜ืชื™ ืœืฉืœื•ื— ื“ื•ื—ื•ืช ื‘ื“ื•ืืจ ื‘ืืžืฆืขื•ืช ื”ืคืงื•ื“ื” ืฉืœื— ืื™ืžื™ื™ืœ.

ื›ืชื•ืฆืื” ืžื›ืš, ืงื™ื‘ืœื ื• ืืช ื”ืงื•ื‘ืฅ ื”ื‘ื .travis.sh:

#/bin/bash

travis_before_install() {
  git submodule update --init --recursive
}

download_extract() {
  aria2c -x 16 $1 -o $2
  tar -xf $2
}

travis_install() {
  if [ "$CXX" = "g++" ]; then
    sudo apt-get install -qq g++-4.8
  fi
  
  if [ "$PVS_ANALYZE" = "Yes" ]; then
    wget -q -O - https://files.viva64.com/etc/pubkey.txt 
      | sudo apt-key add -
    sudo wget -O /etc/apt/sources.list.d/viva64.list 
      https://files.viva64.com/etc/viva64.list  
    
    sudo apt-get update -qq
    sudo apt-get install -qq pvs-studio 
                             libio-socket-ssl-perl 
                             libnet-ssleay-perl
  fi
    
  download_extract 
    "https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz" 
    cmake-3.6.2-Linux-x86_64.tar.gz
}
travis_script() {
  if [ -d cmake-3.6.2-Linux-x86_64 ]; then
    export PATH=$(pwd)/cmake-3.6.2-Linux-x86_64/bin:$PATH
  fi
  
  CMAKE_ARGS="-DHEADLESS=ON ${CMAKE_ARGS}"
  if [ "$PVS_ANALYZE" = "Yes" ]; then
    CMAKE_ARGS="-DCMAKE_EXPORT_COMPILE_COMMANDS=On ${CMAKE_ARGS}"
  fi
  cmake $CMAKE_ARGS CMakeLists.txt
  make
}
travis_after_success() {
  if [ "$PVS_ANALYZE" = "Yes" ]; then
    pvs-studio-analyzer credentials $PVS_USERNAME $PVS_KEY -o PVS-Studio.lic
    pvs-studio-analyzer analyze -j2 -l PVS-Studio.lic 
                                    -o PVS-Studio-${CC}.log 
                                    --disableLicenseExpirationCheck
    
    plog-converter -t html PVS-Studio-${CC}.log -o PVS-Studio-${CC}.html
    sendemail -t [email protected] 
              -u "PVS-Studio $CC report, commit:$TRAVIS_COMMIT" 
              -m "PVS-Studio $CC report, commit:$TRAVIS_COMMIT" 
              -s smtp.gmail.com:587 
              -xu $MAIL_USER 
              -xp $MAIL_PASSWORD 
              -o tls=yes 
              -f $MAIL_USER 
              -a PVS-Studio-${CC}.log PVS-Studio-${CC}.html
  fi
}
set -e
set -x

$1;

ืขื›ืฉื™ื• ื”ื’ื™ืข ื”ื–ืžืŸ ืœื“ื—ื•ืฃ ืืช ื”ืฉื™ื ื•ื™ื™ื ืœืžืื’ืจ git, ื•ืœืื—ืจ ืžื›ืŸ Travis CI ื™ืจื™ืฅ ืื•ื˜ื•ืžื˜ื™ืช ืืช ื”-build. ืœื—ืฅ ืขืœ "ppsspp" ื›ื“ื™ ืœืขื‘ื•ืจ ืœื“ื•ื—ื•ืช ื”ื‘ื ื™ื™ื”:

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
ื ืจืื” ืกืงื™ืจื” ื›ืœืœื™ืช ืฉืœ ื”ืžื‘ื ื” ื”ื ื•ื›ื—ื™:

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP
ืื ื”ื‘ื ื™ื™ื” ืชืกืชื™ื™ื ื‘ื”ืฆืœื—ื”, ื ืงื‘ืœ ืžื™ื™ืœ ืขื ืชื•ืฆืื•ืช ื”ื ื™ืชื•ื— ื”ืกื˜ื˜ื™. ื›ืžื•ื‘ืŸ ืฉื“ื™ื•ื•ืจ ืื™ื ื• ื”ื“ืจืš ื”ื™ื—ื™ื“ื” ืœืงื‘ืœ ื“ื™ื•ื•ื—. ืืชื” ื™ื›ื•ืœ ืœื‘ื—ื•ืจ ื›ืœ ืฉื™ื˜ืช ื™ื™ืฉื•ื. ืื‘ืœ ื—ืฉื•ื‘ ืœื–ื›ื•ืจ ืฉืœืื—ืจ ื”ืฉืœืžืช ื”ื‘ื ื™ื™ื”, ืœื ื ื™ืชืŸ ื™ื”ื™ื” ืœื’ืฉืช ืœืงื‘ืฆื™ ื”ืžื—ืฉื‘ ื”ื•ื™ืจื˜ื•ืืœื™.

ืกื™ื›ื•ื ืฉื’ื™ืื”

ืกื™ื™ืžื ื• ื‘ื”ืฆืœื—ื” ืืช ื”ื—ืœืง ื”ืงืฉื” ื‘ื™ื•ืชืจ. ืขื›ืฉื™ื• ื‘ื•ืื• ื ื•ื•ื“ื ืฉื›ืœ ื”ืžืืžืฆื™ื ืฉืœื ื• ืฉื•ื•ื™ื ืืช ื–ื”. ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ื›ืžื” ื ืงื•ื“ื•ืช ืžืขื ื™ื™ื ื•ืช ืžื“ื•ื— ื”ื ื™ืชื•ื— ื”ืกื˜ื˜ื™ ืฉื”ื’ื™ืข ืืœื™ ื‘ื“ื•ืืจ (ืœื ื‘ื›ื“ื™ ืฆื™ื™ื ืชื™ ื–ืืช).

ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืžืกื•ื›ื ืช

void sha1( unsigned char *input, int ilen, unsigned char output[20] )
{
  sha1_context ctx;

  sha1_starts( &ctx );
  sha1_update( &ctx, input, ilen );
  sha1_finish( &ctx, output );

  memset( &ctx, 0, sizeof( sha1_context ) );
}

ืื–ื”ืจืช PVS-Studio: V597 ื”ืžื”ื“ืจ ื™ื›ื•ืœ ืœืžื—ื•ืง ืืช ืงืจื™ืืช ื”ืคื•ื ืงืฆื™ื” 'memset', ื”ืžืฉืžืฉืช ืœื ื™ืงื•ื™ ืžืื’ืจ 'sum'. ื™ืฉ ืœื”ืฉืชืžืฉ ื‘ืคื•ื ืงืฆื™ื” RtlSecureZeroMemory() ื›ื“ื™ ืœืžื—ื•ืง ืืช ื”ื ืชื•ื ื™ื ื”ืคืจื˜ื™ื™ื. sha1.cpp 325

ืคื™ืกืช ืงื•ื“ ื–ื• ืžืžื•ืงืžืช ื‘ืžื•ื“ื•ืœ ื”ื’ื™ื‘ื•ื‘ ื”ืžืื•ื‘ื˜ื—, ืื•ืœื ื”ื™ื ืžื›ื™ืœื” ืคื’ื ืื‘ื˜ื—ื” ื—ืžื•ืจ (CWE-14). ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ืจืฉื™ืžืช ื”ื”ืจื›ื‘ื” ืฉื ื•ืฆืจืช ื‘ืขืช ื”ื™ื“ื•ืจ ืฉืœ ื’ืจืกืช Debug:

; Line 355
  mov r8d, 20
  xor edx, edx
  lea rcx, QWORD PTR sum$[rsp]
  call memset
; Line 356

ื”ื›ืœ ืžืกื•ื“ืจ ื•ื”ืคื•ื ืงืฆื™ื” ืžืžื˜ ืžื‘ื•ืฆืข, ื•ื‘ื›ืš ืžื“ืจื•ืก ื ืชื•ื ื™ื ื—ืฉื•ื‘ื™ื ื‘-RAM, ืขื ื–ืืช, ืืœ ืชืฉืžื— ืขื“ื™ื™ืŸ. ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ืจืฉื™ืžืช ื”ื”ืจื›ื‘ื” ืฉืœ ื’ืจืกืช ื”ืฉื—ืจื•ืจ ืขื ืื•ืคื˜ื™ืžื™ื–ืฆื™ื”:

; 354  :
; 355  :  memset( sum, 0, sizeof( sum ) );
; 356  :}

ื›ืคื™ ืฉื ื™ืชืŸ ืœืจืื•ืช ืžื”ืจื™ืฉื•ื, ื”ืžื”ื“ืจ ื”ืชืขืœื ืžื”ืงืจื™ืื” ืžืžื˜. ื–ืืช ื‘ืฉืœ ื”ืขื•ื‘ื“ื” ืฉื‘ืคื•ื ืงืฆื™ื” sha1 ืœืื—ืจ ื”ืฉื™ื—ื” ืžืžื˜ ืื™ืŸ ืขื•ื“ ื”ืชื™ื™ื—ืกื•ืช ืœืžื‘ื ื” ctx. ืœื›ืŸ, ื”ืžื”ื“ืจ ืœื ืจื•ืื” ื˜ืขื ืœื‘ื–ื‘ื– ื–ืžืŸ ืžืขื‘ื“ ืขืœ ื”ื—ืœืคืช ื–ื™ื›ืจื•ืŸ ืฉืœื ื™ื”ื™ื” ื‘ืฉื™ืžื•ืฉ ื‘ืขืชื™ื“. ืืชื” ื™ื›ื•ืœ ืœืชืงืŸ ื–ืืช ื‘ืืžืฆืขื•ืช ื”ืคื•ื ืงืฆื™ื” RtlSecureZeroMemory ืื• ื“ื•ืžื” ืฉืึถืœึธื”.

ื ื›ื•ืŸ:

void sha1( unsigned char *input, int ilen, unsigned char output[20] )
{
  sha1_context ctx;

  sha1_starts( &ctx );
  sha1_update( &ctx, input, ilen );
  sha1_finish( &ctx, output );

  RtlSecureZeroMemory(&ctx, sizeof( sha1_context ) );
} 

ื”ืฉื•ื•ืื” ืžื™ื•ืชืจืช

static u32 sceAudioOutputPannedBlocking
             (u32 chan, int leftvol, int rightvol, u32 samplePtr) {
  int result = 0;
  // For some reason, this is the only one that checks for negative.
  if (leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0) {
    ....
  } else {
    if (leftvol >= 0) {
      chans[chan].leftVolume = leftvol;
    }
    if (rightvol >= 0) {
      chans[chan].rightVolume = rightvol;
    }
    chans[chan].sampleAddress = samplePtr;
    result = __AudioEnqueue(chans[chan], chan, true);
  }
}

ืื–ื”ืจืช PVS-Studio: V547 ื”ื‘ื™ื˜ื•ื™ 'leftvol >= 0' ื”ื•ื ืชืžื™ื“ ื ื›ื•ืŸ. sceAudio.cpp 120

ืฉื™ืžื• ืœื‘ ืœืกื ื™ืฃ else ืœืจืืฉื•ื ื™ื if. ื”ืงื•ื“ ื™ื‘ื•ืฆืข ืจืง ืื ื›ืœ ื”ืชื ืื™ื leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0 ื™ืชื‘ืจืจ ื›ืฉืงืจื™. ืœื›ืŸ, ืื ื• ืžืงื‘ืœื™ื ืืช ื”ื”ืฆื”ืจื•ืช ื”ื‘ืื•ืช, ืฉื™ื”ื™ื• ื ื›ื•ื ื•ืช ืขื‘ื•ืจ ืขื ืฃ else: leftvol <= 0xFFFF, rightvol <= 0xFFFF, leftvol >= 0 ะธ rightvol >= 0. ืฉื™ืžื• ืœื‘ ืœืฉืชื™ ื”ื”ืฆื”ืจื•ืช ื”ืื—ืจื•ื ื•ืช. ื”ืื ื™ืฉ ื˜ืขื ืœื‘ื“ื•ืง ืžื”ื• ืชื ืื™ ื”ื›ืจื—ื™ ืœื‘ื™ืฆื•ืข ืงื˜ืข ืงื•ื“ ื–ื”?

ืื– ื ื•ื›ืœ ืœื”ืกื™ืจ ื‘ื‘ื˜ื—ื” ืืช ื”ื”ืฆื”ืจื•ืช ื”ืžื•ืชื ื•ืช ื”ืืœื”:

static u32 sceAudioOutputPannedBlocking
(u32 chan, int leftvol, int rightvol, u32 samplePtr) {
  int result = 0;
  // For some reason, this is the only one that checks for negative.
  if (leftvol > 0xFFFF || rightvol > 0xFFFF || leftvol < 0 || rightvol < 0) {
    ....
  } else {
    chans[chan].leftVolume = leftvol;
    chans[chan].rightVolume = rightvol;

    chans[chan].sampleAddress = samplePtr;
    result = __AudioEnqueue(chans[chan], chan, true);
  }
}

ืขื•ื“ ืชืจื—ื™ืฉ. ื™ืฉ ืื™ื–ื•ืฉื”ื™ ืฉื’ื™ืื” ืžืกืชืชืจืช ืžืื—ื•ืจื™ ื”ืชื ืื™ื ื”ืžื™ื•ืชืจื™ื ื”ืืœื”. ืื•ืœื™ ืœื ื‘ื“ืงื• ืžื” ื ื“ืจืฉ.

Ctrl+C Ctrl+V ืžื›ื” ื—ื–ืจื”

static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
  if (!Memory::IsValidAddress(psmfData) ||
      !Memory::IsValidAddress(psmfData)) {
    return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
  }
  ....
}

V501 ื™ืฉ ื‘ื™ื˜ื•ื™ื™ ืžืฉื ื” ื–ื”ื™ื '!Memory::IsValidAddress(psmfData)' ืžืฉืžืืœ ื•ืžื™ืžื™ืŸ ืœ'||' ืžึทืคืขึดื™ืœ. scePsmf.cpp 703

ืฉื™ืžื• ืœื‘ ืœืฉื™ืง ื‘ืคื ื™ื if. ืืชื” ืœื ื—ื•ืฉื‘ ืฉื–ื” ืžื•ื–ืจ ืฉืื ื—ื ื• ื‘ื•ื“ืงื™ื ืื ื”ื›ืชื•ื‘ืช ืชืงืคื”? psmfData, ืคื™ ืฉืชื™ื™ื? ืื– ื–ื” ื ืจืื” ืœื™ ืžื•ื–ืจ... ืœืžืขืฉื”, ื–ื• ื›ืžื•ื‘ืŸ ื˜ืขื•ืช ื”ืงืœื“ื”, ื•ื”ืจืขื™ื•ืŸ ื”ื™ื” ืœื‘ื“ื•ืง ืืช ืฉื ื™ ืคืจืžื˜ืจื™ ื”ืงืœื˜.

ืืคืฉืจื•ืช ื ื›ื•ื ื”:

static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
  if (!Memory::IsValidAddress(psmfStruct) ||
      !Memory::IsValidAddress(psmfData)) {
    return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
  }
  ....
}

ืžืฉืชื ื” ื ืฉื›ื—

extern void ud_translate_att(
  int size = 0;
  ....
  if (size == 8) {
    ud_asmprintf(u, "b");
  } else if (size == 16) {
    ud_asmprintf(u, "w");
  } else if (size == 64) {
    ud_asmprintf(u, "q");
  }
  ....
}

ืื–ื”ืจืช PVS-Studio: V547 ื”ื‘ื™ื˜ื•ื™ 'ื’ื•ื“ืœ == 8' ื”ื•ื ืชืžื™ื“ ืฉืงืจ. syn-att.c 195

ืฉื’ื™ืื” ื–ื• ืžืžื•ืงืžืช ื‘ืชื™ืงื™ื™ื” ืฉืœื•ื—ื”, ืื– ืœื ืžืžืฉ ืจืœื•ื•ื ื˜ื™ ืœืคืจื•ื™ืงื˜, ืื‘ืœ ื”ื‘ืื’ ื ืžืฆื ืœืคื ื™ ืฉื”ื‘ื—ื ืชื™ ื‘ื•, ืื– ื”ื—ืœื˜ืชื™ ืœืขื–ื•ื‘ ืื•ืชื•. ืื—ืจื™ ื”ื›ืœ, ืžืืžืจ ื–ื” ืœื ืขื•ืกืง ื‘ื‘ื“ื™ืงืช ืฉื’ื™ืื•ืช, ืืœื ื‘ืื™ื ื˜ื’ืจืฆื™ื” ืขื Travis CI, ื•ืœื ื‘ื•ืฆืขื” ืชืฆื•ืจื” ืฉืœ ื”ื ืชื—.

ืžืฉืชื ื” ื’ื•ื“ืœ ืืชื—ื•ืœ ืขืœ ื™ื“ื™ ืงื‘ื•ืข, ืขื ื–ืืช, ื”ื•ื ืื™ื ื• ื‘ืฉื™ืžื•ืฉ ื›ืœืœ ื‘ืงื•ื“, ืขื“ ืœืื•ืคืจื˜ื•ืจ if, ืžื” ืฉื›ืžื•ื‘ืŸ ื ื•ืชืŸ ืฉืงืจ ืชื•ืš ื›ื“ื™ ื‘ื“ื™ืงืช ื”ืชื ืื™ื, ื›ื™ ื›ื–ื›ื•ืจ, ื’ื•ื“ืœ ืฉื•ื•ื” ืœืืคืก. ื’ื ืœื‘ื“ื™ืงื•ืช ื”ื‘ืื•ืช ืื™ืŸ ื”ื™ื’ื™ื•ืŸ.

ื›ื›ืœ ื”ื ืจืื”, ื”ืžื—ื‘ืจ ืฉืœ ืงื˜ืข ื”ืงื•ื“ ืฉื›ื— ืœื”ื—ืœื™ืฃ ืืช ื”ืžืฉืชื ื” ื’ื•ื“ืœ ืœืคื ื™ ืฉ.

ืขืฆื•ืจ

ื›ืืŸ ื›ื ืจืื” ื ืกื™ื™ื ืขื ื”ื˜ืขื•ื™ื•ืช. ืžื˜ืจืช ืžืืžืจ ื–ื” ื”ื™ื ืœื”ื“ื’ื™ื ืืช ืขื‘ื•ื“ืชื• ืฉืœ PVS-Studio ื™ื—ื“ ืขื Travis CI, ื•ืœื ืœื ืชื— ืืช ื”ืคืจื•ื™ืงื˜ ื‘ืฆื•ืจื” ื™ืกื•ื“ื™ืช ื›ื›ืœ ื”ืืคืฉืจ. ืื ืืชื” ืจื•ืฆื” ื˜ืขื•ื™ื•ืช ื’ื“ื•ืœื•ืช ื•ื™ืคื•ืช ื™ื•ืชืจ, ืืชื” ืชืžื™ื“ ื™ื›ื•ืœ ืœื”ืชืคืขืœ ืžื”ืŸ ื›ืืŸ :).

ืžืกืงื ื”

ืฉื™ืžื•ืฉ ื‘ืฉื™ืจื•ืชื™ ืื™ื ื˜ืจื ื˜ ืœื‘ื ื™ื™ืช ืคืจื•ื™ืงื˜ื™ื ื™ื—ื“ ืขื ืชืจื’ื•ืœ ืฉืœ ื ื™ืชื•ื— ืžืฆื˜ื‘ืจ ืžืืคืฉืจ ืœืš ืœืžืฆื•ื ื‘ืขื™ื•ืช ืจื‘ื•ืช ืžื™ื“ ืœืื—ืจ ืžื™ื–ื•ื’ ืงื•ื“. ืขื ื–ืืช, ื™ื™ืชื›ืŸ ืฉืžื‘ื ื” ืื—ื“ ืœื ื™ืกืคื™ืง, ื›ืš ืฉื”ื’ื“ืจืช ื‘ื“ื™ืงื•ืช ื™ื—ื“ ืขื ื ื™ืชื•ื— ืกื˜ื˜ื™ ื™ืฉืคืจ ืžืฉืžืขื•ืชื™ืช ืืช ืื™ื›ื•ืช ื”ืงื•ื“.

ืงื™ืฉื•ืจื™ื ืฉื™ืžื•ืฉื™ื™ื

ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ืžืฉื—ืง PSP

ืื ืืชื” ืจื•ืฆื” ืœืฉืชืฃ ืืช ื”ืžืืžืจ ื”ื–ื” ืขื ืงื”ืœ ื“ื•ื‘ืจ ืื ื’ืœื™ืช, ืื ื ื”ืฉืชืžืฉ ื‘ืงื™ืฉื•ืจ ื”ืชืจื’ื•ื: ืžืงืกื™ื Zvyagintsev. ื›ื™ืฆื“ ืœื”ื’ื“ื™ืจ ืืช PVS-Studio ื‘-Travis CI ื‘ืืžืฆืขื•ืช ื”ื“ื•ื’ืžื” ืฉืœ ืืžื•ืœื˜ื•ืจ ืงื•ื ืกื•ืœืช ื”ืžืฉื—ืงื™ื ืฉืœ PSP.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”