gsymcheck

s_check.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gsymcheck - gEDA Symbol Check 
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00019  * MA 02111-1301 USA.
00020  */
00021 
00022 #include <config.h>
00023 
00024 #include <stdio.h>
00025 #ifdef HAVE_STRING_H
00026 #include <string.h>
00027 #endif
00028 #ifdef HAVE_STRINGS_H
00029 #include <strings.h>
00030 #endif
00031 #ifdef HAVE_UNISTD_H
00032 #include <unistd.h>
00033 #endif
00034 
00035 #include <libgeda/libgeda.h>
00036 
00037 #include "../include/struct.h"
00038 #include "../include/globals.h"
00039 #include "../include/prototype.h"
00040 
00041 int
00042 s_check_all(TOPLEVEL *pr_current)
00043 {
00044   GList *iter;
00045   PAGE *p_current;
00046   int return_status=0;
00047 
00048 
00049   for ( iter = geda_list_get_glist( pr_current->pages );
00050         iter != NULL;
00051         iter = g_list_next( iter ) ) {
00052 
00053     p_current = (PAGE *)iter->data;
00054 
00055     if (s_page_objects (p_current)) {
00056       return_status = return_status +
00057         s_check_symbol (pr_current, p_current,
00058                         s_page_objects (p_current));
00059       if (!quiet_mode) s_log_message("\n");
00060     }
00061   }
00062 
00063   return(return_status);
00064 }
00065 
00066 
00067 int
00068 s_check_symbol (TOPLEVEL *pr_current, PAGE *p_current, const GList *obj_list)
00069 {
00070   SYMCHECK *s_symcheck=NULL;
00071   int errors=0, warnings=0;
00072 
00073   s_symcheck = s_symstruct_init();
00074   
00075   if (!quiet_mode) {
00076     s_log_message("Checking: %s\n", p_current->page_filename);
00077   }
00078   
00079   /* overal symbol structure test */
00080   s_check_symbol_structure (obj_list, s_symcheck);
00081 
00082   /* test all text elements */
00083   s_check_text (obj_list, s_symcheck);
00084 
00085   /* check for graphical attribute */
00086   s_check_graphical (obj_list, s_symcheck);
00087 
00088   /* check for device attribute */
00089   s_check_device (obj_list, s_symcheck);
00090 
00091   /* check for missing attributes */
00092   s_check_missing_attributes (obj_list, s_symcheck);
00093   
00094   /* check for pintype attribute (and multiples) on all pins */
00095   s_check_pintype (obj_list, s_symcheck);
00096     
00097   /* check for pinseq attribute (and multiples) on all pins */
00098   s_check_pinseq (obj_list, s_symcheck);
00099 
00100   /* check for pinnumber attribute (and multiples) on all pins */
00101   s_check_pinnumber (obj_list, s_symcheck);
00102 
00103   /* check for whether all pins are on grid */
00104   s_check_pin_ongrid (obj_list, s_symcheck);
00105 
00106   /* check for slotdef attribute on all pins (if numslots exists) */
00107   s_check_slotdef (obj_list, s_symcheck);
00108 
00109   /* check for old pin#=# attributes */
00110   s_check_oldpin (obj_list, s_symcheck);
00111 
00112   /* check for old pin#=# attributes */
00113   s_check_oldslot (obj_list, s_symcheck);
00114 
00115   /* check for nets or buses within the symbol (completely disallowed) */
00116   s_check_nets_buses (obj_list, s_symcheck);
00117 
00118   /* check for connections with in a symbol (completely disallowed) */
00119   s_check_connections (obj_list, s_symcheck);
00120 
00121   /* now report the info/warnings/errors to the user */
00122   if (!quiet_mode) {
00123     
00124     /* done, now print out the messages */
00125     s_symstruct_print(s_symcheck);
00126     
00127     if (s_symcheck->warning_count > 0) {
00128       s_log_message("%d warnings found ",
00129                     s_symcheck->warning_count);
00130       if (verbose_mode < 2) {
00131         s_log_message("(use -vv to view details)\n");
00132       } else {
00133         s_log_message("\n");
00134       }
00135     }
00136   
00137     if (s_symcheck->error_count == 0) {
00138       s_log_message("No errors found\n");
00139     } else if (s_symcheck->error_count == 1) {
00140       s_log_message("1 ERROR found ");
00141       if (verbose_mode < 1) {
00142         s_log_message("(use -v to view details)\n");
00143       } else {
00144         s_log_message("\n");
00145       }
00146 
00147     } else if (s_symcheck->error_count > 1) {
00148       s_log_message("%d ERRORS found ",
00149                     s_symcheck->error_count);
00150       if (verbose_mode < 1) {
00151         s_log_message("(use -v to view details)\n");
00152       } else {
00153         s_log_message("\n");
00154       }
00155     }
00156   }
00157 
00158   errors = s_symcheck->error_count;
00159   warnings = s_symcheck->warning_count;
00160   s_symstruct_free(s_symcheck);
00161   if (errors) {
00162     return(2);
00163   } else if (warnings) {
00164     return(1);
00165   } else {
00166     return(0);
00167   }
00168 }
00169 
00170 
00171 gboolean 
00172 s_check_list_has_item(char **list , char *item)
00173 {
00174   gint cur;
00175   for (cur = 0; list[cur] != NULL; cur++) {
00176     if (strcmp(item, list[cur]) == 0)
00177       return TRUE;
00178   }
00179   return FALSE;
00180 }
00181 
00182 void
00183 s_check_symbol_structure (const GList *obj_list, SYMCHECK *s_current)
00184 {
00185   const GList *iter;
00186 
00187   gchar *message;
00188   gchar **tokens;
00189 
00190   char *valid_pin_attributes[] = {"pinlabel", "pintype",
00191                   "pinseq", "pinnumber",
00192                   NULL};
00193   char *valid_attributes[] = {"device", "graphical", "description",
00194                   "author", "comment", "numslots",
00195                   "slotdef", "footprint", "documentation",
00196                   "refdes", "slot", "net", "value",
00197                   "symversion", "dist-license", "use-license",
00198                   NULL};
00199   char *obsolete_attributes[] = {"uref", "label", "email", 
00200                  NULL};
00201   char *forbidden_attributes[] = {"type", "name", 
00202                   NULL};
00203   /* pin# ?, slot# ? */
00204   
00205   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
00206     OBJECT *o_current = iter->data;
00207 
00208     if (o_current->type == OBJ_TEXT) {
00209       tokens = g_strsplit(o_current->text->string,"=", 2);
00210       if (tokens[0] != NULL && tokens[1] != NULL) {
00211     if (s_check_list_has_item(forbidden_attributes, tokens[0])) {
00212       message = g_strdup_printf ("Found forbidden %s= attribute: [%s=%s]\n",
00213                      tokens[0], tokens[0], tokens[1]);
00214       s_current->error_messages =
00215         g_list_append(s_current->error_messages, message);
00216       s_current->error_count++;
00217     }
00218     else if (s_check_list_has_item(obsolete_attributes, tokens[0])) {
00219       message = g_strdup_printf ("Found obsolete %s= attribute: [%s=%s]\n",
00220                      tokens[0], tokens[0], tokens[1]);
00221       s_current->warning_messages =
00222         g_list_append(s_current->warning_messages, message);
00223       s_current->warning_count++;
00224     }
00225     else if (s_check_list_has_item(valid_pin_attributes, tokens[0])) {
00226       if (o_current->attached_to == NULL 
00227           || o_current->attached_to->type != OBJ_PIN) {
00228         message = g_strdup_printf ("Found misplaced pin attribute:"
00229                        " [%s=%s]\n", tokens[0], tokens[1]);
00230         s_current->error_messages =
00231           g_list_append(s_current->error_messages, message);
00232         s_current->error_count++;
00233       }
00234     }
00235     else if (!s_check_list_has_item(valid_attributes, tokens[0])) {
00236       message = g_strdup_printf ("Found unknown %s= attribute: [%s=%s]\n",
00237                      tokens[0], tokens[0], tokens[1]);
00238       s_current->warning_messages =
00239         g_list_append(s_current->warning_messages, message);
00240       s_current->warning_count++;
00241     }
00242     else if (o_current->attached_to != NULL) {
00243       message = g_strdup_printf ("Found wrongly attached attribute: "
00244                      "[%s=%s]\n",
00245                      tokens[0], tokens[1]);
00246       s_current->error_messages =
00247         g_list_append(s_current->error_messages, message);
00248       s_current->error_count++;
00249     }     
00250       } else { /* object is not an attribute */
00251         if (o_current->show_name_value != SHOW_NAME_VALUE) {
00252           message = g_strdup_printf ("Found a simple text object with only SHOW_NAME"
00253                                      " or SHOW_VALUE set [%s]\n",
00254                                      o_current->text->string);
00255           s_current->warning_messages =
00256             g_list_append(s_current->warning_messages, message);
00257           s_current->warning_count++;
00258         }
00259       }
00260       g_strfreev(tokens);
00261     }
00262   }
00263 }
00264 
00265 void
00266 s_check_text (const GList *obj_list, SYMCHECK *s_current)
00267 {
00268   const GList *iter;
00269   OBJECT *o_current;
00270   gboolean overbar_started, escape, leave_parser;
00271   char *message;
00272   char *text_string, *ptr;
00273   gunichar current_char;
00274 
00275   for (iter = obj_list; iter != NULL; iter = g_list_next(iter)) {
00276     o_current = iter->data;
00277 
00278     if (o_current->type != OBJ_TEXT)
00279       continue;
00280 
00281     overbar_started = escape = leave_parser = FALSE;
00282     text_string = o_current->text->string;
00283 
00284     for (ptr = text_string;
00285          ptr != NULL && !leave_parser;
00286          ptr = g_utf8_find_next_char (ptr, NULL)) {
00287 
00288       current_char = g_utf8_get_char_validated (ptr, -1);
00289 
00290       /* state machine to interpret the string:
00291        * there are two independant state variables overbar_started and escape.
00292        */
00293       switch (current_char) {
00294       case '\0':
00295         /* end of the string */
00296         leave_parser = TRUE;
00297         break;
00298       case '\\':
00299         if (escape == TRUE) {
00300           escape = FALSE;
00301         } else {
00302           escape = TRUE;
00303         }
00304         break;
00305       case '_':
00306         if (escape == TRUE) {
00307           escape = FALSE;
00308           if (overbar_started == TRUE) {
00309             overbar_started = FALSE;
00310           } else {
00311             overbar_started = TRUE;
00312           }
00313         }
00314         break;
00315       default:
00316         if (escape == TRUE) {
00317           message = g_strdup_printf ("Found text with a '\\' in it: consider"
00318                                      " to escape it with '\\\\' [%s]\n",
00319                                      text_string);
00320           s_current->warning_messages = g_list_append(s_current->warning_messages,
00321                                                       message);
00322           s_current->warning_count++;
00323           escape = FALSE;
00324         }
00325       }
00326     }
00327 
00328     if (escape == TRUE) {
00329       message = g_strdup_printf ("Found text with a trailing '\': consider to "
00330                                  "escape it with '\\\\' [%s]\n",
00331                                  text_string);
00332       s_current->warning_messages = g_list_append(s_current->warning_messages,
00333                                                   message);
00334       s_current->warning_count++;
00335     }
00336 
00337     if (overbar_started == TRUE) {
00338       message = g_strdup_printf ("Found text with unbalanced overbar "
00339                                  "markers '\\_' in it' [%s]\n",
00340                                  text_string);
00341       s_current->warning_messages = g_list_append(s_current->warning_messages,
00342                                                   message);
00343       s_current->warning_count++;
00344     }
00345   }
00346 }
00347 
00348 void
00349 s_check_graphical (const GList *obj_list, SYMCHECK *s_current)
00350 {
00351   char *temp;
00352   
00353   /* look for special graphical tag */
00354   temp = o_attrib_search_floating_attribs_by_name (obj_list, "graphical", 0);
00355 
00356   if (temp) {
00357     s_current->graphical_symbol=TRUE;
00358     g_free(temp);
00359   }
00360 }
00361 
00362 void
00363 s_check_device (const GList *obj_list, SYMCHECK *s_current)
00364 {
00365   char *temp;
00366   char *message;
00367   
00368   /* search for device attribute */
00369   temp = o_attrib_search_floating_attribs_by_name (obj_list, "device", 0);
00370   if (!temp) {
00371     /* did not find device= attribute */
00372     message = g_strdup ("Missing device= attribute\n");
00373     s_current->error_messages = g_list_append(s_current->error_messages,
00374                                       message);
00375     s_current->missing_device_attrib=TRUE;
00376     s_current->error_count++;
00377   } else {
00378     /* found device= attribute */
00379     s_current->missing_device_attrib=FALSE;
00380     s_current->device_attribute = g_strdup (temp);
00381     message = g_strdup_printf ("Found device=%s\n", temp);
00382     s_current->info_messages = g_list_append(s_current->info_messages,
00383                                      message);
00384   }
00385 
00386   /* check for device = none for graphical symbols */
00387   if (temp && s_current->graphical_symbol && (strcmp(temp, "none") == 0)) {
00388     s_current->device_attribute_incorrect=FALSE;
00389     message = g_strdup ("Found graphical symbol, device=none\n");
00390     s_current->info_messages = g_list_append(s_current->info_messages,
00391                                              message);
00392   } else if (s_current->graphical_symbol) {
00393     s_current->device_attribute_incorrect=TRUE;
00394     message = g_strdup ("Found graphical symbol, device= should be set to none\n");
00395     s_current->warning_messages = g_list_append(s_current->warning_messages,
00396                                                 message);
00397     s_current->warning_count++;
00398   } 
00399 
00400   g_free(temp);
00401 }
00402 
00403 
00404 void
00405 s_check_pinseq (const GList *obj_list, SYMCHECK *s_current)
00406 {
00407   char *string;
00408   int found_first=FALSE;
00409   int missing_pinseq_attrib_sum=0;
00410   int multiple_pinseq_attrib_sum=0;
00411   int counter=0;
00412 
00413   GList *found_numbers = NULL;
00414   GList *ptr1 = NULL;
00415   GList *ptr2 = NULL;
00416   const GList *iter;
00417   char *number;
00418   char *message;
00419   
00420   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
00421     OBJECT *o_current = iter->data;
00422     
00423     if (o_current->type == OBJ_PIN)
00424     {
00425       missing_pinseq_attrib_sum = 0;
00426       multiple_pinseq_attrib_sum = 0;
00427       found_first = FALSE;
00428       counter = 0;
00429       
00430       string = o_attrib_search_object_attribs_by_name (o_current, "pinseq",
00431                                                        counter);
00432       if (!string)
00433       {
00434         message = g_strdup ("Missing pinseq= attribute\n");
00435         s_current->error_messages = g_list_append(s_current->error_messages,
00436                                                   message);
00437         missing_pinseq_attrib_sum++;
00438         s_current->error_count++;
00439       }
00440 
00441       while (string)
00442       {
00443         
00444         message = g_strdup_printf ("Found pinseq=%s attribute\n", string); 
00445         s_current->info_messages = g_list_append(s_current->info_messages,
00446                                  message);
00447 
00448         number = g_strdup (string);
00449 
00450         if (strcmp(number, "0") == 0) {
00451           message = g_strdup ("Found pinseq=0 attribute\n");
00452           s_current->error_messages = g_list_append(s_current->error_messages,
00453                                     message);
00454           s_current->error_count++;
00455         }
00456 
00457         if (found_first) {
00458           message = g_strdup_printf (
00459             "Found multiple pinseq=%s attributes on one pin\n",
00460             string);
00461           s_current->error_messages = g_list_append(s_current->error_messages,
00462                                     message);
00463           multiple_pinseq_attrib_sum++;
00464           s_current->error_count++;
00465         }
00466 
00467         g_free(string);
00468         
00469         /* this is the first attribute found */
00470         if (!found_first) {
00471           found_numbers = g_list_append(found_numbers, number);
00472           found_first=TRUE;
00473         } else {
00474           g_free(number);
00475         }
00476         
00477         counter++;
00478         string = o_attrib_search_object_attribs_by_name (o_current, "pinseq",
00479                                                          counter);
00480       }
00481 
00482       s_current->missing_pinseq_attrib += missing_pinseq_attrib_sum;
00483       s_current->multiple_pinseq_attrib += multiple_pinseq_attrib_sum;
00484     }
00485 
00486   }
00487 
00488   ptr1 = found_numbers;
00489   while (ptr1)
00490   {
00491     char *string = (char *) ptr1->data;
00492     int found = 0;
00493     
00494     ptr2 = found_numbers;
00495     while(ptr2 && string)
00496     {
00497       char *current = (char *) ptr2->data;
00498 
00499       if (current && strcmp(string, current) == 0) {
00500         found++;
00501       }
00502       
00503       ptr2 = g_list_next(ptr2);
00504     }
00505 
00506     if (found > 1)
00507     {
00508       message = g_strdup_printf (
00509         "Found duplicate pinseq=%s attribute in the symbol\n",
00510         string);
00511       s_current->error_messages = g_list_append(s_current->error_messages,
00512                                                 message);
00513       s_current->error_count++;
00514       s_current->duplicate_pinseq_attrib++;
00515     }
00516     
00517     ptr1 = g_list_next(ptr1);
00518   }
00519 
00520   ptr1 = found_numbers;
00521   while (ptr1)
00522   {
00523     g_free(ptr1->data);
00524     ptr1 = g_list_next(ptr1);
00525   }
00526   g_list_free(found_numbers);
00527   
00528 }
00529 
00530 
00531 void
00532 s_check_pinnumber (const GList *obj_list, SYMCHECK *s_current)
00533 {
00534   char *string;
00535   int missing_pinnumber_attrib_sum=0;
00536   int multiple_pinnumber_attrib_sum=0;
00537   int counter=0;
00538   int i;
00539 
00540   gchar **net_tokens;
00541   gchar **pin_tokens;
00542   GList *net_numbers = NULL;
00543   GList *pin_numbers = NULL;
00544   GList *cur = NULL;
00545   GList *cur2 = NULL;
00546   const GList *iter;
00547   char *message;
00548   char *net = NULL;
00549     
00550   /* collect all net pins */
00551   for (counter = 0;
00552        (net = o_attrib_search_floating_attribs_by_name (obj_list, "net", counter)) != NULL;
00553        counter++) {
00554     message = g_strdup_printf ("Found net=%s attribute\n", net);
00555     s_current->info_messages = g_list_append(s_current->info_messages,
00556                          message);
00557 
00558     net_tokens = g_strsplit(net,":", -1);
00559     /* length of net tokens have to be 2 */
00560     if (net_tokens[1] == NULL) {
00561       message = g_strdup_printf ("Bad net= attribute [net=%s]\n", net);
00562       s_current->error_messages = g_list_append(s_current->error_messages,
00563                         message);
00564       s_current->error_count++;
00565       g_strfreev(net_tokens);
00566       continue;
00567     } else if (net_tokens[2] != NULL) { /* more than 2 tokens */
00568       message = g_strdup_printf ("Bad net= attribute [net=%s]\n", net);
00569       s_current->error_messages = g_list_append(s_current->error_messages,
00570                         message);
00571       s_current->error_count++;
00572       g_strfreev(net_tokens);
00573       continue;
00574     }
00575 
00576     pin_tokens = g_strsplit(net_tokens[1],",",-1);
00577     
00578     for (i = 0; pin_tokens[i] != NULL; i++) {
00579       net_numbers = g_list_append(net_numbers, g_strdup(pin_tokens[i]));
00580       message = g_strdup_printf ("Found pin number %s in net attribute\n",
00581                                  pin_tokens[i]);
00582       s_current->info_messages = g_list_append(s_current->info_messages,
00583                            message);
00584       s_current->numnetpins++;
00585     }
00586     g_free(net);
00587     g_strfreev(net_tokens);
00588     g_strfreev(pin_tokens);
00589   }
00590   
00591   /* check for duplicate net pin numbers */
00592   net_numbers = g_list_sort(net_numbers, (GCompareFunc)strcmp);
00593 
00594   for (cur = net_numbers;
00595        cur != NULL && g_list_next(cur) != NULL;
00596        cur = g_list_next(cur)) {
00597     if (strcmp((gchar*)cur->data, (gchar*) cur->next->data) == 0) {
00598       message = g_strdup_printf ("Found duplicate pin in net= "
00599                  "attributes [%s]\n", (gchar*) cur->data);
00600       s_current->error_messages = g_list_append(s_current->error_messages,
00601                         message);
00602       s_current->error_count++;
00603     }
00604     if (strcmp((gchar*) cur->data, "0") == 0) {
00605       message = g_strdup ("Found pinnumber 0 in net= attribute\n");
00606       s_current->error_messages = g_list_append(s_current->error_messages,
00607                                                 message);
00608       s_current->error_count++;
00609     }
00610   }
00611 
00612   /* collect all pin numbers */
00613   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
00614     OBJECT *o_current = iter->data;
00615     
00616     if (o_current->type == OBJ_PIN) {
00617       s_current->numpins++;
00618       
00619       missing_pinnumber_attrib_sum = 0;
00620       multiple_pinnumber_attrib_sum = 0;
00621       
00622       for (counter = 0; 
00623        (string = o_attrib_search_object_attribs_by_name (o_current, "pinnumber",
00624                                                          counter)) != NULL;
00625        counter++) {
00626     
00627         message = g_strdup_printf ("Found pinnumber=%s attribute\n", string);
00628         s_current->info_messages = g_list_append(s_current->info_messages,
00629                                  message);
00630 
00631     if (counter == 0) { /* collect the first appearance */
00632       pin_numbers = g_list_append(pin_numbers, string);
00633     }
00634         if (counter >= 1) {
00635           message = g_strdup_printf ("Found multiple pinnumber=%s attributes"
00636                      " on one pin\n", string);
00637           s_current->error_messages = g_list_append(s_current->error_messages,
00638                                     message);
00639           multiple_pinnumber_attrib_sum++;
00640           s_current->error_count++;
00641       g_free(string); 
00642         }
00643       }
00644        
00645       if (counter == 0) {
00646         message = g_strdup ("Missing pinnumber= attribute\n");
00647         s_current->error_messages = g_list_append(s_current->error_messages,
00648                                                   message);
00649         missing_pinnumber_attrib_sum++;
00650         s_current->error_count++;
00651       }
00652 
00653       s_current->missing_pinnumber_attrib += missing_pinnumber_attrib_sum;
00654       s_current->multiple_pinnumber_attrib += multiple_pinnumber_attrib_sum;
00655     }
00656   }
00657 
00658   /* check for duplicate pinlabel numbers */
00659   pin_numbers = g_list_sort(pin_numbers, (GCompareFunc)strcmp);
00660   for (cur = pin_numbers;
00661        cur != NULL && g_list_next(cur) != NULL;
00662        cur = g_list_next(cur)) { 
00663     if (strcmp((gchar*)cur->data, (gchar*) cur->next->data) == 0) {
00664       message = g_strdup_printf ("Found duplicate pinnumber=%s attribute "
00665                  "in the symbol\n", (gchar*) cur->data);
00666       s_current->error_messages = g_list_append(s_current->error_messages,
00667                         message);
00668       s_current->error_count++;
00669       s_current->duplicate_pinnumber_attrib++;
00670     }
00671     if (strcmp((gchar*) cur->data, "0") == 0) {
00672       message = g_strdup ("Found pinnumber=0 attribute\n");
00673       s_current->error_messages = g_list_append(s_current->error_messages,
00674                         message);
00675       s_current->error_count++;
00676     }
00677   }
00678 
00679   /* Check for all pins that are in both lists and print a warning.
00680      Sometimes this is useful and sometimes it's an error. */
00681 
00682   cur = net_numbers;
00683   cur2 = pin_numbers;
00684 
00685   while (cur != NULL && cur2 != NULL) {
00686     
00687     i = strcmp((gchar*)cur->data, (gchar*)cur2->data);
00688 
00689     if (i == 0) {
00690       message = g_strdup_printf ("Found the same number in a pinnumber "
00691                  "attribute and in a net attribute [%s]\n",
00692                  (gchar*) cur->data);
00693       s_current->warning_messages = g_list_append(s_current->warning_messages,
00694                           message);
00695       s_current->warning_count++;
00696       cur = g_list_next(cur);
00697 
00698     } else if ( i > 0 ) {
00699       cur2 = g_list_next(cur2);
00700 
00701     } else { /* i < 0 */
00702       cur = g_list_next(cur);
00703     }
00704   }
00705 
00706   /* FIXME: this is not correct if a pinnumber is defined as pinnumber and
00707      inside a net. We have to calculate the union set */
00708   message = g_strdup_printf ("Found %d pins inside symbol\n", 
00709                  s_current->numpins + s_current->numnetpins);
00710   s_current->info_messages = g_list_append(s_current->info_messages,
00711                                            message);
00712 
00713   g_list_foreach(pin_numbers, (GFunc) g_free, NULL);
00714   g_list_free(pin_numbers);
00715   g_list_foreach(net_numbers, (GFunc) g_free, NULL);
00716   g_list_free(net_numbers);
00717 }
00718 
00719 void
00720 s_check_pin_ongrid (const GList *obj_list, SYMCHECK *s_current)
00721 {
00722   int x1, x2, y1, y2;
00723   const GList *iter;
00724   char *message;
00725 
00726   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
00727     OBJECT *o_current = iter->data;
00728 
00729     if (o_current->type == OBJ_PIN) {
00730       x1 = o_current->line->x[0];
00731       y1 = o_current->line->y[0];
00732       x2 = o_current->line->x[1];
00733       y2 = o_current->line->y[1];
00734       
00735       if (x1 % 100 != 0 || y1 % 100 != 0) {
00736     message = g_strdup_printf("Found offgrid pin at location"
00737                   " (x1=%d,y1=%d)\n", x1, y1);
00738     /* error if it is the whichend, warning if not */
00739     if (o_current->whichend == 0) {
00740       s_current->error_messages = g_list_append(s_current->error_messages,
00741                             message);
00742       s_current->error_count++;
00743     }
00744     else {
00745       s_current->warning_messages = g_list_append(s_current->warning_messages,
00746                               message);
00747       s_current->warning_count++;
00748     }
00749       }
00750       if (x2 % 100 != 0 || y2 % 100 != 0) {
00751     message = g_strdup_printf("Found offgrid pin at location"
00752                   " (x2=%d,y2=%d)\n", x2, y2);
00753     /* error when whichend, warning if not */
00754     if (o_current-> whichend != 0) {
00755       s_current->error_messages = g_list_append(s_current->error_messages,
00756                             message);
00757       s_current->error_count++;
00758     }
00759     else {
00760       s_current->warning_messages = g_list_append(s_current->warning_messages,
00761                               message);
00762       s_current->warning_count++;
00763     }
00764       }
00765     }
00766   }
00767 }
00768 
00769 
00770 void
00771 s_check_slotdef (const GList *obj_list, SYMCHECK *s_current)
00772 {
00773   char* value = NULL;
00774   char* slotdef = NULL;
00775   char* slotnum = NULL;
00776   char* pins = NULL;
00777   char* temp = NULL;
00778   char numslots_str[10];
00779   int slot;
00780   int i,j;
00781   char *message;
00782   char tempstr1[10];
00783   /*  pinlist will store the pin definitions for each slot */
00784   /* example: pinlist[0] = 3,2,8,4,1 ; pinlist[1] = 5,6,8,4,7 */
00785   char** pinlist = NULL;
00786   int n,m;
00787   char* pin;
00788   char* cmp;
00789   int match;
00790   gboolean error_parsing = FALSE;
00791   int errors_found = 0;
00792 
00793   /* look for numslots to see if this symbol has slotting info */
00794   value = o_attrib_search_floating_attribs_by_name (obj_list, "numslots", 0);
00795 
00796   if (!value) {
00797     message = g_strdup ("Did not find numslots= attribute, not checking slotting\n");
00798     s_current->warning_messages = g_list_append(s_current->warning_messages,
00799                                                 message);
00800     s_current->warning_count++;
00801     message = g_strdup ("If this symbol does not need slotting, set numslots to zero (numslots=0)\n");
00802     s_current->info_messages = g_list_append(s_current->info_messages,
00803                                              message);
00804     return;
00805   }
00806 
00807   s_current->numslots=atoi(value);
00808   sprintf(numslots_str, "%d", s_current->numslots);
00809   g_free(value);
00810 
00811   message = g_strdup_printf ("Found numslots=%s attribute\n", numslots_str);
00812   s_current->info_messages = g_list_append(s_current->info_messages,
00813                            message);
00814 
00815   if (s_current->numslots == 0) {
00816     message = g_strdup ("numslots set to zero, symbol does not have slots\n");
00817     s_current->info_messages = g_list_append(s_current->info_messages,
00818                                              message);
00819     return;
00820   }
00821   
00822 
00823   pinlist = (char**)g_malloc0(sizeof(*pinlist) * s_current->numslots);
00824 
00825   i = 0;
00826   /* get the slotdef attribute */
00827   slotdef = o_attrib_search_floating_attribs_by_name (obj_list, "slotdef", 0);
00828   while ((slotdef != NULL) && (!error_parsing))
00829   {
00830 
00831     if (i > s_current->numslots-1) {
00832 
00833       sprintf(tempstr1, "%d", i+1); /* i starts at zero */
00834       message = g_strdup_printf (
00835         "Found %s slotdef= attributes.  Expecting %s slotdef= attributes\n",
00836         tempstr1, numslots_str); 
00837       s_current->error_messages = g_list_append(s_current->error_messages,
00838                                                 message);
00839 
00840       s_current->error_count++;
00841       s_current->slotting_errors++;
00842     }
00843     
00844     message = g_strdup_printf ("Found slotdef=%s attribute\n", slotdef);
00845     s_current->info_messages = g_list_append(s_current->info_messages,
00846                              message);
00847 
00848     slotnum = u_basic_breakup_string(slotdef, ':', 0);
00849     if (!slotnum)
00850     {
00851       message = g_strdup_printf (
00852         "Invalid slotdef=%s attributes, not continuing\n",
00853         slotdef);
00854       s_current->error_messages = g_list_append(s_current->error_messages,
00855                                                 message);
00856       s_current->error_count++;
00857       s_current->slotting_errors++;
00858       error_parsing = TRUE;
00859       continue;
00860     }
00861 
00862     if (strcmp(slotnum, "0") == 0) {
00863       message = g_strdup_printf (
00864         "Found a zero slot in slotdef=%s\n",
00865         slotdef);
00866       s_current->error_messages = g_list_append(s_current->error_messages,
00867                                                 message);
00868       s_current->error_count++;
00869     }
00870   
00871     slot = atoi(slotnum);
00872     g_free(slotnum);
00873 
00874     /* make sure that the slot # is less than the number of slots */
00875     if (slot > s_current->numslots) {
00876       sprintf(tempstr1, "%d", slot);
00877       message = g_strdup_printf (
00878         "Slot %s is larger then the maximum number (%s) of slots\n",
00879         tempstr1, numslots_str);
00880       s_current->error_messages = g_list_append(s_current->error_messages,
00881                                 message);
00882 
00883       s_current->error_count++;
00884       s_current->slotting_errors++;
00885     }
00886 
00887     /* skip over the : */
00888     pins = strchr(slotdef, ':');
00889     if (!pins) {
00890       message = g_strdup_printf (
00891         "Invalid slotdef=%s attributes, not continuing\n",
00892         slotdef);
00893       s_current->error_messages = g_list_append(s_current->error_messages,
00894                                                 message);
00895       s_current->error_count++;
00896       s_current->slotting_errors++;
00897       error_parsing = TRUE;
00898       continue;
00899     }
00900     pins++;  /* get past that : */
00901     if (!pins) {
00902       message = g_strdup_printf (
00903         "Invalid slotdef=%s attributes, not continuing\n",
00904         slotdef);
00905       s_current->error_messages = g_list_append(s_current->error_messages,
00906                                                 message);
00907       s_current->error_count++;
00908       s_current->slotting_errors++;
00909       error_parsing = TRUE;
00910       continue;
00911     }
00912 
00913     if (*pins == '\0') {
00914       message = g_strdup_printf (
00915         "Invalid slotdef=%s attributes, not continuing\n",
00916         slotdef);
00917       s_current->error_messages = g_list_append(s_current->error_messages,
00918                                                 message);
00919       s_current->error_count++;
00920       s_current->slotting_errors++;
00921       error_parsing = TRUE;
00922       continue;
00923     }
00924 
00925     if ((slot > 0) && (slot <= s_current->numslots)) {
00926       if (pinlist[slot-1]) {
00927         message = g_strdup_printf ("Duplicate slot number in slotdef=%s\n",
00928                    slotdef);
00929         s_current->error_messages = g_list_append(s_current->error_messages,
00930                                       message);
00931         s_current->error_count++;
00932         s_current->slotting_errors++;
00933       } else {
00934     pinlist[slot-1] = g_strdup_printf(",%s,", pins);
00935       }
00936     }
00937     
00938     j = 0;
00939     do {
00940       if (temp) {
00941         g_free(temp);
00942         temp = NULL;
00943       }
00944         
00945       temp = u_basic_breakup_string(pins, ',', j);
00946 
00947       if (!temp && j < s_current->numpins) {
00948         message = g_strdup_printf (
00949           "Not enough pins in slotdef=%s\n",
00950           slotdef);
00951         s_current->error_messages = g_list_append(s_current->error_messages,
00952                                       message);
00953         s_current->error_count++;
00954         s_current->slotting_errors++;
00955         break;
00956       }
00957 
00958       if (j > s_current->numpins) {
00959         message = g_strdup_printf (
00960           "Too many pins in slotdef=%s\n",
00961           slotdef);
00962         s_current->error_messages = g_list_append(s_current->error_messages,
00963                                       message);
00964         s_current->error_count++;
00965         s_current->slotting_errors++;
00966         g_free(temp);
00967         temp = NULL;
00968         break;
00969       }
00970       
00971       if (temp && strcmp(temp, "0") == 0) {
00972         message = g_strdup_printf (
00973           "Found a zero pin in slotdef=%s\n",
00974           slotdef);
00975         s_current->error_messages = g_list_append(s_current->error_messages,
00976                                                   message);
00977         s_current->error_count++;
00978       }
00979      
00980       j++;
00981     } while (temp);
00982 
00983     g_free(temp);
00984 
00985     g_free(slotdef);
00986     slotdef = NULL;
00987    
00988     i++;
00989     slotdef = o_attrib_search_floating_attribs_by_name (obj_list, "slotdef", i);
00990   }
00991 
00992   if (!slotdef && i < s_current->numslots) {
00993     message = g_strdup_printf (
00994       "Missing slotdef= (there should be %s slotdef= attributes)\n",
00995       numslots_str);
00996     s_current->error_messages = g_list_append(s_current->error_messages,
00997                                   message);
00998     s_current->error_count++;
00999     s_current->slotting_errors++;
01000   } else {
01001 
01002     /* Validate that pinslist does not contain a null entry.  If any entry */
01003     /* is null, that means the slotdef= attribute was malformed to start */
01004     /* with. */
01005     for (i = 0; i < s_current->numslots; i++) { 
01006       if (pinlist[i] == NULL) {
01007         errors_found++;
01008       }
01009     }
01010 
01011     if (errors_found) {
01012       message = g_strdup_printf(
01013                "Malformed slotdef= (the format is #:#,#,#,...)\n");
01014       s_current->error_messages = g_list_append(s_current->error_messages,
01015                                                 message);
01016       s_current->error_count++;
01017       s_current->slotting_errors++;
01018     } else { 
01019       /* Now compare each pin with the rest */
01020       s_current->numslotpins = 0;
01021       for (i = 0; i < s_current->numslots; i++) {
01022         for (n = 1; n <= s_current->numpins; n++) {
01023           /* Get the number of one pin */
01024           pin = u_basic_breakup_string(pinlist[i], ',', n);
01025           if (pin && *pin) {
01026             match = FALSE;
01027             for (j = i - 1; j >= 0 && !match; j--) {
01028               for (m = 1; m <= s_current->numpins && !match; m++) {
01029                 /* Get the number of the other pin */
01030                 cmp = u_basic_breakup_string(pinlist[j], ',', m);
01031                 if (cmp && *cmp) {
01032                   match = (0 == strcmp (pin, cmp));
01033                   g_free(cmp);
01034                 }
01035               }
01036             }
01037             if (!match) {
01038               /* If they don't match, then increase the number of pins */
01039               s_current->numslotpins++;
01040             }
01041             g_free(pin);
01042           }
01043         }
01044       }
01045       message = g_strdup_printf ("Found %d distinct pins in slots\n", 
01046                                  s_current->numslotpins);
01047       s_current->info_messages = g_list_append(s_current->info_messages,
01048                                                message);
01049     }
01050   }
01051   
01052   g_free(slotdef);
01053   if (pinlist) {
01054     /* Free the pinlist */
01055     for (i = 0; i < s_current->numslots; i++) {
01056       g_free(pinlist[i]);
01057     }
01058     g_free(pinlist);
01059   }
01060  
01061   return;
01062 }
01063 
01064 
01065 void
01066 s_check_oldpin (const GList *obj_list, SYMCHECK *s_current)
01067 {
01068   const GList *iter;
01069   char *ptr;
01070   int found_old = FALSE;
01071   int number_counter = 0;
01072   char *message;
01073 
01074   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
01075     OBJECT *o_current = iter->data;
01076 
01077     if (o_current->type == OBJ_TEXT)
01078     {
01079       if (strstr(o_current->text->string, "pin"))
01080       {
01081         /* skip over "pin" */
01082         ptr = o_current->text->string + 3;
01083 
01084         found_old = FALSE;
01085         number_counter = 0;
01086         while (ptr && *ptr > '0' && *ptr < '9')
01087         {
01088           number_counter++;
01089           ptr++;
01090         }
01091 
01092         if (ptr && *ptr == '=')
01093         {
01094           found_old++;
01095         }
01096 
01097         if (!ptr)
01098           continue;
01099 
01100         /* found no numbers inbetween pin and = */
01101         if (number_counter == 0)
01102           continue;
01103         
01104         /* skip over = char */
01105         ptr++;
01106 
01107         while (ptr && *ptr > '0' && *ptr < '9')
01108         {
01109           ptr++;
01110         }
01111 
01112         if (*ptr == '\0')
01113         {
01114           found_old++;
01115         } 
01116 
01117         /* 2 matches -> number found after pin and only numbers after = sign */
01118         if (found_old == 2)
01119         {
01120           message = g_strdup_printf (
01121             "Found old pin#=# attribute: %s\n",
01122             o_current->text->string);
01123           s_current->error_messages = g_list_append(s_current->error_messages,
01124                                                     message);
01125 
01126           s_current->found_oldpin_attrib += found_old;
01127           s_current->error_count++;
01128 
01129         }
01130       }
01131     }
01132   }
01133   
01134 }
01135 
01136 
01137 void
01138 s_check_oldslot (const GList *obj_list, SYMCHECK *s_current)
01139 {
01140   const GList *iter;
01141   char *ptr;
01142   int found_old = FALSE;
01143   int number_counter = 0;
01144   char *message;
01145   
01146   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
01147     OBJECT *o_current = iter->data;
01148 
01149     if (o_current->type == OBJ_TEXT)
01150     {
01151       if (strstr(o_current->text->string, "slot"))
01152       {
01153         /* skip over "slot" */
01154         ptr = o_current->text->string + 4;
01155 
01156         found_old = FALSE;
01157         number_counter = 0;
01158         while (ptr && *ptr > '0' && *ptr < '9')
01159         {
01160           number_counter++;
01161           ptr++;
01162         }
01163 
01164         if (ptr && *ptr == '=')
01165         {
01166           found_old++;
01167         }
01168 
01169         if (!ptr)
01170           continue;
01171 
01172         /* found no numbers inbetween pin and = */
01173         if (number_counter == 0)
01174           continue;
01175         
01176         /* skip over = char */
01177         ptr++;
01178 
01179         while ((ptr && (*ptr > '0') && (*ptr < '9')) || (*ptr == ','))
01180         {
01181           ptr++;
01182         }
01183 
01184         if (*ptr == '\0')
01185         {
01186           found_old++;
01187         }
01188 
01189         /* 2 matches -> number found after slot and only numbers after = */
01190         if (found_old == 2)
01191         {
01192           message = g_strdup_printf (
01193             "Found old slot#=# attribute: %s\n",
01194             o_current->text->string);
01195           s_current->error_messages = g_list_append(s_current->error_messages,
01196                                                     message);
01197           s_current->found_oldslot_attrib += found_old;
01198           s_current->error_count++;
01199 
01200         }
01201       }
01202     }
01203   }
01204 }
01205 
01206 
01207 void
01208 s_check_nets_buses (const GList *obj_list, SYMCHECK *s_current)
01209 {
01210   const GList *iter;
01211   char *message;
01212 
01213   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
01214     OBJECT *o_current = iter->data;
01215 
01216     if (o_current->type == OBJ_NET)
01217     {
01218       message = 
01219         g_strdup ("Found a net inside a symbol\n");
01220       s_current->error_messages = g_list_append(s_current->error_messages,
01221                                                 message);
01222       s_current->found_net++;
01223       s_current->error_count++;
01224     }
01225 
01226     if (o_current->type == OBJ_BUS)
01227     {
01228       message = 
01229         g_strdup ("Found a bus inside a symbol\n");
01230       s_current->error_messages = g_list_append(s_current->error_messages,
01231                                                 message);
01232       s_current->found_bus++;
01233       s_current->error_count++;
01234     }
01235 
01236   }
01237 }
01238 
01239 void
01240 s_check_connections (const GList *obj_list, SYMCHECK *s_current)
01241 {
01242   const GList *iter;
01243   char *message;
01244 
01245   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
01246     OBJECT *o_current = iter->data;
01247 
01248     if (o_current->conn_list) {
01249       message = 
01250         g_strdup ("Found a connection inside a symbol\n");
01251       s_current->error_messages = g_list_append(s_current->error_messages,
01252                                                 message);
01253       s_current->found_connection++;
01254       s_current->error_count++;
01255     }
01256   }
01257 }
01258 
01259 void
01260 s_check_missing_attribute(OBJECT *object, char *attribute, SYMCHECK *s_current)
01261 {
01262   char *string;
01263   int found_first=FALSE;
01264   int counter=0;
01265   char *message;
01266 
01267   if (!attribute) {
01268     return;
01269   }
01270 
01271   string = o_attrib_search_object_attribs_by_name (object, attribute, counter);
01272   if (!string)
01273   {
01274     message = g_strdup_printf (
01275       "Missing %s= attribute\n",
01276       attribute);
01277     s_current->warning_messages = g_list_append(s_current->warning_messages,
01278                                                 message);
01279     s_current->warning_count++;
01280   }
01281 
01282   while (string)
01283   {
01284 
01285     if (found_first) {
01286       message = g_strdup_printf (
01287         "Found multiple %s=%s attributes on one pin\n",
01288         attribute, string);
01289       s_current->error_messages = g_list_append(s_current->error_messages,
01290                                                 message);
01291       s_current->error_count++;
01292     }
01293         
01294     /* this is the first attribute found */
01295     if (!found_first) {
01296 
01297       message = g_strdup_printf (
01298         "Found %s=%s attribute\n",
01299         attribute, string);
01300       s_current->info_messages = g_list_append(s_current->info_messages,
01301                                                message);
01302       found_first=TRUE;
01303     }
01304 
01305     g_free(string);
01306 
01307     counter++;
01308     string = o_attrib_search_object_attribs_by_name (object, attribute, counter);
01309   }
01310 
01311 }
01312 
01313 void
01314 s_check_missing_attributes (const GList *obj_list, SYMCHECK *s_current)
01315 {
01316   const GList *iter;
01317   char *message;
01318 
01319   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
01320     OBJECT *o_current = iter->data;
01321 
01322     if (o_current->type == OBJ_PIN)
01323     {
01324       s_check_missing_attribute(o_current, "pinlabel", s_current);
01325       s_check_missing_attribute(o_current, "pintype", s_current);
01326     }
01327 
01328     if (o_current->type == OBJ_TEXT)
01329     {
01330       if (strstr(o_current->text->string, "footprint=")) {
01331         message = g_strdup_printf (
01332           "Found %s attribute\n",
01333           o_current->text->string);
01334         s_current->info_messages = g_list_append(s_current->info_messages,
01335                                                message);
01336         s_current->found_footprint++;
01337       }
01338 
01339       if (strstr(o_current->text->string, "refdes=")) {
01340         message = g_strdup_printf (
01341           "Found %s attribute\n",
01342           o_current->text->string);
01343         s_current->info_messages = g_list_append(s_current->info_messages,
01344                                                message);
01345         s_current->found_refdes++;
01346       }
01347 
01348     }
01349   }
01350 
01351   if (s_current->found_footprint == 0) {
01352     message = g_strdup ("Missing footprint= attribute\n");
01353     s_current->warning_messages = g_list_append(s_current->warning_messages,
01354                                                 message);
01355     s_current->warning_count++;
01356   }
01357 
01358     if (s_current->found_footprint > 1) {
01359     message = g_strdup ("Multiple footprint= attributes found\n");
01360     s_current->error_messages = g_list_append(s_current->error_messages,
01361                                                 message);
01362     s_current->error_count++;
01363 
01364   }
01365   
01366   if (s_current->found_refdes == 0) {
01367     message = g_strdup ("Missing refdes= attribute\n");
01368     s_current->warning_messages = g_list_append(s_current->warning_messages,
01369                                                 message);
01370     s_current->warning_count++;
01371 
01372   }
01373 
01374   if (s_current->found_refdes > 1) {
01375     message = g_strdup ("Multiple refdes= attributes found\n");
01376     s_current->error_messages = g_list_append(s_current->error_messages,
01377                                                 message);
01378     s_current->error_count++;
01379   }
01380   
01381 }
01382 
01383 void s_check_pintype (const GList *obj_list, SYMCHECK *s_current)
01384 {
01385   const GList *iter;
01386   int counter=0;
01387   char *pintype;
01388   char *message;
01389   char *pintypes[] = {"in", "out", "io", "oc", "oe",
01390               "pas", "tp", "tri", "clk", "pwr",
01391               NULL};
01392   
01393   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
01394     OBJECT *o_current = iter->data;
01395 
01396     if (o_current->type == OBJ_PIN) {
01397 
01398       for (counter = 0;
01399            (pintype = o_attrib_search_object_attribs_by_name (o_current, "pintype",
01400                                                               counter)) != NULL;
01401            counter++) {
01402 
01403         message = g_strdup_printf("Found pintype=%s attribute\n", pintype);
01404         s_current->info_messages = g_list_append(s_current->info_messages,
01405                                  message);
01406 
01407     if ( ! s_check_list_has_item(pintypes, pintype)) {
01408       message = g_strdup_printf ("Invalid pintype=%s attribute\n", pintype);
01409       s_current->error_messages = g_list_append(s_current->error_messages, 
01410                             message); 
01411       s_current->error_count++; 
01412     }
01413 
01414         g_free(pintype);
01415       }
01416     }
01417   }
01418 }
 All Data Structures Files Functions Variables Typedefs Defines