2020-10-30 10:40:31 +03:00
# -*- coding: utf-8; mode: python -*-
2020-10-30 10:40:32 +03:00
# coding=utf-8
2020-10-30 10:40:31 +03:00
# SPDX-License-Identifier: GPL-2.0
2020-10-30 10:40:32 +03:00
#
2020-10-30 10:40:31 +03: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 10:40:32 +03:00
import codecs
2020-10-30 10:40:31 +03:00
import os
import subprocess
2020-10-30 10:40:33 +03:00
import sys
2020-10-30 10:40:34 +03:00
import re
2020-10-30 10:40:35 +03:00
import kernellog
2020-10-30 10:40:31 +03:00
2020-10-30 10:40:33 +03:00
from docutils import nodes , statemachine
2020-10-30 10:40:31 +03:00
from docutils . statemachine import ViewList
2020-10-30 10:40:33 +03:00
from docutils . parsers . rst import directives , Directive
2020-10-30 10:40:31 +03:00
from docutils . utils . error_reporting import ErrorString
2021-02-02 02:26:25 +03:00
from sphinx . util . docutils import switch_source_input
2020-10-30 10:40:31 +03: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 10:40:41 +03:00
optional_arguments = 2
2020-10-30 10:40:31 +03:00
has_content = False
final_argument_whitespace = True
option_spec = {
2020-10-30 10:40:41 +03:00
" debug " : directives . flag ,
" rst " : directives . unchanged
2020-10-30 10:40:31 +03:00
}
def run ( self ) :
doc = self . state . document
if not doc . settings . file_insertion_enabled :
raise self . warning ( " docutils: file insertion disabled " )
2024-01-01 02:59:59 +03:00
srctree = os . path . abspath ( os . environ [ " srctree " ] )
2020-10-30 10:40:41 +03:00
2024-01-01 02:59:59 +03:00
args = [
os . path . join ( srctree , ' scripts/get_abi.pl ' ) ,
' rest ' ,
' --enable-lineno ' ,
' --dir ' , os . path . join ( srctree , ' Documentation ' , self . arguments [ 0 ] ) ,
]
2020-10-30 10:40:31 +03:00
2024-01-01 02:59:59 +03:00
if ' rst ' in self . options :
args . append ( ' --rst-source ' )
2020-10-30 10:40:31 +03:00
2024-01-01 02:59:59 +03:00
lines = subprocess . check_output ( args , cwd = os . path . dirname ( doc . current_source ) ) . decode ( ' utf-8 ' )
2020-10-30 10:40:35 +03:00
nodeList = self . nestedParse ( lines , self . arguments [ 0 ] )
2020-10-30 10:40:31 +03:00
return nodeList
2020-10-30 10:40:35 +03:00
def nestedParse ( self , lines , fname ) :
2022-03-26 13:27:21 +03:00
env = self . state . document . settings . env
2020-10-30 10:40:31 +03:00
content = ViewList ( )
2020-10-30 10:40:35 +03:00
node = nodes . section ( )
2020-10-30 10:40:31 +03: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 "
2023-09-12 09:07:56 +03:00
line_regex = re . compile ( r " ^ \ . \ . LINENO ( \ S+) \ #([0-9]+)$ " )
2020-10-30 10:40:34 +03:00
ln = 0
2020-10-30 10:40:35 +03:00
n = 0
f = fname
2020-10-30 10:40:34 +03:00
for line in lines . split ( " \n " ) :
2020-10-30 10:40:35 +03:00
n = n + 1
2020-10-30 10:40:34 +03:00
match = line_regex . search ( line )
if match :
2020-10-30 10:40:35 +03: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 13:27:21 +03:00
# Add the file to Sphinx build dependencies
env . note_dependency ( os . path . abspath ( f ) )
2020-10-30 10:40:35 +03:00
f = new_f
2020-10-30 10:40:34 +03:00
# sphinx counts lines from 0
ln = int ( match . group ( 2 ) ) - 1
else :
content . append ( line , f , ln )
2020-10-30 10:40:31 +03:00
2020-10-30 10:40:35 +03: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 10:40:33 +03:00
2020-10-30 10:40:35 +03:00
return node . children
def do_parse ( self , content , node ) :
2021-02-02 02:26:25 +03:00
with switch_source_input ( self . state , content ) :
self . state . nested_parse ( content , 0 , node , match_titles = 1 )