magic/extflat/EFargs.c

403 lines
12 KiB
C
Raw Normal View History

/*
* EFargs.c -
*
* General command-line argument processing and overall initialization
* for the .ext file flattener.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extflat/EFargs.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/paths.h"
#include "utils/geometry.h"
#include "utils/hash.h"
#include "utils/utils.h"
#include "utils/malloc.h"
#include "utils/pathvisit.h"
#include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "textio/textio.h"
#include "utils/pathvisit.h"
#define atoCap(s) ((EFCapValue)atof(s))
/* --------------------- Visible outside extflat ---------------------- */
/* Command-line flags */
EFCapValue EFCapThreshold = 2; /* -c/-C: (fF) smallest interesting C */
int EFResistThreshold = 10; /* -r/-R: (Ohms) smallest interesting R */
int EFOutputFlags = 0; /* -t: output of nodename trailing #!'s */
char *EFSearchPath = NULL; /* -p: Search path for .ext files */
char *EFArgTech = NULL; /* -T: Tech specified on command line */
/* Misc globals */
float EFScale = 0.0; /* Uninitialized scale factor */
char *EFVersion = MAGIC_VERSION;/* Version number of .ext format we read */
char *EFLibPath = NULL; /* Library search path for .ext files */
char *EFTech = NULL;
char *EFStyle = NULL; /* Start with no extraction style */
bool EFCompat = TRUE; /* Start with backwards compatibility enabled */
/* -------------------- Visible only inside extflat ------------------- */
/* Command-line flags */
bool efWarn = FALSE; /* -v: Warn about duplicate node names */
bool efHNStats = FALSE; /* -z: TRUE if we gather mem usage stats */
bool efWatchNodes = FALSE; /* -n: TRUE if watching nodes in table below */
HashTable efWatchTable; /* -n: Names to watch, keyed by HierName */
/* Misc globals */
int efResists[128]; /* Sheet resistivity for each resist class */
int efNumResistClasses = 0; /* Number of resist classes */
bool efResistChanged = FALSE; /* TRUE if .ext resist classes mismatch */
bool efScaleChanged = FALSE; /* TRUE if .ext scales mismatch */
/* Forward declarations */
#ifndef MAGIC_WRAPPER
extern int efLoadPathFunc();
extern void efLoadSearchPath();
#endif
/*
* ----------------------------------------------------------------------------
*
* EFArgs --
*
* Process command-line arguments that are relevant to the extractor
* flattener. Arguments that are specific to the calling function
* are processed by the procedure (*argsProc)(), which should
* have the following form:
*
* (*argsProc)(pargc, pargv, cdata)
* int *pargc;
* char ***pargv;
* ClientData cdata;
* {
* }
*
* If we don't recognize an argument, we call (*argsProc)() with
* *pargc and *pargv pointing to the position in the argument
* vector that we didn't recognize. If (*argsProc)() also doesn't
* recognize the argument, it exits; otherwise, it updates *pargc
* and *pargv to point past the argument it gobbled off and returns.
* If argsProc is NULL, then any arguments we don't recognize are
* considered errors.
*
* Arguments processed are:
*
* -T techname Specify the name of the technology, leaving
* EFArgTech pointing to the technology name.
* -p path Use the colon-separated search path 'path'
* for finding .ext files. Overrides any paths
* found in .magicrc files.
* -s sym=value Set the name 'sym' in the symbol hash table to
* have value 'value', where 'value' is an integer.
* Certain attributes interpreted during circuit
* flattening may have symbolic values; the -s flag
* provides a means of associating a numeric value
* with a symbol.
* -S symfile Read the file 'symfile', which should consist of
* lines of the form sym=value, processing each line
* as though it were an argument to -s.
*
* The following flags are for debugging purposes only:
* -n nodename For debugging: print all merges involving
* the node named 'nodename'.
* -N nodefile For debugging: print all merges involving
* any of the nodes whose names appear in the
* file 'nodefile' (one node name per line).
* -v Warn about unusual occurrences while flattening
* the circuit; mainly for debugging.
* -z Print memory utilized for names.
*
* Results:
* Returns a pointer to a string containing the base name
* of the input .ext file.
*
* Side effects:
* Can set global variables based on the values of command-line
* arguments.
* err_result, if non-null, is set to TRUE if an error occurred.
* err_result is only used by the Tcl version of Magic.
*
* ----------------------------------------------------------------------------
*/
char *
EFArgs(argc, argv, err_result, argsProc, cdata)
int argc; /* Number of command-line args */
char *argv[]; /* Vector of command-line args */
bool *err_result; /* Set to TRUE if error occurs */
bool (*argsProc)(); /* Called for args we don't recognize */
ClientData cdata; /* Passed to (*argsProc)() */
{
static char libpath[FNSIZE];
char *realIn, line[1024], *inname = NULL, *name, *cp;
HierName *hierName;
FILE *f;
const char usage_text[] =
"Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n"
"[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n"
#ifdef MAGIC_WRAPPER
"[rootfile]\n";
#else
"[-T techname] rootfile\n";
#endif
if (err_result != NULL) *err_result = FALSE;
/* Hash table of nodes we're going to watch if -N given */
HashInitClient(&efWatchTable, 32, HT_CLIENTKEYS,
efHNCompare, (char *(*)()) NULL,
efHNHash, (int (*)()) NULL);
/* Process command line options */
for (argc--, argv++; argc-- > 0; argv++)
{
if (argv[0][0] != '-')
{
if (inname)
{
TxError("Warning: multiple input files specified; ");
TxError("ignoring \"%s\"\n", inname);
}
inname = argv[0];
continue;
}
switch (argv[0][1])
{
/*** NORMAL OPTIONS ***/
case 'c':
if ((cp = ArgStr(&argc, &argv, "cap threshold")) == NULL)
goto usage;
EFCapThreshold = atoCap(cp); /* Femtofarads */
break;
case 'p':
cp = ArgStr(&argc, &argv, "search path");
if (cp == NULL)
goto usage;
StrDup(&EFSearchPath, cp);
break;
case 'r':
if ((cp = ArgStr(&argc, &argv, "resist threshold")) == NULL)
goto usage;
EFResistThreshold = atoi(cp); /* Ohms */
break;
case 's':
if ((cp = ArgStr(&argc, &argv, "symbolic name")) == NULL)
goto usage;
efSymAdd(cp);
break;
case 't':
if ((cp = ArgStr(&argc, &argv, "trim characters")) == NULL)
goto usage;
if (strchr(cp, '!')) EFOutputFlags |= EF_TRIMGLOB;
if (strchr(cp, '#')) EFOutputFlags |= EF_TRIMLOCAL;
if (strchr(cp, ',')) EFOutputFlags |= EF_CONVERTCOMMA;
if (strchr(cp, '=')) EFOutputFlags |= EF_CONVERTEQUAL;
if (strchr(cp, '[')) EFOutputFlags |= EF_CONVERTBRACKETS;
if (strchr(cp, ']')) EFOutputFlags |= EF_CONVERTBRACKETS;
break;
case 'C':
EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F;
break;
case 'R':
EFResistThreshold = INFINITE_THRESHOLD;
break;
case 'S':
if ((cp = ArgStr(&argc, &argv, "symbol file")) == NULL)
goto usage;
efSymAddFile(cp);
break;
#ifndef MAGIC_WRAPPER
case 'T':
if ((EFArgTech = ArgStr(&argc, &argv, "tech name")) == NULL)
goto usage;
break;
#endif
/*** OPTIONS FOR DEBUGGING ***/
case 'n':
if ((name = ArgStr(&argc, &argv, "nodename")) == NULL)
goto usage;
printf("Watching node '%s'\n", name);
hierName = EFStrToHN((HierName *) NULL, name);
(void) HashFind(&efWatchTable, (char *) hierName);
efWatchNodes = TRUE;
break;
case 'N':
if ((name = ArgStr(&argc, &argv, "filename")) == NULL)
goto usage;
/* Add everything in the file to the hash table */
f = fopen(name, "r");
if (f == NULL)
{
perror(name);
break;
}
while (fgets(line, sizeof line, f))
{
cp = strchr(line, '\n');
if (cp) *cp = '\0';
printf("Watching node '%s'\n", line);
hierName = EFStrToHN((HierName *) NULL, line);
(void) HashFind(&efWatchTable, (char *) hierName);
}
(void) fclose(f);
efWatchNodes = TRUE;
break;
case 'v':
efWarn = TRUE;
break;
case 'z':
efHNStats = TRUE;
break;
case 'h':
if (argsProc != NULL) (*argsProc)(&argc, &argv, cdata);
TxPrintf(usage_text);
if (err_result != NULL) *err_result = TRUE;
return NULL;
/*** Try a caller-supplied argument processing function ***/
default:
if (argsProc == NULL)
goto usage;
if ((*argsProc)(&argc, &argv, cdata))
{
TxError("\n");
goto usage;
}
break;
}
}
#ifndef MAGIC_WRAPPER
/* This is probably not useful */
if (EFSearchPath == NULL) efLoadSearchPath(&EFSearchPath);
#endif
EFLibPath = libpath;
*EFLibPath = 0; /* start with no path */
if (EFArgTech) (void) sprintf(EFLibPath, EXT_PATH, EFArgTech);
if (inname == NULL)
#ifdef MAGIC_WRAPPER
return NULL;
#else
goto usage;
#endif
/* Eliminate trailing .ext from input name */
if ((cp = strrchr(inname, '.')) && strcmp(cp, ".ext") == 0)
{
realIn = (char *) mallocMagic((unsigned)(cp - inname + 1));
(void) strncpy(realIn, inname, cp - inname);
realIn[cp - inname] = '\0';
inname = realIn;
}
return inname;
usage:
TxError(usage_text);
#ifdef MAGIC_WRAPPER
if (err_result != NULL) *err_result = TRUE;
return NULL;
#else
exit (1);
/*NOTREACHED*/
#endif
}
#ifndef MAGIC_WRAPPER
/*
* ----------------------------------------------------------------------------
*
* efLoadSearchPath --
*
* Load the search path string pointed to by 'path'
* with whatever is specified in the .magicrc files
* in $CAD_ROOT/magic/sys, ~, and ., searched in that
* order with the last path taking precedence. See paths.h.
*
* Results:
* None.
*
* Side effects:
* Leaves *path pointing to the correct search path,
* which may either be static or allocated via StrDup().
*
* ----------------------------------------------------------------------------
*/
void
efLoadSearchPath(path)
char **path;
{
PaVisit *pv;
*path = NULL;
pv = PaVisitInit();
PaVisitAddClient(pv, "path", efLoadPathFunc, (ClientData) path);
PaVisitFiles(DOT_MAGIC_PATH, ".magicrc", pv);
PaVisitFree(pv);
if (*path == NULL)
*path = ".";
}
int
efLoadPathFunc(line, ppath)
char *line;
char **ppath;
{
char *cp, *dp, c;
char path[BUFSIZ];
/* Skip leading blanks */
for (cp = &line[4]; *cp && isspace(*cp); cp++)
/* Nothing */;
/* Copy the path into 'path' */
for (dp = path; (c = *cp++) && !isspace(c) && c != '\n'; )
{
if (c == '"')
{
while ((c = *cp++) && c != '"')
*dp++ = c;
if (c == '\0')
break;
}
else *dp++ = c;
}
*dp = '\0';
(void) StrDup(ppath, path);
return 0; /* continue search */
}
#endif