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
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 downcase = False
206 line_length = 71
207 max_split = 20
208 split_characters = "+-*/,) "
209 comment_split_characters = " "
210
211
212 __indent = 0
213 __keyword_list = []
214 __comment_pattern = re.compile(r"^(\s*#|c$|(c\s+([^=]|$))|cf2py|c\-\-|c\*\*)", re.IGNORECASE)
215 __continuation_line = re.compile(r"(?: )[$&]")
216
218 """Write a fortran line, with correct indent and line splits"""
219
220
221 assert(isinstance(line, str) and line.find('\n') == -1)
222
223
224 res_lines = []
225
226
227 if not line.lstrip():
228 res_lines.append("\n")
229 return res_lines
230
231
232 if self.__comment_pattern.search(line):
233
234 res_lines = self.write_comment_line(line.lstrip()[1:])
235 return res_lines
236 elif self.__continuation_line.search(line):
237 return line+'\n'
238 else:
239
240
241
242 myline = line.lstrip()
243
244
245 num_group = self.number_re.search(myline)
246 num = ""
247 if num_group:
248 num = num_group.group('num')
249 myline = num_group.group('rest')
250
251
252
253 (myline, part, post_comment) = myline.partition("!")
254
255 if part:
256 part = " " + part
257
258 myline = myline.replace('\"', '\'')
259
260 splitline = myline.split('\'')
261 myline = ""
262 i = 0
263 while i < len(splitline):
264 if i % 2 == 1:
265
266 while splitline[i] and splitline[i][-1] == '\\':
267 splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1)
268 else:
269
270 if FortranWriter.downcase:
271 splitline[i] = splitline[i].lower()
272 else:
273 splitline[i] = splitline[i].upper()
274 i = i + 1
275
276 myline = "\'".join(splitline).rstrip()
277
278
279 if self.__keyword_list and re.search(self.keyword_pairs[\
280 self.__keyword_list[-1]][0], myline.lower()):
281 key = self.__keyword_list.pop()
282 self.__indent = self.__indent - self.keyword_pairs[key][1]
283
284
285 single_indent = 0
286 for key in self.single_indents.keys():
287 if re.search(key, myline.lower()):
288 self.__indent = self.__indent + self.single_indents[key]
289 single_indent = -self.single_indents[key]
290 break
291
292
293
294 res = self.split_line(" " + num + \
295 " " * (5 + self.__indent - len(num)) + myline,
296 self.split_characters,
297 " " * 5 + self.line_cont_char + \
298 " " * (self.__indent + 1))
299
300
301 for key in self.keyword_pairs.keys():
302 if re.search(key, myline.lower()):
303 self.__keyword_list.append(key)
304 self.__indent = self.__indent + self.keyword_pairs[key][1]
305 break
306
307
308 if single_indent != None:
309 self.__indent = self.__indent + single_indent
310 single_indent = None
311
312
313 res_lines.append("\n".join(res) + part + post_comment + "\n")
314
315 return res_lines
316
348
349 - def split_line(self, line, split_characters, line_start):
350 """Split a line if it is longer than self.line_length
351 columns. Split in preferential order according to
352 split_characters, and start each new line with line_start."""
353
354 def get_split_index(line, max_length, max_split, split_characters):
355 split_at = 0
356 for character in split_characters:
357 index = line[(max_length - max_split): \
358 max_length].rfind(character)
359 if index >= 0:
360 split_at_tmp = max_length - max_split + index
361 if split_at_tmp > split_at:
362 split_at = split_at_tmp
363 return split_at
364
365
366 res_lines = [line]
367
368 while len(res_lines[-1]) > self.line_length:
369 split_at = get_split_index(res_lines[-1], self.line_length,
370 self.max_split, split_characters)
371 if split_at == 0:
372 split_at = get_split_index(res_lines[-1], self.line_length,
373 self.max_split + 30, split_characters)
374 if split_at == 0:
375 split_at = self.line_length
376
377 newline = res_lines[-1][split_at:]
378 nquotes = self.count_number_of_quotes(newline)
379
380
381
382 offset = 0
383 if nquotes%2==1:
384 if res_lines[-1][(split_at-1)] == '\'':
385 offset = 1
386 nquotes -=1
387 res_lines.append(line_start +(res_lines[-1][(split_at-offset):]))
388 else:
389 res_lines.append(line_start +('//\''+res_lines[-1][(split_at-offset):]))
390
391 elif res_lines[-1][(split_at)] in self.split_characters:
392 if res_lines[-1][(split_at)] in ')':
393
394 offset = -1
395
396
397 res_lines.append(line_start +res_lines[-1][(split_at-offset):])
398 elif line_start.startswith(('c','C')) or res_lines[-1][(split_at)] in split_characters:
399 res_lines.append(line_start +res_lines[-1][(split_at):])
400 else:
401 l_start = line_start.rstrip()
402 res_lines.append(l_start +res_lines[-1][(split_at):])
403
404 res_lines[-2] = (res_lines[-2][:(split_at-offset)]+'\'' if nquotes%2==1 \
405 else res_lines[-2][:split_at-offset])
406 return res_lines
407
409 """ Count the number of real quotes (not escaped ones) in a line. """
410
411 splitline = line.split('\'')
412 i = 0
413 while i < len(splitline):
414 if i % 2 == 1:
415
416 while splitline[i] and splitline[i][-1] == '\\':
417 splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1)
418 i = i + 1
419 return len(splitline)-1
420
422 """write the incoming text but fully removing the associate routine/function
423 text can be a path to a file, an iterator, a string
424 fct_names should be a list of functions to remove
425 """
426
427 f77_type = ['real*8', 'integer', 'double precision', 'logical']
428 pattern = re.compile('^\s+(?:SUBROUTINE|(?:%(type)s)\s+function)\s+([a-zA-Z]\w*)' \
429 % {'type':'|'.join(f77_type)}, re.I)
430
431 removed = []
432 if isinstance(text, str):
433 if '\n' in text:
434 text = text.split('\n')
435 else:
436 text = open(text)
437 if isinstance(fct_names, str):
438 fct_names = [fct_names]
439
440 to_write=True
441 for line in text:
442 fct = pattern.findall(line)
443 if fct:
444 if fct[0] in fct_names:
445 to_write = False
446 else:
447 to_write = True
448
449 if to_write:
450 if formatting:
451 if line.endswith('\n'):
452 line = line[:-1]
453 self.writelines(line)
454 else:
455 if not line.endswith('\n'):
456 line = '%s\n' % line
457 file.writelines(self, line)
458 else:
459 removed.append(line)
460
461 return removed
462
463
464
465
466
468 """Routines for writing C++ lines. Keeps track of brackets,
469 spaces, indentation and splitting of long lines"""
470
472 """Exception raised if an error occurs in the definition
473 or the execution of a CPPWriter."""
474 pass
475
476
477 standard_indent = 2
478 line_cont_indent = 4
479
480 indent_par_keywords = {'^if': standard_indent,
481 '^else if': standard_indent,
482 '^for': standard_indent,
483 '^while': standard_indent,
484 '^switch': standard_indent}
485 indent_single_keywords = {'^else': standard_indent}
486 indent_content_keywords = {'^class': standard_indent,
487 '^namespace': 0}
488 cont_indent_keywords = {'^case': standard_indent,
489 '^default': standard_indent,
490 '^public': standard_indent,
491 '^private': standard_indent,
492 '^protected': standard_indent}
493
494 spacing_patterns = [('\s*\"\s*}', '\"'),
495 ('\s*,\s*', ', '),
496 ('\s*-\s*', ' - '),
497 ('([{(,=])\s*-\s*', '\g<1> -'),
498 ('(return)\s*-\s*', '\g<1> -'),
499 ('\s*\+\s*', ' + '),
500 ('([{(,=])\s*\+\s*', '\g<1> +'),
501 ('\(\s*', '('),
502 ('\s*\)', ')'),
503 ('\{\s*', '{'),
504 ('\s*\}', '}'),
505 ('\s*=\s*', ' = '),
506 ('\s*>\s*', ' > '),
507 ('\s*<\s*', ' < '),
508 ('\s*!\s*', ' !'),
509 ('\s*/\s*', '/'),
510 ('\s*\*\s*', ' * '),
511 ('\s*-\s+-\s*', '-- '),
512 ('\s*\+\s+\+\s*', '++ '),
513 ('\s*-\s+=\s*', ' -= '),
514 ('\s*\+\s+=\s*', ' += '),
515 ('\s*\*\s+=\s*', ' *= '),
516 ('\s*/=\s*', ' /= '),
517 ('\s*>\s+>\s*', ' >> '),
518 ('<\s*double\s*>>\s*', '<double> > '),
519 ('\s*<\s+<\s*', ' << '),
520 ('\s*-\s+>\s*', '->'),
521 ('\s*=\s+=\s*', ' == '),
522 ('\s*!\s+=\s*', ' != '),
523 ('\s*>\s+=\s*', ' >= '),
524 ('\s*<\s+=\s*', ' <= '),
525 ('\s*&&\s*', ' && '),
526 ('\s*\|\|\s*', ' || '),
527 ('\s*{\s*}', ' {}'),
528 ('\s*;\s*', '; '),
529 (';\s*\}', ';}'),
530 (';\s*$}', ';'),
531 ('\s*<\s*([a-zA-Z0-9]+?)\s*>', '<\g<1>>'),
532 ('^#include\s*<\s*(.*?)\s*>', '#include <\g<1>>'),
533 ('(\d+\.{0,1}\d*|\.\d+)\s*[eE]\s*([+-]{0,1})\s*(\d+)',
534 '\g<1>e\g<2>\g<3>'),
535 ('\s+',' ')]
536 spacing_re = dict([(key[0], re.compile(key[0])) for key in \
537 spacing_patterns])
538
539 init_array_pattern = re.compile(r"=\s*\{.*\}")
540 short_clause_pattern = re.compile(r"\{.*\}")
541
542 comment_char = '//'
543 comment_pattern = re.compile(r"^(\s*#\s+|\s*//)")
544 start_comment_pattern = re.compile(r"^(\s*/\*)")
545 end_comment_pattern = re.compile(r"(\s*\*/)$")
546
547 quote_chars = re.compile(r"[^\\][\"\']|^[\"\']")
548 no_space_comment_patterns = re.compile(r"--|\*\*|==|\+\+")
549 line_length = 80
550 max_split = 40
551 split_characters = " "
552 comment_split_characters = " "
553
554
555 __indent = 0
556 __keyword_list = collections.deque()
557 __comment_ongoing = False
558
560 """Write a C++ line, with correct indent, spacing and line splits"""
561
562
563 assert(isinstance(line, str) and line.find('\n') == -1)
564
565 res_lines = []
566
567
568 if self.comment_pattern.search(line) or \
569 self.start_comment_pattern.search(line) or \
570 self.__comment_ongoing:
571
572 res_lines = self.write_comment_line(line.lstrip())
573 return res_lines
574
575
576
577
578 myline = line.lstrip()
579
580
581 if not myline:
582 return ["\n"]
583
584
585 if myline[0] == "{":
586
587 indent = self.__indent
588 key = ""
589 if self.__keyword_list:
590 key = self.__keyword_list[-1]
591 if key in self.indent_par_keywords:
592 indent = indent - self.indent_par_keywords[key]
593 elif key in self.indent_single_keywords:
594 indent = indent - self.indent_single_keywords[key]
595 elif key in self.indent_content_keywords:
596 indent = indent - self.indent_content_keywords[key]
597 else:
598
599 self.__indent = self.__indent + self.standard_indent
600
601 res_lines.append(" " * indent + "{" + "\n")
602
603 self.__keyword_list.append("{")
604 myline = myline[1:].lstrip()
605 if myline:
606
607 res_lines.extend(self.write_line(myline))
608 return res_lines
609
610
611 if myline[0] == "}":
612
613 if not self.__keyword_list:
614 raise self.CPPWriterError(\
615 'Non-matching } in C++ output: ' \
616 + myline)
617
618 if self.__keyword_list[-1] in list(self.cont_indent_keywords.keys()):
619 key = self.__keyword_list.pop()
620 self.__indent = self.__indent - self.cont_indent_keywords[key]
621
622 if not self.__keyword_list.pop() == "{":
623 raise self.CPPWriterError(\
624 'Non-matching } in C++ output: ' \
625 + ",".join(self.__keyword_list) + myline)
626
627 key = ""
628 if self.__keyword_list:
629 key = self.__keyword_list[-1]
630 if key in self.indent_par_keywords:
631 self.__indent = self.__indent - \
632 self.indent_par_keywords[key]
633 self.__keyword_list.pop()
634 elif key in self.indent_single_keywords:
635 self.__indent = self.__indent - \
636 self.indent_single_keywords[key]
637 self.__keyword_list.pop()
638 elif key in self.indent_content_keywords:
639 self.__indent = self.__indent - \
640 self.indent_content_keywords[key]
641 self.__keyword_list.pop()
642 else:
643
644 self.__indent = self.__indent - self.standard_indent
645
646
647 breakline_index = 1
648 if len(myline) > 1:
649 if myline[1] in [";", ","]:
650 breakline_index = 2
651 elif myline[1:].lstrip()[:2] == "//":
652 if myline.endswith('\n'):
653 breakline_index = len(myline) - 1
654 else:
655 breakline_index = len(myline)
656 res_lines.append("\n".join(self.split_line(\
657 myline[:breakline_index],
658 self.split_characters)) + "\n")
659 if len(myline) > breakline_index and myline[breakline_index] =='\n':
660 breakline_index +=1
661 myline = myline[breakline_index:].lstrip()
662
663 if myline:
664
665 res_lines.extend(self.write_line(myline))
666 return res_lines
667
668
669 for key in self.indent_par_keywords.keys():
670 if re.search(key, myline):
671
672 parenstack = collections.deque()
673 for i, ch in enumerate(myline[len(key)-1:]):
674 if ch == '(':
675 parenstack.append(ch)
676 elif ch == ')':
677 try:
678 parenstack.pop()
679 except IndexError:
680
681 raise self.CPPWriterError(\
682 'Non-matching parenthesis in C++ output' \
683 + myline)
684 if not parenstack:
685
686 break
687 endparen_index = len(key) + i
688
689 res_lines.append("\n".join(self.split_line(\
690 myline[:endparen_index], \
691 self.split_characters)) + \
692 "\n")
693 myline = myline[endparen_index:].lstrip()
694
695 self.__keyword_list.append(key)
696 self.__indent = self.__indent + \
697 self.indent_par_keywords[key]
698 if myline:
699
700 res_lines.extend(self.write_line(myline))
701
702 return res_lines
703
704
705 for key in self.indent_single_keywords.keys():
706 if re.search(key, myline):
707 end_index = len(key) - 1
708
709 res_lines.append(" " * self.__indent + myline[:end_index] + \
710 "\n")
711 myline = myline[end_index:].lstrip()
712
713 self.__keyword_list.append(key)
714 self.__indent = self.__indent + \
715 self.indent_single_keywords[key]
716 if myline:
717
718 res_lines.extend(self.write_line(myline))
719
720 return res_lines
721
722
723 for key in self.indent_content_keywords.keys():
724 if re.search(key, myline):
725
726 if "{" in myline:
727 end_index = myline.index("{")
728 else:
729 end_index = len(myline)
730 res_lines.append("\n".join(self.split_line(\
731 myline[:end_index], \
732 self.split_characters)) + \
733 "\n")
734 myline = myline[end_index:].lstrip()
735
736 self.__keyword_list.append(key)
737 self.__indent = self.__indent + \
738 self.indent_content_keywords[key]
739 if myline:
740
741 res_lines.extend(self.write_line(myline))
742
743 return res_lines
744
745
746 for key in self.cont_indent_keywords.keys():
747 if re.search(key, myline):
748
749 if self.__keyword_list[-1] in list(self.cont_indent_keywords.keys()):
750 self.__indent = self.__indent - \
751 self.cont_indent_keywords[\
752 self.__keyword_list.pop()]
753
754 res_lines.append("\n".join(self.split_line(myline, \
755 self.split_characters)) + \
756 "\n")
757
758 self.__keyword_list.append(key)
759 self.__indent = self.__indent + \
760 self.cont_indent_keywords[key]
761
762 return res_lines
763
764
765 if self.init_array_pattern.search(myline):
766 res_lines.append("\n".join(self.split_line(\
767 myline,
768 self.split_characters)) + \
769 "\n")
770 return res_lines
771
772
773 if self.short_clause_pattern.search(myline):
774 lines = self.split_line(myline,
775 self.split_characters)
776 if len(lines) == 1:
777 res_lines.append("\n".join(lines) + "\n")
778 return res_lines
779
780
781 if "{" in myline:
782 end_index = myline.index("{")
783 res_lines.append("\n".join(self.split_line(\
784 myline[:end_index], \
785 self.split_characters)) + \
786 "\n")
787 myline = myline[end_index:].lstrip()
788 if myline:
789
790 res_lines.extend(self.write_line(myline))
791 return res_lines
792
793
794 if "}" in myline:
795 end_index = myline.index("}")
796 res_lines.append("\n".join(self.split_line(\
797 myline[:end_index], \
798 self.split_characters)) + \
799 "\n")
800 myline = myline[end_index:].lstrip()
801 if myline:
802
803 res_lines.extend(self.write_line(myline))
804 return res_lines
805
806
807 res_lines.append("\n".join(self.split_line(myline, \
808 self.split_characters)) + "\n")
809
810
811 if self.__keyword_list:
812 if self.__keyword_list[-1] in self.indent_par_keywords:
813 self.__indent = self.__indent - \
814 self.indent_par_keywords[self.__keyword_list.pop()]
815 elif self.__keyword_list[-1] in self.indent_single_keywords:
816 self.__indent = self.__indent - \
817 self.indent_single_keywords[self.__keyword_list.pop()]
818 elif self.__keyword_list[-1] in self.indent_content_keywords:
819 self.__indent = self.__indent - \
820 self.indent_content_keywords[self.__keyword_list.pop()]
821
822 return res_lines
823
856
858 """Split a line if it is longer than self.line_length
859 columns. Split in preferential order according to
860 split_characters. Also fix spacing for line."""
861
862
863 comment = ""
864 if line.find(self.comment_char) > -1:
865 line, dum, comment = line.partition(self.comment_char)
866
867
868 quotes = self.quote_chars.finditer(line)
869
870 start_pos = 0
871 line_quotes = []
872 line_no_quotes = []
873 for i, quote in enumerate(quotes):
874 if i % 2 == 0:
875
876 line_no_quotes.append(line[start_pos:quote.start()])
877 start_pos = quote.start()
878 else:
879
880 line_quotes.append(line[start_pos:quote.end()])
881 start_pos = quote.end()
882
883 line_no_quotes.append(line[start_pos:])
884
885
886 line.rstrip()
887 for i, no_quote in enumerate(line_no_quotes):
888 for key in self.spacing_patterns:
889 no_quote = self.spacing_re[key[0]].sub(key[1], no_quote)
890 line_no_quotes[i] = no_quote
891
892
893 line = line_no_quotes[0]
894 for i in range(len(line_quotes)):
895 line += line_quotes[i]
896 if len(line_no_quotes) > i + 1:
897 line += line_no_quotes[i+1]
898
899
900 res_lines = [" " * self.__indent + line]
901
902 while len(res_lines[-1]) > self.line_length:
903 long_line = res_lines[-1]
904 split_at = -1
905 for character in split_characters:
906 index = long_line[(self.line_length - self.max_split): \
907 self.line_length].rfind(character)
908 if index >= 0:
909 split_at = self.line_length - self.max_split + index + 1
910 break
911
912
913 if split_at == -1:
914 split_at = len(long_line)
915 for character in split_characters:
916 split = long_line[self.line_length].find(character)
917 if split > 0:
918 split_at = min(split, split_at)
919 if split_at == len(long_line):
920 break
921
922
923 quotes = self.quote_chars.findall(long_line[:split_at])
924 if quotes and len(quotes) % 2 == 1:
925 quote_match = self.quote_chars.search(long_line[split_at:])
926 if not quote_match:
927 raise self.CPPWriterError(\
928 "Error: Unmatched quote in line " + long_line)
929 split_at = quote_match.end() + split_at + 1
930 split_match = re.search(self.split_characters,
931 long_line[split_at:])
932 if split_match:
933 split_at = split_at + split_match.start()
934 else:
935 split_at = len(long_line) + 1
936
937
938 if long_line[split_at:].lstrip():
939
940 res_lines[-1] = long_line[:split_at].rstrip()
941 res_lines.append(" " * \
942 (self.__indent + self.line_cont_indent) + \
943 long_line[split_at:].strip())
944 else:
945 break
946
947 if comment:
948 res_lines[-1] += " " + self.comment_char + comment
949
950 return res_lines
951
980
986
988
992
994 """Extends the regular file.writeline() function to write out
995 nicely formatted code"""
996
997 self.write(lines)
998