globals cosmetics, CONST variant
[mala.git] / std / std_io.c
blob2ec87b75a355aa654b072114cac41ddc2735e33a
1 /*
2 std_io.c - MaLa standard IO module parsers
4 Copyright (C) 2005, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
20 #include <stdio.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include "mala.h"
24 #include "std.h"
26 static
27 mala_actioninit std_io[] =
30 MALA_PARSER("--NL", mala_newline_parser, NULL, NULL, NULL),
31 MALA_PARSER_BRIEF("--NL", "prints a newline"),
32 // MALA_PARSER_HELP("--NL", ("TODO")),
33 //MALA_PARSER_RESULT_USAGE("--NL", ("")),
36 //TODO MALA_MACRO_PARSER("--PRINTL",("--PRINT", "--LITERAL", "%1", "--NL")),
37 MALA_PARSER_BRIEF("--PRINTL", "prints a textline to stdout"),
38 // MALA_PARSER_HELP("--PRINTL", ("TODO")),
39 // MALA_PARSER_SIGNATURE_USAGE("--", ("")),
40 // MALA_PARSER_RESULT_USAGE("--", ("")),
41 //MALA_PARSER_SIGNATURE_TYPE("--PRINTL", ("WORD-OR-BLOCK")),
42 //MALA_PARSER_RESULT_TYPE("--PRINTL", ("VOID")),
44 MALA_PARSER("--PRINT", mala_print_parser, NULL, NULL, NULL),
45 MALA_PARSER_BRIEF("--PRINT", "prints to stdout"),
46 // MALA_PARSER_HELP("--PRINT", ("TODO")),
47 // MALA_PARSER_SIGNATURE_USAGE("--", ("")),
48 // MALA_PARSER_RESULT_USAGE("--", ("")),
49 //MALA_PARSER_SIGNATURE_TYPE("--PRINT", ("WORD-OR-BLOCK")),
50 //MALA_PARSER_RESULT_TYPE("--PRINT", ("VOID")),
52 MALA_PARSER("--PRINTWRAPED",mala_printwraped_parser, NULL, NULL, NULL),
53 MALA_PARSER_BRIEF("--PRINTWRAPED", "prints formatted text"),
54 //TODO MALA_PARSER_HELP("--PRINTWRAPED", ("Wraps some text to fit nicely on the screen. Tabulators become aligned. The last tabulator delimited field of a line will be printed word-wraped and indented.")),
55 //TODO MALA_PARSER_SIGNATURE_USAGE("--PRINTWRAPED",
56 // ("Columns available on the screen",
57 // "Lines available on the screen",
58 // "Indent of the block in characters",
59 // "Tabwidth to be used",
60 // "Text to be printed")),
61 // //MALA_PARSER_RESULT_USAGE("--PRINTWRAPED", ("TODO")),
62 //TODO MALA_PARSER_SIGNATURE_TYPE("--PRINTWRAPED",
63 // ("COLUMNS",
64 // "LINES",
65 // "INDENT",
66 // "TABWIDTH",
67 // "TEXT")),
69 MALA_ACTIONS_END
72 struct mala_printwraped_context;
74 static int
75 mala_predicate_greaterthan_int (int * a, int * b);
77 static void
78 mala_estimate_tabwidth (struct mala_printwraped_context* pwc);
80 static void
81 mala_insert_space (struct mala_printwraped_context* pwc, int stop);
83 static void
84 mala_ltab (struct mala_printwraped_context* pwc);
86 static void
87 mala_rtab (struct mala_printwraped_context* pwc);
89 static void
90 mala_wrap_words (struct mala_printwraped_context* pwc);
92 static void
93 mala_print_wraped (struct mala_printwraped_context* pwc);
95 static void
96 mala_put_word (struct mala_printwraped_context* pwc);
99 struct mala_printwraped_context
101 // constant values
102 int columns;
103 int lines;
104 int indent;
105 int tabwidth;
106 const char * text;
108 // states
109 int pos;
110 const char * out_itr;
111 const char * parse_itr;
112 int tabstops[20];
113 int ltab_itr;
114 int wrap_indent;
115 int wrap_indent_locked;
116 const char * lastspace;
120 /* TODO to predicates */
121 static int
122 mala_predicate_greaterthan_int (int * a, int * b)
124 return *a > *b;
127 static void
128 mala_estimate_tabwidth (struct mala_printwraped_context* pwc)
130 int current_tab;
131 int ltab_cnt;
133 again:
134 for (current_tab = 19; current_tab; --current_tab)
135 pwc->tabstops[current_tab] = 0;
137 pwc->tabstops[0] = pwc->indent;
138 current_tab = 0;
139 ltab_cnt = 0;
141 for (pwc->parse_itr = pwc->text, pwc->pos = pwc->indent;
142 *pwc->parse_itr;
143 ++pwc->parse_itr)
145 switch (*pwc->parse_itr)
147 case '\t':
148 if (*(pwc->parse_itr+1) != ' ')
150 // left bound tab
151 if (ltab_cnt < 19)
153 ++ltab_cnt;
155 if (pwc->tabstops[ltab_cnt] < pwc->pos)
157 pwc->tabstops[ltab_cnt] = pwc->indent +
158 (pwc->pos - 1 + pwc->tabwidth) -
159 ((pwc->pos - 1 + pwc->tabwidth) % pwc->tabwidth);
162 pwc->pos = pwc->tabstops[ltab_cnt];
164 if (pwc->pos + pwc->tabwidth >= pwc->columns && pwc->tabwidth > 2)
166 --pwc->tabwidth;
167 printf("tab decreased to %d\n",pwc->tabwidth);
168 goto again;
172 break;
173 case '\n':
174 // end of line
175 ltab_cnt = 0;
176 pwc->pos = pwc->indent;
177 break;
178 default:
179 // normal character
180 ++pwc->pos;
181 break;
186 static void
187 mala_insert_space (struct mala_printwraped_context* pwc, int stop)
189 while (pwc->pos < stop)
191 ++pwc->pos;
192 putchar (' ');
196 static void
197 mala_ltab (struct mala_printwraped_context* pwc)
199 while(*pwc->lastspace == ' ')
200 ++pwc->lastspace;
201 ++pwc->lastspace;
203 if (pwc->ltab_itr < 19)
205 ++pwc->ltab_itr;
206 pwc->wrap_indent = pwc->tabstops[pwc->ltab_itr] -
207 (pwc->parse_itr - pwc->lastspace) - 1;
209 pwc->wrap_indent_locked = 0;
210 ++pwc->parse_itr;
211 ++pwc->out_itr;
214 static void
215 mala_rtab (struct mala_printwraped_context* pwc)
217 const char * tmp_itr;
219 int old_indent = pwc->wrap_indent;
221 ++pwc->parse_itr;
222 while (isblank (*pwc->parse_itr))
223 ++pwc->parse_itr;
225 pwc->lastspace = pwc->parse_itr;
227 tmp_itr = pwc->parse_itr;
228 while (*tmp_itr != '\0' && *tmp_itr != '\n')
229 ++tmp_itr;
231 int length = tmp_itr - pwc->parse_itr;
233 if (pwc->pos + 2 + length < pwc->columns)
235 pwc->wrap_indent = pwc->columns - length;
237 else
239 pwc->wrap_indent = old_indent + pwc->tabwidth;
240 putchar('\n');
241 pwc->pos = 0;
243 pwc->wrap_indent_locked = 0;
246 static void
247 mala_put_word (struct mala_printwraped_context* pwc)
249 const char* stop;
250 int length;
251 int left;
255 stop = pwc->out_itr;
256 length = stop - pwc->lastspace;
257 left = pwc->columns - pwc->pos;
259 if (pwc->pos + length > pwc->columns)
261 while(*pwc->lastspace == ' ')
262 ++pwc->lastspace;
264 if (length > pwc->columns - pwc->wrap_indent)
266 stop = pwc->lastspace + pwc->columns - pwc->wrap_indent - 1;
269 if (isalpha (*(pwc->lastspace - 1)))
271 putchar ('-');
274 putchar ('\n');
275 pwc->pos = 0;
278 if (pwc->pos < pwc->wrap_indent)
279 mala_insert_space (pwc, pwc->wrap_indent);
281 while (pwc->lastspace < stop)
283 if (isalpha (*pwc->lastspace))
284 pwc->wrap_indent_locked = 1;
285 else if (!pwc->wrap_indent_locked)
286 ++pwc->wrap_indent;
288 putchar (*pwc->lastspace);
289 ++pwc->pos;
290 ++pwc->lastspace;
294 while (stop < pwc->out_itr);
297 static void
298 mala_wrap_words (struct mala_printwraped_context* pwc)
300 /* prints all text until the next \t \n or \0 linewraped */
301 for (;pwc->out_itr < pwc->parse_itr; ++pwc->out_itr)
303 if (*pwc->out_itr == ' ')
305 mala_put_word (pwc);
308 mala_put_word (pwc);
311 static void
312 mala_print_wraped (struct mala_printwraped_context* pwc)
315 - a line consists of many tab delimited fields with one optional right aligned field at the
316 end introduced with tab-space "\t "
317 - the last normal tab field gets word wraped and aligned the first alphabetic character of this
318 field. Too long words become (simple) hyphenated.
319 - tabs are aligned every 'tabwidth' characters, when the terminal is too small, tabwidth is
320 gradually decremented until the data fits more nicely until tabwidth = 2.
322 Example:
323 "foo \tbar\n\n\tfoo\t- foo explanation which gets word wraped because this text is long\n\tbaz\t- baz explanation\t [note]"
325 becomes something like:
327 foo bar
329 foo - foo explanation which gets word wraped
330 because this text is long
331 baz - baz explanation [note]
334 for (pwc->lastspace = pwc->out_itr = pwc->parse_itr = pwc->text,
335 pwc->pos = 0;
336 *pwc->parse_itr;
337 ++pwc->parse_itr)
339 switch (*pwc->parse_itr)
341 case '\t':
342 mala_wrap_words (pwc);
343 if (*(pwc->parse_itr+1) != ' ')
344 mala_ltab (pwc);
345 else
346 mala_rtab (pwc);
347 break;
348 case '\n':
349 mala_wrap_words (pwc);
350 putchar('\n');
351 ++pwc->lastspace;
352 pwc->wrap_indent = pwc->indent;
353 pwc->wrap_indent_locked = 0;
354 pwc->ltab_itr = 0;
355 pwc->pos = 0;
356 break;
360 mala_wrap_words (pwc);
361 putchar ('\n');
366 mala_printwraped_parser (MalaEngine eng,
367 MalaStringListNode_ref pptr,
368 void * data)
370 struct mala_printwraped_context pwc;
371 int zero = 0;
373 (void) data;
375 if (mala_engine_arg_eval_fmt (eng, pptr, 1, "%d", &pwc.columns,
376 (MalaPredicate) mala_predicate_greaterthan_int, &zero
377 ) >= MALA_EXCEPTION)
378 return eng->state;
380 if (mala_engine_arg_eval_fmt (eng, pptr, 2, "%d", &pwc.lines,
381 (MalaPredicate) mala_predicate_greaterthan_int, &zero
382 ) >= MALA_EXCEPTION)
383 return eng->state;
385 if (mala_engine_arg_eval_fmt (eng, pptr, 3, "%d", &pwc.indent,
386 (MalaPredicate) mala_predicate_greaterthan_int, &zero
387 ) >= MALA_EXCEPTION)
388 return eng->state;
390 if (mala_engine_arg_eval_fmt (eng, pptr, 4, "%d", &pwc.tabwidth,
391 (MalaPredicate) mala_predicate_greaterthan_int, &zero
392 ) >= MALA_EXCEPTION)
393 return eng->state;
395 pwc.text = mala_string_cstr (mala_engine_arg_eval_string (eng, pptr, 5, NULL, NULL));
396 if (!pwc.text)
397 return eng->state;
399 MALA_SIDEEFFECT_BEGIN
401 pwc.ltab_itr = 0;
402 pwc.wrap_indent_locked = 0;
403 pwc.wrap_indent = pwc.indent;
405 mala_estimate_tabwidth (&pwc);
406 mala_print_wraped (&pwc);
408 MALA_SIDEEFFECT_END;
410 mala_engine_command_done (eng, pptr, 5);
411 return MALA_SUCCESS;
415 mala_newline_parser (MalaEngine eng,
416 MalaStringListNode_ref pptr,
417 void * data)
419 (void) data;
421 MALA_SIDEEFFECT_BEGIN
422 putchar('\n');
423 MALA_SIDEEFFECT_END;
425 mala_engine_command_done (eng, pptr, 0);
426 return MALA_SUCCESS;
430 mala_print_parser (MalaEngine eng,
431 MalaStringListNode_ref pptr,
432 void * data)
434 (void) data;
435 MalaStringListNode next;
437 next = mala_engine_arg_eval (eng, pptr, 1, MALA_LITERAL);
439 if (!next)
440 return eng->state;
442 // TODO print blocks ?
444 MALA_SIDEEFFECT_BEGIN
445 printf("%s",mala_string_cstr (mala_stringlistnode_string (next)));
446 MALA_SIDEEFFECT_END;
448 mala_engine_command_done (eng, pptr, 1);
449 return MALA_SUCCESS;
453 mala_module_std_io_init (MalaEngine self)
455 return mala_engine_actions_register (self, std_io);
460 // Local Variables:
461 // mode: C
462 // c-file-style: "gnu"
463 // End:
464 // arch-tag: 3d2a15ac-145d-42d7-98a5-14dc9b7d2003
465 // end_of_file