2 # newfangle - fully featured notangle replacement in awk
4 # Copyright (C) 2009 Sam Liddicott <sam@liddicott.com>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 # NOTE: Arnold Robbins public domain getopt for awk is also used:
22 # getopt.awk --- do C library getopt(3) function in awk
24 # Arnold Robbins, arnold@skeeve.com, Public Domain
26 # Initial version: March, 1991
30 function getopt
(argc, argv, options
, thisopt
, i
)
32 if (length(options
) ==
0) # no options given
34 if (argv[Optind
] ==
"--") { # all done
38 } else if (argv[Optind
] !~
/^
-[^
: \t\n\f\r\v\b]/) {
44 thisopt =
substr(argv[Optind
], _opti
, 1)
46 i =
index(options
, thisopt
)
49 printf("%c -- invalid option\n",
50 thisopt
) > "/dev/stderr"
51 if (_opti
>=
length(argv[Optind
])) {
58 if (substr(options
, i
+ 1, 1) ==
":") {
60 if (length(substr(argv[Optind
], _opti
+ 1)) > 0)
61 Optarg =
substr(argv[Optind
], _opti
+ 1)
63 Optarg =
argv[++Optind
]
67 if (_opti ==
0 || _opti
>=
length(argv[Optind
])) {
75 function error
(message
)
77 print "ERROR: " FILENAME ":" FNR " " message
> "/dev/stderr";
80 function warning
(message
)
82 print "WARNING: " FILENAME ":" FNR " " message
> "/dev/stderr";
85 function new_mode_tracker
(context
, language
, mode
) {
87 context
[0, "language"] = language
;
88 context
[0, "mode"] = mode
;
90 function push_mode_tracker
(context
, language
, mode
,
94 if (!
("" in context
)) {
96 new_mode_tracker
(context
, language
, mode
);
99 if (context
[top
, "language"] == language
&& mode==
"") mode = context
[top
, "mode"];
101 context
[top
, "language"] = language
;
102 context
[top
, "mode"] = mode
;
106 function dump_mode_tracker
(context
,
109 for(c=
0; c
<= context
[""]; c
++) {
110 printf(" %2d %s:%s\n", c
, context
[c
, "language"], context
[c
, "mode"]) > "/dev/stderr";
111 for(d=
1; ( (c
, "values", d
) in context
); d
++) {
112 printf(" %2d %s\n", d
, context
[c
, "values", d
]) > "/dev/stderr";
116 function finalize_mode_tracker
(context
)
118 if ( ("" in context
) && context
[""] != 0) return 0;
121 function mode_tracker
(context
, text
, values
,
122 # optional parameters
124 mode
, submodes
, language
,
125 cindex
, c
, a
, part
, item
, name
, result
, new_values
, new_mode
,
126 delimiters
, terminators
)
128 cindex = context
[""] + 0;
129 mode = context
[cindex
, "mode"];
130 language = context
[cindex
, "language" ];
131 submodes=modes
[language
, mode
, "submodes"];
133 if ((language
, mode
, "delimiters") in modes
) {
134 delimiters = modes
[language
, mode
, "delimiters"];
135 if (length(submodes
)>0) submodes = submodes
"|";
136 submodes=submodes delimiters
;
137 } else delimiters=
"";
138 if ((language
, mode
, "terminators") in modes
) {
139 terminators = modes
[language
, mode
, "terminators"];
140 if (length(submodes
)>0) submodes = submodes
"|";
141 submodes=submodes terminators
;
142 } else terminators=
"";
143 if (!
length(submodes
)) return text
;
144 while((cindex
>=
0) && length(text
)) {
145 if (match(text
, "(" submodes
")", a
)) {
147 error
(sprintf("Internal error, matched zero length submode, should be impossible - likely regex computation error\n" \
148 "Language=%s\nmode=%s\nmatch=%s\n", language
, mode
, submodes
));
150 part =
substr(text
, 1, RSTART -1);
152 if (match(a
[1], "^" terminators
"$")) {
153 #printf("%2d EXIT MODE [%s] by [%s] [%s]\n", cindex, mode, a[1], text) > "/dev/stderr"
154 context
[cindex
, "values", ++context
[cindex
, "values"]] = item
;
155 delete context
[cindex
];
156 context
[""] =
--cindex
;
158 mode = context
[cindex
, "mode"];
159 language = context
[cindex
, "language"];
160 submodes=modes
[language
, mode
, "submodes"];
162 if ((language
, mode
, "delimiters") in modes
) {
163 delimiters = modes
[language
, mode
, "delimiters"];
164 if (length(submodes
)>0) submodes = submodes
"|";
165 submodes=submodes delimiters
;
166 } else delimiters=
"";
167 if ((language
, mode
, "terminators") in modes
) {
168 terminators = modes
[language
, mode
, "terminators"];
169 if (length(submodes
)>0) submodes = submodes
"|";
170 submodes=submodes terminators
;
171 } else terminators=
"";
172 if (!
length(submodes
)) return text
;
175 text =
substr(text
, 1 + length(part
) + length(a
[1]));
177 else if (match(a
[1], "^" delimiters
"$")) {
179 context
[cindex
, "values", ++context
[cindex
, "values"]] = item
;
184 text =
substr(text
, 1 + length(part
) + length(a
[1]));
186 else if ((language
, a
[1], "terminators") in modes
) {
187 #check if new_mode is defined
189 #printf("%2d ENTER MODE [%s] in [%s]\n", cindex, a[1], text) > "/dev/stderr"
190 text =
substr(text
, 1 + length(part
) + length(a
[1]));
191 context
[""] =
++cindex
;
192 context
[cindex
, "mode"] = a
[1];
193 context
[cindex
, "language"] = language
;
195 submodes=modes
[language
, mode
, "submodes"];
197 if ((language
, mode
, "delimiters") in modes
) {
198 delimiters = modes
[language
, mode
, "delimiters"];
199 if (length(submodes
)>0) submodes = submodes
"|";
200 submodes=submodes delimiters
;
201 } else delimiters=
"";
202 if ((language
, mode
, "terminators") in modes
) {
203 terminators = modes
[language
, mode
, "terminators"];
204 if (length(submodes
)>0) submodes = submodes
"|";
205 submodes=submodes terminators
;
206 } else terminators=
"";
207 if (!
length(submodes
)) return text
;
209 error
(sprintf("Submode '%s' set unknown mode in text: %s\nLanguage %s Mode %s\n", a
[1], text
, language
, mode
));
210 text =
substr(text
, 1 + length(part
) + length(a
[1]));
214 context
[cindex
, "values", ++context
[cindex
, "values"]] = item text
;
220 context
["item"] = item
;
222 if (length(item
)) context
[cindex
, "values", ++context
[cindex
, "values"]] = item
;
225 function transform_escape
(s
, r
, text
,
231 for(c=
1; c
<= max
&& (c in s
); c
++) {
232 gsub(s
[c
], r
[c
], text
);
236 function mode_escaper
(context
, s
, r
, src
,
239 for(c = context
[""]; c
>=
0; c
--) {
240 if ( (context
[c
, "language"], context
[c
, "mode"]) in escapes
) {
241 cpl = escapes
[context
[c
, "language"], context
[c
, "mode"]];
242 for (cp =
1; cp
<= cpl
; cp
++) {
244 s
[src
] = escapes
[context
[c
, "language"], context
[c
, "mode"], cp
, "s"];
245 r
[src
] = escapes
[context
[c
, "language"], context
[c
, "mode"], cp
, "r"];
251 function dump_escaper
(c
, s
, r
, cc
) {
252 for(cc=
1; cc
<=c
; cc
++) {
253 printf("%2d s[%s] r[%s]\n", cc
, s
[cc
], r
[cc
]) > "/dev/stderr"
256 function parse_chunk_args
(language
, text
, values
, mode
,
261 new_mode_tracker
(context
, language
, mode
);
262 rest = mode_tracker
(context
, text
, values
);
264 for(c=
1; c
<= context
[0, "values"]; c
++) {
265 values
[c
] = context
[0, "values", c
];
269 function new_chunk
(chunk_name
, params
,
273 # HACK WHILE WE CHANGE TO ( ) for PARAM CHUNKS
274 gsub("\\(\\)$", "", chunk_name
);
275 if (!
(chunk_name in chunk_names
)) {
276 if (debug
) print "New chunk " chunk_name
;
277 chunk_names
[chunk_name
];
279 chunks
[chunk_name
, p
] = params
[p
];
281 if ("append" in params
) {
282 append=params
["append"];
283 if (!
(append in chunk_names
)) {
284 warning
("Chunk " chunk_name
" is appended to chunk " append
" which is not defined yet");
287 chunk_include
(append
, chunk_name
);
288 chunk_line
(append
, ORS);
291 active_chunk = chunk_name
;
292 prime_chunk
(chunk_name
);
295 function prime_chunk
(chunk_name
)
297 chunks
[chunk_name
, "part", ++chunks
[chunk_name
, "part"] ] = \
298 chunk_name SUBSEP
"chunklet" SUBSEP
"" ++chunks
[chunk_name
, "chunklet"];
299 chunks
[chunk_name
, "part", chunks
[chunk_name
, "part"], "FILENAME"] =
FILENAME;
300 chunks
[chunk_name
, "part", chunks
[chunk_name
, "part"], "LINENO"] =
FNR + 1;
303 function chunk_line
(chunk_name
, line
){
304 chunks
[chunk_name
, "chunklet", chunks
[chunk_name
, "chunklet"],
305 ++chunks
[chunk_name
, "chunklet", chunks
[chunk_name
, "chunklet"], "line"] ] = line
;
308 function chunk_include
(chunk_name
, chunk_ref
, indent
, tail
)
310 chunks
[chunk_name
, "part", ++chunks
[chunk_name
, "part"] ] = chunk_ref
;
311 chunks
[chunk_name
, "part", chunks
[chunk_name
, "part"], "type" ] = part_type_chunk
;
312 chunks
[chunk_name
, "part", chunks
[chunk_name
, "part"], "indent" ] = indent_string
(indent
);
313 chunks
[chunk_name
, "part", chunks
[chunk_name
, "part"], "tail" ] = tail
;
314 prime_chunk
(chunk_name
);
317 function indent_string
(indent
) {
318 return sprintf("%" indent "s
", "");
320 function output_chunk_names( c, prefix, suffix)
326 for (c in chunk_names) {
327 print prefix c suffix "\n";
330 function output_chunks( a)
332 for (a in chunk_names) {
333 output_chunk(chunk_names[a]);
337 function output_chunk(chunk) {
339 lineno_needed = linenos;
344 function write_chunk(chunk_name) {
346 return write_chunk_r(chunk_name, context);
348 function write_chunk_r(chunk_name, context, indent, tail,
350 chunk_path, chunk_args,
353 chunk_params, part, max_part, part_line, frag, max_frag, text,
354 chunklet, only_part, call_chunk_args, new_context)
356 if (match(chunk_name, "^
(.
*)\\[([0-9]*)\\]$
", chunk_name_parts)) {
357 chunk_name = chunk_name_parts[1];
358 only_part = chunk_name_parts[2];
361 new_mode_tracker(context, chunks[chunk_name, "language
"], "");
362 split(chunks[chunk_name, "params
"], chunk_params, " *; *");
363 if (! (chunk_name in chunk_names)) {
364 error(sprintf(_"The root module
<<%s
>> was not defined.
\nUsed by
: %s
",\
365 chunk_name, chunk_path));
368 max_part = chunks[chunk_name, "part
"];
369 for(part = 1; part <= max_part; part++) {
370 if (! only_part || part == only_part) {
371 if (linenos && (chunk_name SUBSEP "part
" SUBSEP part SUBSEP "FILENAME" in chunks)) {
372 a_filename = chunks[chunk_name, "part
", part, "FILENAME"];
373 a_lineno = chunks[chunk_name, "part
", part, "LINENO
"];
374 if (a_filename != filename || a_lineno != lineno) {
379 chunklet = chunks[chunk_name, "part
", part];
380 if (chunks[chunk_name, "part
", part, "type
"] == part_type_chunk) {
381 if (match(chunklet, "^
([^
\\[\\(]*)\\((.
*)\\)$
", chunklet_parts)) {
382 chunklet = chunklet_parts[1];
383 parse_chunk_args("c
-like
", chunklet_parts[2], call_chunk_args, "(");
384 for (c in call_chunk_args) {
385 call_chunk_args[c] = expand_chunk_args(call_chunk_args[c], chunk_params, chunk_args);
388 split("", call_chunk_args);
390 # update the transforms arrays
391 new_src = mode_escaper(context, s, r, src);
392 split("", new_context);
393 write_chunk_r(chunklet, new_context,
394 chunks[chunk_name, "part
", part, "indent
"] indent,
395 chunks[chunk_name, "part
", part, "tail
"],
396 chunk_path "\n " chunk_name,
399 } else if (chunklet SUBSEP "line
" in chunks) {
400 max_frag = chunks[chunklet, "line
"];
401 for(frag = 1; frag <= max_frag; frag++) {
402 if (newline && lineno_needed && ! lineno_suppressed) {
403 filename = a_filename;
405 print "#line " lineno " \"" filename "\"\n"
409 text = chunks
[chunklet
, frag
];
412 text = expand_chunk_args
(text
, chunk_params
, chunk_args
);
416 if (part == max_part
&& frag == max_frag
&& length(chunk_path
)) {
422 } else if (length(text
) || length(tail
)) {
423 if (newline
) text = indent text
;
428 mode_tracker
(context
, text
);
429 print transform_escape
(s
, r
, text
, src
);
431 lineno_suppressed =
substr(lastline
, length(lastline
)) ==
"\\";
435 # empty last chunklet
439 if (! finalize_mode_tracker
(context
)) {
440 dump_mode_tracker
(context
);
441 error
(sprintf(_
"Module %s did not close context properly.\nUsed by: %s\n", chunk_name
, chunk_path
));
444 function expand_chunk_args
(text
, params
, args
,
445 p
, text_array
, next_text
, v
, t
, l
)
447 if (split(text
, text_array
, "\\${")) {
449 v
[params
[p
]]=args
[p
];
452 for(t=
2; t in text_array
; t
++) {
453 if (match(text_array
[t
], "^([a-zA-Z_][a-zA-Z0-9_]*)}", l
) &&
456 text = text v
[l
[1]] substr(text_array
[t
], length(l
[1])+2);
458 text = text
"${" text_array
[t
];
468 modes
["c-like", "", "submodes" ]=
"\\\\|\"|'|{|\\(|\\[";
469 modes
["c-like", "", "delimiters"]=
" *, *";
470 modes
["c-like", "\\", "terminators"]=
".";
471 modes
["c-like", "\"", "submodes" ]=
"\\\\";
472 modes
["c-like", "\"", "terminators"]=
"\"";
473 escapes
["c-like", "\"", ++escapes
["c-like", "\""], "s"]=
"\\\\";
474 escapes
["c-like", "\"", escapes
["c-like", "\""], "r"]=
"\\\\";
475 escapes
["c-like", "\"", ++escapes
["c-like", "\""], "s"]=
"\"";
476 escapes
["c-like", "\"", escapes
["c-like", "\""], "r"]=
"\\" "\"";
477 escapes
["c-like", "\"", ++escapes
["c-like", "\""], "s"]=
"\n";
478 escapes
["c-like", "\"", escapes
["c-like", "\""], "r"]=
"\\n";
479 modes
["c-like", "'", "submodes" ]=
"\\\\";
480 modes
["c-like", "'", "terminators"]=
"'";
481 escapes
["c-like", "'", ++escapes
["c-like", "'"], "s"]=
"\\\\";
482 escapes
["c-like", "'", escapes
["c-like", "'"], "r"]=
"\\\\";
483 escapes
["c-like", "'", ++escapes
["c-like", "'"], "s"]=
"'";
484 escapes
["c-like", "'", escapes
["c-like", "'"], "r"]=
"\\" "'";
485 escapes
["c-like", "'", ++escapes
["c-like", "'"], "s"]=
"\n";
486 escapes
["c-like", "'", escapes
["c-like", "'"], "r"]=
"\\n";
487 modes
["c-like", "{", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
488 modes
["c-like", "{", "delimiters"]=
" *, *";
489 modes
["c-like", "{", "terminators"]=
"}";
490 modes
["c-like", "[", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
491 modes
["c-like", "[", "delimiters"]=
" *, *";
492 modes
["c-like", "[", "terminators"]=
"\\]";
493 modes
["c-like", "(", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
494 modes
["c-like", "(", "delimiters"]=
" *, *";
495 modes
["c-like", "(", "terminators"]=
"\\)";
497 modes
["c", "", "submodes" ]=
"\\\\|\"|'|{|\\(|\\[";
498 modes
["c", "", "delimiters"]=
" *, *";
499 modes
["c", "\\", "terminators"]=
".";
500 modes
["c", "\"", "submodes" ]=
"\\\\";
501 modes
["c", "\"", "terminators"]=
"\"";
502 escapes
["c", "\"", ++escapes
["c", "\""], "s"]=
"\\\\";
503 escapes
["c", "\"", escapes
["c", "\""], "r"]=
"\\\\";
504 escapes
["c", "\"", ++escapes
["c", "\""], "s"]=
"\"";
505 escapes
["c", "\"", escapes
["c", "\""], "r"]=
"\\" "\"";
506 escapes
["c", "\"", ++escapes
["c", "\""], "s"]=
"\n";
507 escapes
["c", "\"", escapes
["c", "\""], "r"]=
"\\n";
508 modes
["c", "'", "submodes" ]=
"\\\\";
509 modes
["c", "'", "terminators"]=
"'";
510 escapes
["c", "'", ++escapes
["c", "'"], "s"]=
"\\\\";
511 escapes
["c", "'", escapes
["c", "'"], "r"]=
"\\\\";
512 escapes
["c", "'", ++escapes
["c", "'"], "s"]=
"'";
513 escapes
["c", "'", escapes
["c", "'"], "r"]=
"\\" "'";
514 escapes
["c", "'", ++escapes
["c", "'"], "s"]=
"\n";
515 escapes
["c", "'", escapes
["c", "'"], "r"]=
"\\n";
516 modes
["c", "{", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
517 modes
["c", "{", "delimiters"]=
" *, *";
518 modes
["c", "{", "terminators"]=
"}";
519 modes
["c", "[", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
520 modes
["c", "[", "delimiters"]=
" *, *";
521 modes
["c", "[", "terminators"]=
"\\]";
522 modes
["c", "(", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
523 modes
["c", "(", "delimiters"]=
" *, *";
524 modes
["c", "(", "terminators"]=
"\\)";
525 modes
["c", "", "submodes"] = modes
["c", "", "submodes"] "|" "/\\*";
526 modes
["c", "/*", "terminators"]=
"\\*/";
527 modes
["c", "", "submodes"] = modes
["c", "", "submodes"] "|" "//";
528 modes
["c", "//", "terminators"]=
"\n";
529 escapes
["c", "//", ++escapes
["c", "//"], "s"]=
"\n";
530 escapes
["c", "//", escapes
["c", "//"], "r"]=
"\n//";
531 modes
["c", "", "submodes"] = modes
["c", "", "submodes"] "|" "#";
532 modes
["c", "#", "submodes" ]=
"\\\\";
533 modes
["c", "#", "terminators"]=
"\n";
534 escapes
["c", "#", ++escapes
["c", "#"], "s"]=
"\n";
535 escapes
["c", "#", escapes
["c", "#"], "r"]=
"\\\\\n";
537 modes
["awk", "", "submodes" ]=
"\\\\|\"|'|{|\\(|\\[";
538 modes
["awk", "", "delimiters"]=
" *, *";
539 modes
["awk", "\\", "terminators"]=
".";
540 modes
["awk", "\"", "submodes" ]=
"\\\\";
541 modes
["awk", "\"", "terminators"]=
"\"";
542 escapes
["awk", "\"", ++escapes
["awk", "\""], "s"]=
"\\\\";
543 escapes
["awk", "\"", escapes
["awk", "\""], "r"]=
"\\\\";
544 escapes
["awk", "\"", ++escapes
["awk", "\""], "s"]=
"\"";
545 escapes
["awk", "\"", escapes
["awk", "\""], "r"]=
"\\" "\"";
546 escapes
["awk", "\"", ++escapes
["awk", "\""], "s"]=
"\n";
547 escapes
["awk", "\"", escapes
["awk", "\""], "r"]=
"\\n";
548 modes
["awk", "'", "submodes" ]=
"\\\\";
549 modes
["awk", "'", "terminators"]=
"'";
550 escapes
["awk", "'", ++escapes
["awk", "'"], "s"]=
"\\\\";
551 escapes
["awk", "'", escapes
["awk", "'"], "r"]=
"\\\\";
552 escapes
["awk", "'", ++escapes
["awk", "'"], "s"]=
"'";
553 escapes
["awk", "'", escapes
["awk", "'"], "r"]=
"\\" "'";
554 escapes
["awk", "'", ++escapes
["awk", "'"], "s"]=
"\n";
555 escapes
["awk", "'", escapes
["awk", "'"], "r"]=
"\\n";
556 modes
["awk", "{", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
557 modes
["awk", "{", "delimiters"]=
" *, *";
558 modes
["awk", "{", "terminators"]=
"}";
559 modes
["awk", "[", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
560 modes
["awk", "[", "delimiters"]=
" *, *";
561 modes
["awk", "[", "terminators"]=
"\\]";
562 modes
["awk", "(", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
563 modes
["awk", "(", "delimiters"]=
" *, *";
564 modes
["awk", "(", "terminators"]=
"\\)";
565 modes
["awk", "", "submodes"] = modes
["awk", "", "submodes"] "|" "#";
566 modes
["awk", "#", "terminators"]=
"\n";
567 escapes
["awk", "#", ++escapes
["awk", "#"], "s"]=
"\n";
568 escapes
["awk", "#", escapes
["awk", "#"], "r"]=
"\n#";
569 modes
["awk", "", "submodes"] = modes
["awk", "", "submodes"] "|" "/\\^";
570 modes
["awk", "/^", "terminators"]=
"/";
571 modes
["perl", "", "submodes" ]=
"\\\\|\"|'|{|\\(|\\[";
572 modes
["perl", "", "delimiters"]=
" *, *";
573 modes
["perl", "\\", "terminators"]=
".";
574 modes
["perl", "\"", "submodes" ]=
"\\\\";
575 modes
["perl", "\"", "terminators"]=
"\"";
576 escapes
["perl", "\"", ++escapes
["perl", "\""], "s"]=
"\\\\";
577 escapes
["perl", "\"", escapes
["perl", "\""], "r"]=
"\\\\";
578 escapes
["perl", "\"", ++escapes
["perl", "\""], "s"]=
"\"";
579 escapes
["perl", "\"", escapes
["perl", "\""], "r"]=
"\\" "\"";
580 escapes
["perl", "\"", ++escapes
["perl", "\""], "s"]=
"\n";
581 escapes
["perl", "\"", escapes
["perl", "\""], "r"]=
"\\n";
582 modes
["perl", "'", "submodes" ]=
"\\\\";
583 modes
["perl", "'", "terminators"]=
"'";
584 escapes
["perl", "'", ++escapes
["perl", "'"], "s"]=
"\\\\";
585 escapes
["perl", "'", escapes
["perl", "'"], "r"]=
"\\\\";
586 escapes
["perl", "'", ++escapes
["perl", "'"], "s"]=
"'";
587 escapes
["perl", "'", escapes
["perl", "'"], "r"]=
"\\" "'";
588 escapes
["perl", "'", ++escapes
["perl", "'"], "s"]=
"\n";
589 escapes
["perl", "'", escapes
["perl", "'"], "r"]=
"\\n";
590 modes
["perl", "{", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
591 modes
["perl", "{", "delimiters"]=
" *, *";
592 modes
["perl", "{", "terminators"]=
"}";
593 modes
["perl", "[", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
594 modes
["perl", "[", "delimiters"]=
" *, *";
595 modes
["perl", "[", "terminators"]=
"\\]";
596 modes
["perl", "(", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
597 modes
["perl", "(", "delimiters"]=
" *, *";
598 modes
["perl", "(", "terminators"]=
"\\)";
599 modes
["perl", "", "submodes"] = modes
["perl", "", "submodes"] "|" "/\\*";
600 modes
["perl", "/*", "terminators"]=
"\\*/";
601 modes
["perl", "", "submodes"] = modes
["perl", "", "submodes"] "|" "#";
602 modes
["perl", "#", "terminators"]=
"\n";
603 escapes
["perl", "#", ++escapes
["perl", "#"], "s"]=
"\n";
604 escapes
["perl", "#", escapes
["perl", "#"], "r"]=
"\n#";
605 modes
["sh", "", "submodes" ]=
"\\\\|\"|'|{|\\(|\\[";
606 modes
["sh", "", "delimiters"]=
" *, *";
607 modes
["sh", "\\", "terminators"]=
".";
608 modes
["sh", "\"", "submodes" ]=
"\\\\";
609 modes
["sh", "\"", "terminators"]=
"\"";
610 escapes
["sh", "\"", ++escapes
["sh", "\""], "s"]=
"\\\\";
611 escapes
["sh", "\"", escapes
["sh", "\""], "r"]=
"\\\\";
612 escapes
["sh", "\"", ++escapes
["sh", "\""], "s"]=
"\"";
613 escapes
["sh", "\"", escapes
["sh", "\""], "r"]=
"\\" "\"";
614 escapes
["sh", "\"", ++escapes
["sh", "\""], "s"]=
"\n";
615 escapes
["sh", "\"", escapes
["sh", "\""], "r"]=
"\\n";
616 modes
["sh", "'", "submodes" ]=
"\\\\";
617 modes
["sh", "'", "terminators"]=
"'";
618 escapes
["sh", "'", ++escapes
["sh", "'"], "s"]=
"\\\\";
619 escapes
["sh", "'", escapes
["sh", "'"], "r"]=
"\\\\";
620 escapes
["sh", "'", ++escapes
["sh", "'"], "s"]=
"'";
621 escapes
["sh", "'", escapes
["sh", "'"], "r"]=
"\\" "'";
622 escapes
["sh", "'", ++escapes
["sh", "'"], "s"]=
"\n";
623 escapes
["sh", "'", escapes
["sh", "'"], "r"]=
"\\n";
624 modes
["sh", "{", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
625 modes
["sh", "{", "delimiters"]=
" *, *";
626 modes
["sh", "{", "terminators"]=
"}";
627 modes
["sh", "[", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
628 modes
["sh", "[", "delimiters"]=
" *, *";
629 modes
["sh", "[", "terminators"]=
"\\]";
630 modes
["sh", "(", "submodes" ]=
"\\\\|\"|{|\\(|\\[|'|/\\*";
631 modes
["sh", "(", "delimiters"]=
" *, *";
632 modes
["sh", "(", "terminators"]=
"\\)";
633 #<\chunkref{mode:common-string}("sh", "\textbackslash{}"")>
634 #<\chunkref{mode:common-string}("sh", "'")>
635 modes
["sh", "", "submodes"] = modes
["sh", "", "submodes"] "|" "#";
636 modes
["sh", "#", "terminators"]=
"\n";
637 escapes
["sh", "#", ++escapes
["sh", "#"], "s"]=
"\n";
638 escapes
["sh", "#", escapes
["sh", "#"], "r"]=
"\n#";
639 escapes
["sh", "\"", ++escapes
["sh", "\""], "s"]=
"\\$";
640 escapes
["sh", "\"", escapes
["sh", "\""], "r"]=
"\\$";
647 Optind =
1 # skip ARGV[0]
648 while(getopt
(ARGC, ARGV, "R:LdT:hr")!=-1) {
649 if (Optopt ==
"R") root = Optarg
;
650 else if (Optopt ==
"r") root=
"";
651 else if (Optopt ==
"L") linenos =
1;
652 else if (Optopt ==
"d") debug =
1;
653 else if (Optopt ==
"T") tabs = indent_string
(Optarg
+0);
654 else if (Optopt ==
"h") help
();
655 else if (Optopt ==
"?") help
();
657 for (i=
1; i
<Optind
; i
++) { ARGV[i
]=
""; }
660 if (match($
0, "^\\\\Chunk{ *([^ ,}]*),?(.*)}", line
)) {
661 next_chunk_name = line
[1];
662 get_chunk_args
(line
[2], next_chunk_args
);
666 /^
\\begin{lstlisting
}|^
\\begin{Chunk
}/ {
667 if (match($
0, "}.*[[,] *name= *{? *([^], }]*)", line
)) {
670 new_chunk
(next_chunk_name
, next_chunk_args
);
676 if (match($
0, "^[<]<(.*)[>]>= *$", line
)) {
683 /^
\\[e
]nd
{lstlisting
}|^
\\[e
]nd
{Chunk
}/ {
693 length(active_chunk
) {
700 "([=]<\\\\chunkref{([^}>]*)}(\\(.*\\)|)>|<<([a-zA-Z_][-a-zA-Z0-9_]*)>>)",
703 chunklet =
substr(chunk
, 1, RSTART - 1);
704 indent
+=
length(chunklet
);
705 chunk_line
(active_chunk
, chunklet
);
706 chunk =
substr(chunk
, RSTART + RLENGTH);
707 if (substr(line
[1], 1, 1) ==
"=") {
710 gsub("\\\\#", "#", line
[3]);
711 gsub("\\\\textbackslash{}", "\\", line
[3]);
712 gsub("\\\\\\^", "^", line
[3]);
713 chunk_include
(active_chunk
, line
[2] line
[3], indent
);
714 } else if (substr(line
[1], 1, 1) ==
"<") {
715 chunk_include
(active_chunk
, line
[4], indent
);
717 error
("Unknown chunk fragment: " line
[1]);
720 chunk_line
(active_chunk
, chunk
);
721 chunk_line
(active_chunk
, "\n");
725 print "------ chunk names "
726 output_chunk_names
();
727 print "====== chunks"
731 print a
"=" chunks
[a
];
735 if (length(root
)) output_chunk
(root
);
736 else output_chunk_names
();
738 function get_chunk_args
(text
, values
,
739 # optional parameters
740 path
, # hierarchical precursors
744 split("", next_chunk_args
);
745 while(length(text
)) {
746 if (match(text
, "^ *}(.*)", a
)) {
749 if (!
match(text
, " *([^,=]*[^,= ]) *(([,=]) *(([^,}]*) *,* *(.*))|)$", a
)) {
754 if (substr(a
[4],1,1) ==
"{") {
755 text = get_chunk_args
(substr(a
[4],2), values
, path name SUBSEP
);
757 values
[path name
]=a
[5];
761 values
[path name
]=
"";