2020-10-30 08:40:31 +01:00
# -*- coding: utf-8; mode: python -*-
2020-10-30 08:40:32 +01:00
# coding=utf-8
2020-10-30 08:40:31 +01:00
# SPDX-License-Identifier: GPL-2.0
2020-10-30 08:40:32 +01:00
#
2020-10-30 08:40:31 +01:00
u """
kernel - abi
~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Implementation of the ` ` kernel - abi ` ` reST - directive .
: copyright : Copyright ( C ) 2016 Markus Heiser
: copyright : Copyright ( C ) 2016 - 2020 Mauro Carvalho Chehab
: maintained - by : Mauro Carvalho Chehab < mchehab + huawei @kernel.org >
: license : GPL Version 2 , June 1991 see Linux / COPYING for details .
The ` ` kernel - abi ` ` ( : py : class : ` KernelCmd ` ) directive calls the
scripts / get_abi . pl script to parse the Kernel ABI files .
Overview of directive ' s argument and options.
. . code - block : : rst
. . kernel - abi : : < ABI directory location >
: debug :
The argument ` ` < ABI directory location > ` ` is required . It contains the
location of the ABI files to be parsed .
` ` debug ` `
Inserts a code - block with the * raw * reST . Sometimes it is helpful to see
what reST is generated .
"""
2020-10-30 08:40:32 +01:00
import codecs
2020-10-30 08:40:31 +01:00
import os
import subprocess
2020-10-30 08:40:33 +01:00
import sys
2020-10-30 08:40:34 +01:00
import re
2020-10-30 08:40:35 +01:00
import kernellog
2020-10-30 08:40:31 +01:00
2020-10-30 08:40:33 +01:00
from os import path
2020-10-30 08:40:31 +01:00
2020-10-30 08:40:33 +01:00
from docutils import nodes , statemachine
2020-10-30 08:40:31 +01:00
from docutils . statemachine import ViewList
2020-10-30 08:40:33 +01:00
from docutils . parsers . rst import directives , Directive
2020-10-30 08:40:31 +01:00
from docutils . utils . error_reporting import ErrorString
2021-02-01 16:26:25 -07:00
from sphinx . util . docutils import switch_source_input
2020-10-30 08:40:31 +01:00
__version__ = ' 1.0 '
def setup ( app ) :
app . add_directive ( " kernel-abi " , KernelCmd )
return dict (
version = __version__
, parallel_read_safe = True
, parallel_write_safe = True
)
class KernelCmd ( Directive ) :
u """ KernelABI (``kernel-abi``) directive """
required_arguments = 1
2020-10-30 08:40:41 +01:00
optional_arguments = 2
2020-10-30 08:40:31 +01:00
has_content = False
final_argument_whitespace = True
option_spec = {
2020-10-30 08:40:41 +01:00
" debug " : directives . flag ,
" rst " : directives . unchanged
2020-10-30 08:40:31 +01:00
}
def run ( self ) :
doc = self . state . document
if not doc . settings . file_insertion_enabled :
raise self . warning ( " docutils: file insertion disabled " )
env = doc . settings . env
cwd = path . dirname ( doc . current_source )
2020-10-30 08:40:34 +01:00
cmd = " get_abi.pl rest --enable-lineno --dir "
2020-10-30 08:40:31 +01:00
cmd + = self . arguments [ 0 ]
2020-10-30 08:40:41 +01:00
if ' rst ' in self . options :
cmd + = " --rst-source "
2020-10-30 08:40:31 +01:00
srctree = path . abspath ( os . environ [ " srctree " ] )
fname = cmd
# extend PATH with $(srctree)/scripts
path_env = os . pathsep . join ( [
srctree + os . sep + " scripts " ,
os . environ [ " PATH " ]
] )
shell_env = os . environ . copy ( )
shell_env [ " PATH " ] = path_env
shell_env [ " srctree " ] = srctree
lines = self . runCmd ( cmd , shell = True , cwd = cwd , env = shell_env )
2020-10-30 08:40:35 +01:00
nodeList = self . nestedParse ( lines , self . arguments [ 0 ] )
2020-10-30 08:40:31 +01:00
return nodeList
def runCmd ( self , cmd , * * kwargs ) :
2021-12-21 22:23:54 -08:00
u """ Run command ``cmd`` and return its stdout as unicode. """
2020-10-30 08:40:31 +01:00
try :
proc = subprocess . Popen (
cmd
, stdout = subprocess . PIPE
, stderr = subprocess . PIPE
, * * kwargs
)
out , err = proc . communicate ( )
2020-10-30 08:40:32 +01:00
out , err = codecs . decode ( out , ' utf-8 ' ) , codecs . decode ( err , ' utf-8 ' )
2020-10-30 08:40:31 +01:00
if proc . returncode != 0 :
raise self . severe (
u " command ' %s ' failed with return code %d "
% ( cmd , proc . returncode )
)
except OSError as exc :
raise self . severe ( u " problems with ' %s ' directive: %s . "
% ( self . name , ErrorString ( exc ) ) )
2020-10-30 08:40:32 +01:00
return out
2020-10-30 08:40:31 +01:00
2020-10-30 08:40:35 +01:00
def nestedParse ( self , lines , fname ) :
2022-03-26 11:27:21 +01:00
env = self . state . document . settings . env
2020-10-30 08:40:31 +01:00
content = ViewList ( )
2020-10-30 08:40:35 +01:00
node = nodes . section ( )
2020-10-30 08:40:31 +01:00
if " debug " in self . options :
code_block = " \n \n .. code-block:: rst \n :linenos: \n "
for l in lines . split ( " \n " ) :
code_block + = " \n " + l
lines = code_block + " \n \n "
2022-03-26 11:27:23 +01:00
line_regex = re . compile ( " ^ \ . \ . LINENO ( \ S+) \ #([0-9]+)$ " )
2020-10-30 08:40:34 +01:00
ln = 0
2020-10-30 08:40:35 +01:00
n = 0
f = fname
2020-10-30 08:40:34 +01:00
for line in lines . split ( " \n " ) :
2020-10-30 08:40:35 +01:00
n = n + 1
2020-10-30 08:40:34 +01:00
match = line_regex . search ( line )
if match :
2020-10-30 08:40:35 +01:00
new_f = match . group ( 1 )
# Sphinx parser is lazy: it stops parsing contents in the
# middle, if it is too big. So, handle it per input file
if new_f != f and content :
self . do_parse ( content , node )
content = ViewList ( )
2022-03-26 11:27:21 +01:00
# Add the file to Sphinx build dependencies
env . note_dependency ( os . path . abspath ( f ) )
2020-10-30 08:40:35 +01:00
f = new_f
2020-10-30 08:40:34 +01:00
# sphinx counts lines from 0
ln = int ( match . group ( 2 ) ) - 1
else :
content . append ( line , f , ln )
2020-10-30 08:40:31 +01:00
2020-10-30 08:40:35 +01:00
kernellog . info ( self . state . document . settings . env . app , " %s : parsed %i lines " % ( fname , n ) )
if content :
self . do_parse ( content , node )
2020-10-30 08:40:33 +01:00
2020-10-30 08:40:35 +01:00
return node . children
def do_parse ( self , content , node ) :
2021-02-01 16:26:25 -07:00
with switch_source_input ( self . state , content ) :
self . state . nested_parse ( content , 0 , node , match_titles = 1 )