forked from endlesssoftware/mmk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mmk.c
1357 lines (1247 loc) · 41.1 KB
/
mmk.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
**++
** FACILITY: MMK
**
** ABSTRACT: The MMK Make Utility
**
** MODULE DESCRIPTION:
**
** This is the main routine for MMK.
**
** AUTHOR: M. Madison
**
** Copyright (c) 2008, Matthew Madison.
** Copyright (c) 2014, Endless Software Solutions.
**
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** * Redistributions of source code must retain the above
** copyright notice, this list of conditions and the following
** disclaimer.
** * Redistributions in binary form must reproduce the above
** copyright notice, this list of conditions and the following
** disclaimer in the documentation and/or other materials provided
** with the distribution.
** * Neither the name of the copyright owner nor the names of any
** other contributors may be used to endorse or promote products
** derived from this software without specific prior written
** permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** CREATION DATE: 20-AUG-1992
**
** MODIFICATION HISTORY:
**
** 20-AUG-1992 V1.0 Madison Initial coding.
** 27-AUG-1992 V1.1 Madison Spruce up a bit.
** 29-SEP-1992 V1.2 Madison Add /FORCE, /FROM, /IDENT, /OUTPUT.
** 12-OCT-1992 V1.2-1 Madison Fix some parsing problems.
** 23-DEC-1992 V1.2-2 Madison Change MMS$xxx file refs to MMK_xxx
** 12-JAN-1993 V1.2-3 Madison Fix a couple of minor bugs.
** 08-MAR-1993 V1.2-4 Madison Fix library module reference bugs.
** 02-APR-1993 V1.3 Madison Add support for "-" on command lines.
** 23-APR-1993 V1.3-1 Madison Fix suffix processing.
** 29-APR-1993 V1.3-2 Madison Fix dependency rule parsing.
** 30-APR-1993 V1.4 Madison Default rules are now compiled-in.
** 04-JUN-1993 V1.5 Madison Add support for some more directives.
** 07-JUN-1993 V1.6 Madison Add MMS$CHANGED_LIST.
** 21-AUG-1993 V1.7 Madison Main source fix, build-rule fix.
** 28-SEP-1993 V2.0 Madison Fix up for general release.
** 24-SEP-1993 V2.0-1 Madison Fixed /FROM_SOURCES problem.
** 27-SEP-1993 V2.0-2 Madison Fixed a couple more MMS discrepancies.
** 27-SEP-1993 V2.0-3 Madison Changed file_get_rdt to do shared open.
** 27-SEP-1993 V2.0-4 Madison Retracted the -2 and -3 shared-open changes.
** 17-OCT-1993 V2.1 Madison Allow substitution rules in var refs.
** 17-OCT-1993 V2.2 Madison Delete intermediate libfiles.
** 20-OCT-1993 V2.3 Madison Add CTRL/T support.
** 22-OCT-1993 V2.3-1 Madison Fix lines w/just blanks, deletion of
** intermediates for multiple libmods.
** 28-OCT-1993 V2.3-2 Madison More fixes.
** 22-NOV-1993 V2.3-3 Madison Fix parsing of target from command line.
** 01-DEC-1993 V2.3-4 Madison Fix /IGNORE getting ignored for built-in rules.
** 02-DEC-1993 V2.3-5 Madison Allow symbol refs inside symbol refs.
** 09-DEC-1993 V2.3-6 Madison extract_name fix.
** 12-DEC-1993 V2.4 Madison Add MMS, MMSQUAL macros, support for
** multiple dependencies for targets.
** 02-MAR-1994 V2.4-1 Madison Fix non-resolvable specials.
** 03-MAR-1994 V2.4-2 Madison Fix description parsing symbol problem.
** 04-APR-1994 V2.4-3 Madison Fixed a couple of symbol problems.
** 04-APR-1994 V2.4-4 Madison Another symbol problem. Argh!
** 08-APR-1994 V2.4-5 Madison Fix space-sep lists on lhs of dep rules.
** 11-APR-1994 V2.4-6 Madison Make default rules more MMS-compatible.
** 14-APR-1994 V2.4-7 Madison More random fixes.
** 06-MAY-1994 V2.4-8 Madison Output @-prefixed commands on /NOACT.
** 14-JUN-1994 V2.5 Madison Support for multiple targets on command
** line, courtesy of Richard Levitte.
** 29-JUN-1994 V2.6 Madison TEX, library module, and source list fixes.
** 01-JUL-1994 V3.0 Madison Support for CMS.
** 06-JUL-1994 V3.0-1 Madison A couple of bug fixes.
** 12-JUL-1994 V3.1 Madison Add :: support, circular-dependency checks.
** 14-JUL-1994 V3.2 Madison Add prefix support in inference rules.
** 17-AUG-1994 V3.2-1 Madison Upcase sfx list; fix MMS definition.
** 22-AUG-1994 V3.2-2 Madison Fix LIBMOD bypass in dependecny creation.
** 18-OCT-1994 V3.2-3 Madison Fix PARSE_DESCRIP error-signal bug.
** 02-DEC-1994 V3.3 Madison Add /GENERATION qualifier for specifying
** default CMS generation on fetches.
** 10-JAN-1995 V3.3-1 Madison Prefix commands with $ if /OUTPUT specified.
** 13-JAN-1995 V3.3-1 Madison Add /NOACTION to $(MMS) symbol when noaction.
** 16-MAR-1995 V3.3-2 Madison Turn off verify of CMS libraries.
** 30-APR-1995 V3.3-3 Madison Fix lib mod prefixing.
** 07-JUN-1995 V3.3-4 Madison Use default CMS generation in CMS RDT compares.
** 19-JUN-1995 V3.3-5 Madison Fix for Fill_In_Missing_Sources.
** 21-JUN-1995 V3.4 Madison Support /MACRO=fspec, /SKIP_INTERMEDIATES,
** /OVERRIDE, /CHECK_STATUS.
** 27-JUN-1995 V3.4-1 Madison Fix CMS fetches of description files.
** 12-JUL-1995 V3.4-2 Madison Clean up after RMS search lists.
** 17-JUL-1995 V3.4-3 Madison Wasn't setting have_rdt flag when getting RDT.
** 21-JUL-1995 V3.4-4 Madison Fix for /SKIP.
** 03-OCT-1995 V3.4-5 Madison Handle parsing of target file specs
** with names longer than 32 characters.
** 05-OCT-1995 V3.4-6 Madison Fixed error paths causing ACCVIOs in SP_MGR.
** 09-OCT-1995 V3.4-7 Madison Another case of incorrect use of free().
** 06-NOV-1995 V3.4-8 Madison Fix library problem, rule problem.
** 21-FEB-1996 V3.4-9 Madison Fix in READDESC.
** 29-MAY-1996 V3.4-10 Madison Special hack for macros with dots.
** 22-AUG-1996 V3.5 Madison Add /CMS_LIBRARY qualifier.
** 22-DEC-1996 X3.6 Madison Add FIRST and LAST rules.
** 15-FEB-1997 V3.6 Madison Define MMS$CMS_GEN always.
** 23-MAR-1997 V3.6-1 Madison Set MMS$STATUS to action status.
** 20-JUN-1997 V3.6-2 Madison Make null-object parsing compatible with MMS.
** 06-JUN-1998 V3.7 Madison Add /WORKING_DIRECTORY.
** 27-DEC-1998 V3.8 Madison IFNDEF, multiple CMS libraries, prototype cleanup.
** 21-OCT-1999 V3.8-1 Madison Fix put_command so it outputs full command to file.
** 17-JAN-2000 V3.8-2 Madison Fix parsing of blank-separated targets.
** 03-MAY-2000 V3.8-3 Madison Open /OUTPUT files with sharing.
** 20-JAN-2001 V3.9 Madison Recursive rule searches from Chuck Lane.
** 30-MAR-2001 V3.9-1 Madison Fix prefixed rules; add architecture built-ins.
** 08-APR-2001 V3.9-2 Madison More fixes for recursive rule searches.
** 11-JUL-2002 V3.9-3 Madison Fix /MACRO=filespec.
** 29-JUL-2002 V3.9-4 Madison Second attempt at fixing :: handling.
** 07-AUG-2002 V3.9-5 Madison Another fix for recursive rule searches.
** 05-OCT-2003 V3.9-7 Madison Fix for semicolons in target object names.
** 09-DEC-2003 V3.9-8 Madison Don't fill in CMS-derived sources when not using CMS.
** 29-JAN-2004 V3.9-8 Madison Don't define MMS$CMS_LIBRARY when CMS library is CMS$LIB.
** 03-MAY-2004 V3.9-9 Madison Integrate IA64 changes, courtesy of Dan O'Reilly and Hunter Goatley.
** 02-MAR-2008 V4.0 Madison Cleanup for open-source release.
** 10-OCT-2008 V4.1 Sneddon New MMS compat. features.
** 01-APR-2010 V4.1-1 Sneddon Updated version number for minor release. Added MMSTARGETS.
** 04-OCT-2010 V5.0 Sneddon New version. Add /VERIFY=ALL.
** 07-SEP-2012 V5.0 Sneddon Add temporary_symbols.
** 10-DEC-2012 V5.0 Sneddon Fix to /VERIFY=ALL code.
** 21-FEB-2013 V5.0 Sneddon Move definition of MMSTARGETS to before
** we read in the description file.
** 26-FEB-2013 V5.1 Sneddon Move version number into its own
** #include file, now it is totally
** unrelated to this module.
** 18-MAR-2013 V5.2 Sneddon Fix for #58. We only parse the command
** line if DCL hasn't done it already.
** 01-MAY-2013 V5.2-1 Sneddon #66: Targets inserted into wrong end
** of queue.
** 13-JUN-2014 V5.3 Sneddon Changes for new Define_Symbol args.
** Define MMSSUFFIXES before parsing.
** 5-SEP-2023 V5.4 Goatley Add code from Craig Berry to define
** architecture builtins.
**--
*/
#include "version.h"
#pragma module MMK MMK_VERSION
#pragma extern_model save
#pragma extern_model common_block shr
char $$$Copyright[] = MMK_COPYRIGHT;
#pragma extern_model restore
#include "mmk.h"
#include "clidefs.h"
#include <libclidef.h>
#include <libdef.h>
#include <fscndef.h>
#include <rmsdef.h>
#include <syidef.h>
#ifndef SYI$_ARCH_NAME
#define SYI$_ARCH_NAME 4454
#endif
#include <stdio.h>
typedef struct _exhblk {
struct _exhblk *exh_a_flink;
unsigned int (*exh_p_handler)(unsigned int *);
unsigned int exh_l_argcnt;
unsigned int *exh_a_statptr;
} EXHBLK;
/*
** Forward declarations
*/
unsigned int main(void);
static void add_to_mmsqual(char *);
unsigned int put_output(void *);
unsigned int put_command(void *);
static unsigned int cli_get_value(char *, char *, int);
static unsigned int cli_present(char *);
static void Dump_It_All(void);
static void dump_dependency(struct DEPEND *d);
static unsigned int exit_handler(unsigned int *);
static unsigned int change_working_directory(char *);
/*
** Globals used throughout the program
*/
#pragma nostandard
GLOBAL struct SYMTABLE global_symbols;
GLOBAL struct SYMTABLE local_symbols;
GLOBAL struct SYMTABLE cmdline_symbols;
GLOBAL struct SYMTABLE builtin_symbols;
GLOBAL struct SYMTABLE *temporary_symbols;
GLOBAL struct RULE rules;
GLOBAL struct RULE *default_rule = 0;
GLOBAL struct DEPEND dependencies;
GLOBAL struct DEPEND dep_internal;
GLOBAL struct DEPEND dep_deferred;
GLOBAL struct SFX suffixes;
GLOBAL struct CMD do_first;
GLOBAL struct CMD do_last;
GLOBAL int verify, do_log, did_an_update, noaction, check_status;
GLOBAL int builtins, mms_syntax, gnu_syntax, case_sensitive;
GLOBAL int from_sources, force, ignore, use_cms, skip_intermediates;
GLOBAL int override_silent, override_ignore, symbol_override;
GLOBAL int override_builtins, override_case, override_gnu_syntax, override_mms_syntax;
GLOBAL unsigned int exit_status;
GLOBAL char cms$lib[256*16];
GLOBAL char cms_default_generation[256];
#pragma standard
/*
** Local statics
*/
static FILEHANDLE out_unit = 0;
static char mmsqual[4096];
static char old_sys_disk[256], old_def_dir[256];
static int changed_default = 0;
static unsigned int final_status;
static EXHBLK desblk = { 0, exit_handler, 1, &final_status };
static $DESCRIPTOR(sys_disk_d, "SYS$DISK");
/*
** External references
*/
#ifndef __VAX
extern mmk_cld;
#else
globalref mmk_cld;
#endif
#define MMK_CLD (&mmk_cld)
void Map_Default_Rules(void);
/*
**++
** ROUTINE: main
**
** FUNCTIONAL DESCRIPTION:
**
** Main program. Fetches the command from the command line,
** uses CLI$ routines to parse it, then starts the build process.
**
** RETURNS: cond_value, longword (unsigned), write only, by value
**
** PROTOTYPE:
**
** main
**
** IMPLICIT INPUTS: See global definitions at module head.
**
** IMPLICIT OUTPUTS: See global definitions at module head.
**
** COMPLETION CODES:
**
** SS$_NORMAL, MMK__ALLOK : normal successful completion.
**
** SIDE EFFECTS: None.
**
**--
*/
unsigned int main (void) {
ITMLST syilst[2];
DESCRIP cmdstr;
char target[256], descripfile[256], tmp[256];
char str1[256], *str2, *str3;
int length_needed;
$DESCRIPTOR(cmdname, "MMK ");
unsigned int status;
int did1macro, doing_file, i;
unsigned short len;
FILEHANDLE munit;
struct TARGET {
struct TARGET *flink, *blink;
char *name;
} targetque = {&targetque,&targetque,NULL}, *targetent;
/*
** Initialize the globals
*/
temporary_symbols = 0;
for (i = 0; i < MMK_K_SYMTABLE_SIZE; i++) {
INIT_QUEUE(global_symbols.symlist[i]);
INIT_QUEUE(local_symbols.symlist[i]);
INIT_QUEUE(cmdline_symbols.symlist[i]);
INIT_QUEUE(builtin_symbols.symlist[i]);
}
INIT_QUEUE(rules);
INIT_QUEUE(dependencies);
INIT_QUEUE(dep_internal);
INIT_QUEUE(dep_deferred);
INIT_QUEUE(suffixes);
INIT_QUEUE(do_first);
INIT_QUEUE(do_last);
exit_status = SS$_NORMAL;
ignore = override_silent = override_ignore = symbol_override;
skip_intermediates = 0;
builtins = override_builtins = 0;
case_sensitive = override_case = 0;
gnu_syntax = override_gnu_syntax = 0;
mms_syntax = override_mms_syntax = 0;
/*
** Fetch and parse command string
*/
/*
** Fetch the value of the DCL reserved word $VERB. We use this to
** test if the command line has already been parsed by DCL. If the
** value returned does NOT match the MMK verb, then we need to
** parse it ourselves.
*/
status = cli_get_value("$VERB", tmp, sizeof(tmp));
if (OK(status)) {
status = strncmp(tmp, cmdname.dsc$a_pointer,
cmdname.dsc$w_length-1) == 0;
}
if (!OK(status)) {
INIT_DYNDESC(cmdstr);
status = lib$get_foreign(&cmdstr);
str$prefix(&cmdstr, &cmdname);
status = cli$dcl_parse(&cmdstr, MMK_CLD, lib$get_input,
lib$get_input);
if (!OK(status)) return (status | STS$M_INHIB_MSG);
}
/*
** Check for /IDENT
*/
if (cli_present("IDENTIFICATION") == CLI$_PRESENT) {
lib$signal(MMK__IDENT, 1, MMK_VERSION, MMK__COPYRIGHT, 1, MMK_COPYRIGHT);
return SS$_NORMAL;
}
/*
** Define the version macros
*/
Define_Symbol(MMK_K_SYM_BUILTIN, "MMK_VERSION", MMK_VERSION, strlen(MMK_VERSION));
Define_Symbol(MMK_K_SYM_BUILTIN, "MMK_MAJOR_VERSION", MMK_MAJOR_VERSION, strlen(MMK_MAJOR_VERSION));
Define_Symbol(MMK_K_SYM_BUILTIN, "MMK_MINOR_VERSION", MMK_MINOR_VERSION, strlen(MMK_MINOR_VERSION));
Define_Symbol(MMK_K_SYM_BUILTIN, "MMK_REVISION", MMK_REVISION, strlen(MMK_REVISION));
/*
* Architecture built-ins
*/
ITMLST_INIT(syilst[0], SYI$_ARCH_NAME, sizeof(tmp), tmp, &len);
ITMLST_INIT(syilst[1], 0, 0, 0, 0);
status = sys$getsyi(0, 0, 0, syilst, 0, 0, 0);
if (!OK(status)) {
strcpy(tmp, "VAX");
len = strlen(tmp);
}
Define_Symbol(MMK_K_SYM_BUILTIN, "MMS$ARCH_NAME", tmp, len);
Define_Symbol(MMK_K_SYM_BUILTIN, "MMSARCH_NAME", tmp, len);
/*
** From Craig Berry, added by Hunter Goatley, 5-SEP-2023 15:28
Fix architecture built-in macro for x86_64
Rather than adding a fourth hard-coded option to the list, let's
derive the built-in name from the architecture name we already
have. Some of them come back from sys$getsyi in mixed case, so
upper case the result when defining the built-in.
N.B. The existing behavior differs from MMS and is not changed
here. MMS will set, for example, MMSALPHA to a value of "ALPHA"
whereas MMK sets it to "1". Either should work in an IFDEF, so
it may not matter.
*/
if ((len + 3) > sizeof(str1))
return SS$_INSFMEM;
/* We don't have snprintf() on VAX, so just copy the bytes to
** create the MMSxxxx builtin name
*/
str1[0] = 'M';
str1[1] = 'M';
str1[2] = 'S';
for (str2 = &str1[3], str3 = tmp; *str2 = toupper(*str3++); str2++);
Define_Symbol(MMK_K_SYM_BUILTIN, str1, "1", 1);
/*
** Get the command parameters and qualifiers
*/
descripfile[0] = target[0] = mmsqual[0] = '\0';
(void) cli_get_value("DESCRIPTION", descripfile, sizeof(descripfile));
if (descripfile[0]) {
add_to_mmsqual("/DESCRIPTION=");
add_to_mmsqual(descripfile);
}
do_log = (cli_present("LOG") == CLI$_PRESENT);
if (do_log) add_to_mmsqual("/LOG");
if (OK(cli_get_value("WORKING_DIRECTORY", tmp, sizeof(tmp)))) {
sys$dclexh(&desblk);
status = change_working_directory(tmp);
if (!OK(status)) {
lib$signal(MMK__SETDEFERR, 2, strlen(tmp), tmp, status);
return MMK__SETDEFERR|STS$M_INHIB_MSG;
}
}
status = cli_present("VERIFY");
if (status == CLI$_PRESENT) {
override_silent = 1;
if (OK(cli_get_value("VERIFY", tmp, sizeof(tmp)))) {
verify = *tmp == 'A' ? 2 : '1';
add_to_mmsqual("/VERIFY=");
add_to_mmsqual(tmp);
} else {
verify = 1;
add_to_mmsqual("/VERIFY");
}
} else if (status == CLI$_NEGATED) {
override_silent = 1;
add_to_mmsqual("/NOVERIFY");
} else {
verify = 1;
}
symbol_override = (cli_present("OVERRIDE") == CLI$_PRESENT);
if (symbol_override) add_to_mmsqual("/OVERRIDE");
skip_intermediates = (cli_present("SKIP_INTERMEDIATES") == CLI$_PRESENT);
if (skip_intermediates) add_to_mmsqual("/SKIP_INTERMEDIATES");
noaction = cli_present("ACTION") == CLI$_NEGATED;
if (noaction) add_to_mmsqual("/NOACTION");
force = cli_present("FORCE") == CLI$_PRESENT;
if (force) add_to_mmsqual("/FORCE");
from_sources = cli_present("FROM_SOURCES") == CLI$_PRESENT;
if (from_sources) {
add_to_mmsqual("/FROM_SOURCES");
skip_intermediates = 0;
}
check_status = (cli_present("CHECK_STATUS") == CLI$_PRESENT);
if (check_status) {
add_to_mmsqual("/CHECK_STATUS");
noaction = 1;
}
if (cli_present("EXTENDED_SYNTAX") == CLI$_PRESENT) {
add_to_mmsqual("/EXTENDED_SYNTAX=(");
mms_syntax = OK(cli_present("EXTENDED_SYNTAX.MMS_SYNTAX"));
if (mms_syntax) add_to_mmsqual("MMS_SYNTAX");
gnu_syntax = (cli_present("EXTENDED_SYNTAX.GNU_SYNTAX") == CLI$_PRESENT);
if (gnu_syntax) {
if (mms_syntax) add_to_mmsqual(",");
add_to_mmsqual("GNU_SYNTAX");
}
case_sensitive = (cli_present("EXTENDED_SYNTAX.CASE_SENSITIVE") == CLI$_PRESENT);
if (case_sensitive) {
if (mms_syntax || gnu_syntax) add_to_mmsqual(",");
add_to_mmsqual("CASE_SENSITIVE");
}
add_to_mmsqual(")");
}
if (cli_present("CMS_LIBRARY") == CLI$_PRESENT) {
int curlen;
add_to_mmsqual("/CMS_LIBRARY=(");
curlen = 0;
do {
status = cli_get_value("CMS_LIBRARY", &cms$lib[curlen], sizeof(cms$lib)-curlen);
curlen += strlen(&cms$lib[curlen]);
if (status == CLI$_COMMA)
cms$lib[curlen++] = ',';
} while (status == CLI$_COMMA);
add_to_mmsqual(cms$lib);
add_to_mmsqual(")");
} else {
strcpy(cms$lib, "CMS$LIB");
}
use_cms = cli_present("CMS") == CLI$_PRESENT;
if (use_cms) {
add_to_mmsqual("/CMS");
if (cms$lib[0] == '\0') use_cms = 0;
}
if (use_cms) {
if (!OK(cli_get_value("GENERATION", cms_default_generation,
sizeof(cms_default_generation)))) {
strcpy(cms_default_generation, "1+");
}
status = cli_present("GENERATION");
if (status == CLI$_PRESENT) {
add_to_mmsqual("/GENERATION=");
add_to_mmsqual(cms_default_generation);
}
}
status = cli_present("IGNORE");
if (status == CLI$_PRESENT) {
override_ignore = 1;
if (OK(cli_get_value("IGNORE", tmp, sizeof(tmp)))) {
ignore = *tmp == 'F' ? 3 : (*tmp == 'E' ? 2 : 1);
add_to_mmsqual("/IGNORE=");
add_to_mmsqual(tmp);
} else {
ignore = 3;
add_to_mmsqual("/IGNORE");
}
} else if (status == CLI$_NEGATED) {
override_ignore = 1;
add_to_mmsqual("/NOIGNORE");
}
if (cli_present("OUTPUT") == CLI$_PRESENT) {
cli_get_value("OUTPUT", tmp, sizeof(tmp));
status = file_create_share(tmp, &out_unit, ".LOG");
if (!OK(status)) {
lib$signal(MMK__OPENOUT, 1, tmp, status);
return (MMK__OPENOUT|STS$M_INHIB_MSG);
}
add_to_mmsqual("/OUTPUT=SYS$OUTPUT:");
}
/*
** Command-line definition of symbols
*/
if (cli_present("MACRO") == CLI$_PRESENT) add_to_mmsqual("/MACRO=(");
did1macro = 0;
doing_file = 0;
munit = 0;
while (1) {
char *ep, *vp, *sp;
char macro_file[256];
int slew = 0, len;
if (doing_file) {
status = file_read(munit, tmp, sizeof(tmp), &len);
if (!OK(status)) {
file_close(munit);
munit = 0;
doing_file = 0;
continue;
}
slew += 1;
tmp[len] = '\0';
} else {
status = cli_get_value("MACRO", tmp, sizeof(tmp));
if (!OK(status)) break;
}
/*
** Trim leading blanks from macro name. If it's a null line, just
** ignore it.
*/
for (sp = tmp; isspace(*sp); sp++);
if (*sp == '\0') continue;
/*
** Locate the "=". If there is none present and we're doing command-line
** macros, check to see if this is a file specification.
*/
ep = strchr(sp,'=');
if (!doing_file && ep == 0) {
status = file_open(sp, &munit, "SYS$DISK:[].MMS", macro_file, 0);
if (OK(status)) {
doing_file = 1;
if (did1macro) add_to_mmsqual(",");
add_to_mmsqual(sp);
did1macro = 1;
slew = 0;
continue;
}
/*
** For compatibility with previous versions of MMK, we allow ":" in place
** of "=" (but only in command-line macros).
*/
ep = strchr(sp, ':');
}
if (ep != 0) {
vp = ep + 1;
while (isspace(*vp)) vp++;
while (isspace(*(ep-1))) ep--;
*ep = 0;
Define_Symbol(MMK_K_SYM_CMDLINE, sp, vp, strlen(vp));
if (!doing_file) {
if (did1macro) add_to_mmsqual(",");
add_to_mmsqual(tmp);
add_to_mmsqual("=\"");
add_to_mmsqual(vp);
add_to_mmsqual("\"");
did1macro = 1;
}
} else if (!doing_file) {
/*
** For compatibility with previous versions, we allow MACRO to be equivalent
** to MACRO=1 (but only for command-line macros).
*/
Define_Symbol(MMK_K_SYM_CMDLINE, tmp, "1", 1);
if (did1macro) add_to_mmsqual(",");
add_to_mmsqual(tmp);
} else {
lib$signal(MMK__MACFILSYNTAX, 2, slew, macro_file);
}
}
if (cli_present("MACRO") == CLI$_PRESENT) add_to_mmsqual(")");
did_an_update = 0;
/*
** Rules processing is as follows:
**
** 1. The default rules are mapped in, having been compiled
** by the description file compiler.
**
** 2. Unless /NOLOCAL_RULES is specified, the rules file
** located through the logical name MMK_LOCAL_RULES is
** processed. Use this logical to point to files containing
** system-wide build rules.
**
** 3. If the /RULES=(file[,...]) qualifier is present, the
** specified rules files are read in. If it is absent,
** a personal rules file is located by the logical name
** MMK_PERSONAL_RULES. If /NORULES is specified, no
** per-build or personal rules files are read in.
*/
status = cli_present("RULES_FILE");
if (status != CLI$_NEGATED) {
Map_Default_Rules();
if (!OK(exit_status)) return exit_status | STS$M_INHIB_MSG;
}
if (cli_present("LOCAL_RULES") != CLI$_NEGATED) {
if (logical_present("MMK_LOCAL_RULES")) {
Read_Description("MMK_LOCAL_RULES", "SYS$DISK:[].MMS", 1);
}
} else add_to_mmsqual("/NOLOCAL_RULES");
if (status == CLI$_PRESENT || status == CLI$_DEFAULTED) {
did1macro = 0;
if (status == CLI$_PRESENT) add_to_mmsqual("/RULES_FILE=(");
while (OK(cli_get_value("RULES_FILE", tmp, sizeof(tmp)))) {
Read_Description(tmp, "SYS$DISK:[].MMS", 1);
if (status == CLI$_PRESENT) {
if (did1macro) add_to_mmsqual(",");
add_to_mmsqual(tmp);
did1macro = 1;
}
}
if (status == CLI$_PRESENT) add_to_mmsqual(")");
} else if (status != CLI$_NEGATED) {
if (logical_present("MMK_PERSONAL_RULES")) {
Read_Description("MMK_PERSONAL_RULES","SYS$DISK:[].MMS", 1);
}
} else add_to_mmsqual("/NORULES_FILE");
/*
** We've parsed all the qualifiers, so create the MMSQUALIFIERS macro
** (and MMS macro, too).
*/
Define_Symbol(MMK_K_SYM_BUILTIN, "MMSQUALIFIERS", mmsqual, strlen(mmsqual));
/*
** Build list of targets specified on the command line into MMSTARGETS.
*/
status = cli_present("TARGET");
if (status == CLI$_PRESENT) {
do {
status = cli_get_value("TARGET", target, sizeof(target));
targetent = malloc(sizeof(struct TARGET));
targetent->name = strdup(target);
queue_insert(targetent, targetque.blink);
Define_Symbol(MMK_K_SYM_BUILTIN, "MMSTARGETS", target, -1, ",");
} while (status != SS$_NORMAL);
} else {
target[0] = '\0';
targetque.name = target;
Define_Symbol(MMK_K_SYM_BUILTIN, "MMSTARGETS", target, 0);
}
/*
** Now read in and parse the description file.
*/
Read_Description(descripfile, "SYS$DISK:[]DESCRIP.MMS", 0);
/*
** Dump our brains if we're told to
*/
if (cli_present("DUMP") == CLI$_PRESENT) Dump_It_All();
/*
** Now define the MMS symbol (left undefined while we were parsing so
** we can identify $(MMS) references in action lines and execute them
** even if /NOACTION is specified.
*/
Define_Symbol(MMK_K_SYM_DESCRIP,
"MMS", (noaction ? "MMK/NOACTION" : "MMK"),
(noaction ? 12 : 3));
set_mmssuffixes();
/*
** Now that all the dependencies are defined, we can do the build.
*/
targetent = targetque.flink;
do {
did_an_update = 0;
Build_Target(targetent->name);
if ($VMS_STATUS_SEVERITY(exit_status) == STS$K_SEVERE) break;
/*
** If everything is up-to-date, say so.
*/
if (check_status) {
static $DESCRIPTOR(mms$status, "MMS$STATUS");
static $DESCRIPTOR(one, "1");
static $DESCRIPTOR(zero, "0");
static unsigned int gsym = LIB$K_CLI_GLOBAL_SYM;
lib$set_symbol(&mms$status, did_an_update ? &zero : &one, &gsym);
if (did_an_update) {
lib$signal(MMK__NEEDSUPD, 1, targetent->name);
} else {
lib$signal(MMK__TRGCURRENT, 1, targetent->name);
}
} else {
if (!did_an_update) {
lib$signal(MMK__NOUPDATE, 1, targetent->name);
if (exit_status == SS$_NORMAL) exit_status = MMK__NOUPDATE;
}
}
targetent = targetent->flink;
} while (targetent != &targetque);
/*
** If we did have to execute some commands, there will be a subprocess
** hanging around that we should kill.
*/
close_subprocess();
return exit_status | STS$M_INHIB_MSG;
} /* main */
/*
**++
** ROUTINE: add_to_mmsqual
**
** FUNCTIONAL DESCRIPTION:
**
** Adds a string to the mmsqual variable.
**
** RETURNS: void
**
** PROTOTYPE:
**
** add_to_mmsqual(char *)
**
** IMPLICIT INPUTS: None.
**
** IMPLICIT OUTPUTS: None.
**
** COMPLETION CODES: None.
**
** SIDE EFFECTS: None.
**
**--
*/
static void add_to_mmsqual (char *str) {
static char *qp = mmsqual;
static int qlen = 0;
int i;
i = strlen(str);
if (i == 0) return;
if (qlen + i > sizeof(mmsqual)-1) return;
if (i == 1) {
*qp++ = *str;
*qp = '\0';
} else {
strcpy(qp, str);
qp += i;
}
qlen += i;
} /* add_to_mmsqual */
/*
**++
** ROUTINE: cli_get_value
**
** FUNCTIONAL DESCRIPTION:
**
** C Interface to CLI$GET_VALUE.
**
** RETURNS: cond_value, longword (unsigned), write only, by value
**
** PROTOTYPE:
**
** cli_get_value (char *argname, DESCRIP *arg)
**
** argname: ASCIZ_string, read only, by reference
** arg: char_string, write only, by descriptor (dynamic)
**
** IMPLICIT INPUTS: None.
**
** IMPLICIT OUTPUTS: None.
**
** COMPLETION CODES:
**
** All those from CLI$PRESENT and CLI$GET_VALUE.
**
** SIDE EFFECTS: None.
**
**--
*/
static unsigned int cli_get_value (char *argname, char *arg, int argsize) {
DESCRIP argnamd, argd;
unsigned short arglen;
int status;
INIT_SDESC(argnamd, strlen(argname), argname);
INIT_SDESC(argd, argsize-1, arg);
status = cli$present(&argnamd);
if ($VMS_STATUS_SUCCESS(status)) {
status = cli$get_value(&argnamd, &argd, &arglen);
if (OK(status)) *(arg+arglen) = '\0';
}
return status;
}
/*
**++
** ROUTINE: put_output
**
** FUNCTIONAL DESCRIPTION:
**
** LIB$PUT_OUTPUT replacement that directs things either
** to SYS$OUTPUT or to the file specified in /OUTPUT.
**
** RETURNS: cond_value, longword (unsigned), write only, by value
**
** PROTOTYPE:
**
** put_output(void *dsc)
**
** IMPLICIT INPUTS: None.
**
** IMPLICIT OUTPUTS: None.
**
** COMPLETION CODES:
**
**
** SIDE EFFECTS: None.
**
**--
*/
unsigned int put_output (void *xdsc) {
struct dsc$descriptor *dsc = xdsc;
return (out_unit != 0 ? file_write(out_unit, dsc->dsc$a_pointer, dsc->dsc$w_length)
: lib$put_output(dsc));
} /* put_output */
/*
**++
** ROUTINE: put_command
**
** FUNCTIONAL DESCRIPTION:
**
** LIB$PUT_OUTPUT replacement that directs things either
** to SYS$OUTPUT or to the file specified in /OUTPUT (for commands).
**
** RETURNS: cond_value, longword (unsigned), write only, by value
**
** PROTOTYPE:
**
** put_command(struct dsc$descriptor *dsc)
**
** IMPLICIT INPUTS: None.
**
** IMPLICIT OUTPUTS: None.
**
** COMPLETION CODES:
**
**
** SIDE EFFECTS: None.
**
**--
*/
unsigned int put_command (void *xxdsc) {
struct dsc$descriptor *xdsc = xxdsc;
char *cmdbuf;
unsigned int status;
int i;
if (out_unit == 0) return lib$put_output(xdsc);
for (i = 0; i < xdsc->dsc$w_length; i++) {
if (isspace(xdsc->dsc$a_pointer[i])) continue;
if (xdsc->dsc$a_pointer[i] == '$') {
return file_write(out_unit, xdsc->dsc$a_pointer, xdsc->dsc$w_length);
} else break;
}
cmdbuf = malloc(xdsc->dsc$w_length + 2);
if (cmdbuf == 0)
return LIB$_INSVIRMEM;
cmdbuf[0] = '$';
cmdbuf[1] = ' ';
memcpy(cmdbuf + 2, xdsc->dsc$a_pointer, xdsc->dsc$w_length);
status = file_write(out_unit, cmdbuf, xdsc->dsc$w_length + 2);
free(cmdbuf);
return status;
} /* put_command */
/*
**++
** ROUTINE: cli_present
**
** FUNCTIONAL DESCRIPTION:
**
** C Interface to CLI$PRESENT.
**
** RETURNS: cond_value, intword (unsigned), write only, by value
**
** PROTOTYPE:
**
** cli_present (char *argname)
**
** argname: ASCIZ_string, read only, by reference
**
** IMPLICIT INPUTS: None.
**
** IMPLICIT OUTPUTS: None.
**
** COMPLETION CODES:
**
** All those from CLI$PRESENT.
**
** SIDE EFFECTS: None.
**
**--
*/
static unsigned int cli_present (char *argname) {
DESCRIP argnamd;
INIT_SDESC(argnamd, strlen(argname), argname);
return cli$present(&argnamd);
}
/*
**++
** ROUTINE: Dump_It_All
**
** FUNCTIONAL DESCRIPTION:
**
** Prints out the contents of the suffix, global symbol, rule,
** and dependency lists.
**
** Mainly for use in debugging MMK, or in debugging description files.
**
** RETURNS: void
**
** PROTOTYPE:
**
** Dump_It_All
**
** IMPLICIT INPUTS: None.
**
** IMPLICIT OUTPUTS: None.
**
** COMPLETION CODES:
**
**
** SIDE EFFECTS: None.
**