1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Classes to write good-looking output in different languages:
17 Fortran, C++, etc."""
18
19
20 from __future__ import absolute_import
21 import re
22 import collections
23 from six.moves import range
24 import six
25 import io
26
27 try:
28 import madgraph
29 except ImportError:
30 import internal.misc
31 else:
32 import madgraph.various.misc as misc
33
35 """Generic Writer class. All writers should inherit from this class."""
36
37 supported_preprocessor_commands = ['if']
38 preprocessor_command_re=re.compile(
39 "\s*(?P<command>%s)\s*\(\s*(?P<body>.*)\s*\)\s*{\s*"\
40 %('|'.join(supported_preprocessor_commands)))
41 preprocessor_endif_re=re.compile(\
42 "\s*}\s*(?P<endif>else)?\s*(\((?P<body>.*)\))?\s*(?P<new_block>{)?\s*")
43
45 """Exception raised if an error occurs in the definition
46 or the execution of a Writer."""
47
48 pass
49
51 """Exception raised if an error occurs in the handling of the
52 preprocessor tags '##' in the template file."""
53 pass
54
58
63
65 """Write a line with proper indent and splitting of long lines
66 for the language in question."""
67 return ['%s\n' % l for l in line.split('\n')]
68 pass
69
75
97
98 - def writelines(self, lines, context={}, formatting=True):
99 """Extends the regular file.writeline() function to write out
100 nicely formatted code. When defining a context, then the lines
101 will be preprocessed to apply possible conditional statements on the
102 content of the template depending on the contextual variables specified."""
103
104 splitlines = []
105 if isinstance(lines, list):
106 for line in lines:
107 if not isinstance(line, str):
108 raise self.FileWriterError("%s not string" % repr(line))
109 splitlines.extend(line.split('\n'))
110 elif isinstance(lines, str):
111 splitlines.extend(lines.split('\n'))
112 else:
113 raise self.FileWriterError("%s not string" % repr(lines))
114
115 if len(context)>0:
116 splitlines = self.preprocess_template(splitlines,context=context)
117
118 for line in splitlines:
119 if formatting:
120 res_lines = self.write_line(line)
121 else:
122 res_lines = [line+'\n']
123 for line_to_write in res_lines:
124 self.write(line_to_write)
125
127 """ This class takes care of applying the pre-processing statements
128 starting with ## in the template .inc files, using the contextual
129 variables specified in the dictionary 'context' given in input with
130 the variable names given as keys and their respective value as values."""
131
132 template_lines = []
133 if isinstance(input_lines, list):
134 for line in input_lines:
135 if not isinstance(line, str):
136 raise self.FileWriterError("%s not string" % repr(input_lines))
137 template_lines.extend(line.split('\n'))
138 elif isinstance(input_lines, str):
139 template_lines.extend(input_lines.split('\n'))
140 else:
141 raise self.FileWriterError("%s not string" % repr(input_lines))
142
143
144 for contextual_variable, value in context.items():
145 exec('%s=%s'%(str(contextual_variable),repr(value)))
146
147 res = []
148
149 if_stack = []
150 for i, line in enumerate(template_lines):
151 if not line.startswith('##'):
152 if all(if_stack):
153 res.append(line)
154 continue
155 preproc_command = self.preprocessor_command_re.match(line[2:])
156
157 if preproc_command is None:
158 preproc_endif = self.preprocessor_endif_re.match(line[2:])
159 if len(if_stack)==0 or preproc_endif is None:
160 raise self.FilePreProcessingError('Incorrect '+\
161 'preprocessing command %s at line %d.'%(line,i))
162 if preproc_endif.group('new_block') is None:
163 if_stack.pop()
164 elif preproc_endif.group('endif')=='else':
165 if_stack[-1]=(not if_stack[-1])
166
167 elif preproc_command.group('command')=='if':
168 try:
169 if_stack.append(eval(preproc_command.group('body'))==True)
170 except Exception as e:
171 raise self.FilePreProcessingError('Could not evaluate'+\
172 "python expression '%s' given the context %s provided."%\
173 (preproc_command.group('body'),str(context))+\
174 "\nLine %d of file %s."%(i,self.name))
175
176 if len(if_stack)>0:
177 raise self.FilePreProcessingError('Some conditional statements are'+\
178 ' not properly terminated.')
179 return res
180
181
182
183
185 """Routines for writing fortran lines. Keeps track of indentation
186 and splitting of long lines"""
187
189 """Exception raised if an error occurs in the definition
190 or the execution of a FortranWriter."""
191 pass
192
193
194 keyword_pairs = {'^if.+then\s*$': ('^endif', 2),
195 '^type(?!\s*\()\s*.+\s*$': ('^endtype', 2),
196 '^do(?!\s+\d+)\s+': ('^enddo\s*$', 2),
197 '^subroutine': ('^end\s*$', 0),
198 '^module': ('^end\s*$', 0),
199 'function': ('^end\s*$', 0)}
200 single_indents = {'^else\s*$':-2,
201 '^else\s*if.+then\s*$':-2}
202 number_re = re.compile('^(?P<num>\d+)\s+(?P<rest>.*)')
203 line_cont_char = '$'
204 comment_char = 'c'
205 uniformcase = True
206 downcase = False
207 line_length = 71
208 max_split = 20
209 split_characters = "+-*/,) "
210 comment_split_characters = " "
211
212
213 __indent = 0
214 __keyword_list = []
215 __comment_pattern = re.compile(r"^(\s*#|c$|(c\s+([^=]|$))|cf2py|c\-\-|c\*\*)", re.IGNORECASE)
216 __continuation_line = re.compile(r"(?: )[$&]")
217
219 """Write a fortran line, with correct indent and line splits"""
220
221
222 assert(isinstance(line, str) and line.find('\n') == -1)
223
224
225 res_lines = []
226
227
228 if not line.lstrip():
229 res_lines.append("\n")
230 return res_lines
231
232
233 if self.__comment_pattern.search(line):
234
235 res_lines = self.write_comment_line(line.lstrip()[1:])
236 return res_lines
237 elif self.__continuation_line.search(line):
238 return line+'\n'
239 else:
240
241
242
243 myline = line.lstrip()
244
245
246 num_group = self.number_re.search(myline)
247 num = ""
248 if num_group:
249 num = num_group.group('num')
250 myline = num_group.group('rest')
251
252
253
254 (myline, part, post_comment) = myline.partition("!")
255
256 if part:
257 part = " " + part
258
259 myline = myline.replace('\"', '\'')
260
261 if self.uniformcase:
262 splitline = myline.split('\'')
263 myline = ""
264 i = 0
265 while i < len(splitline):
266 if i % 2 == 1:
267
268 while splitline[i] and splitline[i][-1] == '\\':
269 splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1)
270 else:
271
272 if FortranWriter.downcase:
273 splitline[i] = splitline[i].lower()
274 else:
275 splitline[i] = splitline[i].upper()
276 i = i + 1
277
278 myline = "\'".join(splitline).rstrip()
279
280
281 if self.__keyword_list and re.search(self.keyword_pairs[\
282 self.__keyword_list[-1]][0], myline.lower()):
283 key = self.__keyword_list.pop()
284 self.__indent = self.__indent - self.keyword_pairs[key][1]
285
286
287 single_indent = 0
288 for key in self.single_indents.keys():
289 if re.search(key, myline.lower()):
290 self.__indent = self.__indent + self.single_indents[key]
291 single_indent = -self.single_indents[key]
292 break
293
294
295
296 res = self.split_line(" " + num + \
297 " " * (5 + self.__indent - len(num)) + myline,
298 self.split_characters,
299 " " * 5 + self.line_cont_char + \
300 " " * (self.__indent + 1))
301
302
303 for key in self.keyword_pairs.keys():
304 if re.search(key, myline.lower()):
305 self.__keyword_list.append(key)
306 self.__indent = self.__indent + self.keyword_pairs[key][1]
307 break
308
309
310 if single_indent != None:
311 self.__indent = self.__indent + single_indent
312 single_indent = None
313
314
315 res_lines.append("\n".join(res) + part + post_comment + "\n")
316
317 return res_lines
318
350
351 - def split_line(self, line, split_characters, line_start):
352 """Split a line if it is longer than self.line_length
353 columns. Split in preferential order according to
354 split_characters, and start each new line with line_start."""
355
356 def get_split_index(line, max_length, max_split, split_characters):
357 split_at = 0
358 for character in split_characters:
359 index = line[(max_length - max_split): \
360 max_length].rfind(character)
361 if index >= 0:
362 split_at_tmp = max_length - max_split + index
363 if split_at_tmp > split_at:
364 split_at = split_at_tmp
365 return split_at
366
367
368 res_lines = [line]
369
370 while len(res_lines[-1]) > self.line_length:
371 split_at = get_split_index(res_lines[-1], self.line_length,
372 self.max_split, split_characters)
373 if split_at == 0:
374 split_at = get_split_index(res_lines[-1], self.line_length,
375 self.max_split + 30, split_characters)
376 if split_at == 0:
377 split_at = self.line_length
378
379 newline = res_lines[-1][split_at:]
380 nquotes = self.count_number_of_quotes(newline)
381
382
383
384 offset = 0
385 if nquotes%2==1:
386 if res_lines[-1][(split_at-1)] == '\'':
387 offset = 1
388 nquotes -=1
389 res_lines.append(line_start +(res_lines[-1][(split_at-offset):]))
390 else:
391 res_lines.append(line_start +('//\''+res_lines[-1][(split_at-offset):]))
392
393 elif res_lines[-1][(split_at)] in self.split_characters:
394 if res_lines[-1][(split_at)] in ')':
395
396 offset = -1
397
398
399 res_lines.append(line_start +res_lines[-1][(split_at-offset):])
400 elif line_start.startswith(('c','C')) or res_lines[-1][(split_at)] in split_characters:
401 res_lines.append(line_start +res_lines[-1][(split_at):])
402 else:
403 l_start = line_start.rstrip()
404 res_lines.append(l_start +res_lines[-1][(split_at):])
405
406 res_lines[-2] = (res_lines[-2][:(split_at-offset)]+'\'' if nquotes%2==1 \
407 else res_lines[-2][:split_at-offset])
408 return res_lines
409
411 """ Count the number of real quotes (not escaped ones) in a line. """
412
413 splitline = line.split('\'')
414 i = 0
415 while i < len(splitline):
416 if i % 2 == 1:
417
418 while splitline[i] and splitline[i][-1] == '\\':
419 splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1)
420 i = i + 1
421 return len(splitline)-1
422
424 """write the incoming text but fully removing the associate routine/function
425 text can be a path to a file, an iterator, a string
426 fct_names should be a list of functions to remove
427 """
428
429 f77_type = ['real*8', 'integer', 'double precision', 'logical']
430 pattern = re.compile('^\s+(?:SUBROUTINE|(?:%(type)s)\s+function)\s+([a-zA-Z]\w*)' \
431 % {'type':'|'.join(f77_type)}, re.I)
432
433 removed = []
434 if isinstance(text, str):
435 if '\n' in text:
436 text = text.split('\n')
437 else:
438 text = open(text)
439 if isinstance(fct_names, str):
440 fct_names = [fct_names]
441
442 to_write=True
443 for line in text:
444 fct = pattern.findall(line)
445 if fct:
446 if fct[0] in fct_names:
447 to_write = False
448 else:
449 to_write = True
450
451 if to_write:
452 if formatting:
453 if line.endswith('\n'):
454 line = line[:-1]
455 self.writelines(line)
456 else:
457 if not line.endswith('\n'):
458 line = '%s\n' % line
459 file.writelines(self, line)
460 else:
461 removed.append(line)
462
463 return removed
464
465
466
467
468
470 """Routines for writing C++ lines. Keeps track of brackets,
471 spaces, indentation and splitting of long lines"""
472
474 """Exception raised if an error occurs in the definition
475 or the execution of a CPPWriter."""
476 pass
477
478
479 standard_indent = 2
480 line_cont_indent = 4
481
482 indent_par_keywords = {'^if': standard_indent,
483 '^else if': standard_indent,
484 '^for': standard_indent,
485 '^while': standard_indent,
486 '^switch': standard_indent}
487 indent_single_keywords = {'^else': standard_indent}
488 indent_content_keywords = {'^class': standard_indent,
489 '^namespace': 0}
490 cont_indent_keywords = {'^case': standard_indent,
491 '^default': standard_indent,
492 '^public': standard_indent,
493 '^private': standard_indent,
494 '^protected': standard_indent}
495
496 spacing_patterns = [('\s*\"\s*}', '\"'),
497 ('\s*,\s*', ', '),
498 ('\s*-\s*', ' - '),
499 ('([{(,=])\s*-\s*', '\g<1> -'),
500 ('(return)\s*-\s*', '\g<1> -'),
501 ('\s*\+\s*', ' + '),
502 ('([{(,=])\s*\+\s*', '\g<1> +'),
503 ('\(\s*', '('),
504 ('\s*\)', ')'),
505 ('\{\s*', '{'),
506 ('\s*\}', '}'),
507 ('\s*=\s*', ' = '),
508 ('\s*>\s*', ' > '),
509 ('\s*<\s*', ' < '),
510 ('\s*!\s*', ' !'),
511 ('\s*/\s*', '/'),
512 ('\s*\*\s*', ' * '),
513 ('\s*-\s+-\s*', '-- '),
514 ('\s*\+\s+\+\s*', '++ '),
515 ('\s*-\s+=\s*', ' -= '),
516 ('\s*\+\s+=\s*', ' += '),
517 ('\s*\*\s+=\s*', ' *= '),
518 ('\s*/=\s*', ' /= '),
519 ('\s*>\s+>\s*', ' >> '),
520 ('<\s*double\s*>>\s*', '<double> > '),
521 ('\s*<\s+<\s*', ' << '),
522 ('\s*-\s+>\s*', '->'),
523 ('\s*=\s+=\s*', ' == '),
524 ('\s*!\s+=\s*', ' != '),
525 ('\s*>\s+=\s*', ' >= '),
526 ('\s*<\s+=\s*', ' <= '),
527 ('\s*&&\s*', ' && '),
528 ('\s*\|\|\s*', ' || '),
529 ('\s*{\s*}', ' {}'),
530 ('\s*;\s*', '; '),
531 (';\s*\}', ';}'),
532 (';\s*$}', ';'),
533 ('\s*<\s*([a-zA-Z0-9]+?)\s*>', '<\g<1>>'),
534 ('^#include\s*<\s*(.*?)\s*>', '#include <\g<1>>'),
535 ('(\d+\.{0,1}\d*|\.\d+)\s*[eE]\s*([+-]{0,1})\s*(\d+)',
536 '\g<1>e\g<2>\g<3>'),
537 ('\s+',' ')]
538 spacing_re = dict([(key[0], re.compile(key[0])) for key in \
539 spacing_patterns])
540
541 init_array_pattern = re.compile(r"=\s*\{.*\}")
542 short_clause_pattern = re.compile(r"\{.*\}")
543
544 comment_char = '//'
545 comment_pattern = re.compile(r"^(\s*#\s+|\s*//)")
546 start_comment_pattern = re.compile(r"^(\s*/\*)")
547 end_comment_pattern = re.compile(r"(\s*\*/)$")
548
549 quote_chars = re.compile(r"[^\\][\"\']|^[\"\']")
550 no_space_comment_patterns = re.compile(r"--|\*\*|==|\+\+")
551 line_length = 80
552 max_split = 40
553 split_characters = " "
554 comment_split_characters = " "
555
556
557 __indent = 0
558 __keyword_list = collections.deque()
559 __comment_ongoing = False
560
562 """Write a C++ line, with correct indent, spacing and line splits"""
563
564
565 assert(isinstance(line, str) and line.find('\n') == -1)
566
567 res_lines = []
568
569
570 if self.comment_pattern.search(line) or \
571 self.start_comment_pattern.search(line) or \
572 self.__comment_ongoing:
573
574 res_lines = self.write_comment_line(line.lstrip())
575 return res_lines
576
577
578
579
580 myline = line.lstrip()
581
582
583 if not myline:
584 return ["\n"]
585
586
587 if myline[0] == "{":
588
589 indent = self.__indent
590 key = ""
591 if self.__keyword_list:
592 key = self.__keyword_list[-1]
593 if key in self.indent_par_keywords:
594 indent = indent - self.indent_par_keywords[key]
595 elif key in self.indent_single_keywords:
596 indent = indent - self.indent_single_keywords[key]
597 elif key in self.indent_content_keywords:
598 indent = indent - self.indent_content_keywords[key]
599 else:
600
601 self.__indent = self.__indent + self.standard_indent
602
603 res_lines.append(" " * indent + "{" + "\n")
604
605 self.__keyword_list.append("{")
606 myline = myline[1:].lstrip()
607 if myline:
608
609 res_lines.extend(self.write_line(myline))
610 return res_lines
611
612
613 if myline[0] == "}":
614
615 if not self.__keyword_list:
616 raise self.CPPWriterError(\
617 'Non-matching } in C++ output: ' \
618 + myline)
619
620 if self.__keyword_list[-1] in list(self.cont_indent_keywords.keys()):
621 key = self.__keyword_list.pop()
622 self.__indent = self.__indent - self.cont_indent_keywords[key]
623
624 if not self.__keyword_list.pop() == "{":
625 raise self.CPPWriterError(\
626 'Non-matching } in C++ output: ' \
627 + ",".join(self.__keyword_list) + myline)
628
629 key = ""
630 if self.__keyword_list:
631 key = self.__keyword_list[-1]
632 if key in self.indent_par_keywords:
633 self.__indent = self.__indent - \
634 self.indent_par_keywords[key]
635 self.__keyword_list.pop()
636 elif key in self.indent_single_keywords:
637 self.__indent = self.__indent - \
638 self.indent_single_keywords[key]
639 self.__keyword_list.pop()
640 elif key in self.indent_content_keywords:
641 self.__indent = self.__indent - \
642 self.indent_content_keywords[key]
643 self.__keyword_list.pop()
644 else:
645
646 self.__indent = self.__indent - self.standard_indent
647
648
649 breakline_index = 1
650 if len(myline) > 1:
651 if myline[1] in [";", ","]:
652 breakline_index = 2
653 elif myline[1:].lstrip()[:2] == "//":
654 if myline.endswith('\n'):
655 breakline_index = len(myline) - 1
656 else:
657 breakline_index = len(myline)
658 res_lines.append("\n".join(self.split_line(\
659 myline[:breakline_index],
660 self.split_characters)) + "\n")
661 if len(myline) > breakline_index and myline[breakline_index] =='\n':
662 breakline_index +=1
663 myline = myline[breakline_index:].lstrip()
664
665 if myline:
666
667 res_lines.extend(self.write_line(myline))
668 return res_lines
669
670
671 for key in self.indent_par_keywords.keys():
672 if re.search(key, myline):
673
674 parenstack = collections.deque()
675 for i, ch in enumerate(myline[len(key)-1:]):
676 if ch == '(':
677 parenstack.append(ch)
678 elif ch == ')':
679 try:
680 parenstack.pop()
681 except IndexError:
682
683 raise self.CPPWriterError(\
684 'Non-matching parenthesis in C++ output' \
685 + myline)
686 if not parenstack:
687
688 break
689 endparen_index = len(key) + i
690
691 res_lines.append("\n".join(self.split_line(\
692 myline[:endparen_index], \
693 self.split_characters)) + \
694 "\n")
695 myline = myline[endparen_index:].lstrip()
696
697 self.__keyword_list.append(key)
698 self.__indent = self.__indent + \
699 self.indent_par_keywords[key]
700 if myline:
701
702 res_lines.extend(self.write_line(myline))
703
704 return res_lines
705
706
707 for key in self.indent_single_keywords.keys():
708 if re.search(key, myline):
709 end_index = len(key) - 1
710
711 res_lines.append(" " * self.__indent + myline[:end_index] + \
712 "\n")
713 myline = myline[end_index:].lstrip()
714
715 self.__keyword_list.append(key)
716 self.__indent = self.__indent + \
717 self.indent_single_keywords[key]
718 if myline:
719
720 res_lines.extend(self.write_line(myline))
721
722 return res_lines
723
724
725 for key in self.indent_content_keywords.keys():
726 if re.search(key, myline):
727
728 if "{" in myline:
729 end_index = myline.index("{")
730 else:
731 end_index = len(myline)
732 res_lines.append("\n".join(self.split_line(\
733 myline[:end_index], \
734 self.split_characters)) + \
735 "\n")
736 myline = myline[end_index:].lstrip()
737
738 self.__keyword_list.append(key)
739 self.__indent = self.__indent + \
740 self.indent_content_keywords[key]
741 if myline:
742
743 res_lines.extend(self.write_line(myline))
744
745 return res_lines
746
747
748 for key in self.cont_indent_keywords.keys():
749 if re.search(key, myline):
750
751 if self.__keyword_list[-1] in list(self.cont_indent_keywords.keys()):
752 self.__indent = self.__indent - \
753 self.cont_indent_keywords[\
754 self.__keyword_list.pop()]
755
756 res_lines.append("\n".join(self.split_line(myline, \
757 self.split_characters)) + \
758 "\n")
759
760 self.__keyword_list.append(key)
761 self.__indent = self.__indent + \
762 self.cont_indent_keywords[key]
763
764 return res_lines
765
766
767 if self.init_array_pattern.search(myline):
768 res_lines.append("\n".join(self.split_line(\
769 myline,
770 self.split_characters)) + \
771 "\n")
772 return res_lines
773
774
775 if self.short_clause_pattern.search(myline):
776 lines = self.split_line(myline,
777 self.split_characters)
778 if len(lines) == 1:
779 res_lines.append("\n".join(lines) + "\n")
780 return res_lines
781
782
783 if "{" in myline:
784 end_index = myline.index("{")
785 res_lines.append("\n".join(self.split_line(\
786 myline[:end_index], \
787 self.split_characters)) + \
788 "\n")
789 myline = myline[end_index:].lstrip()
790 if myline:
791
792 res_lines.extend(self.write_line(myline))
793 return res_lines
794
795
796 if "}" in myline:
797 end_index = myline.index("}")
798 res_lines.append("\n".join(self.split_line(\
799 myline[:end_index], \
800 self.split_characters)) + \
801 "\n")
802 myline = myline[end_index:].lstrip()
803 if myline:
804
805 res_lines.extend(self.write_line(myline))
806 return res_lines
807
808
809 res_lines.append("\n".join(self.split_line(myline, \
810 self.split_characters)) + "\n")
811
812
813 if self.__keyword_list:
814 if self.__keyword_list[-1] in self.indent_par_keywords:
815 self.__indent = self.__indent - \
816 self.indent_par_keywords[self.__keyword_list.pop()]
817 elif self.__keyword_list[-1] in self.indent_single_keywords:
818 self.__indent = self.__indent - \
819 self.indent_single_keywords[self.__keyword_list.pop()]
820 elif self.__keyword_list[-1] in self.indent_content_keywords:
821 self.__indent = self.__indent - \
822 self.indent_content_keywords[self.__keyword_list.pop()]
823
824 return res_lines
825
858
860 """Split a line if it is longer than self.line_length
861 columns. Split in preferential order according to
862 split_characters. Also fix spacing for line."""
863
864
865 comment = ""
866 if line.find(self.comment_char) > -1:
867 line, dum, comment = line.partition(self.comment_char)
868
869
870 quotes = self.quote_chars.finditer(line)
871
872 start_pos = 0
873 line_quotes = []
874 line_no_quotes = []
875 for i, quote in enumerate(quotes):
876 if i % 2 == 0:
877
878 line_no_quotes.append(line[start_pos:quote.start()])
879 start_pos = quote.start()
880 else:
881
882 line_quotes.append(line[start_pos:quote.end()])
883 start_pos = quote.end()
884
885 line_no_quotes.append(line[start_pos:])
886
887
888 line.rstrip()
889 for i, no_quote in enumerate(line_no_quotes):
890 for key in self.spacing_patterns:
891 no_quote = self.spacing_re[key[0]].sub(key[1], no_quote)
892 line_no_quotes[i] = no_quote
893
894
895 line = line_no_quotes[0]
896 for i in range(len(line_quotes)):
897 line += line_quotes[i]
898 if len(line_no_quotes) > i + 1:
899 line += line_no_quotes[i+1]
900
901
902 res_lines = [" " * self.__indent + line]
903
904 while len(res_lines[-1]) > self.line_length:
905 long_line = res_lines[-1]
906 split_at = -1
907 for character in split_characters:
908 index = long_line[(self.line_length - self.max_split): \
909 self.line_length].rfind(character)
910 if index >= 0:
911 split_at = self.line_length - self.max_split + index + 1
912 break
913
914
915 if split_at == -1:
916 split_at = len(long_line)
917 for character in split_characters:
918 split = long_line[self.line_length].find(character)
919 if split > 0:
920 split_at = min(split, split_at)
921 if split_at == len(long_line):
922 break
923
924
925 quotes = self.quote_chars.findall(long_line[:split_at])
926 if quotes and len(quotes) % 2 == 1:
927 quote_match = self.quote_chars.search(long_line[split_at:])
928 if not quote_match:
929 raise self.CPPWriterError(\
930 "Error: Unmatched quote in line " + long_line)
931 split_at = quote_match.end() + split_at + 1
932 split_match = re.search(self.split_characters,
933 long_line[split_at:])
934 if split_match:
935 split_at = split_at + split_match.start()
936 else:
937 split_at = len(long_line) + 1
938
939
940 if long_line[split_at:].lstrip():
941
942 res_lines[-1] = long_line[:split_at].rstrip()
943 res_lines.append(" " * \
944 (self.__indent + self.line_cont_indent) + \
945 long_line[split_at:].strip())
946 else:
947 break
948
949 if comment:
950 res_lines[-1] += " " + self.comment_char + comment
951
952 return res_lines
953
982
988
990
994
996 """Extends the regular file.writeline() function to write out
997 nicely formatted code"""
998
999 self.write(lines)
1000