Download code
From LiteratePrograms
Back to Literate_programming_tools_(Matlab)
Download for Windows: zip
Download for UNIX: zip, tar.gz, tar.bz2
ocamaweb2.m
1 % Copyright (c) 2010 the authors listed at the following URL, and/or 2 % the authors of referenced articles or incorporated external code: 3 % http://en.literateprograms.org/Literate_programming_tools_(Matlab)?action=history&offset=20090103220900 4 % 5 % Permission is hereby granted, free of charge, to any person obtaining 6 % a copy of this software and associated documentation files (the 7 % "Software"), to deal in the Software without restriction, including 8 % without limitation the rights to use, copy, modify, merge, publish, 9 % distribute, sublicense, and/or sell copies of the Software, and to 10 % permit persons to whom the Software is furnished to do so, subject to 11 % the following conditions: 12 % 13 % The above copyright notice and this permission notice shall be 14 % included in all copies or substantial portions of the Software. 15 % 16 % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 % MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 % IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 % CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 % TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 % SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 % 24 % Retrieved from: http://en.literateprograms.org/Literate_programming_tools_(Matlab)?oldid=15749 25 26 function str = ocamaweb2(fnames, varargin) 27 % OCAMAWEB2 - produce an ASCII file ready to be pasted into 28 % <a href="http://www.literateprograms.org">LP.org</a>. 29 % 30 % use: 31 % ocamaweb2( matlab_file, 'ascii-file-name' [, first-section-level]) 32 % (default section level is 0) 33 % if you give no file name (or empty file name), nothing is writen. 34 % 35 % You just need to copy-and-paste the obtained file to LP.org 36 % 37 % Author: Charles-Albert LEHALLE 38 39 40 output_style = 'LP.org'; 41 42 43 str = ''; 44 if ~iscell(fnames) 45 fnames = {fnames}; 46 end 47 if nargin<3 48 ext = 0; 49 else 50 ext = varargin{2}; 51 end 52 53 if nargin>1 & ~isempty(varargin{1}) 54 xlog('$open$', [varargin{1} '.log']); 55 end 56 57 blocks = {}; 58 for i=1:length(fnames) 59 [str_tmp, blk_tmp] = FILE2LIT( fnames{i}, ext, output_style); 60 blocks{end+1} = blk_tmp; 61 str = sprintf('%s\n%s', str, str_tmp); 62 end 63 64 65 if nargin>1 & ~isempty(varargin{1}) 66 fod = fopen(varargin{1},'w'); 67 for f=1:length(blocks) 68 this_block = blocks{f}; 69 for b=1:length(this_block) 70 PRETTY_PRINT( fod, this_block(b), output_style, ext); 71 end 72 end 73 %fprintf(fod, '%s', str); 74 fclose(fod); 75 xlog('$close$'); 76 end 77 78 str = blocks; 79 80 81 82 function [str, blocks] = FILE2LIT(fname, ext, output_style) 83 84 str_ext = repmat('=',1,ext+3); 85 str = sprintf('%sFunction %s%s\n', str_ext, fname, str_ext); 86 87 oneliner = help(fname); 88 la = '<'; 89 ra = '>'; 90 str = sprintf('%s\n%s\n<%s language=matlab>\n%s%s%s.m%s%S=', str, strtrim(oneliner), 'codeblock', la, la, fname, ra, ra); 91 92 %blocks = struct('name', fname, 'id', 1, 'cmt', '', 'code', '', 'state', 1); 93 blocks = NEW_BLOCK( [fname '.m'], 1, '', -1, 100, 1, 0); 94 cb = 1; % Current Block Id 95 %BLOCK STATES- 1: read code / 0: read comments 96 97 fid = fopen(which(fname),'r'); 98 while 1 99 tline = fgetl(fid); 100 if ~ischar(tline) 101 break 102 end 103 xlog('>>> %s\n', tline); 104 trline = strtrim(tline); 105 if length(trline)>1 & (all(trline(1:2)=='%%') | all(trline(1:2)=='%<') ) 106 107 if blocks(cb).state == 0 108 % current block is now in code mode 109 blocks(cb).state = 1; 110 xlog('quit comments for <%s>\n', blocks(cb).name); 111 end 112 if all(trline(1:2)=='%%') & blocks(cb).preceeding > 0 113 % if %% -> close preceeding block... 114 % but not the root one 115 xlog('Closing block <%s>\n', blocks(cb).name); 116 blocks(cb).state = 1; 117 cb = blocks(cb).preceeding; 118 xlog('Open block <%s>\n', blocks(cb).name); 119 end 120 % Parsing block heading 121 [b_name, b_type, b_level] = PARSE_1ST_LINE( trline); 122 xlog('block <%s> seen @[%s] as a <%d:%d>\n', b_name, trline, b_type, b_level); 123 % Including block reference into corrent bloc 124 b_id = length(blocks)+1; 125 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, BLOCK_MARK( b_name, b_id, output_style)); 126 % Creating my new block 127 blocks(end+1) = NEW_BLOCK( b_name, 0, '', b_type, b_level, b_id, cb); 128 cb = b_id; 129 130 elseif length(trline)>1 & all(trline(1:2)=='%>') 131 132 xlog('close block <%s>\n', blocks(cb).name); 133 cb = blocks(cb).preceeding; 134 xlog('open block <%s>\n', blocks(cb).name); 135 136 elseif isempty(trline) | trline(1)~='%' 137 138 xlog('end of comments for block <%s>\n', blocks(cb).name); 139 blocks(cb).state = 1; 140 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 141 142 else 143 144 if blocks(cb).state ==0 145 % comment 146 xlog('write into cmt\n'); 147 blocks(cb).cmt = sprintf('%s\n%s', blocks(cb).cmt, strtrim(trline(2:end))); 148 else 149 % code 150 xlog('write into code\n'); 151 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 152 end 153 154 end 155 156 str = sprintf('%s\n%s',str,tline); 157 end 158 fclose(fid); 159 160 str = sprintf('%s\n</%s>\n', str, 'codeblock'); 161 162 163 164 function [bn, bt, bl] = PARSE_1ST_LINE( str) 165 switch str(1:2) 166 case '%%' 167 bt = 0; 168 case '%<' 169 bt = 1; 170 otherwise 171 error('print4literate:P1L', 'problem with line <%s>', str); 172 end 173 str = str(3:end); % if lower error 174 idx_space = strfind(str, ' '); 175 if isempty(idx_space) | idx_space(1)==1 176 bn = str; 177 bl = 0; 178 else 179 bn = str(idx_space(1)+1:end); 180 bl = BLK_LEVEL(str(1:idx_space(1)-1)); 181 end 182 183 184 function lev = BLK_LEVEL( str) 185 switch str 186 case '**' 187 lev = 100; 188 case '*' 189 lev = 10; 190 otherwise 191 lev = str2num(str(2:end)); 192 end 193 194 195 function str = BLOCK_MARK(bname, bnum, bstyle) 196 switch bstyle 197 case 'LP.org' 198 la = '<'; 199 ra = '>'; 200 str = sprintf('\n%s%s%s_%d%s%s', la, la, bname, bnum, ra, ra); 201 otherwise 202 error('P4L:BM', 'no style <%s> available', bstyle); 203 end 204 205 206 function blk = NEW_BLOCK( b_name, b_state, cmt, b_type, b_level, b_id, p_block) 207 blk = struct('name', b_name, 'id', b_id, 'cmt', cmt, 'code', '', 'state', b_state, 'type', b_type, 'level', b_level, 'preceeding', p_block); 208 209 210 function PRETTY_PRINT( fod, ablock, output_style, dec) 211 if nargin < 4 212 dec = 0; 213 end 214 % Comments 215 fprintf(fod, PRETTY_SECTION( output_style, ablock.level, ablock.name, ablock.cmt, ablock.id, dec)); 216 % Code 217 fprintf(fod, PRETTY_CODE( output_style, ablock.level, ablock.name, ablock.code, ablock.id, dec)); 218 219 220 function str = PRETTY_SECTION( output_style, level, name, cmt, id, dec) 221 switch output_style 222 case 'LP.org' 223 sections = { {'==', '=='}, {'===', '==='}, {'====', '===='}, {'''''''', '.''''''<br/>'}, {'''''', '.''''<br/>'}}; 224 otherwise 225 error('P4L:SECTION', 'style <%s> unknown', output_style); 226 end 227 str = sprintf('%s%s%s\n%s\n', GET_LEV_BEFORE(sections, level, dec), name, GET_LEV_AFTER(sections, level, dec), PRETTY_CMT(output_style, cmt)); 228 229 230 231 function str = GET_LEV_BEFORE(sections, level, dec) 232 if level == 100 233 level = -2; 234 elseif level == 10 235 level = -1; 236 end 237 level = min(level+3+dec, length(sections)); 238 str = sections{level}{1}; 239 240 241 function str = GET_LEV_AFTER(sections, level, dec) 242 if level == 100 243 level = -2; 244 elseif level == 10 245 level = -1; 246 end 247 level = min(level+3+dec, length(sections)); 248 str = sections{level}{2}; 249 250 251 252 253 function str = PRETTY_CMT(output_style, cmt) 254 str = regexprep(cmt, '\$\$([^\$]+)\$\$', 'UNIQ226ad661200f6268-math163bb624b218e7400000001'); 255 str = regexprep(str, '\$([^\$]+)\$', 'UNIQ226ad661200f6268-math163bb624b218e7400000002'); 256 str = strrep(str, '\', '\\'); 257 258 259 function str = PRETTY_CODE( output_style, level, name, code, id, dec) 260 switch output_style 261 case 'LP.org' 262 cb = 'codeblock'; 263 ra = '<'; 264 la = '>'; 265 sections = { ['<' cb ' language="matlab">'], [ra ra], [la la '='], ['</' cb '>'] }; 266 otherwise 267 error('P4L:CODE', 'style <%s> unknown', output_style); 268 end 269 if id>1 270 name = sprintf('%s_%d', name, id); 271 end 272 str = sprintf('%s\n%s%s%s%s\n%s\n', sections{1}, sections{2}, name, sections{3}, STR_REP(code), sections{4}); 273 274 275 function str = STR_REP( str) 276 str = strrep(strrep(str, '%', '%%'), '\', '\\'); 277 278 279 280
ocamaweb2_original.m
1 % Copyright (c) 2010 the authors listed at the following URL, and/or 2 % the authors of referenced articles or incorporated external code: 3 % http://en.literateprograms.org/Literate_programming_tools_(Matlab)?action=history&offset=20090103220900 4 % 5 % Permission is hereby granted, free of charge, to any person obtaining 6 % a copy of this software and associated documentation files (the 7 % "Software"), to deal in the Software without restriction, including 8 % without limitation the rights to use, copy, modify, merge, publish, 9 % distribute, sublicense, and/or sell copies of the Software, and to 10 % permit persons to whom the Software is furnished to do so, subject to 11 % the following conditions: 12 % 13 % The above copyright notice and this permission notice shall be 14 % included in all copies or substantial portions of the Software. 15 % 16 % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 % MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 % IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 % CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 % TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 % SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 % 24 % Retrieved from: http://en.literateprograms.org/Literate_programming_tools_(Matlab)?oldid=15749 25 26 function str = ocamaweb2(fnames, varargin) 27 % OCAMAWEB2 - produce an ASCII file ready to be pasted into 28 % <a href="http://www.literateprograms.org">LP.org</a>. 29 % 30 % use: 31 % ocamaweb2( matlab_file, 'ascii-file-name' [, first-section-level]) 32 % (default section level is 0) 33 % if you give no file name (or empty file name), nothing is writen. 34 % 35 % You just need to copy-and-paste the obtained file to LP.org 36 % 37 % Author: Charles-Albert LEHALLE 38 39 %%** Ocamaweb4LP.org 40 % To export codes to LP.org 41 output_style = 'LP.org'; 42 43 %<* Default values for parameters 44 % If only one file, it's put in a cellarray. 45 str = ''; 46 if ~iscell(fnames) 47 fnames = {fnames}; 48 end 49 if nargin<3 50 ext = 0; 51 else 52 ext = varargin{2}; 53 end 54 %>* 55 if nargin>1 & ~isempty(varargin{1}) 56 xlog('$open$', [varargin{1} '.log']); 57 end 58 %<* Read all files 59 % Read all files 60 % inside a loop. 61 blocks = {}; 62 for i=1:length(fnames) 63 [str_tmp, blk_tmp] = FILE2LIT( fnames{i}, ext, output_style); 64 blocks{end+1} = blk_tmp; 65 str = sprintf('%s\n%s', str, str_tmp); 66 end 67 %>* 68 %<* Write in a file if needed 69 if nargin>1 & ~isempty(varargin{1}) 70 fod = fopen(varargin{1},'w'); 71 for f=1:length(blocks) 72 this_block = blocks{f}; 73 for b=1:length(this_block) 74 PRETTY_PRINT( fod, this_block(b), output_style, ext); 75 end 76 end 77 %fprintf(fod, '%s', str); 78 fclose(fod); 79 xlog('$close$'); 80 end 81 %>* 82 str = blocks; 83 %%** Internals 84 % All the internal functions are here. 85 % They are the main processing elements of this function. 86 %< Parse one matfile 87 function [str, blocks] = FILE2LIT(fname, ext, output_style) 88 89 str_ext = repmat('=',1,ext+3); 90 str = sprintf('%sFunction %s%s\n', str_ext, fname, str_ext); 91 92 oneliner = help(fname); 93 la = '<'; 94 ra = '>'; 95 str = sprintf('%s\n%s\n<%s language=matlab>\n%s%s%s.m%s%S=', str, strtrim(oneliner), 'codeblock', la, la, fname, ra, ra); 96 97 %blocks = struct('name', fname, 'id', 1, 'cmt', '', 'code', '', 'state', 1); 98 blocks = NEW_BLOCK( [fname '.m'], 1, '', -1, 100, 1, 0); 99 cb = 1; % Current Block Id 100 %BLOCK STATES- 1: read code / 0: read comments 101 102 fid = fopen(which(fname),'r'); 103 while 1 104 tline = fgetl(fid); 105 if ~ischar(tline) 106 break 107 end 108 xlog('>>> %s\n', tline); 109 trline = strtrim(tline); 110 if length(trline)>1 & (all(trline(1:2)=='%%') | all(trline(1:2)=='%<') ) 111 %< Begin of block 112 if blocks(cb).state == 0 113 % current block is now in code mode 114 blocks(cb).state = 1; 115 xlog('quit comments for <%s>\n', blocks(cb).name); 116 end 117 if all(trline(1:2)=='%%') & blocks(cb).preceeding > 0 118 % if %% -> close preceeding block... 119 % but not the root one 120 xlog('Closing block <%s>\n', blocks(cb).name); 121 blocks(cb).state = 1; 122 cb = blocks(cb).preceeding; 123 xlog('Open block <%s>\n', blocks(cb).name); 124 end 125 % Parsing block heading 126 [b_name, b_type, b_level] = PARSE_1ST_LINE( trline); 127 xlog('block <%s> seen @[%s] as a <%d:%d>\n', b_name, trline, b_type, b_level); 128 % Including block reference into corrent bloc 129 b_id = length(blocks)+1; 130 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, BLOCK_MARK( b_name, b_id, output_style)); 131 % Creating my new block 132 blocks(end+1) = NEW_BLOCK( b_name, 0, '', b_type, b_level, b_id, cb); 133 cb = b_id; 134 %> 135 elseif length(trline)>1 & all(trline(1:2)=='%>') 136 %< End of block 137 xlog('close block <%s>\n', blocks(cb).name); 138 cb = blocks(cb).preceeding; 139 xlog('open block <%s>\n', blocks(cb).name); 140 %> 141 elseif isempty(trline) | trline(1)~='%' 142 %< End of comments 143 xlog('end of comments for block <%s>\n', blocks(cb).name); 144 blocks(cb).state = 1; 145 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 146 %> 147 else 148 %< Write comment or code 149 if blocks(cb).state ==0 150 % comment 151 xlog('write into cmt\n'); 152 blocks(cb).cmt = sprintf('%s\n%s', blocks(cb).cmt, strtrim(trline(2:end))); 153 else 154 % code 155 xlog('write into code\n'); 156 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 157 end 158 %> 159 end 160 161 str = sprintf('%s\n%s',str,tline); 162 end 163 fclose(fid); 164 165 str = sprintf('%s\n</%s>\n', str, 'codeblock'); 166 %>* 167 168 %<*3 Parse the first block line 169 % returns the block name, the block type, and the block level 170 function [bn, bt, bl] = PARSE_1ST_LINE( str) 171 switch str(1:2) 172 case '%%' 173 bt = 0; 174 case '%<' 175 bt = 1; 176 otherwise 177 error('print4literate:P1L', 'problem with line <%s>', str); 178 end 179 str = str(3:end); % if lower error 180 idx_space = strfind(str, ' '); 181 if isempty(idx_space) | idx_space(1)==1 182 bn = str; 183 bl = 0; 184 else 185 bn = str(idx_space(1)+1:end); 186 bl = BLK_LEVEL(str(1:idx_space(1)-1)); 187 end 188 %>* 189 %<* Guess block level 190 function lev = BLK_LEVEL( str) 191 switch str 192 case '**' 193 lev = 100; 194 case '*' 195 lev = 10; 196 otherwise 197 lev = str2num(str(2:end)); 198 end 199 %>* 200 %<* Write block mark 201 function str = BLOCK_MARK(bname, bnum, bstyle) 202 switch bstyle 203 case 'LP.org' 204 la = '<'; 205 ra = '>'; 206 str = sprintf('\n%s%s%s_%d%s%s', la, la, bname, bnum, ra, ra); 207 otherwise 208 error('P4L:BM', 'no style <%s> available', bstyle); 209 end 210 %>* 211 %<* Create new block 212 function blk = NEW_BLOCK( b_name, b_state, cmt, b_type, b_level, b_id, p_block) 213 blk = struct('name', b_name, 'id', b_id, 'cmt', cmt, 'code', '', 'state', b_state, 'type', b_type, 'level', b_level, 'preceeding', p_block); 214 %>* 215 %<* Final print 216 function PRETTY_PRINT( fod, ablock, output_style, dec) 217 if nargin < 4 218 dec = 0; 219 end 220 % Comments 221 fprintf(fod, PRETTY_SECTION( output_style, ablock.level, ablock.name, ablock.cmt, ablock.id, dec)); 222 % Code 223 fprintf(fod, PRETTY_CODE( output_style, ablock.level, ablock.name, ablock.code, ablock.id, dec)); 224 %>* 225 %<* Pretty Section 226 function str = PRETTY_SECTION( output_style, level, name, cmt, id, dec) 227 switch output_style 228 case 'LP.org' 229 sections = { {'==', '=='}, {'===', '==='}, {'====', '===='}, {'''''''', '.''''''<br/>'}, {'''''', '.''''<br/>'}}; 230 otherwise 231 error('P4L:SECTION', 'style <%s> unknown', output_style); 232 end 233 str = sprintf('%s%s%s\n%s\n', GET_LEV_BEFORE(sections, level, dec), name, GET_LEV_AFTER(sections, level, dec), PRETTY_CMT(output_style, cmt)); 234 %>* 235 %<* Get section codes 236 %< Before section 237 function str = GET_LEV_BEFORE(sections, level, dec) 238 if level == 100 239 level = -2; 240 elseif level == 10 241 level = -1; 242 end 243 level = min(level+3+dec, length(sections)); 244 str = sections{level}{1}; 245 %> 246 %< After section 247 function str = GET_LEV_AFTER(sections, level, dec) 248 if level == 100 249 level = -2; 250 elseif level == 10 251 level = -1; 252 end 253 level = min(level+3+dec, length(sections)); 254 str = sections{level}{2}; 255 %> 256 %>* 257 %<* Pretty outputs 258 %< Pretty Cmt 259 % This one is special for LaTeX expressions, for instance 260 % $\alpha=\int_{x\in\Omega} f_\alpha(x)dx$ should be translated to a math 261 % expression for LP.org. 262 function str = PRETTY_CMT(output_style, cmt) 263 str = regexprep(cmt, '\$\$([^\$]+)\$\$', 'UNIQ11b46e5157593704-math5bece46f18884d6100000001'); 264 str = regexprep(str, '\$([^\$]+)\$', 'UNIQ11b46e5157593704-math5bece46f18884d6100000002'); 265 str = strrep(str, '\', '\\'); 266 %> 267 %< Pretty Code 268 function str = PRETTY_CODE( output_style, level, name, code, id, dec) 269 switch output_style 270 case 'LP.org' 271 cb = 'codeblock'; 272 ra = '<'; 273 la = '>'; 274 sections = { ['<' cb ' language="matlab">'], [ra ra], [la la '='], ['</' cb '>'] }; 275 otherwise 276 error('P4L:CODE', 'style <%s> unknown', output_style); 277 end 278 if id>1 279 name = sprintf('%s_%d', name, id); 280 end 281 str = sprintf('%s\n%s%s%s%s\n%s\n', sections{1}, sections{2}, name, sections{3}, STR_REP(code), sections{4}); 282 %> 283 %< String Replace 284 function str = STR_REP( str) 285 str = strrep(strrep(str, '%', '%%'), '\', '\\'); 286 %> 287 %>* 288
print4literate.m
1 % Copyright (c) 2010 the authors listed at the following URL, and/or 2 % the authors of referenced articles or incorporated external code: 3 % http://en.literateprograms.org/Literate_programming_tools_(Matlab)?action=history&offset=20090103220900 4 % 5 % Permission is hereby granted, free of charge, to any person obtaining 6 % a copy of this software and associated documentation files (the 7 % "Software"), to deal in the Software without restriction, including 8 % without limitation the rights to use, copy, modify, merge, publish, 9 % distribute, sublicense, and/or sell copies of the Software, and to 10 % permit persons to whom the Software is furnished to do so, subject to 11 % the following conditions: 12 % 13 % The above copyright notice and this permission notice shall be 14 % included in all copies or substantial portions of the Software. 15 % 16 % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 % MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 % IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 % CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 % TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 % SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 % 24 % Retrieved from: http://en.literateprograms.org/Literate_programming_tools_(Matlab)?oldid=15749 25 26 function str = print4literate(fnames, varargin) 27 % PRINT4LITERATE - produce an ASCII file ready to be pasted into 28 % <a href="http://www.literateprograms.org">LP.org</a>. 29 % 30 % use: 31 % print4literate({file1, ..., fileN}, 'ascii-file-name' [, section-level]) 32 % (default section level is 3) 33 % if you give no file name (or empty file name), nothing is writen. 34 % 35 % Original author: Charles-Albert LEHALLE 36 37 str = ''; 38 if ~iscell(fnames) 39 fnames = {fnames}; 40 end 41 if nargin<3 42 ext = 3; 43 else 44 ext = varargin{2}; 45 end 46 for i=1:length(fnames) 47 str = sprintf('%s\n%s', str, FILE2LIT( fnames{i}, ext)); 48 end 49 if nargin>1 & ~isempty(varargin{1}) 50 fod = fopen(varargin{1},'w'); 51 fprintf(fod, '%s', str); 52 fclose(fod); 53 end 54 55 %%* Work on one function 56 function str = FILE2LIT(fname, ext) 57 str_ext = repmat('=',1,ext); 58 str = sprintf('%sFunction %s%s\n', str_ext, fname, str_ext); 59 60 oneliner = help(fname); 61 str = sprintf('%s\n%s\n<%s language=matlab>\n=', str, strtrim(oneliner), 'codeblock', fname); 62 63 fid = fopen(which(fname),'r'); 64 while 1 65 tline = fgetl(fid); 66 if ~ischar(tline), break, end 67 str = sprintf('%s\n%s',str,tline); 68 end 69 fclose(fid); 70 71 str = sprintf('%s\n</%s>\n', str, 'codeblock'); 72
noweb.log
1 undefined chunk name: <<%s.m>>
input.nw
1 2 <<print4literate.m>>= 3 function str = print4literate(fnames, varargin) 4 % PRINT4LITERATE - produce an ASCII file ready to be pasted into 5 % <a href="http://www.literateprograms.org">LP.org</a>. 6 % 7 % use: 8 % print4literate({file1, ..., fileN}, 'ascii-file-name' [, section-level]) 9 % (default section level is 3) 10 % if you give no file name (or empty file name), nothing is writen. 11 % 12 % Original author: Charles-Albert LEHALLE 13 14 str = ''; 15 if ~iscell(fnames) 16 fnames = {fnames}; 17 end 18 if nargin<3 19 ext = 3; 20 else 21 ext = varargin{2}; 22 end 23 for i=1:length(fnames) 24 str = sprintf('%s\n%s', str, FILE2LIT( fnames{i}, ext)); 25 end 26 if nargin>1 & ~isempty(varargin{1}) 27 fod = fopen(varargin{1},'w'); 28 fprintf(fod, '%s', str); 29 fclose(fod); 30 end 31 32 %%* Work on one function 33 function str = FILE2LIT(fname, ext) 34 str_ext = repmat('=',1,ext); 35 str = sprintf('%sFunction %s%s\n', str_ext, fname, str_ext); 36 37 oneliner = help(fname); 38 str = sprintf('%s\n%s\n<%s language=matlab>\n<<%s.m>>=', str, strtrim(oneliner), 'codeblock', fname); 39 40 fid = fopen(which(fname),'r'); 41 while 1 42 tline = fgetl(fid); 43 if ~ischar(tline), break, end 44 str = sprintf('%s\n%s',str,tline); 45 end 46 fclose(fid); 47 48 str = sprintf('%s\n</%s>\n', str, 'codeblock'); 49 50 @ text 51 52 53 <<ocamaweb2.m>>= 54 function str = ocamaweb2(fnames, varargin) 55 % OCAMAWEB2 - produce an ASCII file ready to be pasted into 56 % <a href="http://www.literateprograms.org">LP.org</a>. 57 % 58 % use: 59 % ocamaweb2( matlab_file, 'ascii-file-name' [, first-section-level]) 60 % (default section level is 0) 61 % if you give no file name (or empty file name), nothing is writen. 62 % 63 % You just need to copy-and-paste the obtained file to LP.org 64 % 65 % Author: Charles-Albert LEHALLE 66 67 68 <<Ocamaweb4LP.org_2>> 69 70 <<Internals_6>> 71 72 @ text 73 74 75 <<Ocamaweb4LP.org_2>>= 76 output_style = 'LP.org'; 77 78 79 <<Default values for parameters_3>> 80 if nargin>1 & ~isempty(varargin{1}) 81 xlog('$open$', [varargin{1} '.log']); 82 end 83 84 <<Read all files_4>> 85 86 <<Write in a file if needed_5>> 87 str = blocks; 88 89 @ text 90 91 92 <<Default values for parameters_3>>= 93 str = ''; 94 if ~iscell(fnames) 95 fnames = {fnames}; 96 end 97 if nargin<3 98 ext = 0; 99 else 100 ext = varargin{2}; 101 end 102 103 @ text 104 105 106 <<Read all files_4>>= 107 blocks = {}; 108 for i=1:length(fnames) 109 [str_tmp, blk_tmp] = FILE2LIT( fnames{i}, ext, output_style); 110 blocks{end+1} = blk_tmp; 111 str = sprintf('%s\n%s', str, str_tmp); 112 end 113 114 @ text 115 116 117 <<Write in a file if needed_5>>= 118 if nargin>1 & ~isempty(varargin{1}) 119 fod = fopen(varargin{1},'w'); 120 for f=1:length(blocks) 121 this_block = blocks{f}; 122 for b=1:length(this_block) 123 PRETTY_PRINT( fod, this_block(b), output_style, ext); 124 end 125 end 126 %fprintf(fod, '%s', str); 127 fclose(fod); 128 xlog('$close$'); 129 end 130 131 @ text 132 133 134 <<Internals_6>>= 135 136 << Parse one matfile_7>> 137 138 139 <<Parse the first block line_12>> 140 141 <<Guess block level_13>> 142 143 <<Write block mark_14>> 144 145 <<Create new block_15>> 146 147 <<Final print_16>> 148 149 <<Pretty Section_17>> 150 151 <<Get section codes_18>> 152 153 <<Pretty outputs_21>> 154 155 @ text 156 157 158 << Parse one matfile_7>>= 159 function [str, blocks] = FILE2LIT(fname, ext, output_style) 160 161 str_ext = repmat('=',1,ext+3); 162 str = sprintf('%sFunction %s%s\n', str_ext, fname, str_ext); 163 164 oneliner = help(fname); 165 la = '<'; 166 ra = '>'; 167 str = sprintf('%s\n%s\n<%s language=matlab>\n%s%s%s.m%s%S=', str, strtrim(oneliner), 'codeblock', la, la, fname, ra, ra); 168 169 %blocks = struct('name', fname, 'id', 1, 'cmt', '', 'code', '', 'state', 1); 170 blocks = NEW_BLOCK( [fname '.m'], 1, '', -1, 100, 1, 0); 171 cb = 1; % Current Block Id 172 %BLOCK STATES- 1: read code / 0: read comments 173 174 fid = fopen(which(fname),'r'); 175 while 1 176 tline = fgetl(fid); 177 if ~ischar(tline) 178 break 179 end 180 xlog('>>> %s\n', tline); 181 trline = strtrim(tline); 182 if length(trline)>1 & (all(trline(1:2)=='%%') | all(trline(1:2)=='%<') ) 183 184 << Begin of block_8>> 185 elseif length(trline)>1 & all(trline(1:2)=='%>') 186 187 << End of block_9>> 188 elseif isempty(trline) | trline(1)~='%' 189 190 << End of comments_10>> 191 else 192 193 << Write comment or code_11>> 194 end 195 196 str = sprintf('%s\n%s',str,tline); 197 end 198 fclose(fid); 199 200 str = sprintf('%s\n</%s>\n', str, 'codeblock'); 201 202 @ text 203 204 205 << Begin of block_8>>= 206 if blocks(cb).state == 0 207 % current block is now in code mode 208 blocks(cb).state = 1; 209 xlog('quit comments for <%s>\n', blocks(cb).name); 210 end 211 if all(trline(1:2)=='%%') & blocks(cb).preceeding > 0 212 % if %% -> close preceeding block... 213 % but not the root one 214 xlog('Closing block <%s>\n', blocks(cb).name); 215 blocks(cb).state = 1; 216 cb = blocks(cb).preceeding; 217 xlog('Open block <%s>\n', blocks(cb).name); 218 end 219 % Parsing block heading 220 [b_name, b_type, b_level] = PARSE_1ST_LINE( trline); 221 xlog('block <%s> seen @[%s] as a <%d:%d>\n', b_name, trline, b_type, b_level); 222 % Including block reference into corrent bloc 223 b_id = length(blocks)+1; 224 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, BLOCK_MARK( b_name, b_id, output_style)); 225 % Creating my new block 226 blocks(end+1) = NEW_BLOCK( b_name, 0, '', b_type, b_level, b_id, cb); 227 cb = b_id; 228 229 @ text 230 231 232 << End of block_9>>= 233 xlog('close block <%s>\n', blocks(cb).name); 234 cb = blocks(cb).preceeding; 235 xlog('open block <%s>\n', blocks(cb).name); 236 237 @ text 238 239 240 << End of comments_10>>= 241 xlog('end of comments for block <%s>\n', blocks(cb).name); 242 blocks(cb).state = 1; 243 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 244 245 @ text 246 247 248 << Write comment or code_11>>= 249 if blocks(cb).state ==0 250 % comment 251 xlog('write into cmt\n'); 252 blocks(cb).cmt = sprintf('%s\n%s', blocks(cb).cmt, strtrim(trline(2:end))); 253 else 254 % code 255 xlog('write into code\n'); 256 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 257 end 258 259 @ text 260 261 262 <<Parse the first block line_12>>= 263 function [bn, bt, bl] = PARSE_1ST_LINE( str) 264 switch str(1:2) 265 case '%%' 266 bt = 0; 267 case '%<' 268 bt = 1; 269 otherwise 270 error('print4literate:P1L', 'problem with line <%s>', str); 271 end 272 str = str(3:end); % if lower error 273 idx_space = strfind(str, ' '); 274 if isempty(idx_space) | idx_space(1)==1 275 bn = str; 276 bl = 0; 277 else 278 bn = str(idx_space(1)+1:end); 279 bl = BLK_LEVEL(str(1:idx_space(1)-1)); 280 end 281 282 @ text 283 284 285 <<Guess block level_13>>= 286 function lev = BLK_LEVEL( str) 287 switch str 288 case '**' 289 lev = 100; 290 case '*' 291 lev = 10; 292 otherwise 293 lev = str2num(str(2:end)); 294 end 295 296 @ text 297 298 299 <<Write block mark_14>>= 300 function str = BLOCK_MARK(bname, bnum, bstyle) 301 switch bstyle 302 case 'LP.org' 303 la = '<'; 304 ra = '>'; 305 str = sprintf('\n%s%s%s_%d%s%s', la, la, bname, bnum, ra, ra); 306 otherwise 307 error('P4L:BM', 'no style <%s> available', bstyle); 308 end 309 310 @ text 311 312 313 <<Create new block_15>>= 314 function blk = NEW_BLOCK( b_name, b_state, cmt, b_type, b_level, b_id, p_block) 315 blk = struct('name', b_name, 'id', b_id, 'cmt', cmt, 'code', '', 'state', b_state, 'type', b_type, 'level', b_level, 'preceeding', p_block); 316 317 @ text 318 319 320 <<Final print_16>>= 321 function PRETTY_PRINT( fod, ablock, output_style, dec) 322 if nargin < 4 323 dec = 0; 324 end 325 % Comments 326 fprintf(fod, PRETTY_SECTION( output_style, ablock.level, ablock.name, ablock.cmt, ablock.id, dec)); 327 % Code 328 fprintf(fod, PRETTY_CODE( output_style, ablock.level, ablock.name, ablock.code, ablock.id, dec)); 329 330 @ text 331 332 333 <<Pretty Section_17>>= 334 function str = PRETTY_SECTION( output_style, level, name, cmt, id, dec) 335 switch output_style 336 case 'LP.org' 337 sections = { {'==', '=='}, {'===', '==='}, {'====', '===='}, {'''''''', '.''''''<br/>'}, {'''''', '.''''<br/>'}}; 338 otherwise 339 error('P4L:SECTION', 'style <%s> unknown', output_style); 340 end 341 str = sprintf('%s%s%s\n%s\n', GET_LEV_BEFORE(sections, level, dec), name, GET_LEV_AFTER(sections, level, dec), PRETTY_CMT(output_style, cmt)); 342 343 @ text 344 345 346 <<Get section codes_18>>= 347 348 << Before section_19>> 349 350 << After section_20>> 351 352 @ text 353 354 355 << Before section_19>>= 356 function str = GET_LEV_BEFORE(sections, level, dec) 357 if level == 100 358 level = -2; 359 elseif level == 10 360 level = -1; 361 end 362 level = min(level+3+dec, length(sections)); 363 str = sections{level}{1}; 364 365 @ text 366 367 368 << After section_20>>= 369 function str = GET_LEV_AFTER(sections, level, dec) 370 if level == 100 371 level = -2; 372 elseif level == 10 373 level = -1; 374 end 375 level = min(level+3+dec, length(sections)); 376 str = sections{level}{2}; 377 378 @ text 379 380 381 <<Pretty outputs_21>>= 382 383 << Pretty Cmt_22>> 384 385 << Pretty Code_23>> 386 387 << String Replace_24>> 388 389 @ text 390 391 392 << Pretty Cmt_22>>= 393 function str = PRETTY_CMT(output_style, cmt) 394 str = regexprep(cmt, '\$\$([^\$]+)\$\$', '$1'); 395 str = regexprep(str, '\$([^\$]+)\$', '$1'); 396 str = strrep(str, '\', '\\'); 397 398 @ text 399 400 401 << Pretty Code_23>>= 402 function str = PRETTY_CODE( output_style, level, name, code, id, dec) 403 switch output_style 404 case 'LP.org' 405 cb = 'codeblock'; 406 ra = '<'; 407 la = '>'; 408 sections = { ['<' cb ' language="matlab">'], [ra ra], [la la '='], ['</' cb '>'] }; 409 otherwise 410 error('P4L:CODE', 'style <%s> unknown', output_style); 411 end 412 if id>1 413 name = sprintf('%s_%d', name, id); 414 end 415 str = sprintf('%s\n%s%s%s%s\n%s\n', sections{1}, sections{2}, name, sections{3}, STR_REP(code), sections{4}); 416 417 @ text 418 419 420 << String Replace_24>>= 421 function str = STR_REP( str) 422 str = strrep(strrep(str, '%', '%%'), '\', '\\'); 423 424 @ text 425 426 427 <<ocamaweb2_original.m>>= 428 function str = ocamaweb2(fnames, varargin) 429 % OCAMAWEB2 - produce an ASCII file ready to be pasted into 430 % <a href="http://www.literateprograms.org">LP.org</a>. 431 % 432 % use: 433 % ocamaweb2( matlab_file, 'ascii-file-name' [, first-section-level]) 434 % (default section level is 0) 435 % if you give no file name (or empty file name), nothing is writen. 436 % 437 % You just need to copy-and-paste the obtained file to LP.org 438 % 439 % Author: Charles-Albert LEHALLE 440 441 %%** Ocamaweb4LP.org 442 % To export codes to LP.org 443 output_style = 'LP.org'; 444 445 %<* Default values for parameters 446 % If only one file, it's put in a cellarray. 447 str = ''; 448 if ~iscell(fnames) 449 fnames = {fnames}; 450 end 451 if nargin<3 452 ext = 0; 453 else 454 ext = varargin{2}; 455 end 456 %>* 457 if nargin>1 & ~isempty(varargin{1}) 458 xlog('$open$', [varargin{1} '.log']); 459 end 460 %<* Read all files 461 % Read all files 462 % inside a loop. 463 blocks = {}; 464 for i=1:length(fnames) 465 [str_tmp, blk_tmp] = FILE2LIT( fnames{i}, ext, output_style); 466 blocks{end+1} = blk_tmp; 467 str = sprintf('%s\n%s', str, str_tmp); 468 end 469 %>* 470 %<* Write in a file if needed 471 if nargin>1 & ~isempty(varargin{1}) 472 fod = fopen(varargin{1},'w'); 473 for f=1:length(blocks) 474 this_block = blocks{f}; 475 for b=1:length(this_block) 476 PRETTY_PRINT( fod, this_block(b), output_style, ext); 477 end 478 end 479 %fprintf(fod, '%s', str); 480 fclose(fod); 481 xlog('$close$'); 482 end 483 %>* 484 str = blocks; 485 %%** Internals 486 % All the internal functions are here. 487 % They are the main processing elements of this function. 488 %< Parse one matfile 489 function [str, blocks] = FILE2LIT(fname, ext, output_style) 490 491 str_ext = repmat('=',1,ext+3); 492 str = sprintf('%sFunction %s%s\n', str_ext, fname, str_ext); 493 494 oneliner = help(fname); 495 la = '<'; 496 ra = '>'; 497 str = sprintf('%s\n%s\n<%s language=matlab>\n%s%s%s.m%s%S=', str, strtrim(oneliner), 'codeblock', la, la, fname, ra, ra); 498 499 %blocks = struct('name', fname, 'id', 1, 'cmt', '', 'code', '', 'state', 1); 500 blocks = NEW_BLOCK( [fname '.m'], 1, '', -1, 100, 1, 0); 501 cb = 1; % Current Block Id 502 %BLOCK STATES- 1: read code / 0: read comments 503 504 fid = fopen(which(fname),'r'); 505 while 1 506 tline = fgetl(fid); 507 if ~ischar(tline) 508 break 509 end 510 xlog('>>> %s\n', tline); 511 trline = strtrim(tline); 512 if length(trline)>1 & (all(trline(1:2)=='%%') | all(trline(1:2)=='%<') ) 513 %< Begin of block 514 if blocks(cb).state == 0 515 % current block is now in code mode 516 blocks(cb).state = 1; 517 xlog('quit comments for <%s>\n', blocks(cb).name); 518 end 519 if all(trline(1:2)=='%%') & blocks(cb).preceeding > 0 520 % if %% -> close preceeding block... 521 % but not the root one 522 xlog('Closing block <%s>\n', blocks(cb).name); 523 blocks(cb).state = 1; 524 cb = blocks(cb).preceeding; 525 xlog('Open block <%s>\n', blocks(cb).name); 526 end 527 % Parsing block heading 528 [b_name, b_type, b_level] = PARSE_1ST_LINE( trline); 529 xlog('block <%s> seen @[%s] as a <%d:%d>\n', b_name, trline, b_type, b_level); 530 % Including block reference into corrent bloc 531 b_id = length(blocks)+1; 532 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, BLOCK_MARK( b_name, b_id, output_style)); 533 % Creating my new block 534 blocks(end+1) = NEW_BLOCK( b_name, 0, '', b_type, b_level, b_id, cb); 535 cb = b_id; 536 %> 537 elseif length(trline)>1 & all(trline(1:2)=='%>') 538 %< End of block 539 xlog('close block <%s>\n', blocks(cb).name); 540 cb = blocks(cb).preceeding; 541 xlog('open block <%s>\n', blocks(cb).name); 542 %> 543 elseif isempty(trline) | trline(1)~='%' 544 %< End of comments 545 xlog('end of comments for block <%s>\n', blocks(cb).name); 546 blocks(cb).state = 1; 547 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 548 %> 549 else 550 %< Write comment or code 551 if blocks(cb).state ==0 552 % comment 553 xlog('write into cmt\n'); 554 blocks(cb).cmt = sprintf('%s\n%s', blocks(cb).cmt, strtrim(trline(2:end))); 555 else 556 % code 557 xlog('write into code\n'); 558 blocks(cb).code = sprintf('%s\n%s', blocks(cb).code, tline); 559 end 560 %> 561 end 562 563 str = sprintf('%s\n%s',str,tline); 564 end 565 fclose(fid); 566 567 str = sprintf('%s\n</%s>\n', str, 'codeblock'); 568 %>* 569 570 %<*3 Parse the first block line 571 % returns the block name, the block type, and the block level 572 function [bn, bt, bl] = PARSE_1ST_LINE( str) 573 switch str(1:2) 574 case '%%' 575 bt = 0; 576 case '%<' 577 bt = 1; 578 otherwise 579 error('print4literate:P1L', 'problem with line <%s>', str); 580 end 581 str = str(3:end); % if lower error 582 idx_space = strfind(str, ' '); 583 if isempty(idx_space) | idx_space(1)==1 584 bn = str; 585 bl = 0; 586 else 587 bn = str(idx_space(1)+1:end); 588 bl = BLK_LEVEL(str(1:idx_space(1)-1)); 589 end 590 %>* 591 %<* Guess block level 592 function lev = BLK_LEVEL( str) 593 switch str 594 case '**' 595 lev = 100; 596 case '*' 597 lev = 10; 598 otherwise 599 lev = str2num(str(2:end)); 600 end 601 %>* 602 %<* Write block mark 603 function str = BLOCK_MARK(bname, bnum, bstyle) 604 switch bstyle 605 case 'LP.org' 606 la = '<'; 607 ra = '>'; 608 str = sprintf('\n%s%s%s_%d%s%s', la, la, bname, bnum, ra, ra); 609 otherwise 610 error('P4L:BM', 'no style <%s> available', bstyle); 611 end 612 %>* 613 %<* Create new block 614 function blk = NEW_BLOCK( b_name, b_state, cmt, b_type, b_level, b_id, p_block) 615 blk = struct('name', b_name, 'id', b_id, 'cmt', cmt, 'code', '', 'state', b_state, 'type', b_type, 'level', b_level, 'preceeding', p_block); 616 %>* 617 %<* Final print 618 function PRETTY_PRINT( fod, ablock, output_style, dec) 619 if nargin < 4 620 dec = 0; 621 end 622 % Comments 623 fprintf(fod, PRETTY_SECTION( output_style, ablock.level, ablock.name, ablock.cmt, ablock.id, dec)); 624 % Code 625 fprintf(fod, PRETTY_CODE( output_style, ablock.level, ablock.name, ablock.code, ablock.id, dec)); 626 %>* 627 %<* Pretty Section 628 function str = PRETTY_SECTION( output_style, level, name, cmt, id, dec) 629 switch output_style 630 case 'LP.org' 631 sections = { {'==', '=='}, {'===', '==='}, {'====', '===='}, {'''''''', '.''''''<br/>'}, {'''''', '.''''<br/>'}}; 632 otherwise 633 error('P4L:SECTION', 'style <%s> unknown', output_style); 634 end 635 str = sprintf('%s%s%s\n%s\n', GET_LEV_BEFORE(sections, level, dec), name, GET_LEV_AFTER(sections, level, dec), PRETTY_CMT(output_style, cmt)); 636 %>* 637 %<* Get section codes 638 %< Before section 639 function str = GET_LEV_BEFORE(sections, level, dec) 640 if level == 100 641 level = -2; 642 elseif level == 10 643 level = -1; 644 end 645 level = min(level+3+dec, length(sections)); 646 str = sections{level}{1}; 647 %> 648 %< After section 649 function str = GET_LEV_AFTER(sections, level, dec) 650 if level == 100 651 level = -2; 652 elseif level == 10 653 level = -1; 654 end 655 level = min(level+3+dec, length(sections)); 656 str = sections{level}{2}; 657 %> 658 %>* 659 %<* Pretty outputs 660 %< Pretty Cmt 661 % This one is special for LaTeX expressions, for instance 662 % $\alpha=\int_{x\in\Omega} f_\alpha(x)dx$ should be translated to a math 663 % expression for LP.org. 664 function str = PRETTY_CMT(output_style, cmt) 665 str = regexprep(cmt, '\$\$([^\$]+)\$\$', '$1'); 666 str = regexprep(str, '\$([^\$]+)\$', '$1'); 667 str = strrep(str, '\', '\\'); 668 %> 669 %< Pretty Code 670 function str = PRETTY_CODE( output_style, level, name, code, id, dec) 671 switch output_style 672 case 'LP.org' 673 cb = 'codeblock'; 674 ra = '<'; 675 la = '>'; 676 sections = { ['<' cb ' language="matlab">'], [ra ra], [la la '='], ['</' cb '>'] }; 677 otherwise 678 error('P4L:CODE', 'style <%s> unknown', output_style); 679 end 680 if id>1 681 name = sprintf('%s_%d', name, id); 682 end 683 str = sprintf('%s\n%s%s%s%s\n%s\n', sections{1}, sections{2}, name, sections{3}, STR_REP(code), sections{4}); 684 %> 685 %< String Replace 686 function str = STR_REP( str) 687 str = strrep(strrep(str, '%', '%%'), '\', '\\'); 688 %> 689 %>* 690 691 @ text 692
