increase the resolution for exported RS274X files from 2.3 to 3.4 format
[geda-gerbv.git] / src / gerb_stats.c
blob773cd626c7817a2c42d5b1579712f49056a928a3
1 /*
2 * gEDA - GNU Electronic Design Automation
3 * gerbv_stats.c -- a part of gerbv.
5 * Copyright (C) Stuart Brorson (sdb@cloud9.net)
7 * $Id$
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
24 /** \file gerb_stats.c
25 \brief Statistics generating functions for RS274X files
26 \ingroup libgerbv
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include <stdlib.h>
34 #include <string.h>
35 #include <glib.h>
36 #include <math.h>
38 #include "gerbv.h"
39 #include "gerb_stats.h"
42 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
43 #define dprintf if(DEBUG) printf
45 /* ------------------------------------------------------- */
46 /** Allocates a new gerbv_stats structure
47 @return gerbv_stats pointer on success, NULL on ERROR */
48 gerbv_stats_t *
49 gerbv_stats_new(void) {
51 gerbv_stats_t *stats;
52 gerbv_error_list_t *error_list;
53 gerbv_aperture_list_t *aperture_list;
54 gerbv_aperture_list_t *D_code_list;
56 /* Malloc space for new stats struct. Return NULL if error. */
57 if ((stats = (gerbv_stats_t *)g_malloc(sizeof(gerbv_stats_t))) == NULL) {
58 return NULL;
61 /* Set new stats struct to zero */
62 memset((void *)stats, 0, sizeof(gerbv_stats_t));
64 /* Initialize error list */
65 error_list = gerbv_stats_new_error_list();
66 if (error_list == NULL)
67 GERB_FATAL_ERROR("malloc error_list failed\n");
68 stats->error_list = (gerbv_error_list_t *) error_list;
70 /* Initialize aperture list */
71 aperture_list = gerbv_stats_new_aperture_list();
72 if (aperture_list == NULL)
73 GERB_FATAL_ERROR("malloc aperture_list failed\n");
74 stats->aperture_list = (gerbv_aperture_list_t *) aperture_list;
76 /* Initialize D codes list */
77 D_code_list = gerbv_stats_new_aperture_list();
78 if (D_code_list == NULL)
79 GERB_FATAL_ERROR("malloc D_code_list failed\n");
80 stats->D_code_list = (gerbv_aperture_list_t *) D_code_list;
82 return stats;
85 void
86 gerbv_destroy_error_list (gerbv_error_list_t *errorList) {
87 gerbv_error_list_t *nextError=errorList,*tempError;
89 while (nextError) {
90 tempError = nextError->next;
91 g_free (nextError->error_text);
92 g_free (nextError);
93 nextError = tempError;
97 void
98 gerbv_destroy_aperture_list (gerbv_aperture_list_t *apertureList) {
99 gerbv_aperture_list_t *nextAperture=apertureList,*tempAperture;
101 while (nextAperture) {
102 tempAperture = nextAperture->next;
103 g_free (nextAperture);
104 nextAperture = tempAperture;
108 /* ------------------------------------------------------- */
109 void
110 gerbv_stats_destroy(gerbv_stats_t *stats) {
111 if (stats == NULL)
112 return;
113 gerbv_destroy_error_list (stats->error_list);
114 gerbv_destroy_aperture_list (stats->aperture_list);
115 gerbv_destroy_aperture_list (stats->D_code_list);
116 g_free (stats);
120 /* ------------------------------------------------------- */
121 /*! This fcn is called with a two gerbv_stats_t structs:
122 * accum_stats and input_stats. Accum_stats holds
123 * a list of stats accumulated for
124 * all layers. This will be reported in the report window.
125 * Input_stats holds a list of the stats for one particular layer
126 * to be added to the accumulated list. */
127 void
128 gerbv_stats_add_layer(gerbv_stats_t *accum_stats,
129 gerbv_stats_t *input_stats,
130 int this_layer) {
132 dprintf("---> Entering gerbv_stats_add_layer ... \n");
134 gerbv_error_list_t *error;
135 gerbv_aperture_list_t *aperture;
136 gerbv_aperture_list_t *D_code;
138 accum_stats->layer_count++;
139 accum_stats->G0 += input_stats->G0;
140 accum_stats->G1 += input_stats->G1;
141 accum_stats->G2 += input_stats->G2;
142 accum_stats->G3 += input_stats->G3;
143 accum_stats->G4 += input_stats->G4;
144 accum_stats->G10 += input_stats->G10;
145 accum_stats->G11 += input_stats->G11;
146 accum_stats->G12 += input_stats->G12;
147 accum_stats->G36 += input_stats->G36;
148 accum_stats->G37 += input_stats->G37;
149 accum_stats->G54 += input_stats->G54;
150 accum_stats->G55 += input_stats->G55;
151 accum_stats->G70 += input_stats->G70;
152 accum_stats->G71 += input_stats->G71;
153 accum_stats->G74 += input_stats->G74;
154 accum_stats->G75 += input_stats->G75;
155 accum_stats->G90 += input_stats->G90;
156 accum_stats->G91 += input_stats->G91;
157 accum_stats->G_unknown += input_stats->G_unknown;
159 accum_stats->D1 += input_stats->D1;
160 accum_stats->D2 += input_stats->D2;
161 accum_stats->D3 += input_stats->D3;
162 /* Create list of user-defined D codes from aperture list */
163 for (D_code = input_stats->D_code_list;
164 D_code != NULL;
165 D_code = D_code->next) {
166 if (D_code->number != -1) {
167 dprintf(" .... In gerbv_stats_add_layer, D code section, adding number = %d to accum_stats D list ...\n",
168 D_code->number);
169 gerbv_stats_add_to_D_list(accum_stats->D_code_list,
170 D_code->number);
171 dprintf(" .... In gerbv_stats_add_layer, D code section, calling increment_D_count with count %d ...\n",
172 D_code->count);
173 gerbv_stats_increment_D_list_count(accum_stats->D_code_list,
174 D_code->number,
175 D_code->count,
176 accum_stats->error_list);
179 accum_stats->D_unknown += input_stats->D_unknown;
180 accum_stats->D_error += input_stats->D_error;
182 accum_stats->M0 += input_stats->M0;
183 accum_stats->M1 += input_stats->M1;
184 accum_stats->M2 += input_stats->M2;
185 accum_stats->M_unknown += input_stats->M_unknown;
187 accum_stats->X += input_stats->X;
188 accum_stats->Y += input_stats->Y;
189 accum_stats->I += input_stats->I;
190 accum_stats->J += input_stats->J;
192 accum_stats->star += input_stats->star;
193 accum_stats->unknown += input_stats->unknown;
195 /* ==== Now deal with the error list ==== */
196 for (error = input_stats->error_list;
197 error != NULL;
198 error = error->next) {
199 if (error->error_text != NULL) {
200 gerbv_stats_add_error(accum_stats->error_list,
201 this_layer,
202 error->error_text,
203 error->type);
207 /* ==== Now deal with the aperture list ==== */
208 for (aperture = input_stats->aperture_list;
209 aperture != NULL;
210 aperture = aperture->next) {
211 if (aperture->number != -1) {
212 gerbv_stats_add_aperture(accum_stats->aperture_list,
213 this_layer,
214 aperture->number,
215 aperture->type,
216 aperture->parameter);
220 dprintf("<---- .... Leaving gerbv_stats_add_layer. \n");
222 return;
225 /* ------------------------------------------------------- */
226 gerbv_error_list_t *
227 gerbv_stats_new_error_list() {
228 gerbv_error_list_t *error_list;
230 /* Malloc space for new error_list struct. Return NULL if error. */
231 if ((error_list = (gerbv_error_list_t *)g_malloc(sizeof(gerbv_error_list_t))) == NULL) {
232 return NULL;
235 error_list->layer = -1;
236 error_list->error_text = NULL;
237 error_list->next = NULL;
238 return error_list;
242 /* ------------------------------------------------------- */
243 void
244 gerbv_stats_add_error(gerbv_error_list_t *error_list_in,
245 int layer, const char *error_text,
246 gerbv_message_type_t type) {
248 gerbv_error_list_t *error_list_new;
249 gerbv_error_list_t *error_last = NULL;
250 gerbv_error_list_t *error;
252 /* Replace embedded error messages */
253 switch (type) {
254 case GERBV_MESSAGE_FATAL:
255 GERB_FATAL_ERROR("%s",error_text);
256 break;
257 case GERBV_MESSAGE_ERROR:
258 GERB_COMPILE_ERROR("%s",error_text);
259 break;
260 case GERBV_MESSAGE_WARNING:
261 GERB_COMPILE_WARNING("%s",error_text);
262 break;
263 case GERBV_MESSAGE_NOTE:
264 break;
267 /* First handle case where this is the first list element */
268 if (error_list_in->error_text == NULL) {
269 error_list_in->layer = layer;
270 error_list_in->error_text = g_strdup_printf("%s", error_text);
271 error_list_in->type = type;
272 error_list_in->next = NULL;
273 return;
276 /* Next check to see if this error is already in the list */
277 for(error = error_list_in; error != NULL; error = error->next) {
278 if ((strcmp(error->error_text, error_text) == 0) &&
279 (error->layer == layer) ) {
280 return; /* This error text is already in the error list */
282 error_last = error; /* point to last element in error list */
284 /* This error text is unique. Therefore, add it to the list */
286 /* Now malloc space for new error list element */
287 error_list_new = (gerbv_error_list_t *) g_malloc(sizeof(gerbv_error_list_t));
288 if (error_list_new == NULL) {
289 GERB_FATAL_ERROR("malloc error_list failed\n");
292 /* Set member elements */
293 error_list_new->layer = layer;
294 error_list_new->error_text = g_strdup_printf("%s", error_text);
295 error_list_new->type = type;
296 error_list_new->next = NULL;
297 error_last->next = error_list_new;
299 return;
302 /* ------------------------------------------------------- */
303 gerbv_aperture_list_t *
304 gerbv_stats_new_aperture_list() {
305 gerbv_aperture_list_t *aperture_list;
306 int i;
308 dprintf("Mallocing new gerb aperture list\n");
309 /* Malloc space for new aperture_list struct. Return NULL if error. */
310 if ((aperture_list = (gerbv_aperture_list_t *)g_malloc(sizeof(gerbv_aperture_list_t)))
311 == NULL) {
312 return NULL;
315 dprintf(" Placing values in certain structs.\n");
316 aperture_list->number = -1;
317 aperture_list->count = 0;
318 aperture_list->type = 0;
319 for (i = 0; i<5; i++) {
320 aperture_list->parameter[i] = 0.0;
322 aperture_list->next = NULL;
323 return aperture_list;
327 /* ------------------------------------------------------- */
328 void
329 gerbv_stats_add_aperture(gerbv_aperture_list_t *aperture_list_in,
330 int layer, int number, gerbv_aperture_type_t type,
331 double parameter[5]) {
333 gerbv_aperture_list_t *aperture_list_new;
334 gerbv_aperture_list_t *aperture_last = NULL;
335 gerbv_aperture_list_t *aperture;
336 int i;
338 dprintf(" ---> Entering gerbv_stats_add_aperture ....\n");
340 /* First handle case where this is the first list element */
341 if (aperture_list_in->number == -1) {
342 dprintf(" .... Adding first aperture to aperture list ... \n");
343 dprintf(" .... Aperture type = %d ... \n", type);
344 aperture_list_in->number = number;
345 aperture_list_in->type = type;
346 aperture_list_in->layer = layer;
347 for(i=0; i<5; i++) {
348 aperture_list_in->parameter[i] = parameter[i];
350 aperture_list_in->next = NULL;
351 dprintf(" <--- .... Leaving gerbv_stats_add_aperture.\n");
352 return;
355 /* Next check to see if this aperture is already in the list */
356 for(aperture = aperture_list_in;
357 aperture != NULL;
358 aperture = aperture->next) {
359 if ((aperture->number == number) &&
360 (aperture->layer == layer) ) {
361 dprintf(" .... This aperture is already in the list ... \n");
362 dprintf(" <--- .... Leaving gerbv_stats_add_aperture.\n");
363 return;
365 aperture_last = aperture; /* point to last element in list */
367 /* This aperture number is unique. Therefore, add it to the list */
368 dprintf(" .... Adding another aperture to list ... \n");
369 dprintf(" .... Aperture type = %d ... \n", type);
371 /* Now malloc space for new aperture list element */
372 aperture_list_new = (gerbv_aperture_list_t *) g_malloc(sizeof(gerbv_aperture_list_t));
373 if (aperture_list_new == NULL) {
374 GERB_FATAL_ERROR("malloc aperture_list failed\n");
377 /* Set member elements */
378 aperture_list_new->layer = layer;
379 aperture_list_new->number = number;
380 aperture_list_new->type = type;
381 aperture_list_new->next = NULL;
382 for(i=0; i<5; i++) {
383 aperture_list_new->parameter[i] = parameter[i];
385 aperture_last->next = aperture_list_new;
387 dprintf(" <--- .... Leaving gerbv_stats_add_aperture.\n");
389 return;
392 /* ------------------------------------------------------- */
393 void
394 gerbv_stats_add_to_D_list(gerbv_aperture_list_t *D_list_in,
395 int number) {
397 gerbv_aperture_list_t *D_list;
398 gerbv_aperture_list_t *D_list_last=NULL;
399 gerbv_aperture_list_t *D_list_new;
401 dprintf(" ----> Entering add_to_D_list, numbr = %d\n", number);
403 /* First handle case where this is the first list element */
404 if (D_list_in->number == -1) {
405 dprintf(" .... Adding first D code to D code list ... \n");
406 dprintf(" .... Aperture number = %d ... \n", number);
407 D_list_in->number = number;
408 D_list_in->count = 0;
409 D_list_in->next = NULL;
410 dprintf(" <--- .... Leaving add_to_D_list.\n");
411 return;
414 /* Look to see if this is already in list */
415 for(D_list = D_list_in;
416 D_list != NULL;
417 D_list = D_list->next) {
418 if (D_list->number == number) {
419 dprintf(" .... Found in D list .... \n");
420 dprintf(" <--- .... Leaving add_to_D_list.\n");
421 return;
423 D_list_last = D_list; /* point to last element in list */
426 /* This aperture number is unique. Therefore, add it to the list */
427 dprintf(" .... Adding another D code to D code list ... \n");
429 /* Malloc space for new aperture list element */
430 D_list_new = (gerbv_aperture_list_t *) g_malloc(sizeof(gerbv_aperture_list_t));
431 if (D_list_new == NULL) {
432 GERB_FATAL_ERROR("malloc D_list failed\n");
435 /* Set member elements */
436 D_list_new->number = number;
437 D_list_new->count = 0;
438 D_list_new->next = NULL;
439 D_list_last->next = D_list_new;
441 dprintf(" <--- .... Leaving add_to_D_list.\n");
443 return;
446 /* ------------------------------------------------------- */
447 int
448 gerbv_stats_increment_D_list_count(gerbv_aperture_list_t *D_list_in,
449 int number,
450 int count,
451 gerbv_error_list_t *error) {
453 gerbv_aperture_list_t *D_list;
455 dprintf(" Entering inc_D_list_count, code = D%d, input count to add = %d\n", number, count);
457 /* Find D code in list and increment it */
458 for(D_list = D_list_in;
459 D_list != NULL;
460 D_list = D_list->next) {
461 if (D_list->number == number) {
462 dprintf(" old count = %d\n", D_list->count);
463 D_list->count += count; /* Add to this aperture count, then return */
464 dprintf(" updated count = %d\n", D_list->count);
465 return 0; /* Return 0 for success */
469 /* This D number is not defined. Therefore, flag error */
470 dprintf(" .... Didn't find this D code in defined list .... \n");
471 dprintf(" <--- .... Leaving inc_D_list_count.\n");
472 gerbv_stats_add_error(error,
474 "Undefined aperture number called out in D code.\n",
475 GERBV_MESSAGE_ERROR);
476 return -1; /* Return -1 for failure */