1 /*
2 * DBtechtype.c --
3 *
4 * Creation of tile and plane types and their names.
5 * Lookup procedures are in DBtechname.c
6 *
7 * *********************************************************************
8 * * Copyright (C) 1985, 1990 Regents of the University of California. *
9 * * Permission to use, copy, modify, and distribute this *
10 * * software and its documentation for any purpose and without *
11 * * fee is hereby granted, provided that the above copyright *
12 * * notice appear in all copies. The University of California *
13 * * makes no representations about the suitability of this *
14 * * software for any purpose. It is provided "as is" without *
15 * * express or implied warranty. Export of this software outside *
16 * * of the United States of America may require an export license. *
17 * *********************************************************************
18 */
19
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBtechtype.c,v 1.2 2008/09/05 13:56:25 tim Exp $";
22 #endif /* not lint */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27
28 #include "utils/magic.h"
29 #include "utils/geometry.h"
30 #include "utils/utils.h"
31 #include "tiles/tile.h"
32 #include "utils/hash.h"
33 #include "database/database.h"
34 #include "database/databaseInt.h"
35 #include "utils/tech.h"
36 #include "textio/textio.h"
37 #include "utils/malloc.h"
38
39 /* Types and their names */
40 int DBNumTypes;
41 char *DBTypeLongNameTbl[NT];
42 int DBTypePlaneTbl[NT]; /* Normally accessed as macro "DBPlane(x)" */
43 NameList dbTypeNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
44 HashTable DBTypeAliasTable;
45
46 /* Planes and their names */
47 int DBNumPlanes;
48 char *DBPlaneLongNameTbl[PL_MAXTYPES];
49 NameList dbPlaneNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
50
51
52 /*
53 * Sets of types.
54 * These are generated after the "types" section of the
55 * technology file has been read, but before any automatically
56 * generated types (contact images) are created.
57 */
58 int DBNumUserLayers;
59 TileTypeBitMask DBZeroTypeBits;
60 TileTypeBitMask DBAllTypeBits;
61 TileTypeBitMask DBBuiltinLayerBits;
62 TileTypeBitMask DBAllButSpaceBits;
63 TileTypeBitMask DBAllButSpaceAndDRCBits;
64 TileTypeBitMask DBSpaceBits;
65 TileTypeBitMask DBUserLayerBits;
66 TileTypeBitMask DBActiveLayerBits; /* Layers that are locked */
67 TileTypeBitMask DBTechActiveLayerBits; /* Layers marked locked in the techfile */
68
69
70 /* Table of default, builtin planes */
71 DefaultPlane dbTechDefaultPlanes[] =
72 {
73 PL_ROUTER, "router",
74 PL_DRC_ERROR, "designRuleError",
75 PL_DRC_CHECK, "designRuleCheck",
76 PL_M_HINT, "mhint",
77 PL_F_HINT, "fhint",
78 PL_R_HINT, "rhint",
79 0, 0, 0
80 };
81
82 /* Table of default, builtin types */
83 DefaultType dbTechDefaultTypes[] =
84 {
85 TT_SPACE, -1, "space", FALSE,
86 TT_CHECKPAINT, PL_DRC_CHECK, "checkpaint,CP", FALSE,
87 TT_CHECKSUBCELL, PL_DRC_CHECK, "checksubcell,CS", FALSE,
88 TT_ERROR_P, PL_DRC_ERROR, "error_p,EP", FALSE,
89 TT_ERROR_S, PL_DRC_ERROR, "error_s,ES", FALSE,
90 TT_ERROR_PS, PL_DRC_ERROR, "error_ps,EPS", FALSE,
91 TT_MAGNET, PL_M_HINT, "magnet,mag", TRUE,
92 TT_FENCE, PL_F_HINT, "fence,f", TRUE,
93 TT_ROTATE, PL_R_HINT, "rotate,r", TRUE,
94 0, 0, NULL, 0
95 };
96
97 /* Forward declarations */
98 char *dbTechNameAdd();
99 NameList *dbTechNameAddOne();
100
101 /*
102 * ----------------------------------------------------------------------------
103 *
104 * DBTechInitPlane --
105 *
106 * Initialize the default plane information.
107 *
108 * Results:
109 * None.
110 *
111 * Side effects:
112 * Initializes DBNumPlanes to PL_TECHDEPBASE.
113 * Initializes DBPlaneLongNameTbl[] for builtin planes.
114 *
115 * ----------------------------------------------------------------------------
116 */
117
118 void
DBTechInitPlane()119 DBTechInitPlane()
120 {
121 DefaultPlane *dpp;
122 char *cp;
123
124 /* Clear out any old information */
125 if (dbPlaneNameLists.sn_next != NULL)
126 {
127 NameList *tbl;
128
129 for (tbl = dbPlaneNameLists.sn_next; tbl != &dbPlaneNameLists;
130 tbl = tbl->sn_next)
131 {
132 freeMagic(tbl->sn_name);
133 freeMagic(tbl);
134 }
135 }
136
137 /* Tables of short names */
138 dbPlaneNameLists.sn_next = &dbPlaneNameLists;
139 dbPlaneNameLists.sn_prev = &dbPlaneNameLists;
140
141 for (dpp = dbTechDefaultPlanes; dpp->dp_names; dpp++)
142 {
143 cp = dbTechNameAdd(dpp->dp_names, (ClientData) dpp->dp_plane,
144 &dbPlaneNameLists, FALSE);
145 if (cp == NULL)
146 {
147 TxError("DBTechInit: can't add plane names %s\n", dpp->dp_names);
148 niceabort();
149 }
150 DBPlaneLongNameTbl[dpp->dp_plane] = cp;
151 }
152
153 DBNumPlanes = PL_TECHDEPBASE;
154 }
155
156
157 /*
158 * ----------------------------------------------------------------------------
159 *
160 * DBTypeInit --
161 *
162 * Initialization routine for the types database on startup (runs only
163 * once).
164 *
165 * Results:
166 * None.
167 *
168 * Side effects:
169 * Hash table initialization.
170 *
171 * ----------------------------------------------------------------------------
172 */
173
174 void
DBTypeInit()175 DBTypeInit()
176 {
177 HashInit(&DBTypeAliasTable, 8, HT_STRINGKEYS);
178 }
179
180 /*
181 * ----------------------------------------------------------------------------
182 *
183 * DBTechInitType --
184 *
185 * Add the names and planes of the builtin types.
186 *
187 * Results:
188 * None.
189 *
190 * Side effects:
191 * See above.
192 * Initializes DBNumTypes to TT_TECHDEPBASE.
193 *
194 * ----------------------------------------------------------------------------
195 */
196
197 void
DBTechInitType()198 DBTechInitType()
199 {
200 DefaultType *dtp;
201 char *cp;
202
203 /* Clear out any old information */
204 if (dbTypeNameLists.sn_next != NULL)
205 {
206 NameList *tbl;
207
208 for (tbl = dbTypeNameLists.sn_next; tbl != &dbTypeNameLists;
209 tbl = tbl->sn_next)
210 {
211 freeMagic(tbl->sn_name);
212 freeMagic(tbl);
213 }
214 }
215
216 /* Tables of short names */
217 dbTypeNameLists.sn_next = &dbTypeNameLists;
218 dbTypeNameLists.sn_prev = &dbTypeNameLists;
219
220 /*
221 * Add the type names to the list of known names, and set
222 * the default plane for each type.
223 */
224 for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
225 {
226 cp = dbTechNameAdd(dtp->dt_names, (ClientData) dtp->dt_type,
227 &dbTypeNameLists, FALSE);
228 if (cp == NULL)
229 {
230 TxError("DBTechInit: can't add type names %s\n", dtp->dt_names);
231 niceabort();
232 }
233 DBTypeLongNameTbl[dtp->dt_type] = cp;
234 DBPlane(dtp->dt_type) = dtp->dt_plane;
235 TTMaskSetOnlyType(&DBLayerTypeMaskTbl[dtp->dt_type], dtp->dt_type);
236 }
237
238 /* Zero the active layers (this mask is inverted later) */
239 TTMaskZero(&DBActiveLayerBits);
240
241 /* Hash table of layer aliases, free'ing the allocated type masks */
242 HashFreeKill(&DBTypeAliasTable);
243 HashInit(&DBTypeAliasTable, 8, HT_STRINGKEYS);
244
245 DBNumTypes = TT_TECHDEPBASE;
246 }
247
248 /*
249 * ----------------------------------------------------------------------------
250 *
251 * DBTechAddPlane --
252 *
253 * Define a tile plane type for the new technology.
254 *
255 * Results:
256 * TRUE if successful, FALSE on error
257 *
258 * Side effects:
259 * Updates the database technology variables.
260 * In particular, updates the number of known tile planes.
261 *
262 * ----------------------------------------------------------------------------
263 */
264
265 /*ARGSUSED*/
266 bool
DBTechAddPlane(sectionName,argc,argv)267 DBTechAddPlane(sectionName, argc, argv)
268 char *sectionName;
269 int argc;
270 char *argv[];
271 {
272 char *cp;
273
274 if (DBNumPlanes >= PL_MAXTYPES)
275 {
276 TechError("Too many tile planes (max=%d)\n", PL_MAXTYPES);
277 return FALSE;
278 }
279
280 if (argc != 1)
281 {
282 TechError("Line must contain names for plane\n");
283 return FALSE;
284 }
285
286 cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists, FALSE);
287 if (cp == NULL)
288 return FALSE;
289 DBPlaneLongNameTbl[DBNumPlanes++] = cp;
290 return TRUE;
291 }
292
293 /*
294 * ----------------------------------------------------------------------------
295 *
296 * DBTechAddNameToType --
297 *
298 * Add a new name (alias) to an existing tile type.
299 *
300 * Results:
301 * None.
302 *
303 * Side Effects:
304 * Adds "newname" to dbTypeNameLists. May change the primary name
305 * of the type stored in the pointer array DBTypeLongNameTbl[].
306 *
307 * ----------------------------------------------------------------------------
308 */
309
310 void
DBTechAddNameToType(newname,ttype,canonical)311 DBTechAddNameToType(newname, ttype, canonical)
312 char *newname;
313 TileType ttype;
314 bool canonical;
315 {
316 char *cp;
317
318 cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists, TRUE);
319 if (canonical)
320 DBTypeLongNameTbl[ttype] = cp;
321 }
322
323 /*
324 * ----------------------------------------------------------------------------
325 *
326 * DBTechAddAlias --
327 *
328 * Define an alias representing a mask of one or more tiletypes
329 *
330 * Results:
331 * TRUE if successful, FALSE on error. Returns TRUE on some
332 * errors that may not necessarily be fatal.
333 *
334 * Side effects:
335 * Updates the database technology variables.
336 * In particular, updates the alias hash table.
337 *
338 * ----------------------------------------------------------------------------
339 */
340
341 bool
DBTechAddAlias(sectionName,argc,argv)342 DBTechAddAlias(sectionName, argc, argv)
343 char *sectionName;
344 int argc;
345 char *argv[];
346 {
347 char *cp;
348 int pNum;
349 HashEntry *he;
350 TileType atype;
351 TileTypeBitMask *amask, tmask;
352
353 if (argc < 2)
354 {
355 TechError("Line must contain at least 2 fields\n");
356 return TRUE;
357 }
358
359 /* First check that the alias name does not shadow an existing type */
360 if (DBTechNameTypeExact(argv[0]) >= 0)
361 {
362 TechError("Type alias \"%s\" shadows a defined type\n", argv[0]);
363 return TRUE;
364 }
365
366 /* Next, check the type list. If there is only one type, then */
367 /* add the name to the type's names as usual, instead of adding */
368 /* it to the alias hash table, which is meant for names that */
369 /* map to multiple types. */
370
371 DBTechNoisyNameMask(argv[1], &tmask);
372 if ((atype = DBTechNameType(argv[1])) >= 0)
373 if (TTMaskEqual(&DBLayerTypeMaskTbl[atype], &tmask))
374 {
375 DBTechAddNameToType(argv[0], atype, FALSE);
376 return TRUE;
377 }
378
379 he = HashFind(&DBTypeAliasTable, argv[0]);
380 amask = (TileTypeBitMask *)HashGetValue(he);
381 if (amask == NULL)
382 {
383 amask = (TileTypeBitMask *)mallocMagic(sizeof(TileTypeBitMask));
384 TTMaskZero(amask);
385 TTMaskSetMask(amask, &tmask);
386 HashSetValue(he, amask);
387 }
388 else
389 {
390 TechError("Type \"%s\" is already defined and cannot be an alias\n",
391 argv[0]);
392 return TRUE;
393 }
394 return TRUE;
395 }
396
397
398 /*
399 * ----------------------------------------------------------------------------
400 *
401 * DBTechAddType --
402 *
403 * Define a tile type for the new technology.
404 *
405 * Results:
406 * TRUE if successful, FALSE on error. Returns TRUE on some
407 * errors that may not necessarily be fatal.
408 *
409 * Side effects:
410 * Updates the database technology variables.
411 * In particular, updates the number of known tile types.
412 *
413 * ----------------------------------------------------------------------------
414 */
415
416 /*ARGSUSED*/
417 bool
DBTechAddType(sectionName,argc,argv)418 DBTechAddType(sectionName, argc, argv)
419 char *sectionName;
420 int argc;
421 char *argv[];
422 {
423 char *cp;
424 int pNum;
425
426 if (DBNumTypes >= TT_MAXTYPES-TT_RESERVEDTYPES)
427 {
428 TechError("Too many tile types (max=%d)\n",
429 TT_MAXTYPES-TT_RESERVEDTYPES);
430 return FALSE;
431 }
432
433 if (argc < 2)
434 {
435 TechError("Line must contain at least 2 fields\n");
436 return TRUE;
437 }
438
439 if (!strcmp(argv[0], "alias"))
440 {
441 /* Check that we have not used "*" in the alias list, since if */
442 /* we define aliases in the "types" section (which is allowed */
443 /* for backwards compatibility), the contacts have not yet been */
444 /* defined. */
445
446 if (strchr(argv[2], '*') != NULL)
447 {
448 TechError("Type alias \"%s\" contains the wildcard character "
449 "\"*\" (alias ignored).\n"
450 "Perhaps you want to define aliases in "
451 "the \"alias\" section?\n", argv[2]);
452 return TRUE;
453 }
454 return (DBTechAddAlias(sectionName, argc - 1, argv + 1));
455 }
456 else
457 {
458 cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
459 if (cp == NULL)
460 return FALSE;
461
462 /* Set the lock layer bit if the plane name begins with '-' */
463 if (*argv[0] == LOCKLAYERCHAR)
464 {
465 TTMaskSetType(&DBActiveLayerBits, DBNumTypes);
466 argv[0]++;
467 }
468
469 pNum = DBTechNoisyNamePlane(argv[0]);
470 if (pNum < 0)
471 return FALSE;
472
473 DBTypeLongNameTbl[DBNumTypes] = cp;
474 DBPlane(DBNumTypes) = pNum;
475 TTMaskSetOnlyType(&DBLayerTypeMaskTbl[DBNumTypes], DBNumTypes);
476 DBNumTypes++;
477 }
478
479 return TRUE;
480 }
481
482
483
484 /*
485 * ----------------------------------------------------------------------------
486 * dbTechNewStackedType --
487 *
488 * Generate a new tiletype for a stacked layer (generally speaking,
489 * a stacked contact). Return the new tile type for the stacked
490 * contact type.
491 *
492 * Results:
493 * The new tile type
494 *
495 * Side effects:
496 * Updates the name tables with the new type name. Note that other
497 * tables, such as the home plane table, are not affected by this
498 * routine.
499 * ----------------------------------------------------------------------------
500 */
501
502 TileType
dbTechNewStackedType(type1,type2)503 dbTechNewStackedType(type1, type2)
504 TileType type1, type2;
505 {
506 char buf[1024], *cp;
507
508 if (DBNumTypes >= TT_MAXTYPES - TT_RESERVEDTYPES)
509 {
510 TechError("Too many types to generate a new contact. Maximum=%d\n",
511 TT_MAXTYPES - TT_RESERVEDTYPES);
512 return (TileType) -1;
513 }
514
515 sprintf(buf, "%s+%s", DBTypeShortName(type1), DBTypeShortName(type2));
516 cp = dbTechNameAdd(buf, (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
517 if (cp == NULL)
518 {
519 TechError("Couldn't generate new stacking type %s\n", buf);
520 return (TileType) -1;
521 }
522
523 DBTypeLongNameTbl[DBNumTypes] = cp;
524
525 return DBNumTypes++;
526 }
527
528 /*
529 * ----------------------------------------------------------------------------
530 *
531 * DBTechFinalType --
532 *
533 * After processing the types and planes sections, compute the
534 * various derived type and plane masks and tables.
535 *
536 * Results:
537 * None.
538 *
539 * Side effects:
540 * Initializes DBNumUserLayers to be DBNumTypes at the time
541 * this procedure is called, since none of the automatically
542 * generated plane images have yet been created.
543 * Initializes the following bit masks:
544 * DBAllTypeBits
545 * DBSpaceBits
546 * DBBuiltinLayerBits
547 * DBAllButSpaceBits
548 * DBAllButSpaceAndDRCBits
549 * DBUserLayerBits
550 *
551 * ----------------------------------------------------------------------------
552 */
553
554 void
DBTechFinalType()555 DBTechFinalType()
556 {
557 TileType i;
558 int pNum;
559
560 DBNumUserLayers = DBNumTypes;
561
562 for (i = 0; i < TT_MAXTYPES; i++)
563 {
564 if (i >= TT_SELECTBASE)
565 TTMaskSetType(&DBAllButSpaceAndDRCBits, i);
566
567 if (i < TT_TECHDEPBASE)
568 TTMaskSetType(&DBBuiltinLayerBits, i);
569 else if (i < DBNumUserLayers)
570 TTMaskSetType(&DBUserLayerBits, i);
571 }
572
573 TTMaskCom2(&DBAllTypeBits, &DBZeroTypeBits);
574 TTMaskSetOnlyType(&DBSpaceBits, TT_SPACE);
575 TTMaskCom2(&DBAllButSpaceBits, &DBSpaceBits);
576
577 /* UserLayerBits includes space */
578 TTMaskSetType(&DBUserLayerBits, TT_SPACE);
579
580 /* Set locked layer bitmask */
581 TTMaskCom(&DBActiveLayerBits);
582 TTMaskAndMask(&DBActiveLayerBits, &DBAllButSpaceAndDRCBits);
583 /* Save this mask for later reference */
584 TTMaskZero(&DBTechActiveLayerBits);
585 TTMaskSetMask(&DBTechActiveLayerBits, &DBActiveLayerBits);
586
587 /* Space is visible on all planes except the router */
588 TTMaskZero(&DBPlaneTypes[PL_ROUTER]);
589 for (pNum = PL_PAINTBASE; pNum < PL_MAXTYPES; pNum++)
590 TTMaskSetOnlyType(&DBPlaneTypes[pNum], TT_SPACE);
591 }
592
593 /*
594 * ----------------------------------------------------------------------------
595 *
596 * dbTechNameLookupExact --
597 *
598 * Lookup a type or plane name.
599 * Case is significant.
600 *
601 * Results:
602 * Returns the ClientData associated with the given name.
603 * If the name was not found, we return -2. Unlike dbTechNameLookup,
604 * this routine requires an exact name match, and never returns -1
605 * (which indicates ambiguity in dbTechNameLookup()).
606 *
607 * Side effects:
608 * None.
609 *
610 * ----------------------------------------------------------------------------
611 */
612
613 ClientData
dbTechNameLookupExact(str,table)614 dbTechNameLookupExact(str, table)
615 char *str; /* The name to be looked up */
616 NameList *table; /* Table of names to search */
617 {
618 NameList *top;
619
620 top = table;
621 while ((top = top->sn_next) != table)
622 if (!strcmp(top->sn_name, str))
623 return (top->sn_value);
624
625 return ((ClientData) -2);
626 }
627
628
629 /*
630 * ----------------------------------------------------------------------------
631 *
632 * dbTechNameLookup --
633 *
634 * Lookup a type or plane name.
635 * Case is significant.
636 *
637 * Results:
638 * Returns the ClientData associated with the given name.
639 * If the name was not found, we return -2; if it was ambiguous,
640 * we return -1.
641 *
642 * Side effects:
643 * None.
644 *
645 * ----------------------------------------------------------------------------
646 */
647
648 ClientData
dbTechNameLookup(str,table)649 dbTechNameLookup(str, table)
650 char *str; /* The name to be looked up */
651 NameList *table; /* Table of names to search */
652 {
653 /*
654 * The search is carried out by using two pointers, one which moves
655 * forward through list from its start, and one which moves backward
656 * through table from its end. The two pointers mark the range of
657 * strings that match the portion of str that we have scanned. When
658 * all of the characters of str have been scanned, then the two
659 * pointers better be identical, or one of the strings in the range
660 * between the two pointers better match 'str' exactly.
661 */
662 NameList *bot, *top;
663 char currentchar;
664 int indx;
665
666 bot = table->sn_next;
667 top = table->sn_prev;
668 if (top == bot) return ((ClientData) -2);
669
670 for (indx = 0; ; indx++)
671 {
672 /* Check for the end of string */
673 currentchar = str[indx];
674 if (currentchar == '\0')
675 {
676 if (bot == top)
677 return (bot->sn_value);
678
679 /*
680 * Several entries match this one up to the last character
681 * of the string. If one is an exact match, we allow it;
682 * otherwise, we claim the string was ambiguous.
683 */
684 for ( ; bot != top; bot = bot->sn_next)
685 if (bot->sn_name[indx] == '\0')
686 return (bot->sn_value);
687
688 return ((ClientData) -1);
689 }
690
691 /*
692 * Move bot up until the string it points to matches str in the
693 * indx'th position. Make match refer to the indx of bot in table.
694 */
695 while (bot->sn_name[indx] != currentchar)
696 {
697 if (bot == top) return((ClientData) -2);
698 bot = bot->sn_next;
699 }
700
701 /* Move top down until it matches */
702 while (top->sn_name[indx] != currentchar)
703 {
704 if (bot == top) return((ClientData) -2);
705 top = top->sn_prev;
706 }
707 }
708
709 /*NOTREACHED*/
710 }
711
712 /*
713 * ----------------------------------------------------------------------------
714 *
715 * dbTechNameAdd --
716 *
717 * Add several names to a name table.
718 * The shortest name is marked as the standard "short" name
719 * for this cdata value.
720 *
721 * Results:
722 * Returns a pointer to the first name added if successful,
723 * or NULL if not. In this latter case, we print error messages.
724 *
725 * Side effects:
726 * Adds new entries to the table pointed to by *ptable, and
727 * modifies *ptable if necessary.
728 *
729 * ----------------------------------------------------------------------------
730 */
731
732 char *
dbTechNameAdd(name,cdata,ptable,alias)733 dbTechNameAdd(name, cdata, ptable, alias)
734 char *name; /* Comma-separated list of names to be added */
735 ClientData cdata; /* Value to be stored with each name above */
736 NameList *ptable; /* Table to which we will add names */
737 int alias; /* 1 if this is an alias (never make primary) */
738 {
739 char *cp;
740 char onename[BUFSIZ];
741 char *first;
742 int shortestLength, length;
743 NameList *primary, *current;
744
745 if (name == NULL)
746 return (NULL);
747
748 first = NULL;
749 shortestLength = INFINITY;
750 primary = NULL;
751 while (*name)
752 {
753 if (*name == ',')
754 {
755 name++;
756 continue;
757 }
758 for (cp = onename; *name && *name != ','; *cp++ = *name++)
759 /* Nothing */;
760 *cp = '\0';
761 if (*(cp = onename))
762 {
763 if ((current = dbTechNameAddOne(cp, cdata, FALSE, alias, ptable)) == NULL)
764 return (NULL);
765 if (first == NULL)
766 first = current->sn_name;
767 length = strlen(onename);
768 if (length < shortestLength)
769 shortestLength = length, primary = current;
770 }
771 }
772
773 if (primary && (alias == 0))
774 primary->sn_primary = TRUE;
775 return (first);
776 }
777
778 /*
779 * ----------------------------------------------------------------------------
780 *
781 * dbTechNameAddOne --
782 *
783 * Add a single name to the table.
784 *
785 * Results:
786 * Returns a pointer to the new entry if succesful,
787 * or NULL if the name was already in the table.
788 *
789 * Side effects:
790 * See above.
791 *
792 * ----------------------------------------------------------------------------
793 */
794
795 NameList *
dbTechNameAddOne(name,cdata,isPrimary,isAlias,ptable)796 dbTechNameAddOne(name, cdata, isPrimary, isAlias, ptable)
797 char *name; /* Name to be added */
798 ClientData cdata; /* Client value associated with this name */
799 bool isPrimary; /* TRUE if this is the primary abbreviation */
800 bool isAlias; /* TRUE if this name is an alias */
801 NameList *ptable; /* Table of names to which we're adding this */
802 {
803 int cmp;
804 NameList *tbl, *new;
805
806 /* Sort the name into the existing list */
807 for (tbl = ptable->sn_next ;tbl != ptable; tbl = tbl->sn_next)
808 if ((cmp = strcmp(name, tbl->sn_name)) == 0)
809 {
810 TechError("Duplicate name: %s\n", name);
811 return (NULL);
812 }
813 else if (cmp < 0)
814 break;
815
816 /* Create a new name */
817 new = (NameList *) mallocMagic((unsigned) (sizeof (NameList)));
818 new->sn_name = StrDup((char **) NULL, name);
819 new->sn_value = cdata;
820 new->sn_primary = isPrimary;
821 new->sn_alias = isAlias;
822
823 /* Link this entry in to the list before 'tbl' */
824 new->sn_next = tbl;
825 new->sn_prev = tbl->sn_prev;
826 tbl->sn_prev->sn_next = new;
827 tbl->sn_prev = new;
828 return (new);
829 }
830