2 * (c) Oleg Puchinin 2006,2007
3 * graycardinalster@gmail.com
7 #include <gclib/gclib.h>
20 char * __bice_get (char *optname
)
23 value
= ENV
->settings
->get (optname
);
25 value
= getenv (optname
);
29 EHash
* bob_init_compile_env ()
41 compile_env
= new EHash
;
43 cc
= __bice_get ((char *) "CC");
44 cxx
= __bice_get ((char *) "CXX");
45 cflags
= __bice_get ((char *) "CFLAGS");
46 cxxflags
= __bice_get ((char *) "CXXFLAGS");
47 opts
= __bice_get ((char *) "OPTS");
48 include
= __bice_get ((char *) "INCLUDE");
49 libs
= __bice_get ((char *) "LIBS");
50 ldflags
= __bice_get ((char *) "LDFLAGS");
57 cflags
= (char *) "-O3 -Wall -pipe";
63 include
= (char *) "";
67 ldflags
= (char *) "";
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 ((char *) "CC", strdup (cc
));
81 compile_env
->set ((char *) "CXX", strdup (cxx
));
82 compile_env
->set ((char *) "CFLAGS", strdup (cflags
));
83 compile_env
->set ((char *) "CXXFLAGS", strdup (cxxflags
));
84 compile_env
->set ((char *) "OPTS", strdup (opts
));
85 compile_env
->set ((char *) "INCLUDE", strdup (include
));
86 compile_env
->set ((char *) "LIBS", strdup (libs
));
87 compile_env
->set ((char *) "LDFLAGS", strdup (ldflags
));
92 int sb_prname (char *arg
)
96 d_ptr
= arg
+ strlen (arg
);
99 while (*d_ptr
!= '\\' &&
106 if (EQ (d_ptr
, "tags"))
108 else if (EQ (d_ptr
, "the_tt"))
110 else if (EQ (d_ptr
, "gc_indent"))
112 else if (EQ (d_ptr
, "structs"))
113 i_cmd
= cmd_give_structs
;
119 void tags (DArray
* d_names
, char * d_file_output
)
121 struct fdump_param_t d_param
;
123 struct d_tag_t
* d_tag
;
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",
137 fflush (ENV
->d_stream_dbg
);
146 if(! d_tags
->get_size ()) {
154 for (a
= 0; a
< d_tags
->get_size (); a
++) {
155 d_tag
= (d_tag_t
*) d_tags
->get (a
);
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
));
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
);
174 fputc ('\n', 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");
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");
213 printf ("Can't make tags file. Maybe you do not have write permissions ?\n");
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
)
240 strcpy (m_buf
, d_str
);
243 strncpy (d_tag
->d_name
, d_name
, 255);
244 d_tag
->d_name
[255] = 0;
245 S
= strchr (d_str
, '\t');
251 S
= strchr (d_file
, '\t');
256 strncpy (d_tag
->d_file
, d_file
, 255);
257 d_tag
->d_file
[255] = 0;
262 d_tag
->d_line
= atoi (S
);
269 char * cts (struct c_word
* d_word
)
277 if (!strncmp (S
, "else ", 5))
280 if (d_word
->ch
!= '(')
283 while (!strncmp (S
, "do ", 3))
286 if (!strncmp (S
, "return ", 7))
289 if (ENV
->d_cops
->sfind (S
) != -1)
292 if (words_count (S
) != 1)
298 bool def_test (char * d_op
)
302 while (*S
== ' ' || *S
== '\t')
305 if (! strncmp (S
, "define", 6))
312 find_one_ext ((char *) "*.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");
321 int sblib_find (const char * path
, const char * name
, const char * f_outname
)
330 devnull
= open ("/dev/null", O_WRONLY
, 0600);
331 fd
= open (f_outname
, O_WRONLY
, 0600);
333 fd
= open (f_outname
, O_WRONLY
| O_CREAT
, 0600);
339 lseek (fd
, 0, SEEK_END
);
342 execlp ("find", path
, "-name", name
, NULL
);
343 } else if (pid
> 0) {
344 waitpid (pid
, &status
, 0);
351 # define TMP_FILE_NAME (char *) "./silent_bob.tmp"
352 struct tt_state_t
* get_onett_tag (char * f_name
, char ** d_tt_buf
)
355 tt_state_t
* Ret
= 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
);
368 if (access (TMP_FILE_NAME
, R_OK
) != 0)
371 Ret
->fileName
= strdup (TMP_FILE_NAME
);
372 S
= THE_TT::do_tt_file (Ret
);
378 munmap (Ret
->fileData
, Ret
->fileDataSize
);
386 unlink (TMP_FILE_NAME
);
391 unlink (TMP_FILE_NAME
);
395 void globalsPrint (tt_state_t
* tt
, char * d_out
, int d_found_type
)
400 if (SB_FLGET (SB_FLSIMULATE
))
403 if (d_found_type
& OT::Other
)
406 t_line
= tt
->attachment
[ENV
->t_op_no
].pair_line
+1;
407 t_line
+= ww_begin_line (tt
, d_out
,
408 tt
->attachment
[ENV
->t_op_no
].offset
);
410 if (SB_FLGET(SB_FLTAGSTYLE
))
411 mk_tag (d_out
, tt
->fileName
,
412 t_line
, d_found_type
);
414 if (d_found_type
& OT::Class
) {
415 S
= strchr (d_out
, ':');
422 printf ("%s\t\t//file %s //line %i\n", d_out
,
423 tt
->fileName
, t_line
);
431 EArray
* got_tag (char * d_tag
)
433 struct d_tag_t
*d_new_tag
;
442 if (ENV
->d_tags_file
== NULL
) {
443 ENV
->d_tags_file
= new EArray
;
444 ENV
->d_tags_file
->from_file ((char *) "./tags");
447 snprintf (d_buf
, 255, "%s\t", d_tag
);
448 d_len
= strlen (d_buf
);
450 if (ENV
->d_tags_file
->get_size () == 0)
453 i
= ENV
->d_tags_file
->snfind_fast (d_buf
, strlen (d_buf
));
456 fprintf (ENV
->d_stream_dbg
, "\tENV->d_tags_file->snfind_fast == -1"); LN
;
460 d_len
= strlen (d_buf
);
463 S
= ENV
->d_tags_file
->get (i
);
466 } while (! strncmp (S
, d_buf
, d_len
));
470 S
= ENV
->d_tags_file
->get (i
);
471 fprintf (ENV
->d_stream_dbg
, "\ttag : %s\n", S
); fflush (ENV
->d_stream_dbg
);
473 d_new_tag
= CNEW (d_tag_t
, 1);
474 memset (d_new_tag
, 0, sizeof (d_tag_t
));
475 if (strstr (S
, ";\tf"))
476 d_new_tag
->d_type
= OT::Function
;
478 if (bob_tag (S
, d_tag
, d_new_tag
) == false) {
480 fprintf (ENV
->d_stream_dbg
, "\tBAD tag : %s\n", S
);
484 d_ret
->add ((long) d_new_tag
);
490 S
= ENV
->d_tags_file
->get (i
);
491 if (strncmp (S
, d_tag
, strlen (d_tag
)))
498 char * macro_name (char * d_op
, char * d_macro_name
)
504 strncpy (m_buf
, d_op
, 255);
507 S
= strstr (m_buf
, "define");
520 S
= strchr (d_begin
, ' ');
524 S
= strchr (d_begin
, '(');
528 strcpy (d_macro_name
, d_begin
);
532 void mk_tag_macro (char * d_op
, char * d_file
, int t_line
)
536 if (! macro_name (d_op
, S
))
539 printf ("%s\t%s\t%i\n", S
, d_file
, t_line
);
542 void mk_tag (char * d_op
, char * d_file
, int line
, int d_found_type
)
544 char * d_format
= (char *) "%s\t%s\t%i\n";
547 if (d_found_type
& OT::Define
) {
548 mk_tag_macro (d_op
, d_file
, line
);
552 if (d_found_type
& OT::Class
) {
553 S
= strchr (d_op
, ':');
558 S
= ww_last_word (d_op
);
559 if (! S
|| !(*S
) || (*S
== ' '))
563 if (! strncmp (S
, "static", 6))
565 if (! strncmp (S
, "struct", 6))
569 if (*S
== 'u' && !strncmp (S
, "union", 5))
571 if (*S
== 'e' && !strncmp (S
, "enum", 4))
574 if (d_found_type
& OT::Function
)
575 d_format
= (char *) "%s\t%s\t%i\t;\tf\n";
576 else if (d_found_type
& OT::Class
)
577 d_format
= (char *) "%s\t%s\t%i\t;\tc\n";
578 else if (d_found_type
& OT::Struct
)
579 (char *) "%s\t%s\t%i\t;\ts\n";
581 printf (d_format
, S
, d_file
, line
);
584 DArray
* mk_tag_structtail_split (char *S
)
586 bool b_macro
= false;
591 d_array
= new DArray (128);
598 if (*S
== '\"' || *S
== '\'') {
600 if (S
== NULL
|| *S
== '\0')
617 d_array
->add (d_old
);
632 if (*S
== ' ' || *S
== ',') {
636 while (*S
== ' ' || *S
== '*')
639 d_array
->add (d_old
);
650 void mk_tag_structtail (char * S
, char * d_file
, int t_line
)
656 d_array
= mk_tag_structtail_split (S
);
660 for (i
= 0; i
< d_array
->get_size (); i
++) {
661 w
= ww_last_word (d_array
->get (i
));
662 if (! w
|| !(*w
) || *w
== ' ')
664 printf ("%s\t%s\t%i\n", w
, d_file
, t_line
);
670 void mk_tags (char *f_name
, DArray
*d_in
)
673 DArray
* d_array
= NULL
;
680 d_array
= new DArray (1024);
681 d_array
->from_file (ENV
->tmp_tags
);
685 d_size
= d_array
->get_size ();
686 heap
= new DHeapSort (d_size
);
688 for (i
= 0; i
< d_size
; ++i
)
689 heap
->add (d_array
->get (i
));
691 my_file
= fopen (f_name
, "w");
692 if (my_file
== NULL
) {
693 fprintf (stderr
, "file %s:\n", f_name
);
698 fprintf (my_file
, "!_TAG_FILE_FORMAT\t2\n");
699 fprintf (my_file
, "!_TAG_FILE_SORTED\t1\n");
700 fprintf (my_file
, "!_TAG_PROGRAM_AUTHOR\tOleg Puchinin (graycardinalster@gmail.com)\n");
701 fprintf (my_file
, "!_TAG_PROGRAM_NAME\tSilent Bob\n");
702 fprintf (my_file
, "!_TAG_PROGRAM_URL\thttp://sf.net/projects/silentbob\n");
703 fprintf (my_file
, "!_TAG_PROGRAM_VERSION\t1.6\n");
705 while ((S
= heap
->extract_min ()) && S
)
706 fprintf (my_file
, "%s", S
);
709 d_array
->foreach (free
);
717 char * name2obj (char * name
)
723 strcpy (m_buf
, name
);
724 S
= rindex (m_buf
, '.');
728 return strdup (m_buf
);
732 bool brace_count (char * d_str
, int * d_count
, bool b_force_block
) // "nice"
736 if (! d_str
|| ! d_count
)
739 while (*d_str
!= 0) {
740 if (!strncmp (d_str
, "/*", 2)) {
747 if (strncmp (d_str
, "*/", 2)) {
752 b_in_comment
= false;
757 if (!strncmp (d_str
, "//", 2))
760 if (*d_str
== '\"' || *d_str
== '\'') {
761 d_str
= sstrend (d_str
);
762 if (d_str
== NULL
|| *d_str
== 0) {
763 assert (true, "HimTeh 4");
778 if (*d_str
== ';' && *d_count
== 0 && !b_force_block
) {
788 void nogui_fdump (struct fdump_param_t
* d_param
)
797 if (!d_array
.from_file (d_param
->d_file_name
))
800 if (d_param
->d_file_output
== NULL
)
803 d_file
= fopen (d_param
->d_file_output
, "w");
808 if (! d_param
->linear
) {
809 for (a
= 0; a
< d_param
->n_trip
; a
++)
810 fprintf (d_file
, "\t");
811 fprintf (d_file
, "//<***>\n");
814 i
= d_param
->d_line
-1;
815 d_size
= d_array
.get_size ();
816 b_in_comment
= false;
818 if (d_array
.get (i
)[0] != '#') {
820 if (!d_param
->linear
) {
821 for (a
= 0; a
< d_param
->n_trip
; a
++)
822 fprintf (d_file
, "\t");
824 fprintf (d_file
, "%s", d_array
.get(i
));
826 if (brace_count (d_array
.get(i
), &d_count
, d_param
->b_force_block
) && !d_count
)
829 if (!d_count
&& ((i
- d_param
->d_line
) > 2) && !d_param
->b_force_block
)
837 fprintf (d_file
, "%s", S
);
838 S
= &S
[strlen (S
)-2];
839 while ((*S
== ' ') || (*S
== '\t'))
845 } while (i
< d_size
);
848 if (!d_param
->linear
) {
849 for (a
= 0; a
< d_param
->n_trip
; a
++)
850 fprintf (d_file
, "\t");
851 fprintf (d_file
, "//</***>\n");
854 if (d_param
->d_file_output
!= NULL
)
857 d_array
.foreach (free
);
861 /* code for "linear" functionality, */
862 void nogui_tagsdump (char * f_name
, int n_trip
) {
865 struct fdump_param_t d_param
;
868 d_tags
= got_tag (f_name
);
870 assert (d_tags
->get_size () == 0, "HimTeh 1");
871 for (i
= 0; i
< d_tags
->get_size (); i
++) {
872 d_tag
= (d_tag_t
*) d_tags
->get (i
);
874 fputc ('\n', stdout
);
876 if (!SB_FLGET(SB_FLLINEAR
)) {
877 for (a
= 0; a
< n_trip
; a
++)
878 fputc ('\t', stdout
);
881 printf ("// file %s line %i\n", d_tag
->d_file
, d_tag
->d_line
);
883 memset (&d_param
, 0, sizeof (struct fdump_param_t
));
884 d_param
.n_trip
= n_trip
;
885 d_param
.d_file_name
= d_tag
->d_file
;
886 d_param
.d_line
= d_tag
->d_line
;
887 d_param
.linear
= SB_FLGET (SB_FLLINEAR
);
888 if (d_tag
->d_type
& OT::Function
)
889 d_param
.b_force_block
= true;
890 nogui_fdump (&d_param
);
893 d_tags
->foreach (free
);
898 void opMacro (char ** d_ptr
, char ** d_out
, char ch
)
905 macro_start
= *d_out
;
910 if ((ch
== '\n') && (d_my
[strlen (d_my
) - 1] != '\\'))
916 ch
= t_op (d_ptr
, d_out
);
924 int remove_tmp_files ()
929 for (i
= 0; i
< ENV
->max_proc
; ++i
) {
930 sprintf (m_buf
, "%s%i", ENV
->tmp_files
, i
);
934 unlink (ENV
->tmp_files
);
935 unlink (ENV
->tmp_tags
);
936 return ENV
->max_proc
;
939 void setParam (char *opt
)
947 S
= index (m_buf
, '=');
955 ENV
->settings
->set (m_buf
, strdup (S
));
958 int split_tmp_files ()
965 f_tmpfiles
= fopen (ENV
->tmp_files
, "r");
969 proc_files
= CNEW (FILE *, ENV
->max_proc
);
970 memset (proc_files
, 0, sizeof (FILE *) * ENV
->max_proc
);
972 for (i
= 0; i
< ENV
->max_proc
; ++i
) {
973 sprintf (m_buf
, "%s%i", ENV
->tmp_files
, i
);
975 proc_files
[i
] = fopen (m_buf
, "w");
976 if (! proc_files
[i
]) {
983 while (fgets (m_buf
, 512, f_tmpfiles
)) {
984 fprintf (proc_files
[i
], "%s", m_buf
);
985 if (++i
>= ENV
->max_proc
)
989 for (i
= 0; i
< ENV
->max_proc
; ++i
)
990 fclose (proc_files
[i
]);
992 return ENV
->max_proc
;
995 DArray
* split_to_words (char * d_op
)
997 DArray
* d_Ret
= new DArray (16);
998 char * d_old
= strdup (d_op
);
1004 if (d_Ret
== NULL
|| d_old
== NULL
)
1015 if (!(if_abc(d_end
) ||
1026 goto split_to_words_L1
;
1030 if (d_end
[-1] == ' ')
1035 while (*S
&& *S
== ' ')
1039 d_Ret
->add (LPCHAR(new_cword (S
, ch
)));
1044 if (ch
== '\"' || ch
== '\'') {
1046 d_end
= sstrend (d_end
);
1047 assert (d_end
== NULL
, "Lena 1");
1048 if (*d_end
== '\0' || *(++d_end
) == '\0')
1059 char * sstrend (char * d_ptr
)
1061 bool t_instring
= false;
1065 unsigned limit
= 1024;
1076 while (*d_ptr
&& (limit
> 0)) {
1077 if (*d_ptr
== '\'' || *d_ptr
== '\"') {
1078 if (t_instring
&& *d_ptr
!= ch_last
) {
1084 if (d_ptr
[-1] == '\\') {
1086 while (d_ptr
[-(d_slash_count
)] == '\\')
1089 if (d_slash_count
& 1)
1117 char * sstrkill (char *OP
)
1127 if (*S
== '\"' || *S
== '\'') {
1132 if (*tail
== '\0' ||*(tail
+1) == '\0') {
1146 int words_count (char *S
)
1148 bool b_begin
= true;
1173 if (!(if_abc (S
) || (*S
== '_')
1174 || (*S
== '*') || (if_digit (S
))))
1185 int ww_begin_line (struct tt_state_t
* d_tt_state
, char *d_out
, int d_offset
)
1187 char *S
= &d_tt_state
->fileData
[d_offset
] - 1;
1188 char * d_end
= &d_out
[strlen (d_out
)] - 1;
1191 while (d_end
> d_out
) {
1192 if (*d_end
== ' ' || *d_end
== '\t') {
1193 while ((S
>= d_tt_state
->fileData
) && (*S
== ' ' || *S
== '\t'))
1196 if (S
< d_tt_state
->fileData
)
1199 while ((d_end
>= d_out
) && (*d_end
== ' ' || *d_end
== '\t'))
1220 char * ww_begin_offset (struct tt_state_t
* d_tt_state
, char *d_out
, int d_offset
)
1222 char *S
= &d_tt_state
->fileData
[d_offset
] - 1;
1223 char * d_real
= &d_out
[strlen (d_out
)] - 1;
1225 while (d_real
!= d_out
) {
1226 if (*d_real
== ' ' || *d_real
== '\t') {
1227 while (*S
== ' ' || *S
== '\t')
1230 while ((*d_real
== ' ' || *d_real
== '\t')
1231 && (d_real
!= d_out
))
1246 char * ww_last_word (char *d_op
)
1252 if (*S
== '(' || *S
== '=' || *S
== '[')
1263 S
= strchr (d_word
, ' ');
1269 while (*d_word
== '*' ||
1277 bool validOption (char *Name
)
1283 S
= ENV
->listOptions
->first ();
1287 S
= ENV
->listOptions
->next ();
1292 int lastPluginID
= 0;
1295 return ++lastPluginID
;