Journal [Script Python] Création automatique des fichiers headers en C

Posté par  (site web personnel) .
Étiquettes : aucune
0
27
déc.
2004
Voici un peutut script python qui est la réponse à ma question: http://linuxfr.org/forums/19/5740.html(...)

#! /usr/bin/env python

# -*- coding: utf-8 -*-
#
# version 0.1
#
############
## TODO ##
############
#
# [X] Suivre les #include
# [ ] Déclarations des variables
# [ ] Supprimer la valeur après le "="
# [ ] Fonctions
# [ ] permettre la mise en forme des fonctions ne possédant pas de bloc {}
# [ ] C++
# [ ] Voir si ca fonctionne
#

import os, os.path, sys, string, re;

SHORT_CONST=1

if 1<len(sys.argv): input_name=sys.argv[1]
else:
print "Please select a file to create the header"
sys.exit(1);

if 2<len(sys.argv): output_name=sys.argv[2]
else: output_name=string.replace(file+'.h', '.c.h', '.h');

if 3<len(sys.argv): CONST=sys.argv[3]
elif SHORT_CONST: CONST="_"+re.sub('[^A-Z]', '_', string.upper(os.path.basename(output_name)))
else: CONST="_"+re.sub('[^A-Z]', '_', string.upper(output_name))

os.system('indent -l0 -npsl < '+input_name+' 2>/dev/null > '+output_name);

def add_file(filename, list=[]):
if not os.access(filename, os.F_OK):
list.append("/* Can't find file '"+filename+"' */\n")
return list;
buffer = open(filename, 'r')
while 1:
line=buffer.readline();
if len(line) == 0: break; # EOF
match=re.match('#[\\s]*include[\\s]+"([^"]+)"', line)
if match:
list.append("/* "+string.strip(line)+" */\n");
list = add_file(os.path.dirname(filename)+'/'+match.group(1), list)
list.append("/* END "+string.strip(line)+" */\n");
else: list.append(line);
buffer.close()
return list

lines = add_file(output_name)

buffer = open(output_name, 'w')

buffer.write("#ifndef "+CONST+"\n#define "+CONST+"\n\n");

# for line in lines: print string.rstrip(line);

i=0
# line='//'

len_lines=len(lines)

while i < len_lines:
line=string.rstrip(lines[i]); i+=1
nudeline=string.rstrip(line.split('//')[0])
if len(nudeline) and nudeline[-1]==")" and i<len_lines and len(lines[i]) and lines[i][0]=="{":
buffer.write(line+";\n")
# Entering function block code
i+=1
while i < len_lines:
line=string.rstrip(lines[i]); i+=1
if len(line) and line[0]=="}": break
elif len(line):
buffer.write(line+"\n")

buffer.write("\n#endif\n");

