1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
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 2 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
30 #ifndef HAVE_VSNPRINTF
47 #include "../include/prototype.h"
49 #ifdef HAVE_LIBDMALLOC
53 /*! this is modified here and in o_list.c */
56 #define NUMCOLORS 9 /*!< */
59 struct st_old_colors
{
65 * Colors must be in alphabetical order
66 * be sure that you update above define
68 struct st_old_colors old_colors
[] = {
80 /*! \todo Finish function documentation!!!
82 * \par Function Description
85 void error_if_called(void)
87 fprintf(stderr
, "Somebody called error_if_called!\n");
91 /*! \todo Finish function documentation!!!
93 * \par Function Description
96 void exit_if_null(void *ptr
)
99 fprintf(stderr
, "gEDA: Got NULL ptr!, please e-mail maintainer\n");
105 /*! \todo Finish function documentation!!!
107 * \par Function Description
110 /* hack rename this to be s_return_tail */
111 /* update object_tail or any list of that matter */
112 OBJECT
*return_tail(OBJECT
*head
)
114 OBJECT
*o_current
=NULL
;
115 OBJECT
*ret_struct
=NULL
;
118 while ( o_current
!= NULL
) { /* goto end of list */
119 ret_struct
= o_current
;
120 o_current
= o_current
->next
;
126 /*! \todo Finish function documentation!!!
128 * \par Function Description
131 /* hack rename this to be s_return_head */
132 /* update object_tail or any list of that matter */
133 OBJECT
*return_head(OBJECT
*tail
)
135 OBJECT
*o_current
=NULL
;
136 OBJECT
*ret_struct
=NULL
;
139 while ( o_current
!= NULL
) { /* goto end of list */
140 ret_struct
= o_current
;
141 o_current
= o_current
->prev
;
147 /*! \todo Finish function documentation!!!
149 * \par Function Description
152 OBJECT
*s_basic_init_object( char *name
)
156 new_node
= (OBJECT
*) g_malloc(sizeof(OBJECT
));
158 if (new_node
== NULL
) {
159 fprintf(stderr
, "Could not perform malloc; something is broken or increase your process limits\n");
164 new_node
->sid
= global_sid
++;
168 /*! \todo get rid of magic number 16 that's the size of new_node->sid, */
169 new_node
->name
= (char *) g_malloc(sizeof(char)*(strlen(name
)+16));
170 sprintf(new_node
->name
, "%s.%d", name
, new_node
->sid
);
172 /* Setup the bounding box */
174 new_node
->w_left
= 0;
175 new_node
->w_right
= 0;
176 new_node
->w_bottom
= 0;
178 /* Setup line/circle structs */
179 new_node
->line
= NULL
;
180 new_node
->circle
= NULL
;
181 new_node
->arc
= NULL
;
182 new_node
->box
= NULL
;
183 new_node
->picture
= NULL
;
184 new_node
->text
= NULL
;
185 new_node
->complex = NULL
;
187 new_node
->tile_locs
= NULL
;
189 new_node
->conn_list
= NULL
;
191 new_node
->visited
= 0;
193 new_node
->complex_basename
= NULL
;
194 new_node
->complex_parent
= NULL
;
196 /* Setup the color */
197 new_node
->color
= WHITE
;
198 new_node
->saved_color
= -1;
199 new_node
->selected
= FALSE
;
200 new_node
->locked_color
= -1;
201 new_node
->draw_grips
= FALSE
;
203 new_node
->bus_ripper_direction
= 0;
205 new_node
->action_func
= error_if_called
;
206 new_node
->sel_func
= error_if_called
;
207 new_node
->draw_func
= error_if_called
;
209 new_node
->line_end
= END_NONE
;
210 new_node
->line_type
= TYPE_SOLID
;
211 new_node
->line_width
= 0;
212 new_node
->line_space
= 0;
213 new_node
->line_length
= 0;
214 new_node
->fill_width
= 0;
215 new_node
->fill_angle1
= 0;
216 new_node
->fill_angle2
= 0;
217 new_node
->fill_pitch1
= 0;
218 new_node
->fill_pitch2
= 0;
220 new_node
->attribs
= NULL
;
221 new_node
->attached_to
= NULL
;
222 new_node
->attribute
= 0;
223 new_node
->show_name_value
= SHOW_NAME_VALUE
;
224 new_node
->visibility
= VISIBLE
;
226 new_node
->pin_type
= PIN_TYPE_NET
;
227 new_node
->whichend
= -1;
229 /* Setup link list stuff */
230 new_node
->prev
= NULL
;
231 new_node
->next
= NULL
;
236 OBJECT
*s_basic_link_object( OBJECT
*new_node
, OBJECT
*ptr
)
238 /* should never happen, but could */
239 if (new_node
== NULL
) {
240 fprintf(stderr
, "Got a null new_node in link_object\n");
245 new_node
->prev
= NULL
; /* setup previous link */
248 new_node
->prev
= ptr
; /* setup previous link */
249 ptr
->next
= new_node
;
254 /*! \todo Finish function documentation!!!
256 * \par Function Description
259 void print_struct_forw(OBJECT
*ptr
)
261 OBJECT
*o_current
=NULL
;
265 if (o_current
== NULL
) {
267 printf("AGGGGGGGGGGG NULLLLL PRINT\n");
269 printf("TRYING to PRINT\n");
270 while (o_current
!= NULL
) {
271 printf("Name: %s\n", o_current
->name
);
272 printf("Type: %d\n", o_current
->type
);
273 printf("Sid: %d\n", o_current
->sid
);
275 if (o_current
->type
== OBJ_COMPLEX
|| o_current
->type
== OBJ_PLACEHOLDER
) {
276 print_struct_forw(o_current
->complex->prim_objs
);
279 o_attrib_print (o_current
->attribs
);
282 o_current
= o_current
->next
;
286 /*! \todo Finish function documentation!!!
288 * \par Function Description
291 void print_struct_back(OBJECT
*ptr
)
293 OBJECT
*o_current
=NULL
;
297 while (o_current
!= NULL
) {
298 printf("Name: %s\n", o_current
->name
);
299 printf("Type: %d\n", o_current
->type
);
300 printf("Sid: %d\n", o_current
->sid
);
302 o_current
= o_current
->prev
;
306 /*! \todo Finish function documentation!!!
308 * \par Function Description
311 void print_struct(OBJECT
*ptr
)
313 OBJECT
*o_current
=NULL
;
317 if (o_current
!= NULL
) {
318 printf("Name: %s\n", o_current
->name
);
319 printf("Type: %d\n", o_current
->type
);
320 printf("Sid: %d\n", o_current
->sid
);
321 if (o_current
->line
!= NULL
) {
322 printf("Line points.x1: %d\n", o_current
->line
->x
[0]);
323 printf("Line points.y1: %d\n", o_current
->line
->y
[0]);
324 printf("Line points.x2: %d\n", o_current
->line
->x
[1]);
325 printf("Line points.y2: %d\n", o_current
->line
->y
[1]);
328 o_attrib_print (o_current
->attribs
);
334 /*! \todo Finish function documentation!!!
336 * \par Function Description
340 s_delete_object(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
342 if (o_current
!= NULL
) {
343 s_conn_remove(toplevel
, o_current
);
345 /* second half of if is odd that we need it? hack */
346 /* need to do this early so we can do the printfs */
347 if (o_current
->attached_to
!= NULL
&& o_current
->attribute
== 1) {
348 if (o_current
->attached_to
->object
) {
349 /*printf("removing %s\n", o_current->attached_to->object->name);*/
351 printf("found a null I didn't expect!!!!!!!!!\n");
354 /* do the actual remove */
355 o_attrib_delete(o_current
->attached_to
);
358 if (toplevel
->page_current
->object_lastplace
== o_current
) {
359 toplevel
->page_current
->object_lastplace
= NULL
;
362 if (o_current
->line
) {
363 /* printf("sdeleting line\n");*/
364 g_free(o_current
->line
);
366 /* yes this object might be in the tile system */
367 s_tile_remove_object_all(toplevel
,
368 toplevel
->page_current
,
371 o_current
->line
= NULL
;
373 if (o_current
->circle
) {
374 /* printf("sdeleting circle\n");*/
375 g_free(o_current
->circle
);
377 o_current
->circle
= NULL
;
379 if (o_current
->arc
) {
380 /* printf("sdeleting arc\n");*/
381 g_free(o_current
->arc
);
383 o_current
->arc
= NULL
;
385 if (o_current
->box
) {
386 /* printf("sdeleting box\n");*/
387 g_free(o_current
->box
);
389 o_current
->box
= NULL
;
391 if (o_current
->picture
) {
392 /* printf("sdeleting picture\n");*/
394 if (o_current
->picture
->original_picture
)
395 g_object_unref(o_current
->picture
->original_picture
);
396 if (o_current
->picture
->displayed_picture
)
397 g_object_unref(o_current
->picture
->displayed_picture
);
399 if (o_current
->picture
->filename
)
400 g_free(o_current
->picture
->filename
);
401 g_free(o_current
->picture
);
403 o_current
->picture
= NULL
;
405 if (o_current
->text
) {
406 if (o_current
->text
->string
) {
407 /*printf("sdeleting text->string\n");*/
408 g_free(o_current
->text
->string
);
410 o_current
->text
->string
= NULL
;
412 if (o_current
->text
->prim_objs
) {
413 /*printf("sdeleting text complex\n");*/
414 s_delete_list_fromstart(toplevel
,
415 o_current
->text
->prim_objs
);
417 o_current
->text
->prim_objs
= NULL
;
419 /* printf("sdeleting text\n");*/
420 g_free(o_current
->text
);
422 o_current
->text
= NULL
;
424 if (o_current
->name
) {
425 /* printf("sdeleting name\n");*/
426 g_free(o_current
->name
);
428 o_current
->name
= NULL
;
431 if (o_current
->complex_basename
) {
432 /* printf("sdeleting complex_basename\n");*/
433 g_free(o_current
->complex_basename
);
435 o_current
->complex_basename
= NULL
;
437 if (o_current
->complex) {
439 if (o_current
->complex->prim_objs
) {
440 /* printf("sdeleting complex->primitive_objects\n");*/
441 s_delete_list_fromstart(toplevel
,
442 o_current
->complex->prim_objs
);
444 o_current
->complex->prim_objs
= NULL
;
446 g_free(o_current
->complex);
447 o_current
->complex = NULL
;
450 if (o_current
->attribs
) {
451 o_attrib_free_all(toplevel
, o_current
->attribs
);
453 o_current
->attribs
= NULL
;
456 g_free(o_current
); /* assuming it is not null */
458 o_current
=NULL
; /* misc clean up */
462 /*! \todo Finish function documentation!!!
464 * \par Function Description
468 s_delete(TOPLEVEL
*toplevel
, OBJECT
*o_current
)
470 if (o_current
!= NULL
) {
474 printf("sdel: %s\n", o_current
->name
);
475 printf("sdel: %d\n", o_current
->sid
);
479 o_current
->next
->prev
= o_current
->prev
;
481 o_current
->next
= NULL
;
484 o_current
->prev
->next
= o_current
->next
;
486 o_current
->prev
= NULL
;
488 s_delete_object(toplevel
, o_current
);
492 /*! \todo Finish function documentation!!!
494 * \par Function Description
497 /* deletes everything include the head */
498 void s_delete_list_fromstart(TOPLEVEL
*toplevel
, OBJECT
*start
)
500 OBJECT
*temp
=NULL
; /* literally is a temp */
501 OBJECT
*current
=NULL
; /* ugg... you have both o_current and current? */
502 OBJECT
*o_current
=NULL
; /* hack */
505 current
= return_tail(start
);
507 /* do the delete backwards */
508 /*while(current != NULL && current->type != OBJ_HEAD ) {*/
509 while(current
!= NULL
) {
510 o_current
= current
->prev
;
511 s_delete(toplevel
, current
);
515 /* now delete the head node */
516 /* might not need this but what the hell */
517 /* no longer needed, since it's deleted above */
518 /*s_delete_head(toplevel, start);*/
521 #if 0 /* old way of doing this */
522 /*! \todo Finish function documentation!!!
524 * \par Function Description
527 void s_delete_list_fromstart(OBJECT
*start
)
529 OBJECT
*traverse
=NULL
;
530 OBJECT
*o_current
=NULL
;
532 for (traverse
= start
; traverse
; traverse
= o_current
) {
533 o_current
= traverse
->next
;
534 if (traverse
->type
!= OBJ_HEAD
) /* don't delete any head nodes */
537 break; /* found a head node */
543 /*! \todo Finish function documentation!!!
545 * \par Function Description
548 /* deletes everything include the GList */
550 s_delete_object_glist(TOPLEVEL
*toplevel
, GList
*list
)
552 OBJECT
*o_current
=NULL
;
555 ptr
= g_list_last(list
);
557 /* do the delete backwards */
559 o_current
= (OBJECT
*) ptr
->data
;
560 s_delete_object(toplevel
, o_current
);
561 ptr
= g_list_previous (ptr
);
567 /*! \todo Finish function documentation!!!
569 * \par Function Description
570 * This function removes one object pointed by parameter <B>object</B> from
571 * a list as far as it does not represents a head. If so the function returns
572 * NULL. If not it returns the pointer on the object, i.e. the same as the
575 * This function must be followed by a call to #return_tail() on the
576 * list it belonged to as it can be the last object. Therefore the tail
577 * of the list is modified.
579 * \param [in] toplevel The TOPLEVEL object.
583 OBJECT
*s_remove(TOPLEVEL
*toplevel
, OBJECT
*object
)
585 if(object
->type
== OBJ_HEAD
)
588 if(object
->prev
!= NULL
)
589 object
->prev
->next
= object
->next
;
590 if(object
->next
!= NULL
)
591 object
->next
->prev
= object
->prev
;
599 /*! \todo Finish function documentation!!!
601 * \par Function Description
605 void string_toupper(char *in
, char *out
)
612 for (i
= 0 ; i
< len
; i
++) {
613 out
[i
] = toupper(in
[i
]);
617 /*! \todo Finish function documentation!!!
619 * \par Function Description
622 void string_tolower(char *in
, char *out
)
629 for (i
= 0 ; i
< len
; i
++) {
630 out
[i
] = tolower(in
[i
]);
634 /*! \todo Finish function documentation!!!
636 * \par Function Description
639 int colornametovalue(char *string
)
643 int upper
= NUMCOLORS
- 1;
646 struct st_old_colors
*ptr
=NULL
;
652 string_tolower(string
, string
);
653 while (lower
<= upper
) {
654 middle
= (lower
+ upper
) / 2;
656 ptr
= &old_colors
[middle
];
657 val
= strcmp (ptr
->name
, string
);
661 } else if (val
== 0) {
670 /*! \todo Finish function documentation!!!
672 * \par Function Description
675 /* used by o_text_read */
676 char *remove_nl(char *string
)
684 while(string
[i
] != '\0' && string
[i
] != '\n' && string
[i
] != '\r') {
693 /*! \todo Finish function documentation!!!
695 * \par Function Description
698 /* used by o_text_read */
699 char *remove_last_nl(char *string
)
706 len
= strlen(string
);
707 if (string
[len
-1] == '\n' || string
[len
-1] == '\r')
708 string
[len
-1] = '\0';
713 #ifndef HAVE_VSNPRINTF
714 /*! \todo Finish function documentation!!!
716 * \par Function Description
719 void vsnprintf(char *buff
, size_t bufsiz
, const char *fmt
, va_list ap
)
723 vsprintf(tmpbuf
, fmt
, ap
);
727 /*! \todo Finish function documentation!!!
729 * \par Function Description
732 /* this function is called by expand_env_variables */
733 /* changes and returns new string, frees the one that was passed in */
734 char *remove_string(char *string
, int start
, int end
)
745 len
= strlen(string
);
747 return_string
= (char *) g_malloc(sizeof(char)*(len
+1));
750 for (i
= 0 ; i
< len
; i
++) {
751 if (i
>= start
&& i
<= end
) {
753 /* removing characters */
755 return_string
[j
] = string
[i
];
759 return_string
[j
] = '\0';
761 /* free original string */
764 return(return_string
);
767 /*! \todo Finish function documentation!!!
769 * \par Function Description
772 /* this function is called by expand_env_variables */
773 /* changes and returns new string, frees the one that was passed in */
774 char *insert_string(char *string
, int start
, char *insert_string
)
776 char *new_string
=NULL
;
784 /* this should never happen */
785 if (!insert_string
) {
789 /* this should never happen either */
794 len
= strlen(string
);
795 insert_len
= strlen(insert_string
);
796 total_len
= len
+insert_len
;
798 new_string
= (char *) g_malloc(sizeof(char)*(total_len
+1));
801 while (i
< total_len
) {
803 for (j
= 0 ; j
< insert_len
; j
++) {
804 new_string
[i
+j
] = insert_string
[j
];
808 new_string
[i
] = string
[orig_count
];
814 new_string
[i
] = '\0';
816 /* now free the original string */
822 /*! \todo Finish function documentation!!!
824 * \par Function Description
827 /* this function changes and then returns the string which has the
828 * expanded environment variables, frees passed in string */
829 /* Environment variables MUST be in the form ${variable_name} */
830 /* $variable_name is not valid here */
831 char *expand_env_variables(char *string
)
833 char wanted_var
[80]; /* size is hack */
834 char *return_string
=NULL
;
835 char *environment_string
=NULL
;
840 int start_of_variable
= -1;
841 int end_of_variable
= -1;
849 return_string
= string
;
855 for (i
= 0 ; i
< strlen(return_string
); i
++) {
857 switch(return_string
[i
]) {
862 printf("found a $\n");
878 /* ends filling of wanted_var */
886 /* the > 1 bit is so that we don't store the { */
887 if (found_dollar
&& found_lbrac
&& (count
> 1)) {
888 wanted_var
[j
] = return_string
[i
];
889 j
++; /* check for size */
892 /* skip over initial { */
895 if (found_rbrac
&& !found_lbrac
) {
896 wanted_var
[j
] = '\0';
898 printf("variable wanted: _%s_\n", wanted_var
);
899 printf("Between index: %d and %d\n",
905 environment_string
= getenv(wanted_var
);
908 if (environment_string
) {
909 printf("%s = _%s_\n", wanted_var
,
914 return_string
= remove_string(return_string
,
919 printf("removed string: _%s_\n", return_string
);
922 if (environment_string
) {
923 return_string
= insert_string(
931 printf("final string: _%s_\n", return_string
);
939 start_of_variable
= -1;
948 fprintf(stderr
, "Found malformed environment variable (use ${varname})!\n");
951 return(return_string
);