current version
[opsoft_test.git] / silentbob / sblib / Sblib.cxx
blob024f2f16298cd56d0815cff5a65a9380a15312d9
1 /*
2 * (c) Oleg Puchinin 2006,2007
3 * graycardinalster@gmail.com
5 */
7 #include <gclib/gclib.h>
8 #include <env.h>
9 #include <bob_flags.h>
10 #include <head.h>
11 #include <wit.h>
12 #include <dbg.h>
13 #include <string.h>
14 #include <sys/wait.h>
15 #include <errno.h>
16 #include <the_tt.h>
18 struct env_t *ENV;
20 char * __bice_get (char *optname)
22 char * value;
23 value = ENV->settings->get (optname);
24 if (! value)
25 value = getenv (optname);
26 return value;
29 EHash * bob_init_compile_env ()
31 EHash * compile_env;
32 char *cc;
33 char *cxx;
34 char *cflags;
35 char *cxxflags;
36 char *opts;
37 char *include;
38 char *libs;
39 char *ldflags;
41 compile_env = new EHash;
43 cc = __bice_get ("CC");
44 cxx = __bice_get ("CXX");
45 cflags = __bice_get ("CFLAGS");
46 cxxflags = __bice_get ("CXXFLAGS");
47 opts = __bice_get ("OPTS");
48 include = __bice_get ("INCLUDE");
49 libs = __bice_get ("LIBS");
50 ldflags = __bice_get ("LDFLAGS");
52 if (! cc)
53 cc = "gcc";
54 if (! cxx)
55 cxx = "g++";
56 if (! cflags)
57 cflags = "-O3 -Wall -pipe";
58 if (! cxxflags)
59 cxxflags = cflags;
60 if (! opts)
61 opts = "";
62 if (! include)
63 include = "";
64 if (! libs)
65 libs = "";
66 if (! ldflags)
67 ldflags = "";
69 if (SB_FLGET (SB_FLVERBOSE)) {
70 printf ("C compiler: %s\n", cc);
71 printf ("C++ compiler: %s\n", cxx);
72 printf ("C flags: %s\n", cflags);
73 printf ("C++ flags: %s\n", cxxflags);
74 printf ("OPTS: %s\n", opts);
75 printf ("INCLUDE: %s\n", include);
76 printf ("LIBS: %s\n", libs);
77 printf ("LDFLAGS: %s\n", ldflags);
80 compile_env->set ("CC", strdup (cc));
81 compile_env->set ("CXX", strdup (cxx));
82 compile_env->set ("CFLAGS", strdup (cflags));
83 compile_env->set ("CXXFLAGS", strdup (cxxflags));
84 compile_env->set ("OPTS", strdup (opts));
85 compile_env->set ("INCLUDE", strdup (include));
86 compile_env->set ("LIBS", strdup (libs));
87 compile_env->set ("LDFLAGS", strdup (ldflags));
89 return compile_env;
92 int sb_prname (char *arg)
94 int i_cmd = 0;
95 char * d_ptr;
96 d_ptr = arg + strlen (arg);
97 d_ptr--;
99 while (*d_ptr != '\\' &&
100 d_ptr > arg)
101 d_ptr--;
103 if (*d_ptr == '\\')
104 d_ptr++;
106 if (EQ (d_ptr, "tags"))
107 i_cmd = cmd_tags;
108 else if (EQ (d_ptr, "the_tt"))
109 i_cmd = cmd_the_tt;
110 else if (EQ (d_ptr, "gc_indent"))
111 i_cmd = cmd_indent;
112 else if (EQ (d_ptr, "structs"))
113 i_cmd = cmd_give_structs;
115 return i_cmd;
118 // SilentBob --tags
119 void tags (DArray * d_names, char * d_file_output)
121 struct fdump_param_t d_param;
122 EArray * d_tags;
123 struct d_tag_t * d_tag;
124 int a, i, n_names;
126 if (! d_names)
127 return;
129 n_names = d_names->get_size ();
131 for (i = 0; i < n_names; i++) {
132 d_tags = got_tag (d_names->get (i));
133 if (d_tags == NULL) {
134 if (d_tags->get_size () == 0) {
135 fprintf (ENV->d_stream_dbg, "Tag not found : %s\n",
136 d_names->get (i));
137 fflush (ENV->d_stream_dbg);
138 delete d_tags;
139 continue;
143 if (! d_tags)
144 continue;
146 if(! d_tags->get_size ()) {
147 delete d_tags;
148 d_tags = NULL;
149 continue;
152 fault (! d_tags);
154 for (a = 0; a < d_tags->get_size (); a++) {
155 d_tag = (d_tag_t *) d_tags->get (a);
157 fault (! d_tag);
159 if (! d_file_output)
160 printf ("// file %s line %i\n",
161 d_tag->d_file, d_tag->d_line);
163 memset (&d_param, 0, sizeof (struct fdump_param_t));
164 d_param.n_trip = 0;
165 d_param.d_file_name = d_tag->d_file;
166 d_param.d_line = d_tag->d_line;
167 d_param.linear = true;
168 d_param.d_file_output = d_file_output;
169 if (d_tag->d_type == OT::Function)
170 d_param.b_force_block = true;
172 nogui_fdump (&d_param);
173 if (! d_file_output)
174 fputc ('\n', stdout);
176 DROP (d_tag);
179 if (d_tags) {
180 d_tags->drop ();
181 delete d_tags;
185 fflush (stdout);
188 void bug_longmacro ()
190 printf ("Too big macro."
191 "If your macro have more than 300 lines, please "
192 "contact <graycardinal@pisem.net>\n"
193 "Program stopped.\n");
195 exit (0);
198 void bug_nosuch_tag (char * f_name)
200 printf ("Tag \"%s\" not found. Broken \"tags\" file ? "
201 "Try \"silent-bob --make-ctags\".\n", f_name);
204 void bug_nocalltags ()
206 printf ("File \"call_tags\" not found. "
207 "Try \"silent-bob --call-tags [-L] <files>\"\n");
208 exit (1);
211 void bug_system ()
213 printf ("Can't make tags file. Maybe you do not have write permissions ?\n");
214 exit (1);
217 void bug_fork ()
219 perror ("fork");
220 exit (1);
223 void bug_plugin (char *name)
225 fprintf (stderr, "Can't load plugin (%s)\n", name);
228 void bug_notsupported ()
230 printf ("SilentBob (or language plugin)"
231 " don't support this feature !\n");
234 bool bob_tag (char *d_str, char * d_name, d_tag_t * d_tag)
236 char m_buf[256];
237 char *d_file;
238 char *S;
240 strcpy (m_buf, d_str);
241 d_str = m_buf;
243 strncpy (d_tag->d_name, d_name, 255);
244 d_tag->d_name[255] = 0;
245 S = strchr (d_str, '\t');
246 if (! S)
247 return false;
249 S++;
250 d_file = S;
251 S = strchr (d_file, '\t');
252 if (! S)
253 return false;
255 *S = 0;
256 strncpy (d_tag->d_file, d_file, 255);
257 d_tag->d_file[255] = 0;
259 S++;
261 if (if_digit (S))
262 d_tag->d_line = atoi (S);
263 else
264 return false;
266 return true;
269 char * cts (struct c_word * d_word)
271 char * S;
273 if (d_word == NULL)
274 return NULL;
276 S = d_word->S;
277 if (!strncmp (S, "else ", 5))
278 S += 5;
280 if (d_word->ch != '(')
281 return NULL;
283 while (!strncmp (S, "do ", 3))
284 S += 3;
286 if (!strncmp (S, "return ", 7))
287 S += 7;
289 if (ENV->d_cops->sfind (S) != -1)
290 return NULL;
292 if (words_count (S) != 1)
293 return NULL;
295 return S;
298 bool def_test (char * d_op)
300 char * S = d_op;
301 ++S;
302 while (*S == ' ' || *S == '\t')
303 ++S;
305 if (! strncmp (S, "define", 6))
306 return true;
307 return false;
310 int find_cfiles ()
312 find_one_ext ("*.h");
313 find_one_ext ("*.hpp");
314 find_one_ext ("*.cpp");
315 find_one_ext ("*.c");
316 find_one_ext ("*.cc");
317 find_one_ext ("*.cxx");
318 return 0;
321 int sblib_find (char * path, char * name, char * f_outname)
323 int devnull;
324 int fd;
325 int pid;
326 int status = -1;
328 pid = fork ();
329 if (pid == 0) {
330 devnull = open ("/dev/null", O_WRONLY, 0600);
331 fd = open (f_outname, O_WRONLY, 0600);
332 if (fd == -1) {
333 fd = open (f_outname, O_WRONLY | O_CREAT, 0600);
334 if (fd == -1) {
335 close (devnull);
336 return -1;
338 } else
339 lseek (fd, 0, SEEK_END);
340 dup2 (devnull, 2);
341 dup2 (fd, 1);
342 execlp ("find", path, "-name", name, NULL);
343 } else if (pid > 0) {
344 waitpid (pid, &status, 0);
345 return status;
348 return status;
351 # define TMP_FILE_NAME "./silent_bob.tmp"
352 struct tt_state_t * get_onett_tag (char * f_name, char ** d_tt_buf)
354 DArray d_array;
355 tt_state_t * Ret = NULL;
356 char * S;
358 if (d_tt_buf)
359 *d_tt_buf = NULL;
361 d_array.add (f_name);
362 Ret = CNEW (tt_state_t, 1);
364 unlink (TMP_FILE_NAME);
365 tags (&d_array, TMP_FILE_NAME);
367 while( 1 ) {
368 if (access (TMP_FILE_NAME, R_OK) != 0)
369 break;
371 Ret->fileName = strdup (TMP_FILE_NAME);
372 S = THE_TT::do_tt_file (Ret);
374 if (S == NULL)
375 break;
377 if (Ret->mmaped)
378 munmap (Ret->fileData, Ret->fileDataSize);
380 if (Ret->fd)
381 close (Ret->fd);
383 if (d_tt_buf)
384 *d_tt_buf = S;
386 unlink (TMP_FILE_NAME);
387 return Ret;
390 DROP (Ret);
391 unlink (TMP_FILE_NAME);
392 return NULL;
395 void globalsPrint (tt_state_t * tt, char * d_out, int d_found_type)
397 int t_line;
399 if (SB_FLGET (SB_FLSIMULATE))
400 return;
402 if (d_found_type & OT::Other)
403 return;
405 t_line = tt->attachment[ENV->t_op_no].pair_line+1;
406 t_line += ww_begin_line (tt, d_out,
407 tt->attachment[ENV->t_op_no].offset);
409 if (SB_FLGET(SB_FLTAGSTYLE))
410 mk_tag (d_out, tt->fileName,
411 t_line, d_found_type);
412 else
413 printf ("%s\t\t//file %s //line %i\n", d_out,
414 tt->fileName, t_line);
417 #define NOT_VALID 0
418 #define CALL_BACK 1
419 #define VALID 2
421 EArray * got_tag (char * d_tag)
423 struct d_tag_t *d_new_tag;
424 char d_buf[256];
425 EArray * d_ret;
426 int d_len;
427 char *S;
428 int i;
430 d_ret = new EArray;
432 if (ENV->d_tags_file == NULL) {
433 ENV->d_tags_file = new EArray;
434 ENV->d_tags_file->from_file ("./tags");
437 snprintf (d_buf, 255, "%s\t", d_tag);
438 d_len = strlen (d_buf);
440 if (ENV->d_tags_file->get_size () == 0)
441 return d_ret;
443 i = ENV->d_tags_file->snfind_fast (d_buf, strlen (d_buf));
445 if (i == -1) {
446 fprintf (ENV->d_stream_dbg, "\tENV->d_tags_file->snfind_fast == -1"); LN;
447 return d_ret;
450 d_len = strlen (d_buf);
451 do {
452 i++;
453 S = ENV->d_tags_file->get (i);
454 if (! S)
455 break;
456 } while (! strncmp (S, d_buf, d_len));
457 --i;
459 while (true) {
460 S = ENV->d_tags_file->get (i);
461 fprintf (ENV->d_stream_dbg, "\ttag : %s\n", S); fflush (ENV->d_stream_dbg);
463 d_new_tag = CNEW (d_tag_t, 1);
464 memset (d_new_tag, 0, sizeof (d_tag_t));
465 if (strstr (S, ";\tf"))
466 d_new_tag->d_type = OT::Function;
468 if (bob_tag (S, d_tag, d_new_tag) == false) {
469 DROP (d_new_tag);
470 fprintf (ENV->d_stream_dbg, "\tBAD tag : %s\n", S);
471 return d_ret;
474 d_ret->add ((long) d_new_tag);
476 i--;
477 if (i < 0)
478 break;
480 S = ENV->d_tags_file->get (i);
481 if (strncmp (S, d_tag, strlen (d_tag)))
482 break;
485 return d_ret;
488 char * macro_name (char * d_op, char * d_macro_name)
490 char *d_begin;
491 char *S;
492 char m_buf[256];
494 strncpy (m_buf, d_op, 255);
495 m_buf[255] = 0;
497 S = strstr (m_buf, "define");
499 if (! S)
500 return NULL;
502 S = strchr (S, ' ');
503 if (! S)
504 return NULL;
506 while (*S == ' ')
507 S++;
509 d_begin = S;
510 S = strchr (d_begin, ' ');
511 if (S)
512 *S = 0;
514 S = strchr (d_begin, '(');
515 if (S)
516 *S = 0;
518 strcpy (d_macro_name, d_begin);
519 return d_macro_name;
522 void mk_tag_macro (char * d_op, char * d_file, int t_line)
524 char S[256];
526 if (! macro_name (d_op, S))
527 return;
529 printf ("%s\t%s\t%i\n", S, d_file, t_line);
532 void mk_tag (char * d_op, char * d_file, int line, int d_found_type)
534 char * d_format = "%s\t%s\t%i\n";
535 char * S;
537 if (d_found_type & OT::Define) {
538 mk_tag_macro (d_op, d_file, line);
539 return;
542 if (d_found_type & OT::Class) {
543 S = strchr (d_op, ':');
544 if (S)
545 *S = 0;
548 S = ww_last_word (d_op);
549 if (! S || !(*S) || (*S == ' '))
550 return;
552 if (*S == 's') {
553 if (! strncmp (S, "static", 6))
554 return;
555 if (! strncmp (S, "struct", 6))
556 return;
559 if (*S == 'u' && !strncmp (S, "union", 5))
560 return;
561 if (*S == 'e' && !strncmp (S, "enum", 4))
562 return;
564 if (d_found_type & OT::Function)
565 d_format = "%s\t%s\t%i\t;\tf\n";
567 printf (d_format, S, d_file, line);
570 DArray * mk_tag_structtail_split (char *S)
572 bool b_macro = false;
573 char * d_old = NULL;
574 int brace_depth = 0;
575 DArray * d_array;
577 d_array = new DArray (128);
578 if (! d_array)
579 return NULL;
581 d_old = S;
583 while (true) {
584 if (*S == '\"' || *S == '\'') {
585 S = sstrend (S);
586 if (S == NULL || *S == '\0')
587 break;
590 if (*S == '(')
591 brace_depth++;
593 if (*S == ')') {
594 brace_depth--;
595 if (! brace_depth) {
596 S++;
597 break;
601 if (*S == 0) {
602 if (! b_macro)
603 d_array->add (d_old);
604 break;
607 if (brace_depth) {
608 S++;
609 continue;
612 if (S[1] == '(') {
613 b_macro = true;
614 S++;
615 continue;
618 if (*S == ' ' || *S == ',') {
619 *S = 0;
620 S++;
621 b_macro = false;
622 while (*S == ' ' || *S == '*')
623 S++;
624 if (! b_macro)
625 d_array->add (d_old);
626 d_old = S;
628 continue;
630 S++;
633 return d_array;
636 void mk_tag_structtail (char * S, char * d_file, int t_line)
638 char *w;
639 DArray * d_array;
640 int i;
642 d_array = mk_tag_structtail_split (S);
643 if (! d_array)
644 return;
646 for (i = 0; i < d_array->get_size (); i++) {
647 w = ww_last_word (d_array->get (i));
648 if (! w || !(*w) || *w == ' ')
649 continue;
650 printf ("%s\t%s\t%i\n", w, d_file, t_line);
653 delete d_array;
656 void mk_tags (char *f_name, DArray *d_in)
658 DHeapSort * heap;
659 DArray * d_array = NULL;
660 char *S;
661 FILE * my_file;
662 int d_size;
663 int i;
665 if (d_in == NULL) {
666 d_array = new DArray (1024);
667 d_array->from_file (ENV->tmp_tags);
668 } else
669 d_array = d_in;
671 d_size = d_array->get_size ();
672 heap = new DHeapSort (d_size);
674 for (i = 0; i < d_size; ++i)
675 heap->add (d_array->get (i));
677 my_file = fopen (f_name, "w");
678 if (my_file == NULL) {
679 fprintf (stderr, "file %s:\n", f_name);
680 perror ("fopen");
681 return;
684 fprintf (my_file, "!_TAG_FILE_FORMAT\t2\n");
685 fprintf (my_file, "!_TAG_FILE_SORTED\t1\n");
686 fprintf (my_file, "!_TAG_PROGRAM_AUTHOR\tOleg Puchinin (graycardinalster@gmail.com)\n");
687 fprintf (my_file, "!_TAG_PROGRAM_NAME\tSilent Bob\n");
688 fprintf (my_file, "!_TAG_PROGRAM_URL\thttp://sf.net/projects/silentbob\n");
689 fprintf (my_file, "!_TAG_PROGRAM_VERSION\t1.6\n");
691 while ((S = heap->extract_min ()) && S)
692 fprintf (my_file, "%s", S);
694 if (d_in == NULL) {
695 d_array->foreach (free);
696 delete d_array;
699 fclose (my_file);
700 delete heap;
703 char * name2obj (char * name)
705 char *S;
706 char m_buf[512];
707 if (! name)
708 return NULL;
709 strcpy (m_buf, name);
710 S = rindex (m_buf, '.');
711 if (! S)
712 return NULL;
713 strcpy (S, ".o");
714 return strdup (m_buf);
716 bool b_in_comment;
718 bool brace_count (char * d_str, int * d_count, bool b_force_block) // "nice"
720 bool Ret = false;
722 if (! d_str || ! d_count)
723 return false;
725 while (*d_str != 0) {
726 if (!strncmp (d_str, "/*", 2)) {
727 b_in_comment = true;
728 d_str += 2;
729 continue;
732 if (b_in_comment) {
733 if (strncmp (d_str, "*/", 2)) {
734 d_str ++;
735 continue;
736 } else {
737 d_str += 2;
738 b_in_comment = false;
739 continue;
743 if (!strncmp (d_str, "//", 2))
744 break;
746 if (*d_str == '\"' || *d_str == '\'') {
747 d_str = sstrend (d_str);
748 if (d_str == NULL || *d_str == 0) {
749 assert (true, "HimTeh 4");
750 break;
754 if (*d_str == '{') {
755 Ret = true;
756 (*d_count)++;
759 if (*d_str == '}') {
760 Ret = true;
761 (*d_count)--;
764 if (*d_str == ';' && *d_count == 0 && !b_force_block) {
765 Ret = true;
766 break;
768 d_str++;
771 return Ret;
774 void nogui_fdump (struct fdump_param_t * d_param)
776 int d_count = 0;
777 DArray d_array;
778 FILE * d_file;
779 int d_size;
780 char * S;
781 int i,a;
783 if (!d_array.from_file (d_param->d_file_name))
784 return;
786 if (d_param->d_file_output == NULL)
787 d_file = stdout;
788 else
789 d_file = fopen (d_param->d_file_output, "w");
791 if (! d_file)
792 return;
794 if (! d_param->linear) {
795 for (a = 0; a < d_param->n_trip; a++)
796 fprintf (d_file, "\t");
797 fprintf (d_file, "//<***>\n");
800 i = d_param->d_line-1;
801 d_size = d_array.get_size ();
802 b_in_comment = false;
804 if (d_array.get (i)[0] != '#') {
805 while (i < d_size) {
806 if (!d_param->linear) {
807 for (a = 0; a < d_param->n_trip; a++)
808 fprintf (d_file, "\t");
810 fprintf (d_file, "%s", d_array.get(i));
812 if (brace_count (d_array.get(i), &d_count, d_param->b_force_block) && !d_count)
813 break;
815 if (!d_count && ((i - d_param->d_line) > 2) && !d_param->b_force_block)
816 break;
818 i++;
820 } else {
821 do {
822 S = d_array.get (i);
823 fprintf (d_file, "%s", S);
824 S = &S[strlen (S)-2];
825 while ((*S == ' ') || (*S == '\t'))
826 S--;
828 if (*S != '\\')
829 break;
830 i++;
831 } while (i < d_size);
834 if (!d_param->linear) {
835 for (a = 0; a < d_param->n_trip; a++)
836 fprintf (d_file, "\t");
837 fprintf (d_file, "//</***>\n");
840 if (d_param->d_file_output != NULL)
841 fclose (d_file);
843 d_array.foreach (free);
847 /* code for "linear" functionality, */
848 void nogui_tagsdump (char * f_name, int n_trip) {
849 DArray * d_tags;
850 d_tag_t * d_tag;
851 struct fdump_param_t d_param;
852 int a,i;
854 d_tags = got_tag (f_name);
856 assert (d_tags->get_size () == 0, "HimTeh 1");
857 for (i = 0; i < d_tags->get_size (); i++) {
858 d_tag = (d_tag_t *) d_tags->get (i);
859 if (i != 0)
860 fputc ('\n', stdout);
862 if (!SB_FLGET(SB_FLLINEAR)) {
863 for (a = 0; a < n_trip; a++)
864 fputc ('\t', stdout);
867 printf ("// file %s line %i\n", d_tag->d_file, d_tag->d_line);
869 memset (&d_param, 0, sizeof (struct fdump_param_t));
870 d_param.n_trip = n_trip;
871 d_param.d_file_name = d_tag->d_file;
872 d_param.d_line = d_tag->d_line;
873 d_param.linear = SB_FLGET (SB_FLLINEAR);
874 if (d_tag->d_type & OT::Function)
875 d_param.b_force_block = true;
876 nogui_fdump (&d_param);
879 d_tags->foreach (free);
880 delete d_tags;
881 printf ("\n");
884 void opMacro (char ** d_ptr, char ** d_out, char ch)
886 char *macro_start;
887 char * d_my;
888 int n = 0;
890 d_my = *d_out;
891 macro_start = *d_out;
892 while (true) {
893 if (ch == '\n')
894 n++;
896 if ((ch == '\n') && (d_my[strlen (d_my) - 1] != '\\'))
897 break;
899 // if (n > 300)
900 // break;
902 ch = t_op (d_ptr, d_out);
903 ENV->t_op_no++;
904 if (ch == 0)
905 break;
906 d_my = *d_out;
910 int remove_tmp_files ()
912 char m_buf[512];
913 int i = 0;
915 for (i = 0; i < ENV->max_proc; ++i) {
916 sprintf (m_buf, "%s%i", ENV->tmp_files, i);
917 unlink (m_buf);
920 unlink (ENV->tmp_files);
921 unlink (ENV->tmp_tags);
922 return ENV->max_proc;
925 void setParam (char *opt)
927 char m_buf[512];
928 char *S;
930 if (! opt)
931 return;
932 strcpy (m_buf, opt);
933 S = index (m_buf, '=');
934 if (! S)
935 return;
937 *S = '\0';
938 ++S;
939 strip2 (m_buf);
940 strip (S);
941 ENV->settings->set (m_buf, strdup (S));
944 int split_tmp_files ()
946 FILE * f_tmpfiles;
947 FILE ** proc_files;
948 char m_buf[512];
949 int i = 0;
951 f_tmpfiles = fopen (ENV->tmp_files, "r");
952 if (! f_tmpfiles)
953 return -1;
955 proc_files = CNEW (FILE *, ENV->max_proc);
956 memset (proc_files, 0, sizeof (FILE *) * ENV->max_proc);
957 errno = 0;
958 for (i = 0; i < ENV->max_proc; ++i) {
959 sprintf (m_buf, "%s%i", ENV->tmp_files, i);
960 unlink (m_buf);
961 proc_files[i] = fopen (m_buf, "w");
962 if (! proc_files[i]) {
963 perror ("fopen");
964 return -1;
968 i = 0;
969 while (fgets (m_buf, 512, f_tmpfiles)) {
970 fprintf (proc_files[i], "%s", m_buf);
971 if (++i >= ENV->max_proc)
972 i = 0;
975 for (i = 0; i < ENV->max_proc; ++i)
976 fclose (proc_files[i]);
978 return ENV->max_proc;
981 DArray * split_to_words (char * d_op)
983 DArray * d_Ret = new DArray (16);
984 char * d_old = strdup (d_op);
985 bool b_done = false;
986 char * S = d_old;
987 char * d_end;
988 char ch;
990 if (d_Ret == NULL || d_old == NULL)
991 return NULL;
993 while (true) {
994 b_done = false;
995 d_end = S;
997 if (*d_end == ' ')
998 d_end++;
1000 while (*d_end) {
1001 if (!(if_abc(d_end) ||
1002 if_digit (d_end) ||
1003 *d_end == '_' ||
1004 *d_end == ' ') )
1005 break;
1006 d_end ++;
1009 if (! *d_end) {
1010 ch = 0;
1011 b_done = true;
1012 goto split_to_words_L1;
1015 ch = *d_end;
1016 if (d_end[-1] == ' ')
1017 d_end[-1] = 0;
1018 else
1019 *d_end = 0;
1021 while (*S && *S == ' ')
1022 S++;
1024 split_to_words_L1:
1025 d_Ret->add (LPCHAR(new_cword (S, ch)));
1027 if (b_done)
1028 break;
1030 if (ch == '\"' || ch == '\'') {
1031 *d_end = ch;
1032 d_end = sstrend (d_end);
1033 assert (d_end == NULL, "Lena 1");
1034 if (*d_end == '\0' || *(++d_end) == '\0')
1035 break;
1038 S = d_end + 1;
1041 DROP (d_old);
1042 return d_Ret;
1045 char * sstrend (char * d_ptr)
1047 bool t_instring = false;
1048 int d_slash_count;
1049 char ch_last;
1050 char *d_old;
1051 unsigned limit = 1024;
1053 if (! d_ptr)
1054 return (char *) 0;
1056 if (!(*d_ptr))
1057 return (char *) 0;
1059 ch_last = *d_ptr;
1060 d_old = d_ptr;
1061 limit--;
1062 while (*d_ptr && (limit > 0)) {
1063 if (*d_ptr == '\'' || *d_ptr == '\"') {
1064 if (t_instring && *d_ptr != ch_last) {
1065 d_ptr++;
1066 continue; // Mmm...
1069 if (t_instring) {
1070 if (d_ptr[-1] == '\\') {
1071 d_slash_count = 1;
1072 while (d_ptr [-(d_slash_count)] == '\\')
1073 d_slash_count++;
1075 if (d_slash_count & 1)
1076 t_instring = false;
1077 } else {
1078 d_ptr++;
1079 t_instring = false;
1080 continue;
1082 } else {
1083 ch_last = *d_ptr;
1084 t_instring = true;
1088 if (t_instring) {
1089 d_ptr++;
1090 continue;
1091 } else
1092 break;
1095 d_ptr --;
1097 if (*d_ptr == 0)
1098 return 0;
1100 return d_ptr;
1103 char * sstrkill (char *OP)
1105 char *S;
1106 char *tail;
1108 if (! OP)
1109 return NULL;
1111 S = OP;
1112 while (*S) {
1113 if (*S == '\"' || *S == '\'') {
1114 tail = sstrend (S);
1115 if (! tail)
1116 break;
1118 if (*tail == '\0' ||*(tail+1) == '\0') {
1119 *S = '\0';
1120 break;
1123 ++S;
1124 strcpy (S, tail);
1126 ++S;
1129 return OP;
1132 int words_count (char *S)
1134 bool b_begin = true;
1135 int d_ret = 0;
1137 if (S == 0)
1138 return 0;
1140 while (*S) {
1141 if (*S == ' ') {
1142 b_begin = true;
1143 S++;
1144 continue;
1147 if (b_begin) {
1148 if (if_abc (S) ||
1149 (*S == '_') ||
1150 (*S == '*') ||
1151 (*S == '&')) {
1152 S++;
1153 d_ret ++;
1154 b_begin = false;
1155 continue;
1156 } else
1157 break;
1158 } else {
1159 if (!(if_abc (S) || (*S == '_')
1160 || (*S == '*') || (if_digit (S))))
1161 break;
1164 S++;
1165 b_begin = false;
1168 return d_ret;
1171 int ww_begin_line (struct tt_state_t * d_tt_state, char *d_out, int d_offset)
1173 char *S = &d_tt_state->fileData [d_offset] - 1;
1174 char * d_end = &d_out[strlen (d_out)] - 1;
1175 int Ret = 0;
1177 while (d_end > d_out) {
1178 if (*d_end == ' ' || *d_end == '\t') {
1179 while ((S >= d_tt_state->fileData) && (*S == ' ' || *S == '\t'))
1180 --S;
1182 if (S < d_tt_state->fileData)
1183 return Ret;
1185 while ((d_end >= d_out) && (*d_end == ' ' || *d_end == '\t'))
1186 --d_end;
1188 if (d_end <= d_out)
1189 return Ret;
1191 continue;
1194 if (*S == '\n')
1195 --Ret;
1197 if (*S == *d_end)
1198 --d_end;
1200 --S;
1203 return Ret;
1206 char * ww_begin_offset (struct tt_state_t * d_tt_state, char *d_out, int d_offset)
1208 char *S = &d_tt_state->fileData [d_offset] - 1;
1209 char * d_real = &d_out[strlen (d_out)] - 1;
1211 while (d_real != d_out) {
1212 if (*d_real == ' ' || *d_real == '\t') {
1213 while (*S == ' ' || *S == '\t')
1214 S--;
1216 while ((*d_real == ' ' || *d_real == '\t')
1217 && (d_real != d_out))
1218 --d_real;
1220 continue;
1223 if (*S == *d_real)
1224 --d_real;
1226 --S;
1229 return S;
1232 char * ww_last_word (char *d_op)
1234 char * S = d_op;
1235 char * d_word;
1237 while (*S) {
1238 if (*S == '(' || *S == '=' || *S == '[')
1239 break;
1240 S++;
1243 if (S[-1] == ' ')
1244 S--;
1246 *S = 0;
1247 d_word = d_op;
1248 while (true) {
1249 S = strchr (d_word, ' ');
1250 if (S == NULL)
1251 break;
1252 d_word = S+1;
1255 while (*d_word == '*' ||
1256 *d_word == '&' ||
1257 *d_word == ' ')
1258 d_word++;
1260 return d_word;
1263 bool validOption (char *Name)
1265 char *S;
1266 if (! Name)
1267 return false;
1269 S = ENV->listOptions->first ();
1270 while (S) {
1271 if (EQ (Name, S))
1272 return true;
1273 S = ENV->listOptions->next ();
1275 return false;