buffer.close();

  • # Utilisation

    Posté par  (site web personnel) . Évalué à 1.

    ./monscript.py monfichier.c [ monfichier.h [ _CONSTANTE_MONFICHIER_H ] ]
    la constante _CONSTANTE_MONFICHIER_H permet de faire un #ifndef et un #define au début pour éciter d'inclure le fichier deux fois. On peut choisir son nom.
  • # C'est bien sympa mais...

    Posté par  (site web personnel) . Évalué à 0.

    .... Tu penses pas que ca aurait plus eu sa place dan sle forum impliqué???

    Non j'dis pas ca pour faire chier mais faudra m'expliquer pourquoi en faire un journal...
  • # Scons

    Posté par  (site web personnel, Mastodon) . Évalué à 1.

    J'arrive après la bataille, mais peut être que ça te sera utile :
    http://www.scons.org/(...)
    • [^] # Re: Scons

      Posté par  (site web personnel) . Évalué à 1.

      J'ai déja vu ce projet mais je crois qu'il agit dun remplacement des autotools, non ?
      J'ai juste envie de générer un fichier header.

      peut être que Scons le permet mais je n'ai plus trop envie de lire tout le site en anglais ...

      Sinon, merci
  • # Bug

    Posté par  (site web personnel) . Évalué à 1.

    Oui, un bug:
    Lorsque une partie du code d'une fonction est commenté et que ce code contient une ligne qui contient le caractère "}" en première position, la fin de la fonction n'est plus trouvée au bon endroit.
    • [^] # Re: Bug

      Posté par  (site web personnel) . Évalué à 1.

      Il suffit de rajouter -fc1 à indent:
      #! /usr/bin/env python
      # -*- coding: utf-8 -*-
      # 
      # version 0.1
      # 
      ############
      ##  TODO  ##
      ############
      # 
      # [X] Suivre les #include
      # [ ] Déclarations des variables
      # 	[ ] Suprimer la valeur après le "="
      # [ ] Fonctions
      # 	[ ] permettre la mise en forme des fonctions ne possédant pas de bloc {}
      # [ ] C++
      # 	[ ] Voir si ca fonctionne
      # [X] Bugs
      # 	[X] Lorsque du code contenant "}" est commenté. Solution: rajouter "-fc1" à indent
      # 
      
      import os, os.path, sys, string, re;
      
      SHORT_CONST=1
      
      if 1<len(sys.argv):	input_name=sys.argv[1]
      else:
      			print "Please select a file to create the header"
      			sys.exit(1);
      
      if 2<len(sys.argv):	output_name=sys.argv[2]
      else:			output_name=string.replace(file+'.h', '.c.h', '.h');
      
      if 3<len(sys.argv):	CONST=sys.argv[3]
      elif SHORT_CONST:	CONST="_"+re.sub('[^A-Z]', '_', string.upper(os.path.basename(output_name)))
      else:			CONST="_"+re.sub('[^A-Z]', '_', string.upper(output_name))
      
      os.system('indent -l0 -npsl -fc1 < '+input_name+' 2>/dev/null > '+output_name);
      
      def add_file(filename, list=[]):
      	if not os.access(filename, os.F_OK):
      		list.append("/*	Can't find file '"+filename+"'	*/\n")
      		return list;
      	buffer = open(filename, 'r')
      	while 1:
      		line=buffer.readline();
      		if len(line) == 0: break; # EOF
      		match=re.match('#[\\s]*include[\\s]+"([^"]+)"', line)
      		if match:
      			list.append("/*	"+string.strip(line)+"	*/\n");
      			list = add_file(os.path.dirname(filename)+'/'+match.group(1), list)
      			list.append("/* END	"+string.strip(line)+"	*/\n");
      		else:	list.append(line);
      	buffer.close()
      	return list
      
      lines = add_file(output_name)
      
      
      buffer = open(output_name, 'w')
      
      buffer.write("#ifndef "+CONST+"\n#define "+CONST+"\n\n");
      
      i=0
      
      len_lines=len(lines)
      
      while i < len_lines:
      	line=string.rstrip(lines[i]); i+=1
      	nudeline=string.rstrip(line.split('//')[0])
      	if len(nudeline) and nudeline[-1]==")" and i<len_lines and len(lines[i]) and lines[i][0]=="{":
      		buffer.write(line+";\n")
      		# Entering function block code
      		i+=1
      		while i < len_lines:
      			line=string.rstrip(lines[i]); i+=1
      			if len(line) and line[0]=="}": break
      	elif len(line):
      		buffer.write(line+"\n")
      
      buffer.write("\n#endif\n");
      
      buffer.close();
      
    • [^] # Re: Bug

      Posté par  (site web personnel) . Évalué à 1.

      problème: ca ne compile pas lorsque les fonctions ont le mot clef "static" au début:
      #! /usr/bin/env python
      # -*- coding: utf-8 -*-
      # 
      # version 0.2
      # 
      ############
      ##  TODO  ##
      ############
      # 
      # [X] Suivre les #include
      # [ ] Déclarations des variables
      # 	[ ] Suprimer la valeur après le "="
      # [ ] Fonctions
      # 	[ ] permettre la mise en forme des fonctions ne possédant pas de bloc {}
      # [ ] C++
      # 	[ ] Voir si ca fonctionne
      # [X] Bugs
      # 	[X] Lorsque du code contenant "}" est commenté. Solution: rajouter "-fc1" à indent
      # 	[X] Ca ne compile pas lorsque le mot "static" apparait au début des lignes
      # 
      
      import os, os.path, sys, string, re;
      
      SHORT_CONST=1
      
      if 1<len(sys.argv):	input_name=sys.argv[1]
      else:
      			print "Please select a file to create the header"
      			sys.exit(1);
      
      if 2<len(sys.argv):	output_name=sys.argv[2]
      else:			output_name=string.replace(file+'.h', '.c.h', '.h');
      
      if 3<len(sys.argv):	CONST=sys.argv[3]
      elif SHORT_CONST:	CONST="_"+re.sub('[^A-Z]', '_', string.upper(os.path.basename(output_name)))
      else:			CONST="_"+re.sub('[^A-Z]', '_', string.upper(output_name))
      
      os.system('indent -l0 -npsl -fc1 < '+input_name+' 2>/dev/null > '+output_name);
      
      def add_file(filename, list=[]):
      	if not os.access(filename, os.F_OK):
      		list.append("/*	Can't find file '"+filename+"'	*/\n")
      		return list;
      	buffer = open(filename, 'r')
      	while 1:
      		line=buffer.readline();
      		if len(line) == 0: break; # EOF
      		match=re.match('#[\\s]*include[\\s]+"([^"]+)"', line)
      		if match:
      			list.append("/*	"+string.strip(line)+"	*/\n");
      			list = add_file(os.path.dirname(filename)+'/'+match.group(1), list)
      			list.append("/* END	"+string.strip(line)+"	*/\n");
      		else:	list.append(line);
      	buffer.close()
      	return list
      
      lines = add_file(output_name)
      
      
      def make_line(line):
      	if line[0:6]=="static":		line = line[7:]
      	return line+"\n";
      
      
      buffer = open(output_name, 'w')
      
      buffer.write("#ifndef "+CONST+"\n#define "+CONST+"\n\n");
      
      i=0
      len_lines=len(lines)
      while i < len_lines:
      	line=string.rstrip(lines[i]); i+=1
      	nudeline=string.rstrip(line.split('//')[0])
      	if len(nudeline) and nudeline[-1]==")" and i<len_lines and len(lines[i]) and lines[i][0]=="{":
      		buffer.write(make_line(line+";"))
      		# Entering function block code
      		i+=1
      		while i < len_lines:
      			line=string.rstrip(lines[i]); i+=1
      			if len(line) and line[0]=="}": break
      	elif len(line):
      		buffer.write(make_line(line))
      
      buffer.write("\n#endif\n");
      
      buffer.close();
      
  • # Toute nouvelle version

    Posté par  (site web personnel) . Évalué à 2.

    Ca y est. Il fonctionne parfaitement (j'ai pu compiler sans problème raydium avec). Maintenant:
    • Change les #include (lorsque ce n'est pas un fichier header inclus) pour le fichier header correspondant. Si le fichier header n'existe pas, il est créé
    • Les lignes non reconnues sont commentées et ne viennent pas polluer le fichier .h
    • Les lignes commencant par static sont supprimées (avant, juste le mot-clef static était supprimé)
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    # 
    # version 0.6
    # 
    ############
    ##  TODO  ##
    ############
    # 
    # [X] Suivre les #include
    # [X] Déclarations des variables
    # 	[X] Suprimer la valeur après le "="
    # [X] Fonctions
    # 	[X] permettre la mise en forme des fonctions ne possédant pas de bloc {}
    # [ ] C++
    # 	[ ] Voir si ca fonctionne
    # [X] Bugs
    # 	[X] Lorsque du code contenant "}" est commenté. Solution: rajouter "-fc1" à indent
    # 	[X] Ca ne compile pas lorsque le mot "static" apparait au début des lignes
    # 	[X] Il fallait ajouter le mot clef "extern" pour les déclarations de variables
    # 	[X] Ajout de constantes pour un inclusion conditionelle lors des #include ""
    # 
    
    import os, os.path, sys, string, re, Queue;
    
    SHORT_CONST=1
    def get_const(filename):
    	if SHORT_CONST:		filename=os.path.basename(filename)
    	if filename[-2:]=='.c':	filename=filename+".h"
    	CONST="_"+re.sub('[^A-Z]', '_', string.upper(filename))
    	return CONST;
    
    def get_indent_file(filename):
    	return os.popen('indent -l0 -npsl -fc1 -bbb < '+filename+' 2>/dev/null')
    
    def make_line(line):
    	if line[:6]=="static":
    		line = line[7:]
    	line=string.replace(line, ';;', ';')
    	line=string.replace(line, 'extern extern', 'extern')
    	line=string.replace(line, '/**/', '')
    	return line+"\n";
    
    def create_header(input_name, output_name, filename, origin='shell', tab=0):
    	input=get_indent_file(input_name)
    	output=open(output_name, 'w')
    	print '%s<"%s" origin="%s">'%("    "*tab, filename, origin)
    	output.write("#ifndef "+get_const(filename)+"\n")
    	output.write("#define "+get_const(filename)+"\n")
    	delete=0
    	keep=0
    	while 1:
    		line=input.readline()
    		if len(line)==0: break; # EOF
    		line=line.rstrip()
    		if len(line)==0: continue
    		try:	spaces=re.match(r'^(?P\s*)\S+.*$', line).group('spaces')
    		except:	spaces=''
    		
    		if line[0]=="#":
    			match=re.match(r'^#\s*include\s*"(?P[^"]*)"', line)
    			if match:
    				file=match.group('file')
    				dir=os.path.dirname(filename)+"/"
    				if file[-2:]!='.h' and os.access(dir+file, os.F_OK):
    					line=line.replace(file, file+'.h')
    					tab+=1
    					create_header(dir+file, dir+file+'.h', dir+file+'.h', filename[:], tab)
    					tab-=1
    			output.write(line+"\n")
    			continue
    		if keep==2   and line[0]=="{":	keep=1
    		if delete==2 and line[0]=="{":	delete=1
    		if delete==1:
    			if line[0]!="}" : continue
    			delete=0
    		elif keep==1:
    			output.write(line+"\n")
    			if line[0]!="}" : continue
    			keep=0
    		else:
    			if   line[:6]=='static' : continue
    			elif line[:6]=='struct' :
    				line="extern "+line
    				if   line[-1]=='{': keep=1 ; delete=0
    				elif line[-1]!=';': keep=2 ; delete=0
    			elif line[:7]=='typedef':
    				if   line[-1]=='{': keep=1 ; delete=0
    				elif line[-1]!=';': keep=2 ; delete=0
    			else:
    				match = re.match(r'^(?P[A-Za-z_]+(\s+[(][^=;]*)?[^=(;]*)\s*(?P[\S])', line)
    				if match:
    					if match.group('char')=='(':
    						# function
    						if   line[-1]=='{': delete=1 ; keep=0
    						elif line[-1]!=';': delete=2 ; keep=0
    						line="extern "+line+";"
    					else: # maybe '=' or ';'
    						if   line[-1]=='{': delete=1 ; keep=0
    						elif line[-1]!=';': delete=2 ; keep=0
    						line="extern "+match.group('begin').rstrip()+";"
    # 				else:	line="/**UNRECOGNIZED** "+line+" **/"
    				else:	line="// "+line+" // Unrecognized"
    			output.write(line+"\n")
    			continue
    	print '%s</"%s">'%("    "*tab, filename)
    	output.write("#endif\n")
    	input.close()
    	output.close()
    
    
    
    if 1<len(sys.argv):
    	input_name=sys.argv[1]
    else:
    	print "Please select a file to create the header"
    	sys.exit(1);
    if 2<len(sys.argv):
    	output_name=sys.argv[2]
    else:	output_name=input_name+'.h'
    if 3<len(sys.argv):
    	CONST=sys.argv[3]
    else:	CONST=get_const(output_name)
    
    create_header(input_name, output_name, output_name)
    

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.