~ubuntu-branches/ubuntu/precise/pcb/precise

« back to all changes in this revision

Viewing changes to src/file.c

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2005-02-20 13:14:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050220131400-pfz66g5vhx0azl8f
Tags: 1.99j+20050127-2
* Improved package description: (closes: #295405)
* Fixed dependency: tk84 -> tk8.4 (closes: #295404)
* Updated README.debian (closes: #269578)
* Applied patch to src/djopt.c to allow compilation with gcc-4.0
  (closes: #294319), thanks to Andreas Jochens for the patch.
* Prevent example files from being compressed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: file.c,v 1.20 2005/01/03 12:56:59 danmc Exp $ */
 
2
 
1
3
/*
2
4
 *                            COPYRIGHT
3
5
 *
24
26
 *
25
27
 */
26
28
 
27
 
static  char    *rcsid = "$Id: file.c,v 1.1 1998/02/19 18:06:34 sync Exp $";
28
 
 
29
29
/* file save, load, merge ... routines
30
30
 * getpid() needs a cast to (int) to get rid of compiler warnings
31
31
 * on several architectures
32
32
 */
33
33
 
 
34
#ifdef HAVE_CONFIG_H
 
35
#include "config.h"
 
36
#endif
 
37
 
34
38
#include <stdlib.h>
 
39
#include <dirent.h>
35
40
#include <pwd.h>
36
41
#include <time.h>
37
42
#include <ctype.h>
40
45
#include <sys/stat.h>
41
46
#include <netinet/in.h>
42
47
#include <netdb.h>
 
48
#ifdef HAVE_STRING_H
 
49
#include <string.h>
 
50
#endif
 
51
#ifdef HAVE_UNISTD_H
43
52
#include <unistd.h>
 
53
#endif
44
54
 
45
55
#include "global.h"
46
56
 
 
57
#include "buffer.h"
47
58
#include "change.h"
48
59
#include "create.h"
49
60
#include "crosshair.h"
55
66
#include "misc.h"
56
67
#include "netlist.h"
57
68
#include "parse_l.h"
 
69
#include "polygon.h"
58
70
#include "rats.h"
59
71
#include "remove.h"
60
72
#include "set.h"
61
73
 
 
74
#ifdef HAVE_LIBDMALLOC
 
75
#include <dmalloc.h>
 
76
#endif
 
77
 
 
78
RCSID("$Id: file.c,v 1.20 2005/01/03 12:56:59 danmc Exp $");
 
79
 
62
80
#if !defined(HAS_ATEXIT) && !defined(HAS_ON_EXIT)
63
81
/* ---------------------------------------------------------------------------
64
82
 * some local identifiers for OS without an atexit() or on_exit()
65
83
 * call
66
84
 */
67
 
static  char    TMPFilename[80];
 
85
static char TMPFilename[80];
68
86
#endif
69
87
 
70
88
/* ---------------------------------------------------------------------------
71
89
 * some local prototypes
72
90
 */
73
 
static  void    PrintQuotedString(FILE *, char *);
74
 
static  void    WritePCBInfoHeader(FILE *);
75
 
static  void    WritePCBDataHeader(FILE *);
76
 
static  void    WritePCBFontData(FILE *);
77
 
static  void    WritePCBViaData(FILE *);
78
 
static  void    WritePCBRatData(FILE *);
79
 
static  void    WritePCBElementData(FILE *);
80
 
static  void    WritePCBLayerData(FILE *, Cardinal);
81
 
static  int     WritePCB(FILE *);
82
 
static  int     WritePCBFile(char *);
83
 
static  int     WritePCBPipe(char *);
 
91
static void PrintQuotedString (FILE *, char *);
 
92
static void WritePCBInfoHeader (FILE *);
 
93
static void WritePCBDataHeader (FILE *);
 
94
static void WritePCBFontData (FILE *);
 
95
static void WriteViaData (FILE *, DataTypePtr);
 
96
static void WritePCBRatData (FILE *);
 
97
static void WriteElementData (FILE *, DataTypePtr);
 
98
static void WriteLayerData (FILE *, Cardinal, LayerTypePtr);
 
99
static int WritePCB (FILE *);
 
100
static int WritePCBFile (char *);
 
101
static int WritePipe (char *, Boolean);
 
102
static void ParseLibraryTree (void);
84
103
 
85
104
/* ---------------------------------------------------------------------------
86
105
 * opens a file and check if it exists
87
106
 */
88
 
FILE *CheckAndOpenFile(char *Filename,
89
 
        Boolean Confirm, Boolean AllButton, Boolean *WasAllButton)
 
107
FILE *
 
108
CheckAndOpenFile (char *Filename,
 
109
                  Boolean Confirm, Boolean AllButton, Boolean * WasAllButton)
90
110
{
91
 
        FILE            *fp = NULL;
92
 
        struct stat     buffer;
93
 
        char            message[MAXPATHLEN+80];
 
111
  FILE *fp = NULL;
 
112
  struct stat buffer;
 
113
  char message[MAXPATHLEN + 80];
94
114
 
95
 
        if (Filename && *Filename)
 
115
  if (Filename && *Filename)
 
116
    {
 
117
      if (!stat (Filename, &buffer) && Confirm)
96
118
        {
97
 
                if (!stat(Filename, &buffer) && Confirm)
98
 
                {
99
 
                        sprintf(message, "file '%s' exists, use anyway?", Filename);
100
 
                        *WasAllButton = False;
101
 
                        switch(ConfirmReplaceFileDialog(message, AllButton))
102
 
                        {
103
 
                                case ALL_BUTTON:        *WasAllButton = True; break;
104
 
                                case CANCEL_BUTTON: return(NULL);
105
 
                        }
106
 
                }
107
 
                if ((fp = fopen(Filename, "w")) == NULL)
108
 
                        OpenErrorMessage(Filename);
 
119
          sprintf (message, "file '%s' exists, use anyway?", Filename);
 
120
          *WasAllButton = False;
 
121
          switch (ConfirmReplaceFileDialog (message, AllButton))
 
122
            {
 
123
            case ALL_BUTTON:
 
124
              *WasAllButton = True;
 
125
              break;
 
126
            case CANCEL_BUTTON:
 
127
              return (NULL);
 
128
            }
109
129
        }
110
 
        return(fp);
 
130
      if ((fp = fopen (Filename, "w")) == NULL)
 
131
        OpenErrorMessage (Filename);
 
132
    }
 
133
  return (fp);
111
134
}
112
135
 
113
136
/* ---------------------------------------------------------------------------
114
137
 * opens a file for saving connection data
115
138
 */
116
 
FILE *OpenConnectionDataFile(void)
117
 
{
118
 
        char    *filename;
119
 
        Boolean result;         /* not used */
120
 
 
121
 
        filename = GetUserInput("enter filename to save connection data:", "");
122
 
        return(CheckAndOpenFile(filename, True, False, &result));
 
139
FILE *
 
140
OpenConnectionDataFile (void)
 
141
{
 
142
  char *filename;
 
143
  Boolean result;               /* not used */
 
144
 
 
145
  filename = GetUserInput ("enter filename to save connection data:", "");
 
146
  return (CheckAndOpenFile (filename, True, False, &result));
 
147
}
 
148
 
 
149
/* ---------------------------------------------------------------------------
 
150
 * save elements in the current buffer
 
151
 */
 
152
int
 
153
SaveBufferElements (char *Filename)
 
154
{
 
155
  int result;
 
156
 
 
157
  if (SWAP_IDENT)
 
158
    SwapBuffers ();
 
159
  result = WritePipe (Filename, False);
 
160
  if (SWAP_IDENT)
 
161
    SwapBuffers ();
 
162
  return (result);
123
163
}
124
164
 
125
165
/* ---------------------------------------------------------------------------
126
166
 * save PCB
127
167
 */
128
 
int SavePCB(char *Filename)
 
168
int
 
169
SavePCB (char *Filename)
129
170
{
130
 
        int     retcode;
131
 
        char    *copy;
 
171
  int retcode;
 
172
  char *copy;
132
173
 
133
 
        if (!(retcode = WritePCBPipe(Filename)))
134
 
        {
135
 
                        /* thanks to Nick Bailey for the bug-fix;
136
 
                         * first of all make a copy of the passed filename because
137
 
                         * it might be identical to 'PCB->Filename'
138
 
                         */
139
 
                copy = MyStrdup(Filename, "SavePCB()");
140
 
                SaveFree(PCB->Filename);
141
 
                PCB->Filename = copy;
142
 
                SetChangedFlag(False);
143
 
        }
144
 
        return(retcode);
 
174
  if (!(retcode = WritePipe (Filename, True)))
 
175
    {
 
176
      /* thanks to Nick Bailey for the bug-fix;
 
177
       * first of all make a copy of the passed filename because
 
178
       * it might be identical to 'PCB->Filename'
 
179
       */
 
180
      copy = MyStrdup (Filename, "SavePCB()");
 
181
      SaveFree (PCB->Filename);
 
182
      PCB->Filename = copy;
 
183
      SetChangedFlag (False);
 
184
    }
 
185
  return (retcode);
145
186
}
146
187
 
147
188
/* ---------------------------------------------------------------------------
149
190
 * parse the file with enabled 'PCB mode' (see parser)
150
191
 * if successful, update some other stuff
151
192
 */
152
 
int LoadPCB(char *Filename)
 
193
int
 
194
LoadPCB (char *Filename)
153
195
{
154
 
        PCBTypePtr      newPCB = CreateNewPCB(False);
155
 
        int             save;
156
 
 
157
 
                /* new data isn't added to the undo list */
158
 
        if (!ParsePCB(newPCB, Filename))
 
196
  PCBTypePtr newPCB = CreateNewPCB (False);
 
197
 
 
198
  /* new data isn't added to the undo list */
 
199
  if (!ParsePCB (newPCB, Filename))
 
200
    {
 
201
      RemovePCB (PCB);
 
202
      PCB = newPCB;
 
203
      InitNetlistWindow (Output.Toplevel);
 
204
      ResetStackAndVisibility ();
 
205
      /* set the zoom first before the Xorig, Yorig */
 
206
      SetZoom (PCB->Zoom);
 
207
 
 
208
      /* update cursor location */
 
209
      Crosshair.X = MAX (0, MIN (PCB->CursorX, (LocationType) PCB->MaxWidth));
 
210
      Crosshair.Y = MAX (0, MIN (PCB->CursorY, (LocationType) PCB->MaxHeight));
 
211
 
 
212
      Xorig = Crosshair.X - TO_PCB (Output.Width / 2);
 
213
      Yorig = Crosshair.Y - TO_PCB (Output.Height / 2);
 
214
      RedrawZoom (Output.Width / 2, Output.Height / 2);
 
215
 
 
216
      /* update cursor confinement and output area (scrollbars) */
 
217
      ChangePCBSize (PCB->MaxWidth, PCB->MaxHeight);
 
218
 
 
219
      /* create default font if necessary */
 
220
      if (!PCB->Font.Valid)
159
221
        {
160
 
                RemovePCB(PCB);
161
 
                PCB = newPCB;
162
 
                InitNetlistWindow(Output.Toplevel);
163
 
                ResetStackAndVisibility();
164
 
 
165
 
                        /* update cursor location */
166
 
                Crosshair.X = MIN(PCB->CursorX, (Position) PCB->MaxWidth);
167
 
                Crosshair.Y = MIN(PCB->CursorY, (Position) PCB->MaxHeight);
168
 
 
169
 
                        /* update zoom information. Presetting it to a not allowed
170
 
                         * value makes sure that the routine is forced to
171
 
                         * initialize some things
172
 
                         * SetZoom() also calls CenterDisplay()
173
 
                         */
174
 
                save = PCB->Zoom;
175
 
                PCB->Zoom = MAX_ZOOM+1;
176
 
                SetZoom(save);
177
 
 
178
 
                        /* update cursor confinement and output area (scrollbars) */
179
 
                ChangePCBSize(PCB->MaxWidth, PCB->MaxHeight);
180
 
 
181
 
                        /* create default font if necessary */
182
 
                if (!PCB->Font.Valid)
183
 
                {
184
 
                        Message("file '%s' has no font information\n"
185
 
                                "  default font will be used\n", Filename);
186
 
                        CreateDefaultFont();
187
 
                }
188
 
 
189
 
                        /* clear 'changed flag' */
190
 
                SetChangedFlag(False);
191
 
                PCB->Filename = MyStrdup(Filename, "LoadPCB()");
192
 
                UpdateSettingsOnScreen();
193
 
                return(0);
 
222
          Message ("file '%s' has no font information\n"
 
223
                   "  default font will be used\n", Filename);
 
224
          CreateDefaultFont ();
194
225
        }
195
226
 
196
 
                /* release unused memory */
197
 
        RemovePCB(newPCB);
198
 
        return(1);
 
227
      /* clear 'changed flag' */
 
228
      SetChangedFlag (False);
 
229
      PCB->Filename = MyStrdup (Filename, "LoadPCB()");
 
230
      /* just in case a bad file saved file is loaded */
 
231
      UpdatePIPFlags (NULL, NULL, NULL, False);
 
232
      UpdateSettingsOnScreen ();
 
233
      return (0);
 
234
    }
 
235
 
 
236
  /* release unused memory */
 
237
  RemovePCB (newPCB);
 
238
  return (1);
199
239
}
200
240
 
201
241
/* ---------------------------------------------------------------------------
202
242
 * writes the quoted string created by another subroutine
203
243
 */
204
 
static void PrintQuotedString(FILE *FP, char *S)
 
244
static void
 
245
PrintQuotedString (FILE * FP, char *S)
205
246
{
206
 
        static  DynamicStringType       ds;
 
247
  static DynamicStringType ds;
207
248
 
208
 
        CreateQuotedString(&ds, S);
209
 
        fputs(ds.Data, FP);
 
249
  CreateQuotedString (&ds, S);
 
250
  fputs (ds.Data, FP);
210
251
}
211
252
 
212
253
/* ---------------------------------------------------------------------------
213
254
 * writes layout header information
214
255
 * date, UID and name of user
215
256
 */
216
 
static void WritePCBInfoHeader(FILE *FP)
 
257
static void
 
258
WritePCBInfoHeader (FILE * FP)
217
259
{
218
 
        struct passwd   *pwentry;
219
 
        struct hostent  *hostentry;
220
 
        time_t          currenttime;
221
 
        char            hostname[256];
 
260
  struct passwd *pwentry;
 
261
  struct hostent *hostentry;
 
262
  time_t currenttime;
 
263
  char hostname[256];
222
264
 
223
 
                /* write some useful comments */
224
 
        currenttime = time(NULL);
225
 
        pwentry = getpwuid(getuid());
226
 
        fprintf(FP, "# release: %s "RELEASE"\n", Progname);
227
 
        fprintf(FP, "# date:    %s", asctime(localtime(&currenttime)));
228
 
        fprintf(FP, "# user:    %s (%s)\n", pwentry->pw_name, pwentry->pw_gecos);
229
 
        if (gethostname(hostname, 255) != -1)
230
 
        {
231
 
                hostentry = gethostbyname(hostname); 
232
 
                fprintf(FP, "# host:    %s\n",hostentry ? hostentry->h_name : hostname);
233
 
        }
 
265
  /* write some useful comments */
 
266
  currenttime = time (NULL);
 
267
  pwentry = getpwuid (getuid ());
 
268
  fprintf (FP, "# release: %s " VERSION "\n", Progname);
 
269
  fprintf (FP, "# date:    %s", asctime (localtime (&currenttime)));
 
270
  fprintf (FP, "# user:    %s (%s)\n", pwentry->pw_name, pwentry->pw_gecos);
 
271
  if (gethostname (hostname, 255) != -1)
 
272
    {
 
273
      hostentry = gethostbyname (hostname);
 
274
      fprintf (FP, "# host:    %s\n",
 
275
               hostentry ? hostentry->h_name : hostname);
 
276
    }
234
277
}
235
278
 
236
279
/* ---------------------------------------------------------------------------
238
281
 * the name of the PCB, cursor location, zoom and grid
239
282
 * layergroups and some flags
240
283
 */
241
 
static void WritePCBDataHeader(FILE *FP)
 
284
static void
 
285
WritePCBDataHeader (FILE * FP)
242
286
{
243
 
        Cardinal        group,
244
 
                        entry;
245
 
 
246
 
        fputs("\nPCB(", FP);
247
 
        PrintQuotedString(FP, EMPTY(PCB->Name));
248
 
        fprintf(FP, " %i %i)\n\n",
249
 
                (int) PCB->MaxWidth, (int) PCB->MaxHeight);
250
 
        fprintf(FP, "Grid(%i %i %i %i)\n",
251
 
                (int) PCB->Grid, (int) PCB->GridOffsetX, (int) PCB->GridOffsetY, (int) Settings.DrawGrid);
252
 
        fprintf(FP, "Cursor(%i %i %i)\n",
253
 
                (int) Crosshair.X, (int) Crosshair.Y, PCB->Zoom);
254
 
        fprintf(FP, "Flags(0x%08x)\n", (int) PCB->Flags);
255
 
        fputs("Groups(\"", FP);
256
 
        for (group = 0; group < MAX_LAYER; group++)
257
 
                if (PCB->LayerGroups.Number[group])
258
 
                {
259
 
                        for (entry = 0; entry < PCB->LayerGroups.Number[group]; entry++)
260
 
                        {
261
 
                                switch(PCB->LayerGroups.Entries[group][entry])
262
 
                                {
263
 
                                        case MAX_LAYER +COMPONENT_LAYER:
264
 
                                                fputc('c', FP);
265
 
                                                break;
266
 
 
267
 
                                        case MAX_LAYER +SOLDER_LAYER:
268
 
                                                fputc('s', FP);
269
 
                                                break;
270
 
 
271
 
                                        default:
272
 
                                                fprintf(FP, "%d",
273
 
                                                        PCB->LayerGroups.Entries[group][entry]+1);
274
 
                                                break;
275
 
                                }
276
 
                                if (entry != PCB->LayerGroups.Number[group]-1)
277
 
                                        fputc(',', FP);
278
 
                        }
279
 
                        if (group != MAX_LAYER-1)
280
 
                                fputc(':', FP);
281
 
                }
282
 
        fputs("\")\nStyles(\"", FP);
283
 
        for (group = 0; group < NUM_STYLES - 1; group++)
284
 
                fprintf(FP, "%s,%i,%i,%i:", PCB->RouteStyle[group].Name,
285
 
                        PCB->RouteStyle[group].Thick,
286
 
                        PCB->RouteStyle[group].Diameter,
287
 
                        PCB->RouteStyle[group].Hole);
288
 
        fprintf(FP, "%s,%i,%i,%i\")\n\n", PCB->RouteStyle[group].Name,
289
 
                PCB->RouteStyle[group].Thick,
290
 
                PCB->RouteStyle[group].Diameter,
291
 
                PCB->RouteStyle[group].Hole);
 
287
  Cardinal group, entry;
 
288
 
 
289
  fputs ("\nPCB[", FP);
 
290
  PrintQuotedString (FP, EMPTY (PCB->Name));
 
291
  fprintf (FP, " %i %i]\n\n", (int) PCB->MaxWidth, (int) PCB->MaxHeight);
 
292
  fprintf (FP, "Grid[%2.8f %i %i %i]\n",
 
293
           PCB->Grid, (int) PCB->GridOffsetX, (int) PCB->GridOffsetY,
 
294
           (int) Settings.DrawGrid);
 
295
  fprintf (FP, "Cursor[%i %i %f]\n", (int) TO_PCB_X (Output.Width / 2),
 
296
           (int) TO_PCB_Y (Output.Height / 2), PCB->Zoom);
 
297
  fprintf (FP, "Thermal[%f]\n", PCB->ThermScale);
 
298
  fprintf (FP, "DRC[%i %i %i %i]\n", Settings.Bloat, Settings.Shrink,
 
299
           Settings.minWid, Settings.minSlk);
 
300
  fprintf (FP, "Flags(0x%016x)\n", (int) PCB->Flags);
 
301
  fputs ("Groups(\"", FP);
 
302
  for (group = 0; group < MAX_LAYER; group++)
 
303
    if (PCB->LayerGroups.Number[group])
 
304
      {
 
305
        for (entry = 0; entry < PCB->LayerGroups.Number[group]; entry++)
 
306
          {
 
307
            switch (PCB->LayerGroups.Entries[group][entry])
 
308
              {
 
309
              case MAX_LAYER + COMPONENT_LAYER:
 
310
                fputc ('c', FP);
 
311
                break;
 
312
 
 
313
              case MAX_LAYER + SOLDER_LAYER:
 
314
                fputc ('s', FP);
 
315
                break;
 
316
 
 
317
              default:
 
318
                fprintf (FP, "%d",
 
319
                         PCB->LayerGroups.Entries[group][entry] + 1);
 
320
                break;
 
321
              }
 
322
            if (entry != PCB->LayerGroups.Number[group] - 1)
 
323
              fputc (',', FP);
 
324
          }
 
325
        if (group != MAX_LAYER - 1)
 
326
          fputc (':', FP);
 
327
      }
 
328
  fputs ("\")\nStyles[\"", FP);
 
329
  for (group = 0; group < NUM_STYLES - 1; group++)
 
330
    fprintf (FP, "%s,%i,%i,%i,%i:", PCB->RouteStyle[group].Name,
 
331
             PCB->RouteStyle[group].Thick,
 
332
             PCB->RouteStyle[group].Diameter,
 
333
             PCB->RouteStyle[group].Hole, PCB->RouteStyle[group].Keepaway);
 
334
  fprintf (FP, "%s,%i,%i,%i,%i\"]\n\n", PCB->RouteStyle[group].Name,
 
335
           PCB->RouteStyle[group].Thick,
 
336
           PCB->RouteStyle[group].Diameter,
 
337
           PCB->RouteStyle[group].Hole, PCB->RouteStyle[group].Keepaway);
292
338
}
293
339
 
294
340
/* ---------------------------------------------------------------------------
295
341
 * writes font data of non empty symbols
296
342
 */
297
 
static void WritePCBFontData(FILE *FP)
 
343
static void
 
344
WritePCBFontData (FILE * FP)
298
345
{
299
 
        Cardinal        i, j;
300
 
        LineTypePtr     line;
301
 
        FontTypePtr     font;
302
 
 
303
 
        for (font = &PCB->Font, i = 0; i <= MAX_FONTPOSITION; i++)
304
 
        {
305
 
                if (!font->Symbol[i].Valid)
306
 
                        continue;
307
 
 
308
 
                if (isprint(i))
309
 
                        fprintf(FP, "Symbol('%c' %i)\n(\n",
310
 
                                (char) i, (int) font->Symbol[i].Delta);
311
 
                else
312
 
                        fprintf(FP, "Symbol(%i %i)\n(\n", i, (int) font->Symbol[i].Delta);
313
 
 
314
 
                line = font->Symbol[i].Line;
315
 
                for (j = font->Symbol[i].LineN; j; j --, line++)
316
 
                        fprintf(FP, "\tSymbolLine(%i %i %i %i %i)\n",
317
 
                                (int) line->Point1.X, (int) line->Point1.Y,
318
 
                                (int) line->Point2.X, (int) line->Point2.Y,
319
 
                                (int) line->Thickness);
320
 
                fputs(")\n", FP);
321
 
        }
 
346
  Cardinal i, j;
 
347
  LineTypePtr line;
 
348
  FontTypePtr font;
 
349
 
 
350
  for (font = &PCB->Font, i = 0; i <= MAX_FONTPOSITION; i++)
 
351
    {
 
352
      if (!font->Symbol[i].Valid)
 
353
        continue;
 
354
 
 
355
      if (isprint (i))
 
356
        fprintf (FP, "Symbol['%c' %i]\n(\n",
 
357
                 (char) i, (int) font->Symbol[i].Delta);
 
358
      else
 
359
        fprintf (FP, "Symbol[%i %i]\n(\n", i, (int) font->Symbol[i].Delta);
 
360
 
 
361
      line = font->Symbol[i].Line;
 
362
      for (j = font->Symbol[i].LineN; j; j--, line++)
 
363
        fprintf (FP, "\tSymbolLine[%i %i %i %i %i]\n",
 
364
                 line->Point1.X, line->Point1.Y,
 
365
                 line->Point2.X, line->Point2.Y, line->Thickness);
 
366
      fputs (")\n", FP);
 
367
    }
322
368
}
323
369
 
324
370
/* ---------------------------------------------------------------------------
325
371
 * writes via data
326
372
 */
327
 
static void WritePCBViaData(FILE *FP)
 
373
static void
 
374
WriteViaData (FILE * FP, DataTypePtr Data)
328
375
{
329
 
                /* write information about vias */
330
 
        VIA_LOOP(PCB->Data,
331
 
                fprintf(FP, "Via(%i %i %i %i %i ",
332
 
                        (int) via->X, (int) via->Y,
333
 
                        (int) via->Thickness, (int) via->Clearance,
334
 
                        (int) via->DrillingHole);
335
 
                PrintQuotedString(FP, EMPTY(via->Name));
336
 
                fprintf(FP, " 0x%08x)\n", (int) via->Flags);
337
 
        );
 
376
  int n;
 
377
  /* write information about vias */
 
378
  for (n = 0; n < Data->ViaN; n++)
 
379
    {
 
380
      PinTypePtr via = &Data->Via[n];
 
381
      fprintf (FP, "Via[%i %i %i %i %i %i ",
 
382
               via->X, via->Y,
 
383
               via->Thickness, via->Clearance, via->Mask, via->DrillingHole);
 
384
      PrintQuotedString (FP, EMPTY (via->Name));
 
385
      fprintf (FP, " 0x%08x]\n", (int) via->Flags);
 
386
    }
338
387
}
339
388
 
340
389
/* ---------------------------------------------------------------------------
341
390
 * writes rat-line data
342
391
 */
343
 
static void WritePCBRatData(FILE *FP)
 
392
static void
 
393
WritePCBRatData (FILE * FP)
344
394
{
345
 
                /* write information about rats */
346
 
        RAT_LOOP(PCB->Data,
347
 
                fprintf(FP, "Rat(%i %i %i %i %i %i ",
348
 
                        (int) line->Point1.X, (int) line->Point1.Y,
349
 
                        (int) line->group1, (int) line->Point2.X,
350
 
                        (int) line->Point2.Y, (int) line->group2);
351
 
                fprintf(FP, " 0x%08x)\n", (int) line->Flags);
352
 
        );
 
395
  int n;
 
396
  /* write information about rats */
 
397
  for (n = 0; n < PCB->Data->RatN; n++)
 
398
    {
 
399
      RatTypePtr line = &PCB->Data->Rat[n];
 
400
      fprintf (FP, "Rat[%i %i %i %i %i %i ",
 
401
               (int) line->Point1.X, (int) line->Point1.Y,
 
402
               (int) line->group1, (int) line->Point2.X,
 
403
               (int) line->Point2.Y, (int) line->group2);
 
404
      fprintf (FP, " 0x%08x]\n", (int) line->Flags);
 
405
    }
353
406
}
354
407
 
355
408
/* ---------------------------------------------------------------------------
356
409
 * writes netlist data
357
410
 */
358
 
static void WritePCBNetlistData(FILE *FP)
 
411
static void
 
412
WritePCBNetlistData (FILE * FP)
359
413
{
360
 
                /* write out the netlist if it exists */
361
 
        if (PCB->NetlistLib.MenuN)
 
414
  /* write out the netlist if it exists */
 
415
  if (PCB->NetlistLib.MenuN)
 
416
    {
 
417
      int n, p;
 
418
      fprintf (FP, "NetList()\n(\n");
 
419
 
 
420
      for (n = 0; n < PCB->NetlistLib.MenuN; n++)
362
421
        {
363
 
                fprintf(FP,"NetList()\n(\n");
364
 
                MENU_LOOP(&PCB->NetlistLib,
365
 
                        fprintf(FP,"\tNet(\"%s\" \"%s\")\n\t(\n", &menu->Name[2],
366
 
                                UNKNOWN(menu->Style));
367
 
                        ENTRY_LOOP(menu,
368
 
                                fprintf(FP, "\t\tConnect(\"%s\")\n", entry->ListEntry);
369
 
                        );
370
 
                        fprintf(FP,"\t)\n");
371
 
                );
372
 
                fprintf(FP,")\n");
 
422
          LibraryMenuTypePtr menu = &PCB->NetlistLib.Menu[n];
 
423
          fprintf (FP, "\tNet(\"%s\" \"%s\")\n\t(\n", &menu->Name[2],
 
424
                   UNKNOWN (menu->Style));
 
425
          for (p = 0; p < menu->EntryN; p++)
 
426
            {
 
427
              LibraryEntryTypePtr entry = &menu->Entry[p];
 
428
              fprintf (FP, "\t\tConnect(\"%s\")\n", entry->ListEntry);
 
429
            }
 
430
          fprintf (FP, "\t)\n");
373
431
        }
 
432
      fprintf (FP, ")\n");
 
433
    }
374
434
}
375
435
 
376
436
/* ---------------------------------------------------------------------------
377
437
 * writes element data
378
438
 */
379
 
static void WritePCBElementData(FILE *FP)
 
439
static void
 
440
WriteElementData (FILE * FP, DataTypePtr Data)
380
441
{
381
 
        ELEMENT_LOOP(PCB->Data,
382
 
                        /* only non empty elements */
383
 
                if (!element->LineN && !element->PinN &&
384
 
                        !element->ArcN && !element->PadN)
385
 
                        continue;
386
 
 
387
 
                                /* the coordinates and text-flags are the same for
388
 
                                 * both names of an element
389
 
                                 */
390
 
                fprintf(FP, "\nElement(0x%08x ", (int) element->Flags);
391
 
                PrintQuotedString(FP, EMPTY(DESCRIPTION_NAME(element)));
392
 
                fputc(' ', FP);
393
 
                PrintQuotedString(FP, EMPTY(NAMEONPCB_NAME(element)));
394
 
                fputc(' ', FP);
395
 
                PrintQuotedString(FP, EMPTY(VALUE_NAME(element)));
396
 
                fprintf(FP, " %i %i %i %i %i %i 0x%08x)\n(\n",
397
 
                                (int) element->MarkX, (int) element->MarkY,
398
 
                                (int) (DESCRIPTION_TEXT(element).X - element->MarkX),
399
 
                                (int) (DESCRIPTION_TEXT(element).Y - element->MarkY),
400
 
                                (int) DESCRIPTION_TEXT(element).Direction,
401
 
                                (int) DESCRIPTION_TEXT(element).Scale,
402
 
                                (int) DESCRIPTION_TEXT(element).Flags);
403
 
 
404
 
                PIN_LOOP(element,
405
 
                        fprintf(FP, "\tPin(%i %i %i %i %i %i ",
406
 
                                (int) (pin->X - element->MarkX),
407
 
                                (int) (pin->Y - element->MarkY),
408
 
                                (int) pin->Thickness, (int) pin->Clearance,
409
 
                                (int) pin->Mask, (int) pin->DrillingHole);
410
 
                        PrintQuotedString(FP, EMPTY(pin->Name));
411
 
                        fprintf(FP, " ");
412
 
                        PrintQuotedString(FP, EMPTY(pin->Number));
413
 
                        fprintf(FP, " 0x%08x)\n", (int) pin->Flags);
414
 
                );
415
 
                PAD_LOOP(element,
416
 
                        fprintf(FP, "\tPad(%i %i %i %i %i %i %i ",
417
 
                                (int) (pad->Point1.X - element->MarkX),
418
 
                                (int) (pad->Point1.Y - element->MarkY),
419
 
                                (int) (pad->Point2.X - element->MarkX),
420
 
                                (int) (pad->Point2.Y - element->MarkY),
421
 
                                (int) pad->Thickness, (int) pad->Clearance,
422
 
                                (int) pad->Mask);
423
 
                        PrintQuotedString(FP, EMPTY(pad->Name));
424
 
                        fprintf(FP, " ");
425
 
                        PrintQuotedString(FP, EMPTY(pad->Number));
426
 
                        fprintf(FP, " 0x%08x)\n", (int) pad->Flags);
427
 
                );
428
 
 
429
 
                ELEMENTLINE_LOOP(element,
430
 
                        fprintf(FP, "\tElementLine (%i %i %i %i %i)\n",
431
 
                                (int) (line->Point1.X - element->MarkX),
432
 
                                (int) (line->Point1.Y - element->MarkY),
433
 
                                (int) (line->Point2.X - element->MarkX),
434
 
                                (int) (line->Point2.Y - element->MarkY),
435
 
                                (int) line->Thickness);
436
 
                );
437
 
 
438
 
                ARC_LOOP(element,
439
 
                        fprintf(FP, "\tElementArc (%i %i %i %i %i %i %i)\n",
440
 
                                (int) (arc->X - element->MarkX),
441
 
                                (int) (arc->Y - element->MarkY),
442
 
                                (int) arc->Width, (int) arc->Height,
443
 
                                (int) arc->StartAngle, (int) arc->Delta,
444
 
                                (int) arc->Thickness);
445
 
                );
446
 
                fprintf(FP, "\t)\n");
447
 
        );
 
442
  int n, p;
 
443
  for (n = 0; n < Data->ElementN; n++)
 
444
    {
 
445
      ElementTypePtr element = &Data->Element[n];
 
446
      /* only non empty elements */
 
447
      if (!element->LineN && !element->PinN && !element->ArcN
 
448
          && !element->PadN)
 
449
        continue;
 
450
      /* the coordinates and text-flags are the same for
 
451
       * both names of an element
 
452
       */
 
453
      fprintf (FP, "\nElement[0x%08x ", (int) element->Flags);
 
454
      PrintQuotedString (FP, EMPTY (DESCRIPTION_NAME (element)));
 
455
      fputc (' ', FP);
 
456
      PrintQuotedString (FP, EMPTY (NAMEONPCB_NAME (element)));
 
457
      fputc (' ', FP);
 
458
      PrintQuotedString (FP, EMPTY (VALUE_NAME (element)));
 
459
      fprintf (FP, " %i %i %i %i %i %i 0x%08x]\n(\n",
 
460
               (int) element->MarkX, (int) element->MarkY,
 
461
               (int) (DESCRIPTION_TEXT (element).X -
 
462
                      element->MarkX),
 
463
               (int) (DESCRIPTION_TEXT (element).Y -
 
464
                      element->MarkY),
 
465
               (int) DESCRIPTION_TEXT (element).Direction,
 
466
               (int) DESCRIPTION_TEXT (element).Scale,
 
467
               (int) DESCRIPTION_TEXT (element).Flags);
 
468
      for (p = 0; p < element->PinN; p++)
 
469
        {
 
470
          PinTypePtr pin = &element->Pin[p];
 
471
          fprintf (FP, "\tPin[%i %i %i %i %i %i ",
 
472
                   (int) (pin->X - element->MarkX),
 
473
                   (int) (pin->Y - element->MarkY),
 
474
                   (int) pin->Thickness, (int) pin->Clearance,
 
475
                   (int) pin->Mask, (int) pin->DrillingHole);
 
476
          PrintQuotedString (FP, EMPTY (pin->Name));
 
477
          fprintf (FP, " ");
 
478
          PrintQuotedString (FP, EMPTY (pin->Number));
 
479
          fprintf (FP, " 0x%08x]\n", (int) pin->Flags);
 
480
        }
 
481
      for (p = 0; p < element->PadN; p++)
 
482
        {
 
483
          PadTypePtr pad = &element->Pad[p];
 
484
          fprintf (FP, "\tPad[%i %i %i %i %i %i %i ",
 
485
                   (int) (pad->Point1.X - element->MarkX),
 
486
                   (int) (pad->Point1.Y - element->MarkY),
 
487
                   (int) (pad->Point2.X - element->MarkX),
 
488
                   (int) (pad->Point2.Y - element->MarkY),
 
489
                   (int) pad->Thickness, (int) pad->Clearance,
 
490
                   (int) pad->Mask);
 
491
          PrintQuotedString (FP, EMPTY (pad->Name));
 
492
          fprintf (FP, " ");
 
493
          PrintQuotedString (FP, EMPTY (pad->Number));
 
494
          fprintf (FP, " 0x%08x]\n", (int) pad->Flags);
 
495
        }
 
496
      for (p = 0; p < element->LineN; p++)
 
497
      {
 
498
        LineTypePtr line = &element->Line[p];
 
499
        fprintf (FP,
 
500
                 "\tElementLine [%i %i %i %i %i]\n",
 
501
                 (int) (line->Point1.X -
 
502
                        element->MarkX),
 
503
                 (int) (line->Point1.Y -
 
504
                        element->MarkY),
 
505
                 (int) (line->Point2.X -
 
506
                        element->MarkX),
 
507
                 (int) (line->Point2.Y -
 
508
                        element->MarkY), (int) line->Thickness);
 
509
      }
 
510
      for (p = 0; p < element->ArcN; p++)
 
511
        {
 
512
          ArcTypePtr arc = &element->Arc[p];
 
513
          fprintf (FP,
 
514
                   "\tElementArc [%i %i %i %i %i %i %i]\n",
 
515
                   (int) (arc->X - element->MarkX),
 
516
                   (int) (arc->Y - element->MarkY),
 
517
                   (int) arc->Width, (int) arc->Height,
 
518
                   (int) arc->StartAngle, (int) arc->Delta,
 
519
                   (int) arc->Thickness);
 
520
        }
 
521
      fputs ("\n\t)\n", FP);
 
522
    }
448
523
}
449
524
 
450
525
/* ---------------------------------------------------------------------------
451
526
 * writes layer data
452
527
 */
453
 
static void WritePCBLayerData(FILE *FP, Cardinal Number)
454
 
{
455
 
        LayerTypePtr    layer = &PCB->Data->Layer[Number];
456
 
 
457
 
                /* write information about non empty layers */
458
 
        if (layer->LineN || layer->ArcN || layer->TextN || layer->PolygonN || 
459
 
                (layer->Name && *layer->Name))
460
 
        {
461
 
                fprintf(FP, "Layer(%i ", (int) Number+1);
462
 
                PrintQuotedString(FP, EMPTY(layer->Name));
463
 
                fputs(")\n(\n", FP);
464
 
 
465
 
                LINE_LOOP(layer,
466
 
                        fprintf(FP, "\tLine(%i %i %i %i %i %i 0x%08x)\n",
467
 
                                (int) line->Point1.X, (int) line->Point1.Y,
468
 
                                (int) line->Point2.X, (int) line->Point2.Y,
469
 
                                (int) line->Thickness, (int) line->Clearance,
470
 
                                (int) line->Flags);
471
 
                );
472
 
                ARC_LOOP(layer,
473
 
                        fprintf(FP, "\tArc(%i %i %i %i %i %i %i %i 0x%08x)\n",
474
 
                                (int) arc->X, (int) arc->Y, (int) arc->Width,
475
 
                                (int) arc->Height, (int) arc->Thickness,
476
 
                                (int) arc->Clearance, (int) arc->StartAngle,
477
 
                                (int) arc->Delta, (int) arc->Flags);
478
 
                );
479
 
                TEXT_LOOP(layer,
480
 
                        fprintf(FP, "\tText(%i %i %i %i ",
481
 
                                (int) text->X, (int) text->Y,
482
 
                                (int) text->Direction, (int) text->Scale);
483
 
                        PrintQuotedString(FP, EMPTY(text->TextString));
484
 
                        fprintf(FP, " 0x%08x)\n", (int) text->Flags);
485
 
                );
486
 
                POLYGON_LOOP(layer,
487
 
                        {
488
 
                                int     i = 0;
489
 
 
490
 
                                fprintf(FP, "\tPolygon(0x%08x)\n\t(", polygon->Flags);
491
 
                                POLYGONPOINT_LOOP(polygon,
492
 
                                        {
493
 
                                                if (i++ % 5 == 0)
494
 
                                                        fputs("\n\t\t", FP);
495
 
                                                fprintf(FP, "(%i %i) ",
496
 
                                                        (int) point->X, (int) point->Y);
497
 
                                        }
498
 
                                );
499
 
                                fputs("\n\t)\n", FP);
500
 
                        }
501
 
                );
502
 
 
503
 
                fputs(")\n", FP);
504
 
        }
505
 
}
506
 
 
507
 
/* ---------------------------------------------------------------------------
508
 
 * writes PCB to file
509
 
 */
510
 
static int WritePCB(FILE *FP)
511
 
{
512
 
        Cardinal        i;
513
 
 
514
 
        WritePCBInfoHeader(FP);
515
 
        WritePCBDataHeader(FP);
516
 
        WritePCBFontData(FP);
517
 
        WritePCBViaData(FP);
518
 
        WritePCBElementData(FP);
519
 
        WritePCBRatData(FP);
520
 
        for (i = 0; i < MAX_LAYER + 2; i++)
521
 
                WritePCBLayerData(FP, i);
522
 
        WritePCBNetlistData(FP);
523
 
 
524
 
        return(STATUS_OK);
525
 
}
526
 
 
527
 
/* ---------------------------------------------------------------------------
528
 
 * writes PCB to file
529
 
 */
530
 
static int WritePCBFile(char *Filename)
531
 
{
532
 
        FILE    *fp;
533
 
        int             result;
534
 
 
535
 
        if ((fp = fopen(Filename, "w")) == NULL)
536
 
        {
537
 
                OpenErrorMessage(Filename);
538
 
                return(STATUS_ERROR);
539
 
        }
540
 
        result = WritePCB(fp);
541
 
        fclose(fp);
542
 
        return(result);
543
 
}
544
 
 
545
 
/* ---------------------------------------------------------------------------
546
 
 * writes PCB to pipe using the command defined by Settings.SaveCommand
 
528
static void
 
529
WriteLayerData (FILE * FP, Cardinal Number, LayerTypePtr layer)
 
530
{
 
531
  int n;
 
532
  /* write information about non empty layers */
 
533
  if (layer->LineN || layer->ArcN || layer->TextN || layer->PolygonN ||
 
534
      (layer->Name && *layer->Name))
 
535
    {
 
536
      fprintf (FP, "Layer(%i ", (int) Number + 1);
 
537
      PrintQuotedString (FP, EMPTY (layer->Name));
 
538
      fputs (")\n(\n", FP);
 
539
 
 
540
      for (n = 0; n < layer->LineN; n++)
 
541
        {
 
542
          LineTypePtr line = &layer->Line[n];
 
543
          fprintf (FP, "\tLine[%i %i %i %i %i %i 0x%08x]\n",
 
544
                   (int) line->Point1.X, (int) line->Point1.Y,
 
545
                   (int) line->Point2.X, (int) line->Point2.Y,
 
546
                   (int) line->Thickness, (int) line->Clearance,
 
547
                   (int) line->Flags);
 
548
        }
 
549
      for (n = 0; n < layer->ArcN; n++)
 
550
        {
 
551
          ArcTypePtr arc = &layer->Arc[n];
 
552
          fprintf (FP, "\tArc[%i %i %i %i %i %i %i %i 0x%08x]\n",
 
553
                   (int) arc->X, (int) arc->Y, (int) arc->Width,
 
554
                   (int) arc->Height, (int) arc->Thickness,
 
555
                   (int) arc->Clearance, (int) arc->StartAngle,
 
556
                   (int) arc->Delta, (int) arc->Flags);
 
557
        }
 
558
      for (n = 0; n < layer->TextN; n++)
 
559
        {
 
560
          TextTypePtr text = &layer->Text[n];
 
561
          fprintf (FP, "\tText[%i %i %i %i ",
 
562
                   (int) text->X, (int) text->Y,
 
563
                   (int) text->Direction, (int) text->Scale);
 
564
          PrintQuotedString (FP, EMPTY (text->TextString));
 
565
          fprintf (FP, " 0x%08x]\n", (int) text->Flags);
 
566
        }
 
567
      for (n = 0; n < layer->PolygonN; n++)
 
568
        {
 
569
          PolygonTypePtr polygon = &layer->Polygon[n];
 
570
          int p, i = 0;
 
571
          fprintf (FP, "\tPolygon(0x%08x)\n\t(", (int) polygon->Flags);
 
572
          for (p = 0; p < polygon->PointN; p++)
 
573
            {
 
574
              PointTypePtr point = &polygon->Points[p];
 
575
              if (i++ % 5 == 0)
 
576
                fputs ("\n\t\t", FP);
 
577
              fprintf (FP, "[%i %i] ", (int) point->X, (int) point->Y);
 
578
            }
 
579
          fputs ("\n\t)\n", FP);
 
580
        }
 
581
      fputs (")\n", FP);
 
582
    }
 
583
}
 
584
 
 
585
/* ---------------------------------------------------------------------------
 
586
 * writes just the elements in the buffer to file
 
587
 */
 
588
static int
 
589
WriteBuffer (FILE * FP)
 
590
{
 
591
  Cardinal i;
 
592
 
 
593
  WriteViaData (FP, PASTEBUFFER->Data);
 
594
  WriteElementData (FP, PASTEBUFFER->Data);
 
595
  for (i = 0; i < MAX_LAYER + 2; i++)
 
596
    WriteLayerData (FP, i, &(PASTEBUFFER->Data->Layer[i]));
 
597
  return (STATUS_OK);
 
598
}
 
599
 
 
600
/* ---------------------------------------------------------------------------
 
601
 * writes PCB to file
 
602
 */
 
603
static int
 
604
WritePCB (FILE * FP)
 
605
{
 
606
  Cardinal i;
 
607
 
 
608
  WritePCBInfoHeader (FP);
 
609
  WritePCBDataHeader (FP);
 
610
  WritePCBFontData (FP);
 
611
  WriteViaData (FP, PCB->Data);
 
612
  WriteElementData (FP, PCB->Data);
 
613
  WritePCBRatData (FP);
 
614
  for (i = 0; i < MAX_LAYER + 2; i++)
 
615
    WriteLayerData (FP, i, &(PCB->Data->Layer[i]));
 
616
  WritePCBNetlistData (FP);
 
617
 
 
618
  return (STATUS_OK);
 
619
}
 
620
 
 
621
/* ---------------------------------------------------------------------------
 
622
 * writes PCB to file
 
623
 */
 
624
static int
 
625
WritePCBFile (char *Filename)
 
626
{
 
627
  FILE *fp;
 
628
  int result;
 
629
 
 
630
  if ((fp = fopen (Filename, "w")) == NULL)
 
631
    {
 
632
      OpenErrorMessage (Filename);
 
633
      return (STATUS_ERROR);
 
634
    }
 
635
  result = WritePCB (fp);
 
636
  fclose (fp);
 
637
  return (result);
 
638
}
 
639
 
 
640
/* ---------------------------------------------------------------------------
 
641
 * writes to pipe using the command defined by Settings.SaveCommand
547
642
 * %f are replaced by the passed filename
548
643
 */
549
 
static int WritePCBPipe(char *Filename)
 
644
static int
 
645
WritePipe (char *Filename, Boolean thePcb)
550
646
{
551
 
        FILE                            *fp;
552
 
        int                             result;
553
 
        char                            *p;
554
 
        static  DynamicStringType       command;
555
 
 
556
 
                /* setup commandline */
557
 
        DSClearString(&command);
558
 
        for (p = Settings.SaveCommand; *p; p++)
559
 
        {
560
 
                        /* copy character if not special or add string to command */
561
 
                if (!(*p == '%' && *(p+1) == 'f'))
562
 
                        DSAddCharacter(&command, *p);
563
 
                else
564
 
                {
565
 
                        DSAddString(&command, Filename);
566
 
 
567
 
                                /* skip the character */
568
 
                        p++;
569
 
                }
570
 
        }
571
 
        DSAddCharacter(&command, '\0');
572
 
 
573
 
        if ((fp = popen(command.Data, "w")) == NULL)
574
 
        {
575
 
                PopenErrorMessage(command.Data);
576
 
                return(STATUS_ERROR);
577
 
        }
578
 
        result = WritePCB(fp);
579
 
        return(pclose(fp) ? STATUS_ERROR : result);
 
647
  FILE *fp;
 
648
  int result;
 
649
  char *p;
 
650
  static DynamicStringType command;
 
651
 
 
652
  /* setup commandline */
 
653
  DSClearString (&command);
 
654
  for (p = Settings.SaveCommand; *p; p++)
 
655
    {
 
656
      /* copy character if not special or add string to command */
 
657
      if (!(*p == '%' && *(p + 1) == 'f'))
 
658
        DSAddCharacter (&command, *p);
 
659
      else
 
660
        {
 
661
          DSAddString (&command, Filename);
 
662
 
 
663
          /* skip the character */
 
664
          p++;
 
665
        }
 
666
    }
 
667
  DSAddCharacter (&command, '\0');
 
668
 
 
669
  if ((fp = popen (command.Data, "w")) == NULL)
 
670
    {
 
671
      PopenErrorMessage (command.Data);
 
672
      return (STATUS_ERROR);
 
673
    }
 
674
  if (thePcb)
 
675
    result = WritePCB (fp);
 
676
  else
 
677
    result = WriteBuffer (fp);
 
678
  return (pclose (fp) ? STATUS_ERROR : result);
580
679
}
581
680
 
582
681
#if defined(HAS_ON_EXIT)
583
682
/* ---------------------------------------------------------------------------
584
683
 * just a glue function for systems with on_exit()
585
684
 */
586
 
void GlueEmergencySave(int status, caddr_t arg)
 
685
void
 
686
GlueEmergencySave (int status, caddr_t arg)
587
687
{
588
 
        if (status)
589
 
                EmergencySave();
 
688
  if (status)
 
689
    EmergencySave ();
590
690
}
591
691
#endif
592
692
 
595
695
 * this is used for fatal errors and does not call the program specified
596
696
 * in 'saveCommand' for savety reasons
597
697
 */
598
 
void SaveInTMP(void)
 
698
void
 
699
SaveInTMP (void)
599
700
{
600
 
        char    filename[80];
 
701
  char filename[80];
601
702
 
602
 
                /* memory might have been released before this function is called */
603
 
        if (PCB && PCB->Changed)
604
 
        {
605
 
                sprintf(filename, EMERGENCY_NAME, (int) getpid());
606
 
                Message("trying to save your layout in '%s'\n", filename);
607
 
                WritePCBFile(filename);
608
 
        }
 
703
  /* memory might have been released before this function is called */
 
704
  if (PCB && PCB->Changed)
 
705
    {
 
706
      sprintf (filename, EMERGENCY_NAME, (int) getpid ());
 
707
      Message ("trying to save your layout in '%s'\n", filename);
 
708
      WritePCBFile (filename);
 
709
    }
609
710
}
610
711
 
611
712
/* ---------------------------------------------------------------------------
612
713
 * front-end for 'SaveInTMP()'
613
714
 * justs makes sure that the routine is only called once
614
715
 */
615
 
void EmergencySave(void)
 
716
void
 
717
EmergencySave (void)
616
718
{
617
 
        static  Boolean already_called = False;
 
719
  static Boolean already_called = False;
618
720
 
619
 
        if (!already_called)
620
 
        {
621
 
                        /* in case of an emergency it's necessary to use the original
622
 
                         * error descriptor
623
 
                         */
624
 
                RestoreStderr();
625
 
                SaveInTMP();
626
 
                already_called = True;
627
 
        }
 
721
  if (!already_called)
 
722
    {
 
723
      /* in case of an emergency it's necessary to use the original
 
724
       * error descriptor
 
725
       */
 
726
      RestoreStderr ();
 
727
      SaveInTMP ();
 
728
      already_called = True;
 
729
    }
628
730
}
629
731
 
630
732
/* ---------------------------------------------------------------------------
631
733
 * creates backup file
632
734
 */
633
 
void Backup(void)
 
735
void
 
736
Backup (void)
634
737
{
635
 
        char    filename[80];
 
738
  char filename[80];
636
739
 
637
 
        sprintf(filename, BACKUP_NAME, (int) getpid());
638
 
        WritePCBFile(filename);
 
740
  sprintf (filename, BACKUP_NAME, (int) getpid ());
 
741
  WritePCBFile (filename);
639
742
}
640
743
 
641
744
#if !defined(HAS_ATEXIT) && !defined(HAS_ON_EXIT)
645
748
 * before LEX and YACC functions are called because they are able to abort
646
749
 * the program.
647
750
 */
648
 
void SaveTMPData(void)
 
751
void
 
752
SaveTMPData (void)
649
753
{
650
 
        sprintf(TMPFilename, EMERGENCY_NAME, (int) getpid());
651
 
        WritePCBFile(TMPFilename);
 
754
  sprintf (TMPFilename, EMERGENCY_NAME, (int) getpid ());
 
755
  WritePCBFile (TMPFilename);
652
756
}
653
757
 
654
758
/* ---------------------------------------------------------------------------
655
759
 * removes the temporary copy of the data file
656
760
 */
657
 
void RemoveTMPData(void)
658
 
{
659
 
        unlink(TMPFilename);
660
 
}
661
 
#endif
 
761
void
 
762
RemoveTMPData (void)
 
763
{
 
764
  unlink (TMPFilename);
 
765
}
 
766
#endif
 
767
 
 
768
/* ---------------------------------------------------------------------------
 
769
 * parse the directory tree where additional library elements are found
 
770
 */
 
771
void
 
772
ParseLibraryTree (void)
 
773
{
 
774
  char path[MAXPATHLEN + 1];
 
775
  char working[MAXPATHLEN + 1];
 
776
  char *libpaths, *p;
 
777
  DIR *dir, *subdir;
 
778
  struct stat buffer;
 
779
  struct dirent *direntry, *e2;
 
780
  LibraryMenuTypePtr menu = NULL;
 
781
  LibraryEntryTypePtr entry;
 
782
 
 
783
  memset (path, 0, sizeof path);
 
784
  memset (working, 0, sizeof working);
 
785
 
 
786
  /* save the current working directory */
 
787
  GetWorkingDirectory (working);
 
788
 
 
789
  /* Additional loop to allow for multiple 'newlib' style library directories */
 
790
  libpaths = MyStrdup (Settings.LibraryTree, "ParseLibraryTree");
 
791
  for (p = strtok (libpaths, ":"); p && *p; p = strtok (NULL, ":"))
 
792
    {
 
793
      strncpy (path, p, sizeof (path) - 1);
 
794
 
 
795
      /* 
 
796
       * start out in the working directory in case the path is a
 
797
       * relative path 
 
798
       */
 
799
      chdir (working);
 
800
 
 
801
      if ((dir = opendir (path)) == NULL)
 
802
        {
 
803
          OpendirErrorMessage (path);
 
804
          continue;
 
805
        }
 
806
 
 
807
      /*
 
808
       * change to the directory which is the top of the library tree
 
809
       * and then extract that directory to ensure we have a full path
 
810
       * name, not a relative path name.
 
811
       */
 
812
      chdir (path);
 
813
      GetWorkingDirectory (path);
 
814
 
 
815
      /* read all entries */
 
816
      while ((direntry = readdir (dir)) != NULL)
 
817
        {
 
818
          chdir (path);
 
819
          /* find directories
 
820
           * ignore entries beginning with "." and CVS
 
821
           * directories
 
822
           */
 
823
          if (!stat (direntry->d_name, &buffer)
 
824
              && S_ISDIR (buffer.st_mode) && direntry->d_name[0] != '.'
 
825
              && NSTRCMP (direntry->d_name, "CVS") != 0)
 
826
            {
 
827
              /* add directory name into menu */
 
828
              menu = GetLibraryMenuMemory (&Library);
 
829
              menu->Name = MyStrdup (direntry->d_name, "ParseLibraryTree()");
 
830
              subdir = opendir (direntry->d_name);
 
831
              chdir (direntry->d_name);
 
832
              while (subdir && (e2 = readdir (subdir)))
 
833
                {
 
834
                  if (!stat (e2->d_name, &buffer) && S_ISREG (buffer.st_mode)
 
835
                      && e2->d_name[0] != '.'
 
836
                      && NSTRCMP (e2->d_name, "CVS") != 0
 
837
                      && NSTRCMP (e2->d_name, "Makefile") != 0
 
838
                      && NSTRCMP (e2->d_name, "Makefile.am") != 0
 
839
                      && NSTRCMP (e2->d_name, "Makefile.in") != 0 )
 
840
                {
 
841
                      long len = strlen (path) + strlen (e2->d_name) +
 
842
                        strlen (direntry->d_name) + 3;
 
843
#if 0
 
844
                      if (NSTRCMP
 
845
                          (e2->d_name + strlen (e2->d_name) - 4, ".lel") != 0)
 
846
                        break;
 
847
#endif
 
848
                      entry = GetLibraryEntryMemory (menu);
 
849
                      entry->AllocatedMemory = MyCalloc (1, len,
 
850
                                                         "ParseLibraryTree()");
 
851
                      strcat (entry->AllocatedMemory, path);
 
852
                      strcat (entry->AllocatedMemory, "/");
 
853
                      strcat (entry->AllocatedMemory, direntry->d_name);
 
854
                      strcat (entry->AllocatedMemory, "/");
 
855
                      entry->ListEntry = entry->AllocatedMemory
 
856
                        + strlen (entry->AllocatedMemory);
 
857
                      strcat (entry->AllocatedMemory, e2->d_name);
 
858
                      /* mark as directory tree library */
 
859
                      entry->Template = (char *) -1;
 
860
                    }
 
861
                }
 
862
              closedir (subdir);
 
863
            }
 
864
        }
 
865
      closedir (dir);
 
866
    }
 
867
  free (libpaths);
 
868
 
 
869
  /* restore the original working directory */
 
870
  chdir (working);
 
871
}
662
872
 
663
873
/* ---------------------------------------------------------------------------
664
874
 * read contents of the library description file
 
875
 * also parse a special library directory tree
665
876
 */
666
 
int ReadLibraryContents(void)
 
877
int
 
878
ReadLibraryContents (void)
667
879
{
668
 
        static  char            *command = NULL;
669
 
        char                    inputline[MAX_LIBRARY_LINE_LENGTH+1];
670
 
        FILE                    *resultFP;
671
 
        LibraryMenuTypePtr      menu;
672
 
        LibraryEntryTypePtr     entry;
673
 
 
674
 
                /* release old command string */
675
 
        MyFree(&command);
676
 
        command = EvaluateFilename(Settings.LibraryContentsCommand,
677
 
                Settings.LibraryPath, Settings.LibraryFilename, NULL);
678
 
 
679
 
                /* open a pipe to the output of the command */
680
 
        if ((resultFP = popen(command, "r")) == NULL)
681
 
        {
682
 
                PopenErrorMessage(command);
683
 
                return(1);
684
 
        }
685
 
 
686
 
                /* the library contents are seperated by colons;
687
 
                 * template : package : name : description
688
 
                 */
689
 
        while(fgets(inputline, MAX_LIBRARY_LINE_LENGTH, resultFP))
690
 
        {
691
 
                size_t  len = strlen(inputline);
692
 
 
693
 
                        /* check for maximum linelength */
694
 
                if (len)
695
 
                {
696
 
                        len--;
697
 
                        if (inputline[len] != '\n')
698
 
                                Message("linelength (%i) exceeded; following characters will be ignored\n", MAX_LIBRARY_LINE_LENGTH);
699
 
                        else
700
 
                                inputline[len] = '\0';
701
 
                }
702
 
 
703
 
                        /* if the line defines a menu */
704
 
                if (!strncmp(inputline, "TYPE=", 5))
705
 
                {
706
 
                        menu = GetLibraryMenuMemory(&Library);
707
 
                        menu->Name = MyStrdup(UNKNOWN(&inputline[5]),
708
 
                                "ReadLibraryDescription()");
709
 
                }
710
 
                else
711
 
                {
712
 
                                /* allocate a new menu entry if not already done */
713
 
                        if (!menu)
714
 
                        {
715
 
                                menu = GetLibraryMenuMemory(&Library);
716
 
                                menu->Name = MyStrdup(UNKNOWN((char *) NULL),
717
 
                                        "ReadLibraryDescription()");
718
 
                        }
719
 
                        entry = GetLibraryEntryMemory(menu);
720
 
                        entry->AllocatedMemory = MyStrdup(inputline,
721
 
                                "ReadLibraryDescription()");
722
 
 
723
 
                                /* now break the line into pieces separated by colons */
724
 
                        if ((entry->Template = strtok(entry->AllocatedMemory, ":")) != NULL)
725
 
                                if ((entry->Package= strtok(NULL, ":")) != NULL)
726
 
                                        if ((entry->Value = strtok(NULL, ":")) != NULL)
727
 
                                                entry->Description = strtok(NULL, ":");
728
 
 
729
 
                                /* create the list entry */
730
 
                        len = strlen(EMPTY(entry->Value)) +
731
 
                                strlen(EMPTY(entry->Description)) +3;
732
 
                        entry->ListEntry = MyCalloc(len, sizeof(char),
733
 
                                "ReadLibraryDescription()");
734
 
                        sprintf(entry->ListEntry,
735
 
                                "%s, %s", EMPTY(entry->Value), EMPTY(entry->Description));
736
 
                }
737
 
        }
738
 
 
739
 
        return(pclose(resultFP));
 
880
  static char *command = NULL;
 
881
  char inputline[MAX_LIBRARY_LINE_LENGTH + 1];
 
882
  FILE *resultFP;
 
883
  LibraryMenuTypePtr menu = NULL;
 
884
  LibraryEntryTypePtr entry;
 
885
 
 
886
  /* release old command string */
 
887
  MyFree (&command);
 
888
  command = EvaluateFilename (Settings.LibraryContentsCommand,
 
889
                              Settings.LibraryPath, Settings.LibraryFilename,
 
890
                              NULL);
 
891
 
 
892
  /* open a pipe to the output of the command */
 
893
  if ((resultFP = popen (command, "r")) == NULL)
 
894
    {
 
895
      PopenErrorMessage (command);
 
896
      return (1);
 
897
    }
 
898
 
 
899
  /* the library contents are seperated by colons;
 
900
   * template : package : name : description
 
901
   */
 
902
  while (fgets (inputline, MAX_LIBRARY_LINE_LENGTH, resultFP))
 
903
    {
 
904
      size_t len = strlen (inputline);
 
905
 
 
906
      /* check for maximum linelength */
 
907
      if (len)
 
908
        {
 
909
          len--;
 
910
          if (inputline[len] != '\n')
 
911
            Message
 
912
              ("linelength (%i) exceeded; following characters will be ignored\n",
 
913
               MAX_LIBRARY_LINE_LENGTH);
 
914
          else
 
915
            inputline[len] = '\0';
 
916
        }
 
917
 
 
918
      /* if the line defines a menu */
 
919
      if (!strncmp (inputline, "TYPE=", 5))
 
920
        {
 
921
          menu = GetLibraryMenuMemory (&Library);
 
922
          menu->Name = MyStrdup (UNKNOWN (&inputline[5]),
 
923
                                 "ReadLibraryDescription()");
 
924
        }
 
925
      else
 
926
        {
 
927
          /* allocate a new menu entry if not already done */
 
928
          if (!menu)
 
929
            {
 
930
              menu = GetLibraryMenuMemory (&Library);
 
931
              menu->Name = MyStrdup (UNKNOWN ((char *) NULL),
 
932
                                     "ReadLibraryDescription()");
 
933
            }
 
934
          entry = GetLibraryEntryMemory (menu);
 
935
          entry->AllocatedMemory = MyStrdup (inputline,
 
936
                                             "ReadLibraryDescription()");
 
937
 
 
938
          /* now break the line into pieces separated by colons */
 
939
          if ((entry->Template = strtok (entry->AllocatedMemory, ":")) !=
 
940
              NULL)
 
941
            if ((entry->Package = strtok (NULL, ":")) != NULL)
 
942
              if ((entry->Value = strtok (NULL, ":")) != NULL)
 
943
                entry->Description = strtok (NULL, ":");
 
944
 
 
945
          /* create the list entry */
 
946
          len = strlen (EMPTY (entry->Value)) +
 
947
            strlen (EMPTY (entry->Description)) + 3;
 
948
          entry->ListEntry = MyCalloc (len, sizeof (char),
 
949
                                       "ReadLibraryDescription()");
 
950
          sprintf (entry->ListEntry,
 
951
                   "%s, %s", EMPTY (entry->Value),
 
952
                   EMPTY (entry->Description));
 
953
        }
 
954
    }
 
955
  ParseLibraryTree ();
 
956
  return (pclose (resultFP));
740
957
}
741
958
 
742
959
#define BLANK(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' \
743
960
                || (x) == '\0')
744
 
        
 
961
 
745
962
/* ---------------------------------------------------------------------------
746
963
 * Read in a netlist and store it in the netlist menu 
747
964
 */
748
 
 
749
 
 int    ReadNetlist(char *filename)
750
 
 {
751
 
        static  char            *command = NULL;
752
 
        char                    inputline[MAX_NETLIST_LINE_LENGTH + 1];
753
 
        char                    temp[MAX_NETLIST_LINE_LENGTH + 1];
754
 
        FILE                    *fp;
755
 
        LibraryMenuTypePtr      menu;
756
 
        LibraryEntryTypePtr     entry;
757
 
        int                     i, j, lines, kind;
758
 
        Boolean                 continued;
759
 
        
760
 
        if (!filename)
761
 
                return(1);              /* nothing to do */
762
 
        MyFree(&command);
763
 
        command = EvaluateFilename(Settings.RatCommand,
764
 
                        Settings.RatPath, filename, NULL);
765
 
        
766
 
                /* open pipe to stdout of command */
767
 
        if (*command == '\0' || (fp = popen(command, "r")) == NULL)
768
 
        {
769
 
                PopenErrorMessage(command);
770
 
                return(1);
771
 
        }
772
 
        lines = 0;
773
 
                /* kind = 0  is net name
774
 
                 * kind = 1  is route style name
775
 
                 * kind = 2  is connection
776
 
                 */
 
965
 
 
966
int
 
967
ReadNetlist (char *filename)
 
968
{
 
969
  static char *command = NULL;
 
970
  char inputline[MAX_NETLIST_LINE_LENGTH + 1];
 
971
  char temp[MAX_NETLIST_LINE_LENGTH + 1];
 
972
  FILE *fp;
 
973
  LibraryMenuTypePtr menu = NULL;
 
974
  LibraryEntryTypePtr entry;
 
975
  int i, j, lines, kind;
 
976
  Boolean continued;
 
977
 
 
978
  if (!filename)
 
979
    return (1);                 /* nothing to do */
 
980
  MyFree (&command);
 
981
  command = EvaluateFilename (Settings.RatCommand,
 
982
                              Settings.RatPath, filename, NULL);
 
983
 
 
984
  /* open pipe to stdout of command */
 
985
  if (*command == '\0' || (fp = popen (command, "r")) == NULL)
 
986
    {
 
987
      PopenErrorMessage (command);
 
988
      return (1);
 
989
    }
 
990
  lines = 0;
 
991
  /* kind = 0  is net name
 
992
   * kind = 1  is route style name
 
993
   * kind = 2  is connection
 
994
   */
 
995
  kind = 0;
 
996
  while (fgets (inputline, MAX_NETLIST_LINE_LENGTH, fp))
 
997
    {
 
998
      size_t len = strlen (inputline);
 
999
      /* check for maximum length line */
 
1000
      if (len)
 
1001
        {
 
1002
          if (inputline[--len] != '\n')
 
1003
            Message ("line length (%i) exceeded in netlist file.\n"
 
1004
                     "additional characters will be ignored.\n",
 
1005
                     MAX_NETLIST_LINE_LENGTH);
 
1006
          else
 
1007
            inputline[len] = '\0';
 
1008
        }
 
1009
      continued = (inputline[len - 1] == '\\') ? True : False;
 
1010
      if (continued)
 
1011
        inputline[len - 1] = '\0';
 
1012
      lines++;
 
1013
      i = 0;
 
1014
      while (inputline[i] != '\0')
 
1015
        {
 
1016
          j = 0;
 
1017
          /* skip leading blanks */
 
1018
          while (inputline[i] != '\0' && BLANK (inputline[i]))
 
1019
            i++;
 
1020
          if (kind == 0)
 
1021
            {
 
1022
              /* add two spaces for included/unincluded */
 
1023
              temp[j++] = ' ';
 
1024
              temp[j++] = ' ';
 
1025
            }
 
1026
          while (!BLANK (inputline[i]))
 
1027
            temp[j++] = inputline[i++];
 
1028
          temp[j] = '\0';
 
1029
          while (inputline[i] != '\0' && BLANK (inputline[i]))
 
1030
            i++;
 
1031
          if (kind == 0)
 
1032
            {
 
1033
              menu = GetLibraryMenuMemory (&PCB->NetlistLib);
 
1034
              menu->Name = MyStrdup (temp, "ReadNetlist()");
 
1035
              kind++;
 
1036
            }
 
1037
          else
 
1038
            {
 
1039
              if (kind == 1 && strchr (temp, '-') == NULL)
 
1040
                {
 
1041
                  kind++;
 
1042
                  menu->Style = MyStrdup (temp, "ReadNetlist()");
 
1043
                }
 
1044
              else
 
1045
                {
 
1046
                  entry = GetLibraryEntryMemory (menu);
 
1047
                  entry->ListEntry = MyStrdup (temp, "ReadNetlist()");
 
1048
                }
 
1049
            }
 
1050
        }
 
1051
      if (!continued)
777
1052
        kind = 0;
778
 
        while (fgets(inputline, MAX_NETLIST_LINE_LENGTH, fp))
779
 
        {
780
 
                size_t  len = strlen(inputline);
781
 
                        /* check for maximum length line */
782
 
                if (len)
783
 
                {
784
 
                        if (inputline[--len] != '\n')
785
 
                                Message("line length (%i) exceeded in netlist file.\n"
786
 
                                        "additional characters will be ignored.\n",
787
 
                                        MAX_NETLIST_LINE_LENGTH);
788
 
                        else
789
 
                                inputline[len] = '\0';
790
 
                }
791
 
                continued = (inputline[len-1] == '\\') ? True : False;
792
 
                if (continued)
793
 
                        inputline[len-1] = '\0';
794
 
                lines++;
795
 
                i = 0;
796
 
                while (inputline[i] != '\0')
797
 
                {
798
 
                        j = 0;
799
 
                                /* skip leading blanks */
800
 
                        while(inputline[i] != '\0' && BLANK(inputline[i]))
801
 
                                i++;
802
 
                        if (kind == 0)
803
 
                        {
804
 
                        /* add two spaces for included/unincluded */
805
 
                                temp[j++] = ' ';
806
 
                                temp[j++] = ' ';
807
 
                        }
808
 
                        while(!BLANK(inputline[i]))
809
 
                                temp[j++] = inputline[i++];
810
 
                        temp[j] = '\0';
811
 
                        while(inputline[i] != '\0' && BLANK(inputline[i]))
812
 
                                i++;
813
 
                        if (kind == 0)
814
 
                        {
815
 
                                menu = GetLibraryMenuMemory(&PCB->NetlistLib);
816
 
                                menu->Name = MyStrdup(temp, "ReadNetlist()");
817
 
                                kind++;
818
 
                        }
819
 
                        else
820
 
                        {
821
 
                                if (kind == 1 && strchr(temp, '-') == NULL)
822
 
                                {
823
 
                                        kind++;
824
 
                                        menu->Style = MyStrdup(temp, "ReadNetlist()");
825
 
                                }
826
 
                                else
827
 
                                {
828
 
                                        entry = GetLibraryEntryMemory(menu);
829
 
                                        entry->ListEntry = MyStrdup(temp, "ReadNetlist()");
830
 
                                }
831
 
                        }
832
 
                }
833
 
                if (!continued)
834
 
                        kind = 0;
835
 
        }
836
 
        if (!lines)
837
 
        {
838
 
                Message("Empty netlist file!\n");
839
 
                pclose(fp);
840
 
                return(1);
841
 
        }
842
 
        pclose(fp);
843
 
        return(0);
 
1053
    }
 
1054
  if (!lines)
 
1055
    {
 
1056
      Message ("Empty netlist file!\n");
 
1057
      pclose (fp);
 
1058
      return (1);
 
1059
    }
 
1060
  pclose (fp);
 
1061
  return (0);
844
1062
}