2 /* This is grenum, an advanced refdes renumber utility for gEDA's gschem.
4 * Copyright (C) 2005-2006 Levente Kovacs
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Levente.Kovacs@interware.hu
50 int main(int argc
, char *argv
[])
52 FILE *infile
,*outfile
;
53 char buff
[BUFFSIZE
], infilename
[FILENAMESIZE
], outfilename
[FILENAMESIZE
];
58 #ifdef HAVE_GETOPT_LONG
60 const struct option long_opts
[]={
61 {"version", no_argument
, NULL
, 'v'},
62 {"help", no_argument
, NULL
, 'h'},
63 {"pagejump", no_argument
, NULL
, 'p'},
66 const char *opt_options
= "vhp";
68 struct refdes_ refdes
, refdes_db
[MAX_PREFIX_COUNT
];
70 flags
=0x00; /*Clear all flags*/
74 #ifdef HAVE_GETOPT_LONG
75 c
= getopt_long(argc
, argv
, opt_options
, long_opts
, &opt_idx
);
77 c
= getopt(argc
, argv
, opt_options
);
90 flags
|=PAGEJUMP
; /*Set the pagejump flag*/
96 printf("grenum: no input file\n");
100 for(c
=0;c
<MAX_PREFIX_COUNT
;++c
)
102 refdes_db
[c
].prefix
[0]='\0'; /*Zero all the strings in the database.*/
103 refdes_db
[c
].value
=COUNT_START
;
106 for(pages
=1;optind
<argc
;++optind
,++pages
)
108 if((flags
&PAGEJUMP
)==PAGEJUMP
) /*pagejumps*/
110 for(c
=0;c
<MAX_PREFIX_COUNT
;++c
)
111 refdes_db
[c
].value
=PAGE_JMP
*pages
+COUNT_START
; /*Reset the counters according to page numbers*/
113 strcpy(&infilename
[0],argv
[optind
]); /*Copy the filename to the buffer*/
114 if((infile
=fopen(infilename
, "r")) == NULL
) /*Open file, use r+ for read and write*/
116 perror("grenum: unable to open input file");
117 return FILE_OP_ERROR
;
119 strcpy(&outfilename
[0],&infilename
[0]);
120 if((outfile
=fopen(strcat(&outfilename
[0],".tmp"),"w"))==NULL
)
122 perror("grenum: could not create tmp file");
123 fclose(infile
); /*Close the file*/
124 return FILE_OP_ERROR
;
126 printf("grenum: processing file %s\n",&infilename
[0]);
127 while((ret
=get_refdes_from_file(infile
, &refdes
, buff
))!=END_OF_FILE
) /*Read one line.*/
128 { /*Process starts here*/
130 printf("%s\n",&buff
[0]); /*Print out what is read*/
134 case NOT_REFDES_LINE
:
135 if(fputs(buff
,outfile
)==-1)
137 perror("grenum: could not write to tmp file");
138 fclose(infile
); /*Close the files*/
140 return FILE_OP_ERROR
;
143 case REFDES_WITH_VALUE
: /*We shall compare the maximum value, shall search for gaps, and set the refes_db.value to the next free value*/
144 c
=refdes_lookup(refdes_db
, &refdes
);
147 case REFDES_NOT_FOUND
: /*No such prefix*/
148 strcpy(&refdes_db
[refdes
.prefixes
].prefix
[0],&refdes
.prefix
[0]); /*Register the prefix to the database*/
149 refdes_db
[refdes
.prefixes
+1].prefix
[0]='\0';
150 refdes_db
[refdes
.prefixes
].value
=refdes
.value
; /*Renumber... Finally :-)*/
152 case MAX_PREFIX_COUNT
: /*Out of memory*/
153 printf("grenum: out of memory. Too much refdes prefixes.\n");
154 fclose(infile
); /*Close the files*/
156 return OUT_OF_MEMORY
;
158 if(refdes
.value
-refdes_db
[c
].value
==1) /*If we have the next value, don't do anything, just update the database.*/
160 refdes_db
[c
].value
=refdes
.value
;
163 /*Now we have a hole in numbering. Let's see if it'll be fixed, and seek for the maximum value. eg. R1,R2,R5,R3. So, we have to search for R3,R4, and set the db to R3.*/
165 for(i
=refdes_db
[c
].value
+1; i
<refdes
.value
; ++i
)
167 if(seek_value(c
, infile
, i
, refdes_db
)==VALUE_NOT_FOUND
)
169 refdes_db
[c
].value
=i
-1;
176 flags
|=~GAP_DETECTED
;
179 break; /*continue our job*/
180 case REFDES_WITHOUT_VALUE
:
181 c
=refdes_lookup(refdes_db
, &refdes
);
184 case -1: /*No such prefix*/
185 strcpy(&refdes_db
[refdes
.prefixes
].prefix
[0],&refdes
.prefix
[0]);
186 refdes
.value
=++refdes_db
[refdes
.prefixes
].value
;
187 refdes_db
[refdes
.prefixes
+1].prefix
[0]='\0';
189 case MAX_PREFIX_COUNT
:
190 printf("grenum: out of memory. Too much refdes prefixes.\n");
191 fclose(infile
); /*Close the files*/
193 return OUT_OF_MEMORY
;
195 if((flags
&GAP_DETECTED
)==GAP_DETECTED
)
197 for(i
=refdes_db
[c
].value
+1; seek_value(c
, infile
, i
, refdes_db
)!=VALUE_NOT_FOUND
; ++i
);
198 refdes
.value
=refdes_db
[c
].value
=i
;
201 refdes
.value
=++refdes_db
[c
].value
; /*renumber*/
204 sprintf(buff
, "refdes=%s%d\n", &refdes
.prefix
[0], refdes
.value
);
206 case REFDES_ERROR
: /*e.g. awdf#$%WSf82f8 :-) No "=" signal in the refdes string.*/
207 printf("grenum: parse error\n");
208 fclose(infile
); /*Close the files*/
212 if(fputs(buff
,outfile
)==-1) /*Finally, write the refdes line to the output file*/
214 perror("grenum: could not write to tmp file");
215 fclose(infile
); /*Close the files*/
217 return FILE_OP_ERROR
;
219 } /*Process ends here*/
222 strcpy(&buff
[0],&infilename
[0]); /*buff has the original infilename*/
223 /*The next few lines implements the copy program*/
224 fseek(infile
,0L,SEEK_SET
); /*Go to the begining of the infile*/
225 outfile
=fopen(strcat(&buff
[0],".save"),"w");
228 perror("grenum: ould not create backup file");
229 fclose(infile
); /*Close the file*/
230 return FILE_OP_ERROR
;
232 while(fgets(&buff
[0],BUFFSIZE
,infile
)!=NULL
) /*Read one line.*/
234 if(fputs(&buff
[0],outfile
)==-1)
236 perror("grenum: could not write to backup file");
237 fclose(infile
); /*Close the files*/
239 return FILE_OP_ERROR
;
244 rename(outfilename
, infilename
); /*Move the tmpfile to the original*/
246 printf("grenum: file(s) successfully processed\n");
247 return OK
; /*Everything is okay*/
250 int get_refdes_from_file(FILE *fp
, struct refdes_
*refdes
, char *buff
)
253 /* Read one line from file, and return the following things:
255 * END_OF_FILE if file reaches its end. The content of buff is unknown!
257 * NOT_REFDES_LINE if the current line is not a refdes. The line will
260 * Return according to parse_refdes(). The buff will contain the current line too.
263 if(fgets(buff
, BUFFSIZE
, fp
)==NULL
)
265 if(strstr(buff
, "refdes=")==NULL
)
266 return NOT_REFDES_LINE
;
267 return parse_refdes(refdes
, buff
);
270 int seek_value(int prefix
, FILE *fp
, unsigned int value
, struct refdes_
*db
)
274 struct refdes_ refdes
;
277 fgetpos(fp
, &filepos
); /*First of all, save the file pos.*/
278 rewind(fp
); /*Rewind*/
279 while((ret
=get_refdes_from_file(fp
, &refdes
, buff
))!=END_OF_FILE
)
281 if(ret
==REFDES_WITH_VALUE
&& prefix
==refdes_lookup(db
, &refdes
) && refdes
.value
==value
)
283 fsetpos(fp
,&filepos
);
287 fsetpos(fp
,&filepos
);
288 return VALUE_NOT_FOUND
;
291 int parse_refdes(struct refdes_
*refdes
, char *ref_str
)
294 char buff
[BUFFSIZE
],*cpr
,*cp
;
297 * This function parses the refdes line from the .sch file. It takes a pointer to the
298 * complete refdes definition string, and a pointer which points to a refdes structure
299 * where it'll store the info.
301 * parse_refdes() will return
303 * REFDES_WITH_VALUE if there was a prefix with renumbered value
304 * (for example R1,IC3,U5);
306 * REFDES_WITHOUT_VALUE if there was a "?" mark found, and it has to be
307 * renumbered (e.g. U?);
309 * REFDES_ERROR, if there was some uncool thing.
311 * The refdes structure is filled with the prefix and the value.
313 * Note that if a "?" is found, the value member remains untouched.
317 cpr
=strstr(ref_str
,"="); /*seek for the "="*/
318 if(cpr
==NULL
) /*This should not happen*/
320 cp
=strstr(ref_str
,"?");
321 /*refdes=U1 refdes=IC?
326 { /*Not renumbered yet*/
327 strncpy(&refdes
->prefix
[0],cpr
+1,cp
-cpr
-1); /*Copy the prefix to the refdes structure*/
328 refdes
->prefix
[cp
-cpr
-1]='\0';
331 printf("Prefix=%s\n",&refdes
->prefix
[0]);
334 return REFDES_WITHOUT_VALUE
;
336 for(cp
=cpr
+1,i
=0;(*cp
!= '\n' && *cp
>='A' && *cp
<='z');++i
,++cp
) /*No "?". Copy the prefix*/
337 buff
[i
]=*cp
; /*Fill the buffer from char to char*/
338 buff
[i
]='\0'; /*Terminate with NULL to be a string*/
340 printf("Prefix=%s\n",&buff
[0]);
342 strcpy(&refdes
->prefix
[0],&buff
[0]); /*Copy to refdes structure*/
343 for(i
=0,cp
;(*cp
!= '\n' && *cp
>='0' && *cp
<='9');++cp
,++i
)
344 buff
[i
]=*cp
; /*Fill the buffer from char to char*/
345 buff
[i
]='\0'; /*Terminate with NULL to be a string*/
347 printf("Value=%s\n",&buff
[0]);
349 refdes
->value
=abs(atoi(&buff
[0]));
350 return REFDES_WITH_VALUE
;
353 int refdes_lookup(struct refdes_
*db
, struct refdes_
*ref
)
357 for(c
=0;c
<MAX_PREFIX_COUNT
;++c
)
359 if(strcmp(ref
->prefix
,(*(db
+c
)).prefix
)==0)
361 else if((*(db
+c
)).prefix
[0]=='\0')
364 return REFDES_NOT_FOUND
;
372 #ifdef HAVE_GETOPT_LONG
373 const char *v_opt
="-v | --version";
374 const char *h_opt
="-h | --help";
375 const char *p_opt
="-p | --pagejump";
377 const char *v_opt
="-v";
378 const char *h_opt
="-h";
379 const char *p_opt
="-p";
383 printf("Usage: grenum [%s] [%s] [%s] file1.sch file2.sch ...\n\n",
384 v_opt
, h_opt
, p_opt
);
385 printf("\t%s\tprints version info\n\t%s\tprints this help\n\t%s\tsets pagejump mode on\n",
386 v_opt
, h_opt
, p_opt
);
387 printf("For more information read the README file and/or the manual.\n");
393 printf("This is grenum, an advanced refdes renumber utility for gEDA's gschem.\n");
394 printf("Version %s. gEDA/gaf version %s\n",GRVERSION
, VERSION
);
395 printf("Compiled on %s at %s\n",COMP_DATE
,COMP_TIME
);